diff --git a/src/plugins/commands/moderation/index.ts b/src/plugins/commands/moderation/index.ts new file mode 100644 index 0000000..73b4994 --- /dev/null +++ b/src/plugins/commands/moderation/index.ts @@ -0,0 +1,22 @@ +import { SlashCommandBuilder } from "@discordjs/builders"; +import { CommandInteraction } from "discord.js"; + +import modules from "./modules"; +export const moduleData = modules; + +export const builder = new SlashCommandBuilder() + .setName("moderation") + .setDescription("Moderation.") + + .addSubcommand(modules.prune.builder); + +export const execute = async (interaction: CommandInteraction) => { + switch (interaction.options.getSubcommand()) { + case "prune": + return modules.prune.execute(interaction); + default: + throw new Error( + `Unknown subcommand: ${interaction.options.getSubcommand()}` + ); + } +}; diff --git a/src/plugins/commands/moderation/modules/index.ts b/src/plugins/commands/moderation/modules/index.ts new file mode 100644 index 0000000..e7dd532 --- /dev/null +++ b/src/plugins/commands/moderation/modules/index.ts @@ -0,0 +1,3 @@ +import prune from "./prune"; + +export default { prune }; diff --git a/src/plugins/commands/moderation/modules/prune/index.ts b/src/plugins/commands/moderation/modules/prune/index.ts new file mode 100644 index 0000000..c847e47 --- /dev/null +++ b/src/plugins/commands/moderation/modules/prune/index.ts @@ -0,0 +1,91 @@ +// Dependencies +import { + CommandInteraction, + Permissions, +} from "discord.js"; + +// Configurations +import getEmbedConfig from "../../../../../helpers/getEmbedConfig"; + +import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; + +// Function +export default { + metadata: { + guildOnly: true, + ephemeral: false, + permissions: [Permissions.FLAGS.MANAGE_MESSAGES], + }, + + builder: (command: SlashCommandSubcommandBuilder) => { + return command + .setName("prune") + .setDescription("Prune messages!") + .addIntegerOption((option) => + option + .setName("count") + .setDescription("How many messages you want to prune.") + .setRequired(true) + ) + .addBooleanOption((option) => + option.setName("bots").setDescription("Include bots.") + ); + }, + execute: async (interaction: CommandInteraction) => { + const { successColor, footerText, footerIcon } = await getEmbedConfig( + interaction.guild + ); + + const count = interaction.options.getInteger("count"); + if (count == null) return; + const bots = interaction.options.getBoolean("bots"); + + if (count < 1 || count > 100) { + const interactionEmbed = { + title: "[:police_car:] Prune", + description: `You can only prune between 1 and 100 messages.`, + color: successColor, + timestamp: new Date(), + footer: { + iconURL: footerIcon, + text: footerText, + }, + }; + await interaction.editReply({ + embeds: [interactionEmbed], + }); + return; + } + + if (interaction?.channel?.type !== "GUILD_TEXT") return; + await interaction.channel.messages.fetch().then(async (messages) => { + const messagesToDelete = ( + bots + ? messages.filter((m) => m?.interaction?.id !== interaction.id) + : messages.filter( + (m) => + m?.interaction?.id !== interaction.id && m?.author?.bot !== true + ) + ).first(count); + + if (interaction?.channel?.type !== "GUILD_TEXT") return; + await interaction.channel + .bulkDelete(messagesToDelete, true) + .then(async () => { + const interactionEmbed = { + title: "[:police_car:] Prune", + description: `Successfully pruned \`${count}\` messages.`, + color: successColor, + timestamp: new Date(), + footer: { + iconURL: footerIcon, + text: footerText, + }, + }; + await interaction.editReply({ + embeds: [interactionEmbed], + }); + }); + }); + }, +};