Files
hikari/bot/src/events/messageCreate.ts
T
naomi 5bd6e03a8d
Node.js CI / Lint and Test (push) Successful in 1m39s
feat: add analytics, fix mcp logic
2025-10-09 20:36:39 -07:00

140 lines
5.0 KiB
TypeScript

/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { ai } from "../modules/ai.js";
import {
checkGuildEntitlement,
checkUserEntitlement,
} from "../utils/checkEntitlement.js";
import { errorHandler } from "../utils/errorHandler.js";
import { logger } from "../utils/logger.js";
import type { Client, Message, OmitPartialGroupDMChannel } from "discord.js";
/**
* Handles the creation of a message in Discord. If Hikari is mentioned in the message,
* trigger a response.
* @param hikari - Hikari's Discord instance.
* @param message - The message payload from Discord.
*/
// eslint-disable-next-line max-lines-per-function, complexity -- This function is large, but it handles a lot of logic.
const guildMessageCreate = async(
hikari: Client,
message: Message<true>,
): Promise<void> => {
try {
if (
!hikari.user
|| !message.mentions.has(hikari.user.id, {
ignoreEveryone: true,
ignoreRoles: true,
})
|| message.author.bot
) {
return;
}
await message.channel.sendTyping();
const hasSubscription = await checkGuildEntitlement(hikari, message.guild);
if (!hasSubscription) {
await message.reply({
content:
// eslint-disable-next-line stylistic/max-len -- Big boi string.
"Your server is not currently subscribed to use this service. Unfortunately, due to Discord restrictions, we cannot offer server subscriptions just yet. We are hard at work on our own payment system, so stay tuned! Until then, you can subscribe as a user and ask questions by DMing me directly!",
});
return;
}
if (!message.channel.isThread()) {
const thread = await message.startThread({
autoArchiveDuration: 60,
name: `Thread for ${message.author.username}`,
});
// Wait five seconds for the thread to be created
await new Promise((resolve) => {
// eslint-disable-next-line no-promise-executor-return -- We want to wait for a bit.
return setTimeout(resolve, 5000);
});
await ai(
hikari,
[ message ],
message.member?.nickname ?? message.author.displayName,
thread,
);
await logger.metric("guild_message", 1, {
guild: message.guild.id,
});
return;
}
const previousMessages = await message.channel.messages.fetch({
limit: 100,
});
await ai(
hikari,
[ ...previousMessages.values() ],
message.member?.nickname ?? message.author.displayName,
message.channel,
);
await logger.metric("thread_message", 1, {
guild: message.guild.id,
});
} catch (error) {
const id = await errorHandler(error, "message create event");
await message.reply({
content: `Something went wrong while processing your request. Please try again later, or [reach out in our support channel](<https://discord.com/channels/1354624415861833870/1385797209706201198>).\n-# ${id}`,
});
}
};
/**
* Processes the creation of a direct message in Discord.
* @param hikari - Hikari's Discord instance.
* @param message - The message payload from Discord.
*/
const directMessageCreate = async(
hikari: Client,
message: OmitPartialGroupDMChannel<Message>,
): Promise<void> => {
try {
if (message.author.bot || message.content === "<Clear History>") {
// Ignore bot messages and the clear history message
return;
}
await message.channel.sendTyping();
const hasSubscription = await checkUserEntitlement(hikari, message.author);
if (!hasSubscription) {
await message.reply({
content:
// eslint-disable-next-line stylistic/max-len -- Big boi string.
"You are not currently subscribed to use this service. Please note that a user subscription is NOT the same as a server subscription.",
});
return;
}
const historyRequest = await message.channel.messages.fetch({ limit: 100 });
const history = [ ...historyRequest.values() ];
const clearMessageIndex = history.findIndex((messageInner) => {
return messageInner.content === "<Clear History>";
});
if (clearMessageIndex !== -1) {
// Remove the clear message and everything sent before it, which means everything after in the array because the array is backwards
history.splice(clearMessageIndex, history.length - clearMessageIndex);
}
await ai(
hikari,
history.reverse(),
message.member?.nickname ?? message.author.displayName,
message.channel,
);
await logger.metric("direct_message", 1, {
user: message.author.id,
});
} catch (error) {
const id = await errorHandler(error, "message create event");
await message.reply({
content: `Something went wrong while processing your request. Please try again later, or [reach out in our support channel](<https://discord.com/channels/1354624415861833870/1385797209706201198>).\n-# ${id}`,
});
}
};
export { guildMessageCreate, directMessageCreate };