From 7c58d2b925055e83c181ad11dbcc7a72a3fa0408 Mon Sep 17 00:00:00 2001 From: HypherionMC Date: Sat, 5 Aug 2023 19:33:34 +0200 Subject: [PATCH] [FEAT] Initial Custom Embeds --- .../sdlink/core/discord/BotController.java | 4 + .../sdlink/core/managers/EmbedManager.java | 72 +++++++++++++ .../messaging/discord/DiscordMessage.java | 100 ++++++++++++++++-- .../core/messaging/embeds/DiscordEmbed.java | 42 ++++++++ 4 files changed, 208 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/hypherionmc/sdlink/core/managers/EmbedManager.java create mode 100644 src/main/java/com/hypherionmc/sdlink/core/messaging/embeds/DiscordEmbed.java diff --git a/src/main/java/com/hypherionmc/sdlink/core/discord/BotController.java b/src/main/java/com/hypherionmc/sdlink/core/discord/BotController.java index 94b642a..795e98b 100644 --- a/src/main/java/com/hypherionmc/sdlink/core/discord/BotController.java +++ b/src/main/java/com/hypherionmc/sdlink/core/discord/BotController.java @@ -8,6 +8,7 @@ import com.hypherionmc.sdlink.core.config.SDLinkConfig; import com.hypherionmc.sdlink.core.discord.commands.CommandManager; import com.hypherionmc.sdlink.core.discord.events.DiscordEventHandler; import com.hypherionmc.sdlink.core.managers.DatabaseManager; +import com.hypherionmc.sdlink.core.managers.EmbedManager; import com.hypherionmc.sdlink.core.managers.WebhookManager; import com.hypherionmc.sdlink.core.services.SDLinkPlatform; import com.hypherionmc.sdlink.core.util.EncryptionUtil; @@ -85,6 +86,9 @@ public class BotController { // Initialize Webhook Clients WebhookManager.init(); + + // Initialize Embeds + EmbedManager.init(); } /** diff --git a/src/main/java/com/hypherionmc/sdlink/core/managers/EmbedManager.java b/src/main/java/com/hypherionmc/sdlink/core/managers/EmbedManager.java new file mode 100644 index 0000000..812d912 --- /dev/null +++ b/src/main/java/com/hypherionmc/sdlink/core/managers/EmbedManager.java @@ -0,0 +1,72 @@ +package com.hypherionmc.sdlink.core.managers; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.hypherionmc.sdlink.core.discord.BotController; +import com.hypherionmc.sdlink.core.messaging.embeds.DiscordEmbed; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ConcurrentHashMap; + +public class EmbedManager { + + private static final File embedDir = new File("./config/simple-discord-link/embeds"); + private static final Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create(); + private static final ConcurrentHashMap embeds = new ConcurrentHashMap<>(); + + public static void init() { + embeds.clear(); + + if (!embedDir.exists()) { + embedDir.mkdirs(); + } + defaultEmbeds(); + if (embedDir.listFiles() == null) + return; + + for (File file : embedDir.listFiles()) { + if (file.isFile() && file.getName().endsWith(".json")) { + try { + String json = FileUtils.readFileToString(file, StandardCharsets.UTF_8); + embeds.put(file.getName().replace(".json", ""), json); + } catch (Exception e) { + BotController.INSTANCE.getLogger().error("Failed to load custom embed {}", file.getName(), e); + } + } + } + } + + public static String getEmbed(String key) { + return embeds.get(key); + } + + private static void defaultEmbeds() { + File defaultEmbed = new File(embedDir.getAbsolutePath() + File.separator + "default.json"); + if (!defaultEmbed.exists()) { + DiscordEmbed embed = new DiscordEmbed(); + + DiscordEmbed.Author author = new DiscordEmbed.Author(); + author.name = "%author%"; + author.url = null; + author.icon_url = "%avatar%"; + embed.author = author; + embed.description = "%message_contents%"; + embed.color = "#000000"; + writeToFile(defaultEmbed, embed); + } + } + + private static void writeToFile(File file, Object data) { + try (Writer writer = new FileWriter(file)) { + gson.toJson(data, writer); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/hypherionmc/sdlink/core/messaging/discord/DiscordMessage.java b/src/main/java/com/hypherionmc/sdlink/core/messaging/discord/DiscordMessage.java index 7f0bce1..959c573 100644 --- a/src/main/java/com/hypherionmc/sdlink/core/messaging/discord/DiscordMessage.java +++ b/src/main/java/com/hypherionmc/sdlink/core/messaging/discord/DiscordMessage.java @@ -13,12 +13,23 @@ import com.hypherionmc.sdlink.core.config.SDLinkConfig; import com.hypherionmc.sdlink.core.config.impl.MessageChannelConfig; import com.hypherionmc.sdlink.core.discord.BotController; import com.hypherionmc.sdlink.core.managers.ChannelManager; +import com.hypherionmc.sdlink.core.managers.EmbedManager; import com.hypherionmc.sdlink.core.managers.WebhookManager; import com.hypherionmc.sdlink.core.messaging.MessageType; import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; +import net.dv8tion.jda.api.utils.data.DataArray; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.internal.utils.Checks; import org.apache.commons.lang3.tuple.Triple; +import javax.annotation.Nonnull; +import java.awt.*; +import java.time.OffsetDateTime; + +import static net.dv8tion.jda.api.EmbedBuilder.ZERO_WIDTH_SPACE; + /** * @author HypherionSA * Represents a message sent from Minecraft to Discord @@ -138,19 +149,32 @@ public final class DiscordMessage { * Build an embed with the supplied information * @param withAuthor Should the author be appended to the embed. Not used for Webhooks */ - private EmbedBuilder buildEmbed(boolean withAuthor, String embedLayout) { - EmbedBuilder builder = new EmbedBuilder(); + private EmbedBuilder buildEmbed(boolean withAuthor, String key) { + String embedJson = EmbedManager.getEmbed(key); - if (withAuthor) { - builder.setAuthor( - this.author.getDisplayName(), - null, - this.author.getAvatar().isEmpty() ? null : this.author.getAvatar() - ); + if (embedJson == null || embedJson.isEmpty()) { + EmbedBuilder builder = new EmbedBuilder(); + + if (withAuthor) { + builder.setAuthor( + this.author.getDisplayName(), + null, + this.author.getAvatar().isEmpty() ? null : this.author.getAvatar() + ); + } + + builder.setDescription(message); + return builder; } - builder.setDescription(message); - return builder; + embedJson = embedJson + .replace("%author%", this.author.getDisplayName()) + .replace("%avatar%", this.author.getAvatar()) + .replace("%message_contents%", this.message) + .replace("%username%", this.author.getRawUsername()); + + DataObject object = DataObject.fromJson(embedJson); + return fromData(object); } /** @@ -220,4 +244,60 @@ public final class DiscordMessage { MessageChannelConfig.DestinationObject chat = SDLinkConfig.INSTANCE.messageDestinations.chat; return Triple.of(ChannelManager.getDestinationChannel(chat.channel), WebhookManager.getWebhookClient(chat.channel), chat); } + + @Nonnull + private EmbedBuilder fromData(@Nonnull DataObject data) + { + Checks.notNull(data, "DataObject"); + EmbedBuilder builder = new EmbedBuilder(); + + builder.setTitle(data.getString("title", null)); + builder.setUrl(data.getString("url", null)); + builder.setDescription(data.getString("description", "")); + + if (!data.isNull("timestamp") && !data.getString("timestamp").equalsIgnoreCase("0")) { + builder.setTimestamp(OffsetDateTime.parse(data.getString("timestamp"))); + } + + if (data.getString("color", "#000000").startsWith("#")) { + builder.setColor(Color.decode(data.getString("color", "#000000"))); + } else { + builder.setColor(data.getInt("color", Role.DEFAULT_COLOR_RAW)); + } + + data.optObject("thumbnail").ifPresent(thumbnail -> + builder.setThumbnail(thumbnail.getString("url")) + ); + + data.optObject("author").ifPresent(author -> + builder.setAuthor( + author.getString("name", ""), + author.getString("url", null), + author.getString("icon_url", null) + ) + ); + + data.optObject("footer").ifPresent(footer -> + builder.setFooter( + footer.getString("text", ""), + footer.getString("icon_url", null) + ) + ); + + data.optObject("image").ifPresent(image -> + builder.setImage(image.getString("url")) + ); + + data.optArray("fields").ifPresent(arr -> + arr.stream(DataArray::getObject).forEach(field -> + builder.addField( + field.getString("name", ZERO_WIDTH_SPACE), + field.getString("value", ZERO_WIDTH_SPACE), + field.getBoolean("inline", false) + ) + ) + ); + + return builder; + } } diff --git a/src/main/java/com/hypherionmc/sdlink/core/messaging/embeds/DiscordEmbed.java b/src/main/java/com/hypherionmc/sdlink/core/messaging/embeds/DiscordEmbed.java new file mode 100644 index 0000000..6a3d1f4 --- /dev/null +++ b/src/main/java/com/hypherionmc/sdlink/core/messaging/embeds/DiscordEmbed.java @@ -0,0 +1,42 @@ +package com.hypherionmc.sdlink.core.messaging.embeds; + +import java.util.ArrayList; + +public class DiscordEmbed { + + public String color; + public String title; + public String url; + public Author author; + public String description; + public Thumbnail thumbnail; + public ArrayList fields; + public Image image; + public int timestamp; + public Footer footer; + + public static class Author { + public String name; + public String icon_url; + public String url; + } + + public static class Field { + public String name; + public String value; + public boolean inline; + } + + public static class Footer { + public String text; + public String icon_url; + } + + public static class Image { + public String url; + } + + public static class Thumbnail { + public String url; + } +} \ No newline at end of file