aboutsummaryrefslogtreecommitdiff
path: root/src/lib/common/autoMod.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/common/autoMod.ts')
-rw-r--r--src/lib/common/autoMod.ts246
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;
-}