Add message forwarding functionality to Kanboard
This update includes the creation of a new "ContextMenuForwardToKanboard" and a utility class "Kanboard", which manage the forwarding of messages to Kanboard. The "forwardMessageToKanboard" method has been extracted from "TagAdded" into "Kanboard" for better code organization. These changes also include some minor adjustments like changing the permission called in "AltitudeBot" and implementing the use of @Getter in the same class.
This commit is contained in:
parent
093571d312
commit
32e4a669ed
|
|
@ -7,6 +7,7 @@ import com.alttd.database.Database;
|
||||||
import com.alttd.database.DatabaseTables;
|
import com.alttd.database.DatabaseTables;
|
||||||
import com.alttd.listeners.JDAListener;
|
import com.alttd.listeners.JDAListener;
|
||||||
import com.alttd.util.Logger;
|
import com.alttd.util.Logger;
|
||||||
|
import lombok.Getter;
|
||||||
import net.dv8tion.jda.api.JDA;
|
import net.dv8tion.jda.api.JDA;
|
||||||
import net.dv8tion.jda.api.JDABuilder;
|
import net.dv8tion.jda.api.JDABuilder;
|
||||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||||
|
|
@ -17,12 +18,9 @@ import java.net.URISyntaxException;
|
||||||
public class AltitudeBot {
|
public class AltitudeBot {
|
||||||
|
|
||||||
private JDA jda;
|
private JDA jda;
|
||||||
|
@Getter
|
||||||
private static AltitudeBot instance;
|
private static AltitudeBot instance;
|
||||||
|
|
||||||
public static AltitudeBot getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
instance = new AltitudeBot();
|
instance = new AltitudeBot();
|
||||||
instance.start();
|
instance.start();
|
||||||
|
|
@ -33,7 +31,7 @@ public class AltitudeBot {
|
||||||
initConfigs();
|
initConfigs();
|
||||||
jda = JDABuilder.createDefault(SettingsConfig.TOKEN,
|
jda = JDABuilder.createDefault(SettingsConfig.TOKEN,
|
||||||
GatewayIntent.GUILD_MEMBERS,
|
GatewayIntent.GUILD_MEMBERS,
|
||||||
GatewayIntent.GUILD_BANS,
|
GatewayIntent.GUILD_MODERATION,
|
||||||
GatewayIntent.GUILD_EMOJIS_AND_STICKERS,
|
GatewayIntent.GUILD_EMOJIS_AND_STICKERS,
|
||||||
GatewayIntent.GUILD_WEBHOOKS,
|
GatewayIntent.GUILD_WEBHOOKS,
|
||||||
GatewayIntent.GUILD_PRESENCES,
|
GatewayIntent.GUILD_PRESENCES,
|
||||||
|
|
@ -70,7 +68,7 @@ public class AltitudeBot {
|
||||||
return new File(AltitudeBot.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getPath();
|
return new File(AltitudeBot.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getPath();
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
Logger.altitudeLogs.error("Unable to retrieve config directory");
|
Logger.altitudeLogs.error("Unable to retrieve config directory");
|
||||||
e.printStackTrace();
|
Logger.altitudeLogs.error(e);
|
||||||
}
|
}
|
||||||
return (null);
|
return (null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.alttd.contextMenuManager;
|
package com.alttd.contextMenuManager;
|
||||||
|
|
||||||
|
import com.alttd.contextMenuManager.contextMenus.ContextMenuForwardToKanboard;
|
||||||
import com.alttd.contextMenuManager.contextMenus.ContextMenuRespondSuggestion;
|
import com.alttd.contextMenuManager.contextMenus.ContextMenuRespondSuggestion;
|
||||||
import com.alttd.modalManager.ModalManager;
|
import com.alttd.modalManager.ModalManager;
|
||||||
import com.alttd.util.Util;
|
import com.alttd.util.Util;
|
||||||
|
|
@ -21,7 +22,8 @@ public class ContextMenuManager extends ListenerAdapter {
|
||||||
|
|
||||||
public ContextMenuManager(ModalManager modalManager) {
|
public ContextMenuManager(ModalManager modalManager) {
|
||||||
contextMenus = List.of(
|
contextMenus = List.of(
|
||||||
new ContextMenuRespondSuggestion(modalManager)
|
new ContextMenuRespondSuggestion(modalManager),
|
||||||
|
new ContextMenuForwardToKanboard()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package com.alttd.contextMenuManager.contextMenus;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class ContextMenuForwardToKanboard extends DiscordContextMenu {
|
||||||
|
@Override
|
||||||
|
public String getContextMenuId() {
|
||||||
|
return "Forward To Kanboard";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(UserContextInteractionEvent event) {
|
||||||
|
event.getInteraction().replyEmbeds(Util.genericErrorEmbed("Error", "This interaction should have been a message interaction"))
|
||||||
|
.setEphemeral(true).queue(RestAction.getDefaultSuccess(), Util::handleFailure);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(MessageContextInteractionEvent event) {
|
||||||
|
if (!event.isFromGuild()) {
|
||||||
|
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<Boolean> booleanCompletableFuture;
|
||||||
|
if (title.isBlank()) {
|
||||||
|
booleanCompletableFuture = Kanboard.forwardMessageToKanboard(message);
|
||||||
|
} else {
|
||||||
|
booleanCompletableFuture = Kanboard.forwardMessageToKanboard(title, message.getContentDisplay());
|
||||||
|
}
|
||||||
|
booleanCompletableFuture.thenAcceptAsync(result -> {
|
||||||
|
if (!result) {
|
||||||
|
replyCallbackAction.setEmbeds(Util.genericErrorEmbed("Error", "Unable to forward message to Kanboard"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
replyCallbackAction.setEmbeds(Util.genericSuccessEmbed("Success", "Forwarded message to Kanboard board!"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandData getUserContextInteraction() {
|
||||||
|
return Commands.message(getContextMenuId())
|
||||||
|
.setGuildOnly(true)
|
||||||
|
.setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.ADMINISTRATOR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.alttd.listeners;
|
package com.alttd.listeners;
|
||||||
|
|
||||||
import com.alttd.config.SettingsConfig;
|
import com.alttd.config.SettingsConfig;
|
||||||
|
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.Message;
|
||||||
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
|
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
|
||||||
|
|
@ -16,55 +17,17 @@ import java.net.http.HttpResponse;
|
||||||
|
|
||||||
public class TagAdded extends ListenerAdapter {
|
public class TagAdded extends ListenerAdapter {
|
||||||
|
|
||||||
public void tagAdded(ForumTagAddEvent event) {
|
@Override
|
||||||
|
public void onForumTagAdd(ForumTagAddEvent event) {
|
||||||
if (event.getTag().getIdLong() != 0L) {//TODO add tag id
|
if (event.getTag().getIdLong() != 0L) {//TODO add tag id
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(event.getChannel() instanceof ThreadChannel threadChannel)) {
|
if (!(event.getChannel() instanceof ThreadChannel threadChannel)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
threadChannel.retrieveStartMessage().queue(this::forwardMessageToKanboard, error -> {
|
threadChannel.retrieveStartMessage().queue(Kanboard::forwardMessageToKanboard, error -> {
|
||||||
Logger.altitudeLogs.error(error);
|
Logger.altitudeLogs.error(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO move to its own util class
|
|
||||||
public void forwardMessageToKanboard(Message message) {
|
|
||||||
String contentDisplay = message.getContentDisplay();
|
|
||||||
HttpClient client = HttpClient.newHttpClient();
|
|
||||||
HttpRequest request;
|
|
||||||
try {
|
|
||||||
String jsonPayload = String.format("{"
|
|
||||||
+ "\"title\": \"%s\","
|
|
||||||
+ "\"description\": \"%s\","
|
|
||||||
+ "\"project_id\": \"%d\""
|
|
||||||
+ "}", "New Task" /*TODO config*/, contentDisplay, 3/*TODO config*/);
|
|
||||||
|
|
||||||
request = HttpRequest.newBuilder()
|
|
||||||
.uri(new URI("https://kanboard.alttd.com/jsonrpc.php")) //TODO correct URL
|
|
||||||
.header("Content-Type", "application/json")
|
|
||||||
.setHeader("Authorization", SettingsConfig.KANBOARD_TOKEN)
|
|
||||||
.POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
|
|
||||||
.build();
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
Logger.altitudeLogs.error(e);
|
|
||||||
//TODO handle better
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpResponse<String> response;
|
|
||||||
try {
|
|
||||||
response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
||||||
} catch (InterruptedException | IOException e) {
|
|
||||||
Logger.altitudeLogs.error(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.statusCode() == 200) {
|
|
||||||
Logger.altitudeLogs.info(response.body());
|
|
||||||
} else {
|
|
||||||
Logger.altitudeLogs.error(String.format("Invalid response [%s]", response.body()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
85
src/main/java/com/alttd/util/Kanboard.java
Normal file
85
src/main/java/com/alttd/util/Kanboard.java
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.alttd.util;
|
||||||
|
|
||||||
|
import com.alttd.config.SettingsConfig;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
|
||||||
|
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.Arrays;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class Kanboard {
|
||||||
|
|
||||||
|
public static CompletableFuture<Boolean> forwardMessageToKanboard(String title, String body) {
|
||||||
|
HttpClient client = HttpClient.newHttpClient();
|
||||||
|
HttpRequest request;
|
||||||
|
try {
|
||||||
|
String jsonPayload = getPayload(UUID.randomUUID().toString(), title, body);
|
||||||
|
|
||||||
|
request = HttpRequest.newBuilder()
|
||||||
|
.uri(new URI("https://kanboard.alttd.com/jsonrpc.php"))
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.setHeader("Authorization", SettingsConfig.KANBOARD_TOKEN)
|
||||||
|
.POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
|
||||||
|
.build();
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
Logger.altitudeLogs.error(e);
|
||||||
|
//TODO handle better
|
||||||
|
return CompletableFuture.completedFuture(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
|
HttpResponse<String> response;
|
||||||
|
try {
|
||||||
|
response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
} catch (InterruptedException | IOException e) {
|
||||||
|
Logger.altitudeLogs.error(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode() == 200) {
|
||||||
|
Logger.altitudeLogs.info(response.body());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Logger.altitudeLogs.error(String.format("Invalid response [%s]", response.body()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompletableFuture<Boolean> forwardMessageToKanboard(Message message) {
|
||||||
|
String body = message.getContentDisplay();
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
return forwardMessageToKanboard(title, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getPayload(String id, String title, String body) {
|
||||||
|
return String.format("""
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "createTask",
|
||||||
|
"id": %s,
|
||||||
|
"params": {
|
||||||
|
"title": "%s",
|
||||||
|
"project_id": "3",
|
||||||
|
"description": "%s",
|
||||||
|
"column_id": "0",
|
||||||
|
"color_id": "red"
|
||||||
|
}
|
||||||
|
}""", id, title, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user