From f2b90180f1a6fe161f9ed3bd84763a06dae00a0f Mon Sep 17 00:00:00 2001 From: Luck Date: Mon, 7 Oct 2024 20:11:03 +0100 Subject: [PATCH] Add messaging APIs --- build.gradle | 2 +- .../luckperms/rest/LuckPermsRestClient.java | 8 ++++ .../rest/LuckPermsRestClientImpl.java | 8 ++++ .../luckperms/rest/model/CustomMessage.java | 44 +++++++++++++++++ .../rest/model/CustomMessageReceiveEvent.java | 44 +++++++++++++++++ .../luckperms/rest/service/EventService.java | 4 ++ .../rest/service/MessagingService.java | 47 +++++++++++++++++++ .../rest/AbstractIntegrationTest.java | 22 ++++++--- .../luckperms/rest/ActionServiceTest.java | 2 - .../luckperms/rest/EventServiceTest.java | 39 +++++++++++++++ 10 files changed, 210 insertions(+), 10 deletions(-) create mode 100644 src/main/java/net/luckperms/rest/model/CustomMessage.java create mode 100644 src/main/java/net/luckperms/rest/model/CustomMessageReceiveEvent.java create mode 100644 src/main/java/net/luckperms/rest/service/MessagingService.java diff --git a/build.gradle b/build.gradle index 2daa6a4..b609f2b 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.1' testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.1' testImplementation 'org.junit.jupiter:junit-jupiter-params:5.9.1' - testImplementation 'org.testcontainers:junit-jupiter:1.18.3' + testImplementation 'org.testcontainers:junit-jupiter:1.20.1' testImplementation 'org.mockito:mockito-core:4.11.0' testImplementation 'org.mockito:mockito-junit-jupiter:4.11.0' testImplementation 'org.awaitility:awaitility:4.2.0' diff --git a/src/main/java/net/luckperms/rest/LuckPermsRestClient.java b/src/main/java/net/luckperms/rest/LuckPermsRestClient.java index 6979b09..03f4472 100644 --- a/src/main/java/net/luckperms/rest/LuckPermsRestClient.java +++ b/src/main/java/net/luckperms/rest/LuckPermsRestClient.java @@ -28,6 +28,7 @@ import net.luckperms.rest.service.ActionService; import net.luckperms.rest.service.EventService; import net.luckperms.rest.service.GroupService; +import net.luckperms.rest.service.MessagingService; import net.luckperms.rest.service.MiscService; import net.luckperms.rest.service.TrackService; import net.luckperms.rest.service.UserService; @@ -76,6 +77,13 @@ static Builder builder() { */ ActionService actions(); + /** + * Gets the messaging service. + * + * @return the messaging service + */ + MessagingService messaging(); + /** * Gets the event service. * diff --git a/src/main/java/net/luckperms/rest/LuckPermsRestClientImpl.java b/src/main/java/net/luckperms/rest/LuckPermsRestClientImpl.java index 800576f..7a56769 100644 --- a/src/main/java/net/luckperms/rest/LuckPermsRestClientImpl.java +++ b/src/main/java/net/luckperms/rest/LuckPermsRestClientImpl.java @@ -28,6 +28,7 @@ import net.luckperms.rest.service.ActionService; import net.luckperms.rest.service.EventService; import net.luckperms.rest.service.GroupService; +import net.luckperms.rest.service.MessagingService; import net.luckperms.rest.service.MiscService; import net.luckperms.rest.service.TrackService; import net.luckperms.rest.service.UserService; @@ -50,6 +51,7 @@ class LuckPermsRestClientImpl implements LuckPermsRestClient { private final GroupService groupService; private final TrackService trackService; private final ActionService actionService; + private final MessagingService messagingService; private final EventService eventService; private final MiscService miscService; @@ -76,6 +78,7 @@ class LuckPermsRestClientImpl implements LuckPermsRestClient { this.groupService = retrofit.create(GroupService.class); this.trackService = retrofit.create(TrackService.class); this.actionService = retrofit.create(ActionService.class); + this.messagingService = retrofit.create(MessagingService.class); this.eventService = retrofit.create(EventService.class); this.miscService = retrofit.create(MiscService.class); } @@ -99,6 +102,11 @@ public ActionService actions() { return this.actionService; } + @Override + public MessagingService messaging() { + return this.messagingService; + } + @Override public EventService events() { return this.eventService; diff --git a/src/main/java/net/luckperms/rest/model/CustomMessage.java b/src/main/java/net/luckperms/rest/model/CustomMessage.java new file mode 100644 index 0000000..312e024 --- /dev/null +++ b/src/main/java/net/luckperms/rest/model/CustomMessage.java @@ -0,0 +1,44 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.luckperms.rest.model; + +public class CustomMessage extends AbstractModel { + private final String channelId; + private final String payload; + + public CustomMessage(String channelId, String payload) { + this.channelId = channelId; + this.payload = payload; + } + + public String channelId() { + return this.channelId; + } + + public String payload() { + return this.payload; + } +} diff --git a/src/main/java/net/luckperms/rest/model/CustomMessageReceiveEvent.java b/src/main/java/net/luckperms/rest/model/CustomMessageReceiveEvent.java new file mode 100644 index 0000000..dbe1426 --- /dev/null +++ b/src/main/java/net/luckperms/rest/model/CustomMessageReceiveEvent.java @@ -0,0 +1,44 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.luckperms.rest.model; + +public class CustomMessageReceiveEvent extends AbstractModel { + private final String channelId; + private final String payload; + + public CustomMessageReceiveEvent(String channelId, String payload) { + this.channelId = channelId; + this.payload = payload; + } + + public String channelId() { + return this.channelId; + } + + public String payload() { + return this.payload; + } +} diff --git a/src/main/java/net/luckperms/rest/service/EventService.java b/src/main/java/net/luckperms/rest/service/EventService.java index ff1166b..c64be7e 100644 --- a/src/main/java/net/luckperms/rest/service/EventService.java +++ b/src/main/java/net/luckperms/rest/service/EventService.java @@ -26,6 +26,7 @@ package net.luckperms.rest.service; import net.luckperms.rest.event.EventCall; +import net.luckperms.rest.model.CustomMessageReceiveEvent; import net.luckperms.rest.model.LogBroadcastEvent; import net.luckperms.rest.model.PostNetworkSyncEvent; import net.luckperms.rest.model.PostSyncEvent; @@ -50,4 +51,7 @@ public interface EventService { @GET("/event/pre-sync") EventCall preSync(); + @GET("/event/custom-message-receive") + EventCall customMessageReceive(); + } diff --git a/src/main/java/net/luckperms/rest/service/MessagingService.java b/src/main/java/net/luckperms/rest/service/MessagingService.java new file mode 100644 index 0000000..f1771f2 --- /dev/null +++ b/src/main/java/net/luckperms/rest/service/MessagingService.java @@ -0,0 +1,47 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.luckperms.rest.service; + +import net.luckperms.rest.model.CustomMessage; +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.POST; +import retrofit2.http.Path; + +import java.util.UUID; + +public interface MessagingService { + + @POST("/messaging/update") + Call pushUpdate(); + + @POST("/messaging/update/{uniqueId}") + Call pushUserUpdate(@Path("uniqueId") UUID uniqueId); + + @POST("/messaging/custom") + Call sendCustomMessage(@Body CustomMessage message); + +} diff --git a/src/test/java/me/lucko/luckperms/rest/AbstractIntegrationTest.java b/src/test/java/me/lucko/luckperms/rest/AbstractIntegrationTest.java index e8d5564..38c4c14 100644 --- a/src/test/java/me/lucko/luckperms/rest/AbstractIntegrationTest.java +++ b/src/test/java/me/lucko/luckperms/rest/AbstractIntegrationTest.java @@ -43,15 +43,23 @@ public class AbstractIntegrationTest { @Container - private static final GenericContainer container = new GenericContainer<>(DockerImageName.parse("ghcr.io/luckperms/rest-api")) - .withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger(AbstractIntegrationTest.class))) - .withExposedPorts(8080) - .waitingFor(new WaitAllStrategy() - .withStrategy(Wait.forListeningPort()) - .withStrategy(Wait.forLogMessage(".*Successfully enabled.*", 1)) - ); + private static final GenericContainer container = createContainer(); protected LuckPermsRestClient createClient() { + return createClient(container); + } + + protected static GenericContainer createContainer() { + return new GenericContainer<>(DockerImageName.parse("ghcr.io/luckperms/rest-api")) + .withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger(AbstractIntegrationTest.class))) + .withExposedPorts(8080) + .waitingFor(new WaitAllStrategy() + .withStrategy(Wait.forListeningPort()) + .withStrategy(Wait.forLogMessage(".*Successfully enabled.*", 1)) + ); + } + + protected static LuckPermsRestClient createClient(GenericContainer container) { assertTrue(container.isRunning()); String host = container.getHost(); diff --git a/src/test/java/me/lucko/luckperms/rest/ActionServiceTest.java b/src/test/java/me/lucko/luckperms/rest/ActionServiceTest.java index 63b22e7..29797e6 100644 --- a/src/test/java/me/lucko/luckperms/rest/ActionServiceTest.java +++ b/src/test/java/me/lucko/luckperms/rest/ActionServiceTest.java @@ -33,8 +33,6 @@ import retrofit2.Response; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; import java.util.stream.Collectors; diff --git a/src/test/java/me/lucko/luckperms/rest/EventServiceTest.java b/src/test/java/me/lucko/luckperms/rest/EventServiceTest.java index 6f48da5..c25fb62 100644 --- a/src/test/java/me/lucko/luckperms/rest/EventServiceTest.java +++ b/src/test/java/me/lucko/luckperms/rest/EventServiceTest.java @@ -29,9 +29,14 @@ import net.luckperms.rest.event.EventCall; import net.luckperms.rest.event.EventProducer; import net.luckperms.rest.model.Action; +import net.luckperms.rest.model.CustomMessage; +import net.luckperms.rest.model.CustomMessageReceiveEvent; import net.luckperms.rest.model.LogBroadcastEvent; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.Network; +import org.testcontainers.utility.DockerImageName; import java.io.IOException; import java.util.ArrayList; @@ -41,6 +46,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import java.util.function.Supplier; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotSame; @@ -72,6 +78,39 @@ public void testLogBroadcastEvent() throws Exception { assertNotSame(event.entry(), exampleAction); } + @Test + public void testCustomMessageReceiveEvent() throws Exception { + try (Network network = Network.newNetwork(); GenericContainer redis = new GenericContainer<>(DockerImageName.parse("redis"))) { + redis.withNetwork(network).withNetworkAliases("redis").start(); + + Supplier> restSupplier = () -> createContainer() + .withNetwork(network) + .withEnv("LUCKPERMS_MESSAGING_SERVICE", "redis") + .withEnv("LUCKPERMS_REDIS_ENABLED", "true") + .withEnv("LUCKPERMS_REDIS_ADDRESS", "redis:6379"); + + try (GenericContainer restA = restSupplier.get(); GenericContainer restB = restSupplier.get()) { + restA.start(); + restB.start(); + + LuckPermsRestClient clientA = createClient(restA); + LuckPermsRestClient clientB = createClient(restB); + + EventCall call = clientA.events().customMessageReceive(); + CustomMessageReceiveEvent event = testEvent(call, 5, () -> { + try { + clientB.messaging().sendCustomMessage(new CustomMessage("custom:test", "aaabbbccc")).execute(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + + assertEquals("custom:test", event.channelId()); + assertEquals("aaabbbccc", event.payload()); + } + } + } + @Test @Disabled("takes too long to run") public void testLogBroadcastEventLongWait() throws Exception {