feat: analytics
Node.js CI / Lint and Test (push) Successful in 49s

This commit is contained in:
2025-10-08 08:41:37 -07:00
parent 36ad30e4a2
commit 5cadb9bbee
12 changed files with 77 additions and 34 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ const freeCodeCampSprintChannels: Array<Channel> = [
channelId: "1424801426160488520",
createThread: false,
name: "fsd sprints",
roleId: "1417979684754428054",
roleId: "1425506225453273224",
},
];
+5
View File
@@ -4,6 +4,7 @@
* @author Naomi Carrigan
*/
import { DiscordAnalytics } from "@nhcarrigan/discord-analytics";
import { Client,
GatewayIntentBits,
Events,
@@ -59,10 +60,13 @@ const amari: Amari = {
recentlyActiveChannels: new Set<string>(),
};
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 cacheData(amari);
analytics.startCron();
scheduleJob("post news", "0 * * * *", async() => {
await postFreeCodeCampNews(amari);
await postHackerNews(amari);
@@ -91,6 +95,7 @@ amari.discord.on(Events.MessageCreate, (message) => {
});
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(
+1
View File
@@ -48,4 +48,5 @@ Welcome to our community! It looks like you may have applied for our mentorship
If that is correct, you should ping Naomi to grant your role and begin onboarding! <a:love:1364089736557494353>`,
});
await logger.metric("processed_mentee_join", 1, { user: member.id });
};
+1
View File
@@ -41,4 +41,5 @@ export const logMenteeLeave = async(
It seems they were part of the mentorship programme, so you may need to offboard them.`,
});
await logger.metric("processed_mentee_leave", 1, { user: member.id });
};
+2
View File
@@ -18,6 +18,7 @@ import type { FastifyRequest, FastifyReply } from "fastify";
* @param request - The fastify request payload.
* @param response - The fastify reply class.
*/
// eslint-disable-next-line max-lines-per-function -- only long because of analytics.
export const processFormSubmission = async(
amari: Amari,
// eslint-disable-next-line @typescript-eslint/naming-convention -- Fastify standard.
@@ -67,4 +68,5 @@ export const processFormSubmission = async(
],
flags: [ MessageFlags.IsComponentsV2 ],
});
await logger.metric("processed_form_submission", 1, { table: String(table) });
};
+19 -6
View File
@@ -6,9 +6,11 @@
import { logger } from "../utils/logger.js";
import type { Amari } from "../interfaces/amari.js";
import type { IssueCreated,
import type {
IssueCreated,
PullRequestCreated,
GithubPayload } from "../interfaces/github.js";
GithubPayload,
} from "../interfaces/github.js";
import type { FastifyRequest, FastifyReply } from "fastify";
const isIssue = (body: GithubPayload): body is IssueCreated => {
@@ -44,7 +46,8 @@ export const processGithubEvent = async(
}
const event = request.headers["x-github-event"];
if (typeof event !== "string") {
await response.status(400).
await response.
status(400).
send({ message: "Invalid GitHub event header." });
return;
}
@@ -57,7 +60,7 @@ export const processGithubEvent = async(
if (action === "opened" && event === "issues" && isIssue(request.body)) {
await logger.log("info", "Processing new issue");
const { issue, repository } = request.body;
const { number } = issue;
const { number, user } = issue;
const { owner, name } = repository;
await amari.github.rest.issues.addAssignees({
assignees: [ "naomi-lgbt" ],
@@ -66,12 +69,22 @@ export const processGithubEvent = async(
owner: owner.login,
repo: name,
});
await logger.metric("processed_github_event", 1, {
action: "opened",
event: "issue",
user: user.login,
});
return;
}
if (action === "opened" && event === "pull_request" && isPull(request.body)) {
await logger.log("info", "Processing new PR");
const { pull_request: pr, repository } = request.body;
const { number } = pr;
const { number, user } = pr;
await logger.log("info", "Processing new PR");
await logger.metric("processed_github_event", 1, {
action: "opened",
event: "pull_request",
user: user.login,
});
const { owner, name } = repository;
await amari.github.rest.pulls.requestReviewers({
owner: owner.login,
+9 -3
View File
@@ -22,12 +22,15 @@ export const processMentorshipRole = async(
oldMember: GuildMember | PartialGuildMember,
updatedMember: GuildMember,
): Promise<void> => {
if (oldMember.roles.cache.has(ids.roles.mentorship)
|| !updatedMember.roles.cache.has(ids.roles.mentorship)) {
if (
oldMember.roles.cache.has(ids.roles.mentorship)
|| !updatedMember.roles.cache.has(ids.roles.mentorship)
) {
return;
}
const channel = amari.discord.channels.cache.get(ids.channels.menteeChat)
const channel
= amari.discord.channels.cache.get(ids.channels.menteeChat)
?? await amari.discord.channels.fetch(ids.channels.menteeChat);
if (channel?.isSendable() !== true) {
@@ -49,4 +52,7 @@ Once you have done this, your next step is to read our [wiki](<https://nhcarriga
Naomi will follow up with you from there! Best of luck on your journey~! <a:love:1364089736557494353>`,
});
await logger.metric("processed_mentorship_role", 1, {
user: updatedMember.id,
});
};
+1
View File
@@ -48,6 +48,7 @@ export const processUserGuildTag = async(
&& member.roles.cache.has(ids.roles.representing)) {
await member.roles.remove(ids.roles.representing);
}
await logger.metric("processed_guild_tag", 1, { user: user.id });
} catch (error) {
if (error instanceof Error) {
await logger.error("process user guild tag module", error);
+1
View File
@@ -34,6 +34,7 @@ export const respondToDm = async(
await message.reply({
content: responses.dm,
});
await logger.metric("processed_dm", 1, { user: author.id });
} catch (error) {
if (error instanceof Error) {
await logger.error("respond to DM module", error);
+15 -18
View File
@@ -31,34 +31,31 @@ export const respondToMention = async(
if (amari.recentlyActiveChannels.has(channel.id)) {
return;
}
if (mentions.has(ids.users.naomi, {
const mentionsNaomi = mentions.has(ids.users.naomi, {
ignoreEveryone: true,
ignoreRepliedUser: true,
ignoreRoles: true,
}) || /naomi/i.test(content)) {
await naomi.send(
{
components: getComponentsForNaomi(author, content, url),
flags: [ MessageFlags.IsComponentsV2 ],
},
);
return;
}
if (mentions.has(ids.roles.nhcarrigan, {
}) || /naomi/i.test(content);
const mentionsNHCarrigan = mentions.has(ids.roles.nhcarrigan, {
ignoreEveryone: true,
ignoreRepliedUser: true,
}) || mentions.has(ids.users.nhcarrigan, {
ignoreEveryone: true,
ignoreRepliedUser: true,
ignoreRoles: true,
}) || /nhcarrigan/i.test(content)) {
await naomi.send(
{
components: getComponentsForNaomi(author, content, url),
flags: [ MessageFlags.IsComponentsV2 ],
},
);
}) || /nhcarrigan/i.test(content);
if (!mentionsNaomi && !mentionsNHCarrigan) {
return;
}
await naomi.send(
{
components: getComponentsForNaomi(author, content, url),
flags: [ MessageFlags.IsComponentsV2 ],
},
);
await logger.metric("processed_mention", 1, { pingType: mentionsNaomi
? "naomi"
: "nhcarrigan", user: author.id });
} catch (error) {
if (error instanceof Error) {
await logger.error("respond to mention module", error);