From 2b878f12652806a413e1bd0b8a4a6c4d6820f413 Mon Sep 17 00:00:00 2001 From: Vankka Date: Fri, 1 Apr 2022 19:07:14 +0300 Subject: [PATCH] Start & stop messages, some bug fixes & cleanup --- .../com/discordsrv/proxy/ProxyDiscordSRV.java | 2 + .../channels/ServerSwitchMessageConfig.java | 13 ++++- .../modules/ServerSwitchMessageModule.java | 14 +---- .../common/server/ServerDiscordSRV.java | 9 +++- .../config/channels/DeathMessageConfig.java | 13 ++++- .../server/modules/DeathMessageModule.java | 14 +---- .../discordsrv/common/AbstractDiscordSRV.java | 35 ++++++++---- .../com/discordsrv/common/DiscordSRV.java | 7 +-- .../config/main/channels/IMessageConfig.java | 27 ++++++++++ .../main/channels/JoinMessageConfig.java | 12 ++++- .../main/channels/LeaveMessageConfig.java | 12 ++++- .../MinecraftToDiscordChatConfig.java | 12 ++++- .../main/channels/StartMessageConfig.java | 43 +++++++++++++++ .../main/channels/StopMessageConfig.java | 43 +++++++++++++++ .../main/channels/base/BaseChannelConfig.java | 2 + .../common/discord/api/DiscordAPIImpl.java | 5 +- .../connection/jda/JDAConnectionManager.java | 26 ++++++--- .../common/event/bus/EventBusImpl.java | 10 +++- .../game/AbstractGameMessageModule.java | 52 ++++++++++-------- .../game/JoinMessageModule.java | 14 +---- .../game/LeaveMessageModule.java | 14 +---- .../game/MinecraftToDiscordChatModule.java | 13 +---- .../game/StartMessageModule.java | 45 ++++++++++++++++ .../game/StopMessageModule.java | 53 +++++++++++++++++++ .../common/module/ModuleManager.java | 4 +- .../common/module/type/AbstractModule.java | 4 ++ 26 files changed, 378 insertions(+), 120 deletions(-) create mode 100644 common/src/main/java/com/discordsrv/common/config/main/channels/IMessageConfig.java create mode 100644 common/src/main/java/com/discordsrv/common/config/main/channels/StartMessageConfig.java create mode 100644 common/src/main/java/com/discordsrv/common/config/main/channels/StopMessageConfig.java create mode 100644 common/src/main/java/com/discordsrv/common/messageforwarding/game/StartMessageModule.java create mode 100644 common/src/main/java/com/discordsrv/common/messageforwarding/game/StopMessageModule.java diff --git a/common/proxy/src/main/java/com/discordsrv/proxy/ProxyDiscordSRV.java b/common/proxy/src/main/java/com/discordsrv/proxy/ProxyDiscordSRV.java index 2d20b5a6..74a99bab 100644 --- a/common/proxy/src/main/java/com/discordsrv/proxy/ProxyDiscordSRV.java +++ b/common/proxy/src/main/java/com/discordsrv/proxy/ProxyDiscordSRV.java @@ -30,5 +30,7 @@ public abstract class ProxyDiscordSRV { public ServerSwitchMessageModule(DiscordSRV discordSRV) { - super(discordSRV, new NamedLogger(discordSRV, "SERVER_SWITCH")); + super(discordSRV, "SERVER_SWITCH_MESSAGES"); } @Subscribe(priority = EventPriority.LAST) @@ -53,16 +51,6 @@ public class ServerSwitchMessageModule extends AbstractGameMessageModule ((ProxyBaseChannelConfig) cfg).serverSwitchMessages); } - @Override - public boolean isEnabled(OrDefault config) { - return config.get(cfg -> cfg.enabled, false); - } - - @Override - public SendableDiscordMessage.Builder getFormat(OrDefault config) { - return config.get(cfg -> cfg.format); - } - @Override public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) { discordSRV.eventBus().publish(new ServerSwitchMessageForwardedEvent(cluster)); diff --git a/common/server/src/main/java/com/discordsrv/common/server/ServerDiscordSRV.java b/common/server/src/main/java/com/discordsrv/common/server/ServerDiscordSRV.java index 880ca75d..f989c852 100644 --- a/common/server/src/main/java/com/discordsrv/common/server/ServerDiscordSRV.java +++ b/common/server/src/main/java/com/discordsrv/common/server/ServerDiscordSRV.java @@ -45,11 +45,16 @@ public abstract class ServerDiscordSRV invokeServerStarted() { - return invokeLifecycle(this::serverStarted, "Failed to enable", true); + return invokeLifecycle(() -> { + if (status().isShutdown()) { + return; + } + this.serverStarted(); + }); } @OverridingMethodsMustInvokeSuper protected void serverStarted() { - + startedMessage(); } } diff --git a/common/server/src/main/java/com/discordsrv/common/server/config/channels/DeathMessageConfig.java b/common/server/src/main/java/com/discordsrv/common/server/config/channels/DeathMessageConfig.java index 7c357df9..a1af1bb4 100644 --- a/common/server/src/main/java/com/discordsrv/common/server/config/channels/DeathMessageConfig.java +++ b/common/server/src/main/java/com/discordsrv/common/server/config/channels/DeathMessageConfig.java @@ -21,11 +21,12 @@ package com.discordsrv.common.server.config.channels; import com.discordsrv.api.discord.api.entity.message.DiscordMessageEmbed; import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; import com.discordsrv.common.config.annotation.Untranslated; +import com.discordsrv.common.config.main.channels.IMessageConfig; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.meta.Comment; @ConfigSerializable -public class DeathMessageConfig { +public class DeathMessageConfig implements IMessageConfig { @Comment("Enable death message forwarding") public boolean enabled = true; @@ -38,4 +39,14 @@ public class DeathMessageConfig { .setColor(1) .build() ); + + @Override + public boolean enabled() { + return enabled; + } + + @Override + public SendableDiscordMessage.Builder format() { + return format; + } } diff --git a/common/server/src/main/java/com/discordsrv/common/server/modules/DeathMessageModule.java b/common/server/src/main/java/com/discordsrv/common/server/modules/DeathMessageModule.java index 493624e3..9ca9b180 100644 --- a/common/server/src/main/java/com/discordsrv/common/server/modules/DeathMessageModule.java +++ b/common/server/src/main/java/com/discordsrv/common/server/modules/DeathMessageModule.java @@ -19,7 +19,6 @@ package com.discordsrv.common.server.modules; import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; -import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; import com.discordsrv.api.event.bus.EventPriority; import com.discordsrv.api.event.bus.Subscribe; import com.discordsrv.api.event.events.message.forward.game.DeathMessageForwardedEvent; @@ -27,7 +26,6 @@ import com.discordsrv.api.event.events.message.receive.game.DeathMessageReceiveE import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.function.OrDefault; -import com.discordsrv.common.logging.NamedLogger; import com.discordsrv.common.messageforwarding.game.AbstractGameMessageModule; import com.discordsrv.common.server.config.channels.DeathMessageConfig; import com.discordsrv.common.server.config.channels.base.ServerBaseChannelConfig; @@ -35,7 +33,7 @@ import com.discordsrv.common.server.config.channels.base.ServerBaseChannelConfig public class DeathMessageModule extends AbstractGameMessageModule { public DeathMessageModule(DiscordSRV discordSRV) { - super(discordSRV, new NamedLogger(discordSRV, "DEATH")); + super(discordSRV, "DEATH_MESSAGES"); } @Subscribe(priority = EventPriority.LAST) @@ -53,16 +51,6 @@ public class DeathMessageModule extends AbstractGameMessageModule ((ServerBaseChannelConfig) cfg).deathMessages); } - @Override - public boolean isEnabled(OrDefault config) { - return config.get(cfg -> cfg.enabled, true); - } - - @Override - public SendableDiscordMessage.Builder getFormat(OrDefault config) { - return config.get(cfg -> cfg.format); - } - @Override public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) { discordSRV.eventBus().publish(new DeathMessageForwardedEvent(cluster)); diff --git a/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java b/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java index 635fa506..9fe5eef7 100644 --- a/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java +++ b/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java @@ -19,7 +19,6 @@ package com.discordsrv.common; import com.discordsrv.api.discord.connection.DiscordConnectionDetails; -import com.discordsrv.api.event.bus.EventBus; import com.discordsrv.api.event.events.lifecycle.DiscordSRVConnectedEvent; import com.discordsrv.api.event.events.lifecycle.DiscordSRVReadyEvent; import com.discordsrv.api.event.events.lifecycle.DiscordSRVReloadedEvent; @@ -58,6 +57,8 @@ import com.discordsrv.common.messageforwarding.discord.DiscordChatMessageModule; import com.discordsrv.common.messageforwarding.discord.DiscordMessageMirroringModule; import com.discordsrv.common.messageforwarding.game.JoinMessageModule; import com.discordsrv.common.messageforwarding.game.LeaveMessageModule; +import com.discordsrv.common.messageforwarding.game.StartMessageModule; +import com.discordsrv.common.messageforwarding.game.StopMessageModule; import com.discordsrv.common.module.ModuleManager; import com.discordsrv.common.module.type.AbstractModule; import com.discordsrv.common.placeholder.ComponentResultStringifier; @@ -100,9 +101,10 @@ import java.util.jar.Manifest; public abstract class AbstractDiscordSRV implements DiscordSRV { private final AtomicReference status = new AtomicReference<>(Status.INITIALIZED); + private CompletableFuture enableFuture; // DiscordSRVApi - private EventBus eventBus; + private EventBusImpl eventBus; private ProfileManager profileManager; private PlaceholderServiceImpl placeholderService; private ComponentFactory componentFactory; @@ -201,7 +203,7 @@ public abstract class AbstractDiscordSRV invokeLifecycle(CheckedRunnable runnable, String message, boolean enable) { + protected CompletableFuture invokeLifecycle(CheckedRunnable runnable) { return invoke(() -> { try { lifecycleLock.lock(); @@ -392,7 +394,7 @@ public abstract class AbstractDiscordSRV invoke(CheckedRunnable runnable, String message, boolean enable) { @@ -406,21 +408,24 @@ public abstract class AbstractDiscordSRV invokeEnable() { - return invokeLifecycle(() -> { + return enableFuture = invokeLifecycle(() -> { this.enable(); waitForStatus(Status.CONNECTED); eventBus().publish(new DiscordSRVReadyEvent()); - }, "Failed to enable", true); + }); } @Override public final CompletableFuture invokeDisable() { - return invokeLifecycle(this::disable, "Failed to disable", false); + if (enableFuture != null && !enableFuture.isDone()) { + enableFuture.cancel(true); + } + return CompletableFuture.runAsync(this::disable, scheduler().executorService()); } @Override @@ -469,6 +474,11 @@ public abstract class AbstractDiscordSRV. + */ + +package com.discordsrv.common.config.main.channels; + +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; + +public interface IMessageConfig { + + boolean enabled(); + SendableDiscordMessage.Builder format(); +} diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/JoinMessageConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/JoinMessageConfig.java index 41899fc3..dacf10d0 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/channels/JoinMessageConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/JoinMessageConfig.java @@ -24,7 +24,7 @@ import com.discordsrv.common.config.annotation.Untranslated; import org.spongepowered.configurate.objectmapping.ConfigSerializable; @ConfigSerializable -public class JoinMessageConfig { +public class JoinMessageConfig implements IMessageConfig { public boolean enabled = true; @@ -36,4 +36,14 @@ public class JoinMessageConfig { .setColor(0x55FF55) .build() ); + + @Override + public boolean enabled() { + return enabled; + } + + @Override + public SendableDiscordMessage.Builder format() { + return format; + } } diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/LeaveMessageConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/LeaveMessageConfig.java index 52bc86bd..4d767d0c 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/channels/LeaveMessageConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/LeaveMessageConfig.java @@ -24,7 +24,7 @@ import com.discordsrv.common.config.annotation.Untranslated; import org.spongepowered.configurate.objectmapping.ConfigSerializable; @ConfigSerializable -public class LeaveMessageConfig { +public class LeaveMessageConfig implements IMessageConfig { public boolean enabled = true; @@ -36,4 +36,14 @@ public class LeaveMessageConfig { .setColor(0xFF5555) .build() ); + + @Override + public boolean enabled() { + return enabled; + } + + @Override + public SendableDiscordMessage.Builder format() { + return format; + } } diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/MinecraftToDiscordChatConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/MinecraftToDiscordChatConfig.java index 0c45eb3b..36eeed90 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/channels/MinecraftToDiscordChatConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/MinecraftToDiscordChatConfig.java @@ -28,7 +28,7 @@ import java.util.Map; import java.util.regex.Pattern; @ConfigSerializable -public class MinecraftToDiscordChatConfig { +public class MinecraftToDiscordChatConfig implements IMessageConfig { @Comment("Is Minecraft to Discord chat forwarding enabled") public boolean enabled = true; @@ -46,6 +46,16 @@ public class MinecraftToDiscordChatConfig { @Comment("What mentions should be translated from chat messages to mentions (this does not effect if they will cause a notification or not)") public Mentions mentions = new Mentions(); + @Override + public boolean enabled() { + return enabled; + } + + @Override + public SendableDiscordMessage.Builder format() { + return format; + } + @ConfigSerializable public static class Mentions { diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/StartMessageConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/StartMessageConfig.java new file mode 100644 index 00000000..082526f4 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/StartMessageConfig.java @@ -0,0 +1,43 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.discordsrv.common.config.main.channels; + +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.common.config.annotation.Untranslated; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +@ConfigSerializable +public class StartMessageConfig implements IMessageConfig { + + public boolean enabled = true; + + @Untranslated(Untranslated.Type.VALUE) + public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder() + .setContent(":arrow_forward: **The server has started**"); + + @Override + public boolean enabled() { + return enabled; + } + + @Override + public SendableDiscordMessage.Builder format() { + return format; + } +} diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/StopMessageConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/StopMessageConfig.java new file mode 100644 index 00000000..bca915f1 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/StopMessageConfig.java @@ -0,0 +1,43 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.discordsrv.common.config.main.channels; + +import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; +import com.discordsrv.common.config.annotation.Untranslated; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +@ConfigSerializable +public class StopMessageConfig implements IMessageConfig { + + public boolean enabled = true; + + @Untranslated(Untranslated.Type.VALUE) + public SendableDiscordMessage.Builder format = SendableDiscordMessage.builder() + .setContent(":pause_button: **The server has stopped**"); + + @Override + public boolean enabled() { + return enabled; + } + + @Override + public SendableDiscordMessage.Builder format() { + return format; + } +} diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/base/BaseChannelConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/base/BaseChannelConfig.java index d13f369f..b3b155d7 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/channels/base/BaseChannelConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/base/BaseChannelConfig.java @@ -31,6 +31,8 @@ public class BaseChannelConfig { public DiscordToMinecraftChatConfig discordToMinecraft = new DiscordToMinecraftChatConfig(); public JoinMessageConfig joinMessages = new JoinMessageConfig(); public LeaveMessageConfig leaveMessages = new LeaveMessageConfig(); + public StartMessageConfig startMessage = new StartMessageConfig(); + public StopMessageConfig stopMessage = new StopMessageConfig(); @Order(10) @Comment("Settings for synchronizing messages between the defined Discord channels and threads") diff --git a/common/src/main/java/com/discordsrv/common/discord/api/DiscordAPIImpl.java b/common/src/main/java/com/discordsrv/common/discord/api/DiscordAPIImpl.java index 9a039137..e84ab75e 100644 --- a/common/src/main/java/com/discordsrv/common/discord/api/DiscordAPIImpl.java +++ b/common/src/main/java/com/discordsrv/common/discord/api/DiscordAPIImpl.java @@ -159,8 +159,9 @@ public class DiscordAPIImpl implements DiscordAPI { futures.add(future.handle((threadChannel, t) -> { if (t != null) { - discordSRV.logger().error("Failed to deliver message to thread \"" - + threadConfig.threadName + "\" in channel " + channel, t); + discordSRV.discordConnectionManager().handleRequestFailure( + "Failed to deliver message to thread \"" + + threadConfig.threadName + "\" in channel " + channel, t); throw new RuntimeException(); // Just here to fail the future } diff --git a/common/src/main/java/com/discordsrv/common/discord/connection/jda/JDAConnectionManager.java b/common/src/main/java/com/discordsrv/common/discord/connection/jda/JDAConnectionManager.java index c75cea31..615d2272 100644 --- a/common/src/main/java/com/discordsrv/common/discord/connection/jda/JDAConnectionManager.java +++ b/common/src/main/java/com/discordsrv/common/discord/connection/jda/JDAConnectionManager.java @@ -77,6 +77,7 @@ public class JDAConnectionManager implements DiscordConnectionManager { } private final DiscordSRV discordSRV; + private final DefaultFailureCallback defaultFailureCallback; private ScheduledExecutorService gatewayPool; private ScheduledExecutorService rateLimitPool; @@ -94,9 +95,10 @@ public class JDAConnectionManager implements DiscordConnectionManager { public JDAConnectionManager(DiscordSRV discordSRV) { this.discordSRV = discordSRV; + this.defaultFailureCallback = new DefaultFailureCallback(new NamedLogger(discordSRV, "DISCORD_REQUESTS")); // Set default failure handling - RestAction.setDefaultFailure(new DefaultFailureCallback(new NamedLogger(discordSRV, "DISCORD_REQUESTS"))); + RestAction.setDefaultFailure(defaultFailureCallback); // Disable all mentions by default for safety AllowedMentions.setDefaultMentions(Collections.emptyList()); @@ -211,9 +213,7 @@ public class JDAConnectionManager implements DiscordConnectionManager { throw new IllegalStateException("Cannot reconnect, still active"); } - CompletableFuture future = CompletableFuture.runAsync(this::connectInternal, discordSRV.scheduler().executor()); - connectionFuture = future; - return future; + return connectionFuture = CompletableFuture.runAsync(this::connectInternal, discordSRV.scheduler().executor()); } private void connectInternal() { @@ -306,7 +306,7 @@ public class JDAConnectionManager implements DiscordConnectionManager { try { discordSRV.scheduler().run(() -> { try { - while (instance.getStatus() != JDA.Status.SHUTDOWN) { + while (instance != null && instance.getStatus() != JDA.Status.SHUTDOWN) { Thread.sleep(50); } } catch (InterruptedException ignored) {} @@ -436,6 +436,10 @@ public class JDAConnectionManager implements DiscordConnectionManager { discordSRV.logger().error("+------------------------------>"); } + public void handleRequestFailure(String context, Throwable cause) { + defaultFailureCallback.accept(context, cause); + } + private class DefaultFailureCallback implements Consumer { private final Logger logger; @@ -446,6 +450,10 @@ public class JDAConnectionManager implements DiscordConnectionManager { @Override public void accept(Throwable t) { + accept(null, t); + } + + public void accept(String context, Throwable t) { if ((t instanceof InterruptedIOException || t instanceof InterruptedException) && discordSRV.status().isShutdown()) { // Ignore interrupted exceptions when DiscordSRV is shutting down or shutdown @@ -460,7 +468,7 @@ public class JDAConnectionManager implements DiscordConnectionManager { // Log route & retry after on warn & context on debug RateLimitedException exception = ((RateLimitedException) t); discordSRV.logger().warning("A request on route " + exception.getRateLimitedRoute() - + " was rate-limited for " + exception.getRetryAfter() + "ms"); + + " was rate-limited for " + exception.getRetryAfter() + "ms"); logger.debug(exception.getCause()); } else if (t instanceof ErrorResponseException) { ErrorResponseException exception = (ErrorResponseException) t; @@ -471,7 +479,7 @@ public class JDAConnectionManager implements DiscordConnectionManager { // Run the cause through this method again accept(cause); } else { - logger.error("Failed to complete request for a unknown reason", exception); + logger.error((context != null ? context + ": " : "") + "Failed to complete request for a unknown reason", exception); } return; } @@ -520,8 +528,10 @@ public class JDAConnectionManager implements DiscordConnectionManager { default: break; } - logger.error("Failed to complete a request: " + response.getMeaning()); + logger.error((context != null ? context : "Failed to complete a request") + ": " + response.getMeaning()); logger.debug(exception); + } else { + logger.error(context != null ? context : "Failed to complete a request due to unknown error", t); } } } diff --git a/common/src/main/java/com/discordsrv/common/event/bus/EventBusImpl.java b/common/src/main/java/com/discordsrv/common/event/bus/EventBusImpl.java index e95dad73..aa665c7a 100644 --- a/common/src/main/java/com/discordsrv/common/event/bus/EventBusImpl.java +++ b/common/src/main/java/com/discordsrv/common/event/bus/EventBusImpl.java @@ -39,7 +39,10 @@ import org.jetbrains.annotations.NotNull; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Function; @@ -65,6 +68,11 @@ public class EventBusImpl implements EventBus { subscribe(this); } + public void shutdown() { + listeners.clear(); + allListeners.clear(); + } + @Override public void subscribe(@NotNull Object eventListener) { if (listeners.containsKey(eventListener)) { diff --git a/common/src/main/java/com/discordsrv/common/messageforwarding/game/AbstractGameMessageModule.java b/common/src/main/java/com/discordsrv/common/messageforwarding/game/AbstractGameMessageModule.java index 381f18d3..52dfd696 100644 --- a/common/src/main/java/com/discordsrv/common/messageforwarding/game/AbstractGameMessageModule.java +++ b/common/src/main/java/com/discordsrv/common/messageforwarding/game/AbstractGameMessageModule.java @@ -31,11 +31,13 @@ import com.discordsrv.api.placeholder.FormattedText; import com.discordsrv.api.player.DiscordSRVPlayer; import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.component.util.ComponentUtil; +import com.discordsrv.common.config.main.channels.IMessageConfig; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.config.main.channels.base.IChannelConfig; import com.discordsrv.common.discord.api.entity.message.ReceivedDiscordMessageClusterImpl; import com.discordsrv.common.function.OrDefault; -import com.discordsrv.common.logging.Logger; +import com.discordsrv.common.future.util.CompletableFutureUtil; +import com.discordsrv.common.logging.NamedLogger; import com.discordsrv.common.module.type.AbstractModule; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; @@ -46,47 +48,46 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.CopyOnWriteArrayList; -public abstract class AbstractGameMessageModule extends AbstractModule { +public abstract class AbstractGameMessageModule extends AbstractModule { - public AbstractGameMessageModule(DiscordSRV discordSRV, Logger logger) { - super(discordSRV, logger); + public AbstractGameMessageModule(DiscordSRV discordSRV, String loggerName) { + super(discordSRV, new NamedLogger(discordSRV, loggerName)); } public abstract OrDefault mapConfig(OrDefault channelConfig); - public abstract boolean isEnabled(OrDefault config); - public abstract SendableDiscordMessage.Builder getFormat(OrDefault config); public abstract void postClusterToEventBus(ReceivedDiscordMessageCluster cluster); - public final void process( - @NotNull AbstractGameMessageReceiveEvent event, - @NotNull DiscordSRVPlayer player, + public final CompletableFuture process( + @Nullable AbstractGameMessageReceiveEvent event, + @Nullable DiscordSRVPlayer player, @Nullable GameChannel channel ) { if (channel == null) { // Send to all channels due to lack of specified channel + List> futures = new ArrayList<>(); for (OrDefault channelConfig : discordSRV.channelConfig().getAllChannels()) { - forwardToChannel(event, player, channelConfig); + futures.add(forwardToChannel(event, player, channelConfig)); } - return; + return CompletableFutureUtil.combine(futures); } OrDefault channelConfig = discordSRV.channelConfig().orDefault(channel); - forwardToChannel(event, player, channelConfig); + return forwardToChannel(event, player, channelConfig); } - private void forwardToChannel( - @NotNull AbstractGameMessageReceiveEvent event, - @NotNull DiscordSRVPlayer player, + private CompletableFuture forwardToChannel( + @Nullable AbstractGameMessageReceiveEvent event, + @Nullable DiscordSRVPlayer player, @NotNull OrDefault channelConfig ) { OrDefault config = mapConfig(channelConfig); - if (!isEnabled(config)) { - return; + if (!config.get(IMessageConfig::enabled, true)) { + return null; } IChannelConfig iChannelConfig = channelConfig.get(cfg -> cfg instanceof IChannelConfig ? (IChannelConfig) cfg : null); if (iChannelConfig == null) { - return; + return null; } List messageChannels = new CopyOnWriteArrayList<>(); @@ -108,13 +109,14 @@ public abstract class AbstractGameMessageModule extends AbstractModule { - SendableDiscordMessage.Builder format = getFormat(config); + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).whenComplete((v, t1) -> { + SendableDiscordMessage.Builder format = config.get(IMessageConfig::format); if (format == null) { return; } - String message = convertMessage(config, ComponentUtil.fromAPI(event.getMessage())); + Component component = event != null ? ComponentUtil.fromAPI(event.getMessage()) : null; + String message = component != null ? convertMessage(config, component) : null; Map, DiscordMessageChannel> messageFutures; messageFutures = sendMessageToChannels( config, format, messageChannels, message, @@ -129,7 +131,11 @@ public abstract class AbstractGameMessageModule extends AbstractModule future = entry.getKey(); if (future.isCompletedExceptionally()) { future.exceptionally(t -> { - discordSRV.logger().error("Failed to deliver a message to the " + entry.getValue() + " channel", t); + if (t instanceof CompletionException) { + t = t.getCause(); + } + discordSRV.discordConnectionManager().handleRequestFailure( + "Failed to deliver a message to " + entry.getValue(), t); return null; }); // Ignore ones that failed @@ -140,7 +146,7 @@ public abstract class AbstractGameMessageModule extends AbstractModule { public JoinMessageModule(DiscordSRV discordSRV) { - super(discordSRV, new NamedLogger(discordSRV, "JOIN_MESSAGES")); + super(discordSRV, "JOIN_MESSAGES"); } @Override @@ -41,16 +39,6 @@ public class JoinMessageModule extends AbstractGameMessageModule cfg.joinMessages); } - @Override - public boolean isEnabled(OrDefault config) { - return config.get(cfg -> cfg.enabled, true); - } - - @Override - public SendableDiscordMessage.Builder getFormat(OrDefault config) { - return config.get(cfg -> cfg.format); - } - @Override public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) { discordSRV.eventBus().publish(new JoinMessageForwardedEvent(cluster)); diff --git a/common/src/main/java/com/discordsrv/common/messageforwarding/game/LeaveMessageModule.java b/common/src/main/java/com/discordsrv/common/messageforwarding/game/LeaveMessageModule.java index 682af5c8..50342c2a 100644 --- a/common/src/main/java/com/discordsrv/common/messageforwarding/game/LeaveMessageModule.java +++ b/common/src/main/java/com/discordsrv/common/messageforwarding/game/LeaveMessageModule.java @@ -19,7 +19,6 @@ package com.discordsrv.common.messageforwarding.game; import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; -import com.discordsrv.api.discord.api.entity.message.SendableDiscordMessage; import com.discordsrv.api.event.bus.EventPriority; import com.discordsrv.api.event.bus.Subscribe; import com.discordsrv.api.event.events.message.forward.game.LeaveMessageForwardedEvent; @@ -28,12 +27,11 @@ import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.config.main.channels.LeaveMessageConfig; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.function.OrDefault; -import com.discordsrv.common.logging.NamedLogger; public class LeaveMessageModule extends AbstractGameMessageModule { public LeaveMessageModule(DiscordSRV discordSRV) { - super(discordSRV, new NamedLogger(discordSRV, "LEAVE_MESSAGES")); + super(discordSRV, "LEAVE_MESSAGES"); } @Override @@ -41,16 +39,6 @@ public class LeaveMessageModule extends AbstractGameMessageModule cfg.leaveMessages); } - @Override - public boolean isEnabled(OrDefault config) { - return config.get(cfg -> cfg.enabled, true); - } - - @Override - public SendableDiscordMessage.Builder getFormat(OrDefault config) { - return config.get(cfg -> cfg.format); - } - @Override public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) { discordSRV.eventBus().publish(new LeaveMessageForwardedEvent(cluster)); diff --git a/common/src/main/java/com/discordsrv/common/messageforwarding/game/MinecraftToDiscordChatModule.java b/common/src/main/java/com/discordsrv/common/messageforwarding/game/MinecraftToDiscordChatModule.java index 82b5cce6..27f666a1 100644 --- a/common/src/main/java/com/discordsrv/common/messageforwarding/game/MinecraftToDiscordChatModule.java +++ b/common/src/main/java/com/discordsrv/common/messageforwarding/game/MinecraftToDiscordChatModule.java @@ -37,7 +37,6 @@ import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.config.main.channels.MinecraftToDiscordChatConfig; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.function.OrDefault; -import com.discordsrv.common.logging.NamedLogger; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.Member; @@ -66,7 +65,7 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule> channelMentions = new ConcurrentHashMap<>(); public MinecraftToDiscordChatModule(DiscordSRV discordSRV) { - super(discordSRV, new NamedLogger(discordSRV, "MINECRAFT_TO_DISCORD")); + super(discordSRV, "MINECRAFT_TO_DISCORD"); } @Override @@ -91,16 +90,6 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule cfg.minecraftToDiscord); } - @Override - public boolean isEnabled(OrDefault config) { - return config.get(cfg -> cfg.enabled, true); - } - - @Override - public SendableDiscordMessage.Builder getFormat(OrDefault config) { - return config.get(cfg -> cfg.format); - } - @Override public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) { discordSRV.eventBus().publish(new GameChatMessageForwardedEvent(cluster)); diff --git a/common/src/main/java/com/discordsrv/common/messageforwarding/game/StartMessageModule.java b/common/src/main/java/com/discordsrv/common/messageforwarding/game/StartMessageModule.java new file mode 100644 index 00000000..dadbbfbf --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/messageforwarding/game/StartMessageModule.java @@ -0,0 +1,45 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.discordsrv.common.messageforwarding.game; + +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.main.channels.StartMessageConfig; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.function.OrDefault; + +public class StartMessageModule extends AbstractGameMessageModule { + + public StartMessageModule(DiscordSRV discordSRV) { + super(discordSRV, "START_MESSAGE"); + } + + @Override + public OrDefault mapConfig(OrDefault channelConfig) { + return channelConfig.map(cfg -> cfg.startMessage); + } + + @Override + public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) {} + + @Override + public void enable() { + process(null, null, null); + } +} diff --git a/common/src/main/java/com/discordsrv/common/messageforwarding/game/StopMessageModule.java b/common/src/main/java/com/discordsrv/common/messageforwarding/game/StopMessageModule.java new file mode 100644 index 00000000..b221867e --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/messageforwarding/game/StopMessageModule.java @@ -0,0 +1,53 @@ +/* + * This file is part of DiscordSRV, licensed under the GPLv3 License + * Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.discordsrv.common.messageforwarding.game; + +import com.discordsrv.api.discord.api.entity.message.ReceivedDiscordMessageCluster; +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.main.channels.StopMessageConfig; +import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; +import com.discordsrv.common.function.OrDefault; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class StopMessageModule extends AbstractGameMessageModule { + + public StopMessageModule(DiscordSRV discordSRV) { + super(discordSRV, "START_MESSAGE"); + } + + @Override + public OrDefault mapConfig(OrDefault channelConfig) { + return channelConfig.map(cfg -> cfg.stopMessage); + } + + @Override + public void postClusterToEventBus(ReceivedDiscordMessageCluster cluster) {} + + @Override + public void disable() { + try { + process(null, null, null).get(5, TimeUnit.SECONDS); + } catch (TimeoutException e) { + logger().error("Failed to queue stop message to be sent within 5 seconds."); + } catch (InterruptedException | ExecutionException ignored) {} + } +} diff --git a/common/src/main/java/com/discordsrv/common/module/ModuleManager.java b/common/src/main/java/com/discordsrv/common/module/ModuleManager.java index 1c07d770..836f2d20 100644 --- a/common/src/main/java/com/discordsrv/common/module/ModuleManager.java +++ b/common/src/main/java/com/discordsrv/common/module/ModuleManager.java @@ -118,7 +118,9 @@ public class ModuleManager { throw new IllegalArgumentException("Cannot unregister a delegate"); } - disable(module); + if (getAbstract(module).isHasBeenEnabled()) { + disable(module); + } this.modules.remove(module); this.moduleLookupTable.values().removeIf(mod -> mod == module); diff --git a/common/src/main/java/com/discordsrv/common/module/type/AbstractModule.java b/common/src/main/java/com/discordsrv/common/module/type/AbstractModule.java index 16768474..de647497 100644 --- a/common/src/main/java/com/discordsrv/common/module/type/AbstractModule.java +++ b/common/src/main/java/com/discordsrv/common/module/type/AbstractModule.java @@ -44,6 +44,10 @@ public abstract class AbstractModule
implements Module { return logger; } + public boolean isHasBeenEnabled() { + return hasBeenEnabled; + } + public final boolean enableModule() { if (hasBeenEnabled || !isEnabled()) { return false;