generated from nhcarrigan/template
feat: add analytics and logging, log interactions
Node.js CI / Lint and Test (push) Failing after 40s
Node.js CI / Lint and Test (push) Failing after 40s
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user