From 0fc5b01b290a789629f36e02a01b31aa510be558 Mon Sep 17 00:00:00 2001 From: Allink Date: Wed, 25 May 2022 17:15:04 +0100 Subject: [PATCH 01/11] 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); From 1726050d65c8fe7520d8cef22768c62961c507bc Mon Sep 17 00:00:00 2001 From: Allink Date: Wed, 25 May 2022 17:18:49 +0100 Subject: [PATCH 02/11] Clean up DiscordToMinecraftListener --- .../discord/DiscordToMinecraftListener.java | 131 ++++++++++-------- 1 file changed, 73 insertions(+), 58 deletions(-) diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java index b164ec82..680d3eb4 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java @@ -26,76 +26,91 @@ public class DiscordToMinecraftListener extends ListenerAdapter public void onMessageReceived(MessageReceivedEvent event) { String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString(); - if (event.getMember() != null && !chat_channel_id.isEmpty() && event.getChannel().getId().equals(chat_channel_id)) + if (event.getMember() == null) { - if (!event.getAuthor().getId().equals(Discord.bot.getSelfUser().getId())) - { - Member member = event.getMember(); - String tag = getDisplay(member); - Message msg = event.getMessage(); + return; + } - ComponentBuilder emsg = new ComponentBuilder(); + if (chat_channel_id.isEmpty()) + { + return; + } - // Prefix - emsg.append(ChatColor.DARK_GRAY + "["); - TextComponent inviteLink = new TextComponent("Discord"); - inviteLink.setColor(ChatColor.DARK_AQUA.asBungee()); - inviteLink.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - new Text("Click here to get the invite link!"))); - inviteLink.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, - ConfigEntry.DISCORD_INVITE_LINK.getString())); - emsg.append(inviteLink); - emsg.append(ChatColor.DARK_GRAY + "] ", ComponentBuilder.FormatRetention.NONE); + if (event.getAuthor().getId().equals(Discord.bot.getSelfUser().getId())) + { + return; + } - // Tag (if they have one) - if (tag != null) - { - emsg.append(tag); - } + if (!event.getChannel().getId().equals(chat_channel_id)) + { + return; + } + Member member = event.getMember(); + String tag = getDisplay(member); + Message msg = event.getMessage(); + + ComponentBuilder emsg = new ComponentBuilder(); + + // Prefix + emsg.append(ChatColor.DARK_GRAY + "["); + TextComponent inviteLink = new TextComponent("Discord"); + inviteLink.setColor(ChatColor.DARK_AQUA.asBungee()); + inviteLink.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, + new Text("Click here to get the invite link!"))); + inviteLink.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, + ConfigEntry.DISCORD_INVITE_LINK.getString())); + emsg.append(inviteLink); + emsg.append(ChatColor.DARK_GRAY + "] ", ComponentBuilder.FormatRetention.NONE); + + // Tag (if they have one) + if (tag != null) + { + emsg.append(tag); + } + + emsg.append(" "); + + // User + TextComponent user = new TextComponent(FUtil.stripColors(member.getEffectiveName())); + user.setColor(ChatColor.RED.asBungee()); + emsg.append(user); + + // Message + emsg.append(ChatColor.DARK_GRAY + ": " + ChatColor.RESET + + FUtil.stripColors(msg.getContentDisplay()), ComponentBuilder.FormatRetention.NONE); + + // Attachments + if (!msg.getAttachments().isEmpty()) + { + if (!msg.getContentDisplay().isEmpty()) emsg.append(" "); - // User - TextComponent user = new TextComponent(FUtil.stripColors(member.getEffectiveName())); - user.setColor(ChatColor.RED.asBungee()); - emsg.append(user); + for (Message.Attachment attachment : msg.getAttachments()) + { + TextComponent media = new TextComponent("[Media] "); + media.setColor(ChatColor.YELLOW.asBungee()); + media.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, attachment.getUrl())); + media.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(attachment.getUrl()))); - // Message - emsg.append(ChatColor.DARK_GRAY + ": " + ChatColor.RESET - + FUtil.stripColors(msg.getContentDisplay()), ComponentBuilder.FormatRetention.NONE); - - // Attachments - if (!msg.getAttachments().isEmpty()) - { - if (!msg.getContentDisplay().isEmpty()) - emsg.append(" "); - - for (Message.Attachment attachment : msg.getAttachments()) - { - TextComponent media = new TextComponent("[Media] "); - media.setColor(ChatColor.YELLOW.asBungee()); - media.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, attachment.getUrl())); - media.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(attachment.getUrl()))); - - emsg.append(media, ComponentBuilder.FormatRetention.NONE); - } - } - - BaseComponent[] components = emsg.create(); - - for (Player player : Bukkit.getOnlinePlayers()) - { - if (TotalFreedomMod.getPlugin().pl.getData(player).doesDisplayDiscord()) - { - player.sendMessage(components); - } - } - - FLog.info(TextComponent.toLegacyText(components), true); + emsg.append(media, ComponentBuilder.FormatRetention.NONE); } } + + BaseComponent[] components = emsg.create(); + + for (Player player : Bukkit.getOnlinePlayers()) + { + if (TotalFreedomMod.getPlugin().pl.getData(player).doesDisplayDiscord()) + { + player.sendMessage(components); + } + } + + FLog.info(TextComponent.toLegacyText(components), true); } + public String getDisplay(Member member) { Guild server = Discord.bot.getGuildById(ConfigEntry.DISCORD_SERVER_ID.getString()); From 72bab1e2ede3353725d001efc8c74005aff323e1 Mon Sep 17 00:00:00 2001 From: Allink Date: Wed, 25 May 2022 18:41:35 +0100 Subject: [PATCH 03/11] Add mean averaging to FUtil --- .../totalfreedommod/util/FUtil.java | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java b/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java index c7b533ab..45364d10 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java @@ -5,12 +5,7 @@ import me.totalfreedom.totalfreedommod.config.ConfigEntry; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.WordUtils; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Color; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.OfflinePlayer; +import org.bukkit.*; import org.bukkit.command.CommandSender; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; @@ -19,10 +14,8 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; -import org.json.simple.JSONArray; import java.io.*; -import java.lang.reflect.Field; import java.net.HttpURLConnection; import java.net.URL; import java.text.ParseException; @@ -800,6 +793,42 @@ public class FUtil return getServer().getOnlinePlayers().size() - i; } + public static double getMeanAverageDouble(double[] doubles) + { + double total = 0; + + for (double aDouble : doubles) + { + total += aDouble; + } + + return total / doubles.length; + } + + public static int getMeanAverageInt(int[] ints) + { + int total = 0; + + for (int anInt : ints) + { + total += anInt; + } + + return total / ints.length; + } + + public static long getMeanAverageLong(long[] longs) + { + long total = 0; + + for (long aLong : longs) + { + total += aLong; + } + + return total / longs.length; + } + public static class PaginationList extends ArrayList { From 6c426644f65a59d505822c64d2cd23dc276c88fa Mon Sep 17 00:00:00 2001 From: Allink Date: Wed, 25 May 2022 18:49:53 +0100 Subject: [PATCH 04/11] Add uptime & memory related functions to FUtil --- .../totalfreedommod/util/FUtil.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java b/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java index 45364d10..2775decd 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/util/FUtil.java @@ -1,5 +1,6 @@ package me.totalfreedom.totalfreedommod.util; +import com.earth2me.essentials.utils.DateUtil; import me.totalfreedom.totalfreedommod.TotalFreedomMod; import me.totalfreedom.totalfreedommod.config.ConfigEntry; import org.apache.commons.io.FileUtils; @@ -16,6 +17,7 @@ import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import java.io.*; +import java.lang.management.ManagementFactory; import java.net.HttpURLConnection; import java.net.URL; import java.text.ParseException; @@ -829,6 +831,26 @@ public class FUtil return total / longs.length; } + public static String getUptime() + { + return DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime()); + } + + public static double getMaxMem() + { + return Runtime.getRuntime().maxMemory() / 1024f / 1024f; + } + + public static double getTotalMem() + { + return Runtime.getRuntime().totalMemory() / 1024f / 1024f; + } + + public static double getFreeMem() + { + return Runtime.getRuntime().freeMemory() / 1024f / 1024f; + } + public static class PaginationList extends ArrayList { From 47c30c32839a4229992c200172e7843d88407392 Mon Sep 17 00:00:00 2001 From: Allink Date: Wed, 25 May 2022 19:41:58 +0100 Subject: [PATCH 05/11] Add plural to Displayables --- .../totalfreedommod/rank/Displayable.java | 2 ++ .../totalfreedommod/rank/Rank.java | 22 ++++++++++++------- .../totalfreedommod/rank/Title.java | 20 ++++++++++++----- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/main/java/me/totalfreedom/totalfreedommod/rank/Displayable.java b/src/main/java/me/totalfreedom/totalfreedommod/rank/Displayable.java index 55cc2fc1..2b2f2e49 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/rank/Displayable.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/rank/Displayable.java @@ -13,6 +13,8 @@ public interface Displayable String getAbbr(); + String getPlural(); + ChatColor getColor(); org.bukkit.ChatColor getTeamColor(); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/rank/Rank.java b/src/main/java/me/totalfreedom/totalfreedommod/rank/Rank.java index 98eaf217..0c04dbbe 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/rank/Rank.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/rank/Rank.java @@ -4,19 +4,19 @@ import net.md_5.bungee.api.ChatColor; public enum Rank implements Displayable { - NON_OP("a", "Non-Op", Type.PLAYER, "", ChatColor.WHITE, null, false, false), - OP("an", "Operator", Type.PLAYER, "OP", ChatColor.GREEN, null, false, false), - ADMIN("an", "Admin", Type.ADMIN, "Admin", ChatColor.DARK_GREEN, org.bukkit.ChatColor.DARK_GREEN, true, true), - SENIOR_ADMIN("a", "Senior Admin", Type.ADMIN, "SrA", ChatColor.GOLD, org.bukkit.ChatColor.GOLD, true, true), - ADMIN_CONSOLE("the", "Console", Type.ADMIN_CONSOLE, "Console", ChatColor.DARK_PURPLE, null, false, false), - SENIOR_CONSOLE("the", "Console", Type.ADMIN_CONSOLE, "Console", ChatColor.DARK_PURPLE, null, false, false); + NON_OP("a", "Non-Op", Type.PLAYER, "", "Non-Ops", ChatColor.WHITE, null, false, false), + OP("an", "Operator", Type.PLAYER, "OP", "Operators", ChatColor.GREEN, null, false, false), + ADMIN("an", "Admin", Type.ADMIN, "Admin", "Administrators", ChatColor.DARK_GREEN, org.bukkit.ChatColor.DARK_GREEN, true, true), + SENIOR_ADMIN("a", "Senior Admin", Type.ADMIN, "SrA", "Senior Administrators", ChatColor.GOLD, org.bukkit.ChatColor.GOLD, true, true), + ADMIN_CONSOLE("the", "Console", Type.ADMIN_CONSOLE, "Console", "Administrator Consoles", ChatColor.DARK_PURPLE, null, false, false), + SENIOR_CONSOLE("the", "Console", Type.ADMIN_CONSOLE, "Console", "Senior Consoles", ChatColor.DARK_PURPLE, null, false, false); private final Type type; private final String name; private final String abbr; - + private final String plural; private final String article; private final String tag; @@ -31,11 +31,12 @@ public enum Rank implements Displayable private final boolean hasDefaultLoginMessage; - Rank(String article, String name, Type type, String abbr, ChatColor color, org.bukkit.ChatColor teamColor, Boolean hasTeam, Boolean hasDefaultLoginMessage) + Rank(String article, String name, Type type, String abbr, String plural, ChatColor color, org.bukkit.ChatColor teamColor, Boolean hasTeam, Boolean hasDefaultLoginMessage) { this.type = type; this.name = name; this.abbr = abbr; + this.plural = plural; this.article = article; this.tag = abbr.isEmpty() ? "" : "[" + abbr + "]"; this.coloredTag = abbr.isEmpty() ? "" : ChatColor.DARK_GRAY + "[" + color + abbr + ChatColor.DARK_GRAY + "]" + color; @@ -88,6 +89,11 @@ public enum Rank implements Displayable return abbr; } + public String getPlural() + { + return plural; + } + public boolean isConsole() { return getType() == Type.ADMIN_CONSOLE; diff --git a/src/main/java/me/totalfreedom/totalfreedommod/rank/Title.java b/src/main/java/me/totalfreedom/totalfreedommod/rank/Title.java index c21d9f79..8cdd0118 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/rank/Title.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/rank/Title.java @@ -5,11 +5,11 @@ import net.md_5.bungee.api.ChatColor; public enum Title implements Displayable { - MASTER_BUILDER("a", "Master Builder", ChatColor.DARK_AQUA, org.bukkit.ChatColor.DARK_AQUA, "MB", true, true), - EXECUTIVE("an", "Executive", ChatColor.RED, org.bukkit.ChatColor.RED, "Exec", true, true), - ASSTEXEC("an", "Assistant Executive", ChatColor.RED, org.bukkit.ChatColor.RED, "Asst Exec", true, true), - DEVELOPER("a", "Developer", ChatColor.DARK_PURPLE, org.bukkit.ChatColor.DARK_PURPLE, "Dev", true, true), - OWNER("the", "Owner", ChatColor.DARK_RED, org.bukkit.ChatColor.DARK_RED, "Owner", true, true); + MASTER_BUILDER("a", "Master Builder", "Master Builders", ChatColor.DARK_AQUA, org.bukkit.ChatColor.DARK_AQUA, "MB", true, true), + EXECUTIVE("an", "Executive", "Executives", ChatColor.RED, org.bukkit.ChatColor.RED, "Exec", true, true), + ASSTEXEC("an", "Assistant Executive", "Assistant Executives", ChatColor.RED, org.bukkit.ChatColor.RED, "Asst Exec", true, true), + DEVELOPER("a", "Developer", "Developers", ChatColor.DARK_PURPLE, org.bukkit.ChatColor.DARK_PURPLE, "Dev", true, true), + OWNER("the", "Owner", "Owners", ChatColor.DARK_RED, org.bukkit.ChatColor.DARK_RED, "Owner", true, true); private final String article; @@ -17,6 +17,7 @@ public enum Title implements Displayable private final String name; private final String abbr; + private final String plural; private final String tag; @@ -29,10 +30,11 @@ public enum Title implements Displayable private final boolean hasTeam; private final boolean hasDefaultLoginMessage; - Title(String article, String name, ChatColor color, org.bukkit.ChatColor teamColor, String tag, Boolean hasTeam, Boolean hasDefaultLoginMessage) + Title(String article, String name, String plural, ChatColor color, org.bukkit.ChatColor teamColor, String tag, Boolean hasTeam, Boolean hasDefaultLoginMessage) { this.article = article; this.name = name; + this.plural = plural; this.coloredTag = ChatColor.DARK_GRAY + "[" + color + tag + ChatColor.DARK_GRAY + "]" + color; this.abbr = tag; this.tag = "[" + tag + "]"; @@ -84,6 +86,12 @@ public enum Title implements Displayable return abbr; } + @Override + public String getPlural() + { + return plural; + } + @Override public String getTag() { From c9f5db014134108e7d9b388ccb14644dbb0936ce Mon Sep 17 00:00:00 2001 From: Allink Date: Wed, 25 May 2022 19:44:45 +0100 Subject: [PATCH 06/11] Add Discord commands like the old bot --- .../totalfreedommod/config/ConfigEntry.java | 1 + .../totalfreedommod/discord/Discord.java | 5 + .../discord/DiscordToMinecraftListener.java | 31 +++-- .../discord/command/DiscordCommand.java | 25 +++++ .../discord/command/DiscordCommandImpl.java | 15 +++ .../command/DiscordCommandManager.java | 84 ++++++++++++++ .../discord/commands/HelpCommand.java | 86 ++++++++++++++ .../discord/commands/ListCommand.java | 106 ++++++++++++++++++ .../discord/commands/TPSCommand.java | 60 ++++++++++ .../discord/commands/UptimeCommand.java | 79 +++++++++++++ src/main/resources/config.yml | 2 + 11 files changed, 486 insertions(+), 8 deletions(-) create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommand.java create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandImpl.java create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandManager.java create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/discord/commands/HelpCommand.java create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/discord/commands/ListCommand.java create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/discord/commands/TPSCommand.java create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/discord/commands/UptimeCommand.java diff --git a/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java b/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java index abede2c7..1446e49b 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java @@ -74,6 +74,7 @@ public enum ConfigEntry SERVER_FULL_MOTD(String.class, "server.motds.full"), // DISCORD_TOKEN(String.class, "discord.token"), + DISCORD_PREFIX(String.class, "discord.prefix"), DISCORD_REPORT_CHANNEL_ID(String.class, "discord.report_channel_id"), DISCORD_CHAT_CHANNEL_ID(String.class, "discord.chat_channel_id"), DISCORD_ADMINCHAT_CHANNEL_ID(String.class, "discord.adminchat_channel_id"), diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java index 6e2a202e..479042be 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java @@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableList; import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.config.ConfigEntry; +import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandManager; import me.totalfreedom.totalfreedommod.player.PlayerData; import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.util.FLog; @@ -59,6 +60,7 @@ public class Discord extends FreedomService public static HashMap LINK_CODES = new HashMap<>(); public static JDA bot = null; + public static DiscordCommandManager DISCORD_COMMAND_MANAGER; public ScheduledThreadPoolExecutor RATELIMIT_EXECUTOR; public List> sentMessages = new ArrayList<>(); public Boolean enabled = false; @@ -153,6 +155,9 @@ public class Discord extends FreedomService public void startBot() { + DISCORD_COMMAND_MANAGER = new DiscordCommandManager(); + DISCORD_COMMAND_MANAGER.init(this); + enabled = !Strings.isNullOrEmpty(ConfigEntry.DISCORD_TOKEN.getString()); if (!enabled) { diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java index 680d3eb4..64c719bf 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/DiscordToMinecraftListener.java @@ -2,13 +2,12 @@ package me.totalfreedom.totalfreedommod.discord; import me.totalfreedom.totalfreedommod.TotalFreedomMod; import me.totalfreedom.totalfreedommod.config.ConfigEntry; +import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandManager; 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; +import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.md_5.bungee.api.chat.BaseComponent; @@ -25,7 +24,9 @@ public class DiscordToMinecraftListener extends ListenerAdapter { public void onMessageReceived(MessageReceivedEvent event) { - String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString(); + final String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString(); + final MessageChannel genericChannel = event.getChannel(); + if (event.getMember() == null) { return; @@ -41,14 +42,28 @@ public class DiscordToMinecraftListener extends ListenerAdapter return; } - if (!event.getChannel().getId().equals(chat_channel_id)) + if (!genericChannel.getId().equals(chat_channel_id)) { return; } - Member member = event.getMember(); - String tag = getDisplay(member); - Message msg = event.getMessage(); + if (!(genericChannel instanceof TextChannel)) + { + return; + } + + final TextChannel textChannel = (TextChannel) genericChannel; + + final Member member = event.getMember(); + final String tag = getDisplay(member); + final Message msg = event.getMessage(); + final String content = msg.getContentStripped(); + + if (content.startsWith(ConfigEntry.DISCORD_PREFIX.getString())) + { + Discord.DISCORD_COMMAND_MANAGER.parse(content, member, textChannel); + return; + } ComponentBuilder emsg = new ComponentBuilder(); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommand.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommand.java new file mode 100644 index 00000000..94c16ad4 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommand.java @@ -0,0 +1,25 @@ +package me.totalfreedom.totalfreedommod.discord.command; + +import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.User; + +import java.util.List; + +public interface DiscordCommand +{ + String getCommandName(); + + String getDescription(); + + String getCategory(); + + List getAliases(); + + boolean isAdmin(); + + boolean canExecute(Member member); + + MessageBuilder execute(Member member, List args); +} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandImpl.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandImpl.java new file mode 100644 index 00000000..cc273a34 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandImpl.java @@ -0,0 +1,15 @@ +package me.totalfreedom.totalfreedommod.discord.command; + +import net.dv8tion.jda.api.entities.Member; + +import java.util.stream.Collectors; + +public abstract class DiscordCommandImpl implements DiscordCommand +{ + @Override + public boolean canExecute(Member member) + { + //return !isAdmin() || member.getRoles().stream().filter((role -> role.getName().toLowerCase().contains("admin") && !role.getName().toLowerCase().contains("discord"))).toList().size() > 0; + return !isAdmin(); + } +} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandManager.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandManager.java new file mode 100644 index 00000000..93f1c60b --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandManager.java @@ -0,0 +1,84 @@ +package me.totalfreedom.totalfreedommod.discord.command; + +import me.totalfreedom.totalfreedommod.config.ConfigEntry; +import me.totalfreedom.totalfreedommod.discord.Discord; +import me.totalfreedom.totalfreedommod.util.FLog; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.TextChannel; +import org.reflections.Reflections; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +public class DiscordCommandManager +{ + public static final String PREFIX = ConfigEntry.DISCORD_PREFIX.getString(); + private Discord discord; + public final List commands = new ArrayList<>(); + + public void init(Discord discord) + { + this.discord = discord; + + final Reflections discordCommandsDir = new Reflections("me.totalfreedom.totalfreedommod.discord.commands"); + + final Set> commandClasses = discordCommandsDir.getSubTypesOf(DiscordCommand.class); + + for (Class commandClass : commandClasses) + { + try + { + commands.add(commandClass.getDeclaredConstructor().newInstance()); + } + catch (Exception e) + { + FLog.warning("Failed to load Discord command: " + commandClass.getName()); + } + } + + FLog.info("Loaded " + commands.size() + " Discord commands."); + } + + public void parse(String content, Member member, TextChannel channel) + { + List args = new ArrayList<>(Arrays.asList(content.split(" "))); + + final String alias = args.remove(0).split(PREFIX)[1]; // The joys of command parsing + + for (DiscordCommand command : commands) + { + if (command.getCommandName().equalsIgnoreCase(alias) || command.getAliases().contains(alias.toLowerCase())) + { + if (command.canExecute(member)) + { + final MessageBuilder messageBuilder = command.execute(member, args); + final Message message = messageBuilder.build(); + final CompletableFuture futureMessage = channel.sendMessage(message).submit(true); + + this.discord.sentMessages.add(futureMessage); + } + else + { + final MessageBuilder messageBuilder = new MessageBuilder(); + final EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setTitle("Command error"); + embedBuilder.setColor(Color.RED); + embedBuilder.setDescription("You don't have permission to execute this command."); + messageBuilder.setEmbed(embedBuilder.build()); + final Message message = messageBuilder.build(); + + final CompletableFuture futureMessage = channel.sendMessage(message).submit(true); + + this.discord.sentMessages.add(futureMessage); + } + } + } + } +} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/HelpCommand.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/HelpCommand.java new file mode 100644 index 00000000..d9825083 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/HelpCommand.java @@ -0,0 +1,86 @@ +package me.totalfreedom.totalfreedommod.discord.commands; + +import me.totalfreedom.totalfreedommod.discord.Discord; +import me.totalfreedom.totalfreedommod.discord.command.DiscordCommand; +import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl; +import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandManager; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Member; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class HelpCommand extends DiscordCommandImpl +{ + @Override + public String getCommandName() + { + return "help"; + } + + @Override + public String getDescription() + { + return "Displays the help command"; + } + + @Override + public String getCategory() + { + return "Help"; + } + + @Override + public List getAliases() + { + return List.of("cmds", "commands", "elp"); + } + + @Override + public boolean isAdmin() + { + return false; + } + + @Override + public MessageBuilder execute(Member member, List args) + { + final EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(Color.GREEN); + embedBuilder.setTitle("Help Command"); + + final Map> commandCategories = new HashMap<>(); + + for (DiscordCommand command : Discord.DISCORD_COMMAND_MANAGER.commands) + { + if (!commandCategories.containsKey(command.getCategory())) + { + commandCategories.put(command.getCategory(), new ArrayList<>(List.of(command))); + } + else + { + commandCategories.get(command.getCategory()).add(command); + } + } + + for (Map.Entry> entry : commandCategories.entrySet()) + { + final String category = entry.getKey(); + final List commands = entry.getValue(); + final StringBuilder fieldValue = new StringBuilder(); + + for (DiscordCommand command : commands) + { + fieldValue.append("**").append(DiscordCommandManager.PREFIX).append(command.getCommandName()).append("** - ").append(command.getDescription()).append("\n"); + } + + embedBuilder.addField(category, fieldValue.toString().trim(), false); + } + + return new MessageBuilder().setEmbed(embedBuilder.build()); + } +} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/ListCommand.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/ListCommand.java new file mode 100644 index 00000000..d81d24ff --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/ListCommand.java @@ -0,0 +1,106 @@ +package me.totalfreedom.totalfreedommod.discord.commands; + +import me.totalfreedom.totalfreedommod.TotalFreedomMod; +import me.totalfreedom.totalfreedommod.admin.AdminList; +import me.totalfreedom.totalfreedommod.config.ConfigEntry; +import me.totalfreedom.totalfreedommod.discord.command.DiscordCommand; +import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl; +import me.totalfreedom.totalfreedommod.rank.Displayable; +import me.totalfreedom.totalfreedommod.rank.RankManager; +import me.totalfreedom.totalfreedommod.util.FUtil; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.User; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ListCommand extends DiscordCommandImpl +{ + private static final TotalFreedomMod PLUGIN = TotalFreedomMod.plugin(); + + @Override + public String getCommandName() + { + return "list"; + } + + @Override + public String getDescription() + { + return "Gives a list of online players."; + } + + @Override + public String getCategory() + { + return "Server Commands"; + } + + @Override + public List getAliases() + { + return List.of("online", "who", "l", "lsit"); + } + + @Override + public boolean isAdmin() + { + return false; + } + + @Override + public MessageBuilder execute(Member member, List args) + { + if (PLUGIN == null) + { + throw new IllegalStateException("TotalFreedomMod somehow null while executing a command!"); + } + + final AdminList adminList = PLUGIN.al; + final RankManager rankManager = PLUGIN.rm; + + EmbedBuilder embedBuilder = new EmbedBuilder() + .setTitle("Player List - " + ConfigEntry.SERVER_NAME.getString()) + .setDescription("There are " + FUtil.getFakePlayerCount() + " / " + Bukkit.getMaxPlayers() + " online players"); + + Map> displayables = new HashMap<>(); + + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) + { + if (adminList.isVanished(onlinePlayer.getName())) + { + continue; + } + + + Displayable displayable = rankManager.getDisplay(onlinePlayer); + + if (displayables.containsKey(displayable)) + { + displayables.get(displayable).add(onlinePlayer.getName()); + } + else + { + displayables.put(displayable, new ArrayList<>(List.of(onlinePlayer.getName()))); + } + } + + for (Map.Entry> entry : displayables.entrySet()) + { + final Displayable displayable = entry.getKey(); + final List players = entry.getValue(); + + embedBuilder.addField(displayable.getPlural() + " (" + players.size() + ")", + String.join(", ", players), false); + } + + return new MessageBuilder().setEmbed(embedBuilder.build()); + } +} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/TPSCommand.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/TPSCommand.java new file mode 100644 index 00000000..0067af00 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/TPSCommand.java @@ -0,0 +1,60 @@ +package me.totalfreedom.totalfreedommod.discord.commands; + +import me.totalfreedom.totalfreedommod.discord.command.DiscordCommand; +import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl; +import me.totalfreedom.totalfreedommod.util.FUtil; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Member; +import org.bukkit.Bukkit; +import org.bukkit.Server; + +import java.util.Collections; +import java.util.List; + +public class TPSCommand extends DiscordCommandImpl +{ + @Override + public String getCommandName() + { + return "tps"; + } + + @Override + public String getDescription() + { + return "Lag information regarding the server."; + } + + @Override + public String getCategory() + { + return "Server Commands"; + } + + @Override + public List getAliases() + { + return Collections.singletonList("lag"); + } + + @Override + public boolean isAdmin() + { + return false; + } + + @Override + public MessageBuilder execute(Member member, List args) + { + final EmbedBuilder builder = new EmbedBuilder(); + builder.setTitle("Server lag information"); + builder.addField("TPS", String.valueOf(Math.round(FUtil.getMeanAverageDouble(Bukkit.getServer().getTPS()))), false); + builder.addField("Uptime", FUtil.getUptime(), false); + builder.addField("Maximum Memory", Math.ceil(FUtil.getMaxMem()) + " MB", false); + builder.addField("Allocated Memory", Math.ceil(FUtil.getTotalMem()) + " MB", false); + builder.addField("Free Memory", Math.ceil(FUtil.getFreeMem()) + " MB", false); + + return new MessageBuilder().setEmbed(builder.build()); + } +} diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/UptimeCommand.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/UptimeCommand.java new file mode 100644 index 00000000..47c2141f --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/UptimeCommand.java @@ -0,0 +1,79 @@ +package me.totalfreedom.totalfreedommod.discord.commands; + +import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl; +import me.totalfreedom.totalfreedommod.util.FLog; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Member; + +import java.awt.*; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Collections; +import java.util.List; + +public class UptimeCommand extends DiscordCommandImpl +{ + @Override + public String getCommandName() + { + return "uptime"; + } + + @Override + public String getDescription() + { + return "Returns the uptime of the VPS."; + } + + @Override + public String getCategory() + { + return "Server Commands"; + } + + @Override + public List getAliases() + { + return Collections.emptyList(); + } + + @Override + public boolean isAdmin() + { + return false; + } + + @Override + public MessageBuilder execute(Member member, List args) + { + final EmbedBuilder embedBuilder = new EmbedBuilder(); + + try + { + final Process uptimeProcess = Runtime.getRuntime().exec(new String[]{"uptime"}); + BufferedReader input = new BufferedReader(new InputStreamReader(uptimeProcess.getInputStream())); + String line = input.readLine(); + + if (line != null) + { + embedBuilder.setTitle("VPS Uptime Information"); + embedBuilder.setDescription(line.trim()); + } + else + { + throw new IllegalStateException("No output from uptime command."); + } + } + catch (Exception e) + { + FLog.warning("Error while executing uptime Discord command"); + e.printStackTrace(); + embedBuilder.setTitle("Command error"); + embedBuilder.setColor(Color.RED); + embedBuilder.setDescription("Something went wrong"); + } + + return new MessageBuilder().setEmbed(embedBuilder.build()); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index b690154b..9d1bd3bc 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -58,6 +58,8 @@ server: discord: # If you do not have a token, make a bot account and get one at https://discordapp.com/developers/applications/me token: '' + # The prefix for the integrated bot commands + prefix: 'tf!' # The official discord server's ID for this server server_id: '' # Channel to send /report messages to From ad9dd42edb5bfa4873317b638b37ecc4eacfa1ce Mon Sep 17 00:00:00 2001 From: Allink Date: Wed, 25 May 2022 19:55:25 +0100 Subject: [PATCH 07/11] Remove unused import --- .../totalfreedommod/discord/command/DiscordCommandImpl.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandImpl.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandImpl.java index cc273a34..8626be04 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandImpl.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/command/DiscordCommandImpl.java @@ -2,8 +2,6 @@ package me.totalfreedom.totalfreedommod.discord.command; import net.dv8tion.jda.api.entities.Member; -import java.util.stream.Collectors; - public abstract class DiscordCommandImpl implements DiscordCommand { @Override From 09a220e0a232663d949c4a03c115a534abb80b69 Mon Sep 17 00:00:00 2001 From: Allink Date: Wed, 25 May 2022 20:18:01 +0100 Subject: [PATCH 08/11] VPS -> Host --- .../totalfreedommod/discord/commands/UptimeCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/UptimeCommand.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/UptimeCommand.java index 47c2141f..eedd4718 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/UptimeCommand.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/commands/UptimeCommand.java @@ -23,7 +23,7 @@ public class UptimeCommand extends DiscordCommandImpl @Override public String getDescription() { - return "Returns the uptime of the VPS."; + return "Returns the uptime of the host."; } @Override @@ -57,7 +57,7 @@ public class UptimeCommand extends DiscordCommandImpl if (line != null) { - embedBuilder.setTitle("VPS Uptime Information"); + embedBuilder.setTitle("Host Uptime Information"); embedBuilder.setDescription(line.trim()); } else From 9c9116631927d5a97a130d6d3fc2f5ce0462461b Mon Sep 17 00:00:00 2001 From: Allink Date: Thu, 26 May 2022 16:10:00 +0100 Subject: [PATCH 09/11] Allow players to report offline players & allow admins to mark reports as completed, deleting them and sending them to an archive channel --- .../totalfreedommod/ChatManager.java | 6 +- .../command/Command_report.java | 29 ++++---- .../command/FreedomCommand.java | 22 ++++-- .../totalfreedommod/config/ConfigEntry.java | 1 + .../totalfreedommod/discord/Discord.java | 67 ++++++++++++++++-- .../discord/MessageReactionListener.java | 68 +++++++++++++++++++ src/main/resources/config.yml | 2 + 7 files changed, 167 insertions(+), 28 deletions(-) create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java diff --git a/src/main/java/me/totalfreedom/totalfreedommod/ChatManager.java b/src/main/java/me/totalfreedom/totalfreedommod/ChatManager.java index eebefc44..2156af99 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/ChatManager.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/ChatManager.java @@ -175,15 +175,15 @@ public class ChatManager extends FreedomService }); } - public void reportAction(Player reporter, Player reported, String report) + public void reportAction(Player reporter, String reportedName, String report) { for (Player player : server.getOnlinePlayers()) { if (plugin.al.isAdmin(player)) { - playerMsg(player, ChatColor.RED + "[REPORTS] " + ChatColor.GOLD + reporter.getName() + " has reported " + reported.getName() + " for " + report); + playerMsg(player, ChatColor.RED + "[REPORTS] " + ChatColor.GOLD + reporter.getName() + " has reported " + reportedName + " for " + report); } } - FLog.info("[REPORTS] " + reporter.getName() + " has reported " + reported.getName() + " for " + report); + FLog.info("[REPORTS] " + reporter.getName() + " has reported " + reportedName + " for " + report); } } \ No newline at end of file diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_report.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_report.java index 086bac6c..554c1f6d 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_report.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_report.java @@ -4,6 +4,7 @@ import me.totalfreedom.totalfreedommod.rank.Rank; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -22,36 +23,40 @@ public class Command_report extends FreedomCommand } Player player = getPlayer(args[0], true); + OfflinePlayer offlinePlayer = getOfflinePlayer(args[0]); - if (player == null) + if (player == null && offlinePlayer == null) { msg(PLAYER_NOT_FOUND); return true; } - - if (sender instanceof Player) + else if (player != null) { - if (player.equals(playerSender)) + if (sender instanceof Player) { - msg(ChatColor.RED + "Please, don't try to report yourself."); + if (player.equals(playerSender)) + { + msg(ChatColor.RED + "Please, don't try to report yourself."); + return true; + } + } + + if (plugin.al.isAdmin(player)) + { + msg(ChatColor.RED + "You can not report admins."); return true; } - } - if (plugin.al.isAdmin(player)) - { - msg(ChatColor.RED + "You can not report admins."); - return true; } String report = StringUtils.join(ArrayUtils.subarray(args, 1, args.length), " "); - plugin.cm.reportAction(playerSender, player, report); + plugin.cm.reportAction(playerSender, (player == null) ? offlinePlayer.getName() : player.getName(), report); boolean logged = false; if (plugin.dc.enabled) { - logged = plugin.dc.sendReport(playerSender, player, report); + logged = (player == null) ? plugin.dc.sendReportOffline(playerSender, offlinePlayer, report) : plugin.dc.sendReport(playerSender, player, report); } msg(ChatColor.GREEN + "Thank you, your report has been successfully logged." diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/FreedomCommand.java b/src/main/java/me/totalfreedom/totalfreedommod/command/FreedomCommand.java index 017307a4..ed826d46 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/command/FreedomCommand.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/command/FreedomCommand.java @@ -1,14 +1,10 @@ package me.totalfreedom.totalfreedommod.command; import com.google.common.collect.Lists; + import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; +import java.util.*; + import me.totalfreedom.totalfreedommod.TotalFreedomMod; import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.player.PlayerData; @@ -18,12 +14,14 @@ import me.totalfreedom.totalfreedommod.util.FUtil; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; import org.bukkit.Server; import org.bukkit.command.*; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.util.StringUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class FreedomCommand implements CommandExecutor, TabCompleter { @@ -229,6 +227,16 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter return player; } + @Nullable + protected OfflinePlayer getOfflinePlayer(String name) + { + return Arrays.stream(Bukkit.getOfflinePlayers()) + .filter(player -> player.getName() != null) + .filter(player -> player.getName().equalsIgnoreCase(name)) + .findFirst() + .orElse(null); + } + protected Admin getAdmin(CommandSender sender) { return plugin.al.getAdmin(sender); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java b/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java index 1446e49b..598c3d1f 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/config/ConfigEntry.java @@ -76,6 +76,7 @@ public enum ConfigEntry DISCORD_TOKEN(String.class, "discord.token"), DISCORD_PREFIX(String.class, "discord.prefix"), DISCORD_REPORT_CHANNEL_ID(String.class, "discord.report_channel_id"), + DISCORD_REPORT_ARCHIVE_CHANNEL_ID(String.class, "discord.report_archive_channel_id"), DISCORD_CHAT_CHANNEL_ID(String.class, "discord.chat_channel_id"), DISCORD_ADMINCHAT_CHANNEL_ID(String.class, "discord.adminchat_channel_id"), diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java index 479042be..d2b6e909 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java @@ -47,6 +47,7 @@ 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.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -64,7 +65,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 static 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) @@ -180,6 +181,7 @@ public class Discord extends FreedomService .addEventListeners(new PrivateMessageListener(), new DiscordToMinecraftListener(), new DiscordToAdminChatListener(), + new MessageReactionListener(), new ListenerAdapter() { @Override @@ -303,7 +305,7 @@ public class Discord extends FreedomService } } - public String sanitizeChatMessage(String message) + public static String sanitizeChatMessage(String message) { String newMessage = message; @@ -397,12 +399,12 @@ public class Discord extends FreedomService FLog.info("Discord integration has successfully shutdown."); } - public String deformat(String input) + public static String deformat(String input) { return input.replaceAll("([_\\\\`*>|])", "\\\\$1"); } - public boolean sendReport(Player reporter, Player reported, String reason) + public boolean shouldISendReport() { if (ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString().isEmpty()) { @@ -430,7 +432,54 @@ public class Discord extends FreedomService return false; } - EmbedBuilder embedBuilder = new EmbedBuilder(); + return true; + } + + public boolean sendReportOffline(Player reporter, OfflinePlayer reported, String reason) + { + if (!shouldISendReport()) + { + return false; + } + + final Guild server = bot.getGuildById(ConfigEntry.DISCORD_SERVER_ID.getString()); + final TextChannel channel = server.getTextChannelById(ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString()); + + final EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setTitle("Report for " + reported.getName() + " (offline)"); + embedBuilder.setDescription(reason); + embedBuilder.setFooter("Reported by " + reporter.getName(), "https://minotar.net/helm/" + reporter.getName() + ".png"); + embedBuilder.setTimestamp(Instant.from(ZonedDateTime.now())); + com.earth2me.essentials.User user = plugin.esb.getEssentialsUser(reported.getName()); + String location = "World: " + Objects.requireNonNull(user.getLastLocation().getWorld()).getName() + ", X: " + user.getLastLocation().getBlockX() + ", Y: " + user.getLastLocation().getBlockY() + ", Z: " + user.getLastLocation().getBlockZ(); + embedBuilder.addField("Location", location, true); + embedBuilder.addField("God Mode", WordUtils.capitalizeFully(String.valueOf(user.isGodModeEnabled())), true); + if (user.getNickname() != null) + { + embedBuilder.addField("Nickname", user.getNickname(), true); + } + MessageEmbed embed = embedBuilder.build(); + Message message = channel.sendMessage(embed).complete(); + + if (!ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString().isEmpty()) + { + message.addReaction("\uD83D\uDCCB").complete(); + } + + return true; + } + + public boolean sendReport(Player reporter, Player reported, String reason) + { + if (!shouldISendReport()) + { + return false; + } + + final Guild server = bot.getGuildById(ConfigEntry.DISCORD_SERVER_ID.getString()); + final TextChannel channel = server.getTextChannelById(ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString()); + + final EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setTitle("Report for " + reported.getName()); embedBuilder.setDescription(reason); embedBuilder.setFooter("Reported by " + reporter.getName(), "https://minotar.net/helm/" + reporter.getName() + ".png"); @@ -445,7 +494,13 @@ public class Discord extends FreedomService embedBuilder.addField("Nickname", user.getNickname(), true); } MessageEmbed embed = embedBuilder.build(); - channel.sendMessage(embed).complete(); + Message message = channel.sendMessage(embed).complete(); + + if (!ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString().isEmpty()) + { + message.addReaction("\uD83D\uDCCB").complete(); + } + return true; } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java new file mode 100644 index 00000000..9eeb55a6 --- /dev/null +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java @@ -0,0 +1,68 @@ +package me.totalfreedom.totalfreedommod.discord; + +import me.totalfreedom.totalfreedommod.config.ConfigEntry; +import me.totalfreedom.totalfreedommod.util.FLog; +import net.dv8tion.jda.api.MessageBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +public class MessageReactionListener extends ListenerAdapter +{ + public void onMessageReactionAdd(MessageReactionAddEvent messageReactionAddEvent) + { + if (!messageReactionAddEvent.isFromGuild()) + { + return; + } + + if (messageReactionAddEvent.getMember() == null) + { + return; + } + + if (messageReactionAddEvent.getMember().getUser().getId().equals(Discord.bot.getSelfUser().getId())) + { + return; + } + + if (!messageReactionAddEvent.getChannel().getId().equals(ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString())) + { + return; + } + + if (!messageReactionAddEvent.getReactionEmote().getEmoji().equals("\uD83D\uDCCB")) + { + return; + } + + final TextChannel archiveChannel = Discord.bot.getTextChannelById(ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString()); + + if (archiveChannel == null) + { + FLog.warning("Report archive channel is defined in the config, yet doesn't actually exist!"); + return; + } + + final Message message = messageReactionAddEvent.retrieveMessage().complete(); + final Member completer = messageReactionAddEvent.getMember(); + + if (!message.getAuthor().getId().equals(Discord.bot.getSelfUser().getId())) + { + return; + } + + // We don't need other embeds... yet? + final MessageEmbed embed = message.getEmbeds().get(0); + final MessageBuilder archiveMessageBuilder = new MessageBuilder(); + archiveMessageBuilder.setContent("Report completed by " + Discord.deformat(completer.getUser().getAsTag())); + archiveMessageBuilder.setEmbed(embed); + final Message archiveMessage = archiveMessageBuilder.build(); + + archiveChannel.sendMessage(archiveMessage).complete(); + message.delete().complete(); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 9d1bd3bc..d0f9ff4d 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -64,6 +64,8 @@ discord: server_id: '' # Channel to send /report messages to report_channel_id: '' + # Channel to send archived reports to + report_archive_channel_id: '' # Channel for Discord to Minecraft and vice-versa chat_channel_id: '' # Channel for Discord to AdminChat and vice-versa From bf41d08580e3d0731c2ace3611b2e0a14b02dd42 Mon Sep 17 00:00:00 2001 From: Allink Date: Thu, 26 May 2022 22:13:57 +0100 Subject: [PATCH 10/11] Mention the user who completes the report so we can have their current Discord name (includes their current name & tag in-case they delete their account) --- .../totalfreedommod/discord/MessageReactionListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java index 9eeb55a6..094a581f 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java @@ -58,7 +58,7 @@ public class MessageReactionListener extends ListenerAdapter // We don't need other embeds... yet? final MessageEmbed embed = message.getEmbeds().get(0); final MessageBuilder archiveMessageBuilder = new MessageBuilder(); - archiveMessageBuilder.setContent("Report completed by " + Discord.deformat(completer.getUser().getAsTag())); + archiveMessageBuilder.setContent("Report completed by " + completer.getUser().getAsMention() + " (" + Discord.deformat(completer.getUser().getAsTag() + ")")); archiveMessageBuilder.setEmbed(embed); final Message archiveMessage = archiveMessageBuilder.build(); From b4b10a3020307d8f5ffbf30ff9553448cb2e2325 Mon Sep 17 00:00:00 2001 From: Allink Date: Sun, 5 Jun 2022 12:14:49 +0100 Subject: [PATCH 11/11] A single space --- .../totalfreedommod/discord/MessageReactionListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java index 094a581f..738a2e5e 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/MessageReactionListener.java @@ -58,7 +58,7 @@ public class MessageReactionListener extends ListenerAdapter // We don't need other embeds... yet? final MessageEmbed embed = message.getEmbeds().get(0); final MessageBuilder archiveMessageBuilder = new MessageBuilder(); - archiveMessageBuilder.setContent("Report completed by " + completer.getUser().getAsMention() + " (" + Discord.deformat(completer.getUser().getAsTag() + ")")); + archiveMessageBuilder.setContent("Report completed by " + completer.getUser().getAsMention() + " (" + Discord.deformat(completer.getUser().getAsTag() + ")")); archiveMessageBuilder.setEmbed(embed); final Message archiveMessage = archiveMessageBuilder.build();