Merge branch 'master' into forms
# Conflicts: # src/main/java/com/alttd/AltitudeBot.java
This commit is contained in:
commit
ead56c4585
|
|
@ -28,6 +28,7 @@ public class AltitudeBot {
|
||||||
private static AltitudeBot instance;
|
private static AltitudeBot instance;
|
||||||
private static String path;
|
private static String path;
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
if (args.length == 0) { //TODO change scripts so it works with this
|
if (args.length == 0) { //TODO change scripts so it works with this
|
||||||
System.out.println("Please give the location for the configs as an arg");
|
System.out.println("Please give the location for the configs as an arg");
|
||||||
|
|
@ -49,7 +50,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,
|
||||||
|
|
@ -92,7 +93,7 @@ public class AltitudeBot {
|
||||||
return file.getPath();
|
return file.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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,12 @@ public class SettingsConfig extends AbstractConfig {
|
||||||
|
|
||||||
// SETTINGS
|
// SETTINGS
|
||||||
public static String TOKEN = "token";
|
public static String TOKEN = "token";
|
||||||
|
public static String KANBOARD_TOKEN = "kanboard-token";
|
||||||
public static boolean DEBUG = false;
|
public static boolean DEBUG = false;
|
||||||
|
|
||||||
private void loadSettings() {
|
private void loadSettings() {
|
||||||
TOKEN = settingsConfig.getString("settings.token", TOKEN);
|
TOKEN = settingsConfig.getString("settings.token", TOKEN);
|
||||||
|
KANBOARD_TOKEN = settingsConfig.getString("settings.kanboard-token", KANBOARD_TOKEN);
|
||||||
DEBUG = settingsConfig.getBoolean("settings.debug", DEBUG);
|
DEBUG = settingsConfig.getBoolean("settings.debug", DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,52 @@
|
||||||
|
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.Message;
|
||||||
|
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 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();
|
||||||
|
|
||||||
|
CompletableFuture<Boolean> booleanCompletableFuture = Kanboard.forwardMessageToKanboard(message);
|
||||||
|
event.deferReply(true).queue(defer -> booleanCompletableFuture.thenAcceptAsync(result -> {
|
||||||
|
if (!result) {
|
||||||
|
defer.editOriginalEmbeds(Util.genericErrorEmbed("Error", "Unable to forward message to Kanboard")).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
defer.editOriginalEmbeds(Util.genericSuccessEmbed("Success", "Forwarded message to Kanboard board!")).queue();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandData getUserContextInteraction() {
|
||||||
|
return Commands.message(getContextMenuId())
|
||||||
|
.setGuildOnly(true)
|
||||||
|
.setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.ADMINISTRATOR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -40,12 +40,13 @@ public class JDAListener extends ListenerAdapter {
|
||||||
Logger.altitudeLogs.info("JDA ready to register commands.");
|
Logger.altitudeLogs.info("JDA ready to register commands.");
|
||||||
LockedChannel lockedChannel = new LockedChannel();
|
LockedChannel lockedChannel = new LockedChannel();
|
||||||
ButtonManager buttonManager = new ButtonManager();
|
ButtonManager buttonManager = new ButtonManager();
|
||||||
|
TagAdded tagAdded = new TagAdded();
|
||||||
AppealRepost appealRepost = new AppealRepost(buttonManager);
|
AppealRepost appealRepost = new AppealRepost(buttonManager);
|
||||||
ModalManager modalManager = new ModalManager(buttonManager);
|
ModalManager modalManager = new ModalManager(buttonManager);
|
||||||
ContextMenuManager contextMenuManager = new ContextMenuManager(modalManager);
|
ContextMenuManager contextMenuManager = new ContextMenuManager(modalManager);
|
||||||
SelectMenuManager selectMenuManager = new SelectMenuManager();
|
SelectMenuManager selectMenuManager = new SelectMenuManager();
|
||||||
CommandManager commandManager = new CommandManager(jda, modalManager, contextMenuManager, lockedChannel, selectMenuManager, buttonManager);
|
CommandManager commandManager = new CommandManager(jda, modalManager, contextMenuManager, lockedChannel, selectMenuManager, buttonManager);
|
||||||
jda.addEventListener(buttonManager, modalManager, commandManager, contextMenuManager, lockedChannel, appealRepost, selectMenuManager);
|
jda.addEventListener(buttonManager, tagAdded, modalManager, commandManager, contextMenuManager, lockedChannel, appealRepost, selectMenuManager);
|
||||||
PollQueries.loadPolls(buttonManager);
|
PollQueries.loadPolls(buttonManager);
|
||||||
new Timer().scheduleAtFixedRate(new PollTimerTask(jda, Logger.altitudeLogs), TimeUnit.MINUTES.toMillis(1), TimeUnit.MINUTES.toMillis(5));
|
new Timer().scheduleAtFixedRate(new PollTimerTask(jda, Logger.altitudeLogs), TimeUnit.MINUTES.toMillis(1), TimeUnit.MINUTES.toMillis(5));
|
||||||
startSchedulers();
|
startSchedulers();
|
||||||
|
|
|
||||||
27
src/main/java/com/alttd/listeners/TagAdded.java
Normal file
27
src/main/java/com/alttd/listeners/TagAdded.java
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.alttd.listeners;
|
||||||
|
|
||||||
|
import com.alttd.util.Kanboard;
|
||||||
|
import com.alttd.util.Logger;
|
||||||
|
import net.dv8tion.jda.api.entities.ISnowflake;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
|
||||||
|
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.util.List;
|
||||||
|
|
||||||
|
public class TagAdded extends ListenerAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChannelUpdateAppliedTags(ChannelUpdateAppliedTagsEvent event) {
|
||||||
|
List<ForumTag> 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
130
src/main/java/com/alttd/util/Kanboard.java
Normal file
130
src/main/java/com/alttd/util/Kanboard.java
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
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;
|
||||||
|
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<Boolean> forwardMessageToKanboard(String title, String body, String webLink) {
|
||||||
|
HttpClient client = HttpClient.newHttpClient();
|
||||||
|
HttpRequest request;
|
||||||
|
String jsonPayload = getPayload(UUID.randomUUID().toString(), title, body, webLink);
|
||||||
|
try {
|
||||||
|
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", "Basic " + 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 && 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]\nPayload: [%s]", response.body(), jsonPayload));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompletableFuture<Boolean> 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).filter(str -> !str.isBlank()).collect(Collectors.joining("\n"));
|
||||||
|
}
|
||||||
|
return forwardMessageToKanboard(title, body, getWebLink(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
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("""
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "createTask",
|
||||||
|
"id": "%s",
|
||||||
|
"params": {
|
||||||
|
"title": "%s",
|
||||||
|
"project_id": "3",
|
||||||
|
"description": "%s%s",
|
||||||
|
"column_id": "0",
|
||||||
|
"color_id": "red"
|
||||||
|
}
|
||||||
|
}""",
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user