diff --git a/src/main/java/cc/fascinated/bat/command/Category.java b/src/main/java/cc/fascinated/bat/command/Category.java index e156033..a497c78 100644 --- a/src/main/java/cc/fascinated/bat/command/Category.java +++ b/src/main/java/cc/fascinated/bat/command/Category.java @@ -16,9 +16,10 @@ public enum Category { GENERAL(Emoji.fromUnicode("U+2699"), "General", false), FUN(Emoji.fromFormatted("U+1F973"), "Fun", false), SERVER(Emoji.fromFormatted("U+1F5A5"), "Server", false), + MODERATION(Emoji.fromFormatted("U+1F6E0"), "Moderation", false), UTILITY(Emoji.fromFormatted("U+1F6E0"), "Utility", false), MUSIC(Emoji.fromFormatted("U+1F3B5"), "Music", false), - SNIPE(Emoji.fromFormatted("U+1F4A3"), "Snipe", false), + MESSAGES(Emoji.fromFormatted("U+1F4A3"), "Snipe", false), LOGS(Emoji.fromFormatted("U+1F4D1"), "Logs", false), BEAT_SABER(Emoji.fromFormatted("U+1FA84"), "Beat Saber", false), BOT_ADMIN(null, null, true); diff --git a/src/main/java/cc/fascinated/bat/features/logging/listeners/MessageListener.java b/src/main/java/cc/fascinated/bat/features/logging/listeners/MessageListener.java index 7f8ec22..c3c069e 100644 --- a/src/main/java/cc/fascinated/bat/features/logging/listeners/MessageListener.java +++ b/src/main/java/cc/fascinated/bat/features/logging/listeners/MessageListener.java @@ -31,7 +31,7 @@ public class MessageListener implements EventListener { @Override public void onGuildMessageDelete(@NonNull BatGuild guild, BatUser user, DiscordMessage message, @NonNull MessageDeleteEvent event) { - if (user.getDiscordUser().isBot() || message.getAuthor().isBot()) return; + if (user == null || user.getDiscordUser().isBot() || message.getAuthor().isBot()) return; log.info("User \"{}\" deleted a message in guild \"{}\"", user.getDiscordUser().getGlobalName(), guild.getName()); logFeature.sendLog(guild, LogType.MESSAGE_DELETE, EmbedUtils.errorEmbed() diff --git a/src/main/java/cc/fascinated/bat/features/messagesnipe/MessageSnipeFeature.java b/src/main/java/cc/fascinated/bat/features/messagesnipe/MessageSnipeFeature.java index e6f4dfd..265a6d3 100644 --- a/src/main/java/cc/fascinated/bat/features/messagesnipe/MessageSnipeFeature.java +++ b/src/main/java/cc/fascinated/bat/features/messagesnipe/MessageSnipeFeature.java @@ -30,7 +30,7 @@ public class MessageSnipeFeature extends Feature implements EventListener { @Autowired public MessageSnipeFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) { - super("Message Snipe", false, Category.SNIPE); + super("Message Snipe", false, Category.MESSAGES); super.registerCommand(commandService, context.getBean(MessageSnipeCommand.class)); } diff --git a/src/main/java/cc/fascinated/bat/features/moderation/ModerationFeature.java b/src/main/java/cc/fascinated/bat/features/moderation/ModerationFeature.java new file mode 100644 index 0000000..a632182 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/moderation/ModerationFeature.java @@ -0,0 +1,23 @@ +package cc.fascinated.bat.features.moderation; + +import cc.fascinated.bat.command.Category; +import cc.fascinated.bat.features.Feature; +import cc.fascinated.bat.features.moderation.command.PurgeCommand; +import cc.fascinated.bat.service.CommandService; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component +public class ModerationFeature extends Feature { + @Autowired + public ModerationFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) { + super("Moderation", true,Category.MODERATION); + + super.registerCommand(commandService, context.getBean(PurgeCommand.class)); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/moderation/command/PurgeCommand.java b/src/main/java/cc/fascinated/bat/features/moderation/command/PurgeCommand.java new file mode 100644 index 0000000..3efc61b --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/moderation/command/PurgeCommand.java @@ -0,0 +1,67 @@ +package cc.fascinated.bat.features.moderation.command; + +import cc.fascinated.bat.command.BatCommand; +import cc.fascinated.bat.command.CommandInfo; +import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.model.BatGuild; +import cc.fascinated.bat.model.BatUser; +import lombok.NonNull; +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @author Fascinated (fascinated7) + */ +@Component +@CommandInfo(name = "purge", description = "Purge messages from a channel", requiredPermissions = Permission.MESSAGE_MANAGE) +public class PurgeCommand extends BatCommand { + private final long MESSAGE_DELETE_DELAY = TimeUnit.SECONDS.toMillis(10); + + public PurgeCommand() { + super.addOption(OptionType.INTEGER, "amount", "The amount of messages to remove", true); + } + + @Override + public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { + OptionMapping amountOption = event.getOption("amount"); + if (amountOption == null) { + return; + } + int amount = amountOption.getAsInt(); + if (amount < 2 || amount > 100) { + event.replyEmbeds(EmbedUtils.errorEmbed() + .setDescription("You can only purge between 2 and 100 messages") + .build()).queue(); + return; + } + + event.replyEmbeds(EmbedUtils.successEmbed() + .setDescription("Purging `%s` messages...".formatted(amount)) + .build()).queue(then -> { + TextChannel textChannel = (TextChannel) channel; + textChannel.getHistory().retrievePast(amount + 1).queue(messages -> { + // Filter out the command message + then.retrieveOriginal().queue(original -> { + if (original == null) return; + List toRemove = messages.stream().filter(message -> !original.getId().equals(message.getId())).toList(); + textChannel.deleteMessages(toRemove).queue(done -> then.editOriginalEmbeds(EmbedUtils.successEmbed() + .setDescription("Successfully purged `%s` messages\n\n*This message will be removed *".formatted( + amount, + (System.currentTimeMillis() + MESSAGE_DELETE_DELAY) / 1000 + )) + .build()).queue(message -> message.delete().queueAfter(MESSAGE_DELETE_DELAY, TimeUnit.MILLISECONDS))); + }); + }); + }); + } +}