diff --git a/src/features/autodelete-spam.ts b/src/features/autodelete-spam.ts index 057900f3..3be428a9 100644 --- a/src/features/autodelete-spam.ts +++ b/src/features/autodelete-spam.ts @@ -1,9 +1,11 @@ import { ChannelHandlers } from "../types"; import { isStaff } from "../helpers/discord"; +import { simplifyString } from "../helpers/modLog"; +import { sleep } from "../helpers/misc"; -const spamKeywords = ["discord", "nitro", "steam", "free", "gift", "airdrop"]; +const spamKeywords = ["nitro", "steam", "free", "gift", "airdrop"]; -const safeKeywords = ["hiring", "remote", "onsite"]; +const safeKeywords = ["forhire", "hiring", "remote", "onsite"]; const safeDomains = [ "https://discord.com", @@ -18,11 +20,6 @@ const safeDomains = [ const checkWords = (message: string, wordList: string[]) => message.split(/\b/).some((word) => wordList.includes(word.toLowerCase())); -const atLeast = - (count: number) => - (...bools: boolean[]) => - bools.filter(Boolean).length >= count; - const autodelete: ChannelHandlers = { handleMessage: async ({ msg: maybeMessage }) => { if (isStaff(maybeMessage.member)) return; @@ -30,27 +27,50 @@ const autodelete: ChannelHandlers = { const msg = maybeMessage.partial ? await maybeMessage.fetch() : maybeMessage; + if (!msg.guild) return; const msgHasPingKeywords = ["@everyone", "@here"].some((pingKeyword) => msg.content.includes(pingKeyword), ); - const msgHasSpamKeywords = checkWords(msg.content, spamKeywords); + if (msgHasPingKeywords) { + msg + .reply({ + embeds: [ + { + title: "Tsk tsk.", + description: `Please do **not** try to use \`@here\` or \`@everyone\` - there are ${msg.guild.memberCount} members in Reactiflux. Everybody here is a volunteer, and somebody will respond when they can.`, + color: "#BA0C2F", + }, + ], + }) + .then(async (tsk) => { + await sleep(15); + tsk.delete(); + }); + } + + const content = simplifyString(msg.content); + const words = content.split(" "); + const msgSpamKeywords = words + .map((word) => spamKeywords.includes(word)) + .filter(Boolean); - const msgHasNoSafeKeywords = !checkWords(msg.content, safeKeywords); + const msgHasSafeKeywords = checkWords(msg.content, safeKeywords); const msgHasLink = msg.content.includes("http") && !safeDomains.some((domain) => msg.content.includes(domain)); - if ( - atLeast(3)( - msgHasPingKeywords, - msgHasSpamKeywords, - msgHasNoSafeKeywords, - msgHasLink, - ) - ) { + const spamScore = + Number(msgHasLink) + + msgSpamKeywords.length + + // Pinging everyone is always treated as spam + Number(msgHasPingKeywords) * 5 - + // If it's a job post, then it's probably not spam + Number(msgHasSafeKeywords) * 10; + + if (spamScore > 3) { await msg.react("💩"); } }, diff --git a/src/features/autothread.ts b/src/features/autothread.ts index 4886bd95..a96c2742 100644 --- a/src/features/autothread.ts +++ b/src/features/autothread.ts @@ -1,5 +1,5 @@ import { differenceInHours, format } from "date-fns"; -import { Client, Message, PartialMessage } from "discord.js"; +import { Client } from "discord.js"; import { CHANNELS } from "../constants"; import { constructDiscordLink, diff --git a/src/features/commands.ts b/src/features/commands.ts index 6b4c1676..42fedcbc 100644 --- a/src/features/commands.ts +++ b/src/features/commands.ts @@ -4,7 +4,6 @@ import { Message, TextChannel } from "discord.js"; import cooldown from "./cooldown"; import { ChannelHandlers } from "../types"; import { isStaff } from "../helpers/discord"; -import { sleep } from "../helpers/misc"; export const EMBED_COLOR = 7506394; @@ -637,38 +636,6 @@ Instead: }); }, }, - { - words: ["@here", "@everyone"], - help: "", - category: "Communication", - cooldown: 0, - handleMessage: async (msg) => { - if (!msg || !msg.guild) { - return; - } - - const member = await msg.guild.members.fetch(msg.author.id); - - if (!member || isStaff(member)) { - return; - } - - await msg.react("💩"); - - const tsk = await msg.reply({ - embeds: [ - { - title: "Tsk tsk.", - description: `Please do **not** try to use \`@here\` or \`@everyone\` - there are ${msg.guild.memberCount} members in Reactiflux. Everybody here is a volunteer, and somebody will respond when they can.`, - color: "#BA0C2F", - }, - ], - }); - await msg.delete(); - await sleep(120); - await tsk.delete(); - }, - }, { words: ["!lock"], help: "", diff --git a/src/features/emojiMod.ts b/src/features/emojiMod.ts index a2b1a7e6..57bbef56 100644 --- a/src/features/emojiMod.ts +++ b/src/features/emojiMod.ts @@ -195,7 +195,7 @@ Thanks! const emojiMod: ChannelHandlers = { handleReaction: async ({ reaction, user, bot }) => { - const { message, users } = reaction; + const { message } = reaction; const { author, guild } = message; if (!guild || !author || author?.id === bot.user?.id) { diff --git a/src/helpers/modLog.ts b/src/helpers/modLog.ts index efbd2d99..053988fd 100644 --- a/src/helpers/modLog.ts +++ b/src/helpers/modLog.ts @@ -17,7 +17,7 @@ const NORMALIZED_CODEPOINTS = /[\u0300-\u036f]/g; const EMOJI_RANGE = /[\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF]/g; const SPECIAL_CHARACTERS = - /[\s≤≥¯˘÷¿…“”‘’«»–—≠±ºª•¶§∞¢£™¡`~`∑´®†¨ˆØ∏\-=_+<>?,./;':"[\]\\{}|!@#$%^&*()]/g; + /[≤≥¯˘÷¿…“”‘’«»–—≠±ºª•¶§∞¢£™¡`~`∑´®†¨ˆØ∏\-=_<>,;'"[\]\\{}|!@#$%^*()]/g; export const simplifyString = (s: string) => s .toLowerCase()