diff --git a/src/main/java/org/geysermc/discordbot/GeyserBot.java b/src/main/java/org/geysermc/discordbot/GeyserBot.java index 0aa74c15..78009ed4 100644 --- a/src/main/java/org/geysermc/discordbot/GeyserBot.java +++ b/src/main/java/org/geysermc/discordbot/GeyserBot.java @@ -66,6 +66,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -116,6 +117,11 @@ public class GeyserBot { if (theClass.getName().contains("SubCommand")) { continue; } + // Don't load abstract classes + if (Modifier.isAbstract(theClass.getModifiers())) { + continue; + } + slashCommands.add(theClass.getDeclaredConstructor().newInstance()); LoggerFactory.getLogger(theClass).debug("Loaded SlashCommand Successfully!"); } diff --git a/src/main/java/org/geysermc/discordbot/commands/FloodgateUuidCommand.java b/src/main/java/org/geysermc/discordbot/commands/FloodgateUuidCommand.java index 0ba5fb73..e19a501d 100644 --- a/src/main/java/org/geysermc/discordbot/commands/FloodgateUuidCommand.java +++ b/src/main/java/org/geysermc/discordbot/commands/FloodgateUuidCommand.java @@ -25,11 +25,11 @@ package org.geysermc.discordbot.commands; -import com.jagrosh.jdautilities.command.SlashCommand; import com.jagrosh.jdautilities.command.SlashCommandEvent; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import org.geysermc.discordbot.commands.filter.FilteredSlashCommand; import org.geysermc.discordbot.util.BotColors; import org.json.JSONObject; import pw.chew.chewbotcca.util.RestClient; @@ -39,7 +39,7 @@ import java.util.Collections; import java.util.UUID; -public class FloodgateUuidCommand extends SlashCommand { +public class FloodgateUuidCommand extends FilteredSlashCommand { public FloodgateUuidCommand() { this.name = "uuid"; @@ -54,7 +54,7 @@ public FloodgateUuidCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void executeFiltered(SlashCommandEvent event) { // get bedrock username, replace char in case they include Floodgate prefix. String username = event.optString("bedrock-username", "").replace(".", ""); EmbedBuilder builder = new EmbedBuilder(); diff --git a/src/main/java/org/geysermc/discordbot/commands/GithubCommand.java b/src/main/java/org/geysermc/discordbot/commands/GithubCommand.java index 1e341408..d68b66c3 100644 --- a/src/main/java/org/geysermc/discordbot/commands/GithubCommand.java +++ b/src/main/java/org/geysermc/discordbot/commands/GithubCommand.java @@ -25,12 +25,12 @@ package org.geysermc.discordbot.commands; -import com.jagrosh.jdautilities.command.SlashCommand; import com.jagrosh.jdautilities.command.SlashCommandEvent; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import org.geysermc.discordbot.commands.filter.FilteredSlashCommand; import org.geysermc.discordbot.util.BotColors; import org.geysermc.discordbot.util.BotHelpers; import org.geysermc.discordbot.util.MessageHelper; @@ -40,7 +40,7 @@ import java.io.IOException; import java.util.Arrays; -public class GithubCommand extends SlashCommand { +public class GithubCommand extends FilteredSlashCommand { public GithubCommand() { this.name = "github"; @@ -54,7 +54,7 @@ public GithubCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void executeFiltered(SlashCommandEvent event) { String repository = event.optString("repo", ""); String owner = event.optString("owner", ""); event.deferReply(false).queue(interactionHook -> { diff --git a/src/main/java/org/geysermc/discordbot/commands/IssueCommand.java b/src/main/java/org/geysermc/discordbot/commands/IssueCommand.java index e6b24566..4ae29b3e 100644 --- a/src/main/java/org/geysermc/discordbot/commands/IssueCommand.java +++ b/src/main/java/org/geysermc/discordbot/commands/IssueCommand.java @@ -26,13 +26,13 @@ package org.geysermc.discordbot.commands; import com.jagrosh.jdautilities.command.CommandEvent; -import com.jagrosh.jdautilities.command.SlashCommand; import com.jagrosh.jdautilities.command.SlashCommandEvent; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import org.geysermc.discordbot.GeyserBot; +import org.geysermc.discordbot.commands.filter.FilteredSlashCommand; import org.geysermc.discordbot.util.BotColors; import org.geysermc.discordbot.util.MessageHelper; import org.kohsuke.github.GHFileNotFoundException; @@ -50,7 +50,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class IssueCommand extends SlashCommand { +public class IssueCommand extends FilteredSlashCommand { private static final Pattern REPO_PATTERN = Pattern.compile("(^| )([\\w.\\-]+/)?([\\w.\\-]+)( |$)", Pattern.CASE_INSENSITIVE); private static final Pattern ISSUE_PATTERN = Pattern.compile("(^| )#?([0-9]+)( |$)", Pattern.CASE_INSENSITIVE); @@ -69,7 +69,7 @@ public IssueCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void executeFiltered(SlashCommandEvent event) { // Issue int issue = (int) event.optLong("number", 0); // Repo diff --git a/src/main/java/org/geysermc/discordbot/commands/PingCommand.java b/src/main/java/org/geysermc/discordbot/commands/PingCommand.java index 781bbe8b..2b566fbe 100644 --- a/src/main/java/org/geysermc/discordbot/commands/PingCommand.java +++ b/src/main/java/org/geysermc/discordbot/commands/PingCommand.java @@ -30,7 +30,6 @@ import br.com.azalim.mcserverping.MCPingResponse; import br.com.azalim.mcserverping.MCPingUtil; import com.jagrosh.jdautilities.command.CommandEvent; -import com.jagrosh.jdautilities.command.SlashCommand; import com.jagrosh.jdautilities.command.SlashCommandEvent; import com.nukkitx.protocol.bedrock.BedrockClient; import com.nukkitx.protocol.bedrock.BedrockPong; @@ -39,6 +38,7 @@ import net.dv8tion.jda.api.interactions.InteractionHook; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import org.geysermc.discordbot.commands.filter.FilteredSlashCommand; import org.geysermc.discordbot.util.BotColors; import org.geysermc.discordbot.util.BotHelpers; import org.geysermc.discordbot.util.MessageHelper; @@ -52,7 +52,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -public class PingCommand extends SlashCommand { +public class PingCommand extends FilteredSlashCommand { private static final int TIMEOUT = 1250; // in ms, has to stay below 1500 (1.5s for each platform, total of 3s) public PingCommand() { @@ -71,7 +71,7 @@ public PingCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void executeFiltered(SlashCommandEvent event) { // Defer to wait for us to load a response and allows for files to be uploaded InteractionHook interactionHook = event.deferReply().complete(); diff --git a/src/main/java/org/geysermc/discordbot/commands/TagCommand.java b/src/main/java/org/geysermc/discordbot/commands/TagCommand.java index 0c7d045f..620bf5f1 100644 --- a/src/main/java/org/geysermc/discordbot/commands/TagCommand.java +++ b/src/main/java/org/geysermc/discordbot/commands/TagCommand.java @@ -25,13 +25,13 @@ package org.geysermc.discordbot.commands; -import com.jagrosh.jdautilities.command.SlashCommand; import com.jagrosh.jdautilities.command.SlashCommandEvent; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent; import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import org.geysermc.discordbot.commands.filter.FilteredSlashCommand; import org.geysermc.discordbot.tags.SlashTag; import org.geysermc.discordbot.tags.TagsManager; import org.geysermc.discordbot.util.BotColors; @@ -41,7 +41,7 @@ import java.util.Collections; import java.util.List; -public class TagCommand extends SlashCommand { +public class TagCommand extends FilteredSlashCommand { public TagCommand() { this.name = "tag"; @@ -56,7 +56,7 @@ public TagCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void executeFiltered(SlashCommandEvent event) { String tagName = event.getOption("name").getAsString(); SlashTag tag = null; diff --git a/src/main/java/org/geysermc/discordbot/commands/TagsCommand.java b/src/main/java/org/geysermc/discordbot/commands/TagsCommand.java index 28a3c4b4..e6f444b8 100644 --- a/src/main/java/org/geysermc/discordbot/commands/TagsCommand.java +++ b/src/main/java/org/geysermc/discordbot/commands/TagsCommand.java @@ -27,12 +27,12 @@ import com.jagrosh.jdautilities.command.Command; import com.jagrosh.jdautilities.command.CommandEvent; -import com.jagrosh.jdautilities.command.SlashCommand; import com.jagrosh.jdautilities.command.SlashCommandEvent; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import org.geysermc.discordbot.commands.filter.FilteredSlashCommand; import org.geysermc.discordbot.tags.TagsManager; import org.geysermc.discordbot.util.BotColors; import org.geysermc.discordbot.util.PropertiesManager; @@ -42,7 +42,7 @@ import java.util.Collections; import java.util.List; -public class TagsCommand extends SlashCommand { +public class TagsCommand extends FilteredSlashCommand { public TagsCommand() { this.name = "tags"; this.arguments = "[search]"; @@ -55,7 +55,7 @@ public TagsCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void executeFiltered(SlashCommandEvent event) { String search = event.optString("search", ""); event.replyEmbeds(handle(search)).queue(); diff --git a/src/main/java/org/geysermc/discordbot/commands/filter/FilteredSlashCommand.java b/src/main/java/org/geysermc/discordbot/commands/filter/FilteredSlashCommand.java new file mode 100644 index 00000000..3178ccf7 --- /dev/null +++ b/src/main/java/org/geysermc/discordbot/commands/filter/FilteredSlashCommand.java @@ -0,0 +1,48 @@ +package org.geysermc.discordbot.commands.filter; + +import com.jagrosh.jdautilities.command.SlashCommand; +import com.jagrosh.jdautilities.command.SlashCommandEvent; +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import org.geysermc.discordbot.listeners.SwearHandler; +import org.geysermc.discordbot.storage.ServerSettings; +import org.geysermc.discordbot.util.BotColors; + +import java.util.regex.Pattern; + +public abstract class FilteredSlashCommand extends SlashCommand { + @Override + protected final void execute(SlashCommandEvent event) { + Pattern filterPattern = null; + for (OptionMapping option : event.getOptions()) { + if (option.getType() != OptionType.STRING) continue; + if ((filterPattern = SwearHandler.checkString(option.getAsString())) != null) break; + } + + if (filterPattern != null) { + event.reply(event.getUser().getAsMention() + + " your command cannot be processed because it contains profanity! Please read our rules for more information.") + .setEphemeral(true).queue(); + + // Log the event + if (event.getGuild() != null) { + String channel = event.getChannel() == null ? "Unknown" : event.getChannel().getAsMention(); + + ServerSettings.getLogChannel(event.getGuild()).sendMessageEmbeds(new EmbedBuilder() + .setTitle("Profanity blocked command") + .setDescription("**Sender:** " + event.getUser().getAsMention() + "\n" + + "**Channel:** " + channel + "\n" + + "**Regex:** `" + filterPattern + "`\n" + + "**Command:** " + event.getCommandString()) + .setColor(BotColors.FAILURE.getColor()) + .build()).queue(); + } + return; + } + + executeFiltered(event); + } + + protected abstract void executeFiltered(SlashCommandEvent event); +} diff --git a/src/main/java/org/geysermc/discordbot/commands/search/ProviderCommand.java b/src/main/java/org/geysermc/discordbot/commands/search/ProviderCommand.java index d2037c84..de4b9dfc 100644 --- a/src/main/java/org/geysermc/discordbot/commands/search/ProviderCommand.java +++ b/src/main/java/org/geysermc/discordbot/commands/search/ProviderCommand.java @@ -26,7 +26,6 @@ package org.geysermc.discordbot.commands.search; import com.jagrosh.jdautilities.command.CommandEvent; -import com.jagrosh.jdautilities.command.SlashCommand; import com.jagrosh.jdautilities.command.SlashCommandEvent; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; @@ -34,6 +33,7 @@ import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import org.geysermc.discordbot.commands.filter.FilteredSlashCommand; import org.geysermc.discordbot.util.BotColors; import org.geysermc.discordbot.util.DicesCoefficient; import org.geysermc.discordbot.util.MessageHelper; @@ -44,9 +44,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; -public class ProviderCommand extends SlashCommand { +public class ProviderCommand extends FilteredSlashCommand { private List cache = null; private long cacheTime = 0; @@ -63,7 +62,7 @@ public ProviderCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void executeFiltered(SlashCommandEvent event) { event.replyEmbeds(handle(event.optString("provider", ""))).queue(); } diff --git a/src/main/java/org/geysermc/discordbot/commands/search/WikiCommand.java b/src/main/java/org/geysermc/discordbot/commands/search/WikiCommand.java index 5a0a5b5e..e2c8368e 100644 --- a/src/main/java/org/geysermc/discordbot/commands/search/WikiCommand.java +++ b/src/main/java/org/geysermc/discordbot/commands/search/WikiCommand.java @@ -28,13 +28,13 @@ import com.algolia.model.search.FacetFilters; import com.algolia.model.search.SearchParamsObject; import com.jagrosh.jdautilities.command.CommandEvent; -import com.jagrosh.jdautilities.command.SlashCommand; import com.jagrosh.jdautilities.command.SlashCommandEvent; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import org.geysermc.discordbot.GeyserBot; +import org.geysermc.discordbot.commands.filter.FilteredSlashCommand; import org.geysermc.discordbot.util.BotColors; import org.geysermc.discordbot.util.DocSearchResult; import org.geysermc.discordbot.util.MessageHelper; @@ -55,7 +55,7 @@ /** * A command to search the Geyser wiki for a query. */ -public class WikiCommand extends SlashCommand { +public class WikiCommand extends FilteredSlashCommand { /** * The attributes to retrieve from the Algolia search. */ @@ -96,7 +96,7 @@ public WikiCommand() { * @param event The SlashCommandEvent. */ @Override - protected void execute(SlashCommandEvent event) { + protected void executeFiltered(SlashCommandEvent event) { String query = event.optString("query", ""); if (query.isEmpty()) { diff --git a/src/main/java/org/geysermc/discordbot/listeners/SwearHandler.java b/src/main/java/org/geysermc/discordbot/listeners/SwearHandler.java index 58c360ff..e9a59e85 100644 --- a/src/main/java/org/geysermc/discordbot/listeners/SwearHandler.java +++ b/src/main/java/org/geysermc/discordbot/listeners/SwearHandler.java @@ -29,14 +29,18 @@ import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateNicknameEvent; +import net.dv8tion.jda.api.events.interaction.command.GenericCommandInteractionEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; import org.geysermc.discordbot.GeyserBot; import org.geysermc.discordbot.storage.ServerSettings; import org.geysermc.discordbot.util.BotColors; import org.geysermc.discordbot.util.BotHelpers; import org.jetbrains.annotations.NotNull; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; import java.net.URISyntaxException; @@ -99,7 +103,7 @@ public static void loadFilters() { } @Nullable - private Pattern checkString(String input) { + public static Pattern checkString(String input) { // TODO: Maybe only clean start and end? Then run through the same as normalInput? input = input.toLowerCase(); String cleanInput = CLEAN_PATTERN.matcher(input).replaceAll(""); @@ -200,4 +204,34 @@ public void onGuildMemberUpdateNickname(@NotNull GuildMemberUpdateNicknameEvent event.getMember().modifyNickname(getRandomNick()).queue(); } } + + // @Override + // public void onGenericCommandInteraction(@Nonnull GenericCommandInteractionEvent event) { + // Pattern filterPattern = null; + // for (OptionMapping option: event.getOptions()) { + // if (option.getType() != OptionType.STRING) continue; + // if ((filterPattern = checkString(option.getAsString())) == null) continue; + // break; + // } + + // if (filterPattern == null) return; + + // event.reply(event.getUser().getAsMention() + + // " your command cannot be processed because it contains profanity! Please read our rules for more information.") + // .setEphemeral(true).queue(); + + // if (event.getGuild() == null) return; + + // @SuppressWarnings("null") + // String channel = event.getChannel() == null ? "Unknown" : event.getChannel().getAsMention(); + + // ServerSettings.getLogChannel(event.getGuild()).sendMessageEmbeds(new EmbedBuilder() + // .setTitle("Profanity removed") + // .setDescription("**Sender:** " + event.getUser().getAsMention() + "\n" + + // "**Channel:** " + channel + "\n" + + // "**Regex:** `" + filterPattern + "`\n" + + // "**Command:** " + event.getCommandString()) + // .setColor(BotColors.FAILURE.getColor()) + // .build()).queue(); + // } } diff --git a/src/main/java/org/geysermc/discordbot/util/MessageHelper.java b/src/main/java/org/geysermc/discordbot/util/MessageHelper.java index 9bcaabe3..8b848f93 100644 --- a/src/main/java/org/geysermc/discordbot/util/MessageHelper.java +++ b/src/main/java/org/geysermc/discordbot/util/MessageHelper.java @@ -75,7 +75,7 @@ public static MessageEmbed errorResponse(Object event, String title, String mess .setEphemeral(true) // Only show error to the user .queue(); } else { - throw new IllegalArgumentException("Event must be one of CommandEvent, SlashCommandEvent"); + throw new IllegalArgumentException("Event must be one of CommandEvent, SlashCommandEvent; got: " + event.getClass().getName()); } return null;