[FEAT] Support for Webhook URL's with Thread ID's

This commit is contained in:
2024-03-17 20:02:32 +02:00
parent 28adbf6569
commit 5c478c5ca6
5 changed files with 68 additions and 16 deletions

View File

@@ -9,6 +9,7 @@ import com.hypherionmc.sdlink.core.discord.BotController;
import com.hypherionmc.sdlink.core.messaging.MessageDestination; import com.hypherionmc.sdlink.core.messaging.MessageDestination;
import lombok.Getter; import lombok.Getter;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildChannel;
import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel;
@@ -22,9 +23,9 @@ import java.util.HashMap;
*/ */
public class ChannelManager { public class ChannelManager {
private static final HashMap<MessageDestination, Pair<MessageChannel, Boolean>> channelMap = new HashMap<>(); private static final HashMap<MessageDestination, Pair<GuildMessageChannel, Boolean>> channelMap = new HashMap<>();
@Getter @Getter
private static MessageChannel consoleChannel; private static GuildMessageChannel consoleChannel;
/** /**
* Load configured channel, while always defaulting back to ChatChannel for channels that aren't configured * Load configured channel, while always defaulting back to ChatChannel for channels that aren't configured
@@ -34,9 +35,9 @@ public class ChannelManager {
JDA jda = BotController.INSTANCE.getJDA(); JDA jda = BotController.INSTANCE.getJDA();
MessageChannel chatChannel = jda.getChannelById(MessageChannel.class, SDLinkConfig.INSTANCE.channelsAndWebhooks.channels.chatChannelID); GuildMessageChannel chatChannel = jda.getChannelById(GuildMessageChannel.class, SDLinkConfig.INSTANCE.channelsAndWebhooks.channels.chatChannelID);
MessageChannel eventChannel = jda.getChannelById(MessageChannel.class, SDLinkConfig.INSTANCE.channelsAndWebhooks.channels.eventsChannelID); GuildMessageChannel eventChannel = jda.getChannelById(GuildMessageChannel.class, SDLinkConfig.INSTANCE.channelsAndWebhooks.channels.eventsChannelID);
consoleChannel = jda.getChannelById(MessageChannel.class, SDLinkConfig.INSTANCE.channelsAndWebhooks.channels.consoleChannelID); consoleChannel = jda.getChannelById(GuildMessageChannel.class, SDLinkConfig.INSTANCE.channelsAndWebhooks.channels.consoleChannelID);
if (chatChannel != null) { if (chatChannel != null) {
channelMap.put(MessageDestination.CHAT, Pair.of(chatChannel, false)); channelMap.put(MessageDestination.CHAT, Pair.of(chatChannel, false));
@@ -46,7 +47,7 @@ public class ChannelManager {
channelMap.put(MessageDestination.CONSOLE, consoleChannel != null ? Pair.of(consoleChannel, true) : Pair.of(chatChannel, false)); channelMap.put(MessageDestination.CONSOLE, consoleChannel != null ? Pair.of(consoleChannel, true) : Pair.of(chatChannel, false));
} }
public static MessageChannel getDestinationChannel(MessageDestination destination) { public static GuildMessageChannel getDestinationChannel(MessageDestination destination) {
return channelMap.get(destination).getLeft(); return channelMap.get(destination).getLeft();
} }
} }

View File

@@ -9,6 +9,8 @@ import com.hypherionmc.sdlink.core.discord.BotController;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel;
import java.util.ArrayList; import java.util.ArrayList;
@@ -153,7 +155,7 @@ public class PermissionChecker {
return; return;
} }
StandardGuildMessageChannel channel = BotController.INSTANCE.getJDA().getChannelById(StandardGuildMessageChannel.class, channelID); GuildMessageChannel channel = BotController.INSTANCE.getJDA().getChannelById(GuildMessageChannel.class, channelID);
if (channel == null) { if (channel == null) {
errCount.incrementAndGet(); errCount.incrementAndGet();
@@ -163,7 +165,7 @@ public class PermissionChecker {
.append(" ID does not point to a valid Discord Channel. Please double check this") .append(" ID does not point to a valid Discord Channel. Please double check this")
.append("\r\n"); .append("\r\n");
} else { } else {
EnumSet<Permission> chatPerms = bot.getPermissionsExplicit(channel); EnumSet<Permission> chatPerms = bot.getPermissions(channel);
BASE_CHANNEL_PERMS.forEach(perm -> { BASE_CHANNEL_PERMS.forEach(perm -> {
if (!chatPerms.contains(perm)) { if (!chatPerms.contains(perm)) {

View File

@@ -10,8 +10,13 @@ import com.hypherionmc.sdlink.core.discord.BotController;
import com.hypherionmc.sdlink.core.messaging.MessageDestination; import com.hypherionmc.sdlink.core.messaging.MessageDestination;
import com.hypherionmc.sdlink.core.messaging.SDLinkWebhookClient; import com.hypherionmc.sdlink.core.messaging.SDLinkWebhookClient;
import com.hypherionmc.sdlink.core.util.EncryptionUtil; import com.hypherionmc.sdlink.core.util.EncryptionUtil;
import org.apache.commons.lang3.tuple.Pair;
import java.util.HashMap; import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static club.minnced.discord.webhook.WebhookClientBuilder.WEBHOOK_PATTERN;
/** /**
* @author HypherionSA * @author HypherionSA
@@ -21,6 +26,7 @@ public class WebhookManager {
private static final HashMap<MessageDestination, WebhookClient> clientMap = new HashMap<>(); private static final HashMap<MessageDestination, WebhookClient> clientMap = new HashMap<>();
private static WebhookClient chatWebhookClient, eventWebhookClient, consoleWebhookClient; private static WebhookClient chatWebhookClient, eventWebhookClient, consoleWebhookClient;
private static final Pattern THREAD_PATTERN = Pattern.compile("thread_id=(\\d+)");
/** /**
* Load configured webhook clients * Load configured webhook clients
@@ -36,26 +42,26 @@ public class WebhookManager {
return; return;
if (!SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.chatWebhook.isEmpty()) { if (!SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.chatWebhook.isEmpty()) {
chatWebhookClient = new SDLinkWebhookClient( chatWebhookClient = createClient(
"Chat", "Chat",
EncryptionUtil.INSTANCE.decrypt(SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.chatWebhook) EncryptionUtil.INSTANCE.decrypt(SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.chatWebhook)
).build(); );
BotController.INSTANCE.getLogger().info("Using Webhook for Chat Messages"); BotController.INSTANCE.getLogger().info("Using Webhook for Chat Messages");
} }
if (!SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.eventsWebhook.isEmpty()) { if (!SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.eventsWebhook.isEmpty()) {
eventWebhookClient = new SDLinkWebhookClient( eventWebhookClient = createClient(
"Events", "Events",
EncryptionUtil.INSTANCE.decrypt(SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.eventsWebhook) EncryptionUtil.INSTANCE.decrypt(SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.eventsWebhook)
).build(); );
BotController.INSTANCE.getLogger().info("Using Webhook for Event Messages"); BotController.INSTANCE.getLogger().info("Using Webhook for Event Messages");
} }
if (!SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.consoleWebhook.isEmpty()) { if (!SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.consoleWebhook.isEmpty()) {
consoleWebhookClient = new SDLinkWebhookClient( consoleWebhookClient = createClient(
"Console", "Console",
EncryptionUtil.INSTANCE.decrypt(SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.consoleWebhook) EncryptionUtil.INSTANCE.decrypt(SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.consoleWebhook)
).build(); );
BotController.INSTANCE.getLogger().info("Using Webhook for Console Messages"); BotController.INSTANCE.getLogger().info("Using Webhook for Console Messages");
} }
@@ -82,4 +88,41 @@ public class WebhookManager {
consoleWebhookClient.close(); consoleWebhookClient.close();
} }
} }
/**
* Workaround to support ThreadID's in Webhook URLS
* @param name The name of the Webhook Client
* @param url The Webhook URL
* @return The client with thread id set, if found
*/
private static WebhookClient createClient(String name, String url) {
url = EncryptionUtil.INSTANCE.decrypt(url);
Matcher threadMatcher = THREAD_PATTERN.matcher(url);
Matcher webhookMatcher = WEBHOOK_PATTERN.matcher(url);
if (threadMatcher.find() && webhookMatcher.find()) {
return new SDLinkWebhookClient(
name,
String.format("https://discord.com/api/webhooks/%s/%s", webhookMatcher.group(1), webhookMatcher.group(2))
).setThreadChannelID(threadMatcher.group(1)).build();
} else if (webhookMatcher.matches()) {
return new SDLinkWebhookClient(name, String.format("https://discord.com/api/webhooks/%s/%s", webhookMatcher.group(1), webhookMatcher.group(2))).build();
}
return new SDLinkWebhookClient(name, url).build();
}
private static Pair<String, String> parseWebhookUrl(String url) {
final Pattern pattern = Pattern.compile("\\?thread_id=[0-9]+", Pattern.CASE_INSENSITIVE);
String thread = "0";
if (pattern.matcher(url).find()) {
thread = pattern.matcher(url).group(0);
}
String whurl = url.replace("?thread_id=" + thread, "");
return Pair.of(whurl, thread);
}
} }

View File

@@ -24,4 +24,9 @@ public class SDLinkWebhookClient extends WebhookClientBuilder {
this.setWait(false); this.setWait(false);
} }
public SDLinkWebhookClient setThreadChannelID(String id) {
this.setThreadId(Long.parseLong(id));
return this;
}
} }

View File

@@ -19,6 +19,7 @@ import com.hypherionmc.sdlink.core.messaging.MessageType;
import com.hypherionmc.sdlink.core.util.SDLinkUtils; import com.hypherionmc.sdlink.core.util.SDLinkUtils;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildChannel;
import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel;
@@ -82,7 +83,7 @@ public final class DiscordMessage {
* Send a Non Console relay message to discord * Send a Non Console relay message to discord
*/ */
private void sendNormalMessage() { private void sendNormalMessage() {
Triple<MessageChannel, WebhookClient, MessageChannelConfig.DestinationObject> channel = resolveDestination(); Triple<GuildMessageChannel, WebhookClient, MessageChannelConfig.DestinationObject> channel = resolveDestination();
// Check if a webhook is configured, and use that instead // Check if a webhook is configured, and use that instead
if (channel.getMiddle() != null && SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.enabled) { if (channel.getMiddle() != null && SDLinkConfig.INSTANCE.channelsAndWebhooks.webhooks.enabled) {
@@ -186,7 +187,7 @@ public final class DiscordMessage {
/** /**
* Figure out where the message must be delivered to, based on the config values * Figure out where the message must be delivered to, based on the config values
*/ */
private Triple<MessageChannel, WebhookClient, MessageChannelConfig.DestinationObject> resolveDestination() { private Triple<GuildMessageChannel, WebhookClient, MessageChannelConfig.DestinationObject> resolveDestination() {
switch (messageType) { switch (messageType) {
case CHAT -> { case CHAT -> {
MessageChannelConfig.DestinationObject chat = SDLinkConfig.INSTANCE.messageDestinations.chat; MessageChannelConfig.DestinationObject chat = SDLinkConfig.INSTANCE.messageDestinations.chat;