From eb4eab2fb1366996d134fd19e4a2f1b1f3af3999 Mon Sep 17 00:00:00 2001 From: GramingFoxTeam Date: Sun, 13 Aug 2023 18:52:53 +0300 Subject: [PATCH] feat(bot-discord): more support mute features(#19) --- apps/bot-discord/src/commands/ban.js | 2 +- apps/bot-discord/src/commands/exile.js | 6 ++- .../src/commands/exileMemberCtx.js | 28 +++++++++++++ .../src/commands/feedbackDislike.js | 2 +- apps/bot-discord/src/commands/feedbackLike.js | 2 +- apps/bot-discord/src/commands/mute.js | 2 +- apps/bot-discord/src/commands/trainMessage.js | 2 +- apps/bot-discord/src/commands/unban.js | 2 +- apps/bot-discord/src/commands/unexile.js | 2 +- apps/bot-discord/src/commands/unmute.js | 4 +- apps/bot-discord/src/config.example.json | 2 +- apps/bot-discord/src/config.json | 2 +- apps/bot-discord/src/events/messageCreate.js | 11 ++++- apps/bot-discord/src/index.js | 18 +++++++++ apps/bot-discord/src/msgCommands/exile.js | 28 +++++++++++++ apps/bot-discord/src/utils/checkModPerms.js | 4 +- .../src/utils/checkSupporterPerms.js | 4 +- .../src/utils/exileMemberToChannel.js | 40 +++++++++++++++++++ apps/bot-discord/src/utils/muteMember.js | 2 +- 19 files changed, 143 insertions(+), 20 deletions(-) create mode 100644 apps/bot-discord/src/commands/exileMemberCtx.js create mode 100644 apps/bot-discord/src/msgCommands/exile.js create mode 100644 apps/bot-discord/src/utils/exileMemberToChannel.js diff --git a/apps/bot-discord/src/commands/ban.js b/apps/bot-discord/src/commands/ban.js index 4e0fa16..85bb8c9 100644 --- a/apps/bot-discord/src/commands/ban.js +++ b/apps/bot-discord/src/commands/ban.js @@ -24,7 +24,7 @@ export default { .setDescription('Reason for the ban') ), async execute(_, config, interaction) { - if (checkForPerms(config, interaction.member)) return interaction.reply({ + if (!checkForPerms(config, interaction.member)) return interaction.reply({ epheremal: true, content: 'You don\'t have the required permissions.' }); diff --git a/apps/bot-discord/src/commands/exile.js b/apps/bot-discord/src/commands/exile.js index 30e5bb8..8db04d0 100644 --- a/apps/bot-discord/src/commands/exile.js +++ b/apps/bot-discord/src/commands/exile.js @@ -2,6 +2,7 @@ import { SlashCommandBuilder } from 'discord.js'; import { checkForPerms } from '../utils/checkSupporterPerms.js' import reportToLogs from '../utils/reportToLogs.js'; import muteMember from '../utils/muteMember.js'; +import exileMemberToChannel from '../utils/exileMemberToChannel.js'; export default { data: new SlashCommandBuilder() @@ -21,7 +22,7 @@ export default { .setRequired(true) ), async execute(_, config, interaction) { - if (checkForPerms(config, interaction.member)) return interaction.reply({ + if (!checkForPerms(config, interaction.member)) return interaction.reply({ epheremal: true, content: 'You don\'t have the required permissions.' }); @@ -32,11 +33,12 @@ export default { const reason = interaction.options.getString('reason'); const parsedDuration = await muteMember(config, member, { - duration: config.discord.mute.supportMuteDuration, reason, supportMute: true }); + exileMemberToChannel(member, interaction.channel, null, config, true); + reportToLogs(config, interaction.client, 'muted', null, { reason, actionTo: await client.users.fetch(interaction.options.getString('user')), diff --git a/apps/bot-discord/src/commands/exileMemberCtx.js b/apps/bot-discord/src/commands/exileMemberCtx.js new file mode 100644 index 0000000..b951312 --- /dev/null +++ b/apps/bot-discord/src/commands/exileMemberCtx.js @@ -0,0 +1,28 @@ +import { ContextMenuCommandBuilder, ApplicationCommandType } from 'discord.js'; +import { checkForPerms } from '../utils/checkSupporterPerms.js' +import muteMember from '../utils/muteMember.js'; +import exileMemberToChannel from '../utils/exileMemberToChannel.js'; + +export default { + data: new ContextMenuCommandBuilder() + .setName('Exile Member') + .setType(ApplicationCommandType.Message), + async execute(helper, config, interaction) { + if ( + !checkForPerms(config, interaction.member) + ) + return interaction.reply({ + content: 'You don\'t have the permission to do this.', + ephemeral: true + }); + + const targetMsg = interaction.targetMessage; + muteMember(config, targetMsg.author, { + channel: interaction.channel, + reason: null, + supportMute: true + }); + + exileMemberToChannel(targetMsg.author, interaction.channel, targetMsg.content, config, true); + } +}; diff --git a/apps/bot-discord/src/commands/feedbackDislike.js b/apps/bot-discord/src/commands/feedbackDislike.js index 388fc58..8b9e5ba 100644 --- a/apps/bot-discord/src/commands/feedbackDislike.js +++ b/apps/bot-discord/src/commands/feedbackDislike.js @@ -7,7 +7,7 @@ export default { }, async execute(helper, config, interaction) { if ( - checkForPerms(config, interaction.member) + !checkForPerms(config, interaction.member) ) return interaction.reply({ content: 'You don\'t have the permission to do this.', diff --git a/apps/bot-discord/src/commands/feedbackLike.js b/apps/bot-discord/src/commands/feedbackLike.js index 960bd85..82e5a16 100644 --- a/apps/bot-discord/src/commands/feedbackLike.js +++ b/apps/bot-discord/src/commands/feedbackLike.js @@ -6,7 +6,7 @@ export default { }, async execute(helper, config, interaction) { if ( - checkForPerms(config, interaction.member) + !checkForPerms(config, interaction.member) ) return interaction.reply({ content: 'You don\'t have the permission to do this.', diff --git a/apps/bot-discord/src/commands/mute.js b/apps/bot-discord/src/commands/mute.js index 56b6dba..3304592 100644 --- a/apps/bot-discord/src/commands/mute.js +++ b/apps/bot-discord/src/commands/mute.js @@ -27,7 +27,7 @@ export default { .setRequired(true) ), async execute(_, config, interaction) { - if (checkForPerms(config, interaction.member)) return interaction.reply({ + if (!checkForPerms(config, interaction.member)) return interaction.reply({ epheremal: true, content: 'You don\'t have the required permissions.' }); diff --git a/apps/bot-discord/src/commands/trainMessage.js b/apps/bot-discord/src/commands/trainMessage.js index 1105f7c..988668d 100644 --- a/apps/bot-discord/src/commands/trainMessage.js +++ b/apps/bot-discord/src/commands/trainMessage.js @@ -8,7 +8,7 @@ export default { .setType(ApplicationCommandType.Message), async execute(helper, config, interaction) { if ( - checkForPerms(config, interaction.member) + !checkForPerms(config, interaction.member) ) return interaction.reply({ content: 'You don\'t have the permission to do this.', diff --git a/apps/bot-discord/src/commands/unban.js b/apps/bot-discord/src/commands/unban.js index a9d84bb..65e987c 100644 --- a/apps/bot-discord/src/commands/unban.js +++ b/apps/bot-discord/src/commands/unban.js @@ -14,7 +14,7 @@ export default { .setRequired(true) ), async execute(_, config, interaction) { - if (checkForPerms(config, interaction.member)) return interaction.reply({ + if (!checkForPerms(config, interaction.member)) return interaction.reply({ epheremal: true, content: 'You don\'t have the required permissions.' }); diff --git a/apps/bot-discord/src/commands/unexile.js b/apps/bot-discord/src/commands/unexile.js index e5e71f3..6d0d806 100644 --- a/apps/bot-discord/src/commands/unexile.js +++ b/apps/bot-discord/src/commands/unexile.js @@ -15,7 +15,7 @@ export default { .setRequired(true) ), async execute(_, config, interaction) { - if (checkForPerms(config, interaction.member)) return interaction.reply({ + if (!checkForPerms(config, interaction.member)) return interaction.reply({ epheremal: true, content: 'You don\'t have the required permissions.' }); diff --git a/apps/bot-discord/src/commands/unmute.js b/apps/bot-discord/src/commands/unmute.js index 1d5e63e..b58cfa0 100644 --- a/apps/bot-discord/src/commands/unmute.js +++ b/apps/bot-discord/src/commands/unmute.js @@ -15,7 +15,7 @@ export default { .setRequired(true) ), async execute(_, config, interaction) { - if (checkForPerms(config, interaction.member)) return interaction.reply({ + if (!checkForPerms(config, interaction.member)) return interaction.reply({ epheremal: true, content: 'You don\'t have the required permissions.' }); @@ -24,7 +24,7 @@ export default { const member = interaction.options.getUser('user'); - const isMuted = await unmuteMember(config, member, false); + const isMuted = await unmuteMember(config, member); if (!isMuted) { await interaction.editReply({ diff --git a/apps/bot-discord/src/config.example.json b/apps/bot-discord/src/config.example.json index b0f6250..776855a 100644 --- a/apps/bot-discord/src/config.example.json +++ b/apps/bot-discord/src/config.example.json @@ -29,7 +29,7 @@ ], "supportGiveRoles" : [ - + "1140310515730632814" ], "supportMuteDuration": 600000 } diff --git a/apps/bot-discord/src/config.json b/apps/bot-discord/src/config.json index 634666a..9d37f72 100644 --- a/apps/bot-discord/src/config.json +++ b/apps/bot-discord/src/config.json @@ -29,7 +29,7 @@ ], "supportGiveRoles" : [ - + "1140310515730632814" ], "supportMuteDuration": 600000 } diff --git a/apps/bot-discord/src/events/messageCreate.js b/apps/bot-discord/src/events/messageCreate.js index bd6e88b..3165760 100644 --- a/apps/bot-discord/src/events/messageCreate.js +++ b/apps/bot-discord/src/events/messageCreate.js @@ -4,14 +4,21 @@ export default { name: Events.MessageCreate, once: false, execute(helper, config, msg) { - if (!msg.guild || msg.system || msg.webhookId) return; + if (!msg.guild || msg.system || msg.webhookId || msg.author.bot) return; + if (msg.content.startsWith('?')) { + const [cmd, args] = msg.content.replace('?', '').split(/\s/g); + const command = msg.client.msgCommands.get(cmd); + if (command) { + await command.execute(msg, args, config); + } + } if (msg.member.roles.cache.some(role => role.id === config.discord.ignoreRole)) return; if (config.discord.ignoreChannels.includes(msg.channelId)) return; if (msg.attachments.first() && msg.attachments.first().contentType.startsWith('image')) { helper.scanImage(msg.attachments.first().url, `${msg.channelId}/${msg.id}`); } - if (!msg.content || msg.author.bot) return; + if (!msg.content) return; helper.scanText( msg.content.toLowerCase().replace(/<.*?>/g, ''), `${msg.channelId}/${msg.id}` diff --git a/apps/bot-discord/src/index.js b/apps/bot-discord/src/index.js index 7e0878c..11652cc 100644 --- a/apps/bot-discord/src/index.js +++ b/apps/bot-discord/src/index.js @@ -24,6 +24,7 @@ const client = new Client({ }); client.commands = new Collection(); +client.msgCommands = new Collection(); client.trainingVotes = new Collection(); client.stickiedMessage = null; client.stickiedMessageTimeout = null; @@ -47,6 +48,23 @@ for (const file of commandFiles) { } } +const msgCommandsPath = join(__dirname, 'msgCommands'); +const msgCommandFiles = readdirSync(msgCommandsPath).filter((file) => + file.endsWith('.js') +); + +for (const file of msgCommandFiles) { + const filePath = join(msgCommandsPath, file); + const command = (await import(`file://${filePath}`)).default; + if ('name' in command && 'execute' in command) { + client.msgCommands.set(command.name, command); + } else { + console.log( + `[WARNING] The command at ${filePath} is missing a required "name" or "execute" property.` + ); + } +} + const discordEventsPath = join(__dirname, 'events'); const discordEventFiles = readdirSync(discordEventsPath).filter((file) => file.endsWith('.js') diff --git a/apps/bot-discord/src/msgCommands/exile.js b/apps/bot-discord/src/msgCommands/exile.js new file mode 100644 index 0000000..dda1b04 --- /dev/null +++ b/apps/bot-discord/src/msgCommands/exile.js @@ -0,0 +1,28 @@ +import exileMemberToChannel from '../utils/exileMemberToChannel.js'; +import { checkForPerms } from '../utils/checkSupporterPerms.js' +import muteMember from '../utils/muteMember.js'; + +export default { + name: 'exile', + async execute(msg, args, config) { + if (!checkForPerms(config, message.member)) return msg.reply('You don\'t have the permission to do this.'); + + if (!msg.reference) return msg.reply('You did not reply to anyone!'); + const referencedMsg = await msg.channel.messages.fetch(msg.reference.messageId); + let message = referencedMsg.content; + if (args[0]) { + if (isNaN(args[0])) return msg.reply('The argument you entered is not a number!'); + + const msgsByAuthor = (await msg.channels.fetch({ limit: 50 })).filter( + m => m.author.id === referencedMsg.author.id + ); + message = msgsByAuthor.slice(Number(`-${args[0]}`)); + } + + await muteMember(config, referencedMsg.author, { + supportMute: true + }); + + exileMemberToChannel(referencedMsg.author, msg.channel, message, config, false); + } +} \ No newline at end of file diff --git a/apps/bot-discord/src/utils/checkModPerms.js b/apps/bot-discord/src/utils/checkModPerms.js index d219191..6907adb 100644 --- a/apps/bot-discord/src/utils/checkModPerms.js +++ b/apps/bot-discord/src/utils/checkModPerms.js @@ -1,6 +1,6 @@ export function checkForPerms(config, member) { - for (const role in config.discord.modRoles) { - if (member.roles.cache.get(role)) { + for (const role of config.discord.modRoles) { + if (member.roles.cache.has(role)) { return true; } } diff --git a/apps/bot-discord/src/utils/checkSupporterPerms.js b/apps/bot-discord/src/utils/checkSupporterPerms.js index a5c8daf..6deadd3 100644 --- a/apps/bot-discord/src/utils/checkSupporterPerms.js +++ b/apps/bot-discord/src/utils/checkSupporterPerms.js @@ -1,6 +1,6 @@ export function checkForPerms(config, member) { - for (const role in config.discord.trainRoles) { - if (member.roles.cache.get(role)) { + for (const role of config.discord.trainRoles) { + if (member.roles.cache.has(role)) { return true; } } diff --git a/apps/bot-discord/src/utils/exileMemberToChannel.js b/apps/bot-discord/src/utils/exileMemberToChannel.js new file mode 100644 index 0000000..db6e794 --- /dev/null +++ b/apps/bot-discord/src/utils/exileMemberToChannel.js @@ -0,0 +1,40 @@ +export default async function exileMemberToChannel(member, channel, message, config, isSlash) { + const redirectChannel = await channel.client.channels.fetch(config.discord.supportChannel); + + let messageContent = ''; + if (Array.isArray(message)) { + for (const msg of message) { + messageContent += `${msg.content}\n`; + } + } else if (!message) message = 'No message provided'; + else messageContent = message; + + await redirectChannel.send({ + content: `<@${member.id}>`, + embeds: [ + { + title: '❗ An exiled member appears!', + fields: [ + { + name: 'Their message', + value: messageContent + } + ] + } + ] + }); + + const messageParams = { + content: `<@${member.id}>`, + embeds: [ + { + title: '❗ You have been exiled!', + description: 'This is due to you asking support in non-support channels. Please use the support channel next time.' + } + ] + }; + + if (isSlash) channel.reply(messageParams); + else channel.send(messageParams); + +} \ No newline at end of file diff --git a/apps/bot-discord/src/utils/muteMember.js b/apps/bot-discord/src/utils/muteMember.js index f7bb699..fda341d 100644 --- a/apps/bot-discord/src/utils/muteMember.js +++ b/apps/bot-discord/src/utils/muteMember.js @@ -7,7 +7,7 @@ export default async function muteMember(config, member, { duration, reason, sup let expires; if (supportMute) { - expires = Math.floor((Date.now() + duration) / 1000); + expires = Math.floor((Date.now() + config.mute.supportMuteDuration) / 1000); } else { const parsedDuration = parse(duration); expires = Math.floor((Date.now() + parsedDuration) / 1000);