diff --git a/.gitignore b/.gitignore index ce1b308..1707d85 100644 --- a/.gitignore +++ b/.gitignore @@ -105,5 +105,4 @@ dist config.json .DS_Store -ormconfig.json -.temp/ \ No newline at end of file +ormconfig.json \ No newline at end of file diff --git a/data/usage/config.txt b/data/usage/config.txt index 6a11414..ccdb647 100644 --- a/data/usage/config.txt +++ b/data/usage/config.txt @@ -7,6 +7,7 @@ commands.disabled: Disabled commands, separated by commas (Default: "") role.moderator: The moderator role name (Default: "Moderator") role.administrator: The administrator role name (Default: "Administrator") +role.muted: The muted role name (Default: "Muted") rules.file: The location of the rules file (Default: "data/rules/rules") diff --git a/src/commands/mute.ts b/src/commands/mute.ts new file mode 100644 index 0000000..5881037 --- /dev/null +++ b/src/commands/mute.ts @@ -0,0 +1,93 @@ +import { CommandInteraction, EmbedBuilder, GuildMember, PermissionsBitField, SlashCommandBuilder, TextChannel } from "discord.js"; +import { AuditType } from "../constants/AuditType"; +import EmbedColours from "../constants/EmbedColours"; +import Audit from "../database/entities/Audit"; +import SettingsHelper from "../helpers/SettingsHelper"; +import { Command } from "../type/command"; + +export default class Mute extends Command { + constructor() { + super(); + + this.CommandBuilder = new SlashCommandBuilder() + .setName("mute") + .setDescription("(DEPRECATED) Mute a member in the server with an optional reason") + .setDefaultMemberPermissions(PermissionsBitField.Flags.ModerateMembers) + .addUserOption(option => + option + .setName('target') + .setDescription('The user') + .setRequired(true)) + .addStringOption(option => + option + .setName('reason') + .setDescription('The reason')); + } + + public override async execute(interaction: CommandInteraction) { + if (!interaction.guild || !interaction.guildId) return; + + const targetUser = interaction.options.get('target'); + const reasonInput = interaction.options.get('reason'); + + if (!targetUser || !targetUser.user || !targetUser.member) { + await interaction.reply('Fields are required.'); + return; + } + + const targetMember = targetUser.member as GuildMember; + const reason = reasonInput && reasonInput.value ? reasonInput.value.toString() : "*none*"; + + const logEmbed = new EmbedBuilder() + .setColor(EmbedColours.Ok) + .setTitle("Member Muted") + .setDescription(`<@${targetUser.user.id}> \`${targetUser.user.tag}\``) + .setThumbnail(targetUser.user.avatarURL()) + .addFields([ + { + name: "Moderator", + value: `<@${interaction.user.id}>`, + }, + { + name: "Reason", + value: reason, + }, + ]); + + const mutedRoleName = await SettingsHelper.GetSetting('role.muted', interaction.guildId); + + if (!mutedRoleName) { + await interaction.reply('Unable to find configuration. Please contact the bot author.'); + return; + } + + const mutedRole = interaction.guild.roles.cache.find(role => role.name == mutedRoleName); + + if (!mutedRole) { + await interaction.reply('Muted role not found.'); + return; + } + + if (!targetMember.manageable) { + await interaction.reply('Insufficient permissions. Please contact a moderator.'); + return; + } + + await targetMember.roles.add(mutedRole); + + const channelName = await SettingsHelper.GetSetting('channels.logs.mod', interaction.guildId); + + if (!channelName) return; + + const channel = interaction.guild.channels.cache.find(x => x.name == channelName) as TextChannel; + + if (channel) { + await channel.send({ embeds: [ logEmbed ]}); + } + + const audit = new Audit(targetUser.user.id, AuditType.Mute, reason, interaction.user.id, interaction.guildId); + await audit.Save(Audit, audit); + + await interaction.reply("Please note the mute and unmute commands have been deprecated and will be removed in a future update. Please use timeout instead"); + } +} \ No newline at end of file diff --git a/src/commands/unmute.ts b/src/commands/unmute.ts new file mode 100644 index 0000000..caf6073 --- /dev/null +++ b/src/commands/unmute.ts @@ -0,0 +1,88 @@ +import { CommandInteraction, EmbedBuilder, GuildMember, PermissionsBitField, SlashCommandBuilder, TextChannel } from "discord.js"; +import EmbedColours from "../constants/EmbedColours"; +import SettingsHelper from "../helpers/SettingsHelper"; +import { Command } from "../type/command"; + +export default class Unmute extends Command { + constructor() { + super(); + + this.CommandBuilder = new SlashCommandBuilder() + .setName("unmute") + .setDescription("(DEPRECATED) Unmute a member in the server with an optional reason") + .setDefaultMemberPermissions(PermissionsBitField.Flags.ModerateMembers) + .addUserOption(option => + option + .setName('target') + .setDescription('The user') + .setRequired(true)) + .addStringOption(option => + option + .setName('reason') + .setDescription('The reason')); + } + + public override async execute(interaction: CommandInteraction) { + if (!interaction.guild || !interaction.guildId) return; + + const targetUser = interaction.options.get('target'); + const reasonInput = interaction.options.get('reason'); + + if (!targetUser || !targetUser.user || !targetUser.member) { + await interaction.reply('Fields are required.'); + return; + } + + const targetMember = targetUser.member as GuildMember; + const reason = reasonInput && reasonInput.value ? reasonInput.value.toString() : "*none*"; + + const logEmbed = new EmbedBuilder() + .setColor(EmbedColours.Ok) + .setTitle("Member Unmuted") + .setDescription(`<@${targetUser.user.id}> \`${targetUser.user.tag}\``) + .setThumbnail(targetUser.user.avatarURL()) + .addFields([ + { + name: "Moderator", + value: `<@${interaction.user.id}>`, + }, + { + name: "Reason", + value: reason, + }, + ]); + + const mutedRoleName = await SettingsHelper.GetSetting('role.muted', interaction.guildId); + + if (!mutedRoleName) { + await interaction.reply('Unable to find configuration. Please contact the bot author.'); + return; + } + + const mutedRole = interaction.guild.roles.cache.find(role => role.name == mutedRoleName); + + if (!mutedRole) { + await interaction.reply('Muted role not found.'); + return; + } + + if (!targetMember.manageable) { + await interaction.reply('Insufficient permissions. Please contact a moderator.'); + return; + } + + await targetMember.roles.remove(mutedRole); + + const channelName = await SettingsHelper.GetSetting('channels.logs.mod', interaction.guildId); + + if (!channelName) return; + + const channel = interaction.guild.channels.cache.find(x => x.name == channelName) as TextChannel; + + if (channel) { + await channel.send({ embeds: [ logEmbed ]}); + } + + await interaction.reply("Please note the mute and unmute commands have been deprecated and will be removed in a future update. Please use timeout instead"); + } +} \ No newline at end of file diff --git a/src/registry.ts b/src/registry.ts index 4414ab2..68428de 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -12,6 +12,7 @@ import Config from "./commands/config"; import Disable from "./commands/disable"; import Ignore from "./commands/ignore"; import Kick from "./commands/kick"; +import Mute from "./commands/mute"; import Poll from "./commands/poll"; import Role from "./commands/Role/role"; import ConfigRole from "./commands/Role/config"; @@ -19,6 +20,7 @@ import Rules from "./commands/rules"; import Say from "./commands/say"; import Setup from "./commands/setup"; import Timeout from "./commands/timeout"; +import Unmute from "./commands/unmute"; import Warn from "./commands/warn"; // Command Imports: MankBot @@ -51,11 +53,13 @@ export default class Registry { CoreClient.RegisterCommand("disable", new Disable()); CoreClient.RegisterCommand("ignore", new Ignore()); CoreClient.RegisterCommand("kick", new Kick()); + CoreClient.RegisterCommand("mute", new Mute()); CoreClient.RegisterCommand("poll", new Poll()); CoreClient.RegisterCommand("rules", new Rules()); CoreClient.RegisterCommand("say", new Say()); CoreClient.RegisterCommand("setup", new Setup()); CoreClient.RegisterCommand("timeout", new Timeout()); + CoreClient.RegisterCommand("unmute", new Unmute()); CoreClient.RegisterCommand("warn", new Warn()); CoreClient.RegisterCommand("role", new Role());