generated from nhcarrigan/template
feat: initial prototype
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- Importing a class.
|
||||
import Anthropic from "@anthropic-ai/sdk";
|
||||
|
||||
/**
|
||||
* The Anthropic AI instance.
|
||||
*/
|
||||
export const ai = new Anthropic({
|
||||
apiKey: process.env.AI_TOKEN,
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
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.
|
||||
* @returns A string containing the usage and cost information.
|
||||
*/
|
||||
export const calculateCost = (
|
||||
usage: Usage,
|
||||
): string => {
|
||||
const inputCost = usage.input_tokens * ((usage.input_tokens > 200_000
|
||||
? 6
|
||||
: 3) / 1_000_000);
|
||||
const outputCost = usage.output_tokens * ((usage.output_tokens > 200_000
|
||||
? 22.5
|
||||
: 15) / 1_000_000);
|
||||
const totalCost = inputCost + outputCost;
|
||||
return `-# Accepted ${usage.input_tokens.toString()} and generated ${usage.output_tokens.toString()}.
|
||||
|
||||
-# Total cost: ${totalCost.toLocaleString("en-GB", {
|
||||
currency: "USD",
|
||||
style: "currency",
|
||||
})}`;
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
type ChatInputCommandInteraction,
|
||||
type Message,
|
||||
} from "discord.js";
|
||||
|
||||
const naomiId = "465650873650118659";
|
||||
|
||||
/**
|
||||
* Checks if a user has an active entitlement (subscription) for the bot.
|
||||
* If they do not, it responds to the interaction with a button to subscribe.
|
||||
* @param interaction -- The interaction payload from Discord.
|
||||
* @returns A boolean indicating whether the user is subscribed.
|
||||
*/
|
||||
const isNaomiInteraction = async(
|
||||
interaction: ChatInputCommandInteraction,
|
||||
): Promise<boolean> => {
|
||||
const isNaomi = interaction.user.id === naomiId;
|
||||
|
||||
if (!isNaomi) {
|
||||
const subscribeButton = new ButtonBuilder().
|
||||
setStyle(ButtonStyle.Premium).
|
||||
setSKUId("1425905043244060762");
|
||||
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
subscribeButton,
|
||||
);
|
||||
await interaction.editReply({
|
||||
components: [ row ],
|
||||
// eslint-disable-next-line stylistic/max-len -- Big boi string.
|
||||
content: "Sorry, as Naomi's personal assistant I am unable to assist you with your request. However, consider donating to Naomi so she can create additional free tools you CAN use.",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a user has an active entitlement (subscription) for the bot.
|
||||
* If they do not, it responds to the message with a button to subscribe.
|
||||
* @param message -- The message payload from Discord.
|
||||
* @returns A boolean indicating whether the user is subscribed.
|
||||
*/
|
||||
const isNaomiMessage = async(
|
||||
message: Message,
|
||||
): Promise<boolean> => {
|
||||
if (message.author.id === "465650873650118659") {
|
||||
return true;
|
||||
}
|
||||
const subscribeButton = new ButtonBuilder().
|
||||
setStyle(ButtonStyle.Premium).
|
||||
setSKUId("1425905043244060762");
|
||||
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
subscribeButton,
|
||||
);
|
||||
await message.client.application.entitlements.fetch();
|
||||
const isEntitled = message.client.application.entitlements.cache.find(
|
||||
(entitlement) => {
|
||||
return entitlement.userId === message.author.id && entitlement.isActive();
|
||||
},
|
||||
);
|
||||
|
||||
if (!isEntitled) {
|
||||
await message.reply({
|
||||
components: [ row ],
|
||||
// eslint-disable-next-line stylistic/max-len -- Big boi string.
|
||||
content: "Sorry, as Naomi's personal assistant I am unable to assist you with your request. However, consider donating to Naomi so she can create additional free tools you CAN use.",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export { isNaomiInteraction, isNaomiMessage };
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
|
||||
import { Logger } from "@nhcarrigan/logger";
|
||||
|
||||
export const logger = new Logger(
|
||||
"Maylin Taryne",
|
||||
process.env.LOG_TOKEN ?? "",
|
||||
);
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
type ChatInputCommandInteraction,
|
||||
type MessageContextMenuCommandInteraction,
|
||||
} from "discord.js";
|
||||
|
||||
/**
|
||||
* Responds to an interaction with a generic error message.
|
||||
* @param interaction -- The interaction payload from Discord.
|
||||
*/
|
||||
export const replyToError = async(
|
||||
interaction:
|
||||
| ChatInputCommandInteraction
|
||||
| MessageContextMenuCommandInteraction,
|
||||
): Promise<void> => {
|
||||
const button = new ButtonBuilder().
|
||||
setLabel("Need help?").
|
||||
setStyle(ButtonStyle.Link).
|
||||
setURL("https://chat.nhcarrigan.com");
|
||||
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(button);
|
||||
if (interaction.deferred || interaction.replied) {
|
||||
await interaction.editReply({
|
||||
components: [ row ],
|
||||
content: "Something went wrong with this command.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
await interaction.reply({
|
||||
components: [ row ],
|
||||
content: "Something went wrong with this command.",
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user