From 1861c17fd95198b5ebe1c5201c47aadf6643f23b Mon Sep 17 00:00:00 2001 From: Simplyalex99 Date: Wed, 11 Jun 2025 11:36:04 -0400 Subject: [PATCH 1/9] update: added more channels --- src/constants/channels.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/constants/channels.ts b/src/constants/channels.ts index a55c99d4..3f45ed3c 100644 --- a/src/constants/channels.ts +++ b/src/constants/channels.ts @@ -2,6 +2,7 @@ import { ChannelType, Client, TextChannel } from "discord.js"; import { guildId, isProd } from "../helpers/env.js"; const LOCAL_CHANNELS: Record = { + introduction: "925847644318879754", helpReact: "926931785219207301", helpThreadsReact: "950790460857794620", helpJs: "950790460857794620", @@ -20,12 +21,25 @@ const LOCAL_CHANNELS: Record = { modLog: "925847644318879754", botLog: "916081991542276096", vcLog: "1237103703740121201", + generalTech: "1166062952084942940", + jobsAdvice: "1166062952084942940", + generalReact: "1166062952084942940", + helpReactNative: "1166062952084942940", + helpStyling: "1166062952084942940", + helpBackend: "1166062952084942940", }; const PRODUCTION_CHANNELS = { + introduction: "306196179538935818", helpReact: "103696749012467712", helpThreadsReact: "902647189120118794", helpJs: "565213527673929729", + generalTech: "102860784329052160", + jobsAdvice: "287623405946011648", + generalReact: "102860784329052160", + helpReactNative: "469170673533583361", + helpStyling: "105765765117935616", + helpBackend: "145170347921113088", random: "103325358643752960", gaming: "509219336175747082", thanks: "798567961468076072", From 01a025f689359670395e539a88ab6f6f206650ed Mon Sep 17 00:00:00 2001 From: Simplyalex99 Date: Wed, 11 Jun 2025 11:37:07 -0400 Subject: [PATCH 2/9] feat: added a job/introduction bot scanner --- src/features/message-scanner.ts | 75 +++++++++++++++++++++++++++++++++ src/index.ts | 15 ++++++- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/features/message-scanner.ts diff --git a/src/features/message-scanner.ts b/src/features/message-scanner.ts new file mode 100644 index 00000000..ac2e6961 --- /dev/null +++ b/src/features/message-scanner.ts @@ -0,0 +1,75 @@ +import type { ChannelHandlers } from "../types/index.d.ts"; +import { EmbedType } from "discord.js"; + +import { CHANNELS } from "../constants/channels.js"; +import { EMBED_COLOR } from "./commands.js"; + +const delayInMilliseconds = 300000; // 5 mins + +const jobKeywords = [ + "looking for work", + "seeking opportunities", + "available for hire", + "open to work", + "freelance available", + "seeking a role", + "looking for projects", + "hire me", + "job opportunities", + "actively seeking", + "available for freelance", + "remote position", + "dm me", + "reach out", + "ready to join", + "new opportunity", + "open position", + "seeking remote", + "available now", + "remote role", + "remote opportunity", + "full-time", + "remote position", + "job opportunities", + "opportunities available", + "new opportunity", + "frontend developer", + "full stack developer", + "software engineer", + "open for", + "β‚Ή", + "$", + "€", +]; + +export const messageScanner: ChannelHandlers = { + handleMessage: async ({ msg }) => { + if (msg.author.bot) return; + + const content = msg.content.toLowerCase(); + + if (content.includes("?") || content.includes("```")) return; + + const containsJobKeyword = jobKeywords.some((keyword) => + content.includes(keyword), + ); + + if (containsJobKeyword) { + const warningMsg = `Oops <@${msg.author.id}>! This message looks more like a job post or intro. Mind sharing that in <#${CHANNELS.jobsLog}> or <#${CHANNELS.introduction}> instead? If this was a mistake, please try again and ask your question. Appreciate you helping us keep channels on-topic πŸ™Œ`; + const sentMsg = await msg.reply({ + embeds: [ + { + title: "Oops! Wrong Channel, Maybe?", + type: EmbedType.Rich, + description: warningMsg, + color: EMBED_COLOR, + }, + ], + }); + await msg.delete(); + setTimeout(() => { + sentMsg.delete().catch(console.error); + }, delayInMilliseconds); + } + }, +}; diff --git a/src/index.ts b/src/index.ts index 25dcb89d..308899a1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,7 +10,7 @@ import { ActivityType, IntentsBitField, } from "discord.js"; - +import { messageScanner } from "./features/message-scanner.js"; import { logger, channelLog } from "./features/log.js"; // import codeblock from './features/codeblock'; import jobsMod, { resetJobCacheCommand } from "./features/jobs-moderation.js"; @@ -205,6 +205,19 @@ addHandler( promotionThread, ); +addHandler( + [ + CHANNELS.helpReact, + CHANNELS.helpJs, + CHANNELS.helpReactNative, + CHANNELS.helpStyling, + CHANNELS.helpBackend, + CHANNELS.generalReact, + CHANNELS.generalTech, + ], + messageScanner, +); + const threadChannels = [CHANNELS.helpJs, CHANNELS.helpThreadsReact]; addHandler(threadChannels, autothread); From 8c5719196fa138ea589a0db25df3124475495d95 Mon Sep 17 00:00:00 2001 From: Simplyalex99 Date: Wed, 11 Jun 2025 12:09:54 -0400 Subject: [PATCH 3/9] update: added more job keywords --- src/features/message-scanner.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/features/message-scanner.ts b/src/features/message-scanner.ts index ac2e6961..b9b70706 100644 --- a/src/features/message-scanner.ts +++ b/src/features/message-scanner.ts @@ -16,6 +16,9 @@ const jobKeywords = [ "looking for projects", "hire me", "job opportunities", + "job offer", + "job opportunity", + "contact me", "actively seeking", "available for freelance", "remote position", From 5cd67b2d963353dccc56ed8391b8766413de1fe9 Mon Sep 17 00:00:00 2001 From: Simplyalex99 Date: Wed, 11 Jun 2025 16:46:02 -0400 Subject: [PATCH 4/9] update: removed job titles keywords and edge case Removed job title keyword to prevent false positives, and to keep the bot solely for job posting related messages rather than intro and job postings. Removed unneeded edge case that could result in false negatives. --- src/features/message-scanner.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/features/message-scanner.ts b/src/features/message-scanner.ts index b9b70706..8bd2fc44 100644 --- a/src/features/message-scanner.ts +++ b/src/features/message-scanner.ts @@ -36,9 +36,6 @@ const jobKeywords = [ "job opportunities", "opportunities available", "new opportunity", - "frontend developer", - "full stack developer", - "software engineer", "open for", "β‚Ή", "$", @@ -51,14 +48,14 @@ export const messageScanner: ChannelHandlers = { const content = msg.content.toLowerCase(); - if (content.includes("?") || content.includes("```")) return; + if (content.includes("```")) return; const containsJobKeyword = jobKeywords.some((keyword) => content.includes(keyword), ); if (containsJobKeyword) { - const warningMsg = `Oops <@${msg.author.id}>! This message looks more like a job post or intro. Mind sharing that in <#${CHANNELS.jobsLog}> or <#${CHANNELS.introduction}> instead? If this was a mistake, please try again and ask your question. Appreciate you helping us keep channels on-topic πŸ™Œ`; + const warningMsg = `Oops <@${msg.author.id}>! This message looks more like a job post or collaboration. Mind sharing that in <#${CHANNELS.jobsLog}> or <#${CHANNELS.lookingForGroup}> instead? If this was a mistake, please try again and ask your question. Appreciate you helping us keep channels on-topic πŸ™Œ`; const sentMsg = await msg.reply({ embeds: [ { From 71f08ae0118efda6051f4d428f4d7eb01b2d3157 Mon Sep 17 00:00:00 2001 From: Simplyalex99 Date: Wed, 11 Jun 2025 16:51:31 -0400 Subject: [PATCH 5/9] update: removed unneeded edge case --- src/features/message-scanner.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/features/message-scanner.ts b/src/features/message-scanner.ts index 8bd2fc44..722b4759 100644 --- a/src/features/message-scanner.ts +++ b/src/features/message-scanner.ts @@ -48,8 +48,6 @@ export const messageScanner: ChannelHandlers = { const content = msg.content.toLowerCase(); - if (content.includes("```")) return; - const containsJobKeyword = jobKeywords.some((keyword) => content.includes(keyword), ); From a2e6162b9f8c215c9ab4547200b1ffdbdfb6c649 Mon Sep 17 00:00:00 2001 From: Simplyalex99 Date: Thu, 12 Jun 2025 11:19:46 -0400 Subject: [PATCH 6/9] update: warning message Added a more helpful feedback in case of job advice related posts using similar keywords such as full time or job opportunity. --- src/features/message-scanner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/message-scanner.ts b/src/features/message-scanner.ts index 722b4759..13868e4a 100644 --- a/src/features/message-scanner.ts +++ b/src/features/message-scanner.ts @@ -53,7 +53,7 @@ export const messageScanner: ChannelHandlers = { ); if (containsJobKeyword) { - const warningMsg = `Oops <@${msg.author.id}>! This message looks more like a job post or collaboration. Mind sharing that in <#${CHANNELS.jobsLog}> or <#${CHANNELS.lookingForGroup}> instead? If this was a mistake, please try again and ask your question. Appreciate you helping us keep channels on-topic πŸ™Œ`; + const warningMsg = `Oops <@${msg.author.id}>! This message looks more like a job/collaboration/advice post. Mind sharing that in <#${CHANNELS.jobsLog}> or <#${CHANNELS.lookingForGroup}> or <#${CHANNELS.jobsAdvice}> instead? If this was a mistake, please try again and ask your question. Appreciate you helping us keep channels on-topic πŸ™Œ`; const sentMsg = await msg.reply({ embeds: [ { From 47d96c4b9d0ddcc652be1d0844ff94002224c546 Mon Sep 17 00:00:00 2001 From: Simplyalex99 Date: Thu, 12 Jun 2025 12:52:50 -0400 Subject: [PATCH 7/9] update: added edge case for langs with dollar sign Added an edge case for code blocks using dollar sign and refactored if statement. --- src/features/message-scanner.ts | 45 +++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/features/message-scanner.ts b/src/features/message-scanner.ts index 13868e4a..d008282c 100644 --- a/src/features/message-scanner.ts +++ b/src/features/message-scanner.ts @@ -41,33 +41,40 @@ const jobKeywords = [ "$", "€", ]; - +const hasCodeBlockWithDollarSign = (content: string): boolean => { + const codeBlockRegex = /```[\s\S]*?\$[\s\S]*?```/g; + return codeBlockRegex.test(content); +}; export const messageScanner: ChannelHandlers = { handleMessage: async ({ msg }) => { if (msg.author.bot) return; const content = msg.content.toLowerCase(); + const ignoreDollar = hasCodeBlockWithDollarSign(content); + + const keywordsToCheck = ignoreDollar + ? jobKeywords.filter((kw) => kw !== "$") + : jobKeywords; - const containsJobKeyword = jobKeywords.some((keyword) => + const containsJobKeyword = keywordsToCheck.some((keyword) => content.includes(keyword), ); + if (!containsJobKeyword) return; - if (containsJobKeyword) { - const warningMsg = `Oops <@${msg.author.id}>! This message looks more like a job/collaboration/advice post. Mind sharing that in <#${CHANNELS.jobsLog}> or <#${CHANNELS.lookingForGroup}> or <#${CHANNELS.jobsAdvice}> instead? If this was a mistake, please try again and ask your question. Appreciate you helping us keep channels on-topic πŸ™Œ`; - const sentMsg = await msg.reply({ - embeds: [ - { - title: "Oops! Wrong Channel, Maybe?", - type: EmbedType.Rich, - description: warningMsg, - color: EMBED_COLOR, - }, - ], - }); - await msg.delete(); - setTimeout(() => { - sentMsg.delete().catch(console.error); - }, delayInMilliseconds); - } + const warningMsg = `Oops <@${msg.author.id}>! This message looks more like a job/collaboration/advice post. Mind sharing that in <#${CHANNELS.jobsLog}> or <#${CHANNELS.lookingForGroup}> or <#${CHANNELS.jobsAdvice}> instead? If this was a mistake, please try again and ask your question. Appreciate you helping us keep channels on-topic πŸ™Œ`; + const sentMsg = await msg.reply({ + embeds: [ + { + title: "Oops! Wrong Channel, Maybe?", + type: EmbedType.Rich, + description: warningMsg, + color: EMBED_COLOR, + }, + ], + }); + await msg.delete(); + setTimeout(() => { + sentMsg.delete().catch(console.error); + }, delayInMilliseconds); }, }; From ee737d8629209a615ac878e9feaef3267d31c97c Mon Sep 17 00:00:00 2001 From: Simplyalex99 Date: Fri, 13 Jun 2025 12:14:56 -0400 Subject: [PATCH 8/9] fix: messages being deleted with partial job keywords rather than full. --- src/features/message-scanner.ts | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/features/message-scanner.ts b/src/features/message-scanner.ts index d008282c..75f165af 100644 --- a/src/features/message-scanner.ts +++ b/src/features/message-scanner.ts @@ -4,8 +4,6 @@ import { EmbedType } from "discord.js"; import { CHANNELS } from "../constants/channels.js"; import { EMBED_COLOR } from "./commands.js"; -const delayInMilliseconds = 300000; // 5 mins - const jobKeywords = [ "looking for work", "seeking opportunities", @@ -37,29 +35,29 @@ const jobKeywords = [ "opportunities available", "new opportunity", "open for", - "β‚Ή", - "$", - "€", + "we’re hiring", + "we are hiring", ]; + +const currencyKeywords = ["β‚Ή", "€", "$"]; const hasCodeBlockWithDollarSign = (content: string): boolean => { const codeBlockRegex = /```[\s\S]*?\$[\s\S]*?```/g; return codeBlockRegex.test(content); }; + export const messageScanner: ChannelHandlers = { handleMessage: async ({ msg }) => { if (msg.author.bot) return; const content = msg.content.toLowerCase(); const ignoreDollar = hasCodeBlockWithDollarSign(content); + const hasCurrencyKeyword = + !ignoreDollar && + currencyKeywords.some((keyword) => content.includes(keyword)); - const keywordsToCheck = ignoreDollar - ? jobKeywords.filter((kw) => kw !== "$") - : jobKeywords; - - const containsJobKeyword = keywordsToCheck.some((keyword) => - content.includes(keyword), - ); - if (!containsJobKeyword) return; + const keywordRegex = new RegExp(`\\b(${jobKeywords.join("|")})\\b`, "i"); + const containsJobKeyword = keywordRegex.test(content); + if (!containsJobKeyword && !hasCurrencyKeyword) return; const warningMsg = `Oops <@${msg.author.id}>! This message looks more like a job/collaboration/advice post. Mind sharing that in <#${CHANNELS.jobsLog}> or <#${CHANNELS.lookingForGroup}> or <#${CHANNELS.jobsAdvice}> instead? If this was a mistake, please try again and ask your question. Appreciate you helping us keep channels on-topic πŸ™Œ`; const sentMsg = await msg.reply({ @@ -75,6 +73,6 @@ export const messageScanner: ChannelHandlers = { await msg.delete(); setTimeout(() => { sentMsg.delete().catch(console.error); - }, delayInMilliseconds); + }, 300_000); }, }; From 3ff72f5f59f28f7a78b5ad5203117169ffb1cad8 Mon Sep 17 00:00:00 2001 From: Simplyalex99 Date: Sat, 14 Jun 2025 13:27:01 -0400 Subject: [PATCH 9/9] fix: removed duplicate job keyword --- src/features/message-scanner.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/features/message-scanner.ts b/src/features/message-scanner.ts index 75f165af..2693a308 100644 --- a/src/features/message-scanner.ts +++ b/src/features/message-scanner.ts @@ -30,7 +30,6 @@ const jobKeywords = [ "remote role", "remote opportunity", "full-time", - "remote position", "job opportunities", "opportunities available", "new opportunity",