From fdf5476288f98549e5a9cc37a22f001e1457e074 Mon Sep 17 00:00:00 2001 From: Stuffy Date: Mon, 29 Jul 2024 14:11:20 -0400 Subject: [PATCH 01/75] working on abstracting interactions --- .../stuffybot/responses/BaseResponse.java | 9 ++++ .../stuffybot/responses/PitResponses.java | 5 ++ .../stuffy/stuffybot/utils/Interactions.java | 51 +++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/main/java/me/stuffy/stuffybot/responses/BaseResponse.java create mode 100644 src/main/java/me/stuffy/stuffybot/responses/PitResponses.java create mode 100644 src/main/java/me/stuffy/stuffybot/utils/Interactions.java diff --git a/src/main/java/me/stuffy/stuffybot/responses/BaseResponse.java b/src/main/java/me/stuffy/stuffybot/responses/BaseResponse.java new file mode 100644 index 0000000..1e1a928 --- /dev/null +++ b/src/main/java/me/stuffy/stuffybot/responses/BaseResponse.java @@ -0,0 +1,9 @@ +package me.stuffy.stuffybot.responses; + +import net.dv8tion.jda.api.entities.MessageEmbed; + +public class BaseResponse { + protected MessageEmbed getResponse(String action, String args) { + return null; + } +} diff --git a/src/main/java/me/stuffy/stuffybot/responses/PitResponses.java b/src/main/java/me/stuffy/stuffybot/responses/PitResponses.java new file mode 100644 index 0000000..a524345 --- /dev/null +++ b/src/main/java/me/stuffy/stuffybot/responses/PitResponses.java @@ -0,0 +1,5 @@ +package me.stuffy.stuffybot.responses; + +public class PitResponses extends BaseResponse{ + +} diff --git a/src/main/java/me/stuffy/stuffybot/utils/Interactions.java b/src/main/java/me/stuffy/stuffybot/utils/Interactions.java new file mode 100644 index 0000000..3f9894e --- /dev/null +++ b/src/main/java/me/stuffy/stuffybot/utils/Interactions.java @@ -0,0 +1,51 @@ +package me.stuffy.stuffybot.utils; + +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; + +public class Interactions { + public static void resolveSlashInteraction(SlashCommandInteractionEvent interaction) { + // Get the hook, defer the reply + // Call getResponse with the action and args + // Edit the hook with the response + // Log the interaction + } + + public static void resolveButtonInteraction(ButtonInteractionEvent interaction) { + // Get the button id + // check if the user is the owner, if not return + // Call getResponse with the action and args + // Edit the hook with the response + + String interactionUser = interaction.getUser().getId(); + String interactionId = interaction.getComponentId(); + + String[] split = interactionId.split(":"); + String buttonType = split[0]; + String ownerId = split[1]; + String args = split[2]; + + if(!interactionUser.equals(ownerId)) { + System.out.println("User " + interactionUser + " tried to interact with " + ownerId + "'s button."); + return; + } + + MessageEmbed getResponse = getResponse(buttonType, args); + interaction.getHook().editOriginalEmbeds(getResponse).queue(); + } + + private static MessageEmbed getResponse(String action, String args) { + // Call the appropriate response class + // Return the response + + String actionClass = action.split("_")[0]; +// switch (actionClass) { +// case "pit": +// return PitResponses.getResponse(action, args); +// default: +// return null; +// } + return null; + } +} From dc0d6e189f0ccc5a0fc30ebce018e768446e76d9 Mon Sep 17 00:00:00 2001 From: Stuffy Date: Fri, 2 Aug 2024 01:47:56 -0400 Subject: [PATCH 02/75] slash commands to interactionids --- src/main/java/me/stuffy/stuffybot/Bot.java | 8 +- .../commands/AchievementCommand.java | 41 ------- .../stuffybot/commands/BaseCommand.java | 43 ++++++- .../stuffybot/commands/MaxedGamesCommand.java | 45 ------- .../stuffybot/commands/MegaWallsCommand.java | 92 --------------- .../stuffy/stuffybot/commands/PitCommand.java | 72 +++++------- .../stuffybot/commands/StatsCommand.java | 83 ------------- ...ournamentCommand.java => TestCommand.java} | 18 +-- .../stuffy/stuffybot/commands/TkrCommand.java | 73 ------------ .../stuffybot/commands/VerifyCommand.java | 111 ------------------ .../stuffy/stuffybot/utils/DiscordUtils.java | 16 +++ .../stuffy/stuffybot/utils/Interactions.java | 43 +------ 12 files changed, 96 insertions(+), 549 deletions(-) delete mode 100644 src/main/java/me/stuffy/stuffybot/commands/AchievementCommand.java delete mode 100644 src/main/java/me/stuffy/stuffybot/commands/MaxedGamesCommand.java delete mode 100644 src/main/java/me/stuffy/stuffybot/commands/MegaWallsCommand.java delete mode 100644 src/main/java/me/stuffy/stuffybot/commands/StatsCommand.java rename src/main/java/me/stuffy/stuffybot/commands/{TournamentCommand.java => TestCommand.java} (54%) delete mode 100644 src/main/java/me/stuffy/stuffybot/commands/TkrCommand.java delete mode 100644 src/main/java/me/stuffy/stuffybot/commands/VerifyCommand.java diff --git a/src/main/java/me/stuffy/stuffybot/Bot.java b/src/main/java/me/stuffy/stuffybot/Bot.java index fa6f087..56b8304 100644 --- a/src/main/java/me/stuffy/stuffybot/Bot.java +++ b/src/main/java/me/stuffy/stuffybot/Bot.java @@ -45,14 +45,8 @@ public Bot() throws InterruptedException { // Register commands jda.addEventListener( - new VerifyCommand("verify", "Links your discord account to your Minecraft account"), - new MaxedGamesCommand("maxes", "Find the games with all achievements unlocked"), - new TournamentCommand("tournament", "Shows tournament stats"), - new AchievementCommand("achievements", "Shows achievements progress for a user"), - new StatsCommand("stats", "Shows overall hypixel stats for a user"), new PitCommand("pit", "Shows pit stats for a user"), - new TkrCommand("tkr", "Shows completed maps in TKR"), - new MegaWallsCommand("megawalls", "Shows Mega Walls stats for a user") + new TestCommand("test", "Test command") ); diff --git a/src/main/java/me/stuffy/stuffybot/commands/AchievementCommand.java b/src/main/java/me/stuffy/stuffybot/commands/AchievementCommand.java deleted file mode 100644 index 3cc543a..0000000 --- a/src/main/java/me/stuffy/stuffybot/commands/AchievementCommand.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.stuffy.stuffybot.commands; - -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; - -import static me.stuffy.stuffybot.utils.DiscordUtils.getUsername; - -public class AchievementCommand extends BaseCommand{ - public AchievementCommand(String name, String description){ - super(name, description, - new OptionData(OptionType.STRING, "ign", "Minecraft Username", false), - new OptionData(OptionType.STRING, "game", "The game", false) - .addChoice("Skyblock", "skyblock"), - new OptionData(OptionType.STRING, "type", "Challenge/Tiered", false) - .addChoice("Challenge", "challenge") - .addChoice("Tiered", "tiered" - ) - ); - } - - - protected void onCommand(SlashCommandInteractionEvent event) { - String ign = getUsername(event); - if (event.getOption("game") == null) { - event.getHook().sendMessage("no game provided").queue(); - return; - } - String game = event.getOption("game").getAsString(); - event.getHook().sendMessage("game: " + game).queue(); - } - - public void onButton(ButtonInteractionEvent event) { - } - - @Override - protected void cleanupEventResources(String messageId) { - - } -} diff --git a/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java b/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java index 152bc10..237afc7 100644 --- a/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java +++ b/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java @@ -2,6 +2,7 @@ import me.stuffy.stuffybot.Bot; import me.stuffy.stuffybot.utils.Logger; +import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; @@ -10,15 +11,22 @@ import org.jetbrains.annotations.NotNull; import java.time.Instant; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import static me.stuffy.stuffybot.utils.DiscordUtils.getUsername; +import static me.stuffy.stuffybot.utils.DiscordUtils.makeErrorEmbed; +import static me.stuffy.stuffybot.utils.Interactions.getResponse; + public abstract class BaseCommand extends ListenerAdapter { private String name; private String description; + private OptionData[] options; private final Map latestValidInteraction = new HashMap<>(); private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); @@ -26,6 +34,7 @@ public abstract class BaseCommand extends ListenerAdapter { public BaseCommand(String name, String description, OptionData... options) { this.name = name; this.description = description; + this.options = options; Bot bot = Bot.getInstance(); bot.getHomeGuild().upsertCommand(name, description) .addOptions(options) @@ -37,12 +46,36 @@ public BaseCommand(String name, String description, OptionData... options) { public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { if (event.getName().equals(this.name)) { event.deferReply().queue(); - String options = ""; + String interactionId = this.name + ":" + event.getUser().getId() + ":"; + ArrayList optionsArray = new ArrayList(); + + for (OptionData option : this.options) { + String optionName = option.getName(); + if(optionName.equals("ign") && event.getOption("ign") == null){ + String ign = getUsername(event); + optionsArray.add("ign=" + ign); + } + } + for (OptionMapping option : event.getOptions()) { - options += option.getName() + ": " + option.getAsString() + ", "; + optionsArray.add(option.getName() + "=" + option.getAsString()); } + + String options = String.join(",", optionsArray); + interactionId += options; + Logger.log(" @" + event.getUser().getName() + ": /" + this.name + " " + options); - this.onCommand(event); + + MessageEmbed response = getResponse(interactionId); + + String errorMessage = "Are your arguments valid?"; + if (response != null) { + event.getHook().sendMessageEmbeds(response).queue(); + } else { + MessageEmbed errorEmbed = makeErrorEmbed("Slash Command Error", "An error occurred while processing your command.\n-# " + errorMessage); + event.getHook().sendMessageEmbeds(errorEmbed).queue(); + } + latestValidInteraction.put(event.getHook().getId(), Instant.now()); scheduler.scheduleAtFixedRate(this::endEvent, 0, 1, TimeUnit.SECONDS); } @@ -59,13 +92,13 @@ private void endEvent() { }); } - protected abstract void onCommand(SlashCommandInteractionEvent event); - @Override public void onButtonInteraction(@NotNull ButtonInteractionEvent event) { this.onButton(event); } + protected abstract void onCommand(SlashCommandInteractionEvent event); + protected abstract void onButton(ButtonInteractionEvent event); protected abstract void cleanupEventResources(String messageId); diff --git a/src/main/java/me/stuffy/stuffybot/commands/MaxedGamesCommand.java b/src/main/java/me/stuffy/stuffybot/commands/MaxedGamesCommand.java deleted file mode 100644 index 7c1f4eb..0000000 --- a/src/main/java/me/stuffy/stuffybot/commands/MaxedGamesCommand.java +++ /dev/null @@ -1,45 +0,0 @@ -package me.stuffy.stuffybot.commands; - -import me.stuffy.stuffybot.profiles.HypixelProfile; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; - -import static me.stuffy.stuffybot.utils.APIUtils.getHypixelProfile; -import static me.stuffy.stuffybot.utils.DiscordUtils.getUsername; -import static me.stuffy.stuffybot.utils.DiscordUtils.makeErrorEmbed; - -public class MaxedGamesCommand extends BaseCommand{ - - public MaxedGamesCommand(String name, String description) { - super(name, description, - new OptionData(OptionType.STRING, "ign", "Your Minecraft Username", false) - ); - } - @Override - protected void onCommand(SlashCommandInteractionEvent event) { - String ign = getUsername(event); - HypixelProfile hypixelProfile; - try { - hypixelProfile = getHypixelProfile(ign); - }catch (Exception e){ - event.getHook().sendMessage("").addEmbeds( - makeErrorEmbed( - "API Error", - "An error occurred while fetching your Hypixel profile. Please try again later." - ) - ).queue(); - return; - } - hypixelProfile.getMaxedGames(); - } - - public void onButton(ButtonInteractionEvent event) { - } - - @Override - protected void cleanupEventResources(String messageId) { - - } -} diff --git a/src/main/java/me/stuffy/stuffybot/commands/MegaWallsCommand.java b/src/main/java/me/stuffy/stuffybot/commands/MegaWallsCommand.java deleted file mode 100644 index 8cae1d7..0000000 --- a/src/main/java/me/stuffy/stuffybot/commands/MegaWallsCommand.java +++ /dev/null @@ -1,92 +0,0 @@ -package me.stuffy.stuffybot.commands; - -import me.stuffy.stuffybot.profiles.HypixelProfile; -import net.dv8tion.jda.api.events.Event; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; -import net.dv8tion.jda.api.interactions.components.selections.SelectOption; -import net.dv8tion.jda.api.interactions.components.selections.StringSelectMenu; - -import java.text.DecimalFormat; -import java.util.HashMap; -import java.util.Map; - -import static me.stuffy.stuffybot.utils.APIUtils.getHypixelProfile; -import static me.stuffy.stuffybot.utils.DiscordUtils.*; - -public class MegaWallsCommand extends BaseCommand{ - private final Map activeEvents = new HashMap<>(); - public MegaWallsCommand(String name, String description) { - super(name, description, - new OptionData(OptionType.STRING, "ign", "The username of the player you want to look up", false)); - } - - @Override - protected void onCommand(SlashCommandInteractionEvent event) { - activeEvents.put(event.getHook().getId(), event); - String ign = getUsername(event); - HypixelProfile hypixelProfile; - try { - hypixelProfile = getHypixelProfile(ign); - }catch (Exception e){ - event.getHook().sendMessage("").addEmbeds( - makeErrorEmbed( - "API Error", - "An error occurred while fetching your Hypixel profile. Please try again later." - ) - ).queue(); - return; - } - - String username = hypixelProfile.getDisplayName(); - Map legendary_skins = hypixelProfile.getMegaWallsLegendaries(); - int legendary_skins_unlocked = 0; - for (Boolean unlocked : legendary_skins.values()){ - if (unlocked){ - legendary_skins_unlocked++; - } - } - - Integer wins = hypixelProfile.getMegaWallsWins(); - Integer finalKills = hypixelProfile.getMegaWallsFinalKills(); - Integer classPoints = hypixelProfile.getMegaWallsClassPoints(); - String className = hypixelProfile.getMegaWallsSelectedClass(); - - DecimalFormat df = new DecimalFormat("#,###"); - event.getHook().sendMessage("").addEmbeds( - makeStatsEmbed( - "Mega Walls Stats for " + username, - "Wins: **" + df.format(wins) + "**\n" + - "Final Kills: **" + df.format(finalKills) + "**\n" + - "Total Class Points: **" + df.format(classPoints) + "**\n\n" + - "Selected Class: **" + className + "**\n" + - "Legendary Skins Unlocked: **" + legendary_skins_unlocked + "**/27" - - ) - ).addActionRow( - StringSelectMenu.create("megawalls-select") - .addOption("Legendaries", "legendaries") - .addOptions( - SelectOption.of("Overall", "overall").withDefault(true) - ).build() - ).queue(); - - } - - @Override - protected void onButton(ButtonInteractionEvent event) { - - } - - @Override - protected void cleanupEventResources(String messageId) { - Event event = activeEvents.remove(messageId); - if (event instanceof SlashCommandInteractionEvent slashEvent) { - slashEvent.getHook().retrieveOriginal().queue(message -> { - message.editMessageComponents().queue(); - }); - } - } -} diff --git a/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java b/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java index d71fd9b..c55cfcf 100644 --- a/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java +++ b/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java @@ -2,18 +2,13 @@ import kotlin.Triple; import me.stuffy.stuffybot.profiles.HypixelProfile; -import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.events.Event; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; -import net.dv8tion.jda.api.interactions.components.buttons.ButtonInteraction; import java.text.DecimalFormat; -import java.util.HashMap; -import java.util.Map; import static me.stuffy.stuffybot.utils.APIUtils.getHypixelProfile; import static me.stuffy.stuffybot.utils.DiscordUtils.*; @@ -21,9 +16,6 @@ import static net.dv8tion.jda.api.interactions.components.buttons.Button.*; public class PitCommand extends BaseCommand{ - private final Map originalEmbeds = new HashMap<>(); - private final Map originalDetailedEmbeds = new HashMap<>(); - private final Map activeEvents = new HashMap<>(); public PitCommand(String name, String description) { super(name, description, @@ -33,7 +25,6 @@ public PitCommand(String name, String description) { @Override protected void onCommand(SlashCommandInteractionEvent event) { - activeEvents.put(event.getHook().getId(), event); String ign = getUsername(event); HypixelProfile hypixelProfile; try { @@ -72,8 +63,6 @@ protected void onCommand(SlashCommandInteractionEvent event) { embedContent ); - originalEmbeds.put(event.getHook().getId(), pitStats); - String runnerId = event.getUser().getId(); event.getHook().sendMessage("") @@ -111,44 +100,43 @@ protected void onCommand(SlashCommandInteractionEvent event) { "Pit Achievement stats for " + username, embedContent2.toString() ); - originalDetailedEmbeds.put(event.getHook().getId(), extraPitStats); } public void onButton(ButtonInteractionEvent event) { - String[] parts = event.getComponentId().split(":"); - String action = parts[0]; - String userId = parts[1]; - - if (action.equals("pitDetailed")) { - MessageEmbed detailedButton = originalDetailedEmbeds.get(event.getHook().getId()); - if(detailedButton == null) { - return; - } - event.editMessageEmbeds(detailedButton) - .setActionRow(secondary("go_back:" + userId, "Go Back")) - .queue(); - } - if (action.equals("go_back")) { - MessageEmbed backButton = originalEmbeds.get(event.getHook().getId()); - if(backButton == null) { - return; - } - event.editMessageEmbeds(backButton) - .setActionRow(secondary("pitDetailed:" + userId, "Challenge Achievement Progress")) - .queue(); - } +// String[] parts = event.getComponentId().split(":"); +// String action = parts[0]; +// String userId = parts[1]; +// +// if (action.equals("pitDetailed")) { +// MessageEmbed detailedButton = null; +// if(detailedButton == null) { +// return; +// } +// event.editMessageEmbeds(detailedButton) +// .setActionRow(secondary("go_back:" + userId, "Go Back")) +// .queue(); +// } +// if (action.equals("go_back")) { +// MessageEmbed backButton = originalEmbeds.get(event.getHook().getId()); +// if(backButton == null) { +// return; +// } +// event.editMessageEmbeds(backButton) +// .setActionRow(secondary("pitDetailed:" + userId, "Challenge Achievement Progress")) +// .queue(); +// } } @Override protected void cleanupEventResources(String messageId) { - originalEmbeds.remove(messageId); - originalDetailedEmbeds.remove(messageId); - Event event = activeEvents.remove(messageId); - if (event instanceof SlashCommandInteractionEvent slashEvent) { - slashEvent.getHook().retrieveOriginal().queue(message -> { - message.editMessageComponents().queue(); - }); - } +// originalEmbeds.remove(messageId); +// originalDetailedEmbeds.remove(messageId); +// Event event = activeEvents.remove(messageId); +// if (event instanceof SlashCommandInteractionEvent slashEvent) { +// slashEvent.getHook().retrieveOriginal().queue(message -> { +// message.editMessageComponents().queue(); +// }); +// } } } diff --git a/src/main/java/me/stuffy/stuffybot/commands/StatsCommand.java b/src/main/java/me/stuffy/stuffybot/commands/StatsCommand.java deleted file mode 100644 index df99c51..0000000 --- a/src/main/java/me/stuffy/stuffybot/commands/StatsCommand.java +++ /dev/null @@ -1,83 +0,0 @@ -package me.stuffy.stuffybot.commands; - -import me.stuffy.stuffybot.profiles.HypixelProfile; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; - -import java.text.DecimalFormat; - -import static me.stuffy.stuffybot.utils.APIUtils.getHypixelProfile; -import static me.stuffy.stuffybot.utils.DiscordUtils.*; - -public class StatsCommand extends BaseCommand{ - public StatsCommand(String name, String description){ - super(name, description, - new OptionData(OptionType.STRING, "ign", "The username of the player you want to look up", false)); - } - - @Override - protected void onCommand(SlashCommandInteractionEvent event) { - String ign = getUsername(event); - HypixelProfile hypixelProfile; - try{ - hypixelProfile = getHypixelProfile(ign); - } catch (Exception e){ - event.getHook().sendMessage("").addEmbeds( - makeErrorEmbed( - "API Error", - "An error occurred while fetching your Hypixel profile. Please try again later." - ) - ).queue(); - return; - } - - String username = hypixelProfile.getDisplayName(); - - DecimalFormat df = new DecimalFormat("#,###"); - DecimalFormat df2 = new DecimalFormat("#,###.##"); - - Integer questsCompleted = hypixelProfile.getQuestsCompleted(); - Integer wins = hypixelProfile.getWins(); - Integer kills = hypixelProfile.getKills(); - Integer rewardStreak = hypixelProfile.getRewardStreak(); - Integer rewardRecord = hypixelProfile.getRewardRecord(); - Integer karma = hypixelProfile.getKarma(); - Integer achievementPoints = hypixelProfile.getAchievementPoints(); - Integer legacyAchievementPoints = hypixelProfile.getLegacyAchievementPoints(); - Integer challenges = hypixelProfile.getChallengesCompleted(); - - Double networkLevel = hypixelProfile.getNetworkLevel(); - - String firstLogin = hypixelProfile.getFirstLogin(); - String onlineStatus = hypixelProfile.getOnlineStatus(); - - String embedContent = - onlineStatus + "\n" + - "Network Level: **" + df2.format(networkLevel) + "**\n" + - "Karma: **" + df.format(karma) + "**\n\n" + - "Achievement Points: **" + df.format(achievementPoints) + "** (+" + df.format(legacyAchievementPoints) + " legacy)" + "\n" + - "Quests Completed: **" + df.format(questsCompleted) + "**\n" + - "Challenges Completed: **" + df.format(challenges) + "**\n\n" + - "Reward Streak|Record: **" + df.format(rewardStreak) + "** | " + df.format(rewardRecord) + "\n" + - "Wins: **" + df.format(wins) + "**\n" + - "Kills: **" + df.format(kills) + "**\n" + - "First Login: " + firstLogin + "\n"; - - event.getHook().sendMessage("").addEmbeds( - makeStatsEmbed( - "Hypixel Stats for " + username, - embedContent - ) - ).queue(); - } - - public void onButton(ButtonInteractionEvent event) { - } - - @Override - protected void cleanupEventResources(String messageId) { - - } -} diff --git a/src/main/java/me/stuffy/stuffybot/commands/TournamentCommand.java b/src/main/java/me/stuffy/stuffybot/commands/TestCommand.java similarity index 54% rename from src/main/java/me/stuffy/stuffybot/commands/TournamentCommand.java rename to src/main/java/me/stuffy/stuffybot/commands/TestCommand.java index 8cf191e..81628e8 100644 --- a/src/main/java/me/stuffy/stuffybot/commands/TournamentCommand.java +++ b/src/main/java/me/stuffy/stuffybot/commands/TestCommand.java @@ -5,22 +5,24 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; -public class TournamentCommand extends BaseCommand{ - public TournamentCommand(String name, String description){ - super(name, description, - new OptionData(OptionType.STRING, "tournament", "The tournament, defaults to most recent", false).addChoices( +public class TestCommand extends BaseCommand{ - ), - new OptionData(OptionType.STRING, "username", "Player's username", false)); + public TestCommand(String name, String description, OptionData... options) { + super(name, description, + new OptionData(OptionType.STRING, "ign", "Your Minecraft Username", false), + new OptionData(OptionType.STRING, "ign2", "Your Minecraft Username", false), + new OptionData(OptionType.STRING, "ign3", "Your Minecraft Username", false), + new OptionData(OptionType.STRING, "ign4", "Your Minecraft Username", false)); } @Override protected void onCommand(SlashCommandInteractionEvent event) { - String tournament = event.getOption("tournament").getAsString(); - String username = event.getOption("username").getAsString(); + } + @Override protected void onButton(ButtonInteractionEvent event) { + } @Override diff --git a/src/main/java/me/stuffy/stuffybot/commands/TkrCommand.java b/src/main/java/me/stuffy/stuffybot/commands/TkrCommand.java deleted file mode 100644 index c6157fd..0000000 --- a/src/main/java/me/stuffy/stuffybot/commands/TkrCommand.java +++ /dev/null @@ -1,73 +0,0 @@ -package me.stuffy.stuffybot.commands; - -import me.stuffy.stuffybot.profiles.HypixelProfile; -import net.dv8tion.jda.api.EmbedBuilder; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; - -import java.util.Map; - -import static me.stuffy.stuffybot.utils.APIUtils.getHypixelProfile; -import static me.stuffy.stuffybot.utils.DiscordUtils.*; - -public class TkrCommand extends BaseCommand{ - public TkrCommand(String name, String description) { - super(name, description, - new OptionData(OptionType.STRING, "ign", "The username of the player you want to look up", false)); - } - - @Override - protected void onCommand(SlashCommandInteractionEvent event) { - String ign = getUsername(event); - HypixelProfile hypixelProfile; - try{ - hypixelProfile = getHypixelProfile(ign); - } catch (Exception e){ - event.getHook().sendMessage("").addEmbeds( - makeErrorEmbed( - "API Error", - "An error occurred while fetching your Hypixel profile. Please try again later." - ) - ).queue(); - return; - } - - String username = hypixelProfile.getDisplayName(); - - Map uniqueGolds = hypixelProfile.getTkrMaps(); - String embedContent = ""; - int uniqueGoldCount = 0; - - for (Map.Entry entry : uniqueGolds.entrySet()) { - String key = entry.getKey(); - Boolean value = entry.getValue(); - if (value) { - uniqueGoldCount++; - } - embedContent += (value ? "✅ " : "❌ ") + key + "\n"; - } - - - embedContent = "Unique Gold Medals: **" + uniqueGoldCount + "**/5\n\n" + embedContent; - - - event.getHook().sendMessage("").addEmbeds( - makeStatsEmbed( - "TKR Unique Gold Medals for " + username, - embedContent - ) - ).queue(); - } - - @Override - protected void onButton(ButtonInteractionEvent event) { - - } - - @Override - protected void cleanupEventResources(String messageId) { - - } -} diff --git a/src/main/java/me/stuffy/stuffybot/commands/VerifyCommand.java b/src/main/java/me/stuffy/stuffybot/commands/VerifyCommand.java deleted file mode 100644 index 0b8d191..0000000 --- a/src/main/java/me/stuffy/stuffybot/commands/VerifyCommand.java +++ /dev/null @@ -1,111 +0,0 @@ -package me.stuffy.stuffybot.commands; - -import me.stuffy.stuffybot.profiles.HypixelProfile; -import me.stuffy.stuffybot.profiles.MojangProfile; -import me.stuffy.stuffybot.utils.Logger; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; -import net.dv8tion.jda.api.interactions.commands.OptionType; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; - -import java.util.UUID; - -import static me.stuffy.stuffybot.utils.APIUtils.getHypixelProfile; -import static me.stuffy.stuffybot.utils.APIUtils.getMojangProfile; -import static me.stuffy.stuffybot.utils.DiscordUtils.*; - -public class VerifyCommand extends BaseCommand { - - public VerifyCommand(String name, String description) { - super(name, description, - new OptionData(OptionType.STRING, "ign", "Your Minecraft Username", true) - ); - } - - /** - * Verifies a user's Minecraft account is linked to the Discord account that sent the command via Hypixel. - * @param event - */ - @Override - protected void onCommand(SlashCommandInteractionEvent event) { - String ign = event.getOption("ign").getAsString(); - MojangProfile profile; - try { - profile = getMojangProfile(ign); - } catch (Exception e) { - event.getHook().sendMessage("").addEmbeds( - makeErrorEmbed( - "Mojang API Error", - "Error interacting with Mojang API. Make sure you spelled the username correctly." - ) - ).queue(); - - return; - } - UUID uuid = profile.getUuid(); - - HypixelProfile hypixelProfile; - try { - hypixelProfile = getHypixelProfile(uuid); - } catch (Exception e) { - System.out.println(e.getMessage()); - event.getHook().sendMessage("").addEmbeds( - makeErrorEmbed( - "Hypixel API Error", - "Error interacting with Hypixel API. Try again later." - ) - ).queue(); - - return; - } - String linkedDiscord = hypixelProfile.getDiscord(); - String runnerUsername = getDiscordUsername(event.getUser().getName()); - if (linkedDiscord == null) { - event.getHook().sendMessage("").addEmbeds( - makeErrorEmbed( - "Username Error", - "There is no discord account linked to the Minecraft account `" + profile.getUsername() + "`." - ) - ).queue(); - return; - } - - if (!linkedDiscord.equals(runnerUsername)) { - event.getHook().sendMessage("").addEmbeds( - makeErrorEmbed( - "Username Error", - "The ign you provided is linked to a different discord account than the one you're using.\n\nYour discord account: `" + runnerUsername + "`\n`" + profile.getUsername() + "`'s Linked discord account: `" + linkedDiscord + "`." - ) - ).queue(); - - return; - } - - // TODO: Check if there is a linked Discord and the same as the one that sent the command (check the database, update the entry, unverify the old one - try{ - verifyUser(event.getUser(), ign); - } catch (Exception e){ - System.out.println(e.getMessage()); - event.getHook().sendMessage("").addEmbeds( - makeErrorEmbed( - "Verification Error", - "An error occurred while verifying your account. Please try again later." - ) - ).queue(); - return; - } - String username = hypixelProfile.getDisplayName(); - Logger.log(" Linked " + username + " (" + uuid + ") for @" + runnerUsername + "."); - - event.getHook().sendMessage("Successfully verified your discord account! (jk this doesn't work yet.) ").queue(); - - } - - public void onButton(ButtonInteractionEvent event) { - } - - @Override - protected void cleanupEventResources(String messageId) { - - } -} diff --git a/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java b/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java index 1dd617f..78c7d8a 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java +++ b/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java @@ -29,6 +29,22 @@ public static MessageEmbed makeUpdateEmbed(String embedTitle, String embedConten return makeEmbed(":mega: " + embedTitle, embedContent, 0xffef14); } + public static MessageEmbed makeStaffRankChangeEmbed(String ign, String oldRank, String newRank, String position) { + String embedContent = "### **" + ign + "**: `" + oldRank + "` ⇒ `" + newRank + "`\nPlayer stats: [Plancke](https://plancke.io/hypixel/player/stats/" + ign + ")\n"; + + if (position != null){ + embedContent += "Suspected Position: " + position + "\n"; + } + int color = 0xaaaaaa; + if(newRank.equals("GM")){ + color = 0x00aa00; + } + if (newRank.equals("ADMIN")){ + color = 0xff5555; + } + return makeEmbed(":mega: Rank Change Detected", embedContent, color); + } + public static MessageEmbed makeStatsEmbed(String embedTitle, String embedContent) { return makeEmbed(embedTitle, embedContent, 0xf7cb72); diff --git a/src/main/java/me/stuffy/stuffybot/utils/Interactions.java b/src/main/java/me/stuffy/stuffybot/utils/Interactions.java index 3f9894e..0c7a532 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/Interactions.java +++ b/src/main/java/me/stuffy/stuffybot/utils/Interactions.java @@ -1,51 +1,10 @@ package me.stuffy.stuffybot.utils; import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; public class Interactions { - public static void resolveSlashInteraction(SlashCommandInteractionEvent interaction) { - // Get the hook, defer the reply - // Call getResponse with the action and args - // Edit the hook with the response - // Log the interaction - } - - public static void resolveButtonInteraction(ButtonInteractionEvent interaction) { - // Get the button id - // check if the user is the owner, if not return - // Call getResponse with the action and args - // Edit the hook with the response - - String interactionUser = interaction.getUser().getId(); - String interactionId = interaction.getComponentId(); - - String[] split = interactionId.split(":"); - String buttonType = split[0]; - String ownerId = split[1]; - String args = split[2]; - - if(!interactionUser.equals(ownerId)) { - System.out.println("User " + interactionUser + " tried to interact with " + ownerId + "'s button."); - return; - } - - MessageEmbed getResponse = getResponse(buttonType, args); - interaction.getHook().editOriginalEmbeds(getResponse).queue(); - } - - private static MessageEmbed getResponse(String action, String args) { - // Call the appropriate response class - // Return the response - String actionClass = action.split("_")[0]; -// switch (actionClass) { -// case "pit": -// return PitResponses.getResponse(action, args); -// default: -// return null; -// } + public static MessageEmbed getResponse(String interactionId) { return null; } } From 85b08083c80e6abdbebfd4646a3e6cf76c5c106c Mon Sep 17 00:00:00 2001 From: Stuffy Date: Fri, 2 Aug 2024 13:18:02 -0400 Subject: [PATCH 03/75] parse interaction options, error handling,created InteractionException for fail reasons --- .../stuffybot/commands/BaseCommand.java | 27 +++++++++----- .../stuffy/stuffybot/utils/DiscordUtils.java | 17 +++++++-- .../stuffybot/utils/InteractionException.java | 13 +++++++ .../stuffy/stuffybot/utils/Interactions.java | 35 +++++++++++++++++-- 4 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 src/main/java/me/stuffy/stuffybot/utils/InteractionException.java diff --git a/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java b/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java index 237afc7..0191ec5 100644 --- a/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java +++ b/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java @@ -1,6 +1,7 @@ package me.stuffy.stuffybot.commands; import me.stuffy.stuffybot.Bot; +import me.stuffy.stuffybot.utils.InteractionException; import me.stuffy.stuffybot.utils.Logger; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; @@ -18,6 +19,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; import static me.stuffy.stuffybot.utils.DiscordUtils.getUsername; import static me.stuffy.stuffybot.utils.DiscordUtils.makeErrorEmbed; @@ -56,9 +58,15 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { optionsArray.add("ign=" + ign); } } - + Pattern pattern = Pattern.compile("[,=:]"); for (OptionMapping option : event.getOptions()) { - optionsArray.add(option.getName() + "=" + option.getAsString()); + String optionString = option.getAsString(); + if(pattern.matcher(optionString).find()){ + MessageEmbed errorEmbed = makeErrorEmbed("Slash Command Error", "An error occurred while processing your command.\n-# Invalid character in option `" + option.getName() + "`"); + event.getHook().sendMessageEmbeds(errorEmbed).queue(); + return; + } + optionsArray.add(option.getName() + "=" + optionString); } String options = String.join(",", optionsArray); @@ -66,16 +74,17 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { Logger.log(" @" + event.getUser().getName() + ": /" + this.name + " " + options); - MessageEmbed response = getResponse(interactionId); - - String errorMessage = "Are your arguments valid?"; - if (response != null) { - event.getHook().sendMessageEmbeds(response).queue(); - } else { - MessageEmbed errorEmbed = makeErrorEmbed("Slash Command Error", "An error occurred while processing your command.\n-# " + errorMessage); + MessageEmbed response = null; + try { + response = getResponse(interactionId); + } catch (InteractionException e) { + MessageEmbed errorEmbed = makeErrorEmbed("Slash Command Error", "An error occurred while processing your command.\n-# " + e.getMessage()); event.getHook().sendMessageEmbeds(errorEmbed).queue(); + return; } + event.getHook().sendMessageEmbeds(response).queue(); + latestValidInteraction.put(event.getHook().getId(), Instant.now()); scheduler.scheduleAtFixedRate(this::endEvent, 0, 1, TimeUnit.SECONDS); } diff --git a/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java b/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java index 78c7d8a..1e79dde 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java +++ b/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java @@ -6,9 +6,7 @@ import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import java.util.Arrays; -import java.util.Date; -import java.util.List; +import java.util.*; public class DiscordUtils { public static MessageEmbed makeEmbed(String embedTitle, String embedContent, int embedColor) { @@ -110,4 +108,17 @@ public static String getUsername(SlashCommandInteractionEvent event) { } return username; } + + public static Map parseOptions(String options) { + String[] parts = options.split(","); + Map optionsMap = new HashMap<>(); + for (String part : parts) { + String[] keyValue = part.split("="); + if (keyValue.length != 2) { + return null; + } + optionsMap.put(keyValue[0], keyValue[1]); + } + return optionsMap; + } } diff --git a/src/main/java/me/stuffy/stuffybot/utils/InteractionException.java b/src/main/java/me/stuffy/stuffybot/utils/InteractionException.java new file mode 100644 index 0000000..43aedb6 --- /dev/null +++ b/src/main/java/me/stuffy/stuffybot/utils/InteractionException.java @@ -0,0 +1,13 @@ +package me.stuffy.stuffybot.utils; + +public class InteractionException extends Throwable { + String message; + public InteractionException(String message) { + this.message = message; + } + + public String getMessage() { + return this.message; + } + +} diff --git a/src/main/java/me/stuffy/stuffybot/utils/Interactions.java b/src/main/java/me/stuffy/stuffybot/utils/Interactions.java index 0c7a532..a62ccc4 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/Interactions.java +++ b/src/main/java/me/stuffy/stuffybot/utils/Interactions.java @@ -2,9 +2,40 @@ import net.dv8tion.jda.api.entities.MessageEmbed; +import java.util.Map; +import java.util.regex.Pattern; + +import static me.stuffy.stuffybot.utils.DiscordUtils.makeErrorEmbed; + public class Interactions { - public static MessageEmbed getResponse(String interactionId) { - return null; + public static MessageEmbed getResponse(String interactionId) throws InteractionException { + String[] parts = interactionId.split(":"); + String command = parts[0]; + String userId = parts[1]; + String options = parts[2]; + + // TODO: Error handling for invalid command + // TODO: Error handling for invalid userId + + + Map optionsMap = DiscordUtils.parseOptions(options); + if(optionsMap == null){ + throw new InteractionException("No options provided, what am I supposed to do with this?"); + } + + if(optionsMap.containsKey("ign")){ + String ign = optionsMap.get("ign"); + if (ign.length() > 16){ + throw new InteractionException("Invalid field `ign`, Usernames cannot be longer than 16 characters"); + } + Pattern pattern = Pattern.compile("[^a-zA-Z0-9_]"); + if (pattern.matcher(ign).find()){ + throw new InteractionException("Invalid field `ign`, Usernames can only contain letters, numbers and underscores"); + } + } + + MessageEmbed embed = makeErrorEmbed("Invalid interactionId", "Invalid interactionId"); + return embed; } } From a12c13a78925def33c98d21229232c8cab6b8bae Mon Sep 17 00:00:00 2001 From: Stuffy Date: Fri, 2 Aug 2024 13:33:49 -0400 Subject: [PATCH 04/75] command stats tracking --- .../stuffy/stuffybot/commands/BaseCommand.java | 5 +++-- .../stuffybot/utils/StatisticsManager.java | 16 +++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java b/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java index 0191ec5..5aa3ca9 100644 --- a/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java +++ b/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java @@ -3,6 +3,7 @@ import me.stuffy.stuffybot.Bot; import me.stuffy.stuffybot.utils.InteractionException; import me.stuffy.stuffybot.utils.Logger; +import me.stuffy.stuffybot.utils.StatisticsManager; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; @@ -85,11 +86,11 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { event.getHook().sendMessageEmbeds(response).queue(); + StatisticsManager.incrementCommandUsage(this.name); + latestValidInteraction.put(event.getHook().getId(), Instant.now()); scheduler.scheduleAtFixedRate(this::endEvent, 0, 1, TimeUnit.SECONDS); } - - // StatisticsManager.incrementTotalCommandsRun(); } private void endEvent() { diff --git a/src/main/java/me/stuffy/stuffybot/utils/StatisticsManager.java b/src/main/java/me/stuffy/stuffybot/utils/StatisticsManager.java index d5852d8..bb5f615 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/StatisticsManager.java +++ b/src/main/java/me/stuffy/stuffybot/utils/StatisticsManager.java @@ -10,21 +10,19 @@ public static void incrementCommandsRun() { totalCommandsRun++; } - public static int getTotalCommandsRun() { - return totalCommandsRun; - } - public static void incrementCommandUsage(String commandName) { - if (commandUsage.containsKey(commandName)) { - commandUsage.put(commandName, commandUsage.get(commandName) + 1); - } else { - commandUsage.put(commandName, 1); - } + int previousUsage = commandUsage.getOrDefault(commandName, 0); + commandUsage.put(commandName, previousUsage + 1); + incrementCommandsRun(); } public static int getCommandUsage(String commandName) { return commandUsage.get(commandName); } + public static int getTotalCommandsRun() { + return totalCommandsRun; + } + } From ec9dde46a6880780d64c4e2cae4809c7721bf63c Mon Sep 17 00:00:00 2001 From: Stuffy Date: Sun, 4 Aug 2024 01:03:08 -0400 Subject: [PATCH 05/75] removed onCommand and onButton from BaseCommand, handle it differently, add april foolishness --- .../me/stuffy/stuffybot/commands/BaseCommand.java | 13 +++++-------- .../me/stuffy/stuffybot/commands/PitCommand.java | 13 ------------- .../me/stuffy/stuffybot/commands/TestCommand.java | 15 --------------- .../me/stuffy/stuffybot/utils/DiscordUtils.java | 6 ++++++ .../java/me/stuffy/stuffybot/utils/MiscUtils.java | 12 +++++++++++- .../stuffy/stuffybot/utils/StatisticsManager.java | 3 ++- 6 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java b/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java index 5aa3ca9..7d4e7c1 100644 --- a/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java +++ b/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java @@ -15,7 +15,6 @@ import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -97,19 +96,17 @@ private void endEvent() { latestValidInteraction.forEach((messageId, time) -> { if (Instant.now().getEpochSecond() - time.getEpochSecond() > 30) { latestValidInteraction.remove(messageId); - cleanupEventResources(messageId); } }); } @Override public void onButtonInteraction(@NotNull ButtonInteractionEvent event) { - this.onButton(event); + if (latestValidInteraction.containsKey(event.getMessageId())) { + latestValidInteraction.remove(event.getMessageId()); + event.deferEdit().queue(); + } } +} - protected abstract void onCommand(SlashCommandInteractionEvent event); - - protected abstract void onButton(ButtonInteractionEvent event); - protected abstract void cleanupEventResources(String messageId); -} diff --git a/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java b/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java index c55cfcf..a805fac 100644 --- a/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java +++ b/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java @@ -23,7 +23,6 @@ public PitCommand(String name, String description) { ); } - @Override protected void onCommand(SlashCommandInteractionEvent event) { String ign = getUsername(event); HypixelProfile hypixelProfile; @@ -125,18 +124,6 @@ public void onButton(ButtonInteractionEvent event) { // event.editMessageEmbeds(backButton) // .setActionRow(secondary("pitDetailed:" + userId, "Challenge Achievement Progress")) // .queue(); -// } - } - - @Override - protected void cleanupEventResources(String messageId) { -// originalEmbeds.remove(messageId); -// originalDetailedEmbeds.remove(messageId); -// Event event = activeEvents.remove(messageId); -// if (event instanceof SlashCommandInteractionEvent slashEvent) { -// slashEvent.getHook().retrieveOriginal().queue(message -> { -// message.editMessageComponents().queue(); -// }); // } } } diff --git a/src/main/java/me/stuffy/stuffybot/commands/TestCommand.java b/src/main/java/me/stuffy/stuffybot/commands/TestCommand.java index 81628e8..e9605b5 100644 --- a/src/main/java/me/stuffy/stuffybot/commands/TestCommand.java +++ b/src/main/java/me/stuffy/stuffybot/commands/TestCommand.java @@ -14,19 +14,4 @@ public TestCommand(String name, String description, OptionData... options) { new OptionData(OptionType.STRING, "ign3", "Your Minecraft Username", false), new OptionData(OptionType.STRING, "ign4", "Your Minecraft Username", false)); } - - @Override - protected void onCommand(SlashCommandInteractionEvent event) { - - } - - @Override - protected void onButton(ButtonInteractionEvent event) { - - } - - @Override - protected void cleanupEventResources(String messageId) { - - } } diff --git a/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java b/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java index 1e79dde..4da475e 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java +++ b/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java @@ -8,6 +8,8 @@ import java.util.*; +import static me.stuffy.stuffybot.utils.MiscUtils.toSkillIssue; + public class DiscordUtils { public static MessageEmbed makeEmbed(String embedTitle, String embedContent, int embedColor) { EmbedBuilder embedBuilder = new EmbedBuilder(); @@ -20,6 +22,10 @@ public static MessageEmbed makeEmbed(String embedTitle, String embedContent, int } public static MessageEmbed makeErrorEmbed(String embedTitle, String embedContent) { + if (Calendar.getInstance().get(Calendar.MONTH) == Calendar.APRIL && Calendar.getInstance().get(Calendar.DAY_OF_MONTH) == 1){ + embedTitle = toSkillIssue(embedTitle); + embedContent = toSkillIssue(embedContent); + } return makeEmbed(":no_entry: " + embedTitle, embedContent, 0xff0000); } diff --git a/src/main/java/me/stuffy/stuffybot/utils/MiscUtils.java b/src/main/java/me/stuffy/stuffybot/utils/MiscUtils.java index 430df49..e76026f 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/MiscUtils.java +++ b/src/main/java/me/stuffy/stuffybot/utils/MiscUtils.java @@ -5,7 +5,6 @@ import java.util.LinkedHashMap; import java.util.Map; -import java.util.Objects; import java.util.UUID; public class MiscUtils { @@ -90,4 +89,15 @@ public static Integer pitXpToLevel(long experience) { return workingLevel; } + + public static String toSkillIssue(String toModify) { + // An Error, an error, AN ERROR + return toModify + .replace("n error", " skill issue") + .replace("n Error", " Skill Issue") + .replace("N ERROR", " SKILL ISSUE") + .replace("error", "skill issue") + .replace("Error", "Skill Issue") + .replace("ERROR", "SKILL ISSUE"); + } } diff --git a/src/main/java/me/stuffy/stuffybot/utils/StatisticsManager.java b/src/main/java/me/stuffy/stuffybot/utils/StatisticsManager.java index bb5f615..d194da7 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/StatisticsManager.java +++ b/src/main/java/me/stuffy/stuffybot/utils/StatisticsManager.java @@ -1,10 +1,11 @@ package me.stuffy.stuffybot.utils; +import java.util.HashMap; import java.util.Map; public class StatisticsManager { private static int totalCommandsRun = 0; - private static Map commandUsage; + private static final Map commandUsage = new HashMap<>(); public static void incrementCommandsRun() { totalCommandsRun++; From 425b1459ebd81eabb88f4076bb59c23706e58153 Mon Sep 17 00:00:00 2001 From: Stuffy Date: Sun, 4 Aug 2024 16:12:38 -0400 Subject: [PATCH 06/75] removed command registering --- src/main/java/me/stuffy/stuffybot/Bot.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/me/stuffy/stuffybot/Bot.java b/src/main/java/me/stuffy/stuffybot/Bot.java index 56b8304..f594cb7 100644 --- a/src/main/java/me/stuffy/stuffybot/Bot.java +++ b/src/main/java/me/stuffy/stuffybot/Bot.java @@ -43,10 +43,9 @@ public Bot() throws InterruptedException { Logger logger = new Logger(); logger.log(" Bot " + self + " started successfully " + time + "."); - // Register commands + // Listen for interactions jda.addEventListener( - new PitCommand("pit", "Shows pit stats for a user"), - new TestCommand("test", "Test command") + new InteractionHandler() ); From 65734d2a0e7d54f3a12159bd350cea6d1eb2a5f9 Mon Sep 17 00:00:00 2001 From: Stuffy Date: Sun, 4 Aug 2024 16:14:15 -0400 Subject: [PATCH 07/75] BaseCommand.java is now InteractionHandler.java, now handles commands and buttons, does not register commands --- .../stuffy/stuffybot/commands/PitCommand.java | 12 ++++++------ .../stuffy/stuffybot/commands/TestCommand.java | 18 ++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java b/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java index a805fac..477c299 100644 --- a/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java +++ b/src/main/java/me/stuffy/stuffybot/commands/PitCommand.java @@ -15,13 +15,13 @@ import static me.stuffy.stuffybot.utils.MiscUtils.convertToRomanNumeral; import static net.dv8tion.jda.api.interactions.components.buttons.Button.*; -public class PitCommand extends BaseCommand{ +public class PitCommand extends InteractionHandler { - public PitCommand(String name, String description) { - super(name, description, - new OptionData(OptionType.STRING, "ign", "Your Minecraft Username", false) - ); - } +// public PitCommand(String name, String description) { +// super(name, description, +// new OptionData(OptionType.STRING, "ign", "Your Minecraft Username", false) +// ); +// } protected void onCommand(SlashCommandInteractionEvent event) { String ign = getUsername(event); diff --git a/src/main/java/me/stuffy/stuffybot/commands/TestCommand.java b/src/main/java/me/stuffy/stuffybot/commands/TestCommand.java index e9605b5..a6f0458 100644 --- a/src/main/java/me/stuffy/stuffybot/commands/TestCommand.java +++ b/src/main/java/me/stuffy/stuffybot/commands/TestCommand.java @@ -1,17 +1,15 @@ package me.stuffy.stuffybot.commands; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; -public class TestCommand extends BaseCommand{ +public class TestCommand extends InteractionHandler { - public TestCommand(String name, String description, OptionData... options) { - super(name, description, - new OptionData(OptionType.STRING, "ign", "Your Minecraft Username", false), - new OptionData(OptionType.STRING, "ign2", "Your Minecraft Username", false), - new OptionData(OptionType.STRING, "ign3", "Your Minecraft Username", false), - new OptionData(OptionType.STRING, "ign4", "Your Minecraft Username", false)); - } +// public TestCommand(String name, String description, OptionData... options) { +// super(name, description, +// new OptionData(OptionType.STRING, "ign", "Your Minecraft Username", false), +// new OptionData(OptionType.STRING, "ign2", "Your Minecraft Username", false), +// new OptionData(OptionType.STRING, "ign3", "Your Minecraft Username", false), +// new OptionData(OptionType.STRING, "ign4", "Your Minecraft Username", false)); +// } } From 03791cfd362d25be4dcf6c670db63ac96efbe4ab Mon Sep 17 00:00:00 2001 From: Stuffy Date: Sun, 4 Aug 2024 16:15:31 -0400 Subject: [PATCH 08/75] framework for future checks --- src/main/java/me/stuffy/stuffybot/utils/MiscUtils.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/me/stuffy/stuffybot/utils/MiscUtils.java b/src/main/java/me/stuffy/stuffybot/utils/MiscUtils.java index e76026f..30a1b19 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/MiscUtils.java +++ b/src/main/java/me/stuffy/stuffybot/utils/MiscUtils.java @@ -100,4 +100,13 @@ public static String toSkillIssue(String toModify) { .replace("Error", "Skill Issue") .replace("ERROR", "SKILL ISSUE"); } + + public static boolean requiresIgn(String commandName) { + return true; + } + + public static boolean validCommand(String commandName) { + return true; + } + } From a5135df03b4494262ef1b942bf53fb9a606ca75a Mon Sep 17 00:00:00 2001 From: Stuffy Date: Sun, 4 Aug 2024 16:17:22 -0400 Subject: [PATCH 09/75] InteractionId is now a class, return Message Data instead of just embed, --- .../stuffybot/commands/InteractionId.java | 35 +++++++++++++ .../stuffy/stuffybot/utils/Interactions.java | 49 ++++++++++++++----- 2 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 src/main/java/me/stuffy/stuffybot/commands/InteractionId.java diff --git a/src/main/java/me/stuffy/stuffybot/commands/InteractionId.java b/src/main/java/me/stuffy/stuffybot/commands/InteractionId.java new file mode 100644 index 0000000..9e6c656 --- /dev/null +++ b/src/main/java/me/stuffy/stuffybot/commands/InteractionId.java @@ -0,0 +1,35 @@ +package me.stuffy.stuffybot.commands; + +import java.util.HashMap; + +public class InteractionId { + private final String command; + private final String userId; + private final HashMap options; + public InteractionId(String componentId) { + String[] parts = componentId.split(":"); + + this.command = parts[0]; + this.userId = parts[1]; + + String options = parts[2]; + this.options = new HashMap<>(); + String[] optionParts = options.split(","); + for (String option : optionParts) { + String[] optionParts2 = option.split("="); + this.options.put(optionParts2[0], optionParts2[1]); + } + } + + public String getCommand() { + return this.command; + } + + public String getUserId() { + return this.userId; + } + + public HashMap getOptions() { + return this.options; + } +} diff --git a/src/main/java/me/stuffy/stuffybot/utils/Interactions.java b/src/main/java/me/stuffy/stuffybot/utils/Interactions.java index a62ccc4..5d8fce6 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/Interactions.java +++ b/src/main/java/me/stuffy/stuffybot/utils/Interactions.java @@ -1,31 +1,55 @@ package me.stuffy.stuffybot.utils; +import me.stuffy.stuffybot.commands.InteractionId; import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; +import net.dv8tion.jda.api.utils.messages.MessageCreateData; -import java.util.Map; +import java.util.HashMap; import java.util.regex.Pattern; import static me.stuffy.stuffybot.utils.DiscordUtils.makeErrorEmbed; +import static net.dv8tion.jda.api.interactions.components.buttons.Button.secondary; public class Interactions { - public static MessageEmbed getResponse(String interactionId) throws InteractionException { - String[] parts = interactionId.split(":"); - String command = parts[0]; - String userId = parts[1]; - String options = parts[2]; + public static MessageCreateData getResponse(String componentId) throws InteractionException { + + InteractionId interactionId; + + try { + interactionId = new InteractionId(componentId); + } catch (Exception e) { + throw new InteractionException(new String[]{ + "You can't fool me, this is gibberish", + "This is not the interaction you are looking for", + "*Someone* messed up the interactionId, and it wasn't me", + "I'm sorry, Dave. I'm afraid I can't do that", + "You can't fool me, that button doesn't exist", + "So, we're just making up our own buttons now?", + "How did you even get here?"}); + } + + String command = interactionId.getCommand(); + String userId = interactionId.getUserId(); + HashMap options = interactionId.getOptions(); // TODO: Error handling for invalid command +// switch (command) { +// case "pit": +// return null; +// default: +// throw new InteractionException("Invalid command, how did you even get here?"); +// } // TODO: Error handling for invalid userId - Map optionsMap = DiscordUtils.parseOptions(options); - if(optionsMap == null){ + if(options == null){ throw new InteractionException("No options provided, what am I supposed to do with this?"); } - if(optionsMap.containsKey("ign")){ - String ign = optionsMap.get("ign"); + if(options.containsKey("ign")){ + String ign = options.get("ign"); if (ign.length() > 16){ throw new InteractionException("Invalid field `ign`, Usernames cannot be longer than 16 characters"); } @@ -36,6 +60,9 @@ public static MessageEmbed getResponse(String interactionId) throws InteractionE } MessageEmbed embed = makeErrorEmbed("Invalid interactionId", "Invalid interactionId"); - return embed; + MessageCreateBuilder data = new MessageCreateBuilder() + .addEmbeds(embed) + .addActionRow(secondary("This is a button", "button")); + return data.build(); } } From 3efb10a16dc53983c4711fe2e1ed7736abd4d867 Mon Sep 17 00:00:00 2001 From: Stuffy Date: Sun, 4 Aug 2024 16:17:54 -0400 Subject: [PATCH 10/75] random exception string --- .../java/me/stuffy/stuffybot/utils/InteractionException.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/me/stuffy/stuffybot/utils/InteractionException.java b/src/main/java/me/stuffy/stuffybot/utils/InteractionException.java index 43aedb6..bdf5173 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/InteractionException.java +++ b/src/main/java/me/stuffy/stuffybot/utils/InteractionException.java @@ -6,6 +6,10 @@ public InteractionException(String message) { this.message = message; } + public InteractionException(String[] messages) { + this.message = messages[(int) (Math.random() * messages.length)]; + } + public String getMessage() { return this.message; } From fa0f95517640ad02acf5c807dc58f6f16ba8c625 Mon Sep 17 00:00:00 2001 From: Stuffy Date: Sun, 4 Aug 2024 16:18:57 -0400 Subject: [PATCH 11/75] removed deprecated parseOptions --- .../me/stuffy/stuffybot/utils/DiscordUtils.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java b/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java index 4da475e..f4b6028 100644 --- a/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java +++ b/src/main/java/me/stuffy/stuffybot/utils/DiscordUtils.java @@ -114,17 +114,4 @@ public static String getUsername(SlashCommandInteractionEvent event) { } return username; } - - public static Map parseOptions(String options) { - String[] parts = options.split(","); - Map optionsMap = new HashMap<>(); - for (String part : parts) { - String[] keyValue = part.split("="); - if (keyValue.length != 2) { - return null; - } - optionsMap.put(keyValue[0], keyValue[1]); - } - return optionsMap; - } } From 1b21d884e1e400a4cab76bcae60b5d84f5af4d23 Mon Sep 17 00:00:00 2001 From: Stuffy Date: Sun, 4 Aug 2024 16:19:21 -0400 Subject: [PATCH 12/75] BaseCommand.java is now InteractionHandler.java --- .../stuffybot/commands/BaseCommand.java | 112 --------------- .../commands/InteractionHandler.java | 135 ++++++++++++++++++ 2 files changed, 135 insertions(+), 112 deletions(-) delete mode 100644 src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java create mode 100644 src/main/java/me/stuffy/stuffybot/commands/InteractionHandler.java diff --git a/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java b/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java deleted file mode 100644 index 7d4e7c1..0000000 --- a/src/main/java/me/stuffy/stuffybot/commands/BaseCommand.java +++ /dev/null @@ -1,112 +0,0 @@ -package me.stuffy.stuffybot.commands; - -import me.stuffy.stuffybot.Bot; -import me.stuffy.stuffybot.utils.InteractionException; -import me.stuffy.stuffybot.utils.Logger; -import me.stuffy.stuffybot.utils.StatisticsManager; -import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.interactions.commands.OptionMapping; -import net.dv8tion.jda.api.interactions.commands.build.OptionData; -import org.jetbrains.annotations.NotNull; - -import java.time.Instant; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.regex.Pattern; - -import static me.stuffy.stuffybot.utils.DiscordUtils.getUsername; -import static me.stuffy.stuffybot.utils.DiscordUtils.makeErrorEmbed; -import static me.stuffy.stuffybot.utils.Interactions.getResponse; - -public abstract class BaseCommand extends ListenerAdapter { - private String name; - private String description; - private OptionData[] options; - private final Map latestValidInteraction = new HashMap<>(); - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); - - - public BaseCommand(String name, String description, OptionData... options) { - this.name = name; - this.description = description; - this.options = options; - Bot bot = Bot.getInstance(); - bot.getHomeGuild().upsertCommand(name, description) - .addOptions(options) - .queue(); - Logger.log(" Registered command " + name + ": " + description); - } - - @Override - public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { - if (event.getName().equals(this.name)) { - event.deferReply().queue(); - String interactionId = this.name + ":" + event.getUser().getId() + ":"; - ArrayList optionsArray = new ArrayList(); - - for (OptionData option : this.options) { - String optionName = option.getName(); - if(optionName.equals("ign") && event.getOption("ign") == null){ - String ign = getUsername(event); - optionsArray.add("ign=" + ign); - } - } - Pattern pattern = Pattern.compile("[,=:]"); - for (OptionMapping option : event.getOptions()) { - String optionString = option.getAsString(); - if(pattern.matcher(optionString).find()){ - MessageEmbed errorEmbed = makeErrorEmbed("Slash Command Error", "An error occurred while processing your command.\n-# Invalid character in option `" + option.getName() + "`"); - event.getHook().sendMessageEmbeds(errorEmbed).queue(); - return; - } - optionsArray.add(option.getName() + "=" + optionString); - } - - String options = String.join(",", optionsArray); - interactionId += options; - - Logger.log(" @" + event.getUser().getName() + ": /" + this.name + " " + options); - - MessageEmbed response = null; - try { - response = getResponse(interactionId); - } catch (InteractionException e) { - MessageEmbed errorEmbed = makeErrorEmbed("Slash Command Error", "An error occurred while processing your command.\n-# " + e.getMessage()); - event.getHook().sendMessageEmbeds(errorEmbed).queue(); - return; - } - - event.getHook().sendMessageEmbeds(response).queue(); - - StatisticsManager.incrementCommandUsage(this.name); - - latestValidInteraction.put(event.getHook().getId(), Instant.now()); - scheduler.scheduleAtFixedRate(this::endEvent, 0, 1, TimeUnit.SECONDS); - } - } - - private void endEvent() { - latestValidInteraction.forEach((messageId, time) -> { - if (Instant.now().getEpochSecond() - time.getEpochSecond() > 30) { - latestValidInteraction.remove(messageId); - } - }); - } - - @Override - public void onButtonInteraction(@NotNull ButtonInteractionEvent event) { - if (latestValidInteraction.containsKey(event.getMessageId())) { - latestValidInteraction.remove(event.getMessageId()); - event.deferEdit().queue(); - } - } -} - - diff --git a/src/main/java/me/stuffy/stuffybot/commands/InteractionHandler.java b/src/main/java/me/stuffy/stuffybot/commands/InteractionHandler.java new file mode 100644 index 0000000..eb1e095 --- /dev/null +++ b/src/main/java/me/stuffy/stuffybot/commands/InteractionHandler.java @@ -0,0 +1,135 @@ +package me.stuffy.stuffybot.commands; + +import me.stuffy.stuffybot.Bot; +import me.stuffy.stuffybot.utils.InteractionException; +import me.stuffy.stuffybot.utils.Logger; +import me.stuffy.stuffybot.utils.StatisticsManager; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import net.dv8tion.jda.api.utils.messages.MessageCreateData; +import org.jetbrains.annotations.NotNull; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; + +import static me.stuffy.stuffybot.utils.DiscordUtils.getUsername; +import static me.stuffy.stuffybot.utils.DiscordUtils.makeErrorEmbed; +import static me.stuffy.stuffybot.utils.Interactions.getResponse; +import static me.stuffy.stuffybot.utils.MiscUtils.*; + +public class InteractionHandler extends ListenerAdapter { + private final Map latestValidInteraction = new HashMap<>(); + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + public InteractionHandler() { + } + + + @Override + public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { + String commandName = event.getName(); + event.deferReply().queue(); + String interactionId = commandName + ":" + event.getUser().getId() + ":"; + ArrayList optionsArray = new ArrayList(); + + // TODO: Error handling for invalid command + if(!validCommand(commandName)){ + MessageEmbed errorEmbed = makeErrorEmbed("Slash Command Error", "An error occurred while processing your command.\n-# Invalid command `" + commandName + "`"); + event.getHook().sendMessageEmbeds(errorEmbed).setEphemeral(true).queue(); + return; + } + + if(requiresIgn(commandName) && event.getOption("ign") == null){ + String ign = getUsername(event); + optionsArray.add("ign=" + ign); + } + + Pattern pattern = Pattern.compile("[,=:]"); + for (OptionMapping option : event.getOptions()) { + String optionString = option.getAsString(); + if(pattern.matcher(optionString).find()){ + MessageEmbed errorEmbed = makeErrorEmbed("Slash Command Error", "An error occurred while processing your command.\n-# Invalid character in option `" + option.getName() + "`"); + event.getHook().sendMessageEmbeds(errorEmbed).setEphemeral(true).queue(); + return; + } + optionsArray.add(option.getName() + "=" + optionString); + } + + String options = String.join(",", optionsArray); + interactionId += options; + + Logger.log(" @" + event.getUser().getName() + ": /" + commandName + " " + options); + + MessageCreateData response = null; + try { + response = getResponse(interactionId);; + } catch (InteractionException e) { + MessageEmbed errorEmbed = makeErrorEmbed("Slash Command Error", "An error occurred while processing your command.\n-# " + e.getMessage()); + event.getHook().sendMessageEmbeds(errorEmbed).setEphemeral(true).queue(); + return; + } + + event.getHook().sendMessage(response).queue(); + + StatisticsManager.incrementCommandUsage(commandName); + + latestValidInteraction.put(event.getHook().getId(), Instant.now()); + scheduler.scheduleAtFixedRate(this::endEvent, 0, 1, TimeUnit.SECONDS); + } + + private void endEvent() { + latestValidInteraction.forEach((messageId, time) -> { + if (Instant.now().getEpochSecond() - time.getEpochSecond() > 30) { + latestValidInteraction.remove(messageId); + } + }); + } + + @Override + public void onButtonInteraction(@NotNull ButtonInteractionEvent event) { + event.deferEdit().queue(); + + Logger.log("