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 = {
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",
+49 -17
View File
@@ -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: [
discord: new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.DirectMessages,
],
partials: [ Partials.Channel ] }),
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);
});
+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;
};