From 1d5a5381a0170bdcafa93b3f57a7232f0fa8d525 Mon Sep 17 00:00:00 2001 From: Vankka Date: Wed, 22 Nov 2023 01:15:06 +0200 Subject: [PATCH] Refactor some mention rendering code to not be Discord -> Minecraft specific --- .../renderer/DiscordSRVMinecraftRenderer.java | 139 +++++++++++------- .../DiscordToMinecraftChatConfig.java | 45 +----- .../config/main/generic/MentionsConfig.java | 56 +++++++ 3 files changed, 147 insertions(+), 93 deletions(-) create mode 100644 common/src/main/java/com/discordsrv/common/config/main/generic/MentionsConfig.java diff --git a/common/src/main/java/com/discordsrv/common/component/renderer/DiscordSRVMinecraftRenderer.java b/common/src/main/java/com/discordsrv/common/component/renderer/DiscordSRVMinecraftRenderer.java index 0edd3426..30c68b80 100644 --- a/common/src/main/java/com/discordsrv/common/component/renderer/DiscordSRVMinecraftRenderer.java +++ b/common/src/main/java/com/discordsrv/common/component/renderer/DiscordSRVMinecraftRenderer.java @@ -28,6 +28,7 @@ import com.discordsrv.api.event.events.message.process.discord.DiscordChatMessag import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.component.util.ComponentUtil; import com.discordsrv.common.config.main.channels.DiscordToMinecraftChatConfig; +import com.discordsrv.common.config.main.generic.MentionsConfig; import dev.vankka.mcdiscordreserializer.renderer.implementation.DefaultMinecraftRenderer; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; @@ -35,6 +36,7 @@ import net.dv8tion.jda.api.utils.MiscUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.function.Supplier; import java.util.regex.Matcher; @@ -75,75 +77,100 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer { @Override public Component appendLink(@NotNull Component part, String link) { - JDA jda = discordSRV.jda(); - - if (jda != null) { - Matcher matcher = MESSAGE_URL_PATTERN.matcher(link); - if (matcher.matches()) { - String channel = matcher.group(1); - GuildChannel guildChannel = jda.getGuildChannelById(channel); - - Context context = CONTEXT.get(); - String format = context != null ? context.config.mentions.messageUrl : null; - if (format == null || guildChannel == null) { - return super.appendLink(part, link); - } - - return Component.text() - .clickEvent(ClickEvent.openUrl(link)) - .append( - ComponentUtil.fromAPI( - discordSRV.componentFactory() - .textBuilder(format) - .addContext(guildChannel) - .addPlaceholder("jump_url", link) - .applyPlaceholderService() - .build() - ) - ) - .build(); - } + Component messageLink = makeMessageLink(link); + if (messageLink == null) { + return super.appendLink(part, link); } - return super.appendLink(part, link); + return part.append(messageLink); + } + + public Component makeMessageLink(String link) { + JDA jda = discordSRV.jda(); + if (jda == null) { + return null; + } + + Matcher matcher = MESSAGE_URL_PATTERN.matcher(link); + if (!matcher.matches()) { + return null; + } + + String channel = matcher.group(1); + GuildChannel guildChannel = jda.getGuildChannelById(channel); + + Context context = CONTEXT.get(); + String format = context != null ? context.config.mentions.messageUrl : null; + if (format == null || guildChannel == null) { + return null; + } + + return Component.text() + .clickEvent(ClickEvent.openUrl(link)) + .append( + ComponentUtil.fromAPI( + discordSRV.componentFactory() + .textBuilder(format) + .addContext(guildChannel) + .addPlaceholder("jump_url", link) + .applyPlaceholderService() + .build() + ) + ) + .build(); } @Override public @NotNull Component appendChannelMention(@NotNull Component component, @NotNull String id) { Context context = CONTEXT.get(); - DiscordToMinecraftChatConfig.Mentions.Format format = context != null ? context.config.mentions.channel : null; + MentionsConfig.Format format = context != null ? context.config.mentions.channel : null; if (format == null) { return component.append(Component.text("<#" + id + ">")); } + Component mention = makeChannelMention(MiscUtil.parseLong(id), format); + if (mention == null) { + return component; + } + + return component.append(mention); + } + + @Nullable + public Component makeChannelMention(long id, MentionsConfig.Format format) { JDA jda = discordSRV.jda(); if (jda == null) { - return Component.empty(); + return null; } GuildChannel guildChannel = jda.getGuildChannelById(id); - return component.append(ComponentUtil.fromAPI( + return ComponentUtil.fromAPI( discordSRV.componentFactory() .textBuilder(guildChannel != null ? format.format : format.unknownFormat) .addContext(guildChannel) .applyPlaceholderService() .build() - )); + ); } @Override public @NotNull Component appendUserMention(@NotNull Component component, @NotNull String id) { Context context = CONTEXT.get(); - DiscordToMinecraftChatConfig.Mentions.Format format = context != null ? context.config.mentions.user : null; + MentionsConfig.Format format = context != null ? context.config.mentions.user : null; DiscordGuild guild = context != null ? context.guild : null; if (format == null || guild == null) { return component.append(Component.text("<@" + id + ">")); } long userId = MiscUtil.parseLong(id); - DiscordUser user = discordSRV.discordAPI().getUserById(userId); - DiscordGuildMember member = guild.getMemberById(userId); + return component.append(makeUserMention(userId, format, guild)); + } + + @NotNull + public Component makeUserMention(long id, MentionsConfig.Format format, DiscordGuild guild) { + DiscordUser user = discordSRV.discordAPI().getUserById(id); + DiscordGuildMember member = guild.getMemberById(id); GameTextBuilder builder = discordSRV.componentFactory() .textBuilder(user != null ? format.format : format.unknownFormat); @@ -155,21 +182,25 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer { builder.addContext(member); } - return component.append(ComponentUtil.fromAPI( + return ComponentUtil.fromAPI( builder.applyPlaceholderService().build() - )); + ); } @Override public @NotNull Component appendRoleMention(@NotNull Component component, @NotNull String id) { Context context = CONTEXT.get(); - DiscordToMinecraftChatConfig.Mentions.Format format = context != null ? context.config.mentions.role : null; + MentionsConfig.Format format = context != null ? context.config.mentions.role : null; if (format == null) { return component.append(Component.text("<#" + id + ">")); } long roleId = MiscUtil.parseLong(id); - DiscordRole role = discordSRV.discordAPI().getRoleById(roleId); + return component.append(makeRoleMention(roleId, format)); + } + + public Component makeRoleMention(long id, MentionsConfig.Format format) { + DiscordRole role = discordSRV.discordAPI().getRoleById(id); GameTextBuilder builder = discordSRV.componentFactory() .textBuilder(role != null ? format.format : format.unknownFormat); @@ -178,9 +209,9 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer { builder.addContext(role); } - return component.append(ComponentUtil.fromAPI( + return ComponentUtil.fromAPI( builder.applyPlaceholderService().build() - )); + ); } @Override @@ -190,31 +221,39 @@ public class DiscordSRVMinecraftRenderer extends DefaultMinecraftRenderer { @NotNull String id ) { Context context = CONTEXT.get(); - DiscordToMinecraftChatConfig.EmoteBehaviour behaviour = context != null ? context.config.customEmojiBehaviour : null; - if (behaviour == null || behaviour == DiscordToMinecraftChatConfig.EmoteBehaviour.HIDE) { + MentionsConfig.EmoteBehaviour behaviour = context != null ? context.config.mentions.customEmojiBehaviour : null; + if (behaviour == null || behaviour == MentionsConfig.EmoteBehaviour.HIDE) { return component; } long emojiId = MiscUtil.parseLong(id); - DiscordCustomEmoji emoji = discordSRV.discordAPI().getEmojiById(emojiId); - if (emoji == null) { + Component emoteMention = makeEmoteMention(emojiId, behaviour); + if (emoteMention == null) { return component; } + return component.append(emoteMention); + } + + public Component makeEmoteMention(long id, MentionsConfig.EmoteBehaviour behaviour) { + DiscordCustomEmoji emoji = discordSRV.discordAPI().getEmojiById(id); + if (emoji == null) { + return null; + } + DiscordChatMessageCustomEmojiRenderEvent event = new DiscordChatMessageCustomEmojiRenderEvent(emoji); discordSRV.eventBus().publish(event); if (event.isProcessed()) { - Component rendered = ComponentUtil.fromAPI(event.getRenderedEmojiFromProcessing()); - return component.append(rendered); + return ComponentUtil.fromAPI(event.getRenderedEmojiFromProcessing()); } switch (behaviour) { case NAME: - return component.append(Component.text(":" + emoji.getName() + ":")); + return Component.text(":" + emoji.getName() + ":"); case BLANK: default: - return component; + return null; } } diff --git a/common/src/main/java/com/discordsrv/common/config/main/channels/DiscordToMinecraftChatConfig.java b/common/src/main/java/com/discordsrv/common/config/main/channels/DiscordToMinecraftChatConfig.java index c8865041..27511036 100644 --- a/common/src/main/java/com/discordsrv/common/config/main/channels/DiscordToMinecraftChatConfig.java +++ b/common/src/main/java/com/discordsrv/common/config/main/channels/DiscordToMinecraftChatConfig.java @@ -20,6 +20,7 @@ package com.discordsrv.common.config.main.channels; import com.discordsrv.common.config.configurate.annotation.Untranslated; import com.discordsrv.common.config.main.generic.DiscordIgnoresConfig; +import com.discordsrv.common.config.main.generic.MentionsConfig; import org.spongepowered.configurate.objectmapping.ConfigSerializable; import org.spongepowered.configurate.objectmapping.meta.Comment; @@ -55,37 +56,7 @@ public class DiscordToMinecraftChatConfig { public DiscordIgnoresConfig ignores = new DiscordIgnoresConfig(); @Comment("The representations of Discord mentions in-game") - public Mentions mentions = new Mentions(); - - @ConfigSerializable - public static class Mentions { - - public Format role = new Format("%role_color%@%role_name%", "[color:#5865F2]@deleted-role"); - public Format channel = new Format("[hover:show_text:Click to go to channel][click:open_url:%channel_jump_url%][color:#5865F2]#%channel_name%", "[color:#5865F2]#Unknown"); - public Format user = new Format("[hover:show_text:Username: @%user_tag%\nRoles: %user_roles:', '|text:'[color:gray][italics:on]None[color][italics]'%][color:#5865F2]@%user_effective_server_name|user_effective_name%", "[color:#5865F2]@Unknown user"); - - public String messageUrl = "[hover:show_text:Click to go to message][click:open_url:%jump_url%][color:#5865F2]#%channel_name% > ..."; - - @ConfigSerializable - public static class Format { - - @Comment("The format shown in-game") - @Untranslated(Untranslated.Type.VALUE) - public String format = ""; - - @Comment("The format when the entity is deleted or can't be looked up") - @Untranslated(Untranslated.Type.VALUE) - public String unknownFormat = ""; - - @SuppressWarnings("unused") // Configurate - public Format() {} - - public Format(String format, String unknownFormat) { - this.format = format; - this.unknownFormat = unknownFormat; - } - } - } + public MentionsConfig mentions = new MentionsConfig(); @Comment("How should unicode emoji be shown in-game:\n" + "- hide: hides emojis in-game\n" @@ -100,18 +71,6 @@ public class DiscordToMinecraftChatConfig { // TODO: add and implement name } - @Comment("How should custom emoji be shown in-game:\n" - + "- hide: custom emoji will not be shown in-game\n" - + "- blank: custom emoji will only be shown in-game if it is rendered by a 3rd party plugin\n" - + "- name: shows the name of the custom emoji in-game (for example :discordsrv:), unless rendered by a 3rd party plugin") - public EmoteBehaviour customEmojiBehaviour = EmoteBehaviour.BLANK; - - public enum EmoteBehaviour { - HIDE, - BLANK, - NAME - } - @Comment("The amount of milliseconds to delay processing Discord messages, if the message is deleted in that time it will not be processed.\n" + "This can be used together with Discord moderation bots, to filter forwarded messages") public long delayMillis = 0L; diff --git a/common/src/main/java/com/discordsrv/common/config/main/generic/MentionsConfig.java b/common/src/main/java/com/discordsrv/common/config/main/generic/MentionsConfig.java new file mode 100644 index 00000000..5cb76610 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/main/generic/MentionsConfig.java @@ -0,0 +1,56 @@ +package com.discordsrv.common.config.main.generic; + +import com.discordsrv.common.config.configurate.annotation.Untranslated; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; +import org.spongepowered.configurate.objectmapping.meta.Comment; + +@ConfigSerializable +public class MentionsConfig { + + public Format role = new Format( + "%role_color%@%role_name%", + "[color:#5865F2]@deleted-role" + ); + public Format channel = new Format( + "[hover:show_text:Click to go to channel][click:open_url:%channel_jump_url%][color:#5865F2]#%channel_name%", + "[color:#5865F2]#Unknown" + ); + public Format user = new Format( + "[hover:show_text:Username: @%user_tag%\nRoles: %user_roles:', '|text:'[color:gray][italics:on]None[color][italics]'%][color:#5865F2]@%user_effective_server_name|user_effective_name%", + "[color:#5865F2]@Unknown user" + ); + + public String messageUrl = "[hover:show_text:Click to go to message][click:open_url:%jump_url%][color:#5865F2]#%channel_name% > ..."; + + @Comment("How should custom emoji be shown in-game:\n" + + "- hide: custom emoji will not be shown in-game\n" + + "- blank: custom emoji will only be shown in-game if it is rendered by a 3rd party plugin\n" + + "- name: shows the name of the custom emoji in-game (for example :discordsrv:), unless rendered by a 3rd party plugin") + public EmoteBehaviour customEmojiBehaviour = EmoteBehaviour.BLANK; + + public enum EmoteBehaviour { + HIDE, + BLANK, + NAME + } + + @ConfigSerializable + public static class Format { + + @Comment("The format shown in-game") + @Untranslated(Untranslated.Type.VALUE) + public String format = ""; + + @Comment("The format when the entity is deleted or can't be looked up") + @Untranslated(Untranslated.Type.VALUE) + public String unknownFormat = ""; + + @SuppressWarnings("unused") // Configurate + public Format() {} + + public Format(String format, String unknownFormat) { + this.format = format; + this.unknownFormat = unknownFormat; + } + } +}