From 53274ec38cbf1708f03c0ca7d38a1aea5622b012 Mon Sep 17 00:00:00 2001 From: Naomi Carrigan Date: Tue, 9 Dec 2025 12:24:55 -0800 Subject: [PATCH] feat: auto-tag the new community fora --- src/config/ids.ts | 10 +++++ src/index.ts | 78 +++++++++++++++++++++++++----------- src/modules/getForumTagId.ts | 28 +++++++++++++ 3 files changed, 93 insertions(+), 23 deletions(-) create mode 100644 src/modules/getForumTagId.ts diff --git a/src/config/ids.ts b/src/config/ids.ts index d33c742..7e903b0 100644 --- a/src/config/ids.ts +++ b/src/config/ids.ts @@ -6,6 +6,9 @@ export const ids = { channels: { + bugReports: "1447723804330823763", + communityFeedback: "1447726591189975210", + featureRequests: "1447726510369931295", formSubmissions: "1410435042898874471", gaming: "1385797656307175468", general: "1385797320389431336", @@ -14,6 +17,7 @@ export const ids = { mentorshipProjectForum: "1400616702265266186", naomiDiscussionForum: "1408154690121633917", news: "1407804798677418198", + policyIdeation: "1417294974046965842", resumeReviewForum: "1407807555266154496", }, guilds: { @@ -41,6 +45,12 @@ export const ids = { member: "1407807699718111292", naomi: "1407807752549699727", }, + unanswered: { + bugReports: "1447726213446500555", + communityFeedback: "1447726807595094036", + featureRequests: "1447726899919978677", + policyIdeation: "1447755602318196828", + }, }, users: { amari: "1406431359345496255", diff --git a/src/index.ts b/src/index.ts index 44821bd..312ffeb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,23 +5,23 @@ */ import { DiscordAnalytics } from "@nhcarrigan/discord-analytics"; -import { Client, +import { + Client, GatewayIntentBits, Events, Partials, - MessageFlags } from "discord.js"; + MessageFlags, +} from "discord.js"; import { scheduleJob } from "node-schedule"; import { App } from "octokit"; import { ids } from "./config/ids.js"; import { handleMessageCreate } from "./events/handleMessageCreate.js"; import { cacheData } from "./modules/cacheData.js"; import { checkRetroAchievements } from "./modules/checkAchievements.js"; +import { getForumTagId } from "./modules/getForumTagId.js"; import { logMenteeJoin } from "./modules/logMenteeJoin.js"; import { logMenteeLeave } from "./modules/logMenteeLeave.js"; -import { - postFreeCodeCampNews, - postHackerNews, -} from "./modules/postNews.js"; +import { postFreeCodeCampNews, postHackerNews } from "./modules/postNews.js"; import { postProgressReminders } from "./modules/postProgressReminders.js"; import { processMentorshipRole } from "./modules/processMentorshipRole.js"; import { processUserGuildTag } from "./modules/processUserGuildTag.js"; @@ -30,8 +30,10 @@ import { instantiateServer } from "./server/serve.js"; import { logger } from "./utils/logger.js"; import type { Amari } from "./interfaces/amari.js"; -if (process.env.GH_CLIENT_ID === undefined - || process.env.GH_PRIVATE_KEY === undefined) { +if ( + process.env.GH_CLIENT_ID === undefined + || process.env.GH_PRIVATE_KEY === undefined +) { throw new Error("Cannot initialise GitHub!"); } @@ -41,17 +43,22 @@ const githubApp = new App({ }); const octokit = await githubApp.getInstallationOctokit(83_119_105); const { data } = await octokit.rest.apps.getAuthenticated(); -await logger.log("debug", `Authenticated to GitHub as ${data?.name ?? "unknown"}`); +await logger.log( + "debug", + `Authenticated to GitHub as ${data?.name ?? "unknown"}`, +); const amari: Amari = { - discord: new Client({ intents: [ - GatewayIntentBits.Guilds, - GatewayIntentBits.GuildMessages, - GatewayIntentBits.MessageContent, - GatewayIntentBits.GuildMembers, - GatewayIntentBits.DirectMessages, - ], - partials: [ Partials.Channel ] }), + discord: new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.MessageContent, + GatewayIntentBits.GuildMembers, + GatewayIntentBits.DirectMessages, + ], + partials: [ Partials.Channel ], + }), github: octokit, lastRssItems: { freeCodeCamp: null, @@ -63,8 +70,10 @@ const amari: Amari = { const analytics = new DiscordAnalytics(amari.discord, logger); amari.discord.once(Events.ClientReady, () => { - void logger.log("debug", - `Authenticated to Discord as ${amari.discord.user?.username ?? "unknown"}`); + void logger.log( + "debug", + `Authenticated to Discord as ${amari.discord.user?.username ?? "unknown"}`, + ); void cacheData(amari); analytics.startCron(); scheduleJob("post news", "0 * * * *", async() => { @@ -98,10 +107,10 @@ amari.discord.on(Events.InteractionCreate, (interaction) => { void analytics.logGatewayEvent(Events.InteractionCreate, { ...interaction }); if (interaction.isButton() && interaction.customId === "resolve") { if (interaction.user.id !== ids.users.naomi) { - return void interaction.reply( - { content: "Who are you????", - flags: [ MessageFlags.Ephemeral ] }, - ); + return void interaction.reply({ + content: "Who are you????", + flags: [ MessageFlags.Ephemeral ], + }); } return void interaction.message.delete(); } @@ -114,6 +123,29 @@ amari.discord.on(Events.InteractionCreate, (interaction) => { }); }); +amari.discord.on(Events.ThreadCreate, (thread) => { + if (thread.parent?.isThreadOnly() !== true) { + return; + } + const { bugReports, communityFeedback, featureRequests, policyIdeation } + = ids.channels; + if ( + ![ bugReports, + communityFeedback, + featureRequests, + policyIdeation ].includes( + thread.parent.id, + ) + ) { + return; + } + const tagId = getForumTagId(thread.parent.id); + if (tagId === null) { + return; + } + void thread.setAppliedTags([ tagId ]); +}); + amari.discord.on(Events.UserUpdate, (_oldUser, updatedUser) => { void processUserGuildTag(amari, updatedUser); }); diff --git a/src/modules/getForumTagId.ts b/src/modules/getForumTagId.ts new file mode 100644 index 0000000..b2b2631 --- /dev/null +++ b/src/modules/getForumTagId.ts @@ -0,0 +1,28 @@ +/** + * @copyright NHCarrigan + * @license Naomi's Public License + * @author Naomi Carrigan + */ + +import { ids } from "../config/ids.js"; + +/** + * Grabs the "unanswered" tag ID for a given forum channel ID. + * @param id - The ID of the forum channel. + * @returns The ID of the "unanswered" tag, or null if not found. + */ +export const getForumTagId = (id: string): string | null => { + if (id === ids.channels.bugReports) { + return ids.tags.unanswered.bugReports; + } + if (id === ids.channels.communityFeedback) { + return ids.tags.unanswered.communityFeedback; + } + if (id === ids.channels.featureRequests) { + return ids.tags.unanswered.featureRequests; + } + if (id === ids.channels.policyIdeation) { + return ids.tags.unanswered.policyIdeation; + } + return null; +};