diff options
Diffstat (limited to 'src/lib/common/autoMod.ts')
-rw-r--r-- | src/lib/common/autoMod.ts | 246 |
1 files changed, 0 insertions, 246 deletions
diff --git a/src/lib/common/autoMod.ts b/src/lib/common/autoMod.ts deleted file mode 100644 index 312beb3..0000000 --- a/src/lib/common/autoMod.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { GuildMember, MessageActionRow, MessageButton, MessageEmbed, TextChannel } from 'discord.js'; -import badLinksArray from '../badlinks'; -import badLinksSecretArray from '../badlinks-secret'; // I cannot make this public so just make a new file that export defaults an empty array -import badWords from '../badwords'; -import { BushButtonInteraction } from '../extensions/discord.js/BushButtonInteraction'; -import { BushMessage } from '../extensions/discord.js/BushMessage'; -import { Moderation } from './Moderation'; - -export class AutoMod { - private message: BushMessage; - - public constructor(message: BushMessage) { - this.message = message; - if (message.author.id === client.user?.id) return; - void this.handle(); - } - - private async handle(): Promise<void> { - if (this.message.channel.type === 'DM' || !this.message.guild) return; - if (!(await this.message.guild.hasFeature('automod'))) return; - - const customAutomodPhrases = (await this.message.guild.getSetting('autoModPhases')) ?? {}; - const badLinks: BadWords = {}; - - const uniqueLinks = [...new Set([...badLinksArray, ...badLinksSecretArray])]; - - uniqueLinks.forEach((link) => { - badLinks[link] = { - severity: Severity.PERM_MUTE, - ignoreSpaces: true, - ignoreCapitalization: true, - reason: 'malicious link' - }; - }); - - const result = { - ...this.checkWords(customAutomodPhrases), - ...this.checkWords((await this.message.guild.hasFeature('excludeDefaultAutomod')) ? {} : badWords), - ...this.checkWords((await this.message.guild.hasFeature('excludeAutomodScamLinks')) ? {} : badLinks) - }; - - if (Object.keys(result).length === 0) return; - - const highestOffence = Object.entries(result) - .map(([key, value]) => ({ word: key, ...value })) - .sort((a, b) => b.severity - a.severity)[0]; - - if (highestOffence.severity === undefined || highestOffence.severity === null) - void this.message.guild.sendLogChannel('error', { - embeds: [ - { - title: 'AutoMod Error', - description: `Unable to find severity information for ${util.format.inlineCode(highestOffence.word)}`, - color: util.colors.error - } - ] - }); - else { - const color = this.punish(highestOffence); - void this.log(highestOffence, color, result); - } - } - - private checkWords(words: BadWords): BadWords { - if (Object.keys(words).length === 0) return {}; - - const matchedWords: BadWords = {}; - for (const word in words) { - const wordOptions = words[word]; - if (this.format(this.message.content, wordOptions).includes(this.format(word, wordOptions))) { - matchedWords[word] = wordOptions; - } - } - return matchedWords; - } - - private format(string: string, wordOptions: BadWordDetails) { - const temp = wordOptions.ignoreCapitalization ? string.toLowerCase() : string; - return wordOptions.ignoreSpaces ? temp.replace(/ /g, '') : temp; - } - - private punish(highestOffence: BadWordDetails & { word: string }) { - let color; - switch (highestOffence.severity) { - case Severity.DELETE: { - color = util.colors.lightGray; - void this.message.delete().catch((e) => deleteError.bind(this, e)); - break; - } - case Severity.WARN: { - color = util.colors.yellow; - void this.message.delete().catch((e) => deleteError.bind(this, e)); - void this.message.member?.warn({ - moderator: this.message.guild!.me!, - reason: `[AutoMod] ${highestOffence.reason}` - }); - break; - } - case Severity.TEMP_MUTE: { - color = util.colors.orange; - void this.message.delete().catch((e) => deleteError.bind(this, e)); - void this.message.member?.mute({ - moderator: this.message.guild!.me!, - reason: `[AutoMod] ${highestOffence.reason}`, - duration: 900_000 // 15 minutes - }); - break; - } - case Severity.PERM_MUTE: { - color = util.colors.red; - void this.message.delete().catch((e) => deleteError.bind(this, e)); - void this.message.member?.mute({ - moderator: this.message.guild!.me!, - reason: `[AutoMod] ${highestOffence.reason}`, - duration: 0 // permanent - }); - break; - } - default: { - throw new Error(`Invalid severity: ${highestOffence.severity}`); - } - } - - return color; - - async function deleteError(this: AutoMod, e: Error | any) { - this.message.guild?.sendLogChannel('error', { - embeds: [ - { - title: 'AutoMod Error', - description: `Unable to delete triggered message.`, - fields: [{ name: 'Error', value: await util.codeblock(`${e.stack ?? e}`, 1024, 'js', true) }], - color: util.colors.error - } - ] - }); - } - } - - private async log(highestOffence: BadWordDetails & { word: string }, color: `#${string}`, offences: BadWords) { - void client.console.info( - 'autoMod', - `Severity <<${highestOffence.severity}>> action performed on <<${this.message.author.tag}>> (<<${ - this.message.author.id - }>>) in <<#${(this.message.channel as TextChannel).name}>> in <<${this.message.guild!.name}>>` - ); - - return await this.message.guild!.sendLogChannel('automod', { - embeds: [ - new MessageEmbed() - .setTitle(`[Severity ${highestOffence.severity}] Automod Action Performed`) - .setDescription( - `**User:** ${this.message.author} (${this.message.author.tag})\n**Sent From**: <#${ - this.message.channel.id - }> [Jump to context](${this.message.url})\n**Blacklisted Words:** ${Object.keys(offences) - .map((key) => `\`${key}\``) - .join(', ')}` - ) - .addField('Message Content', `${await util.codeblock(this.message.content, 1024)}`) - .setColor(color) - .setTimestamp() - ], - components: - highestOffence.severity >= 2 - ? [ - new MessageActionRow().addComponents( - new MessageButton() - .setStyle('DANGER') - .setLabel('Ban User') - .setCustomId(`automod;ban;${this.message.author.id};${highestOffence.reason}`) - ) - ] - : undefined - }); - } - - public static async handleInteraction(interaction: BushButtonInteraction) { - if (!interaction.memberPermissions?.has('BAN_MEMBERS')) - return interaction.reply({ - content: `${util.emojis.error} You are missing the **Ban Members** permission.`, - ephemeral: true - }); - const [action, userId, reason] = interaction.customId.replace('automod;', '').split(';'); - switch (action) { - case 'ban': { - const victim = await interaction.guild!.members.fetch(userId); - const moderator = - interaction.member instanceof GuildMember - ? interaction.member - : await interaction.guild!.members.fetch(interaction.user.id); - - const check = victim ? await Moderation.permissionCheck(moderator, victim, 'ban', true) : true; - - if (check !== true) - return interaction.reply({ - content: check, - ephemeral: true - }); - - const result = await interaction.guild?.bushBan({ - user: userId, - reason, - moderator: interaction.user.id, - evidence: (interaction.message as BushMessage).url ?? undefined - }); - - if (result === 'success') - return interaction.reply({ - content: `${util.emojis.success} Successfully banned **${ - interaction.guild?.members.cache.get(userId)?.user.tag ?? userId - }**.`, - ephemeral: true - }); - else - return interaction.reply({ - content: `${util.emojis.error} Could not ban **${ - interaction.guild?.members.cache.get(userId)?.user.tag ?? userId - }**: \`${result}\` .`, - ephemeral: true - }); - } - } - } -} - -export const enum Severity { - /** Delete message */ - DELETE, - /** Delete message and warn user */ - WARN, - /** Delete message and mute user for 15 minutes */ - TEMP_MUTE, - /** Delete message and mute user permanently */ - PERM_MUTE -} - -interface BadWordDetails { - severity: Severity; - ignoreSpaces: boolean; - ignoreCapitalization: boolean; - reason: string; -} - -export interface BadWords { - [key: string]: BadWordDetails; -} |