feat: auto-tag the new community fora
Node.js CI / Lint and Test (push) Successful in 1m29s

This commit is contained in:
2025-12-09 12:24:55 -08:00
parent 9ada4b9cbe
commit 53274ec38c
3 changed files with 93 additions and 23 deletions
+10
View File
@@ -6,6 +6,9 @@
export const ids = { export const ids = {
channels: { channels: {
bugReports: "1447723804330823763",
communityFeedback: "1447726591189975210",
featureRequests: "1447726510369931295",
formSubmissions: "1410435042898874471", formSubmissions: "1410435042898874471",
gaming: "1385797656307175468", gaming: "1385797656307175468",
general: "1385797320389431336", general: "1385797320389431336",
@@ -14,6 +17,7 @@ export const ids = {
mentorshipProjectForum: "1400616702265266186", mentorshipProjectForum: "1400616702265266186",
naomiDiscussionForum: "1408154690121633917", naomiDiscussionForum: "1408154690121633917",
news: "1407804798677418198", news: "1407804798677418198",
policyIdeation: "1417294974046965842",
resumeReviewForum: "1407807555266154496", resumeReviewForum: "1407807555266154496",
}, },
guilds: { guilds: {
@@ -41,6 +45,12 @@ export const ids = {
member: "1407807699718111292", member: "1407807699718111292",
naomi: "1407807752549699727", naomi: "1407807752549699727",
}, },
unanswered: {
bugReports: "1447726213446500555",
communityFeedback: "1447726807595094036",
featureRequests: "1447726899919978677",
policyIdeation: "1447755602318196828",
},
}, },
users: { users: {
amari: "1406431359345496255", amari: "1406431359345496255",
+55 -23
View File
@@ -5,23 +5,23 @@
*/ */
import { DiscordAnalytics } from "@nhcarrigan/discord-analytics"; import { DiscordAnalytics } from "@nhcarrigan/discord-analytics";
import { Client, import {
Client,
GatewayIntentBits, GatewayIntentBits,
Events, Events,
Partials, Partials,
MessageFlags } from "discord.js"; MessageFlags,
} from "discord.js";
import { scheduleJob } from "node-schedule"; import { scheduleJob } from "node-schedule";
import { App } from "octokit"; import { App } from "octokit";
import { ids } from "./config/ids.js"; import { ids } from "./config/ids.js";
import { handleMessageCreate } from "./events/handleMessageCreate.js"; import { handleMessageCreate } from "./events/handleMessageCreate.js";
import { cacheData } from "./modules/cacheData.js"; import { cacheData } from "./modules/cacheData.js";
import { checkRetroAchievements } from "./modules/checkAchievements.js"; import { checkRetroAchievements } from "./modules/checkAchievements.js";
import { getForumTagId } from "./modules/getForumTagId.js";
import { logMenteeJoin } from "./modules/logMenteeJoin.js"; import { logMenteeJoin } from "./modules/logMenteeJoin.js";
import { logMenteeLeave } from "./modules/logMenteeLeave.js"; import { logMenteeLeave } from "./modules/logMenteeLeave.js";
import { import { postFreeCodeCampNews, postHackerNews } from "./modules/postNews.js";
postFreeCodeCampNews,
postHackerNews,
} from "./modules/postNews.js";
import { postProgressReminders } from "./modules/postProgressReminders.js"; import { postProgressReminders } from "./modules/postProgressReminders.js";
import { processMentorshipRole } from "./modules/processMentorshipRole.js"; import { processMentorshipRole } from "./modules/processMentorshipRole.js";
import { processUserGuildTag } from "./modules/processUserGuildTag.js"; import { processUserGuildTag } from "./modules/processUserGuildTag.js";
@@ -30,8 +30,10 @@ import { instantiateServer } from "./server/serve.js";
import { logger } from "./utils/logger.js"; import { logger } from "./utils/logger.js";
import type { Amari } from "./interfaces/amari.js"; import type { Amari } from "./interfaces/amari.js";
if (process.env.GH_CLIENT_ID === undefined if (
|| process.env.GH_PRIVATE_KEY === undefined) { process.env.GH_CLIENT_ID === undefined
|| process.env.GH_PRIVATE_KEY === undefined
) {
throw new Error("Cannot initialise GitHub!"); throw new Error("Cannot initialise GitHub!");
} }
@@ -41,17 +43,22 @@ const githubApp = new App({
}); });
const octokit = await githubApp.getInstallationOctokit(83_119_105); const octokit = await githubApp.getInstallationOctokit(83_119_105);
const { data } = await octokit.rest.apps.getAuthenticated(); 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 = { const amari: Amari = {
discord: new Client({ intents: [ discord: new Client({
GatewayIntentBits.Guilds, intents: [
GatewayIntentBits.GuildMessages, GatewayIntentBits.Guilds,
GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMembers, GatewayIntentBits.MessageContent,
GatewayIntentBits.DirectMessages, GatewayIntentBits.GuildMembers,
], GatewayIntentBits.DirectMessages,
partials: [ Partials.Channel ] }), ],
partials: [ Partials.Channel ],
}),
github: octokit, github: octokit,
lastRssItems: { lastRssItems: {
freeCodeCamp: null, freeCodeCamp: null,
@@ -63,8 +70,10 @@ const amari: Amari = {
const analytics = new DiscordAnalytics(amari.discord, logger); const analytics = new DiscordAnalytics(amari.discord, logger);
amari.discord.once(Events.ClientReady, () => { amari.discord.once(Events.ClientReady, () => {
void logger.log("debug", void logger.log(
`Authenticated to Discord as ${amari.discord.user?.username ?? "unknown"}`); "debug",
`Authenticated to Discord as ${amari.discord.user?.username ?? "unknown"}`,
);
void cacheData(amari); void cacheData(amari);
analytics.startCron(); analytics.startCron();
scheduleJob("post news", "0 * * * *", async() => { scheduleJob("post news", "0 * * * *", async() => {
@@ -98,10 +107,10 @@ amari.discord.on(Events.InteractionCreate, (interaction) => {
void analytics.logGatewayEvent(Events.InteractionCreate, { ...interaction }); void analytics.logGatewayEvent(Events.InteractionCreate, { ...interaction });
if (interaction.isButton() && interaction.customId === "resolve") { if (interaction.isButton() && interaction.customId === "resolve") {
if (interaction.user.id !== ids.users.naomi) { if (interaction.user.id !== ids.users.naomi) {
return void interaction.reply( return void interaction.reply({
{ content: "Who are you????", content: "Who are you????",
flags: [ MessageFlags.Ephemeral ] }, flags: [ MessageFlags.Ephemeral ],
); });
} }
return void interaction.message.delete(); 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) => { amari.discord.on(Events.UserUpdate, (_oldUser, updatedUser) => {
void processUserGuildTag(amari, updatedUser); void processUserGuildTag(amari, updatedUser);
}); });
+28
View File
@@ -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;
};