From 314dcd6771d96cf22554b7742c78db1a90fd0c20 Mon Sep 17 00:00:00 2001 From: Teriuihi Date: Sun, 31 Mar 2024 14:51:13 +0200 Subject: [PATCH] Refactor code to improve message forwarding to Kanboard This commit extracts the method "forwardMessageToKanboard" from the "TagAdded" class to the new utility class "Kanboard", making the code base cleaner and more maintainable. It also introduces "ContextMenuForwardToKanboard" for better message management. Further modifications include alterations in "AltitudeBot", such as changes in permissions and implementing @Getter. --- .../ContextMenuForwardToKanboard.java | 31 ++------ .../java/com/alttd/listeners/TagAdded.java | 22 +++--- src/main/java/com/alttd/util/Kanboard.java | 71 +++++++++++++++---- 3 files changed, 71 insertions(+), 53 deletions(-) diff --git a/src/main/java/com/alttd/contextMenuManager/contextMenus/ContextMenuForwardToKanboard.java b/src/main/java/com/alttd/contextMenuManager/contextMenus/ContextMenuForwardToKanboard.java index 117bc36..57d6e18 100644 --- a/src/main/java/com/alttd/contextMenuManager/contextMenus/ContextMenuForwardToKanboard.java +++ b/src/main/java/com/alttd/contextMenuManager/contextMenus/ContextMenuForwardToKanboard.java @@ -4,16 +4,13 @@ import com.alttd.contextMenuManager.DiscordContextMenu; import com.alttd.util.Kanboard; import com.alttd.util.Util; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.events.interaction.command.MessageContextInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.UserContextInteractionEvent; import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; import net.dv8tion.jda.api.interactions.commands.build.CommandData; import net.dv8tion.jda.api.interactions.commands.build.Commands; import net.dv8tion.jda.api.requests.RestAction; -import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; import java.util.concurrent.CompletableFuture; @@ -35,33 +32,15 @@ public class ContextMenuForwardToKanboard extends DiscordContextMenu { return; } Message message = event.getInteraction().getTarget(); - Member member = message.getMember(); - if (member == null) - return; - String title = ""; - if (member.getUser().equals(event.getJDA().getSelfUser())) { - if (message.getContentRaw().startsWith("**Suggestion by:")) { - if (message.getGuildChannel() instanceof ThreadChannel threadChannel) { - title = threadChannel.getName(); - } - } - } - - ReplyCallbackAction replyCallbackAction = event.deferReply(true); - CompletableFuture booleanCompletableFuture; - if (title.isBlank()) { - booleanCompletableFuture = Kanboard.forwardMessageToKanboard(message); - } else { - booleanCompletableFuture = Kanboard.forwardMessageToKanboard(title, message.getContentDisplay()); - } - booleanCompletableFuture.thenAcceptAsync(result -> { + CompletableFuture booleanCompletableFuture = Kanboard.forwardMessageToKanboard(message); + event.deferReply(true).queue(defer -> booleanCompletableFuture.thenAcceptAsync(result -> { if (!result) { - replyCallbackAction.setEmbeds(Util.genericErrorEmbed("Error", "Unable to forward message to Kanboard")); + defer.editOriginalEmbeds(Util.genericErrorEmbed("Error", "Unable to forward message to Kanboard")).queue(); return; } - replyCallbackAction.setEmbeds(Util.genericSuccessEmbed("Success", "Forwarded message to Kanboard board!")); - }); + defer.editOriginalEmbeds(Util.genericSuccessEmbed("Success", "Forwarded message to Kanboard board!")).queue(); + })); } @Override diff --git a/src/main/java/com/alttd/listeners/TagAdded.java b/src/main/java/com/alttd/listeners/TagAdded.java index ee45aef..3680d80 100644 --- a/src/main/java/com/alttd/listeners/TagAdded.java +++ b/src/main/java/com/alttd/listeners/TagAdded.java @@ -1,33 +1,27 @@ package com.alttd.listeners; -import com.alttd.config.SettingsConfig; import com.alttd.util.Kanboard; import com.alttd.util.Logger; -import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.ISnowflake; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; -import net.dv8tion.jda.api.events.channel.forum.ForumTagAddEvent; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; +import net.dv8tion.jda.api.events.channel.update.ChannelUpdateAppliedTagsEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; +import java.util.List; public class TagAdded extends ListenerAdapter { @Override - public void onForumTagAdd(ForumTagAddEvent event) { - if (event.getTag().getIdLong() != 0L) {//TODO add tag id + public void onChannelUpdateAppliedTags(ChannelUpdateAppliedTagsEvent event) { + List addedTags = event.getAddedTags(); + if (addedTags.stream().map(ISnowflake::getIdLong).noneMatch(id -> id == 1020378607052398632L)) {//TODO add tag id to config return; } if (!(event.getChannel() instanceof ThreadChannel threadChannel)) { return; } - threadChannel.retrieveStartMessage().queue(Kanboard::forwardMessageToKanboard, error -> { - Logger.altitudeLogs.error(error); - }); + threadChannel.retrieveStartMessage().queue(Kanboard::forwardMessageToKanboard, error -> Logger.altitudeLogs.error(error)); } } diff --git a/src/main/java/com/alttd/util/Kanboard.java b/src/main/java/com/alttd/util/Kanboard.java index 8d86cd2..e711d7f 100644 --- a/src/main/java/com/alttd/util/Kanboard.java +++ b/src/main/java/com/alttd/util/Kanboard.java @@ -1,7 +1,9 @@ package com.alttd.util; import com.alttd.config.SettingsConfig; +import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import java.io.IOException; import java.net.URI; @@ -9,23 +11,26 @@ import java.net.URISyntaxException; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.Base64; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; public class Kanboard { - public static CompletableFuture forwardMessageToKanboard(String title, String body) { + public static CompletableFuture forwardMessageToKanboard(String title, String body, String webLink) { HttpClient client = HttpClient.newHttpClient(); HttpRequest request; + String jsonPayload = getPayload(UUID.randomUUID().toString(), title, body, webLink); try { - String jsonPayload = getPayload(UUID.randomUUID().toString(), title, body); - + byte[] kanboardTokenBytes = String.join(":", "jsonrpc", SettingsConfig.KANBOARD_TOKEN).getBytes(StandardCharsets.UTF_8); + String token = Base64.getEncoder().encodeToString(kanboardTokenBytes); request = HttpRequest.newBuilder() .uri(new URI("https://kanboard.alttd.com/jsonrpc.php")) .header("Content-Type", "application/json") - .setHeader("Authorization", SettingsConfig.KANBOARD_TOKEN) + .setHeader("Authorization", "Basic " + token) .POST(HttpRequest.BodyPublishers.ofString(jsonPayload)) .build(); } catch (URISyntaxException e) { @@ -43,11 +48,11 @@ public class Kanboard { return false; } - if (response.statusCode() == 200) { - Logger.altitudeLogs.info(response.body()); + if (response.statusCode() == 200 && response.body().matches(".*\"result\":[0-9]+,.*")) { + Logger.altitudeLogs.info(String.format("Response body: [%s]\nFor JsonPayload: [%s]", response.body(), jsonPayload)); return true; } else { - Logger.altitudeLogs.error(String.format("Invalid response [%s]", response.body())); + Logger.altitudeLogs.error(String.format("Invalid response: [%s]\nPayload: [%s]", response.body(), jsonPayload)); return false; } }); @@ -55,31 +60,71 @@ public class Kanboard { public static CompletableFuture forwardMessageToKanboard(Message message) { String body = message.getContentDisplay(); + if (messageIsSuggestion(message) && message.getGuildChannel() instanceof ThreadChannel threadChannel) { + return forwardSuggestionToKanboard(message, threadChannel); + } String[] split = body.split("\n"); String title; if (split.length == 1) { title = "No title"; } else { title = split[0]; - body = Arrays.stream(split).skip(1).collect(Collectors.joining("\n")); + body = Arrays.stream(split).skip(1).filter(str -> !str.isBlank()).collect(Collectors.joining("\n")); } - return forwardMessageToKanboard(title, body); + return forwardMessageToKanboard(title, body, getWebLink(message)); } - private static String getPayload(String id, String title, String body) { + private static CompletableFuture forwardSuggestionToKanboard(Message message, ThreadChannel threadChannel) { + String title = threadChannel.getName(); + String content = Arrays.stream(message.getContentDisplay().split("\n")).skip(1).filter(str -> !str.isBlank()).collect(Collectors.joining("\n")); + return forwardMessageToKanboard(title, content, getWebLink(message)); + } + + private static boolean messageIsSuggestion(Message message) { + Member member = message.getMember(); + if (member == null) + return false; + + if (!member.getUser().equals(message.getJDA().getSelfUser())) { + return false; + } + if (!message.getContentRaw().startsWith("**Suggestion by:")) { + return false; + } + return true; + } + + private static String getPayload(String id, String title, String body, String webLink) { return String.format(""" { "jsonrpc": "2.0", "method": "createTask", - "id": %s, + "id": "%s", "params": { "title": "%s", "project_id": "3", - "description": "%s", + "description": "%s%s", "column_id": "0", "color_id": "red" } - }""", id, title, body); + }""", + escapeSpecialJsonChars(id), + escapeSpecialJsonChars(title), + escapeSpecialJsonChars(body), + escapeSpecialJsonChars(String.format("\n\n[Discord link](%s)", webLink))); } + private static String getWebLink(Message message) { + return String.format("https://discord.com/channels/%d/%d/%d", message.getGuildIdLong(), message.getChannelIdLong(), message.getIdLong()); + } + + private static String escapeSpecialJsonChars(String s) { + return s.replace("\"", "\\\"") + .replace("\\", "\\\\") + .replace("\b", "\\b") + .replace("\f", "\\f") + .replace("\n", "\\n") + .replace("\r", "\\r") + .replace("\t", "\\t"); + } }