From 0fc5b01b290a789629f36e02a01b31aa510be558 Mon Sep 17 00:00:00 2001 From: Allink Date: Wed, 25 May 2022 17:15:04 +0100 Subject: [PATCH] Clean up message sanitization and properly strip section signs from nicks/messages --- .../command/Command_vanish.java | 4 +- .../totalfreedommod/discord/Discord.java | 125 ++++++++++-------- .../discord/DiscordToMinecraftListener.java | 7 +- .../totalfreedommod/util/FUtil.java | 5 + 4 files changed, 80 insertions(+), 61 deletions(-) diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_vanish.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_vanish.java index 68ce1b41..9511b28d 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_vanish.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_vanish.java @@ -45,7 +45,7 @@ public class Command_vanish extends FreedomCommand msg("You have unvanished.", ChatColor.GOLD); FUtil.bcastMsg(plugin.rm.craftLoginMessage(playerSender, null)); FUtil.bcastMsg(playerSender.getName() + " joined the game.", ChatColor.YELLOW); - plugin.dc.messageChatChannel("**" + playerSender.getName() + " joined the server" + "**"); + plugin.dc.messageChatChannel("**" + playerSender.getName() + " joined the server" + "**", true); } PlayerData playerData = plugin.pl.getData(playerSender); @@ -91,7 +91,7 @@ public class Command_vanish extends FreedomCommand { msg("You have vanished.", ChatColor.GOLD); FUtil.bcastMsg(playerSender.getName() + " left the game.", ChatColor.YELLOW); - plugin.dc.messageChatChannel("**" + playerSender.getName() + " left the server" + "**"); + plugin.dc.messageChatChannel("**" + playerSender.getName() + " left the server" + "**", true); } FLog.info(playerSender.getName() + " is now vanished."); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java index 1eb5f226..6e2a202e 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java @@ -13,6 +13,8 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.security.auth.login.LoginException; + +import com.google.common.collect.ImmutableList; import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.config.ConfigEntry; @@ -37,8 +39,12 @@ import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.utils.ChunkingFilter; import net.dv8tion.jda.api.utils.MemberCachePolicy; import net.dv8tion.jda.internal.utils.concurrent.CountingThreadFactory; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.WordUtils; +import org.apache.commons.lang3.RandomStringUtils; import org.bukkit.GameRule; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -56,6 +62,7 @@ public class Discord extends FreedomService public ScheduledThreadPoolExecutor RATELIMIT_EXECUTOR; public List> sentMessages = new ArrayList<>(); public Boolean enabled = false; + private final ImmutableList DISCORD_SUBDOMAINS = ImmutableList.of("discordapp.com", "discord.com", "discord.gg"); private final Pattern DISCORD_MENTION_PATTERN = Pattern.compile("(<@!?([0-9]{16,20})>)"); public static String getCode(PlayerData playerData) @@ -215,7 +222,7 @@ public class Discord extends FreedomService } } sentMessages.clear(); - messageChatChannel("**Message queue cleared**"); + messageChatChannel("**Message queue cleared**", true); } public void sendPteroInfo(PlayerData playerData, String username, String password) @@ -246,13 +253,7 @@ public class Discord extends FreedomService public String generateCode(int size) { - StringBuilder code = new StringBuilder(); - SplittableRandom random = new SplittableRandom(); - for (int i = 0; i < size; i++) - { - code.append(random.nextInt(10)); - } - return code.toString(); + return RandomStringUtils.randomNumeric(size); } @EventHandler(priority = EventPriority.MONITOR) @@ -265,9 +266,11 @@ public class Discord extends FreedomService return; } - if (event.getDeathMessage() != null) + Component deathMessage = event.deathMessage(); + + if (deathMessage != null) { - messageChatChannel("**" + event.getDeathMessage() + "**"); + messageChatChannel("**" + PlainTextComponentSerializer.plainText().serialize(deathMessage) + "**", true); } } @@ -282,7 +285,7 @@ public class Discord extends FreedomService { if (!plugin.al.isVanished(event.getPlayer().getName())) { - messageChatChannel("**" + event.getPlayer().getName() + " joined the server" + "**"); + messageChatChannel("**" + event.getPlayer().getName() + " joined the server" + "**", true); } } @@ -291,69 +294,78 @@ public class Discord extends FreedomService { if (!plugin.al.isVanished(event.getPlayer().getName())) { - messageChatChannel("**" + event.getPlayer().getName() + " left the server" + "**"); + messageChatChannel("**" + event.getPlayer().getName() + " left the server" + "**", true); } } + public String sanitizeChatMessage(String message) + { + String newMessage = message; + + if (message.contains("@")) + { + // \u200B is Zero Width Space, invisible on Discord + newMessage = message.replaceAll("@", "@\u200B"); + } + + if (message.toLowerCase().contains("discord.gg")) // discord.gg/invite works as an invite + { + return ""; + } + + for (String subdomain : DISCORD_SUBDOMAINS) + { + if (message.toLowerCase().contains(subdomain + "/invite")) + { + return ""; + } + } + + if (message.contains("§")) + { + newMessage = message.replaceAll("§", ""); + } + + return deformat(newMessage); + } + public void messageChatChannel(String message) + { + messageChatChannel(message, false); + } + + public void messageChatChannel(String message, boolean system) { String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString(); - if (message.contains("@everyone") || message.contains("@here")) - { - message = StringUtils.remove(message, "@"); - } - if (message.toLowerCase().contains("discord.gg")) - { - return; - } - - if (message.contains("§")) - { - message = StringUtils.remove(message, "§"); - } + String sanitizedMessage = (system) ? message : sanitizeChatMessage(message); - - Matcher DISCORD_MENTION_MATCHER = DISCORD_MENTION_PATTERN.matcher(message); - - while (DISCORD_MENTION_MATCHER.find()) - { - String mention = DISCORD_MENTION_MATCHER.group(1); - message = message.replace(mention, mention.replace("@","")); - } + if (sanitizedMessage.isBlank()) return; if (enabled && !chat_channel_id.isEmpty()) { - CompletableFuture sentMessage = Objects.requireNonNull(bot.getTextChannelById(chat_channel_id)).sendMessage(deformat(message)).submit(true); + CompletableFuture sentMessage = Objects.requireNonNull(bot.getTextChannelById(chat_channel_id)).sendMessage(sanitizedMessage).submit(true); sentMessages.add(sentMessage); } } public void messageAdminChatChannel(String message) + { + messageAdminChatChannel(message, false); + } + + public void messageAdminChatChannel(String message, boolean system) { String chat_channel_id = ConfigEntry.DISCORD_ADMINCHAT_CHANNEL_ID.getString(); - if (message.contains("@everyone") || message.contains("@here")) - { - message = StringUtils.remove(message, "@"); - } - if (message.toLowerCase().contains("discord.gg")) - { - return; - } - - if (message.contains("§")) - { - message = StringUtils.remove(message, "§"); - } + String sanitizedMessage = sanitizeChatMessage(message); + if (sanitizedMessage.isBlank()) return; - Matcher DISCORD_MENTION_MATCHER = DISCORD_MENTION_PATTERN.matcher(message); - - while (DISCORD_MENTION_MATCHER.find()) + if (enabled && !chat_channel_id.isEmpty()) { - String mention = DISCORD_MENTION_MATCHER.group(1); - message = message.replace(mention, mention.replace("@","")); + CompletableFuture sentMessage = Objects.requireNonNull(bot.getTextChannelById(chat_channel_id)).sendMessage(sanitizedMessage).submit(true); + sentMessages.add(sentMessage); } if (enabled && !chat_channel_id.isEmpty()) @@ -366,7 +378,7 @@ public class Discord extends FreedomService public String formatBotTag() { SelfUser user = bot.getSelfUser(); - return user.getName() + "#" + user.getDiscriminator(); + return user.getAsTag(); } @Override @@ -374,7 +386,7 @@ public class Discord extends FreedomService { if (bot != null) { - messageChatChannel("**Server has stopped**"); + messageChatChannel("**Server has stopped**", true); } FLog.info("Discord integration has successfully shutdown."); @@ -382,7 +394,7 @@ public class Discord extends FreedomService public String deformat(String input) { - return input.replace("_", "\\_"); + return input.replaceAll("([_\\\\`*>|])", "\\\\$1"); } public boolean sendReport(Player reporter, Player reported, String reason) @@ -400,6 +412,7 @@ public class Discord extends FreedomService Guild server = bot.getGuildById(ConfigEntry.DISCORD_SERVER_ID.getString()); if (server == null) + { FLog.severe("The Discord server ID specified is invalid, or the bot is not on the server."); return false; @@ -436,7 +449,7 @@ public class Discord extends FreedomService { public void start() { - messageChatChannel("**Server has started**"); + messageChatChannel("**Server has started**", true); } } } \ No newline at end of file diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java index f4adf0d9..b164ec82 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java @@ -5,6 +5,7 @@ import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Title; import me.totalfreedom.totalfreedommod.util.FLog; +import me.totalfreedom.totalfreedommod.util.FUtil; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; @@ -55,13 +56,13 @@ public class DiscordToMinecraftListener extends ListenerAdapter emsg.append(" "); // User - TextComponent user = new TextComponent(ChatColor.stripColor(member.getEffectiveName())); + TextComponent user = new TextComponent(FUtil.stripColors(member.getEffectiveName())); user.setColor(ChatColor.RED.asBungee()); emsg.append(user); // Message emsg.append(ChatColor.DARK_GRAY + ": " + ChatColor.RESET - + ChatColor.stripColor(msg.getContentDisplay()), ComponentBuilder.FormatRetention.NONE); + + FUtil.stripColors(msg.getContentDisplay()), ComponentBuilder.FormatRetention.NONE); // Attachments if (!msg.getAttachments().isEmpty()) @@ -86,7 +87,7 @@ public class DiscordToMinecraftListener extends ListenerAdapter { if (TotalFreedomMod.getPlugin().pl.getData(player).doesDisplayDiscord()) { - player.spigot().sendMessage(components); + player.sendMessage(components); } } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java b/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java index 520ee630..c7b533ab 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java @@ -550,6 +550,11 @@ public class FUtil return string; } + public static String stripColors(String string) + { + return string.replaceAll("§", ""); + } + public static Date getUnixDate(long unix) { return new Date(unix);