From ae30bb39c072c6e8087d9b0e59fa9a7f7c960bf4 Mon Sep 17 00:00:00 2001 From: Kaleidox Date: Sat, 28 Dec 2019 19:48:33 +0100 Subject: [PATCH 1/2] 1.3.4-SNAPSHOT --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2ad44a2..2f83bb4 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { apply plugin: 'java-library' group 'de.comroid' -version '1.3.3.1-SNAPSHOT' +version '1.3.4-SNAPSHOT' System.out.println("##teamcity[buildNumber '$version']") From a6acb00b2fc976fd4b8fcb2c88d5636f31a408b2 Mon Sep 17 00:00:00 2001 From: Kaleidox Date: Sat, 28 Dec 2019 20:43:00 +0100 Subject: [PATCH 2/2] basic implementation --- .../util/commands/CommandHandler.java | 12 ++- .../util/commands/ResponseManager.java | 82 +++++++++++++++++++ 2 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 src/main/java/de/comroid/javacord/util/commands/ResponseManager.java diff --git a/src/main/java/de/comroid/javacord/util/commands/CommandHandler.java b/src/main/java/de/comroid/javacord/util/commands/CommandHandler.java index 1de6466..2869c37 100644 --- a/src/main/java/de/comroid/javacord/util/commands/CommandHandler.java +++ b/src/main/java/de/comroid/javacord/util/commands/CommandHandler.java @@ -73,6 +73,7 @@ public final class CommandHandler implements static final String NO_GROUP = "@NoGroup#"; private final DiscordApi api; + private final ResponseManager responseManager; private final Map commands = new ConcurrentHashMap<>(); private final Map responseMap = new ConcurrentHashMap<>(); @@ -93,6 +94,8 @@ public CommandHandler(DiscordApi api) { public CommandHandler(DiscordApi api, boolean handleMessageEdit) { this.api = api; + this.responseManager = new ResponseManager(api); + prefixes = new String[]{"!"}; autoDeleteResponseOnCommandDeletion = true; customPrefixProvider = null; @@ -544,10 +547,12 @@ else if (!message.isPrivateMessage() && !cmd.enableServerChat) problems.add("This command can only run in an NSFW marked channel!"); if (problems.size() > 0) { - applyResponseDeletion(message.getId(), channel.sendMessage(DefaultEmbedFactory.create() + channel.sendMessage(DefaultEmbedFactory.create() .setColor(Color.RED) .setDescription(String.join("\n", problems))) - .exceptionally(get())); + .thenAccept(msg -> responseManager.accept(msg, message)) + .exceptionally(get()); + return; } @@ -703,7 +708,7 @@ else if (commandRep.convertStringResultsToEmbed && reply instanceof String) else msgFut = channel.sendMessage(String.valueOf(reply)); if (msgFut != null) - applyResponseDeletion(message.getId(), msgFut.exceptionally(get())); + msgFut.thenAccept(msg -> responseManager.accept(msg, message)); } } @@ -749,6 +754,7 @@ else if (Command.Parameters.class.isAssignableFrom(klasse)) return method.invoke(invocationTarget, args); } + @Deprecated private void applyResponseDeletion(long cmdMsgId, CompletableFuture message) { message.thenAcceptAsync(msg -> { if (autoDeleteResponseOnCommandDeletion) diff --git a/src/main/java/de/comroid/javacord/util/commands/ResponseManager.java b/src/main/java/de/comroid/javacord/util/commands/ResponseManager.java new file mode 100644 index 0000000..f449755 --- /dev/null +++ b/src/main/java/de/comroid/javacord/util/commands/ResponseManager.java @@ -0,0 +1,82 @@ +package de.comroid.javacord.util.commands; + +import java.io.Closeable; +import java.time.Duration; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import org.apache.logging.log4j.Logger; +import org.javacord.api.DiscordApi; +import org.javacord.api.entity.message.Message; +import org.javacord.core.util.logging.LoggerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ResponseManager implements Consumer, BiConsumer, Closeable { + private static final Logger LOG = LoggerUtil.getLogger(ResponseManager.class); + + private final DiscordApi api; + + private final Collection deleteOnShutdown = new HashSet<>(); + private final Map dependencyMap = new ConcurrentHashMap<>(); + + public ResponseManager(DiscordApi api) { + this.api = api; + + Runtime.getRuntime().addShutdownHook(new Thread(this::close)); + } + + public void accept(final @NotNull Message message, @NotNull Message dependency) { + dependency.addMessageDeleteListener(event -> message.delete().whenComplete((nil, thr) -> { + if (thr != null) + LOG.warn("Could not delete message on-dependency"); + })); + } + + @Override + public void accept(final @NotNull Message message, Duration timeToLive) { + if (timeToLive.isZero()) + deleteOnShutdown.add(message.getId()); + else if (timeToLive.isNegative()) + message.delete().whenComplete((nil, thr) -> { + if (thr != null) + LOG.warn("Could not delete message instantly", thr); + }); + else { + api.getThreadPool().getScheduler() + .schedule(() -> message.delete().whenComplete((nil, thr) -> { + if (thr != null) + LOG.warn("Could not delete message on-timeout", thr); + }), timeToLive.toMillis(), TimeUnit.MILLISECONDS); + } + } + + @Override + public void accept(@NotNull Message message) { + accept(message, Duration.ZERO); + } + + @Override + public void close() { + if (deleteOnShutdown.size() == 0) + return; + + deleteOnShutdown.stream() + .map(api::getCachedMessageById) + .filter(Optional::isPresent) + .map(Optional::get) + .map(msg -> (Runnable) () -> msg.delete().whenComplete((nil, thr) -> { + if (thr != null) + LOG.warn("Could not delete message on-shutdown", thr); + })) + .forEach(api.getThreadPool().getDaemonScheduler()::execute); + + deleteOnShutdown.clear(); + } +}