feat: add analytics and logging, log interactions
Node.js CI / Lint and Test (push) Failing after 40s

This commit is contained in:
2025-10-07 17:59:15 -07:00
parent 8be29449d5
commit d7bc3bca60
6 changed files with 152 additions and 72 deletions
+5
View File
@@ -4,6 +4,7 @@
* @author Naomi Carrigan
*/
import { DiscordAnalytics } from "@nhcarrigan/discord-analytics";
import {
Client,
GatewayIntentBits,
@@ -22,8 +23,11 @@ const caelia = new Client({
],
});
const analytics = new DiscordAnalytics(caelia, logger);
caelia.once(Events.ClientReady, () => {
void logger.log("debug", `Logged in as ${caelia.user?.username ?? "unknown user"}.`);
analytics.startCron();
});
caelia.on(Events.MessageCreate, (message) => {
@@ -31,6 +35,7 @@ caelia.on(Events.MessageCreate, (message) => {
});
caelia.on(Events.InteractionCreate, (interaction) => {
void analytics.logGatewayEvent(Events.InteractionCreate, { ...interaction });
if (!interaction.isChatInputCommand()) {
return;
}
-66
View File
@@ -1,66 +0,0 @@
/**
* @copyright NHCarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { markdown } from "alex";
import { MessageFlags, type Message } from "discord.js";
import { replaceCodeBlocks, replaceLinks } from "extra-markdown-text";
import { alexConfig } from "../config/alex.js";
import { logger } from "../utils/logger.js";
/**
* Checks if a message contains non-inclusive language. If so,
* provides a suggestion to improve vocabulary.
* @param message -- The message payload from Discord.
*/
export const processMessage = async(message: Message): Promise<void> => {
try {
const { content, author, system } = message;
if (author.bot || system || content.length <= 0) {
return;
}
const noCodeBlocks = replaceCodeBlocks(content, () => {
return "";
});
const noLinks = replaceLinks(noCodeBlocks, () => {
return "";
});
const matches = markdown(noLinks, alexConfig).messages;
if (matches.length === 0) {
return;
}
const responses = matches.map((match) => {
return `- You used the word \`${match.actual ?? "unknown word"}\`. This may not be inclusive language, because: ${match.reason.length > 0
? match.reason
: "I said so."}${[ null, "", undefined, "undefined", "null" ].includes(match.note)
? ""
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Fuck off
: ` -- ${match.note!}`}`;
});
await message.reply({ components: [
{ content: `Hi darling~! It looks like you may have used some language that is not the most inclusive...\n\n${responses.join("\n")}`,
type: 10 },
{
components: [
{
label: "Is this inaccurate? Let us know!",
style: 5,
type: 2,
url: "https://chat.nhcarrigan.com",
},
],
type: 1,
},
],
flags: [ MessageFlags.IsComponentsV2 ] }).catch(() => {
return null;
});
} catch (error) {
if (error instanceof Error) {
await logger.error("process message module", error);
}
}
};
+85
View File
@@ -0,0 +1,85 @@
/**
* @copyright NHCarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { markdown } from "alex";
import { MessageFlags, type Message } from "discord.js";
import { replaceCodeBlocks, replaceLinks } from "extra-markdown-text";
import { alexConfig } from "../config/alex.js";
import { logger } from "../utils/logger.js";
/**
* Checks if a message contains non-inclusive language. If so,
* provides a suggestion to improve vocabulary.
* @param message -- The message payload from Discord.
*/
// eslint-disable-next-line max-lines-per-function -- This function is long but it's not complex.
export const processMessage = async(message: Message): Promise<void> => {
try {
const { content, author, system, guild } = message;
if (author.bot || system || content.length <= 0) {
return;
}
const noCodeBlocks = replaceCodeBlocks(content, () => {
return "";
});
const noLinks = replaceLinks(noCodeBlocks, () => {
return "";
});
const matches = markdown(noLinks, alexConfig).messages;
if (matches.length === 0) {
return;
}
await logger.metric("messages_flagged", 1, {
guild: guild?.id ?? "DM",
user: author.id,
});
const responses = matches.map((match) => {
return `- You used the word \`${
match.actual ?? "unknown word"
}\`. This may not be inclusive language, because: ${
match.reason.length > 0
? match.reason
: "I said so."
}${
[ null, "", undefined, "undefined", "null" ].includes(match.note)
? ""
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Fuck off
: ` -- ${match.note!}`
}`;
});
await message.
reply({
components: [
{
content: `Hi darling~! It looks like you may have used some language that is not the most inclusive...\n\n${responses.join(
"\n",
)}`,
type: 10,
},
{
components: [
{
label: "Is this inaccurate? Let us know!",
style: 5,
type: 2,
url: "https://chat.nhcarrigan.com",
},
],
type: 1,
},
],
flags: [ MessageFlags.IsComponentsV2 ],
}).
catch(() => {
return null;
});
} catch (error) {
if (error instanceof Error) {
await logger.error("process message module", error);
}
}
};