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.
This commit is contained in:
Teriuihi 2024-03-31 14:51:13 +02:00
parent 32e4a669ed
commit 314dcd6771
3 changed files with 71 additions and 53 deletions

View File

@ -4,16 +4,13 @@ import com.alttd.contextMenuManager.DiscordContextMenu;
import com.alttd.util.Kanboard; import com.alttd.util.Kanboard;
import com.alttd.util.Util; import com.alttd.util.Util;
import net.dv8tion.jda.api.Permission; 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.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.MessageContextInteractionEvent;
import net.dv8tion.jda.api.events.interaction.command.UserContextInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.UserContextInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; 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.CommandData;
import net.dv8tion.jda.api.interactions.commands.build.Commands; import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.requests.RestAction; import net.dv8tion.jda.api.requests.RestAction;
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -35,33 +32,15 @@ public class ContextMenuForwardToKanboard extends DiscordContextMenu {
return; return;
} }
Message message = event.getInteraction().getTarget(); Message message = event.getInteraction().getTarget();
Member member = message.getMember();
if (member == null)
return;
String title = ""; CompletableFuture<Boolean> booleanCompletableFuture = Kanboard.forwardMessageToKanboard(message);
if (member.getUser().equals(event.getJDA().getSelfUser())) { event.deferReply(true).queue(defer -> booleanCompletableFuture.thenAcceptAsync(result -> {
if (message.getContentRaw().startsWith("**Suggestion by:")) {
if (message.getGuildChannel() instanceof ThreadChannel threadChannel) {
title = threadChannel.getName();
}
}
}
ReplyCallbackAction replyCallbackAction = event.deferReply(true);
CompletableFuture<Boolean> booleanCompletableFuture;
if (title.isBlank()) {
booleanCompletableFuture = Kanboard.forwardMessageToKanboard(message);
} else {
booleanCompletableFuture = Kanboard.forwardMessageToKanboard(title, message.getContentDisplay());
}
booleanCompletableFuture.thenAcceptAsync(result -> {
if (!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; return;
} }
replyCallbackAction.setEmbeds(Util.genericSuccessEmbed("Success", "Forwarded message to Kanboard board!")); defer.editOriginalEmbeds(Util.genericSuccessEmbed("Success", "Forwarded message to Kanboard board!")).queue();
}); }));
} }
@Override @Override

View File

@ -1,33 +1,27 @@
package com.alttd.listeners; package com.alttd.listeners;
import com.alttd.config.SettingsConfig;
import com.alttd.util.Kanboard; import com.alttd.util.Kanboard;
import com.alttd.util.Logger; 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.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 net.dv8tion.jda.api.hooks.ListenerAdapter;
import java.io.IOException; import java.util.List;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class TagAdded extends ListenerAdapter { public class TagAdded extends ListenerAdapter {
@Override @Override
public void onForumTagAdd(ForumTagAddEvent event) { public void onChannelUpdateAppliedTags(ChannelUpdateAppliedTagsEvent event) {
if (event.getTag().getIdLong() != 0L) {//TODO add tag id List<ForumTag> addedTags = event.getAddedTags();
if (addedTags.stream().map(ISnowflake::getIdLong).noneMatch(id -> id == 1020378607052398632L)) {//TODO add tag id to config
return; return;
} }
if (!(event.getChannel() instanceof ThreadChannel threadChannel)) { if (!(event.getChannel() instanceof ThreadChannel threadChannel)) {
return; return;
} }
threadChannel.retrieveStartMessage().queue(Kanboard::forwardMessageToKanboard, error -> { threadChannel.retrieveStartMessage().queue(Kanboard::forwardMessageToKanboard, error -> Logger.altitudeLogs.error(error));
Logger.altitudeLogs.error(error);
});
} }
} }

View File

@ -1,7 +1,9 @@
package com.alttd.util; package com.alttd.util;
import com.alttd.config.SettingsConfig; 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.Message;
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -9,23 +11,26 @@ import java.net.URISyntaxException;
import java.net.http.HttpClient; import java.net.http.HttpClient;
import java.net.http.HttpRequest; import java.net.http.HttpRequest;
import java.net.http.HttpResponse; import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.Base64;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class Kanboard { public class Kanboard {
public static CompletableFuture<Boolean> forwardMessageToKanboard(String title, String body) { public static CompletableFuture<Boolean> forwardMessageToKanboard(String title, String body, String webLink) {
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();
HttpRequest request; HttpRequest request;
String jsonPayload = getPayload(UUID.randomUUID().toString(), title, body, webLink);
try { 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() request = HttpRequest.newBuilder()
.uri(new URI("https://kanboard.alttd.com/jsonrpc.php")) .uri(new URI("https://kanboard.alttd.com/jsonrpc.php"))
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.setHeader("Authorization", SettingsConfig.KANBOARD_TOKEN) .setHeader("Authorization", "Basic " + token)
.POST(HttpRequest.BodyPublishers.ofString(jsonPayload)) .POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
.build(); .build();
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
@ -43,11 +48,11 @@ public class Kanboard {
return false; return false;
} }
if (response.statusCode() == 200) { if (response.statusCode() == 200 && response.body().matches(".*\"result\":[0-9]+,.*")) {
Logger.altitudeLogs.info(response.body()); Logger.altitudeLogs.info(String.format("Response body: [%s]\nFor JsonPayload: [%s]", response.body(), jsonPayload));
return true; return true;
} else { } 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; return false;
} }
}); });
@ -55,31 +60,71 @@ public class Kanboard {
public static CompletableFuture<Boolean> forwardMessageToKanboard(Message message) { public static CompletableFuture<Boolean> forwardMessageToKanboard(Message message) {
String body = message.getContentDisplay(); String body = message.getContentDisplay();
if (messageIsSuggestion(message) && message.getGuildChannel() instanceof ThreadChannel threadChannel) {
return forwardSuggestionToKanboard(message, threadChannel);
}
String[] split = body.split("\n"); String[] split = body.split("\n");
String title; String title;
if (split.length == 1) { if (split.length == 1) {
title = "No title"; title = "No title";
} else { } else {
title = split[0]; 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<Boolean> 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(""" return String.format("""
{ {
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "createTask", "method": "createTask",
"id": %s, "id": "%s",
"params": { "params": {
"title": "%s", "title": "%s",
"project_id": "3", "project_id": "3",
"description": "%s", "description": "%s%s",
"column_id": "0", "column_id": "0",
"color_id": "red" "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");
}
} }