generated from nhcarrigan/template
Compare commits
No commits in common. "8c72375761cc696615b8f47131ebc52ad413c7b1" and "4218596559657fb760701c3fcee2e8607ded0f56" have entirely different histories.
8c72375761
...
4218596559
@ -22,7 +22,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anthropic-ai/sdk": "0.36.3",
|
"@anthropic-ai/sdk": "0.36.3",
|
||||||
"@nhcarrigan/logger": "1.0.0",
|
|
||||||
"discord.js": "14.18.0",
|
"discord.js": "14.18.0",
|
||||||
"fastify": "5.2.1",
|
"fastify": "5.2.1",
|
||||||
"winston": "3.17.0"
|
"winston": "3.17.0"
|
||||||
|
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@ -11,9 +11,6 @@ importers:
|
|||||||
'@anthropic-ai/sdk':
|
'@anthropic-ai/sdk':
|
||||||
specifier: 0.36.3
|
specifier: 0.36.3
|
||||||
version: 0.36.3
|
version: 0.36.3
|
||||||
'@nhcarrigan/logger':
|
|
||||||
specifier: 1.0.0
|
|
||||||
version: 1.0.0
|
|
||||||
discord.js:
|
discord.js:
|
||||||
specifier: 14.18.0
|
specifier: 14.18.0
|
||||||
version: 14.18.0
|
version: 14.18.0
|
||||||
@ -350,9 +347,6 @@ packages:
|
|||||||
typescript: '>=5'
|
typescript: '>=5'
|
||||||
vitest: '>=2'
|
vitest: '>=2'
|
||||||
|
|
||||||
'@nhcarrigan/logger@1.0.0':
|
|
||||||
resolution: {integrity: sha512-2e19Bie+ZKb6yKPKjhawqsENkhHatYkvBAmFZx9eToOXdOca+CYi51tldRMtejg6e0+4hOOf2bo5zdBQKmH0dw==}
|
|
||||||
|
|
||||||
'@nhcarrigan/typescript-config@4.0.0':
|
'@nhcarrigan/typescript-config@4.0.0':
|
||||||
resolution: {integrity: sha512-969HVha7A/Sg77fuMwOm6p14a+7C5iE6g55OD71srqwKIgksQl+Ex/hAI/pyzTQFDQ/FBJbpnHlR4Ov25QV/rw==}
|
resolution: {integrity: sha512-969HVha7A/Sg77fuMwOm6p14a+7C5iE6g55OD71srqwKIgksQl+Ex/hAI/pyzTQFDQ/FBJbpnHlR4Ov25QV/rw==}
|
||||||
engines: {node: '20', pnpm: '9'}
|
engines: {node: '20', pnpm: '9'}
|
||||||
@ -2594,8 +2588,6 @@ snapshots:
|
|||||||
- eslint-import-resolver-webpack
|
- eslint-import-resolver-webpack
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@nhcarrigan/logger@1.0.0': {}
|
|
||||||
|
|
||||||
'@nhcarrigan/typescript-config@4.0.0(typescript@5.7.3)':
|
'@nhcarrigan/typescript-config@4.0.0(typescript@5.7.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.7.3
|
typescript: 5.7.3
|
||||||
|
1
prod.env
1
prod.env
@ -1,3 +1,2 @@
|
|||||||
DISCORD_TOKEN="op://Environment Variables - Naomi/Cordelia Taryne/discord_token"
|
DISCORD_TOKEN="op://Environment Variables - Naomi/Cordelia Taryne/discord_token"
|
||||||
AI_TOKEN="op://Environment Variables - Naomi/Cordelia Taryne/ai_token"
|
AI_TOKEN="op://Environment Variables - Naomi/Cordelia Taryne/ai_token"
|
||||||
LOG_TOKEN="op://Environment Variables - Naomi/Alert Server/api_auth"
|
|
||||||
|
12
src/index.ts
12
src/index.ts
@ -12,7 +12,7 @@ import { proofread } from "./modules/proofread.js";
|
|||||||
import { query } from "./modules/query.js";
|
import { query } from "./modules/query.js";
|
||||||
import { summarise } from "./modules/summarise.js";
|
import { summarise } from "./modules/summarise.js";
|
||||||
import { instantiateServer } from "./server/serve.js";
|
import { instantiateServer } from "./server/serve.js";
|
||||||
import { logger } from "./utils/logger.js";
|
import { logHandler } from "./utils/logHandler.js";
|
||||||
|
|
||||||
const commands: Record<
|
const commands: Record<
|
||||||
string,
|
string,
|
||||||
@ -41,16 +41,8 @@ client.on(Events.InteractionCreate, (interaction) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on(Events.EntitlementCreate, (entitlement) => {
|
|
||||||
void logger.log("info", `User ${entitlement.userId} has subscribed!`);
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on(Events.EntitlementDelete, (entitlement) => {
|
|
||||||
void logger.log("info", `User ${entitlement.userId} has unsubscribed... :c`);
|
|
||||||
});
|
|
||||||
|
|
||||||
client.on(Events.ClientReady, () => {
|
client.on(Events.ClientReady, () => {
|
||||||
void logger.log("debug", "Bot is ready.");
|
logHandler.info("Bot is ready.");
|
||||||
});
|
});
|
||||||
|
|
||||||
instantiateServer();
|
instantiateServer();
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
||||||
import { personality } from "../config/personality.js";
|
import { personality } from "../config/personality.js";
|
||||||
import { ai } from "../utils/ai.js";
|
import { ai } from "../utils/ai.js";
|
||||||
import { calculateCost } from "../utils/calculateCost.js";
|
|
||||||
import { isSubscribed } from "../utils/isSubscribed.js";
|
import { isSubscribed } from "../utils/isSubscribed.js";
|
||||||
import type { ImageBlockParam } from "@anthropic-ai/sdk/resources/index.js";
|
import type { ImageBlockParam } from "@anthropic-ai/sdk/resources/index.js";
|
||||||
|
|
||||||
@ -110,7 +109,4 @@ export const alt = async(
|
|||||||
response?.text
|
response?.text
|
||||||
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
||||||
);
|
);
|
||||||
|
|
||||||
const { usage } = messages;
|
|
||||||
await calculateCost(usage, interaction.user.username, "alt-text");
|
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
||||||
import { personality } from "../config/personality.js";
|
import { personality } from "../config/personality.js";
|
||||||
import { ai } from "../utils/ai.js";
|
import { ai } from "../utils/ai.js";
|
||||||
import { calculateCost } from "../utils/calculateCost.js";
|
|
||||||
import { isSubscribed } from "../utils/isSubscribed.js";
|
import { isSubscribed } from "../utils/isSubscribed.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,7 +40,4 @@ export const evaluate = async(
|
|||||||
response?.text
|
response?.text
|
||||||
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
||||||
);
|
);
|
||||||
|
|
||||||
const { usage } = messages;
|
|
||||||
await calculateCost(usage, interaction.user.username, "evaluate");
|
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
||||||
import { personality } from "../config/personality.js";
|
import { personality } from "../config/personality.js";
|
||||||
import { ai } from "../utils/ai.js";
|
import { ai } from "../utils/ai.js";
|
||||||
import { calculateCost } from "../utils/calculateCost.js";
|
|
||||||
import { isSubscribed } from "../utils/isSubscribed.js";
|
import { isSubscribed } from "../utils/isSubscribed.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +41,4 @@ export const mood = async(
|
|||||||
response?.text
|
response?.text
|
||||||
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
||||||
);
|
);
|
||||||
|
|
||||||
const { usage } = messages;
|
|
||||||
await calculateCost(usage, interaction.user.username, "mood");
|
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
||||||
import { personality } from "../config/personality.js";
|
import { personality } from "../config/personality.js";
|
||||||
import { ai } from "../utils/ai.js";
|
import { ai } from "../utils/ai.js";
|
||||||
import { calculateCost } from "../utils/calculateCost.js";
|
|
||||||
import { isSubscribed } from "../utils/isSubscribed.js";
|
import { isSubscribed } from "../utils/isSubscribed.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +41,4 @@ export const proofread = async(
|
|||||||
response?.text
|
response?.text
|
||||||
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
||||||
);
|
);
|
||||||
|
|
||||||
const { usage } = messages;
|
|
||||||
await calculateCost(usage, interaction.user.username, "proofread");
|
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
||||||
import { personality } from "../config/personality.js";
|
import { personality } from "../config/personality.js";
|
||||||
import { ai } from "../utils/ai.js";
|
import { ai } from "../utils/ai.js";
|
||||||
import { calculateCost } from "../utils/calculateCost.js";
|
|
||||||
import { isSubscribed } from "../utils/isSubscribed.js";
|
import { isSubscribed } from "../utils/isSubscribed.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +41,4 @@ export const query = async(
|
|||||||
response?.text
|
response?.text
|
||||||
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
||||||
);
|
);
|
||||||
|
|
||||||
const { usage } = messages;
|
|
||||||
await calculateCost(usage, interaction.user.username, "query");
|
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
import { MessageFlags, type ChatInputCommandInteraction } from "discord.js";
|
||||||
import { personality } from "../config/personality.js";
|
import { personality } from "../config/personality.js";
|
||||||
import { ai } from "../utils/ai.js";
|
import { ai } from "../utils/ai.js";
|
||||||
import { calculateCost } from "../utils/calculateCost.js";
|
|
||||||
import { isSubscribed } from "../utils/isSubscribed.js";
|
import { isSubscribed } from "../utils/isSubscribed.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +41,4 @@ export const summarise = async(
|
|||||||
response?.text
|
response?.text
|
||||||
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
?? "I'm sorry, I don't have an answer for that. Please try again later.",
|
||||||
);
|
);
|
||||||
|
|
||||||
const { usage } = messages;
|
|
||||||
await calculateCost(usage, interaction.user.username, "summarise");
|
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import fastify from "fastify";
|
import fastify from "fastify";
|
||||||
import { logger } from "../utils/logger.js";
|
import { logHandler } from "../utils/logHandler.js";
|
||||||
|
|
||||||
const html = `<!DOCTYPE html>
|
const html = `<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
@ -60,16 +60,12 @@ export const instantiateServer = (): void => {
|
|||||||
|
|
||||||
server.listen({ port: 5002 }, (error) => {
|
server.listen({ port: 5002 }, (error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
void logger.error("instantiate server", error);
|
logHandler.error(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void logger.log("debug", "Server listening on port 5002.");
|
logHandler.info("Server listening on port 5002.");
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
logHandler.error(error);
|
||||||
void logger.error("instantiate server", error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
void logger.error("instantiate server", new Error("Unknown error"));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
/**
|
|
||||||
* @copyright nhcarrigan
|
|
||||||
* @license Naomi's Public License
|
|
||||||
* @author Naomi Carrigan
|
|
||||||
*/
|
|
||||||
import { logger } from "./logger.js";
|
|
||||||
import type { Usage } from "@anthropic-ai/sdk/resources/index.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the cost of a command run by a user, and sends to
|
|
||||||
* our logging service.
|
|
||||||
* @param usage -- The usage payload from Anthropic.
|
|
||||||
* @param uuid -- The Discord ID of the user who ran the command.
|
|
||||||
* @param command -- The command that was run.
|
|
||||||
*/
|
|
||||||
export const calculateCost = async(
|
|
||||||
usage: Usage,
|
|
||||||
uuid: string,
|
|
||||||
command: string,
|
|
||||||
): Promise<void> => {
|
|
||||||
const inputCost = usage.input_tokens * (3 / 1_000_000);
|
|
||||||
const outputCost = usage.output_tokens * (15 / 1_000_000);
|
|
||||||
const totalCost = inputCost + outputCost;
|
|
||||||
await logger.log(
|
|
||||||
"info",
|
|
||||||
`User ${uuid} ran \`${command}\` which accepted ${usage.input_tokens.toString()} and generated ${usage.output_tokens.toString()}.
|
|
||||||
|
|
||||||
Total cost: ${totalCost.toLocaleString("en-GB", { currency: "USD", style: "currency" })}`,
|
|
||||||
);
|
|
||||||
};
|
|
31
src/utils/logHandler.ts
Normal file
31
src/utils/logHandler.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
import { createLogger, format, transports, config } from "winston";
|
||||||
|
|
||||||
|
const { combine, timestamp, colorize, printf } = format;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard log handler, using winston to wrap and format
|
||||||
|
* messages. Call with `logHandler.log(level, message)`.
|
||||||
|
* @param {string} level - The log level to use.
|
||||||
|
* @param {string} message - The message to log.
|
||||||
|
*/
|
||||||
|
export const logHandler = createLogger({
|
||||||
|
exitOnError: false,
|
||||||
|
format: combine(
|
||||||
|
timestamp({
|
||||||
|
format: "YYYY-MM-DD HH:mm:ss",
|
||||||
|
}),
|
||||||
|
colorize(),
|
||||||
|
printf((info) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- Winston properties...
|
||||||
|
return `${info.level}: ${info.timestamp}: ${info.message}`;
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
level: "silly",
|
||||||
|
levels: config.npm.levels,
|
||||||
|
transports: [ new transports.Console() ],
|
||||||
|
});
|
@ -1,12 +0,0 @@
|
|||||||
/**
|
|
||||||
* @copyright nhcarrigan
|
|
||||||
* @license Naomi's Public License
|
|
||||||
* @author Naomi Carrigan
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Logger } from "@nhcarrigan/logger";
|
|
||||||
|
|
||||||
export const logger = new Logger(
|
|
||||||
"Cordelia Taryne",
|
|
||||||
process.env.LOG_TOKEN ?? "",
|
|
||||||
);
|
|
Loading…
x
Reference in New Issue
Block a user