diff --git a/.gitignore b/.gitignore
index 494fcca..fbc6e95 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@
.vscode/
.idea/
.node-version
+/functions/other/settings.sqlite
+/personality.txt
# Logs
logs
@@ -108,4 +110,4 @@ dist
.dynamodb/
# TernJS port file
-.tern-port
\ No newline at end of file
+.tern-port
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..900ce3a
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,3 @@
+.github
+package.json
+pnpm-lock.yaml
\ No newline at end of file
diff --git a/README.md b/README.md
index df56bac..bf39a90 100644
--- a/README.md
+++ b/README.md
@@ -2,30 +2,70 @@
-## 🤔 What is this bot?
-The **Taurus Discord Bot** is a small bot, it can be used for several things such as:
-- Image Generation
-- AI GPT chats and personality customisations
+# 🤔 What is Taurus?
+
+The Taurus Discord Bot is a small bot with a big impact. It offers several features, including advanced image generation, AI chats, and more.
+
+
+💬 AI Chats
+
+- Powered by Google's [Gemini 1.5 Model](https://deepmind.google/technologies/gemini/#gemini-1.5)
+- Has a configurable global personality via the ``/personalise`` slash command
+- Remembers past messages
+
+**Ways to interact:**
+- Context Menus
+- Mention the Bot with your message
+- Utilise the ``/taurus`` slash command
+
+
+
+
+🖼️ Advanced Image Generation
+
+- 70+ Models
+- 17 Style Presets
+- Negative Prompt Customisation
+- A toggleable NSFW image blocker
+- Supports different languages
+- And much more!
+
+
+
+
+🔧 Additional Features
+
+- Live Console Logging in Discord
+- Personality update logs in Discord
+- User Commands - Use the bot anywhere on Discord
+- An optional CLI via the start scripts
+- A Settings Menu in Discord
+
## 💾 Install
-1. fill in the token and other values in ``config.json.example``
+1. fill in the token and other values in `config.json.example`
+
+2. Rename the file to `config.json`
-2. Rename the file to ``config.json``
+3. Run `pnpm i`
-3. Run ``npm i``
+4. Run `node .`
-4. Run ``node bot``
+5. In Discord run ``/settings`` and fill in the values
-**Note** - Alternatively **instead of steps 3 & 4** you can **run one of the startbot/start scripts.**
+> [!NOTE]
+> - Alternatively **instead of steps 3 & 4** you can **run one of the startbot/start scripts.** *(Reccomended)*
+> - If you do not have pnpm installed you will need to run: ``npm install -g pnpm``
- All PR's are welcome for improvements.
### ℹ️ Getting API Keys:
+
- https://ai.google.dev
- https://app.prodia.com/api
### 🏗️ Additional Credits
- This bot utilizes a modified version of the [discord bot template](https://github.com/NamVr/DiscordBot-Template) made
- by [Naman Vrati](https://github.com/NamVr)! [\[Apache License 2.0\]](https://github.com/NamVr/DiscordBot-Template/blob/master/LICENSE)
\ No newline at end of file
+ by [Naman Vrati](https://github.com/NamVr)! [\[Apache License 2.0\]](https://github.com/NamVr/DiscordBot-Template/blob/master/LICENSE)
diff --git a/bot.js b/bot.js
index 9a276f3..c3b4af5 100644
--- a/bot.js
+++ b/bot.js
@@ -15,7 +15,8 @@ const {
GatewayIntentBits,
Partials,
REST,
- Routes
+ Routes,
+ SlashCommandBuilder,
} = require("discord.js");
const { token, client_id } = require("./config.json");
@@ -57,7 +58,7 @@ for (const file of eventFiles) {
} else {
client.on(
event.name,
- async (...args) => await event.execute(...args, client)
+ async (...args) => await event.execute(...args, client),
);
}
}
@@ -66,8 +67,11 @@ for (const file of eventFiles) {
// Define Collection of Slash/Modal Commands and Cooldowns
client.slashCommands = new Collection();
+client.buttonCommands = new Collection();
client.modalCommands = new Collection();
+client.contextCommands = new Collection();
client.cooldowns = new Collection();
+client.autocompleteInteractions = new Collection();
client.functions = new Collection();
/**********************************************************************/
@@ -93,6 +97,78 @@ for (const module of slashCommands) {
}
}
+/**********************************************************************/
+// Registration of Autocomplete Interactions.
+
+/**
+ * @type {String[]}
+ * @description All autocomplete interactions.
+ */
+
+const autocompleteInteractions = fs.readdirSync("./interactions/autocomplete");
+
+// Loop through all files and store autocomplete interactions in autocompleteInteractions collection.
+
+for (const module of autocompleteInteractions) {
+ const files = fs
+ .readdirSync(`./interactions/autocomplete/${module}`)
+ .filter((file) => file.endsWith(".js"));
+
+ for (const interactionFile of files) {
+ const interaction = require(
+ `./interactions/autocomplete/${module}/${interactionFile}`,
+ );
+ client.autocompleteInteractions.set(interaction.name, interaction);
+ }
+}
+
+/**********************************************************************/
+// Registration of Context-Menu Interactions
+
+/**
+ * @type {String[]}
+ * @description All Context Menu commands.
+ */
+
+const contextMenus = fs.readdirSync("./interactions/context-menus");
+
+// Loop through all files and store context-menus in contextMenus collection.
+
+for (const folder of contextMenus) {
+ const files = fs
+ .readdirSync(`./interactions/context-menus/${folder}`)
+ .filter((file) => file.endsWith(".js"));
+ for (const file of files) {
+ const menu = require(`./interactions/context-menus/${folder}/${file}`);
+ const keyName = `${folder.toUpperCase()} ${menu.data.name}`;
+ client.contextCommands.set(keyName, menu);
+ }
+}
+
+/**********************************************************************/
+// Registration of Button-Command Interactions.
+
+/**
+ * @type {String[]}
+ * @description All button commands.
+ */
+
+const buttonCommands = fs.readdirSync("./interactions/buttons");
+
+// Loop through all files and store button-commands in buttonCommands collection.
+
+for (const module of buttonCommands) {
+ const commandFiles = fs
+ .readdirSync(`./interactions/buttons/${module}`)
+ .filter((file) => file.endsWith(".js"));
+
+ for (const commandFile of commandFiles) {
+ const command = require(`./interactions/buttons/${module}/${commandFile}`);
+ for (const id of command.id) {
+ client.buttonCommands.set(id, command);
+ }
+ }
+}
/**********************************************************************/
// Registration of Modal-Command Interactions.
@@ -113,7 +189,13 @@ for (const module of modalCommands) {
for (const commandFile of commandFiles) {
const command = require(`./interactions/modals/${module}/${commandFile}`);
- client.modalCommands.set(command.id, command);
+ if (Array.isArray(command.id)) {
+ for (const id of command.id) {
+ client.modalCommands.set(id, command);
+ }
+ } else {
+ client.modalCommands.set(command.id, command);
+ }
}
}
@@ -125,17 +207,17 @@ for (const module of modalCommands) {
* @description All functions.
*/
-const functionFiles = fs.readdirSync("./functions");
-
-// Loop through all files and store functions in functions collection.
+client.once("ready", () => {
+ const functionFiles = fs.readdirSync("./functions");
-for (const functionFile of functionFiles) {
- if (functionFile.endsWith(".js")) {
- const func = require(`./functions/${functionFile}`);
- client.functions.set(functionFile.replace('.js', ''), func);
- func(client);
- }
-}
+ for (const functionFile of functionFiles) {
+ if (functionFile.endsWith(".js")) {
+ const func = require(`./functions/${functionFile}`);
+ client.functions.set(functionFile.replace(".js", ""), func);
+ func(client);
+ }
+ }
+});
/**********************************************************************/
// Registration of Slash-Commands in Discord API
@@ -143,7 +225,19 @@ for (const functionFile of functionFiles) {
const rest = new REST({ version: "9" }).setToken(token);
const commandJsonData = [
- ...Array.from(client.slashCommands.values()).map((c) => c.data.toJSON()),
+ ...Array.from(client.slashCommands.values()).map((c) => {
+ const commandData =
+ c.data instanceof SlashCommandBuilder ? c.data.toJSON() : c.data;
+ commandData.integration_types = [0, 1];
+ commandData.contexts = [0, 1, 2];
+ return commandData;
+ }),
+ ...Array.from(client.contextCommands.values()).map((c) => {
+ const commandData = c.data;
+ commandData.integration_types = [0, 1];
+ commandData.contexts = [0, 1, 2];
+ return commandData;
+ }),
];
(async () => {
@@ -153,7 +247,7 @@ const commandJsonData = [
await rest.put(
Routes.applicationCommands(client_id),
- { body: commandJsonData }
+ { body: commandJsonData },
);
console.log("Successfully reloaded application (/) commands.");
@@ -168,10 +262,20 @@ client.login(token);
/**********************************************************************/
// Anti Crash script
-
-process.on("unhandRejection", (reason, promise) => {
+process.on("unhandledRejection", (reason, promise) => {
console.error(`🚫 Critical Error detected:\n\n`, reason, promise);
+
+ // Uncomment the below lines below to see the full error details. - ADVANCED DEBUGGING //
+
+ // console.dir(reason, { showHidden: true, depth: null });
+ // console.log("Promise: ", promise);
});
+
process.on("uncaughtException", (error, origin) => {
console.error(`🚫 Critical Error detected:\n\n`, error, origin);
-});
\ No newline at end of file
+
+ // Uncomment the below lines below to see the full error details. - ADVANCED DEBUGGING //
+
+ // console.dir(error, { showHidden: true, depth: null });
+ // console.log("Origin: ", origin);
+});
diff --git a/config.json.example b/config.json.example
index 9f30171..8508fc4 100644
--- a/config.json.example
+++ b/config.json.example
@@ -1,11 +1,10 @@
{
- "token": "...",
- "owner": ["719815864135712799","483359783831732255"],
- "client_id": "...",
- "guild_id_logs": "...",
- "channel_id_logs": "...",
- "webhook_url_console_logs": "...",
- "Gemini_API_KEY": "...",
- "XProdiaKey": "...",
- "Block_NSFW_Images": true
+ "token": "...",
+ "owner": ["719815864135712799","483359783831732255", "OWNER USER IDS HERE"],
+ "client_id": "...",
+ "emojis": {
+ "loading": "⭕",
+ "working": "🟢",
+ "failed": "🔴"
+ }
}
\ No newline at end of file
diff --git a/events/autocompleteInteraction.js b/events/autocompleteInteraction.js
new file mode 100644
index 0000000..9349331
--- /dev/null
+++ b/events/autocompleteInteraction.js
@@ -0,0 +1,46 @@
+/**
+ * @file Autocomplete Interaction Handler
+ * @author Naman Vrati
+ * @since 3.3.0
+ * @version 3.3.2
+ */
+
+const { Events } = require("discord.js");
+
+module.exports = {
+ name: Events.InteractionCreate,
+
+ /**
+ * @description Executes when an interaction is created and handle it.
+ * @author Naman Vrati
+ * @param {import('discord.js').AutocompleteInteraction & { client: import('../typings').Client }} interaction The interaction which was created
+ */
+
+ async execute(interaction) {
+ // Deconstructed client from interaction object.
+ const { client } = interaction;
+
+ // Checks if the interaction is an autocomplete interaction (to prevent weird bugs)
+
+ if (!interaction.isAutocomplete()) return;
+
+ // Checks if the request is available in our code.
+
+ const request = client.autocompleteInteractions.get(
+ interaction.commandName,
+ );
+
+ // If the interaction is not a request in cache return.
+
+ if (!request) return;
+
+ // A try to execute the interaction.
+
+ try {
+ await request.execute(interaction);
+ } catch (err) {
+ console.error(err);
+ return Promise.reject(err);
+ }
+ },
+};
diff --git a/events/buttonInteraction.js b/events/buttonInteraction.js
new file mode 100644
index 0000000..361892c
--- /dev/null
+++ b/events/buttonInteraction.js
@@ -0,0 +1,51 @@
+/**
+ * @file Button Interaction Handler
+ * @author Naman Vrati
+ * @since 3.0.0
+ * @version 3.3.2
+ */
+
+const { Events } = require("discord.js");
+
+module.exports = {
+ name: Events.InteractionCreate,
+
+ /**
+ * @description Executes when an interaction is created and handle it.
+ * @author Naman Vrati
+ * @param {import('discord.js').ButtonInteraction & { client: import('../typings').Client }} interaction The interaction which was created
+ */
+
+ async execute(interaction) {
+ // Deconstructed client from interaction object.
+ const { client } = interaction;
+
+ // Checks if the interaction is a button interaction (to prevent weird bugs)
+
+ if (!interaction.isButton()) return;
+
+ const command = client.buttonCommands.get(interaction.customId);
+
+ // If the interaction is not a command in cache, return error message.
+ // You can modify the error message at ./messages/defaultButtonError.js file!
+
+ if (!command) {
+ return await require("../messages/defaultButtonError").execute(
+ interaction,
+ );
+ }
+
+ // A try to execute the interaction.
+
+ try {
+ return await command.execute(interaction);
+ } catch (err) {
+ console.error(err);
+ // console.dir(err, { showHidden: true, depth: null });
+ await interaction.reply({
+ content: "There was an issue while executing that button!",
+ ephemeral: true,
+ });
+ }
+ },
+};
diff --git a/events/contextInteraction.js b/events/contextInteraction.js
new file mode 100644
index 0000000..772af8f
--- /dev/null
+++ b/events/contextInteraction.js
@@ -0,0 +1,84 @@
+/**
+ * @file Context Interaction Handler
+ * @author Krish Garg & Naman Vrati
+ * @since 3.0.0
+ * @version 3.3.2
+ */
+const { Events } = require("discord.js");
+const { botInGuild } = require("../functions/other/utils");
+
+module.exports = {
+ name: Events.InteractionCreate,
+
+ /**
+ * @description Executes when an interaction is created and handle it.
+ * @author Naman Vrati
+ * @param {import("discord.js").ContextMenuCommandInteraction & { client: import("../typings").Client }} interaction The interaction which was created
+ */
+
+ execute: async (interaction) => {
+ // Deconstructed client from interaction object.
+ const { client } = interaction;
+
+ // Checks if the interaction is a context interaction (to prevent weird bugs)
+
+ if (!interaction.isContextMenuCommand()) return;
+
+ /**********************************************************************/
+
+ // Checks if the interaction target was a user
+
+ if (interaction.isUserContextMenuCommand()) {
+ const command = client.contextCommands.get(
+ "USER " + interaction.commandName,
+ );
+
+ // A try to execute the interaction.
+
+ try {
+ return await command.execute(interaction);
+ } catch (err) {
+ console.error(err);
+ await interaction.reply({
+ content:
+ "There was an issue while executing that context command! If the issue persists please contact the bot owners.",
+ ephemeral: true,
+ });
+ }
+ }
+ // Checks if the interaction target was a message
+ else if (interaction.isMessageContextMenuCommand()) {
+ const command = client.contextCommands.get(
+ "MESSAGE " + interaction.commandName,
+ );
+
+ // A try to execute the interaction.
+
+ try {
+ return await command.execute(interaction);
+ } catch (err) {
+ if (!botInGuild(interaction)) {
+ return await interaction.reply({
+ content:
+ "This command can only be executed in servers in which the bot is in, or in DMs/Group Chats.",
+ ephemeral: true,
+ });
+ }
+ console.error(err);
+ await interaction.reply({
+ content:
+ "There was an issue while executing that context command! If the issue persists please contact the bot owners.",
+ ephemeral: true,
+ });
+ }
+ }
+
+ // Practically not possible, but we are still caching the bug.
+ // Possible Fix is a restart!
+ else {
+ return console.error(
+ "Something weird happening in context menu. Received a context menu of unknown type. If the issue persists please contact the bot owners.",
+ );
+ }
+ },
+};
diff --git a/events/modalInteraction.js b/events/modalInteraction.js
index 828425a..a038e3e 100644
--- a/events/modalInteraction.js
+++ b/events/modalInteraction.js
@@ -24,7 +24,7 @@ module.exports = {
if (!interaction.isModalSubmit()) return;
- if (interaction.customId === 'taurus_ai_personality') return;
+ if (interaction.customId === "taurus_ai_personality") return;
const command = client.modalCommands.get(interaction.customId);
@@ -32,13 +32,17 @@ module.exports = {
// You can modify the error message at ./messages/defaultModalError.js file!
if (!command) {
- return await require("../messages/defaultModalError").execute(interaction);
+ return await require("../messages/defaultModalError").execute(
+ interaction,
+ );
}
// A try to execute the interaction.
const error = new EmbedBuilder()
- .setDescription("**There was an issue while understanding this modal!\n\nPlease contact the Developers.**")
+ .setDescription(
+ "**There was an issue while understanding this modal!\n\nPlease contact the Developers.**",
+ )
.setColor("Red");
try {
diff --git a/events/onMention.js b/events/onMention.js
index 2a31b72..3a315b8 100644
--- a/events/onMention.js
+++ b/events/onMention.js
@@ -5,24 +5,23 @@
const { Events, EmbedBuilder } = require("discord.js");
-
module.exports = {
name: Events.MessageCreate,
-
async execute(message) {
-
- const {client} = message;
+ const { client } = message;
if (
message.content == `<@${client.user.id}>` ||
message.content == `<@!${client.user.id}>`
) {
const bot_message = new EmbedBuilder()
- .setDescription(`Hi ${message.author}! I am Taurus. Chat to me by mentioning me and typing your message! Or alternatively run \`/taurus\`!`)
+ .setDescription(
+ `Hi ${message.author}! I am Taurus. Chat to me by mentioning me and typing your message! Or alternatively run \`/taurus\`!`,
+ )
.setColor("Gold");
- return message.reply({embeds: [bot_message]});
+ return message.reply({ embeds: [bot_message] });
}
},
};
diff --git a/events/onReady.js b/events/onReady.js
index da24715..d71718f 100644
--- a/events/onReady.js
+++ b/events/onReady.js
@@ -16,15 +16,18 @@ module.exports = {
* @param {import('../typings').Client} client Main Application Client.
*/
execute(client) {
-
client.user.setPresence({
- activities: [{
- type: ActivityType.Custom,
- name: "Status",
- state: "💾 Chilling on my owners computer!"
- }]
- })
+ activities: [
+ {
+ type: ActivityType.Custom,
+ name: "Status",
+ state: "💾 Chilling in the Cloud!",
+ },
+ ],
+ });
- console.log(`Ready! Logged in as ${client.user.tag}`);
+ setTimeout(() => {
+ console.log(`Ready! Logged in as ${client.user.tag}`);
+ }, 25);
},
};
diff --git a/events/slashCreate.js b/events/slashCreate.js
index 402fddd..63ea47e 100644
--- a/events/slashCreate.js
+++ b/events/slashCreate.js
@@ -7,7 +7,8 @@
*/
const { Collection, EmbedBuilder, Events } = require("discord.js"),
-{ owner } = require("../config.json");
+ { botInGuild } = require("../functions/other/utils"),
+ { owner } = require("../config.json");
module.exports = {
name: Events.InteractionCreate,
@@ -42,19 +43,28 @@ module.exports = {
let cooldownAmount = command.cooldown ?? defaultCooldownDuration;
if (interaction.inGuild()) {
- allowedRoleIds = ["...", "..."];
- if (interaction.member.roles.cache.some(role => allowedRoleIds.includes(role.id))) {
- const cooldownPercentage = 0.5;
- cooldownAmount = Math.floor(cooldownAmount * cooldownPercentage);
+ if (botInGuild(interaction)) {
+ allowedRoleIds = ["...", "..."];
+ if (
+ interaction.member.roles.cache.some((role) =>
+ allowedRoleIds.includes(role.id),
+ )
+ ) {
+ const cooldownPercentage = 0.5;
+ cooldownAmount = Math.floor(cooldownAmount * cooldownPercentage);
+ }
}
}
const isOwner = owner.includes(interaction.user.id);
if (!isOwner && timestamps.has(interaction.user.id)) {
- const expirationTime = timestamps.get(interaction.user.id) + cooldownAmount * 1000;
+ const expirationTime =
+ timestamps.get(interaction.user.id) + cooldownAmount * 1000;
const timeLeft = (expirationTime - now) / 1000;
const embed = new EmbedBuilder()
- .setDescription(`Please wait \`\`${timeLeft.toFixed(1)}\`\` more second(s) before reusing the \`${interaction.commandName}\` command.`)
+ .setDescription(
+ `Please wait \`\`${timeLeft.toFixed(1)}\`\` more second(s) before reusing the \`${interaction.commandName}\` command.`,
+ )
.setColor("Orange");
if (now < expirationTime) {
const expiredTimestamp = Math.round(expirationTime / 1000);
@@ -63,19 +73,25 @@ module.exports = {
}
timestamps.set(interaction.user.id, now);
- setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount * 1000);
+ setTimeout(
+ () => timestamps.delete(interaction.user.id),
+ cooldownAmount * 1000,
+ );
const error = new EmbedBuilder()
- .setDescription("**There was an issue while executing that command!\n\nPlease contact the Developers.**")
+ .setDescription(
+ "**There was an issue while executing that command!\n\nPlease contact the Developers.**",
+ )
.setColor("Red");
try {
await command.execute(interaction);
} catch (err) {
+ console.error(err);
await interaction.reply({
embeds: [error],
- ephemeral: true
+ ephemeral: true,
});
}
- }
+ },
};
diff --git a/events/taurusai.js b/events/taurusai.js
index b6619ed..b825333 100644
--- a/events/taurusai.js
+++ b/events/taurusai.js
@@ -3,218 +3,163 @@
* @author TechyGiraffe999
*/
-
-const { Collection, ChannelType, Events, EmbedBuilder } = require("discord.js");
-const fs = require('fs').promises;
-const path = require('path');
-const { GoogleGenerativeAI, HarmBlockThreshold, HarmCategory } = require("@google/generative-ai");
-const { Gemini_API_KEY } = require("../config.json");
-const genAI = new GoogleGenerativeAI(Gemini_API_KEY);
+const { Events, EmbedBuilder } = require("discord.js");
+const fs = require("fs").promises;
+const path = require("path");
+const { GoogleGenerativeAI } = require("@google/generative-ai");
+const {
+ getSafetySettings,
+ handleGeminiError,
+ handleResponse,
+ fetchThreadMessages,
+} = require("../functions/other/utils");
+const { QuickDB } = require("quick.db");
+const { get } = require("http");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../functions/other/settings.sqlite"),
+});
module.exports = {
- name: Events.MessageCreate,
-
- async execute(message) {
- if (message.author.bot || message.author.id === message.client.user.id) return;
- if (message.type === 21) return;
-
- if (!Gemini_API_KEY || Gemini_API_KEY.length < 4) {
- invalid_api = new EmbedBuilder()
- .setTitle("⚠️ Invalid API Key")
- .setDescription("> **The API Key for Gemini is invalid or not provided.**")
- .setColor("Red")
- return message.reply({ embeds: [invalid_api] });
- }
-
- let userQuestion
- let threadMessages = [];
-
- if (message.reference) {
- const originalMessage = await message.channel.messages.fetch(message.reference.messageId);
-
- if (originalMessage.author.id !== message.client.user.id) return;
-
- if (originalMessage.author.id === message.client.user.id) {
- let currentMessage = message;
-
- while (currentMessage.reference) {
- currentMessage = await message.channel.messages.fetch(currentMessage.reference.messageId);
- const sender = currentMessage.author.id === message.client.user.id ? 'model' : 'user';
- let content = currentMessage.content;
- if (sender === 'user') {
- content = content.replace(/<@\d+>\s*/, '');
- }
- threadMessages.unshift({ role: sender, parts: content });
- }
- }
- userQuestion = message.content
-
- } else if (!message.reference) {
- const botMention = `<@${message.client.user.id}>`;
- const regex = new RegExp(`^${botMention}\\s+.+`);
-
- if (!regex.test(message.content)) return;
-
- userQuestion = message.content
- .replace(botMention, "")
- .trim();
- }
-
- const user = message.author;
- const sendTypingInterval = setInterval(() => {
- message.channel.sendTyping();
- }, 5000);
-
- const loadingEmbed = new EmbedBuilder()
- .setTitle("**⌛Loading your response**")
- .setDescription("*TaurusAI may display innacurate/offensive info.*\n\n> *I am powered by Google's Generative AI, [Gemini](https://gemini.google.com) and was integrated by <@719815864135712799>.*")
- .setFooter({text: "This may take a while", iconURL: `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png?size=256`})
- .setTimestamp()
- const loadingMsg = await message.reply({ embeds: [loadingEmbed] });
- const loadingDots = [" ⌛ ", " ⏳ "];
- let i = 0;
- const loadingInterval = setInterval(() => {
- loadingEmbed.setTitle(`**${loadingDots[i]} Loading your response**`);
- loadingMsg.edit({ embeds: [loadingEmbed] });
- i = (i + 1) % loadingDots.length;
- }, 2000);
-
- const personalityFilePath = path.join(__dirname, '../personality.txt');
- const personalityContent = await fs.readFile(personalityFilePath, 'utf-8');
- const personalityLines = personalityContent.split('\n');
-
-
- const safetySettings = [
- {
- category: HarmCategory.HARM_CATEGORY_HARASSMENT,
- threshold: HarmBlockThreshold.BLOCK_ONLY_HIGH,
- },
- {
- category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
- threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
- },
- {
- category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
- threshold: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE,
- },
- {
- category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
- threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
- },
- ];
-
- const user_status = message.member?.presence.clientStatus || {}
- const status_devices = Object.entries(user_status)
- .map(([platform, status]) => `${platform}: ${status}`)
- .join("\n");
-
- parts1 = `${personalityLines}\n Please greet the user with a greeting and then their name which is: <@${message.author.id}>.`
-
- if (Object.keys(user_status).length) {
- parts1 += ` The user's presence is currently:\n${status_devices}`;
- }
-
- async function run() {
- const generationConfig = {
- maxOutputTokens: 750,
- };
- const model = genAI.getGenerativeModel({ model: "gemini-pro", safetySettings, generationConfig});
-
- var history = [
- {
- role: "user",
- parts: parts1,
- },
- {
- role: "model",
- parts: `I will greet the user with their name: <@${message.author.id}>. I will also limit all of my responses to 2000 characters or less, regardless of what you say. Feel feel free to ask me anything! 😊`,
- },
- ];
-
- if (history.length > 0 && threadMessages.length > 0 && history[history.length - 1].role === 'model' && threadMessages[0].role === 'model') {
- history[history.length - 1].parts += threadMessages[0].parts;
- threadMessages.shift();
- }
-
- history = history.concat(threadMessages);
-
- const chat = model.startChat({
- history,
- generationConfig: {
- maxOutputTokens: 750,
- },
- });
-
- const result = await chat.sendMessage(userQuestion);
- const response = await result.response;
-
- const responseLength = response.text().length;
- if (responseLength > 2000) {
- response.text = response.text().substring(0, 1928 - "... \n\n".length) + "... \n\n*Response was cut short due to Discords character limit of 2000*";
- }
- clearInterval(loadingInterval);
- clearInterval(sendTypingInterval);
-
- let responseText = response.text();
- const regex = /<@&?\d+>/g;
- let match;
-
- while ((match = regex.exec(responseText)) !== null) {
- if (match[0] !== `<@${message.author.id}>`) {
- const ping_error = new EmbedBuilder()
- .setTitle("⚠️ Response Cannot Be Sent")
- .setDescription("> *The generated message contains a mention of a Role or different User to the one that sent the original message/command.*")
- .setColor("Red")
- return await loadingMsg.edit({ embeds: [ping_error] });
- }
- }
-
- responseText = responseText.replace(/(?");
- return await loadingMsg.edit({ content: responseText, embeds: [] });
- }
-
- try{
- await run();
- } catch (err) {
- clearInterval(loadingInterval);
- clearInterval(sendTypingInterval);
-
- switch (err.message) {
- case "[GoogleGenerativeAI Error]: Text not available. Response was blocked due to SAFETY":
- const safety_error = new EmbedBuilder()
- .setTitle("⚠️ An Error Occurred")
- .setDescription("> *The response was blocked due to **SAFETY**.*")
- .setColor("Red")
-
- return await loadingMsg.edit({ embeds: [safety_error]});
-
- case "[GoogleGenerativeAI Error]: Error fetching from https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent: [400 Bad Request] User location is not supported for the API use.":
- const location_error = new EmbedBuilder()
- .setTitle("⚠️ An Error Occurred")
- .setDescription("> *The user location is not supported for Gemini API use. Please contact the Developers.*")
- .setColor("Red")
-
- return await loadingMsg.edit({ embeds: [location_error]});
-
- case "Cannot send an empty message":
- case "response.text is not a function":
- const error = new EmbedBuilder()
- .setTitle("⚠️ An Error Occurred")
- .setDescription("An error occurred while processing your request. Please try again later, or in a few minutes. \n*If this issue persists, please contact the Developers.* \n\n> - Generated response may be too long. *(Fix this by specifying for the generated response to be smaller, e.g. 10 Lines)*\n> - Token Limit for this minute may have been reached.")
- .setColor("Red")
-
- return await loadingMsg.edit({ embeds: [error]});
-
- default:
- const error_unknown = new EmbedBuilder()
- .setTitle("⚠️ An Error Occurred")
- .setDescription("An unknown error occurred while processing your request. Please try again later, or in a few minutes. \n*If this issue persists, please contact the Developers*\n> - Token Limit for this minute may have been reached.")
- .setColor("Red")
-
- await loadingMsg.edit({embeds: [error_unknown]
- });
- }
- }
-
- },
-};
\ No newline at end of file
+ name: Events.MessageCreate,
+
+ async execute(message) {
+ if (message.author.bot || message.author.id === message.client.user.id)
+ return;
+ if ([18, 21].includes(message.type)) return;
+
+ const apiKeys = await db.get("apiKeys");
+ const geminiApiKey = apiKeys.gemini;
+ const modelSettings = await db.get("model");
+ let modelId = modelSettings.model;
+ const genAI = new GoogleGenerativeAI(geminiApiKey);
+
+ let userQuestion;
+ let messageDeleted;
+ let threadMessages = [];
+
+ if (message.reference) {
+ const {
+ userQuestion: fetchedUserQuestion,
+ threadMessages: fetchedThreadMessages,
+ messageDeleted: fetchedMessageDeleted,
+ } = await fetchThreadMessages(message);
+ if (fetchedUserQuestion === null && fetchedThreadMessages === null)
+ return;
+ threadMessages = fetchedThreadMessages;
+ userQuestion = fetchedUserQuestion;
+ messageDeleted = fetchedMessageDeleted;
+ } else if (!message.reference) {
+ const botMention = `<@${message.client.user.id}>`;
+ const regex = new RegExp(`^${botMention}\\s+.+`);
+
+ if (!regex.test(message.content)) return;
+ userQuestion = message.content.replace(botMention, "").trim();
+ }
+
+ const user = message.author;
+ const sendTypingInterval = setInterval(() => {
+ message.channel.sendTyping();
+ }, 5000);
+
+ let loadingInterval;
+ let loadingMsg;
+
+ async function run() {
+ const loadingEmbed = new EmbedBuilder()
+ .setTitle("**⌛Loading your response**")
+ .setDescription(
+ "*TaurusAI may display innacurate/offensive info.*\n\n> *I am powered by Google's Generative AI, [Gemini](https://gemini.google.com) and was integrated by <@719815864135712799>.*",
+ )
+ .setFooter({
+ text: "This may take a while",
+ iconURL: `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png?size=256`,
+ })
+ .setTimestamp();
+ loadingMsg = loadingMsg
+ ? await loadingMsg.edit({ embeds: [loadingEmbed] })
+ : await message.reply({ embeds: [loadingEmbed] });
+ const loadingDots = [" ⌛ ", " ⏳ "];
+ let i = 0;
+ loadingInterval = setInterval(() => {
+ loadingEmbed.setTitle(`**${loadingDots[i]} Loading your response**`);
+ loadingMsg.edit({ embeds: [loadingEmbed] });
+ i = (i + 1) % loadingDots.length;
+ }, 2000);
+
+ const user_status = message.member?.presence.clientStatus || {};
+ const status_devices = Object.entries(user_status)
+ .map(([platform, status]) => `${platform}: ${status}`)
+ .join("\n");
+
+ const personalityFilePath = path.join(__dirname, "../personality.txt");
+ const personalityContent = await fs.readFile(
+ personalityFilePath,
+ "utf-8",
+ );
+ const personalityLines = personalityContent.split("\n");
+
+ instruction = `${personalityLines}\n Please greet the user with a greeting and then the current users name, which is: <@${message.author.id}> and limit your responses to 2000 characters or less. Please note the current user may change.`;
+
+ if (Object.keys(user_status).length) {
+ instruction += ` The user's status/presence is currently:\n${status_devices}`;
+ }
+
+ const generationConfig = {
+ maxOutputTokens: 750,
+ };
+
+ const model = genAI.getGenerativeModel({
+ model: modelId,
+ systemInstruction: instruction,
+ safetySettings: await getSafetySettings(),
+ generationConfig,
+ });
+
+ if (
+ threadMessages &&
+ threadMessages.length > 0 &&
+ threadMessages[0].role === "model"
+ ) {
+ messageDeleted = "threadDeleted";
+ threadMessages = [];
+ }
+
+ const chat = model.startChat({
+ history: threadMessages,
+ generationConfig: {
+ maxOutputTokens: 750,
+ },
+ });
+
+ clearInterval(loadingInterval);
+ clearInterval(sendTypingInterval);
+ await handleResponse(
+ chat,
+ userQuestion,
+ false,
+ message,
+ loadingMsg,
+ messageDeleted,
+ );
+ }
+
+ let errorType = null;
+ do {
+ try {
+ await run();
+ errorType = null;
+ } catch (err) {
+ clearInterval(loadingInterval);
+ sendTypingInterval && clearInterval(sendTypingInterval);
+
+ errorType = await handleGeminiError(err, loadingMsg);
+ if (errorType === "quotaErrorBalance") {
+ modelId =
+ modelId === "gemini-1.5-pro-latest"
+ ? "gemini-1.5-flash-latest"
+ : "gemini-1.5-pro-latest";
+ }
+ }
+ } while (errorType === "quota_error" || errorType === "quotaErrorBalance");
+ },
+};
diff --git a/functions/logConsole.js b/functions/logConsole.js
index b89b71b..de7e0f5 100644
--- a/functions/logConsole.js
+++ b/functions/logConsole.js
@@ -1,64 +1,98 @@
module.exports = (client) => {
- const { WebhookClient, EmbedBuilder } = require('discord.js');
- const {webhook_url_console_logs} = require('../config.json');
- const webhookURL = webhook_url_console_logs;
+ const { WebhookClient, EmbedBuilder } = require("discord.js");
+ const { QuickDB } = require("quick.db");
+ const {
+ webhookUpdateEvent,
+ } = require("../interactions/modals/Settings/webhooks");
+ const path = require("path");
+ const db = new QuickDB({
+ filePath: path.join(__dirname, "./other/settings.sqlite"),
+ });
+ (async () => {
+ const webhooks = await db.get("webhooks");
+ webhookUrlConsoleLogs = webhooks.console;
+ webhookURL = webhookUrlConsoleLogs;
+ let isWebhookSetupSuccessful = false;
- let webhookClient;
- try {
- webhookClient = new WebhookClient({ url: webhookURL });
- } catch (error) {
- console.log('\x1b[31m\x1b[1m%s\x1b[0m', 'CONSOLE LOGGING IN DISCORD DISABLED. WEBHOOK URL NOT PROVIDED OR INVALID.');
- return;
- }
+ let webhookClient;
+ const setupWebhookClient = async () => {
+ try {
+ webhookClient = new WebhookClient({ url: webhookURL });
+ isWebhookSetupSuccessful = true;
+ } catch (error) {
+ console.log(
+ "\x1b[31m\x1b[1m%s\x1b[0m",
+ "CONSOLE LOGGING IN DISCORD DISABLED. SET WEBHOOK URL WITH /SETTINGS.",
+ );
+ isWebhookSetupSuccessful = false;
+ }
+ };
+ await setupWebhookClient();
- function customLogger(type, ...messages) {
- const combinedMessage = messages.map(m => (typeof m === 'object' ? JSON.stringify(m, null, 2) : m)).join(' ');
-
- if (combinedMessage === "By passing no model path, you're using the model hosted by Infinite.red - Please download and host the model before releasing this in production. See NSFWJS docs for instructions.") {
- return;
- }
+ webhookUpdateEvent.on("update", async (newWebhookUrl) => {
+ webhookURL = newWebhookUrl;
+ await setupWebhookClient();
+ });
- let messageToSend = combinedMessage;
- if (combinedMessage.length > 4070) {
- messageToSend = `${combinedMessage.slice(0, 4067)}...`;
- }
-
- const embed = new EmbedBuilder()
- .setDescription(`\`\`\`console\n${messageToSend}\`\`\``)
- .setColor(0x3498DB)
-
- if (type === 'error') {
- embed.setColor('Red');
- } else if (type === 'warn') {
- embed.setColor('Orange');
- } else if (combinedMessage === 'Started refreshing application (/) commands.' ||
- combinedMessage === 'Successfully reloaded application (/) commands.' ||
- combinedMessage.startsWith('Ready! Logged in as')) {
- embed.setColor('Green');
- if (combinedMessage === 'Started refreshing application (/) commands.') {
- embed.setTitle('💾 Console Log');
- }
- }
-
- webhookClient.send({
- username: 'Taurus Console',
- avatarURL: 'https://github.com/TecEash1/TecEash1/assets/92249532/bd4aca7e-daab-4eeb-9265-e53cc1925e8c',
- embeds: [embed]
- }).catch(console.error);
-
- console.originalLog(combinedMessage);
- }
-
- console.originalLog = console.log;
- console.log = customLogger.bind(null, 'log');
-
- console.originalError = console.error;
- console.error = customLogger.bind(null, 'error');
-
- console.originalWarn = console.warn;
- console.warn = customLogger.bind(null, 'warn');
-
- console.originalInfo = console.info;
- console.info = customLogger.bind(null, 'info');
+ function customLogger(type, ...messages) {
+ const combinedMessage = messages
+ .map((m) => (typeof m === "object" ? JSON.stringify(m, null, 2) : m))
+ .join(" ");
-};
\ No newline at end of file
+ const blockedMessages = [
+ "By not specifying 'modelOrUrl' parameter, you're using the default model: 'MobileNetV2'. See NSFWJS docs for instructions on hosting your own model (https://github.com/infinitered/nsfwjs?tab=readme-ov-file#host-your-own-model).",
+ "%cBy not specifying 'modelOrUrl' parameter, you're using the default model: 'MobileNetV2'. See NSFWJS docs for instructions on hosting your own model (https://github.com/infinitered/nsfwjs?tab=readme-ov-file#host-your-own-model). color: lightblue",
+ ];
+
+ if (blockedMessages.includes(combinedMessage)) return;
+
+ let messageToSend = combinedMessage;
+ if (combinedMessage.length > 4070) {
+ messageToSend = `${combinedMessage.slice(0, 4067)}...`;
+ }
+
+ const embed = new EmbedBuilder()
+ .setDescription(`\`\`\`console\n${messageToSend}\`\`\``)
+ .setColor(0x3498db);
+
+ if (type === "error") {
+ embed.setColor("Red");
+ } else if (type === "warn") {
+ embed.setColor("Orange");
+ } else if (
+ combinedMessage === "Started refreshing application (/) commands." ||
+ combinedMessage === "Successfully reloaded application (/) commands." ||
+ combinedMessage.startsWith("Ready! Logged in as")
+ ) {
+ embed.setColor("Green");
+ if (combinedMessage === `Ready! Logged in as ${client.user.tag}`) {
+ embed.setTitle("💾 Console Log");
+ }
+ }
+
+ if (isWebhookSetupSuccessful) {
+ webhookClient
+ .send({
+ username: "Taurus Console",
+ avatarURL: client.user.displayAvatarURL(),
+ embeds: [embed],
+ })
+ .catch(console.error);
+ }
+
+ console.originalLog(combinedMessage);
+ }
+
+ console.originalLog = console.log;
+ console.log = customLogger.bind(null, "log");
+
+ console.originalError = console.error;
+ console.error = customLogger.bind(null, "error");
+
+ console.originalWarn = console.warn;
+ console.warn = customLogger.bind(null, "warn");
+
+ console.originalInfo = console.info;
+ console.info = customLogger.bind(null, "info");
+ })();
+};
diff --git a/functions/other/settings.sqlite b/functions/other/settings.sqlite
new file mode 100644
index 0000000..d2f4bb0
Binary files /dev/null and b/functions/other/settings.sqlite differ
diff --git a/functions/other/utils.js b/functions/other/utils.js
new file mode 100644
index 0000000..68830fc
--- /dev/null
+++ b/functions/other/utils.js
@@ -0,0 +1,353 @@
+const { HarmCategory, HarmBlockThreshold } = require("@google/generative-ai");
+const { EmbedBuilder, DiscordAPIError, WebhookClient } = require("discord.js");
+const { owner } = require("../../config.json");
+const path = require("path");
+const { QuickDB } = require("quick.db");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "./settings.sqlite"),
+});
+const axios = require("axios");
+
+function botInGuild(interaction) {
+ const botGuilds = interaction.client.guilds.cache;
+ return botGuilds.has(interaction.guildId);
+}
+
+async function getSafetySettings() {
+ const model = await db.get("model");
+ const safetyEnabled = model.safetySystem;
+
+ const safetySettings = [
+ {
+ category: HarmCategory.HARM_CATEGORY_HARASSMENT,
+ threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
+ },
+ {
+ category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
+ threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
+ },
+ {
+ category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
+ threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
+ },
+ {
+ category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
+ threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
+ },
+ ].map((setting) => {
+ if (!safetyEnabled) {
+ setting.threshold = HarmBlockThreshold.BLOCK_NONE;
+ }
+ return setting;
+ });
+ return safetySettings;
+}
+
+async function handleGeminiError(err, loadingMsg) {
+ switch (err.message) {
+ case "[GoogleGenerativeAI Error]: Candidate was blocked due to SAFETY":
+ const safety_error = new EmbedBuilder()
+ .setTitle("⚠️ An Error Occurred")
+ .setDescription(
+ "> *The response was blocked due to **SAFETY**.* \n- *Result based on your input. Safety Blocking may not be 100% correct.*",
+ )
+ .setColor("Red");
+
+ return await loadingMsg.edit({ embeds: [safety_error] });
+ case "Cannot send an empty message":
+ const error_empty = new EmbedBuilder()
+ .setTitle("⚠️ An Error Occurred")
+ .setDescription(
+ "An error occurred while processing your request. Please try again later, or in a few minutes. \n▸ *If this issue persists, please contact the Developers.* \n> - Generated response may be too long. *(Fix this by specifying for the generated response to be smaller, e.g. 10 Lines)*\n> - Token Limit for this minute may have been reached.",
+ )
+ .setColor("Red");
+
+ return await loadingMsg.edit({ embeds: [error_empty] });
+ }
+
+ switch (err.status) {
+ case 400:
+ const location_error = new EmbedBuilder()
+ .setTitle("⚠️ An Error Occurred")
+ .setDescription(
+ "> *The user location is not supported for Gemini API use. Please contact the Developers.*",
+ )
+ .setColor("Red");
+
+ return await loadingMsg.edit({ embeds: [location_error] });
+ case 429:
+ const quota_error = new EmbedBuilder()
+ .setTitle("⚠️ An Error Occurred")
+ .setDescription(
+ "There are a lot of requests at the moment. Please try again later, or in a few minutes. \n▸ *If this issue persists after a few minutes, please contact the Developers.* \n - *We are aware of these issues and apologize for the inconvenience.* \n> - Token Limit for this minute has been reached.",
+ )
+ .setColor("Red");
+
+ const model = await db.get("model");
+ const fallbackSystem = model.fallbackSystem;
+ if (fallbackSystem) {
+ return "quotaErrorBalance";
+ } else {
+ for (let i = 5; i > 0; i--) {
+ quota_error.setFooter({ text: `⏱️ Retrying request in (${i})` });
+ await loadingMsg.edit({ embeds: [quota_error] });
+ await new Promise((resolve) => setTimeout(resolve, 1000));
+ }
+ return "quota_error";
+ }
+ case 500:
+ const error_internal = new EmbedBuilder()
+ .setTitle("⚠️ An Error Occurred")
+ .setDescription(
+ "An error occurred while processing your request. This error originated from Google's side, not ours. \n▸ *If this issue persists, please contact the Developers.* \n> - Please retry and make another request.",
+ )
+ .setColor("Red");
+
+ return await loadingMsg.edit({ embeds: [error_internal] });
+ case 403:
+ const invalid_api = new EmbedBuilder()
+ .setTitle("⚠️ Invalid API Key")
+ .setDescription(
+ "> **The API Key for Gemini is invalid or not provided.**",
+ )
+ .setColor("Red");
+ return await loadingMsg.edit({ embeds: [invalid_api] });
+ default:
+ console.error(err.message);
+ const error_unknown = new EmbedBuilder()
+ .setTitle("⚠️ An Error Occurred")
+ .setDescription(
+ "An unknown error occurred while processing your request. Please try again later, or in a few minutes. \n▸ *If this issue persists, please contact the Developers.*\n> - Token Limit for this minute may have been reached.",
+ )
+ .setColor("Red");
+
+ return await loadingMsg.edit({ embeds: [error_unknown] });
+ }
+}
+
+async function handleResponse(
+ chat,
+ userQuestion,
+ interaction,
+ message,
+ loadingMsg,
+ messageDeleted,
+ isContextMenuCommand,
+) {
+ const result = await chat.sendMessage(userQuestion);
+ const response = await result.response;
+ let responseText = response.text();
+
+ const responseLength = response.text().length;
+ if (responseLength > 2000) {
+ responseText =
+ response.text().substring(0, 1936 - "... \n\n".length) +
+ "... \n\n*Response was cut short due to Discords character limit of 2000*";
+ }
+
+ const regex = /<@&?\d+>/g;
+ let match;
+
+ while ((match = regex.exec(responseText)) !== null) {
+ const id =
+ message && message.author ? message.author.id : interaction.user.id;
+
+ if (match[0] !== `<@${id}>`) {
+ const ping_error = new EmbedBuilder()
+ .setTitle("⚠️ Response Cannot Be Sent")
+ .setDescription(
+ "> *The generated message contains a mention of a Role or different User to the one that sent the original message/command.*",
+ )
+ .setColor("Red");
+ return await loadingMsg.edit({ embeds: [ping_error] });
+ }
+ }
+
+ let info_embed = [];
+ if (isContextMenuCommand) {
+ const footerText = `Response to message by ${message.author.tag}\n\n${message.content}`;
+ const truncatedFooterText =
+ footerText.length > 2030 ? `${footerText.slice(0, 2027)}...` : footerText;
+
+ const info = new EmbedBuilder()
+ .setFooter({ text: truncatedFooterText })
+ .setColor("Blue");
+
+ info_embed.push(info);
+ }
+
+ switch (messageDeleted) {
+ case "threadDeleted":
+ const deletedThread = new EmbedBuilder()
+ .setFooter({
+ text: "A message has been deleted/is not accessible in the reply thread, Taurus does not know the past reply thread history.",
+ })
+ .setColor("Orange");
+
+ info_embed.push(deletedThread);
+ break;
+ case "slashCommand":
+ const deletedSlashCommand = new EmbedBuilder()
+ .setFooter({
+ text: "Reply thread history not accessible, utilise history by mentioning me to chat instead.",
+ })
+ .setColor("Orange");
+
+ info_embed.push(deletedSlashCommand);
+ break;
+ default:
+ break;
+ }
+
+ // responseText = responseText.replace(/(https?:\/\/(?!media\.discordapp\.net\/attachments\/)[^\s\)]+)/g, "<$1>");
+ return await loadingMsg.edit({ content: responseText, embeds: info_embed });
+}
+
+async function fetchThreadMessages(message) {
+ let threadMessages = [];
+ let messageDeleted;
+ userQuestion = message.content;
+
+ try {
+ const originalMessage = await message.channel.messages.fetch(
+ message.reference.messageId,
+ );
+
+ const startStrings = [
+ "Response to message by",
+ "A message has been deleted",
+ "Reply thread history",
+ ];
+
+ const linkRegex =
+ /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+
+ if (
+ originalMessage.author.id !== message.client.user.id ||
+ (originalMessage.embeds.length > 0 &&
+ (!originalMessage.embeds[0].footer ||
+ !originalMessage.embeds[0].footer.text ||
+ !startStrings.some((str) =>
+ originalMessage.embeds[0].footer.text.startsWith(str),
+ )) &&
+ !linkRegex.test(originalMessage.content))
+ ) {
+ return {
+ userQuestion: null,
+ threadMessages: null,
+ messageDeleted: "threadDeleted",
+ };
+ }
+
+ if (originalMessage.author.id === message.client.user.id) {
+ let currentMessage = message;
+
+ while (
+ currentMessage.reference &&
+ !(
+ currentMessage.author.id === message.client.user.id &&
+ currentMessage.embeds.length > 0 &&
+ !linkRegex.test(currentMessage.content)
+ )
+ ) {
+ currentMessage = await message.channel.messages.fetch(
+ currentMessage.reference.messageId,
+ );
+ const sender =
+ currentMessage.author.id === message.client.user.id
+ ? "model"
+ : "user";
+ let content = currentMessage.content;
+ if (sender === "user") {
+ content = content.replace(/<@\d+>\s*/, "");
+ } else if (
+ sender === "model" &&
+ currentMessage.embeds.length > 0 &&
+ currentMessage.embeds[0].footer &&
+ currentMessage.embeds[0].footer.text &&
+ currentMessage.embeds[0].footer.text.startsWith(
+ "Response to message by",
+ )
+ ) {
+ const footerText = currentMessage.embeds[0].footer.text;
+ const userMessage = footerText.split("\n")[2];
+ threadMessages.unshift({ role: sender, parts: [{ text: content }] });
+ threadMessages.unshift({
+ role: "user",
+ parts: [{ text: userMessage }],
+ });
+ continue;
+ }
+ threadMessages.unshift({ role: sender, parts: [{ text: content }] });
+ }
+ }
+ } catch (error) {
+ if (error instanceof DiscordAPIError && error.code === 10008) {
+ messageDeleted = "threadDeleted";
+ threadMessages = [];
+ } else {
+ throw error;
+ }
+ }
+
+ return { userQuestion, threadMessages, messageDeleted };
+}
+
+async function checkWebhook(webhookURL) {
+ try {
+ const webhookClient = new WebhookClient({ url: webhookURL });
+ return true;
+ } catch (error) {
+ return false;
+ }
+}
+
+const checkAPIKey = async (type, apiKey) => {
+ let url, headers;
+
+ switch (type.toLowerCase()) {
+ case "prodia":
+ url = "https://api.prodia.com/v1/sd/loras";
+ headers = { "X-Prodia-Key": apiKey, accept: "application/json" };
+ break;
+ case "gemini":
+ url = `https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}`;
+ headers = {};
+ break;
+ default:
+ throw new Error(`Invalid API type: ${type}`);
+ }
+
+ try {
+ const response = await axios.get(url, { headers });
+ return response.status === 200;
+ } catch (error) {
+ return false;
+ }
+};
+
+function checkOwnerAndReply(interaction) {
+ const no_access = new EmbedBuilder()
+ .setDescription("**⚠️ This is limited to Developers Only!**")
+ .setColor("Red");
+
+ if (!owner.includes(interaction.user.id)) {
+ interaction.reply({
+ embeds: [no_access],
+ ephemeral: true,
+ });
+ return false;
+ }
+ return true;
+}
+
+module.exports = {
+ botInGuild,
+ getSafetySettings,
+ handleGeminiError,
+ handleResponse,
+ fetchThreadMessages,
+ checkWebhook,
+ checkAPIKey,
+ checkOwnerAndReply,
+};
diff --git a/interactions/autocomplete/category/imageModel.js b/interactions/autocomplete/category/imageModel.js
new file mode 100644
index 0000000..68b07af
--- /dev/null
+++ b/interactions/autocomplete/category/imageModel.js
@@ -0,0 +1,54 @@
+/**
+ * @file Image Autocomplete Interaction
+ * @author TechyGiraffe999
+ */
+
+/**
+ * @type {import("../../../typings").AutocompleteInteraction}
+ */
+
+const { QuickDB } = require("quick.db");
+const path = require("path");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
+module.exports = {
+ name: "image",
+ async execute(interaction) {
+ const focusedOption = interaction.options.getFocused();
+
+ const apiKeys = await db.get("apiKeys");
+ const XProdiaKey = apiKeys.prodia;
+
+ const sdk = require("api")("@prodia/v1.3.0#6fdmny2flsvwyf65");
+ sdk.auth(XProdiaKey);
+
+ async function fetchAndFormatModels(apiMethod) {
+ try {
+ const { data } = await apiMethod();
+ const models = JSON.parse(data);
+ return models;
+ } catch (e) {
+ console.error("Error fetching models: ", e);
+ }
+ }
+
+ const [sdModels, sdxlModels] = await Promise.all([
+ fetchAndFormatModels(sdk.listModels),
+ fetchAndFormatModels(sdk.listSdxlModels),
+ ]);
+
+ const allModels = [...sdModels, ...sdxlModels];
+ const filteredModels = allModels.filter((model) =>
+ model.toLowerCase().startsWith(focusedOption.toLowerCase()),
+ );
+
+ const results = filteredModels.map((model) => ({
+ name: model,
+ value: model,
+ }));
+
+ await interaction.respond(results.slice(0, 25)).catch(() => {});
+ return;
+ },
+};
diff --git a/interactions/buttons/settings/apiKeys.js b/interactions/buttons/settings/apiKeys.js
new file mode 100644
index 0000000..e602013
--- /dev/null
+++ b/interactions/buttons/settings/apiKeys.js
@@ -0,0 +1,38 @@
+/**
+ * @file Settings API Key button interaction
+ * @author TechyGiraffe999
+ */
+
+/**
+ * @type {import('../../../typings').ButtonInteractionCommand}
+ */
+const {
+ ActionRowBuilder,
+ ModalBuilder,
+ TextInputBuilder,
+ TextInputStyle,
+} = require("discord.js");
+const { checkOwnerAndReply } = require("../../../functions/other/utils");
+module.exports = {
+ id: ["gemini", "prodia"],
+
+ async execute(interaction) {
+ if (!checkOwnerAndReply(interaction)) {
+ return;
+ }
+ const modal = new ModalBuilder()
+ .setCustomId(`${interaction.customId}`)
+ .setTitle("API Key Configuration");
+
+ const apiKeyForm = new TextInputBuilder()
+ .setCustomId("apiKey")
+ .setLabel("Your API Key")
+ .setPlaceholder("Your API Key Here")
+ .setMinLength(35)
+ .setMaxLength(50)
+ .setStyle(TextInputStyle.Short);
+
+ modal.addComponents(new ActionRowBuilder().addComponents(apiKeyForm));
+ return await interaction.showModal(modal);
+ },
+};
diff --git a/interactions/buttons/settings/model.js b/interactions/buttons/settings/model.js
new file mode 100644
index 0000000..c452eec
--- /dev/null
+++ b/interactions/buttons/settings/model.js
@@ -0,0 +1,70 @@
+/**
+ * @file Settings Other/Model Button interaction
+ * @author TechyGiraffe999
+ */
+
+/**
+ * @type {import('../../../typings').ButtonInteractionCommand}
+ */
+const { EmbedBuilder } = require("discord.js");
+const path = require("path");
+const { QuickDB } = require("quick.db");
+const { emojis } = require("../../../config.json");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
+const { checkOwnerAndReply } = require("../../../functions/other/utils");
+
+module.exports = {
+ id: ["fallbackSystem", "safetySystem", "model"],
+
+ async execute(interaction) {
+ if (!checkOwnerAndReply(interaction)) {
+ return;
+ }
+ const modelSettings = await db.get("model");
+ let updatedSetting;
+
+ switch (interaction.customId) {
+ case "fallbackSystem":
+ modelSettings.fallbackSystem = !modelSettings.fallbackSystem;
+ updatedSetting = `**🛡️ Fallback System ${modelSettings.fallbackSystem ? "Enabled" : "Disabled"}**`;
+ break;
+ case "safetySystem":
+ modelSettings.safetySystem = !modelSettings.safetySystem;
+ updatedSetting = `**${modelSettings.safetySystem ? "🔒" : "🔓"} Safety System ${modelSettings.safetySystem ? "Enabled" : "Disabled"}**`;
+ break;
+ case "model":
+ modelSettings.model =
+ modelSettings.model === "gemini-1.5-flash-latest"
+ ? "gemini-1.5-pro-latest"
+ : "gemini-1.5-flash-latest";
+ updatedSetting = `**🧠 Model switched to \`\`${modelSettings.model === "gemini-1.5-flash-latest" ? "Gemini 1.5 Flash" : "Gemini 1.5 Pro"}\`\`**`;
+ break;
+ }
+
+ await db.set("model", modelSettings);
+ const embed = new EmbedBuilder()
+ .setDescription(updatedSetting)
+ .setColor("Green");
+
+ const message = await interaction.message.fetch();
+ const embedData = message.embeds[0];
+ const otherFieldIndex = embedData.data.fields.find(
+ (field) => field.name === "🧠 Model:",
+ );
+ otherFieldIndex.value = `${modelSettings.fallbackSystem ? emojis.working : emojis.failed} **Fallback System**\n${modelSettings.safetySystem ? emojis.working : emojis.failed} **Safety System**\n${modelSettings.model === "gemini-1.5-flash-latest" ? "⚡" : "💪"} **${modelSettings.model
+ .replace(/-latest$/, "")
+ .replace(/-/g, " ")
+ .split(" ")
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
+ .join(" ")}**`;
+
+ message.edit({ embeds: [embedData] });
+
+ return await interaction.reply({
+ embeds: [embed],
+ ephemeral: true,
+ });
+ },
+};
diff --git a/interactions/buttons/settings/other.js b/interactions/buttons/settings/other.js
new file mode 100644
index 0000000..5658684
--- /dev/null
+++ b/interactions/buttons/settings/other.js
@@ -0,0 +1,54 @@
+/**
+ * @file Settings Other Button interaction
+ * @author TechyGiraffe999
+ */
+
+/**
+ * @type {import('../../../typings').ButtonInteractionCommand}
+ */
+const { EmbedBuilder } = require("discord.js");
+const path = require("path");
+const { QuickDB } = require("quick.db");
+const { emojis } = require("../../../config.json");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
+const { checkOwnerAndReply } = require("../../../functions/other/utils");
+
+module.exports = {
+ id: ["blockNSFWImages"],
+
+ async execute(interaction) {
+ if (!checkOwnerAndReply(interaction)) {
+ return;
+ }
+ const otherSettings = await db.get("other");
+ let updatedSetting;
+
+ switch (interaction.customId) {
+ case "blockNSFWImages":
+ otherSettings.blockNSFWImages = !otherSettings.blockNSFWImages;
+ updatedSetting = `**🔞 NSFW Image Blocking ${otherSettings.blockNSFWImages ? "Enabled" : "Disabled"}**`;
+ break;
+ }
+
+ await db.set("other", otherSettings);
+ const embed = new EmbedBuilder()
+ .setDescription(updatedSetting)
+ .setColor("Green");
+
+ const message = await interaction.message.fetch();
+ const embedData = message.embeds[0];
+ const otherFieldIndex = embedData.data.fields.find(
+ (field) => field.name === "⚙️ Other:",
+ );
+ otherFieldIndex.value = `${otherSettings.blockNSFWImages ? emojis.working : emojis.failed} **NSFW Image Blocking**`;
+
+ message.edit({ embeds: [embedData] });
+
+ return await interaction.reply({
+ embeds: [embed],
+ ephemeral: true,
+ });
+ },
+};
diff --git a/interactions/buttons/settings/webhooks.js b/interactions/buttons/settings/webhooks.js
new file mode 100644
index 0000000..5d0f142
--- /dev/null
+++ b/interactions/buttons/settings/webhooks.js
@@ -0,0 +1,38 @@
+/**
+ * @file Settings Webhook button interaction
+ * @author TechyGiraffe999
+ */
+
+/**
+ * @type {import('../../../typings').ButtonInteractionCommand}
+ */
+
+const {
+ ActionRowBuilder,
+ ModalBuilder,
+ TextInputBuilder,
+ TextInputStyle,
+} = require("discord.js");
+const { checkOwnerAndReply } = require("../../../functions/other/utils");
+
+module.exports = {
+ id: ["personality", "console"],
+
+ async execute(interaction) {
+ if (!checkOwnerAndReply(interaction)) {
+ return;
+ }
+ const modal = new ModalBuilder()
+ .setCustomId(`${interaction.customId}`)
+ .setTitle("Webhook Configuration");
+
+ const webhookForm = new TextInputBuilder()
+ .setCustomId("webhook")
+ .setLabel("Your Webhook")
+ .setPlaceholder("Your Webhook URL Here")
+ .setStyle(TextInputStyle.Paragraph);
+
+ modal.addComponents(new ActionRowBuilder().addComponents(webhookForm));
+ return await interaction.showModal(modal);
+ },
+};
diff --git a/interactions/context-menus/message/taurusai.js b/interactions/context-menus/message/taurusai.js
new file mode 100644
index 0000000..d64b276
--- /dev/null
+++ b/interactions/context-menus/message/taurusai.js
@@ -0,0 +1,185 @@
+/**
+ * @file Taurus Context Menu.
+ * @author TechyGiraffe999
+ */
+
+/**
+ * @type {import("../../../typings").ContextInteractionCommand}
+ */
+
+const { EmbedBuilder } = require("discord.js");
+const fs = require("fs").promises;
+const path = require("path");
+const { GoogleGenerativeAI } = require("@google/generative-ai");
+const {
+ getSafetySettings,
+ handleGeminiError,
+ handleResponse,
+ fetchThreadMessages,
+} = require("../../../functions/other/utils");
+const { QuickDB } = require("quick.db");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
+
+module.exports = {
+ data: {
+ name: "Taurus",
+ type: 3,
+ },
+
+ async execute(interaction) {
+ const { channel, targetId } = interaction;
+ const apiKeys = await db.get("apiKeys");
+ const geminiApiKey = apiKeys.gemini;
+ const modelSettings = await db.get("model");
+ let modelId = modelSettings.model;
+ const genAI = new GoogleGenerativeAI(geminiApiKey);
+
+ const message = await channel.messages.fetch(targetId);
+
+ if (message.author.bot || message.author.id === message.client.user.id) {
+ return interaction.reply({
+ content: "I cant reply to myself or another bot!",
+ ephemeral: true,
+ });
+ }
+
+ let userQuestion;
+ let messageDeleted;
+ let threadMessages = [];
+
+ if (message.reference) {
+ const {
+ userQuestion: fetchedUserQuestion,
+ threadMessages: fetchedThreadMessages,
+ messageDeleted: fetchedMessageDeleted,
+ } = await fetchThreadMessages(geminiApiKey, message);
+ if (fetchedUserQuestion === null && fetchedThreadMessages === null)
+ return;
+ threadMessages = fetchedThreadMessages;
+ userQuestion = fetchedUserQuestion;
+ messageDeleted = fetchedMessageDeleted;
+ } else if (!message.reference) {
+ const botMention = `<@${message.client.user.id}>`;
+ const regex = new RegExp(`^${botMention}\\s+.+`);
+
+ userQuestion = message.content.replace(botMention, "").trim();
+ }
+
+ const sendTypingInterval = setInterval(() => {
+ interaction.channel.sendTyping();
+ }, 5000);
+
+ const user = message.author;
+
+ let loadingInterval;
+ let loadingMsg;
+
+ async function run() {
+ const loadingEmbed = new EmbedBuilder()
+ .setTitle("**⌛Loading your response**")
+ .setDescription(
+ "*TaurusAI may display innacurate/offensive info.*\n\n> *I am powered by Google's Generative AI, [Gemini](https://gemini.google.com) and was integrated by <@719815864135712799>.*",
+ )
+ .setFooter({
+ text: "This may take a while",
+ iconURL: `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png?size=256`,
+ })
+ .setTimestamp();
+ loadingMsg = loadingMsg
+ ? await loadingMsg.edit({ embeds: [loadingEmbed] })
+ : await interaction.reply({ embeds: [loadingEmbed] });
+ const loadingDots = [" ⌛ ", " ⏳ "];
+ let i = 0;
+ const loadingInterval = setInterval(() => {
+ loadingEmbed.setTitle(`**${loadingDots[i]} Loading your response**`);
+ loadingMsg.edit({ embeds: [loadingEmbed] });
+ i = (i + 1) % loadingDots.length;
+ }, 2000);
+
+ const personalityFilePath = path.join(
+ __dirname + "../../../../personality.txt",
+ );
+ const personalityContent = await fs.readFile(
+ personalityFilePath,
+ "utf-8",
+ );
+ const personalityLines = personalityContent.split("\n");
+
+ const botMention = `<@${message.client.user.id}>`;
+
+ userQuestion = message.content.replace(botMention, "").trim();
+
+ const user_status = message.member?.presence.clientStatus || {};
+ const status_devices = Object.entries(user_status)
+ .map(([platform, status]) => `${platform}: ${status}`)
+ .join("\n");
+
+ instruction = `${personalityLines}\n Please greet the user with a greeting and then their name which is: <@${message.author.id}> and limit your responses to 2000 characters or less.`;
+
+ if (Object.keys(user_status).length) {
+ instruction += ` The user's status/presence is currently:\n${status_devices}`;
+ }
+
+ const generationConfig = {
+ maxOutputTokens: 750,
+ };
+
+ const model = genAI.getGenerativeModel({
+ model: modelId,
+ systemInstruction: instruction,
+ safetySettings: await getSafetySettings(),
+ generationConfig,
+ });
+
+ if (
+ threadMessages &&
+ threadMessages.length > 0 &&
+ threadMessages[0].role === "model"
+ ) {
+ messageDeleted = "threadDeleted";
+ threadMessages = [];
+ }
+
+ const chat = model.startChat({
+ history: threadMessages,
+ generationConfig: {
+ maxOutputTokens: 750,
+ },
+ });
+
+ clearInterval(loadingInterval);
+ sendTypingInterval && clearInterval(sendTypingInterval);
+ await handleResponse(
+ chat,
+ userQuestion,
+ interaction,
+ message,
+ loadingMsg,
+ messageDeleted,
+ true,
+ );
+ }
+
+ let errorType = null;
+ do {
+ try {
+ await run();
+ errorType = null;
+ } catch (err) {
+ clearInterval(loadingInterval);
+ sendTypingInterval && clearInterval(sendTypingInterval);
+
+ errorType = await handleGeminiError(err, loadingMsg);
+
+ if (errorType === "quotaErrorBalance") {
+ modelId =
+ modelId === "gemini-1.5-pro-latest"
+ ? "gemini-1.5-flash-latest"
+ : "gemini-1.5-pro-latest";
+ }
+ }
+ } while (errorType === "quota_error" || errorType === "quotaErrorBalance");
+ },
+};
diff --git a/interactions/modals/AI/ask.js b/interactions/modals/AI/ask.js
new file mode 100644
index 0000000..b08b4bc
--- /dev/null
+++ b/interactions/modals/AI/ask.js
@@ -0,0 +1,139 @@
+/**
+ * @file TaurusAI Ask Modal.
+ * @author TechyGiraffe999
+ */
+
+/**
+ * @type {import("../../../../typings").ModalInteractionCommand}
+ */
+const fs = require("fs").promises;
+const path = require("path");
+const { EmbedBuilder } = require("discord.js");
+const { GoogleGenerativeAI } = require("@google/generative-ai");
+const {
+ botInGuild,
+ getSafetySettings,
+ handleGeminiError,
+ handleResponse,
+} = require("../../../functions/other/utils");
+const { QuickDB } = require("quick.db");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
+
+module.exports = {
+ id: "taurus_ai",
+
+ async execute(interaction) {
+ const apiKeys = await db.get("apiKeys");
+ const geminiApiKey = apiKeys.gemini;
+ const modelSettings = await db.get("model");
+ let modelId = modelSettings.model;
+ const genAI = new GoogleGenerativeAI(geminiApiKey);
+
+ const personalityFilePath = path.join(
+ __dirname + "../../../../personality.txt",
+ );
+ const personalityContent = await fs.readFile(personalityFilePath, "utf-8");
+ const personalityLines = personalityContent.split("\n");
+
+ const userQuestion =
+ interaction.fields.getTextInputValue("question_taurusai");
+
+ const sendTypingInterval =
+ interaction.inGuild() && botInGuild(interaction)
+ ? setInterval(() => {
+ interaction.channel.sendTyping();
+ }, 5000)
+ : null;
+
+ let loadingInterval;
+ let loadingMsg;
+
+ async function run() {
+ const loadingEmbed = new EmbedBuilder()
+ .setTitle("**Loading your response . . .**")
+ .setDescription(
+ "*TaurusAI may display innacurate/offensive info.*\n\n> *I am powered by Google's Generative AI, [Gemini](https://gemini.google.com) and was integrated by <@719815864135712799>.*",
+ )
+ .setFooter({
+ text: "⏳ This may take a while",
+ iconURL: interaction.user.displayAvatarURL(),
+ })
+ .setTimestamp();
+ loadingMsg = loadingMsg
+ ? await loadingMsg.edit({ embeds: [loadingEmbed] })
+ : await interaction.reply({ embeds: [loadingEmbed] });
+ const loadingDots = ["", " . ", " . . ", " . . ."];
+ let i = 0;
+ const loadingInterval = setInterval(async () => {
+ loadingEmbed.setTitle(`**Loading your response ${loadingDots[i]}**`);
+ await loadingMsg.edit({ embeds: [loadingEmbed] });
+ i = (i + 1) % loadingDots.length;
+ }, 500);
+
+ const user_status =
+ interaction.inGuild() && botInGuild(interaction)
+ ? interaction.member?.presence.clientStatus
+ : {};
+
+ const status_devices = Object.entries(user_status)
+ .map(([platform, status]) => `${platform}: ${status}`)
+ .join("\n");
+
+ instruction = `${personalityLines}\n Please greet the user with a greeting and then their name which is: <@${interaction.user.id}> and limit your responses to 2000 characters or less.`;
+
+ if (Object.keys(user_status).length) {
+ instruction += ` The user's status/presence is currently:\n${status_devices}`;
+ }
+
+ const generationConfig = {
+ maxOutputTokens: 750,
+ };
+
+ const model = genAI.getGenerativeModel({
+ model: modelId,
+ systemInstruction: instruction,
+ safetySettings: await getSafetySettings(),
+ generationConfig,
+ });
+
+ const chat = model.startChat({
+ generationConfig: {
+ maxOutputTokens: 750,
+ },
+ });
+
+ clearInterval(loadingInterval);
+ clearInterval(sendTypingInterval);
+ await handleResponse(
+ chat,
+ userQuestion,
+ interaction,
+ false,
+ loadingMsg,
+ "slashCommand",
+ );
+ }
+
+ let errorType = null;
+ do {
+ try {
+ await run();
+ errorType = null;
+ } catch (err) {
+ clearInterval(loadingInterval);
+ sendTypingInterval && clearInterval(sendTypingInterval);
+
+ errorType = await handleGeminiError(err, loadingMsg);
+
+ if (errorType === "quotaErrorBalance") {
+ modelId =
+ modelId === "gemini-1.5-pro-latest"
+ ? "gemini-1.5-flash-latest"
+ : "gemini-1.5-pro-latest";
+ }
+ }
+ } while (errorType === "quota_error" || errorType === "quotaErrorBalance");
+ },
+};
diff --git a/interactions/modals/Settings/apiKeys.js b/interactions/modals/Settings/apiKeys.js
new file mode 100644
index 0000000..459539c
--- /dev/null
+++ b/interactions/modals/Settings/apiKeys.js
@@ -0,0 +1,92 @@
+/**
+ * @file APIKey Settings Modal.
+ * @author TechyGiraffe999
+ */
+
+/**
+ * @type {import("../../../../typings").ModalInteractionCommand}
+ */
+const fs = require("fs").promises;
+const path = require("path");
+const { EmbedBuilder } = require("discord.js");
+const { checkAPIKey } = require("../../../functions/other/utils");
+const { emojis } = require("../../../config.json");
+const { QuickDB } = require("quick.db");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
+
+module.exports = {
+ id: ["gemini", "prodia"],
+
+ async execute(interaction) {
+ const apiKeyName =
+ interaction.customId.charAt(0).toUpperCase() +
+ interaction.customId.slice(1);
+ embed = new EmbedBuilder()
+ .setDescription(`**${emojis.loading} Checking ${apiKeyName} API Key**`)
+ .setColor("Green");
+
+ await interaction.reply({ embeds: [embed], ephemeral: true });
+ const apiKey = interaction.fields.getTextInputValue("apiKey");
+ const apiKeys = await db.get("apiKeys");
+
+ if (apiKeys[interaction.customId] === apiKey) {
+ const alreadyRegistered = new EmbedBuilder()
+ .setDescription(
+ `**🔑 ${apiKeyName} API Key is already registered. (Duplicate Key)**`,
+ )
+ .setColor("Yellow");
+ await interaction.editReply({
+ embeds: [alreadyRegistered],
+ ephemeral: true,
+ });
+ return;
+ }
+
+ let isValidKey;
+ isValidKey = await checkAPIKey(interaction.customId, apiKey);
+
+ if (!isValidKey) {
+ const invalidKey = new EmbedBuilder()
+ .setDescription(
+ `**🔑 ${apiKeyName} API Key Checking Failed, Key invalid**`,
+ )
+ .setColor("Red");
+ await interaction.editReply({ embeds: [invalidKey] });
+ return;
+ }
+
+ const successEmbed = new EmbedBuilder()
+ .setDescription(
+ `**🔑 ${apiKeyName} API Key Checking Successful, the Key was updated!**`,
+ )
+ .setColor("Green");
+ await interaction.editReply({ embeds: [successEmbed] });
+
+ const message = await interaction.message.fetch();
+ const embedData = message.embeds[0];
+
+ const apiKeysFieldIndex = embedData.data.fields.findIndex(
+ (field) => field.name === "🔑 API Keys:",
+ );
+ const apiKeysFieldValue = embedData.data.fields[apiKeysFieldIndex].value;
+ const prodiaKeyStatus = apiKeysFieldValue.split("\n")[0];
+ const geminiKeyStatus = apiKeysFieldValue.split("\n")[1];
+
+ switch (interaction.customId) {
+ case "prodia":
+ apiKeys.prodia = apiKey;
+ embedData.data.fields[apiKeysFieldIndex].value =
+ `${isValidKey ? emojis.working : emojis.failed} **Prodia**\n${geminiKeyStatus}`;
+ break;
+ case "gemini":
+ apiKeys.gemini = apiKey;
+ embedData.data.fields[apiKeysFieldIndex].value =
+ `${prodiaKeyStatus}\n${isValidKey ? emojis.working : emojis.failed} **Gemini**`;
+ }
+
+ await db.set("apiKeys", apiKeys);
+ await message.edit({ embeds: [embedData] });
+ },
+};
diff --git a/interactions/modals/Settings/webhooks.js b/interactions/modals/Settings/webhooks.js
new file mode 100644
index 0000000..7ca2947
--- /dev/null
+++ b/interactions/modals/Settings/webhooks.js
@@ -0,0 +1,111 @@
+/**
+ * @file Webhook Settings Modal.
+ * @author TechyGiraffe999
+ */
+
+/**
+ * @type {import("../../../../typings").ModalInteractionCommand}
+ */
+const fs = require("fs").promises;
+const path = require("path");
+const { EventEmitter } = require("events");
+const webhookUpdateEvent = new EventEmitter();
+const { EmbedBuilder, WebhookClient } = require("discord.js");
+const { checkWebhook } = require("../../../functions/other/utils");
+const { emojis } = require("../../../config.json");
+const { QuickDB } = require("quick.db");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
+
+module.exports = {
+ id: ["personality", "console"],
+ webhookUpdateEvent,
+
+ async execute(interaction) {
+ const webhookName =
+ interaction.customId.charAt(0).toUpperCase() +
+ interaction.customId.slice(1);
+ embed = new EmbedBuilder()
+ .setDescription(`**${emojis.loading} Checking ${webhookName} Webhook**`)
+ .setColor("Green");
+
+ await interaction.reply({ embeds: [embed], ephemeral: true });
+ const webhook = interaction.fields.getTextInputValue("webhook");
+ const webhooks = await db.get("webhooks");
+
+ let isValidWebhook;
+ isValidWebhook = await checkWebhook(webhook);
+
+ if (webhooks[interaction.customId] === webhook) {
+ const alreadyRegistered = new EmbedBuilder()
+ .setDescription(
+ `**🔑 ${webhookName} Webhook is already registered. (Duplicate Webhook)**`,
+ )
+ .setColor("Yellow");
+ await interaction.editReply({
+ embeds: [alreadyRegistered],
+ ephemeral: true,
+ });
+ return;
+ }
+
+ if (!isValidWebhook) {
+ const invalidWebhook = new EmbedBuilder()
+ .setDescription(
+ `**🔑 ${webhookName} Webhook Checking Failed, Webhook invalid**`,
+ )
+ .setColor("Red");
+ await interaction.editReply({ embeds: [invalidWebhook] });
+ return;
+ }
+
+ webhookClient = new WebhookClient({ url: webhook });
+ const emoji = interaction.customId === "console" ? "💾" : "✨";
+ const webhookEmbed = new EmbedBuilder()
+ .setDescription(
+ `**${emoji} Taurus ${webhookName} Webhook Registered, Updates will be logged here**`,
+ )
+ .setColor("Green");
+ webhookClient
+ .send({
+ username: `Taurus ${webhookName}`,
+ avatarURL: interaction.client.user.displayAvatarURL(),
+ embeds: [webhookEmbed],
+ })
+ .catch(console.error);
+
+ const successEmbed = new EmbedBuilder()
+ .setDescription(
+ `**🔑 ${webhookName} Webhook Checking Successful, the Webhook was updated!**`,
+ )
+ .setColor("Green");
+ await interaction.editReply({ embeds: [successEmbed] });
+
+ const message = await interaction.message.fetch();
+ const embedData = message.embeds[0];
+
+ const webhookFieldIndex = embedData.data.fields.findIndex(
+ (field) => field.name === "🔗 Webhooks:",
+ );
+ const webhooksFieldValue = embedData.data.fields[webhookFieldIndex].value;
+ const personalityWebhookStatus = webhooksFieldValue.split("\n")[0];
+ const consoleWebhookStatus = webhooksFieldValue.split("\n")[1];
+
+ switch (interaction.customId) {
+ case "personality":
+ webhooks.personality = webhook;
+ embedData.data.fields[webhookFieldIndex].value =
+ `${isValidWebhook ? emojis.working : emojis.failed} **Personality**\n${consoleWebhookStatus}`;
+ break;
+ case "console":
+ webhooks.console = webhook;
+ embedData.data.fields[webhookFieldIndex].value =
+ `${personalityWebhookStatus}\n${isValidWebhook ? emojis.working : emojis.failed} **Console**`;
+ webhookUpdateEvent.emit("update", webhooks.console);
+ }
+
+ await db.set("webhooks", webhooks);
+ await message.edit({ embeds: [embedData] });
+ },
+};
diff --git a/interactions/modals/category/ask.js b/interactions/modals/category/ask.js
deleted file mode 100644
index c4c514e..0000000
--- a/interactions/modals/category/ask.js
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * @file TaurusAI Ask Modal.
- * @author TechyGiraffe999
- */
-
-/**
- * @type {import("../../../../typings").ModalInteractionCommand}
- */
-const fs = require('fs').promises;
-const path = require('path');
-const { EmbedBuilder } = require("discord.js");
-const { GoogleGenerativeAI, HarmBlockThreshold, HarmCategory } = require("@google/generative-ai");
-const { Gemini_API_KEY } = require("../../../config.json");
-const genAI = new GoogleGenerativeAI(Gemini_API_KEY);
-
-
-module.exports = {
- id: "taurus_ai",
-
- async execute(interaction) {
- if (!Gemini_API_KEY || Gemini_API_KEY.length < 4) {
- invalid_api = new EmbedBuilder()
- .setTitle("⚠️ Invalid API Key")
- .setDescription("> **The API Key for Gemini is invalid or not provided.**")
- .setColor("Red")
- return interaction.reply({ embeds: [invalid_api] });
- }
-
- const personalityFilePath = path.join(__dirname + '../../../../personality.txt');
- const personalityContent = await fs.readFile(personalityFilePath, 'utf-8');
- const personalityLines = personalityContent.split('\n');
-
- const userQuestion = interaction.fields.getTextInputValue("question_taurusai");
-
- const sendTypingInterval = setInterval(() => {
- interaction.channel.sendTyping();
- }, 5000);
-
- const loadingEmbed = new EmbedBuilder()
- .setTitle("**Loading your response . . .**")
- .setDescription("*TaurusAI may display innacurate/offensive info.*\n\n> *I am powered by Google's Generative AI, [Gemini](https://gemini.google.com) and was integrated by <@719815864135712799>.*")
- .setFooter({text: "⏳ This may take a while", iconURL: interaction.user.displayAvatarURL()})
- .setTimestamp()
- const loadingMsg = await interaction.reply({ embeds: [loadingEmbed]
- //, ephemeral: true
- });
- const loadingDots = [""," . ", " . . ", " . . ."];
- let i = 0;
- const loadingInterval = setInterval(async () => {
- loadingEmbed.setTitle(`**Loading your response ${loadingDots[i]}**`);
- await loadingMsg.edit({ embeds: [loadingEmbed] });
- i = (i + 1) % loadingDots.length;
- }, 500);
-
- const safetySettings = [
- {
- category: HarmCategory.HARM_CATEGORY_HARASSMENT,
- threshold: HarmBlockThreshold.BLOCK_ONLY_HIGH,
- },
- {
- category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
- threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
- },
- {
- category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
- threshold: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE,
- },
- {
- category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
- threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
- },
- ];
-
- const user_status = interaction.member?.presence.clientStatus || {}
- const status_devices = Object.entries(user_status)
- .map(([platform, status]) => `${platform}: ${status}`)
- .join("\n");
-
- parts1 = `${personalityLines}\n Please greet the user with a greeting and then their name which is: <@${interaction.user.id}>.`
-
- if (Object.keys(user_status).length) {
- parts1 += ` The user's presence is currently:\n${status_devices}`;
- }
-
- async function run() {
- const generationConfig = {
- maxOutputTokens: 750,
- };
- const model = genAI.getGenerativeModel({ model: "gemini-pro", safetySettings, generationConfig});
-
- const chat = model.startChat({
- history: [
- {
- role: "user",
- parts: parts1,
- },
- {
- role: "model",
- parts: `I will greet the user with their name: <@${interaction.user.id}>. I will also limit all of my responses to 2000 characters or less, regardless of what you say. Feel feel free to ask me anything! 😊`,
- },
- ],
- generationConfig: {
- maxOutputTokens: 750,
- },
- });
-
-
- const result = await chat.sendMessage(userQuestion);
- const response = await result.response;
-
- const responseLength = response.text().length;
- if (responseLength > 2000) {
- response.text = response.text().substring(0, 1928 - "... \n\n".length) + "... \n\n*Response was cut short due to Discords character limit of 2000*";
- }
- clearInterval(loadingInterval);
- clearInterval(sendTypingInterval);
-
- let responseText = response.text();
- const regex = /<@&?\d+>/g;
- let match;
-
- while ((match = regex.exec(responseText)) !== null) {
- if (match[0] !== `<@${interaction.user.id}>`) {
- const ping_error = new EmbedBuilder()
- .setTitle("⚠️ Response Cannot Be Sent")
- .setDescription("> *The generated message contains a mention of a Role or different User to the one that sent the original message/command.*")
- .setColor("Red")
- return await interaction.editReply({ embeds: [ping_error] });
- }
- }
-
- responseText = responseText.replace(/(?");
- return await loadingMsg.edit({ content: responseText, embeds: [] });
- }
-
- try{
- await run();
- } catch (err) {
- clearInterval(loadingInterval);
- clearInterval(sendTypingInterval);
-
- switch (err.message) {
- case "[GoogleGenerativeAI Error]: Text not available. Response was blocked due to SAFETY":
- const safety_error = new EmbedBuilder()
- .setTitle("⚠️ An Error Occurred")
- .setDescription("> *The response was blocked due to **SAFETY**.*")
- .setColor("Red")
-
- return await interaction.editReply({ embeds: [safety_error]});
-
- case "[GoogleGenerativeAI Error]: Error fetching from https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent: [400 Bad Request] User location is not supported for the API use.":
- const location_error = new EmbedBuilder()
- .setTitle("⚠️ An Error Occurred")
- .setDescription("> *The user location is not supported for Gemini API use. Please contact the Developers.*")
- .setColor("Red")
-
- return await interaction.editReply({ embeds: [location_error]});
-
- case "Cannot send an empty message":
- case "response.text is not a function":
- const error = new EmbedBuilder()
- .setTitle("⚠️ An Error Occurred")
- .setDescription("An error occurred while processing your request. Please try again later, or in a few minutes. \n*If this issue persists, please contact the Developers.* \n\n> - Generated response may be too long. *(Fix this by specifying for the generated response to be smaller, e.g. 10 Lines)*\n> - Token Limit for this minute may have been reached.")
- .setColor("Red")
-
- return await interaction.editReply({ embeds: [error]});
-
- default:
- const error_unknown = new EmbedBuilder()
- .setTitle("⚠️ An Error Occurred")
- .setDescription("An unknown error occurred while processing your request. Please try again later, or in a few minutes. \n*If this issue persists, please contact the Developers.*\n> - Token Limit for this minute may have been reached.")
- .setColor("Red")
-
- await interaction.editReply({embeds: [error_unknown]
- });
- }
- }
- }
-};
\ No newline at end of file
diff --git a/interactions/slash/misc/help.js b/interactions/slash/misc/help.js
index f376bca..62b9f6f 100644
--- a/interactions/slash/misc/help.js
+++ b/interactions/slash/misc/help.js
@@ -3,25 +3,32 @@
* @author TechyGiraffe999
*/
-
const { EmbedBuilder, SlashCommandBuilder, Embed } = require("discord.js");
/**
* @type {import('../../../typings').SlashInteractionCommand}
*/
module.exports = {
- data: new SlashCommandBuilder()
- .setName('help')
- .setDescription('Display available slash commands'),
- async execute(interaction, client) {
- const commands = interaction.client.slashCommands;
- const commandList = commands.map((command) => `**/${command.data.name}**: ${command.data.description}`).join('\n');
+ data: new SlashCommandBuilder()
+ .setName("help")
+ .setDescription("Display available slash commands"),
+ async execute(interaction) {
+ const commands = (
+ await interaction.client.application.commands.fetch()
+ ).filter((command) => command.type === 1);
+
+ const commandList = commands
+ .map(
+ (command) =>
+ `**${command.name}:${command.id}>**: ${command.description}`,
+ )
+ .join("\n");
- const embed = new EmbedBuilder()
- .setTitle("⚙️ Available Commands")
- .setDescription(commandList)
- .setColor("Blurple")
+ const embed = new EmbedBuilder()
+ .setTitle("⚙️ Available Commands")
+ .setDescription(commandList)
+ .setColor("Blurple");
- await interaction.reply({ embeds: [embed] });
- },
-};
\ No newline at end of file
+ await interaction.reply({ embeds: [embed] });
+ },
+};
diff --git a/interactions/slash/misc/image.js b/interactions/slash/misc/image.js
index 7422310..c8f48d3 100644
--- a/interactions/slash/misc/image.js
+++ b/interactions/slash/misc/image.js
@@ -7,237 +7,366 @@
* @type {import('../../../typings').SlashInteractionCommand}
*/
-const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
-const {XProdiaKey, Block_NSFW_Images} = require('../../../config.json')
+const { SlashCommandBuilder, EmbedBuilder } = require("discord.js");
+const { checkAPIKey } = require("../../../functions/other/utils");
const translate = require("@iamtraction/google-translate");
-const axios = require('axios');
-const tf = require('@tensorflow/tfjs-node');
-const nsfw = require('nsfwjs');
+const { QuickDB } = require("quick.db");
+const path = require("path");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
+const axios = require("axios");
+const tf = require("@tensorflow/tfjs-node");
+const nsfw = require("nsfwjs");
+
+let nsfwModelPromise = null;
+
+async function loadNsfwModel() {
+ if (!nsfwModelPromise) {
+ nsfwModelPromise = nsfw.load();
+ }
+ return nsfwModelPromise;
+}
+
+function resizeImage(imageTensor) {
+ const [height, width] = imageTensor.shape.slice(0, 2);
+ const aspectRatio = width / height;
+
+ let newWidth, newHeight;
+
+ if (aspectRatio > 1) {
+ newHeight = 224;
+ newWidth = Math.round(aspectRatio * 224);
+ } else {
+ newWidth = 224;
+ newHeight = Math.round(224 / aspectRatio);
+ }
+
+ const resizedImage = tf.image.resizeBilinear(imageTensor, [
+ newHeight,
+ newWidth,
+ ]);
+ return resizedImage;
+}
+
+async function nsfwGetPic(image, nsfw_embed, interaction) {
+ const model = await loadNsfwModel();
+ const pic = await axios.get(image, { responseType: "arraybuffer" });
+ const imageTensor = tf.node.decodeImage(pic.data, 3);
+
+ const resizedImage = resizeImage(imageTensor);
+ imageTensor.dispose();
+
+ const predictions = await model.classify(resizedImage);
+ resizedImage.dispose();
+
+ if (
+ (predictions[0].probability > 0.5 && predictions[0].className === "Porn") ||
+ predictions[0].className === "Hentai" ||
+ predictions[0].className === "Sexy"
+ ) {
+ await interaction.followUp({ embeds: [nsfw_embed] });
+ return true;
+ }
+ return image;
+}
+
+let nsfwWordsCache = null;
+
+async function getNsfwWords() {
+ if (!nsfwWordsCache) {
+ const response = await fetch(
+ "https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/en",
+ );
+ const data = await response.text();
+ nsfwWordsCache = data
+ .split("\n")
+ .filter((word) => word !== "suck" && word !== "sucks");
+ }
+ return nsfwWordsCache;
+}
module.exports = {
- data: new SlashCommandBuilder()
- .setName('image')
- .setDescription('Have AI generate an image!')
- .addStringOption(o => o.setName('prompt').setDescription('The description of the image to generate!').setRequired(true))
- .addStringOption(o => o.setName('model').setDescription('The Model to Use'))
- .addStringOption(o => o.setName('negative-prompt').setDescription('The Negative Prompt to Use'))
- .addIntegerOption(option =>
- option.setName("steps")
- .setDescription("The Number of Steps to Use")
- .setMinValue(1)
- .setMaxValue(30)
- )
- .addIntegerOption(option =>
- option.setName("cfg-scale")
- .setDescription("The CFG Scale")
- .setMinValue(1)
- .setMaxValue(30)
- )
- .addIntegerOption(option =>
- option.setName("seed")
- .setDescription("The Seed")
- .setMinValue(-1)
- )
- .addStringOption(option =>
- option.setName("style-preset")
- .setDescription("The Image Style Prese")
+ data: new SlashCommandBuilder()
+ .setName("image")
+ .setDescription("Have AI generate an image!")
+ .addStringOption((o) =>
+ o
+ .setName("prompt")
+ .setDescription("The description of the image to generate!")
+ .setRequired(true),
+ )
+ .addStringOption((o) =>
+ o
+ .setName("model")
+ .setDescription("The Model to Use")
+ .setAutocomplete(true),
+ )
+ .addStringOption((o) =>
+ o.setName("negative-prompt").setDescription("The Negative Prompt to Use"),
+ )
+ .addIntegerOption((option) =>
+ option
+ .setName("steps")
+ .setDescription("The Number of Steps to Use")
+ .setMinValue(1)
+ .setMaxValue(50),
+ )
+ .addIntegerOption((option) =>
+ option
+ .setName("cfg-scale")
+ .setDescription("The CFG Scale")
+ .setMinValue(1)
+ .setMaxValue(20),
+ )
+ .addIntegerOption((option) =>
+ option.setName("seed").setDescription("The Seed").setMinValue(-1),
+ )
+ .addStringOption((option) =>
+ option
+ .setName("style-preset")
+ .setDescription("The Image Style Preset")
.addChoices(
{ name: "3d Model", value: "3d-model" },
{ name: "Analog Film", value: "analog-film" },
- { name: "Anime", value: "anime" },
- { name: "Cinematic", value: "cinematic" },
- { name: "Comic Book", value: "comic-book" },
- { name: "Digital Art", value: "digital-art" },
- { name: "Enhance", value: "enhance" },
- { name: "Fantasy Art", value: "fantasy-art" },
- { name: "Isometric", value: "isometric" },
- { name: "Line Art", value: "line-art" },
- { name: "Low Poly", value: "low-poly" },
- { name: "Neon Punk", value: "neon-punk" },
- { name: "Origami", value: "origami" },
- { name: "Photographic", value: "photographic" },
- { name: "Pixel Art", value: "pixel-art" },
- { name: "Texture", value: "texture" },
- { name: "Craft Clay", value: "craft-clay" },
- ))
- .addStringOption(option =>
- option.setName("sampler")
- .setDescription("The Image Sampler")
- .addChoices(
- { name: "Euler a", value: "Euler a" },
- { name: "LMS", value: "LMS" },
- { name: "Heun", value: "Heun" },
- { name: "DPM2", value: "DPM2" },
- { name: "DPM2 a", value: "DPM2 a" },
- { name: "DPM++ 2S a", value: "DPM++ 2S a" },
- { name: "DPM++ 2M", value: "DPM++ 2M" },
- { name: "DPM++ 2M SDE", value: "DPM++ 2M SDE" },
- { name: "DPM++ 2M SDE Heun Karras", value: "DPM++ 2M SDE Heun Karras" },
- { name: "DPM++ 3M SD", value: "DPM++ 3M SD" },
- { name: "DPM++ 3M SD Karras", value: "DPM++ 3M SD Karras" },
- { name: "DPM++ 3M SD Exponential", value: "DPM++ 3M SD Exponential" },
- { name: "DPM fast", value: "DPM fast" },
- { name: "DPM adaptive", value: "DPM adaptive" },
- { name: "LMS Karras", value: "LMS Karras" },
- { name: "DPM2 Karras", value: "DPM2 Karras" },
- { name: "DPM2 a Karras", value: "DPM2 a Karras" },
- { name: "DPM++ 2S a Karras", value: "DPM++ 2S a Karras" },
- { name: "DPM++ 2M Karras", value: "DPM++ 2M Karras" },
- { name: "DPM++ SDE Karras", value: "DPM++ SDE Karras" },
- { name: "DPM++ SDE Karras", value: "DPM++ SDE Karras" },
- { name: "DPM++ 2M SDE Exponential", value: "DPM++ 2M SDE Exponential" },
- { name: "DDIM", value: "DDIM" },
- { name: "PLMS", value: "PLMS" },
- { name: "UniPC", value: "UniPC" },
- )),
-
- async execute(interaction, client) {
-
- if (!XProdiaKey || XProdiaKey.length < 4) {
- invalid_api = new EmbedBuilder()
- .setTitle("⚠️ Invalid API Key")
- .setDescription("> **The API Key for Prodia is invalid or not provided.**")
- .setColor("Red")
- return interaction.reply({ embeds: [invalid_api] });
- }
-
- const error = new EmbedBuilder()
- .setTitle('⚠️ Error!')
- .setDescription('**An Error Occured, please try again later!**\n\n> - API Monthly Credits may have been used up\n> - Might be a problem with the API at the moment\n> - Or the Model/Sampler/Style is not available.')
- .setColor('Red');
-
- await interaction.deferReply();
-
- const style_preset = interaction.options.getString('style-preset');
- const steps = interaction.options.getInteger('steps');
- const cfg_scale = interaction.options.getInteger('cfg-scale');
- const seed = interaction.options.getInteger('seed');
- const sampler = interaction.options.getString('sampler');
-
- let prompt = interaction.options.getString('prompt');
- let negative_prompt = interaction.options.getString('negative-prompt');
- let model = interaction.options.getString('model');
-
- prompt = (await translate(prompt, { to: 'en' })).text;
- negative_prompt = (await translate(negative_prompt, { to: 'en' })).text;
-
- const nsfw_embed = new EmbedBuilder()
- .setDescription(`**⚠️ NSFW content detected!**`)
- .setColor('Red');
-
- if (Block_NSFW_Images) {
- try {
- const response = await fetch('https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/en');
- const data = await response.text();
- let nsfw_words = data.split('\n');
- nsfw_words = nsfw_words.filter(word => word !== 'suck' && word !== 'sucks');
-
- let promptWords = prompt.split(' ');
-
- for (let word of nsfw_words) {
- if (promptWords.includes(word)) {
- await interaction.followUp({ embeds: [nsfw_embed] });
- return;
- }
- }
- } catch (err) {
- console.error(err);
- }
- }
-
- async function nsfw_getPic(image) {
- const pic = await axios.get(image, { responseType: 'arraybuffer' });
- const model = await nsfw.load();
- image_analyse = await tf.node.decodeImage(pic.data, 3);
- const predictions = await model.classify(image_analyse);
- image_analyse.dispose();
-
- if (predictions[0].probability > 0.5 && (predictions[0].className === "Porn") || (predictions[0].className === "Hentai") || (predictions[0].className === "Sexy")) {
- await interaction.followUp({ embeds: [nsfw_embed] });
- return true;
- }
- return image
- }
-
- const sdk = require('api')('@prodia/v1.3.0#6fdmny2flsvwyf65');
-
- sdk.auth(XProdiaKey);
-
- try{
- const {data} = await sdk.listModels();
- choices = JSON.parse(data);
- } catch (e) {
- return interaction.followUp({embeds: [error]});
- }
-
- if (model && !choices.includes(model)) {
- const no_model = new EmbedBuilder()
- .setDescription(`**${model}** is not a valid model!\n\n> Run \`/models\` to see the available models!`)
- .setColor('Red');
-
- return interaction.followUp({embeds: [no_model]});
- }
-
- if (!model) {
- model = "absolutereality_V16.safetensors [37db0fc3]";
- }
-
- let generateParams = {
- model: model,
- prompt: prompt,
- ...(style_preset && { style_preset: style_preset }),
- ...(negative_prompt && { negative_prompt: negative_prompt }),
- ...(steps && { steps: steps }),
- ...(sampler && { sampler: sampler }),
- ...(cfg_scale && { cfg_scale: cfg_scale }),
- ...(seed && { seed: seed })
- };
-
-
-
- try{
- sdk.generate(generateParams)
- .then(({ data }) => {
- const jobId = data.job;
- const intervalId = setInterval(() => {
- sdk.getJob({jobId: jobId})
- .then(({ data }) => {
- if (data.status === 'succeeded') {
- clearInterval(intervalId);
-
- let image = data.imageUrl;
-
- (async () => {
- if (Block_NSFW_Images) {
- const newImage = await nsfw_getPic(image);
- image = newImage;
- if (image === true) {
- return;
- }
- }
-
- const success = new EmbedBuilder()
- .setImage(image)
- .setTitle('🖼️ Generated Image!')
- .setDescription(`> **${prompt}**`)
- .setColor('Random')
- .setFooter({ text: `Requested by ${interaction.user.tag}, Powered By Prodia`, iconURL: interaction.user.displayAvatarURL() })
-
- return interaction.followUp({embeds: [success]});
-
- })();
-
- } else if (data.status === 'failed') {
- clearInterval(intervalId);
- return interaction.followUp({embeds: [error]});
- }
- })
- .catch(err => console.error(err));
- }, 2000);
- })
- .catch(err => console.error(err));
- } catch(err) {
- return interaction.followUp({embeds: [error]});
- }
- }
-}
\ No newline at end of file
+ { name: "Anime", value: "anime" },
+ { name: "Cinematic", value: "cinematic" },
+ { name: "Comic Book", value: "comic-book" },
+ { name: "Digital Art", value: "digital-art" },
+ { name: "Enhance", value: "enhance" },
+ { name: "Fantasy Art", value: "fantasy-art" },
+ { name: "Isometric", value: "isometric" },
+ { name: "Line Art", value: "line-art" },
+ { name: "Low Poly", value: "low-poly" },
+ { name: "Neon Punk", value: "neon-punk" },
+ { name: "Origami", value: "origami" },
+ { name: "Photographic", value: "photographic" },
+ { name: "Pixel Art", value: "pixel-art" },
+ { name: "Texture", value: "texture" },
+ { name: "Craft Clay", value: "craft-clay" },
+ ),
+ )
+ .addStringOption((option) =>
+ option.setName("sampler").setDescription("The Image Sampler").addChoices(
+ { name: "Euler a", value: "Euler a" },
+ { name: "LMS", value: "LMS" },
+ { name: "Heun", value: "Heun" },
+ { name: "DPM2", value: "DPM2" },
+ { name: "DPM2 a", value: "DPM2 a" },
+ { name: "DPM++ 2S a", value: "DPM++ 2S a" },
+ { name: "DPM++ 2M", value: "DPM++ 2M" },
+ { name: "DPM++ 2M SDE", value: "DPM++ 2M SDE" },
+ {
+ name: "DPM++ 2M SDE Heun Karras",
+ value: "DPM++ 2M SDE Heun Karras",
+ },
+ { name: "DPM++ 3M SD", value: "DPM++ 3M SD" },
+ { name: "DPM++ 3M SD Karras", value: "DPM++ 3M SD Karras" },
+ { name: "DPM++ 3M SD Exponential", value: "DPM++ 3M SD Exponential" },
+ { name: "DPM fast", value: "DPM fast" },
+ { name: "DPM adaptive", value: "DPM adaptive" },
+ { name: "LMS Karras", value: "LMS Karras" },
+ { name: "DPM2 Karras", value: "DPM2 Karras" },
+ { name: "DPM2 a Karras", value: "DPM2 a Karras" },
+ { name: "DPM++ 2S a Karras", value: "DPM++ 2S a Karras" },
+ { name: "DPM++ 2M Karras", value: "DPM++ 2M Karras" },
+ { name: "DPM++ SDE Karras", value: "DPM++ SDE Karras" },
+ { name: "DPM++ SDE Karras", value: "DPM++ SDE Karras" },
+ {
+ name: "DPM++ 2M SDE Exponential",
+ value: "DPM++ 2M SDE Exponential",
+ },
+ { name: "DDIM", value: "DDIM" },
+ { name: "PLMS", value: "PLMS" },
+ { name: "UniPC", value: "UniPC" },
+ ),
+ )
+ .addBooleanOption((o) =>
+ o.setName("upscale").setDescription("Enable 2x Upscale"),
+ )
+ .addIntegerOption((option) =>
+ option
+ .setName("width")
+ .setDescription("The Width of the Image")
+ .setMinValue(1)
+ .setMaxValue(1024),
+ )
+ .addIntegerOption((option) =>
+ option
+ .setName("height")
+ .setDescription("The Height of the Image")
+ .setMinValue(1)
+ .setMaxValue(1024),
+ ),
+
+ async execute(interaction) {
+ const apiKeys = await db.get("apiKeys");
+ const XProdiaKey = apiKeys.prodia;
+
+ const other = await db.get("other");
+ const blockNSFWImages = other.blockNSFWImages;
+
+ const invalid_api = new EmbedBuilder()
+ .setTitle("⚠️ Invalid API Key")
+ .setDescription(
+ "> *The API Key for Prodia is invalid or not provided*\n> **Please contact the developers**",
+ )
+ .setColor("Red");
+
+ if (!XProdiaKey || XProdiaKey.length < 4) {
+ return interaction.reply({ embeds: [invalid_api] });
+ }
+
+ await interaction.deferReply();
+
+ const isValidKey = await checkAPIKey("prodia", XProdiaKey);
+ if (!isValidKey) {
+ return interaction.reply({ embeds: [invalid_api] });
+ }
+
+ const error = new EmbedBuilder()
+ .setTitle("⚠️ Error!")
+ .setDescription(
+ "**An Error Occured, please try again later!**\n\n> - API Monthly Credits may have been used up\n> - Might be a problem with the API at the moment\n> - Or the Model/Sampler/Style is not available.",
+ )
+ .setColor("Red");
+
+ const style_preset = interaction.options.getString("style-preset");
+ const steps = interaction.options.getInteger("steps");
+ const cfg_scale = interaction.options.getInteger("cfg-scale");
+ const seed = interaction.options.getInteger("seed");
+ const sampler = interaction.options.getString("sampler");
+ const upscale = interaction.options.getBoolean("upscale");
+ const width = interaction.options.getInteger("width");
+ const height = interaction.options.getInteger("height");
+
+ let prompt = interaction.options.getString("prompt");
+ let negative_prompt = interaction.options.getString("negative-prompt");
+ let model = interaction.options.getString("model");
+
+ prompt = (await translate(prompt, { to: "en" })).text;
+ negative_prompt = (await translate(negative_prompt, { to: "en" })).text;
+
+ const nsfw_embed = new EmbedBuilder()
+ .setDescription(`**⚠️ NSFW content detected!**`)
+ .setColor("Red");
+
+ if (blockNSFWImages) {
+ try {
+ const nsfw_words = await getNsfwWords();
+ let promptWords = prompt.split(" ");
+ for (let word of nsfw_words) {
+ if (promptWords.includes(word)) {
+ await interaction.followUp({ embeds: [nsfw_embed] });
+ return;
+ }
+ }
+ } catch (err) {
+ console.error(err);
+ }
+ }
+
+ const sdk = require("api")("@prodia/v1.3.0#6fdmny2flsvwyf65");
+
+ sdk.auth(XProdiaKey);
+
+ async function fetchModels(apiMethod) {
+ try {
+ const { data } = await apiMethod();
+ return JSON.parse(data);
+ } catch (e) {
+ console.error(e);
+ return interaction.followUp({ embeds: [error] });
+ }
+ }
+
+ const [choices, sdxlChoices] = await Promise.all([
+ fetchModels(sdk.listModels),
+ fetchModels(sdk.listSdxlModels),
+ ]);
+
+ const allModels = [...choices, ...sdxlChoices];
+
+ if (model && !allModels.includes(model)) {
+ const no_model = new EmbedBuilder()
+ .setDescription(
+ `**${model}** is not a valid model!\n\n> Run \`/models\` to see the available models!`,
+ )
+ .setColor("Red");
+
+ return interaction.followUp({ embeds: [no_model] });
+ }
+
+ if (!model) {
+ model = "absolutereality_V16.safetensors [37db0fc3]";
+ }
+
+ let generateParams = {
+ model: model,
+ prompt: prompt,
+ ...(style_preset && { style_preset: style_preset }),
+ ...(negative_prompt && { negative_prompt: negative_prompt }),
+ ...(steps && { steps: steps }),
+ ...(sampler && { sampler: sampler }),
+ ...(cfg_scale && { cfg_scale: cfg_scale }),
+ ...(seed && { seed: seed }),
+ ...(upscale && { upscale: upscale }),
+ ...(width && { width: width }),
+ ...(height && { height: height }),
+ };
+
+ try {
+ const generateMethod = sdxlChoices.includes(model)
+ ? sdk.sdxlGenerate
+ : sdk.generate;
+ generateMethod(generateParams)
+ .then(({ data }) => {
+ const jobId = data.job;
+ const intervalId = setInterval(() => {
+ sdk
+ .getJob({ jobId: jobId })
+ .then(({ data }) => {
+ if (data.status === "succeeded") {
+ clearInterval(intervalId);
+
+ let image = data.imageUrl;
+
+ (async () => {
+ if (blockNSFWImages) {
+ const newImage = await nsfwGetPic(
+ image,
+ nsfw_embed,
+ interaction,
+ );
+ image = newImage;
+ if (image === true) {
+ return;
+ }
+ }
+
+ const success = new EmbedBuilder()
+ .setImage(image)
+ .setTitle("🖼️ Generated Image!")
+ .setDescription(`> **${prompt}**`)
+ .setColor("Random")
+ .setFooter({
+ text: `Requested by ${interaction.user.tag}, Powered By Prodia`,
+ iconURL: interaction.user.displayAvatarURL(),
+ });
+
+ return interaction.followUp({ embeds: [success] });
+ })();
+ } else if (data.status === "failed") {
+ clearInterval(intervalId);
+ return interaction.followUp({ embeds: [error] });
+ }
+ })
+ .catch((err) => console.error(err));
+ }, 5000);
+ })
+ .catch((err) => console.error(err));
+ } catch (err) {
+ return interaction.followUp({ embeds: [error] });
+ }
+ },
+};
diff --git a/interactions/slash/misc/info.js b/interactions/slash/misc/info.js
index 899eeb0..4093810 100644
--- a/interactions/slash/misc/info.js
+++ b/interactions/slash/misc/info.js
@@ -3,45 +3,57 @@
* @author TechyGiraffe999
*/
-
-const { EmbedBuilder, SlashCommandBuilder, ButtonBuilder, ButtonStyle, ActionRowBuilder } = require("discord.js");
+const {
+ EmbedBuilder,
+ SlashCommandBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ ActionRowBuilder,
+} = require("discord.js");
/**
* @type {import('../../../typings').SlashInteractionCommand}
*/
module.exports = {
- data: new SlashCommandBuilder()
- .setName('info')
- .setDescription('Displays info on me!'),
- async execute(interaction) {
-
- const github = new ButtonBuilder()
- .setURL('https://github.com/TecEash1/Taurus')
- .setLabel('GitHub Repository')
- .setEmoji("⚒️")
- .setStyle(ButtonStyle.Link);
-
- const buttons = new ActionRowBuilder()
- .addComponents(github);
-
- let totalSecs = (interaction.client.uptime / 1000);
- let days = Math.floor(totalSecs / 86400);totalSecs %= 86400;
- let hrs = Math.floor(totalSecs / 3600);totalSecs %= 3600;
- let mins = Math.floor(totalSecs / 60);
- let seconds = Math.floor(totalSecs % 60);
- let uptime = `**${days}**d **${hrs}**h **${mins}**m **${seconds}**s`;
-
- const embed = new EmbedBuilder()
- .setTitle("🤖 Info")
- .setDescription("I am a bot created by TechyGiraffe999. I was made to be a specialised AI Bot.")
- .addFields(
- { name: `**⌛ UPTIME**`, value: `${uptime}`},
- { name: `**📡 PING**`, value: `Responded in \`\`${interaction.client.ws.ping}ms\`\``}
- )
- .setThumbnail("https://github.com/TecEash1/TecEash1/assets/92249532/bd4aca7e-daab-4eeb-9265-e53cc1925e8c")
- .setColor("Blurple");
-
- await interaction.reply({ embeds: [embed], components: [buttons]});
- },
-};
\ No newline at end of file
+ data: new SlashCommandBuilder()
+ .setName("info")
+ .setDescription("Displays info on me!"),
+ async execute(interaction) {
+ const github = new ButtonBuilder()
+ .setURL("https://github.com/TecEash1/Taurus")
+ .setLabel("GitHub Repository")
+ .setEmoji("⚒️")
+ .setStyle(ButtonStyle.Link);
+
+ const buttons = new ActionRowBuilder().addComponents(github);
+
+ let totalSecs = interaction.client.uptime / 1000;
+ let days = Math.floor(totalSecs / 86400);
+ totalSecs %= 86400;
+ let hrs = Math.floor(totalSecs / 3600);
+ totalSecs %= 3600;
+ let mins = Math.floor(totalSecs / 60);
+ let seconds = Math.floor(totalSecs % 60);
+ let uptime = `**${days}**d **${hrs}**h **${mins}**m **${seconds}**s`;
+
+ const embed = new EmbedBuilder()
+ .setTitle("🤖 Info")
+ .setDescription(
+ "I am a bot created by TechyGiraffe999. I was made to be a specialised AI Bot.",
+ )
+ .addFields(
+ { name: `**⌛ UPTIME**`, value: `${uptime}` },
+ {
+ name: `**📡 PING**`,
+ value: `Responded in \`\`${interaction.client.ws.ping}ms\`\``,
+ },
+ )
+ .setThumbnail(
+ "https://github.com/TecEash1/TecEash1/assets/92249532/bd4aca7e-daab-4eeb-9265-e53cc1925e8c",
+ )
+ .setColor("Blurple");
+
+ await interaction.reply({ embeds: [embed], components: [buttons] });
+ },
+};
diff --git a/interactions/slash/misc/models.js b/interactions/slash/misc/models.js
index 01fe140..def790e 100644
--- a/interactions/slash/misc/models.js
+++ b/interactions/slash/misc/models.js
@@ -7,54 +7,67 @@
* @type {import('../../../typings').SlashInteractionCommand}
*/
-const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
-const {XProdiaKey} = require('../../../config.json')
-
+const { SlashCommandBuilder, EmbedBuilder } = require("discord.js");
+const { QuickDB } = require("quick.db");
+const path = require("path");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
module.exports = {
- data: new SlashCommandBuilder()
- .setName('models')
- .setDescription('List the available models for image generation!'),
-
- async execute(interaction, client) {
-
- if (!XProdiaKey || XProdiaKey.length < 4) {
- invalid_api = new EmbedBuilder()
- .setTitle("⚠️ Invalid API Key")
- .setDescription("> **The API Key for Prodia is invalid or not provided.**")
- .setColor("Red")
- return interaction.reply({ embeds: [invalid_api] });
- }
-
- const error = new EmbedBuilder()
- .setTitle("⚠️ An Unknown Error Occured")
- .setDescription("> **The Prodia API Key usage may have been used up, or the API is invalid or not working at the moment.**\n\n> Please try again later or contact the developers.")
- .setColor("Red")
-
- await interaction.deferReply();
-
- const sdk = require('api')('@prodia/v1.3.0#6fdmny2flsvwyf65');
-
- sdk.auth(XProdiaKey);
-
- try{
- const {data} = await sdk.listModels();
- choices = JSON.parse(data);
- } catch (e) {
- return interaction.followUp({embeds: [error]});
- }
-
-
- const choices_string = "```\n- " + choices.join("\n- ") + "\n```";
-
- const models = new EmbedBuilder()
- .setTitle('🖼️ Available Models')
- .setDescription(choices_string)
- .setColor('Random')
-
- return interaction.followUp({embeds: [models]});
-
-
- },
-};
+ data: new SlashCommandBuilder()
+ .setName("models")
+ .setDescription("List the available models for image generation!"),
+
+ async execute(interaction) {
+ const apiKeys = await db.get("apiKeys");
+ const XProdiaKey = apiKeys.prodia;
+
+ if (!XProdiaKey || XProdiaKey.length < 4) {
+ invalid_api = new EmbedBuilder()
+ .setTitle("⚠️ Invalid API Key")
+ .setDescription(
+ "> **The API Key for Prodia is invalid or not provided.**\n> **Please contact the developers**",
+ )
+ .setColor("Red");
+ return interaction.reply({ embeds: [invalid_api] });
+ }
+
+ const error = new EmbedBuilder()
+ .setTitle("⚠️ An Unknown Error Occured")
+ .setDescription(
+ "> **The Prodia API Key usage may have been used up, or the API is invalid or not working at the moment.**\n\n> Please try again later or contact the developers.",
+ )
+ .setColor("Red");
+
+ await interaction.deferReply();
+ const sdk = require("api")("@prodia/v1.3.0#6fdmny2flsvwyf65");
+
+ sdk.auth(XProdiaKey);
+
+ async function fetchAndFormatModels(apiMethod) {
+ try {
+ const { data } = await apiMethod();
+ const models = JSON.parse(data);
+ return "```\n- " + models.join("\n- ") + "\n```";
+ } catch (e) {
+ return interaction.followUp({ embeds: [error] });
+ }
+ }
+
+ const [choices_string, sdxlChoices_string] = await Promise.all([
+ fetchAndFormatModels(sdk.listModels),
+ fetchAndFormatModels(sdk.listSdxlModels),
+ ]);
+
+ const models = new EmbedBuilder()
+ .setTitle("🖼️ Available Models")
+ .setDescription(
+ `**\n🌟 SD Models:**\n\n ${choices_string}\n\n**🚀 SDXL Models:**\n\n ${sdxlChoices_string}`,
+ )
+ .setColor("Random");
+
+ return interaction.followUp({ embeds: [models] });
+ },
+};
diff --git a/interactions/slash/misc/personalise.js b/interactions/slash/misc/personalise.js
index 4f17e30..26c2f31 100644
--- a/interactions/slash/misc/personalise.js
+++ b/interactions/slash/misc/personalise.js
@@ -7,284 +7,352 @@
* @type {import('../../../typings').SlashInteractionCommand}
*/
-const { SlashCommandBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, EmbedBuilder, ButtonBuilder } = require("discord.js");
-const axios = require('axios');
-const fs = require('fs').promises;
-const path = require('path');
-const {guild_id_logs, channel_id_logs, owner} = require("../../../config.json");
-
-const serverId = guild_id_logs;
-const channelId = channel_id_logs;
-
-const no_access = new EmbedBuilder()
- .setDescription("**Only my developers can directly update my global personality prompt!**\n\nIf you want to suggest a change, please let us know!")
- .setColor("Red");
+const {
+ SlashCommandBuilder,
+ ModalBuilder,
+ TextInputBuilder,
+ TextInputStyle,
+ ActionRowBuilder,
+ EmbedBuilder,
+ ButtonBuilder,
+ WebhookClient,
+} = require("discord.js");
+const axios = require("axios");
+const fs = require("fs").promises;
+const path = require("path");
+const { checkOwnerAndReply } = require("../../../functions/other/utils");
+const { QuickDB } = require("quick.db");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
const link_error = new EmbedBuilder()
- .setDescription("**The file link is not a valid URL!**")
- .setColor("Red");
+ .setDescription("**The file link is not a valid URL!**")
+ .setColor("Red");
const error_null = new EmbedBuilder()
- .setDescription("**You must select at least one option!**")
- .setColor("Red");
+ .setDescription("**You must select at least one option!**")
+ .setColor("Red");
const error_multiple = new EmbedBuilder()
- .setDescription("**You can only select one option!**")
- .setColor("Red");
+ .setDescription("**You can only select one option!**")
+ .setColor("Red");
const file_read_error = new EmbedBuilder()
- .setDescription("**There was an error while reading the file!**")
- .setColor("Red");
+ .setDescription("**There was an error while reading the file!**")
+ .setColor("Red");
const txt_only = new EmbedBuilder()
- .setDescription("**You can only upload a .txt file!**")
- .setColor("Red");
+ .setDescription("**You can only upload a .txt file!**")
+ .setColor("Red");
module.exports = {
data: new SlashCommandBuilder()
.setName("personalise")
.setDescription("Customise my Personality!")
- .addAttachmentOption(option => option
- .setRequired(false)
- .setName("file")
- .setDescription("The personality text file"))
- .addStringOption(option => option
- .setRequired(false)
- .setName("file-link")
- .setDescription("The personality text file link"))
- .addStringOption(option =>
- option.setName("other")
+ .addAttachmentOption((option) =>
+ option
+ .setRequired(false)
+ .setName("file")
+ .setDescription("The personality text file"),
+ )
+ .addStringOption((option) =>
+ option
+ .setRequired(false)
+ .setName("file-link")
+ .setDescription("The personality text file link"),
+ )
+ .addStringOption((option) =>
+ option
+ .setName("other")
.setDescription("Other Options")
.addChoices(
{ name: "Get", value: "get" },
{ name: "Modal", value: "modal" },
- )),
+ ),
+ ),
async execute(interaction) {
+ const webhooks = await db.get("webhooks");
+ const personalityWebhook = webhooks.personality;
+
const file = interaction.options.getAttachment("file");
- const file_link = interaction.options.getString("file-link");
- const other = interaction.options.getString("other");
-
- if (!owner.includes(interaction.user.id)) {
- return await interaction.reply({ embeds: [no_access], ephemeral: true });
- }
-
- const selectedOptions = [file, file_link, other].filter(option => option != null).length;
-
- if (selectedOptions === 0 || selectedOptions > 1) {
- const errorMessage = selectedOptions === 0 ? error_null : error_multiple;
- return await interaction.reply({ embeds: [errorMessage], ephemeral: true });
- }
-
- const urlRegex = /^(ftp|http|https):\/\/[^ "]+$/;
- if (file_link && !urlRegex.test(file_link)) {
- return interaction.reply({ embeds: [link_error], ephemeral: true });
- }
-
- let personalityPrompt;
-
- async function getPersonalityPrompt(file, file_link) {
- const url = file?.url || file_link;
-
- try {
- const response = await axios.get(url);
- return response.data;
- } catch (error) {
- return error
- }
- }
-
- if (file || file_link) {
- const url = file?.url || file_link;
-
- const txtRegex = /\.txt(?=\?|$)/;
- if (!txtRegex.test(url)) {
- return await interaction.reply({ embeds: [txt_only], ephemeral: true });
- }
-
- const result = await getPersonalityPrompt(file, file_link);
-
- if (result instanceof Error) {
- return await interaction.reply({ embeds: [file_read_error], ephemeral: true });
- } else {
- personalityPrompt = result;
- }
- }
-
-
- const personalityFilePath = path.join(__dirname + '../../../../personality.txt');
-
-
- let personalityContent;
- try {
- personalityContent = await fs.readFile(personalityFilePath, 'utf-8');
- } catch (err) {
- console.error(err);
- }
-
- let submitted
- let modal_error
-
- if (other) {
- switch(other){
- case "get":
- return await interaction.reply({ files: [{ attachment: personalityFilePath, name: 'personality.txt' }], ephemeral: true });
- case "modal":
- const personalise = new ModalBuilder()
- .setTitle("Customise how Taurus responds")
- .setCustomId("taurus_ai_personality");
-
- const prompt = new TextInputBuilder()
- .setCustomId("personalise_taurusai")
- .setRequired(true)
- .setLabel("Personality Prompt:")
- .setStyle(TextInputStyle.Paragraph);
- const prompt2 = new TextInputBuilder()
- .setCustomId("personalise_taurusai2")
- .setRequired(false)
- .setLabel("Extra Space:")
- .setStyle(TextInputStyle.Paragraph);
- const prompt3 = new TextInputBuilder()
- .setCustomId("personalise_taurusai3")
- .setRequired(false)
- .setLabel("Extra Space:")
- .setStyle(TextInputStyle.Paragraph);
-
-
- const taurusai_personality_ActionRow = new ActionRowBuilder().addComponents(prompt);
- const taurusai_personality_ActionRow2 = new ActionRowBuilder().addComponents(prompt2);
- const taurusai_personality_ActionRow3 = new ActionRowBuilder().addComponents(prompt3);
-
- personalise.addComponents(taurusai_personality_ActionRow, taurusai_personality_ActionRow2, taurusai_personality_ActionRow3);
- await interaction.showModal(personalise);
-
- submitted = await interaction.awaitModalSubmit({
- time: 300000,
- filter: i => i.user.id === interaction.user.id,
- }).catch(error => {
- modal_error = true;
- return false
- })
-
- if (submitted) {
- personalityPrompt = await submitted.fields.getTextInputValue("personalise_taurusai");
- const personalityPrompt2 = await submitted.fields.getTextInputValue("personalise_taurusai2");
- const personalityPrompt3 = await submitted.fields.getTextInputValue("personalise_taurusai3");
- if (personalityPrompt2) {
- personalityPrompt += personalityPrompt2;
- }
- if (personalityPrompt3) {
- personalityPrompt += personalityPrompt3;
- }
- }
- }
- }
-
- if (modal_error) return;
-
- success = new EmbedBuilder()
- .setDescription("✅ **Personality prompt updated successfully!**")
- .setColor("Green");
-
- cancel = new EmbedBuilder()
- .setDescription("❌ **Operation cancelled.**")
- .setColor("Red");
-
- const error = new EmbedBuilder()
- .setDescription("⚠️ There was an error while fetching the TaurusAI Log channel, please contact the Developers.")
- .setColor("Red");
-
- const row = new ActionRowBuilder()
- .addComponents(
- new ButtonBuilder()
- .setCustomId('yes_botai_personality')
- .setLabel('Update')
- .setEmoji('✅')
- .setStyle('Primary'),
- new ButtonBuilder()
- .setCustomId('no_botai_personality')
- .setLabel('Cancel')
- .setEmoji('❌')
- .setStyle('Primary'),
- );
-
- let personalityContent_truncate = personalityContent;
- if (personalityContent.length > 2002) {
- personalityContent_truncate = personalityContent.substring(0, 2002) + '...';
- }
-
- let personalityPrompt_truncate = personalityPrompt;
- if (personalityPrompt.length > 2002) {
- personalityPrompt_truncate = personalityPrompt.substring(0, 2002) + '...';
- }
-
- let description = `**Current personality prompt:**\n\`\`\`${personalityContent_truncate}\`\`\`\n\n**New personality prompt:**\n\`\`\`${personalityPrompt_truncate}\`\`\``;
-
- embed = new EmbedBuilder()
- .setTitle("Are you sure you want to update the personality prompt?")
- .setDescription(description)
- .setFooter({ text: `⚠️ This will wipe the old Prompt, resetting it with the new one.`, iconURL: interaction.user.displayAvatarURL() })
- .setColor("Orange")
-
- await (submitted ?? interaction).reply({
- embeds: [embed],
- components: [row],
- files: [{ attachment: personalityFilePath, name: 'current_personality.txt' }],
- ephemeral: true
- });
-
- const filter = i => i.customId === 'yes_botai_personality' || i.customId === 'no_botai_personality';
- const collector = interaction.channel.createMessageComponentCollector({ filter, time: 60000 });
-
- collector.on('collect', async i => {
- collector.stop();
- if (i.customId === 'yes_botai_personality') {
-
- const personalityFilePath = path.join(__dirname, '../../../personality.txt');
- const tempFilePath = path.join(__dirname, 'temp.txt');
-
- let oldPersonalityContent;
- try {
- oldPersonalityContent = await fs.readFile(personalityFilePath, 'utf-8');
- await fs.writeFile(tempFilePath, oldPersonalityContent);
- } catch (err) {
- console.error(err);
- }
-
- await fs.writeFile(personalityFilePath, personalityPrompt);
-
- try{
- const guild = interaction.client.guilds.cache.get(serverId);
- const channel = guild.channels.cache.get(channelId);
-
-
- update = new EmbedBuilder()
- .setDescription(`**Personality prompt updated by <@${interaction.user.id}>**`)
- .setColor("Orange")
- .setFooter({ text: `ID: ${interaction.user.id}`, iconURL: interaction.user.displayAvatarURL() })
- .setTimestamp();
-
- await channel.send({
- embeds: [update],
- files: [
- { attachment: personalityFilePath, name: 'new_personality.txt' },
- { attachment: tempFilePath, name: 'old_personality.txt' }
- ]
- });
- await i.update({ embeds: [success], components: [], files: [] });
- } catch (err) {
- await i.update({ embeds: [success,error], components: [], files: [] });
- }
-
- try {
- await fs.unlink(tempFilePath);
- } catch (err) {
- console.error(err);
- }
-
- } else {
- await i.update({ embeds: [cancel], components: [], files: [] });
- }
- });
- }
-}
\ No newline at end of file
+ const file_link = interaction.options.getString("file-link");
+ const other = interaction.options.getString("other");
+
+ if (!checkOwnerAndReply(interaction)) {
+ return;
+ }
+ const selectedOptions = [file, file_link, other].filter(
+ (option) => option != null,
+ ).length;
+
+ if (selectedOptions === 0 || selectedOptions > 1) {
+ const errorMessage = selectedOptions === 0 ? error_null : error_multiple;
+ return await interaction.reply({
+ embeds: [errorMessage],
+ ephemeral: true,
+ });
+ }
+
+ const urlRegex = /^(ftp|http|https):\/\/[^ "]+$/;
+ if (file_link && !urlRegex.test(file_link)) {
+ return interaction.reply({ embeds: [link_error], ephemeral: true });
+ }
+
+ let personalityPrompt;
+
+ async function getPersonalityPrompt(file, file_link) {
+ const url = file?.url || file_link;
+
+ try {
+ const response = await axios.get(url);
+ return response.data;
+ } catch (error) {
+ return error;
+ }
+ }
+
+ if (file || file_link) {
+ const url = file?.url || file_link;
+
+ const txtRegex = /\.txt(?=\?|$)/;
+ if (!txtRegex.test(url)) {
+ return await interaction.reply({ embeds: [txt_only], ephemeral: true });
+ }
+
+ const result = await getPersonalityPrompt(file, file_link);
+
+ if (result instanceof Error) {
+ return await interaction.reply({
+ embeds: [file_read_error],
+ ephemeral: true,
+ });
+ } else {
+ personalityPrompt = result;
+ }
+ }
+
+ const personalityFilePath = path.join(
+ __dirname + "../../../../personality.txt",
+ );
+
+ let personalityContent;
+ try {
+ personalityContent = await fs.readFile(personalityFilePath, "utf-8");
+ } catch (err) {
+ console.error(err);
+ }
+
+ let submitted;
+ let modal_error;
+
+ if (other) {
+ switch (other) {
+ case "get":
+ return await interaction.reply({
+ files: [
+ { attachment: personalityFilePath, name: "personality.txt" },
+ ],
+ ephemeral: true,
+ });
+ case "modal":
+ const personalise = new ModalBuilder()
+ .setTitle("Customise how Taurus responds")
+ .setCustomId("taurus_ai_personality");
+
+ const prompt = new TextInputBuilder()
+ .setCustomId("personalise_taurusai")
+ .setRequired(true)
+ .setLabel("Personality Prompt:")
+ .setStyle(TextInputStyle.Paragraph);
+ const prompt2 = new TextInputBuilder()
+ .setCustomId("personalise_taurusai2")
+ .setRequired(false)
+ .setLabel("Extra Space:")
+ .setStyle(TextInputStyle.Paragraph);
+ const prompt3 = new TextInputBuilder()
+ .setCustomId("personalise_taurusai3")
+ .setRequired(false)
+ .setLabel("Extra Space:")
+ .setStyle(TextInputStyle.Paragraph);
+
+ const taurusai_personality_ActionRow =
+ new ActionRowBuilder().addComponents(prompt);
+ const taurusai_personality_ActionRow2 =
+ new ActionRowBuilder().addComponents(prompt2);
+ const taurusai_personality_ActionRow3 =
+ new ActionRowBuilder().addComponents(prompt3);
+
+ personalise.addComponents(
+ taurusai_personality_ActionRow,
+ taurusai_personality_ActionRow2,
+ taurusai_personality_ActionRow3,
+ );
+ await interaction.showModal(personalise);
+
+ submitted = await interaction
+ .awaitModalSubmit({
+ time: 300000,
+ filter: (i) => i.user.id === interaction.user.id,
+ })
+ .catch((error) => {
+ modal_error = true;
+ return false;
+ });
+
+ if (submitted) {
+ personalityPrompt = await submitted.fields.getTextInputValue(
+ "personalise_taurusai",
+ );
+ const personalityPrompt2 = await submitted.fields.getTextInputValue(
+ "personalise_taurusai2",
+ );
+ const personalityPrompt3 = await submitted.fields.getTextInputValue(
+ "personalise_taurusai3",
+ );
+ if (personalityPrompt2) {
+ personalityPrompt += personalityPrompt2;
+ }
+ if (personalityPrompt3) {
+ personalityPrompt += personalityPrompt3;
+ }
+ }
+ }
+ }
+
+ if (modal_error) return;
+
+ success = new EmbedBuilder()
+ .setDescription("✅ **Personality prompt updated successfully!**")
+ .setColor("Green");
+
+ cancel = new EmbedBuilder()
+ .setDescription("❌ **Operation cancelled.**")
+ .setColor("Red");
+
+ const error = new EmbedBuilder()
+ .setDescription(
+ "**⚠️ There was an error while fetching the TaurusAI Log channel, please contact the Developers.**",
+ )
+ .setColor("Red");
+
+ const row = new ActionRowBuilder().addComponents(
+ new ButtonBuilder()
+ .setCustomId("yes_botai_personality")
+ .setLabel("Update")
+ .setEmoji("✅")
+ .setStyle("Primary"),
+ new ButtonBuilder()
+ .setCustomId("no_botai_personality")
+ .setLabel("Cancel")
+ .setEmoji("❌")
+ .setStyle("Primary"),
+ );
+
+ let personalityContent_truncate = personalityContent;
+ if (personalityContent.length > 2002) {
+ personalityContent_truncate =
+ personalityContent.substring(0, 2002) + "...";
+ }
+
+ let personalityPrompt_truncate = personalityPrompt;
+ if (personalityPrompt.length > 2002) {
+ personalityPrompt_truncate = personalityPrompt.substring(0, 2002) + "...";
+ }
+
+ let description = `**Current personality prompt:**\n\`\`\`${personalityContent_truncate}\`\`\`\n\n**New personality prompt:**\n\`\`\`${personalityPrompt_truncate}\`\`\``;
+
+ embed = new EmbedBuilder()
+ .setTitle("Are you sure you want to update the personality prompt?")
+ .setDescription(description)
+ .setFooter({
+ text: `⚠️ This will wipe the old Prompt, resetting it with the new one.`,
+ iconURL: interaction.user.displayAvatarURL(),
+ })
+ .setColor("Orange");
+
+ await (submitted ?? interaction).reply({
+ embeds: [embed],
+ components: [row],
+ files: [
+ { attachment: personalityFilePath, name: "current_personality.txt" },
+ ],
+ ephemeral: true,
+ });
+
+ const filter = (i) =>
+ i.customId === "yes_botai_personality" ||
+ i.customId === "no_botai_personality";
+ const collector = interaction.channel.createMessageComponentCollector({
+ filter,
+ time: 60000,
+ });
+
+ collector.on("collect", async (i) => {
+ collector.stop();
+ if (i.customId === "yes_botai_personality") {
+ const personalityFilePath = path.join(
+ __dirname,
+ "../../../personality.txt",
+ );
+ const tempFilePath = path.join(__dirname, "temp.txt");
+
+ let oldPersonalityContent;
+ try {
+ oldPersonalityContent = await fs.readFile(
+ personalityFilePath,
+ "utf-8",
+ );
+ await fs.writeFile(tempFilePath, oldPersonalityContent);
+ } catch (err) {
+ console.error(err);
+ }
+
+ await fs.writeFile(personalityFilePath, personalityPrompt);
+
+ try {
+ const webhookClient = new WebhookClient({
+ url: personalityWebhook,
+ });
+
+ update = new EmbedBuilder()
+ .setDescription(
+ `**Personality prompt updated by <@${interaction.user.id}>**`,
+ )
+ .setColor("Orange")
+ .setFooter({
+ text: `ID: ${interaction.user.id}`,
+ iconURL: interaction.user.displayAvatarURL(),
+ })
+ .setTimestamp();
+
+ await webhookClient.send({
+ username: "Taurus Personality",
+ avatarURL: interaction.client.user.displayAvatarURL(),
+ embeds: [update],
+ files: [
+ { attachment: personalityFilePath, name: "new_personality.txt" },
+ { attachment: tempFilePath, name: "old_personality.txt" },
+ ],
+ });
+ await i.update({ embeds: [success], components: [], files: [] });
+ } catch (err) {
+ await i.update({
+ embeds: [success, error],
+ components: [],
+ files: [],
+ });
+ }
+
+ try {
+ await fs.unlink(tempFilePath);
+ } catch (err) {
+ console.error(err);
+ }
+ } else {
+ await i.update({ embeds: [cancel], components: [], files: [] });
+ }
+ });
+ },
+};
diff --git a/interactions/slash/misc/settings.js b/interactions/slash/misc/settings.js
new file mode 100644
index 0000000..58bef2d
--- /dev/null
+++ b/interactions/slash/misc/settings.js
@@ -0,0 +1,232 @@
+/**
+ * @file Settings Command
+ * @author TechyGiraffe999
+ */
+
+const {
+ EmbedBuilder,
+ SlashCommandBuilder,
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ Embed,
+} = require("discord.js");
+const path = require("path");
+const {
+ checkWebhook,
+ checkAPIKey,
+ checkOwnerAndReply,
+} = require("../../../functions/other/utils");
+const { emojis } = require("../../../config.json");
+const { QuickDB } = require("quick.db");
+const db = new QuickDB({
+ filePath: path.join(__dirname, "../../../functions/other/settings.sqlite"),
+});
+
+async function updateFieldValueAndReply(
+ interaction,
+ settings,
+ fieldName,
+ fieldValue,
+) {
+ const field = settings.data.fields.find((field) => field.name === fieldName);
+ field.value = fieldValue;
+ await interaction.editReply({ embeds: [settings] });
+}
+
+/**
+ * @type {import('../../../typings').SlashInteractionCommand}
+ */
+module.exports = {
+ data: new SlashCommandBuilder()
+ .setName("settings")
+ .setDescription("View the settings for Taurus"),
+ async execute(interaction) {
+ try {
+ const settings = new EmbedBuilder()
+ .setTitle("Taurus Settings")
+ .setColor("6414eb")
+ .addFields(
+ {
+ name: "🔗 Webhooks:",
+ value: `${emojis.loading} **Personality**\n${emojis.loading} **Console**`,
+ inline: true,
+ },
+ {
+ name: "🔑 API Keys:",
+ value: `${emojis.loading} **Prodia**\n${emojis.loading} **Gemini**`,
+ inline: true,
+ },
+ {
+ name: "🧠 Model:",
+ value: `${emojis.loading} **Fallback System**\n${emojis.loading} **Safety System**\n${emojis.loading} **Model**`,
+ inline: true,
+ },
+ {
+ name: "⚙️ Other:",
+ value: `${emojis.loading} **NSFW Image Blocking**`,
+ inline: true,
+ },
+ )
+ .setThumbnail(
+ "https://github.com/TecEash1/TecEash1/assets/92249532/bd4aca7e-daab-4eeb-9265-e53cc1925e8c",
+ );
+
+ if (!checkOwnerAndReply(interaction)) {
+ return;
+ }
+ await interaction.reply({ embeds: [settings] });
+
+ const webhooks = await db.get("webhooks");
+ const apiKeys = await db.get("apiKeys");
+ const modelSettings = await db.get("model");
+ const otherSettings = await db.get("other");
+
+ // WEBHOOK CHECKING
+ let isPersonalityWebhookValid = await checkWebhook(webhooks.personality);
+ await updateFieldValueAndReply(
+ interaction,
+ settings,
+ "🔗 Webhooks:",
+ `${isPersonalityWebhookValid ? emojis.working : emojis.failed} **Personality**\n${emojis.loading} **Console**`,
+ );
+
+ let isConsoleWebhookValid = await checkWebhook(webhooks.console);
+ await updateFieldValueAndReply(
+ interaction,
+ settings,
+ "🔗 Webhooks:",
+ `${isPersonalityWebhookValid ? emojis.working : emojis.failed} **Personality**\n${isConsoleWebhookValid ? emojis.working : emojis.failed} **Console**`,
+ );
+
+ // API KEY CHECKING
+ let isProdiaKeyValid = await checkAPIKey("prodia", apiKeys.prodia);
+ await updateFieldValueAndReply(
+ interaction,
+ settings,
+ "🔑 API Keys:",
+ `${isProdiaKeyValid ? emojis.working : emojis.failed} **Prodia**\n${emojis.loading} **Gemini**`,
+ );
+
+ let isGeminiKeyValid = await checkAPIKey("gemini", apiKeys.gemini);
+ await updateFieldValueAndReply(
+ interaction,
+ settings,
+ "🔑 API Keys:",
+ `${isProdiaKeyValid ? emojis.working : emojis.failed} **Prodia**\n${isGeminiKeyValid ? emojis.working : emojis.failed} **Gemini**`,
+ );
+
+ // MODEL SETTINGS CHECKING
+
+ let isFallbackSystemEnabled = modelSettings.fallbackSystem;
+ await updateFieldValueAndReply(
+ interaction,
+ settings,
+ "🧠 Model:",
+ `${isFallbackSystemEnabled ? emojis.working : emojis.failed} **Fallback System**\n${emojis.loading} **Safety System**\n${emojis.loading} **Model**`,
+ );
+
+ let isSafetySystemEnabled = modelSettings.safetySystem;
+ await updateFieldValueAndReply(
+ interaction,
+ settings,
+ "🧠 Model:",
+ `${isFallbackSystemEnabled ? emojis.working : emojis.failed} **Fallback System**\n${isSafetySystemEnabled ? emojis.working : emojis.failed} **Safety System**\n${emojis.loading} **Model**`,
+ );
+
+ let modelName = modelSettings.model;
+ let modelEmoji = modelName === "gemini-1.5-flash-latest" ? "⚡" : "💪";
+ let modelNameFormatted = modelName
+ .replace(/-latest$/, "")
+ .replace(/-/g, " ")
+ .split(" ")
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
+ .join(" ");
+ await updateFieldValueAndReply(
+ interaction,
+ settings,
+ "🧠 Model:",
+ `${isFallbackSystemEnabled ? emojis.working : emojis.failed} **Fallback System**\n${isSafetySystemEnabled ? emojis.working : emojis.failed} **Safety System**\n${modelEmoji} **${modelNameFormatted}**`,
+ );
+
+ // OTHER SETTINGS CHECKING
+ let isNSFWBlockingEnabled = otherSettings.blockNSFWImages;
+ await updateFieldValueAndReply(
+ interaction,
+ settings,
+ "⚙️ Other:",
+ `${isNSFWBlockingEnabled ? emojis.working : emojis.failed} **NSFW Image Blocking**`,
+ );
+
+ // BUTTONS
+ const personality = new ButtonBuilder()
+ .setCustomId("personality")
+ .setLabel("Personality")
+ .setEmoji("✨")
+ .setStyle(ButtonStyle.Secondary);
+ const console = new ButtonBuilder()
+ .setCustomId("console")
+ .setLabel("Console")
+ .setEmoji("💾")
+ .setStyle(ButtonStyle.Secondary);
+ const webhooksRow = new ActionRowBuilder().addComponents(
+ personality,
+ console,
+ );
+
+ const prodia = new ButtonBuilder()
+ .setCustomId("prodia")
+ .setLabel("Prodia")
+ .setEmoji("🖼️")
+ .setStyle(ButtonStyle.Secondary);
+ const gemini = new ButtonBuilder()
+ .setCustomId("gemini")
+ .setLabel("Gemini")
+ .setEmoji("🤖")
+ .setStyle(ButtonStyle.Secondary);
+ const apiKeysRow = new ActionRowBuilder().addComponents(prodia, gemini);
+
+ const fallbackSystem = new ButtonBuilder()
+ .setCustomId("fallbackSystem")
+ .setLabel("Fallback System")
+ .setEmoji("🛡️")
+ .setStyle(ButtonStyle.Secondary);
+ const safetySystem = new ButtonBuilder()
+ .setCustomId("safetySystem")
+ .setLabel("Safety System")
+ .setEmoji("🔒")
+ .setStyle(ButtonStyle.Secondary);
+ const model = new ButtonBuilder()
+ .setCustomId("model")
+ .setLabel("Model")
+ .setEmoji("🔁")
+ .setStyle(ButtonStyle.Secondary);
+ const modelRow = new ActionRowBuilder().addComponents(
+ fallbackSystem,
+ safetySystem,
+ model,
+ );
+
+ const nsfw = new ButtonBuilder()
+ .setCustomId("blockNSFWImages")
+ .setLabel("NSFW Image Blocking")
+ .setEmoji("🔞")
+ .setStyle(ButtonStyle.Secondary);
+ const otherRow = new ActionRowBuilder().addComponents(nsfw);
+
+ await interaction.editReply({
+ components: [webhooksRow, apiKeysRow, modelRow, otherRow],
+ });
+ } catch (error) {
+ console.error(error);
+ // console.dir(error, { showHidden: true, depth: null });
+ error = new EmbedBuilder()
+ .setDescription("⚠️ **An Error occurred**")
+ .setColor("Red");
+ await interaction.followUp({
+ embeds: [errors],
+ ephemeral: true,
+ });
+ }
+ },
+};
diff --git a/interactions/slash/misc/taurusai.js b/interactions/slash/misc/taurusai.js
index 0bc4d16..d8cb61e 100644
--- a/interactions/slash/misc/taurusai.js
+++ b/interactions/slash/misc/taurusai.js
@@ -3,27 +3,33 @@
* @author TechyGiraffe999
*/
-const { SlashCommandBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, EmbedBuilder } = require("discord.js");
-
+const {
+ SlashCommandBuilder,
+ ModalBuilder,
+ TextInputBuilder,
+ TextInputStyle,
+ ActionRowBuilder,
+} = require("discord.js");
module.exports = {
- data: new SlashCommandBuilder()
- .setName('taurus')
- .setDescription('Ask Taurus a question!'),
- async execute(interaction) {
-
- const taurus = new ModalBuilder()
- .setTitle("Ask TaurusAI something")
- .setCustomId("taurus_ai");
+ data: new SlashCommandBuilder()
+ .setName("taurus")
+ .setDescription("Ask Taurus a question!"),
+ async execute(interaction) {
+ const taurus = new ModalBuilder()
+ .setTitle("Ask TaurusAI something")
+ .setCustomId("taurus_ai");
- const question = new TextInputBuilder()
- .setCustomId("question_taurusai")
- .setRequired(true)
- .setLabel("Question:")
- .setStyle(TextInputStyle.Paragraph);
+ const question = new TextInputBuilder()
+ .setCustomId("question_taurusai")
+ .setRequired(true)
+ .setLabel("Question:")
+ .setStyle(TextInputStyle.Paragraph);
- const taurusai_question_ActionRow = new ActionRowBuilder().addComponents(question);
- taurus.addComponents(taurusai_question_ActionRow);
- await interaction.showModal(taurus);
- }
-};
\ No newline at end of file
+ const taurusai_question_ActionRow = new ActionRowBuilder().addComponents(
+ question,
+ );
+ taurus.addComponents(taurusai_question_ActionRow);
+ await interaction.showModal(taurus);
+ },
+};
diff --git a/messages/defaultButtonError.js b/messages/defaultButtonError.js
new file mode 100644
index 0000000..b06df1b
--- /dev/null
+++ b/messages/defaultButtonError.js
@@ -0,0 +1,23 @@
+/**
+ * @file Default Error Message On Error Button Interaction
+ * @author Naman Vrati
+ * @since 3.0.0
+ */
+const excluded_ids = ["yes_botai_personality", "no_botai_personality"];
+
+module.exports = {
+ /**
+ * @description Executes when the button interaction could not be fetched.
+ * @author Naman Vrati
+ * @param {import('discord.js').ButtonInteraction} interaction The Interaction Object of the command.
+ */
+
+ async execute(interaction) {
+ if (excluded_ids.includes(interaction.customId)) return;
+ await interaction.reply({
+ content: "There was an issue while fetching this button!",
+ ephemeral: true,
+ });
+ return;
+ },
+};
diff --git a/messages/defaultModalError.js b/messages/defaultModalError.js
index 284fce2..6a98784 100644
--- a/messages/defaultModalError.js
+++ b/messages/defaultModalError.js
@@ -5,7 +5,9 @@
const { EmbedBuilder } = require("discord.js");
const error = new EmbedBuilder()
- .setDescription("**There was an issue while fetching this modal!\n\nPlease contact the Developers.**")
+ .setDescription(
+ "**There was an issue while fetching this modal!\n\nPlease contact the Developers.**",
+ )
.setColor("Red");
module.exports = {
diff --git a/package.json b/package.json
index 126c4a4..88bfd9e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "taurus",
- "version": "3.0",
+ "version": "4.0",
"description": "An AI Discord Bot!",
"types": "./typings.d.ts",
"main": "bot.js",
@@ -23,18 +23,23 @@
"url": "https://github.com/TecEash1/Taurus/issues"
},
"dependencies": {
- "@google/generative-ai": "^0.2.1",
+ "@google/generative-ai": "^0.11.3",
"@iamtraction/google-translate": "^2.0.1",
- "@tensorflow/tfjs-node": "^4.17.0",
+ "@tensorflow/tfjs-node": "^4.19.0",
"api": "^6.1.1",
- "axios": "^1.6.7",
+ "axios": "^1.6.8",
+ "better-sqlite3": "^10.0.0",
"blessed": "^0.1.81",
"chalk": "^5.3.0",
- "discord-api-types": "^0.37.43",
- "discord.js": "^14.11.0",
+ "discord-api-types": "^0.37.84",
+ "discord.js": "^14.15.2",
"figlet": "^1.7.0",
"moment": "^2.30.1",
- "nsfwjs": "^3.0.0",
- "os": "^0.1.2"
+ "nsfwjs": "^4.1.0",
+ "os": "^0.1.2",
+ "quick.db": "^9.1.7"
+ },
+ "devDependencies": {
+ "prettier": "3.2.5"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..580bba2
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,3032 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@google/generative-ai':
+ specifier: ^0.11.3
+ version: 0.11.3
+ '@iamtraction/google-translate':
+ specifier: ^2.0.1
+ version: 2.0.1
+ '@tensorflow/tfjs-node':
+ specifier: ^4.19.0
+ version: 4.19.0(seedrandom@3.0.5)
+ api:
+ specifier: ^6.1.1
+ version: 6.1.1(openapi-types@12.1.3)
+ axios:
+ specifier: ^1.6.8
+ version: 1.6.8
+ better-sqlite3:
+ specifier: ^10.0.0
+ version: 10.0.0
+ blessed:
+ specifier: ^0.1.81
+ version: 0.1.81
+ chalk:
+ specifier: ^5.3.0
+ version: 5.3.0
+ discord-api-types:
+ specifier: ^0.37.84
+ version: 0.37.84
+ discord.js:
+ specifier: ^14.15.2
+ version: 14.15.2
+ figlet:
+ specifier: ^1.7.0
+ version: 1.7.0
+ moment:
+ specifier: ^2.30.1
+ version: 2.30.1
+ nsfwjs:
+ specifier: ^4.1.0
+ version: 4.1.0(@tensorflow/tfjs@4.19.0(seedrandom@3.0.5))
+ os: {specifier: ^0.1.2, version: 0.1.2}
+ quick.db:
+ specifier: ^9.1.7
+ version: 9.1.7
+ devDependencies:
+ prettier:
+ specifier: 3.2.5
+ version: 3.2.5
+
+packages:
+
+ '@apidevtools/openapi-schemas@2.1.0':
+ resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==}
+ engines: {node: '>=10'}
+
+ '@apidevtools/swagger-methods@3.0.2':
+ resolution: {integrity: sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==}
+
+ '@babel/code-frame@7.24.2':
+ resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.24.5':
+ resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/highlight@7.24.5':
+ resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/runtime@7.24.5':
+ resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==}
+ engines: {node: '>=6.9.0'}
+
+ '@discordjs/builders@1.8.1':
+ resolution: {integrity: sha512-GkF+HM01FHy+NSoTaUPR8z44otfQgJ1AIsRxclYGUZDyUbdZEFyD/5QVv2Y1Flx6M+B0bQLzg2M9CJv5lGTqpA==}
+ engines: {node: '>=16.11.0'}
+
+ '@discordjs/collection@1.5.3':
+ resolution: {integrity: sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==}
+ engines: {node: '>=16.11.0'}
+
+ '@discordjs/collection@2.1.0':
+ resolution: {integrity: sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==}
+ engines: {node: '>=18'}
+
+ '@discordjs/formatters@0.4.0':
+ resolution: {integrity: sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==}
+ engines: {node: '>=16.11.0'}
+
+ '@discordjs/rest@2.3.0':
+ resolution: {integrity: sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==}
+ engines: {node: '>=16.11.0'}
+
+ '@discordjs/util@1.1.0':
+ resolution: {integrity: sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==}
+ engines: {node: '>=16.11.0'}
+
+ '@discordjs/ws@1.1.0':
+ resolution: {integrity: sha512-O97DIeSvfNTn5wz5vaER6ciyUsr7nOqSEtsLoMhhIgeFkhnxLRqSr00/Fpq2/ppLgjDGLbQCDzIK7ilGoB/M7A==}
+ engines: {node: '>=16.11.0'}
+
+ '@exodus/schemasafe@1.3.0':
+ resolution: {integrity: sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==}
+
+ '@fastify/busboy@2.1.1':
+ resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
+ engines: {node: '>=14'}
+
+ '@google/generative-ai@0.11.3':
+ resolution: {integrity: sha512-QtQ1hz6rcybbw35uxXlFF26KNnaTVr2oWwnmDkC1M35KdzN4tVc4wakgJp8uXbY9KDCNHksyp11DbFg0HPckZQ==}
+ engines: {node: '>=18.0.0'}
+
+ '@humanwhocodes/momoa@2.0.4':
+ resolution: {integrity: sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==}
+ engines: {node: '>=10.10.0'}
+
+ '@iamtraction/google-translate@2.0.1':
+ resolution: {integrity: sha512-kOTkt23zflxpgxLIe9tLvDU8IvNscXYbgMSXydNkZGWDtJ75YJiU3v7EBz+t7h/gSiY7sT5r4dlFkMrHCl+N6A==}
+ engines: {node: '>=16.0.0'}
+
+ '@jsdevtools/ono@7.1.3':
+ resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==}
+
+ '@mapbox/node-pre-gyp@1.0.9':
+ resolution: {integrity: sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==}
+ hasBin: true
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@readme/better-ajv-errors@1.6.0':
+ resolution: {integrity: sha512-9gO9rld84Jgu13kcbKRU+WHseNhaVt76wYMeRDGsUGYxwJtI3RmEJ9LY9dZCYQGI8eUZLuxb5qDja0nqklpFjQ==}
+ engines: {node: '>=14'}
+ peerDependencies:
+ ajv: 4.11.8 - 8
+
+ '@readme/data-urls@1.0.1':
+ resolution: {integrity: sha512-FNP4ntG5rCgmrvQGoNH/Ljivc6jSWaaVeMuXneOyQ6oLuhm/NkysXJN3DnBrIsJUJbSae7qIs2QfPYnaropoHw==}
+ engines: {node: '>=14'}
+
+ '@readme/http-status-codes@7.2.0':
+ resolution: {integrity: sha512-/dBh9qw3QhJYqlGwt2I+KUP/lQ6nytdCx3aq+GpMUhibLHF3O7fwoowNcTwlbnwtyJ+TJYTIIrp3oVUlRNx3fA==}
+
+ '@readme/json-schema-ref-parser@1.2.0':
+ resolution: {integrity: sha512-Bt3QVovFSua4QmHa65EHUmh2xS0XJ3rgTEUPH998f4OW4VVJke3BuS16f+kM0ZLOGdvIrzrPRqwihuv5BAjtrA==}
+
+ '@readme/oas-extensions@17.0.1':
+ resolution: {integrity: sha512-PCU7WLz8TkbdxsiE4eQGvJYDYZQPiyLhXme3SvLboSmH+8G6AJPJ5OymzSAdlf5sXpSSoD2q3dTIou3Cb2DirQ==}
+ engines: {node: '>=14'}
+ deprecated: The functionality for this library has been moved into `oas`.
+ peerDependencies:
+ oas: ^20.0.0
+
+ '@readme/oas-to-har@20.1.1':
+ resolution: {integrity: sha512-rz8YpdZw+Jqrd8VQhQaYrzctkCAYdBldoQ5qDQyF9vGvq2lpA1yMvQPgKCJXfPGXH8Cm+NjLbunxnYabKQeKeA==}
+ engines: {node: '>=14'}
+
+ '@readme/openapi-parser@2.5.1':
+ resolution: {integrity: sha512-p9ndWhwjtP+DEiOOF6jeNMpdmYIPM4nl+JEIdnQNdq7b68esI024x7HiYACZpaYaSvISDSyKc7aiRJx4K4IDhg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ openapi-types: '>=7'
+
+ '@readme/postman-to-openapi@4.1.0':
+ resolution: {integrity: sha512-VvV2Hzjskz01m8doSn7Ypt6cSZzgjnypVqXy1ipThbyYD6SGiM74VSePXykOODj/43Y2m6zeYedPk/ZLts/HvQ==}
+ engines: {node: '>=14'}
+
+ '@sapphire/async-queue@1.5.2':
+ resolution: {integrity: sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg==}
+ engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
+
+ '@sapphire/shapeshift@3.9.7':
+ resolution: {integrity: sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==}
+ engines: {node: '>=v16'}
+
+ '@sapphire/snowflake@3.5.3':
+ resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==}
+ engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
+
+ '@tensorflow/tfjs-backend-cpu@4.19.0':
+ resolution: {integrity: sha512-7pT05Ea6GTXjbqRgkmayZRYvaiNl3LLk1TyfUvC8iIqMw5d7p4Wgte2pfM2gMbIZ/opOxURhFYuI0FiQvUrW6g==}
+ engines: {yarn: '>= 1.3.2'}
+ peerDependencies:
+ '@tensorflow/tfjs-core': 4.19.0
+
+ '@tensorflow/tfjs-backend-webgl@4.19.0':
+ resolution: {integrity: sha512-R0DC1W65lqTOccCwxMhH+VOKCgSrhd9GEejIIGhjeXt6oZlACFnOx4SuUr/qKLCDsL5I4E9iFLxAJMmsfYvARw==}
+ engines: {yarn: '>= 1.3.2'}
+ peerDependencies:
+ '@tensorflow/tfjs-core': 4.19.0
+
+ '@tensorflow/tfjs-converter@4.19.0':
+ resolution: {integrity: sha512-xIOE6enaVHPYCXKpHxJnUlN8hzlcQkgFSymHjBmdDnNCresuRwBGz4dqYAQMeQG21Ei3lxCQFdDDH7aSvUEAPw==}
+ peerDependencies:
+ '@tensorflow/tfjs-core': 4.19.0
+
+ '@tensorflow/tfjs-core@4.19.0':
+ resolution: {integrity: sha512-GZ0d53PG0HGQCC7hbWv1qDnZctHYe/cafHZrBY5eNeQjQE6fBr3NsR5GfLadT0TELwmX9/nyritGDzvy6xmzHQ==}
+ engines: {yarn: '>= 1.3.2'}
+
+ '@tensorflow/tfjs-data@4.19.0':
+ resolution: {integrity: sha512-n0ZgJp5UhhBatohUt9pXSCCApusK+1Flyk6yDrQYuxOTjhRppd6jYrF7LCDG3hMFi3QLGl0jab1zYrn9BwtC/w==}
+ peerDependencies:
+ '@tensorflow/tfjs-core': 4.19.0
+ seedrandom: ^3.0.5
+
+ '@tensorflow/tfjs-layers@4.19.0':
+ resolution: {integrity: sha512-NufvuRaZdIyoG+R13d7oL8G5Bywox+ihPMiMZ3tWU+me8C8Y0pVC69mrnhOS9R8an7GDxKKSTTNEZhUvPvMGiQ==}
+ peerDependencies:
+ '@tensorflow/tfjs-core': 4.19.0
+
+ '@tensorflow/tfjs-node@4.19.0':
+ resolution: {integrity: sha512-1HLIAuu5azP8SW7t5EZc1W5VOdjWndJYz1N1agz0It/tMtnuWIdAfcY08VjfuiI/NhAwuPShehqv6CZ3SYh+Vg==}
+ engines: {node: '>=8.11.0'}
+
+ '@tensorflow/tfjs@4.19.0':
+ resolution: {integrity: sha512-d2A1lTc6my7GJ5LwqzXa+igJ5+18exwsnaphZ3roi5nJ197uwxVSMIc2vSJnqZz1KajC5/mZgQr67EZrpTFlBg==}
+ hasBin: true
+
+ '@ts-morph/common@0.18.1':
+ resolution: {integrity: sha512-RVE+zSRICWRsfrkAw5qCAK+4ZH9kwEFv5h0+/YeHTLieWP7F4wWq4JsKFuNWG+fYh/KF+8rAtgdj5zb2mm+DVA==}
+
+ '@types/har-format@1.2.15':
+ resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==}
+
+ '@types/json-schema@7.0.15':
+ resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
+ '@types/long@4.0.2':
+ resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
+
+ '@types/node-fetch@2.6.11':
+ resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==}
+
+ '@types/node@20.12.12':
+ resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==}
+
+ '@types/offscreencanvas@2019.3.0':
+ resolution: {integrity: sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==}
+
+ '@types/offscreencanvas@2019.7.3':
+ resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==}
+
+ '@types/seedrandom@2.4.34':
+ resolution: {integrity: sha512-ytDiArvrn/3Xk6/vtylys5tlY6eo7Ane0hvcx++TKo6RxQXuVfW0AF/oeWqAj9dN29SyhtawuXstgmPlwNcv/A==}
+
+ '@types/ws@8.5.10':
+ resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
+
+ '@vladfrangu/async_event_emitter@2.2.4':
+ resolution: {integrity: sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug==}
+ engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
+
+ '@webgpu/types@0.1.38':
+ resolution: {integrity: sha512-7LrhVKz2PRh+DD7+S+PVaFd5HxaWQvoMqBbsV9fNJO1pjUs1P8bM2vQVNfk+3URTqbuTI7gkXi0rfsN0IadoBA==}
+
+ abbrev@1.1.1:
+ resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
+
+ adm-zip@0.5.12:
+ resolution: {integrity: sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ==}
+ engines: {node: '>=6.0'}
+
+ agent-base@4.3.0:
+ resolution: {integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==}
+ engines: {node: '>= 4.0.0'}
+
+ agent-base@6.0.2:
+ resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
+ engines: {node: '>= 6.0.0'}
+
+ ajv-draft-04@1.0.0:
+ resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==}
+ peerDependencies:
+ ajv: ^8.5.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+
+ ajv@8.13.0:
+ resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-styles@3.2.1:
+ resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+ engines: {node: '>=4'}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
+ api@6.1.1:
+ resolution: {integrity: sha512-we3fnLinpYWlKOHdX4S/Ky9gZvColCnht/qhtv04K2jQbrC/z4SxvZVAT8W8PCC5NLLU4H35r3u4Lt77ZaiY9w==}
+ engines: {node: '>=16'}
+ hasBin: true
+
+ aproba@2.0.0:
+ resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
+
+ are-we-there-yet@2.0.0:
+ resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
+ engines: {node: '>=10'}
+
+ argparse@1.0.10:
+ resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
+
+ argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+ asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+ axios@1.6.8:
+ resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==}
+
+ balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
+ better-sqlite3@10.0.0:
+ resolution: {integrity: sha512-rOz0JY8bt9oMgrFssP7GnvA5R3yln73y/NizzWqy3WlFth8Ux8+g4r/N9fjX97nn4X1YX6MTER2doNpTu5pqiA==}
+
+ bindings@1.5.0:
+ resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
+
+ bl@4.1.0:
+ resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
+
+ blessed@0.1.81:
+ resolution: {integrity: sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==}
+ engines: {node: '>= 0.8.0'}
+ hasBin: true
+
+ brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+
+ brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+
+ braces@3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+
+ buffer@5.7.1:
+ resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+
+ call-bind@1.0.7:
+ resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
+ engines: {node: '>= 0.4'}
+
+ call-me-maybe@1.0.2:
+ resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==}
+
+ caseless@0.12.0:
+ resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
+
+ chalk@2.4.2:
+ resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+ engines: {node: '>=4'}
+
+ chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+
+ chalk@5.3.0:
+ resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+
+ chownr@1.1.4:
+ resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
+
+ chownr@2.0.0:
+ resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
+ engines: {node: '>=10'}
+
+ cli-cursor@3.1.0:
+ resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
+ engines: {node: '>=8'}
+
+ cli-spinners@2.9.2:
+ resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
+ engines: {node: '>=6'}
+
+ cliui@7.0.4:
+ resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
+
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+
+ clone@1.0.4:
+ resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
+ engines: {node: '>=0.8'}
+
+ code-block-writer@11.0.3:
+ resolution: {integrity: sha512-NiujjUFB4SwScJq2bwbYUtXbZhBSlY6vYzm++3Q6oC+U+injTqfPYFK8wS9COOmb2lueqp0ZRB4nK1VYeHgNyw==}
+
+ code-error-fragment@0.0.230:
+ resolution: {integrity: sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==}
+ engines: {node: '>= 4'}
+
+ color-convert@1.9.3:
+ resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.3:
+ resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ color-support@1.1.3:
+ resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
+ hasBin: true
+
+ combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+
+ commander@10.0.1:
+ resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
+ engines: {node: '>=14'}
+
+ commondir@1.0.1:
+ resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
+
+ compute-gcd@1.2.1:
+ resolution: {integrity: sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==}
+
+ compute-lcm@1.1.2:
+ resolution: {integrity: sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==}
+
+ concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+ console-control-strings@1.1.0:
+ resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
+
+ core-js@3.29.1:
+ resolution: {integrity: sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==}
+
+ cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+
+ d@1.0.2:
+ resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
+ engines: {node: '>=0.12'}
+
+ datauri@4.1.0:
+ resolution: {integrity: sha512-y17kh32+I82G+ED9MNWFkZiP/Cq/vO1hN9+tSZsT9C9qn3NrvcBnh7crSepg0AQPge1hXx2Ca44s1FRdv0gFWA==}
+ engines: {node: '>= 10'}
+
+ debug@3.2.7:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ decompress-response@6.0.0:
+ resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
+ engines: {node: '>=10'}
+
+ deep-extend@0.6.0:
+ resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
+ engines: {node: '>=4.0.0'}
+
+ defaults@1.0.4:
+ resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
+
+ define-data-property@1.1.4:
+ resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
+ engines: {node: '>= 0.4'}
+
+ delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+
+ delegates@1.0.0:
+ resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
+
+ detect-libc@2.0.3:
+ resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
+ engines: {node: '>=8'}
+
+ discord-api-types@0.37.83:
+ resolution: {integrity: sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==}
+
+ discord-api-types@0.37.84:
+ resolution: {integrity: sha512-NngmTBW8vermlbO0qNtaS7SHCWB/R96ICqflTwM/cV7zsxyQGd38E2bBlwaxLbXgb2YTF3+Yx6+qGs/3sXedCw==}
+
+ discord.js@14.15.2:
+ resolution: {integrity: sha512-wGD37YCaTUNprtpqMIRuNiswwsvSWXrHykBSm2SAosoTYut0VUDj9yo9t4iLtMKvuhI49zYkvKc2TNdzdvpJhg==}
+ engines: {node: '>=16.11.0'}
+
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+ end-of-stream@1.4.4:
+ resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
+
+ es-define-property@1.0.0:
+ resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
+ engines: {node: '>= 0.4'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es5-ext@0.10.64:
+ resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
+ engines: {node: '>=0.10'}
+
+ es6-iterator@2.0.3:
+ resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
+
+ es6-promise@3.3.1:
+ resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==}
+
+ es6-promise@4.2.8:
+ resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==}
+
+ es6-promisify@5.0.0:
+ resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==}
+
+ es6-symbol@3.1.4:
+ resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
+ engines: {node: '>=0.12'}
+
+ es6-weak-map@2.0.3:
+ resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==}
+
+ escalade@3.1.2:
+ resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
+ engines: {node: '>=6'}
+
+ escape-string-regexp@1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+
+ esniff@2.0.1:
+ resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
+ engines: {node: '>=0.10'}
+
+ event-emitter@0.3.5:
+ resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
+
+ execa@5.1.1:
+ resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+ engines: {node: '>=10'}
+
+ expand-template@2.0.3:
+ resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
+ engines: {node: '>=6'}
+
+ ext@1.7.0:
+ resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fast-glob@3.3.2:
+ resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+ engines: {node: '>=8.6.0'}
+
+ fast-safe-stringify@2.1.1:
+ resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
+
+ fastq@1.17.1:
+ resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
+
+ fetch-har@8.1.5:
+ resolution: {integrity: sha512-c9WDro4RWC+suOVRJFNW21cgqTOELRZpvFJgfENvOM7Yt/VA4QeFtRax795SyOpTisdpcl5XNQlQZdAE6HERDA==}
+ engines: {node: '>=14'}
+
+ figlet@1.7.0:
+ resolution: {integrity: sha512-gO8l3wvqo0V7wEFLXPbkX83b7MVjRrk1oRLfYlZXol8nEpb/ON9pcKLI4qpBv5YtOTfrINtqb7b40iYY2FTWFg==}
+ engines: {node: '>= 0.4.0'}
+ hasBin: true
+
+ figures@3.2.0:
+ resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
+ engines: {node: '>=8'}
+
+ file-uri-to-path@1.0.0:
+ resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
+
+ fill-range@7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+
+ find-cache-dir@3.3.2:
+ resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==}
+ engines: {node: '>=8'}
+
+ find-up@4.1.0:
+ resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+ engines: {node: '>=8'}
+
+ follow-redirects@1.15.6:
+ resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+
+ form-data-encoder@1.9.0:
+ resolution: {integrity: sha512-rahaRMkN8P8d/tgK/BLPX+WBVM27NbvdXBxqQujBtkDAIFspaRqN7Od7lfdGQA6KAD+f82fYCLBq1ipvcu8qLw==}
+
+ form-data@4.0.0:
+ resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+ engines: {node: '>= 6'}
+
+ formdata-node@4.4.1:
+ resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==}
+ engines: {node: '>= 12.20'}
+
+ fs-constants@1.0.0:
+ resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
+
+ fs-minipass@1.2.7:
+ resolution: {integrity: sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==}
+
+ fs-minipass@2.1.0:
+ resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
+ engines: {node: '>= 8'}
+
+ fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ gauge@3.0.2:
+ resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
+ engines: {node: '>=10'}
+
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
+ get-intrinsic@1.2.4:
+ resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
+ engines: {node: '>= 0.4'}
+
+ get-stream@6.0.1:
+ resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+ engines: {node: '>=10'}
+
+ github-from-package@0.0.0:
+ resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+
+ google-protobuf@3.21.2:
+ resolution: {integrity: sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==}
+
+ gopd@1.0.1:
+ resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+
+ grapheme-splitter@1.0.4:
+ resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
+
+ has-flag@3.0.0:
+ resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+ engines: {node: '>=4'}
+
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
+ has-property-descriptors@1.0.2:
+ resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
+
+ has-proto@1.0.3:
+ resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
+ engines: {node: '>= 0.4'}
+
+ has-symbols@1.0.3:
+ resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+ engines: {node: '>= 0.4'}
+
+ has-unicode@2.0.1:
+ resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ http2-client@1.3.5:
+ resolution: {integrity: sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==}
+
+ https-proxy-agent@2.2.4:
+ resolution: {integrity: sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==}
+ engines: {node: '>= 4.5.0'}
+
+ https-proxy-agent@5.0.1:
+ resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
+ engines: {node: '>= 6'}
+
+ human-signals@2.1.0:
+ resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+ engines: {node: '>=10.17.0'}
+
+ ieee754@1.2.1:
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
+ image-size@1.0.0:
+ resolution: {integrity: sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==}
+ engines: {node: '>=12.0.0'}
+ hasBin: true
+
+ inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ ini@1.3.8:
+ resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-interactive@1.0.0:
+ resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
+ engines: {node: '>=8'}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ is-promise@2.2.2:
+ resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
+
+ is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+
+ is-unicode-supported@0.1.0:
+ resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
+ engines: {node: '>=10'}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ isomorphic-fetch@3.0.0:
+ resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==}
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ js-yaml@4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+
+ json-schema-compare@0.2.2:
+ resolution: {integrity: sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==}
+
+ json-schema-merge-allof@0.8.1:
+ resolution: {integrity: sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==}
+ engines: {node: '>=12.0.0'}
+
+ json-schema-to-ts@2.12.0:
+ resolution: {integrity: sha512-uTde38yBm5lzJSRPWRaasxZo72pb+JGE4iUksNdNfAkFaLhV4N9akeBxPPUpZy5onINt9Zo0oTLrAoEXyZESiQ==}
+ engines: {node: '>=16'}
+
+ json-schema-traverse@1.0.0:
+ resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
+
+ json-to-ast@2.1.0:
+ resolution: {integrity: sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ==}
+ engines: {node: '>= 4'}
+
+ jsonc-parser@3.2.0:
+ resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
+
+ jsonpath-plus@7.2.0:
+ resolution: {integrity: sha512-zBfiUPM5nD0YZSBT/o/fbCUlCcepMIdP0CJZxM1+KgA4f2T206f6VAg9e7mX35+KlMaIc5qXW34f3BnwJ3w+RA==}
+ engines: {node: '>=12.0.0'}
+
+ jsonpointer@5.0.1:
+ resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==}
+ engines: {node: '>=0.10.0'}
+
+ kleur@3.0.3:
+ resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
+ engines: {node: '>=6'}
+
+ leven@3.1.0:
+ resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
+ engines: {node: '>=6'}
+
+ locate-path@5.0.0:
+ resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+ engines: {node: '>=8'}
+
+ lodash.camelcase@4.3.0:
+ resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
+
+ lodash.deburr@4.1.0:
+ resolution: {integrity: sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==}
+
+ lodash.merge@4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+
+ lodash.setwith@4.3.2:
+ resolution: {integrity: sha512-Cv2pndcuNDaqDMJ0gbLm5qNG5jyfsL6f8+f5PfZVVNhQCv+y+P5gAKkCdZbtiQlux7nsnWF7UmZd8JEFIo/4tg==}
+
+ lodash.snakecase@4.1.1:
+ resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==}
+
+ lodash.startcase@4.4.0:
+ resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==}
+
+ lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
+ log-symbols@4.1.0:
+ resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
+ engines: {node: '>=10'}
+
+ long@4.0.0:
+ resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==}
+
+ lru-queue@0.1.0:
+ resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==}
+
+ magic-bytes.js@1.10.0:
+ resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==}
+
+ make-dir@3.1.0:
+ resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
+ engines: {node: '>=8'}
+
+ marked@4.3.0:
+ resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==}
+ engines: {node: '>= 12'}
+ hasBin: true
+
+ memoizee@0.4.15:
+ resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==}
+
+ merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromatch@4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ mimer@2.0.2:
+ resolution: {integrity: sha512-izxvjsB7Ur5HrTbPu6VKTrzxSMBFBqyZQc6dWlZNQ4/wAvf886fD4lrjtFd8IQ8/WmZKdxKjUtqFFNaj3hQ52g==}
+ engines: {node: '>= 12'}
+ hasBin: true
+
+ mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+
+ mimic-response@3.1.0:
+ resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
+ engines: {node: '>=10'}
+
+ minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+
+ minimatch@5.1.6:
+ resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
+ engines: {node: '>=10'}
+
+ minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
+ minipass@2.9.0:
+ resolution: {integrity: sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==}
+
+ minipass@3.3.6:
+ resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
+ engines: {node: '>=8'}
+
+ minipass@5.0.0:
+ resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
+ engines: {node: '>=8'}
+
+ minipass@7.1.1:
+ resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minizlib@1.3.3:
+ resolution: {integrity: sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==}
+
+ minizlib@2.1.2:
+ resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
+ engines: {node: '>= 8'}
+
+ mkdirp-classic@0.5.3:
+ resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
+
+ mkdirp@0.5.6:
+ resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
+ hasBin: true
+
+ mkdirp@1.0.4:
+ resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ moment@2.30.1:
+ resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
+
+ ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ mustache@4.2.0:
+ resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
+ hasBin: true
+
+ napi-build-utils@1.0.2:
+ resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
+
+ next-tick@1.1.0:
+ resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
+
+ node-abi@3.62.0:
+ resolution: {integrity: sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==}
+ engines: {node: '>=10'}
+
+ node-abort-controller@3.1.1:
+ resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
+
+ node-domexception@1.0.0:
+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+ engines: {node: '>=10.5.0'}
+
+ node-fetch-h2@2.3.0:
+ resolution: {integrity: sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==}
+ engines: {node: 4.x || >=6.0.0}
+
+ node-fetch@2.6.13:
+ resolution: {integrity: sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==}
+ engines: {node: 4.x || >=6.0.0}
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+
+ node-fetch@2.7.0:
+ resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
+ engines: {node: 4.x || >=6.0.0}
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+
+ node-readfiles@0.2.0:
+ resolution: {integrity: sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==}
+
+ nopt@5.0.0:
+ resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ npm-run-path@4.0.1:
+ resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+ engines: {node: '>=8'}
+
+ npmlog@5.0.1:
+ resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
+
+ nsfwjs@4.1.0:
+ resolution: {integrity: sha512-2V27SoNXUJbAAi+vW8RHJbONs2AHa1odmjlRsVX2mirxR4IGt1OIzZ49IXgPVg6nktwA8Su61YEJql7VreEKyg==}
+ peerDependencies:
+ '@tensorflow/tfjs': ^4.0.0
+
+ oas-kit-common@1.0.8:
+ resolution: {integrity: sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==}
+
+ oas-linter@3.2.2:
+ resolution: {integrity: sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==}
+
+ oas-normalize@8.4.1:
+ resolution: {integrity: sha512-cGODg+AntZteJRHBiYDWKtcO2svWGMXuFWYu2I8b4hOrNiwB3hgDs/ScX3O9mYm6RpLsUIftt6rDHGc8eYG8aA==}
+ engines: {node: '>=14'}
+
+ oas-resolver@2.5.6:
+ resolution: {integrity: sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==}
+ hasBin: true
+
+ oas-schema-walker@1.1.5:
+ resolution: {integrity: sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==}
+
+ oas-validator@5.0.8:
+ resolution: {integrity: sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==}
+
+ oas@20.10.3:
+ resolution: {integrity: sha512-dBxDuwn2ssggPMOqEKEzT4sjCqbkol8JozuWrpwD7chcmbKbverj5vpk2kmsczeyguFkLcKUOMcqUUimf9h+IQ==}
+ engines: {node: '>=14'}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ object-inspect@1.13.1:
+ resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
+
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+
+ openapi-types@12.1.3:
+ resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==}
+
+ ora@5.4.1:
+ resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
+ engines: {node: '>=10'}
+
+ os@0.1.2:
+ resolution: {integrity: sha512-ZoXJkvAnljwvc56MbvhtKVWmSkzV712k42Is2mA0+0KTSRakq5XXuXpjZjgAt9ctzl51ojhQWakQQpmOvXWfjQ==}
+
+ p-limit@2.3.0:
+ resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+ engines: {node: '>=6'}
+
+ p-locate@4.1.0:
+ resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+ engines: {node: '>=8'}
+
+ p-try@2.2.0:
+ resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+ engines: {node: '>=6'}
+
+ path-browserify@1.0.1:
+ resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+
+ path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+
+ path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-to-regexp@6.2.2:
+ resolution: {integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==}
+
+ picocolors@1.0.1:
+ resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
+
+ picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ pkg-dir@4.2.0:
+ resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
+ engines: {node: '>=8'}
+
+ prebuild-install@7.1.2:
+ resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ prettier@3.2.5:
+ resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==}
+ engines: {node: '>=14'}
+ hasBin: true
+
+ progress@2.0.3:
+ resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
+ engines: {node: '>=0.4.0'}
+
+ prompts@2.4.2:
+ resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
+ engines: {node: '>= 6'}
+
+ proxy-from-env@1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+
+ pump@3.0.0:
+ resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
+
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
+ qs@6.12.1:
+ resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==}
+ engines: {node: '>=0.6'}
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ queue@6.0.2:
+ resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==}
+
+ quick.db@9.1.7:
+ resolution: {integrity: sha512-ZLPVLVFZtvFRLHqIK99iyrLDUznOTpnp5tB+QpGErT+reDSvgBELuVsMkGSSiqKT9R2YSOhO+096Wb0xTaOHMA==}
+
+ rc@1.2.8:
+ resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
+ hasBin: true
+
+ readable-stream@3.6.2:
+ resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+ engines: {node: '>= 6'}
+
+ reftools@1.1.9:
+ resolution: {integrity: sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==}
+
+ regenerator-runtime@0.13.11:
+ resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
+
+ regenerator-runtime@0.14.1:
+ resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+
+ remove-undefined-objects@2.0.2:
+ resolution: {integrity: sha512-b6x4MUtR4YBW1aCoGx3tE4mA2PFjiXSmtSdNmLexQzUdZa4ybnJAItXLKpkcVgCUJIzJtk2DFG402sMSEMlonQ==}
+ engines: {node: '>=14'}
+
+ remove-undefined-objects@3.0.0:
+ resolution: {integrity: sha512-nxG1yYfc/Jxi+bNCBiqKhxVJPE+QvziIOKbD+Dxc93Uisz92v/ZYpo4WR0TJuf+dk2xE8lW2WPJsA3mDFzXy8w==}
+ engines: {node: '>=16'}
+
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+
+ require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+
+ restore-cursor@3.1.0:
+ resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
+ engines: {node: '>=8'}
+
+ reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rimraf@2.7.1:
+ resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
+ hasBin: true
+
+ rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ hasBin: true
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+ seedrandom@3.0.5:
+ resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==}
+
+ semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+
+ semver@7.6.2:
+ resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ set-blocking@2.0.0:
+ resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
+
+ set-function-length@1.2.2:
+ resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
+ engines: {node: '>= 0.4'}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ should-equal@2.0.0:
+ resolution: {integrity: sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==}
+
+ should-format@3.0.3:
+ resolution: {integrity: sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==}
+
+ should-type-adaptors@1.1.0:
+ resolution: {integrity: sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==}
+
+ should-type@1.4.0:
+ resolution: {integrity: sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==}
+
+ should-util@1.0.1:
+ resolution: {integrity: sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==}
+
+ should@13.2.3:
+ resolution: {integrity: sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==}
+
+ side-channel@1.0.6:
+ resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
+ engines: {node: '>= 0.4'}
+
+ signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
+ simple-concat@1.0.1:
+ resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
+
+ simple-get@4.0.1:
+ resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
+
+ sisteransi@1.0.5:
+ resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+
+ sprintf-js@1.0.3:
+ resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+
+ ssri@10.0.6:
+ resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
+ string_decoder@1.3.0:
+ resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
+ strip-final-newline@2.0.0:
+ resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+ engines: {node: '>=6'}
+
+ strip-json-comments@2.0.1:
+ resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
+ engines: {node: '>=0.10.0'}
+
+ supports-color@5.5.0:
+ resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+ engines: {node: '>=4'}
+
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+
+ swagger2openapi@7.0.8:
+ resolution: {integrity: sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==}
+ hasBin: true
+
+ tar-fs@2.1.1:
+ resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==}
+
+ tar-stream@2.2.0:
+ resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
+ engines: {node: '>=6'}
+
+ tar@4.4.19:
+ resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==}
+ engines: {node: '>=4.5'}
+
+ tar@6.2.1:
+ resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
+ engines: {node: '>=10'}
+
+ timers-ext@0.1.7:
+ resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==}
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ tr46@0.0.3:
+ resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+
+ ts-algebra@1.2.2:
+ resolution: {integrity: sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==}
+
+ ts-mixer@6.0.4:
+ resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==}
+
+ ts-morph@17.0.1:
+ resolution: {integrity: sha512-10PkHyXmrtsTvZSL+cqtJLTgFXkU43Gd0JCc0Rw6GchWbqKe0Rwgt1v3ouobTZwQzF1mGhDeAlWYBMGRV7y+3g==}
+
+ tslib@2.6.2:
+ resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
+
+ tunnel-agent@0.6.0:
+ resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
+
+ type@2.7.2:
+ resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==}
+
+ undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+
+ undici@5.28.4:
+ resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
+ engines: {node: '>=14.0'}
+
+ undici@6.13.0:
+ resolution: {integrity: sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==}
+ engines: {node: '>=18.0'}
+
+ uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ validate-npm-package-name@5.0.1:
+ resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
+ validate.io-array@1.0.6:
+ resolution: {integrity: sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==}
+
+ validate.io-function@1.0.2:
+ resolution: {integrity: sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==}
+
+ validate.io-integer-array@1.0.0:
+ resolution: {integrity: sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==}
+
+ validate.io-integer@1.0.5:
+ resolution: {integrity: sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==}
+
+ validate.io-number@1.0.3:
+ resolution: {integrity: sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==}
+
+ wcwidth@1.0.1:
+ resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
+
+ web-streams-polyfill@4.0.0-beta.3:
+ resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==}
+ engines: {node: '>= 14'}
+
+ webidl-conversions@3.0.1:
+ resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+
+ whatwg-fetch@3.6.20:
+ resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==}
+
+ whatwg-url@5.0.0:
+ resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ wide-align@1.1.5:
+ resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
+
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ ws@8.17.0:
+ resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+ yallist@4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+
+ yaml@1.10.2:
+ resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
+ engines: {node: '>= 6'}
+
+ yargs-parser@20.2.9:
+ resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
+ engines: {node: '>=10'}
+
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
+ yargs@16.2.0:
+ resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
+ engines: {node: '>=10'}
+
+ yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+
+snapshots:
+
+ '@apidevtools/openapi-schemas@2.1.0': {}
+
+ '@apidevtools/swagger-methods@3.0.2': {}
+
+ '@babel/code-frame@7.24.2':
+ dependencies:
+ '@babel/highlight': 7.24.5
+ picocolors: 1.0.1
+
+ '@babel/helper-validator-identifier@7.24.5': {}
+
+ '@babel/highlight@7.24.5':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.24.5
+ chalk: 2.4.2
+ js-tokens: 4.0.0
+ picocolors: 1.0.1
+
+ '@babel/runtime@7.24.5':
+ dependencies:
+ regenerator-runtime: 0.14.1
+
+ '@discordjs/builders@1.8.1':
+ dependencies:
+ '@discordjs/formatters': 0.4.0
+ '@discordjs/util': 1.1.0
+ '@sapphire/shapeshift': 3.9.7
+ discord-api-types: 0.37.83
+ fast-deep-equal: 3.1.3
+ ts-mixer: 6.0.4
+ tslib: 2.6.2
+
+ '@discordjs/collection@1.5.3': {}
+
+ '@discordjs/collection@2.1.0': {}
+
+ '@discordjs/formatters@0.4.0':
+ dependencies:
+ discord-api-types: 0.37.83
+
+ '@discordjs/rest@2.3.0':
+ dependencies:
+ '@discordjs/collection': 2.1.0
+ '@discordjs/util': 1.1.0
+ '@sapphire/async-queue': 1.5.2
+ '@sapphire/snowflake': 3.5.3
+ '@vladfrangu/async_event_emitter': 2.2.4
+ discord-api-types: 0.37.83
+ magic-bytes.js: 1.10.0
+ tslib: 2.6.2
+ undici: 6.13.0
+
+ '@discordjs/util@1.1.0': {}
+
+ '@discordjs/ws@1.1.0':
+ dependencies:
+ '@discordjs/collection': 2.1.0
+ '@discordjs/rest': 2.3.0
+ '@discordjs/util': 1.1.0
+ '@sapphire/async-queue': 1.5.2
+ '@types/ws': 8.5.10
+ '@vladfrangu/async_event_emitter': 2.2.4
+ discord-api-types: 0.37.83
+ tslib: 2.6.2
+ ws: 8.17.0
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
+ '@exodus/schemasafe@1.3.0': {}
+
+ '@fastify/busboy@2.1.1': {}
+
+ '@google/generative-ai@0.11.3': {}
+
+ '@humanwhocodes/momoa@2.0.4': {}
+
+ '@iamtraction/google-translate@2.0.1':
+ dependencies:
+ undici: 5.28.4
+
+ '@jsdevtools/ono@7.1.3': {}
+
+ '@mapbox/node-pre-gyp@1.0.9':
+ dependencies:
+ detect-libc: 2.0.3
+ https-proxy-agent: 5.0.1
+ make-dir: 3.1.0
+ node-fetch: 2.7.0
+ nopt: 5.0.0
+ npmlog: 5.0.1
+ rimraf: 3.0.2
+ semver: 7.6.2
+ tar: 6.2.1
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.17.1
+
+ '@readme/better-ajv-errors@1.6.0(ajv@8.13.0)':
+ dependencies:
+ '@babel/code-frame': 7.24.2
+ '@babel/runtime': 7.24.5
+ '@humanwhocodes/momoa': 2.0.4
+ ajv: 8.13.0
+ chalk: 4.1.2
+ json-to-ast: 2.1.0
+ jsonpointer: 5.0.1
+ leven: 3.1.0
+
+ '@readme/data-urls@1.0.1': {}
+
+ '@readme/http-status-codes@7.2.0': {}
+
+ '@readme/json-schema-ref-parser@1.2.0':
+ dependencies:
+ '@jsdevtools/ono': 7.1.3
+ '@types/json-schema': 7.0.15
+ call-me-maybe: 1.0.2
+ js-yaml: 4.1.0
+
+ '@readme/oas-extensions@17.0.1(oas@20.10.3)':
+ dependencies:
+ oas: 20.10.3
+
+ '@readme/oas-to-har@20.1.1':
+ dependencies:
+ '@readme/data-urls': 1.0.1
+ '@readme/oas-extensions': 17.0.1(oas@20.10.3)
+ oas: 20.10.3
+ qs: 6.12.1
+ remove-undefined-objects: 2.0.2
+ transitivePeerDependencies:
+ - encoding
+
+ '@readme/openapi-parser@2.5.1(openapi-types@12.1.3)':
+ dependencies:
+ '@apidevtools/openapi-schemas': 2.1.0
+ '@apidevtools/swagger-methods': 3.0.2
+ '@jsdevtools/ono': 7.1.3
+ '@readme/better-ajv-errors': 1.6.0(ajv@8.13.0)
+ '@readme/json-schema-ref-parser': 1.2.0
+ ajv: 8.13.0
+ ajv-draft-04: 1.0.0(ajv@8.13.0)
+ call-me-maybe: 1.0.2
+ openapi-types: 12.1.3
+
+ '@readme/postman-to-openapi@4.1.0':
+ dependencies:
+ '@readme/http-status-codes': 7.2.0
+ js-yaml: 4.1.0
+ jsonc-parser: 3.2.0
+ lodash.camelcase: 4.3.0
+ marked: 4.3.0
+ mustache: 4.2.0
+
+ '@sapphire/async-queue@1.5.2': {}
+
+ '@sapphire/shapeshift@3.9.7':
+ dependencies:
+ fast-deep-equal: 3.1.3
+ lodash: 4.17.21
+
+ '@sapphire/snowflake@3.5.3': {}
+
+ '@tensorflow/tfjs-backend-cpu@4.19.0(@tensorflow/tfjs-core@4.19.0)':
+ dependencies:
+ '@tensorflow/tfjs-core': 4.19.0
+ '@types/seedrandom': 2.4.34
+ seedrandom: 3.0.5
+
+ '@tensorflow/tfjs-backend-webgl@4.19.0(@tensorflow/tfjs-core@4.19.0)':
+ dependencies:
+ '@tensorflow/tfjs-backend-cpu': 4.19.0(@tensorflow/tfjs-core@4.19.0)
+ '@tensorflow/tfjs-core': 4.19.0
+ '@types/offscreencanvas': 2019.3.0
+ '@types/seedrandom': 2.4.34
+ seedrandom: 3.0.5
+
+ '@tensorflow/tfjs-converter@4.19.0(@tensorflow/tfjs-core@4.19.0)':
+ dependencies:
+ '@tensorflow/tfjs-core': 4.19.0
+
+ '@tensorflow/tfjs-core@4.19.0':
+ dependencies:
+ '@types/long': 4.0.2
+ '@types/offscreencanvas': 2019.7.3
+ '@types/seedrandom': 2.4.34
+ '@webgpu/types': 0.1.38
+ long: 4.0.0
+ node-fetch: 2.6.13
+ seedrandom: 3.0.5
+ transitivePeerDependencies:
+ - encoding
+
+ '@tensorflow/tfjs-data@4.19.0(@tensorflow/tfjs-core@4.19.0)(seedrandom@3.0.5)':
+ dependencies:
+ '@tensorflow/tfjs-core': 4.19.0
+ '@types/node-fetch': 2.6.11
+ node-fetch: 2.6.13
+ seedrandom: 3.0.5
+ string_decoder: 1.3.0
+ transitivePeerDependencies:
+ - encoding
+
+ '@tensorflow/tfjs-layers@4.19.0(@tensorflow/tfjs-core@4.19.0)':
+ dependencies:
+ '@tensorflow/tfjs-core': 4.19.0
+
+ '@tensorflow/tfjs-node@4.19.0(seedrandom@3.0.5)':
+ dependencies:
+ '@mapbox/node-pre-gyp': 1.0.9
+ '@tensorflow/tfjs': 4.19.0(seedrandom@3.0.5)
+ adm-zip: 0.5.12
+ google-protobuf: 3.21.2
+ https-proxy-agent: 2.2.4
+ progress: 2.0.3
+ rimraf: 2.7.1
+ tar: 4.4.19
+ transitivePeerDependencies:
+ - encoding
+ - seedrandom
+ - supports-color
+
+ '@tensorflow/tfjs@4.19.0(seedrandom@3.0.5)':
+ dependencies:
+ '@tensorflow/tfjs-backend-cpu': 4.19.0(@tensorflow/tfjs-core@4.19.0)
+ '@tensorflow/tfjs-backend-webgl': 4.19.0(@tensorflow/tfjs-core@4.19.0)
+ '@tensorflow/tfjs-converter': 4.19.0(@tensorflow/tfjs-core@4.19.0)
+ '@tensorflow/tfjs-core': 4.19.0
+ '@tensorflow/tfjs-data': 4.19.0(@tensorflow/tfjs-core@4.19.0)(seedrandom@3.0.5)
+ '@tensorflow/tfjs-layers': 4.19.0(@tensorflow/tfjs-core@4.19.0)
+ argparse: 1.0.10
+ chalk: 4.1.2
+ core-js: 3.29.1
+ regenerator-runtime: 0.13.11
+ yargs: 16.2.0
+ transitivePeerDependencies:
+ - encoding
+ - seedrandom
+
+ '@ts-morph/common@0.18.1':
+ dependencies:
+ fast-glob: 3.3.2
+ minimatch: 5.1.6
+ mkdirp: 1.0.4
+ path-browserify: 1.0.1
+
+ '@types/har-format@1.2.15': {}
+
+ '@types/json-schema@7.0.15': {}
+
+ '@types/long@4.0.2': {}
+
+ '@types/node-fetch@2.6.11':
+ dependencies:
+ '@types/node': 20.12.12
+ form-data: 4.0.0
+
+ '@types/node@20.12.12':
+ dependencies:
+ undici-types: 5.26.5
+
+ '@types/offscreencanvas@2019.3.0': {}
+
+ '@types/offscreencanvas@2019.7.3': {}
+
+ '@types/seedrandom@2.4.34': {}
+
+ '@types/ws@8.5.10':
+ dependencies:
+ '@types/node': 20.12.12
+
+ '@vladfrangu/async_event_emitter@2.2.4': {}
+
+ '@webgpu/types@0.1.38': {}
+
+ abbrev@1.1.1: {}
+
+ adm-zip@0.5.12: {}
+
+ agent-base@4.3.0:
+ dependencies:
+ es6-promisify: 5.0.0
+
+ agent-base@6.0.2:
+ dependencies:
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+
+ ajv-draft-04@1.0.0(ajv@8.13.0):
+ optionalDependencies:
+ ajv: 8.13.0
+
+ ajv@8.13.0:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+ uri-js: 4.4.1
+
+ ansi-regex@5.0.1: {}
+
+ ansi-styles@3.2.1:
+ dependencies:
+ color-convert: 1.9.3
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ api@6.1.1(openapi-types@12.1.3):
+ dependencies:
+ '@readme/oas-to-har': 20.1.1
+ '@readme/openapi-parser': 2.5.1(openapi-types@12.1.3)
+ caseless: 0.12.0
+ chalk: 4.1.2
+ commander: 10.0.1
+ datauri: 4.1.0
+ execa: 5.1.1
+ fetch-har: 8.1.5
+ figures: 3.2.0
+ find-cache-dir: 3.3.2
+ form-data-encoder: 1.9.0
+ formdata-node: 4.4.1
+ get-stream: 6.0.1
+ isomorphic-fetch: 3.0.0
+ js-yaml: 4.1.0
+ json-schema-to-ts: 2.12.0
+ json-schema-traverse: 1.0.0
+ lodash.camelcase: 4.3.0
+ lodash.deburr: 4.1.0
+ lodash.merge: 4.6.2
+ lodash.setwith: 4.3.2
+ lodash.startcase: 4.4.0
+ make-dir: 3.1.0
+ node-abort-controller: 3.1.1
+ oas: 20.10.3
+ ora: 5.4.1
+ prompts: 2.4.2
+ remove-undefined-objects: 2.0.2
+ semver: 7.6.2
+ ssri: 10.0.6
+ ts-morph: 17.0.1
+ validate-npm-package-name: 5.0.1
+ transitivePeerDependencies:
+ - encoding
+ - openapi-types
+
+ aproba@2.0.0: {}
+
+ are-we-there-yet@2.0.0:
+ dependencies:
+ delegates: 1.0.0
+ readable-stream: 3.6.2
+
+ argparse@1.0.10:
+ dependencies:
+ sprintf-js: 1.0.3
+
+ argparse@2.0.1: {}
+
+ asynckit@0.4.0: {}
+
+ axios@1.6.8:
+ dependencies:
+ follow-redirects: 1.15.6
+ form-data: 4.0.0
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+
+ balanced-match@1.0.2: {}
+
+ base64-js@1.5.1: {}
+
+ better-sqlite3@10.0.0:
+ dependencies:
+ bindings: 1.5.0
+ prebuild-install: 7.1.2
+
+ bindings@1.5.0:
+ dependencies:
+ file-uri-to-path: 1.0.0
+
+ bl@4.1.0:
+ dependencies:
+ buffer: 5.7.1
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+
+ blessed@0.1.81: {}
+
+ brace-expansion@1.1.11:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
+ brace-expansion@2.0.1:
+ dependencies:
+ balanced-match: 1.0.2
+
+ braces@3.0.2:
+ dependencies:
+ fill-range: 7.0.1
+
+ buffer@5.7.1:
+ dependencies:
+ base64-js: 1.5.1
+ ieee754: 1.2.1
+
+ call-bind@1.0.7:
+ dependencies:
+ es-define-property: 1.0.0
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.4
+ set-function-length: 1.2.2
+
+ call-me-maybe@1.0.2: {}
+
+ caseless@0.12.0: {}
+
+ chalk@2.4.2:
+ dependencies:
+ ansi-styles: 3.2.1
+ escape-string-regexp: 1.0.5
+ supports-color: 5.5.0
+
+ chalk@4.1.2:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
+ chalk@5.3.0: {}
+
+ chownr@1.1.4: {}
+
+ chownr@2.0.0: {}
+
+ cli-cursor@3.1.0:
+ dependencies:
+ restore-cursor: 3.1.0
+
+ cli-spinners@2.9.2: {}
+
+ cliui@7.0.4:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
+ cliui@8.0.1:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
+ clone@1.0.4: {}
+
+ code-block-writer@11.0.3: {}
+
+ code-error-fragment@0.0.230: {}
+
+ color-convert@1.9.3:
+ dependencies:
+ color-name: 1.1.3
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.3: {}
+
+ color-name@1.1.4: {}
+
+ color-support@1.1.3: {}
+
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
+ commander@10.0.1: {}
+
+ commondir@1.0.1: {}
+
+ compute-gcd@1.2.1:
+ dependencies:
+ validate.io-array: 1.0.6
+ validate.io-function: 1.0.2
+ validate.io-integer-array: 1.0.0
+
+ compute-lcm@1.1.2:
+ dependencies:
+ compute-gcd: 1.2.1
+ validate.io-array: 1.0.6
+ validate.io-function: 1.0.2
+ validate.io-integer-array: 1.0.0
+
+ concat-map@0.0.1: {}
+
+ console-control-strings@1.1.0: {}
+
+ core-js@3.29.1: {}
+
+ cross-spawn@7.0.3:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ d@1.0.2:
+ dependencies:
+ es5-ext: 0.10.64
+ type: 2.7.2
+
+ datauri@4.1.0:
+ dependencies:
+ image-size: 1.0.0
+ mimer: 2.0.2
+
+ debug@3.2.7:
+ dependencies:
+ ms: 2.1.3
+
+ debug@4.3.4:
+ dependencies:
+ ms: 2.1.2
+
+ decompress-response@6.0.0:
+ dependencies:
+ mimic-response: 3.1.0
+
+ deep-extend@0.6.0: {}
+
+ defaults@1.0.4:
+ dependencies:
+ clone: 1.0.4
+
+ define-data-property@1.1.4:
+ dependencies:
+ es-define-property: 1.0.0
+ es-errors: 1.3.0
+ gopd: 1.0.1
+
+ delayed-stream@1.0.0: {}
+
+ delegates@1.0.0: {}
+
+ detect-libc@2.0.3: {}
+
+ discord-api-types@0.37.83: {}
+
+ discord-api-types@0.37.84: {}
+
+ discord.js@14.15.2:
+ dependencies:
+ '@discordjs/builders': 1.8.1
+ '@discordjs/collection': 1.5.3
+ '@discordjs/formatters': 0.4.0
+ '@discordjs/rest': 2.3.0
+ '@discordjs/util': 1.1.0
+ '@discordjs/ws': 1.1.0
+ '@sapphire/snowflake': 3.5.3
+ discord-api-types: 0.37.83
+ fast-deep-equal: 3.1.3
+ lodash.snakecase: 4.1.1
+ tslib: 2.6.2
+ undici: 6.13.0
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
+ emoji-regex@8.0.0: {}
+
+ end-of-stream@1.4.4:
+ dependencies:
+ once: 1.4.0
+
+ es-define-property@1.0.0:
+ dependencies:
+ get-intrinsic: 1.2.4
+
+ es-errors@1.3.0: {}
+
+ es5-ext@0.10.64:
+ dependencies:
+ es6-iterator: 2.0.3
+ es6-symbol: 3.1.4
+ esniff: 2.0.1
+ next-tick: 1.1.0
+
+ es6-iterator@2.0.3:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+ es6-symbol: 3.1.4
+
+ es6-promise@3.3.1: {}
+
+ es6-promise@4.2.8: {}
+
+ es6-promisify@5.0.0:
+ dependencies:
+ es6-promise: 4.2.8
+
+ es6-symbol@3.1.4:
+ dependencies:
+ d: 1.0.2
+ ext: 1.7.0
+
+ es6-weak-map@2.0.3:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+ es6-iterator: 2.0.3
+ es6-symbol: 3.1.4
+
+ escalade@3.1.2: {}
+
+ escape-string-regexp@1.0.5: {}
+
+ esniff@2.0.1:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+ event-emitter: 0.3.5
+ type: 2.7.2
+
+ event-emitter@0.3.5:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+
+ execa@5.1.1:
+ dependencies:
+ cross-spawn: 7.0.3
+ get-stream: 6.0.1
+ human-signals: 2.1.0
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+
+ expand-template@2.0.3: {}
+
+ ext@1.7.0:
+ dependencies:
+ type: 2.7.2
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-glob@3.3.2:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+
+ fast-safe-stringify@2.1.1: {}
+
+ fastq@1.17.1:
+ dependencies:
+ reusify: 1.0.4
+
+ fetch-har@8.1.5:
+ dependencies:
+ '@readme/data-urls': 1.0.1
+ '@types/har-format': 1.2.15
+ readable-stream: 3.6.2
+ optionalDependencies:
+ formdata-node: 4.4.1
+
+ figlet@1.7.0: {}
+
+ figures@3.2.0:
+ dependencies:
+ escape-string-regexp: 1.0.5
+
+ file-uri-to-path@1.0.0: {}
+
+ fill-range@7.0.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ find-cache-dir@3.3.2:
+ dependencies:
+ commondir: 1.0.1
+ make-dir: 3.1.0
+ pkg-dir: 4.2.0
+
+ find-up@4.1.0:
+ dependencies:
+ locate-path: 5.0.0
+ path-exists: 4.0.0
+
+ follow-redirects@1.15.6: {}
+
+ form-data-encoder@1.9.0: {}
+
+ form-data@4.0.0:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ mime-types: 2.1.35
+
+ formdata-node@4.4.1:
+ dependencies:
+ node-domexception: 1.0.0
+ web-streams-polyfill: 4.0.0-beta.3
+
+ fs-constants@1.0.0: {}
+
+ fs-minipass@1.2.7:
+ dependencies:
+ minipass: 2.9.0
+
+ fs-minipass@2.1.0:
+ dependencies:
+ minipass: 3.3.6
+
+ fs.realpath@1.0.0: {}
+
+ function-bind@1.1.2: {}
+
+ gauge@3.0.2:
+ dependencies:
+ aproba: 2.0.0
+ color-support: 1.1.3
+ console-control-strings: 1.1.0
+ has-unicode: 2.0.1
+ object-assign: 4.1.1
+ signal-exit: 3.0.7
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wide-align: 1.1.5
+
+ get-caller-file@2.0.5: {}
+
+ get-intrinsic@1.2.4:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ has-proto: 1.0.3
+ has-symbols: 1.0.3
+ hasown: 2.0.2
+
+ get-stream@6.0.1: {}
+
+ github-from-package@0.0.0: {}
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob@7.2.3:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+
+ google-protobuf@3.21.2: {}
+
+ gopd@1.0.1:
+ dependencies:
+ get-intrinsic: 1.2.4
+
+ grapheme-splitter@1.0.4: {}
+
+ has-flag@3.0.0: {}
+
+ has-flag@4.0.0: {}
+
+ has-property-descriptors@1.0.2:
+ dependencies:
+ es-define-property: 1.0.0
+
+ has-proto@1.0.3: {}
+
+ has-symbols@1.0.3: {}
+
+ has-unicode@2.0.1: {}
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ http2-client@1.3.5: {}
+
+ https-proxy-agent@2.2.4:
+ dependencies:
+ agent-base: 4.3.0
+ debug: 3.2.7
+ transitivePeerDependencies:
+ - supports-color
+
+ https-proxy-agent@5.0.1:
+ dependencies:
+ agent-base: 6.0.2
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+
+ human-signals@2.1.0: {}
+
+ ieee754@1.2.1: {}
+
+ image-size@1.0.0:
+ dependencies:
+ queue: 6.0.2
+
+ inflight@1.0.6:
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+
+ inherits@2.0.4: {}
+
+ ini@1.3.8: {}
+
+ is-extglob@2.1.1: {}
+
+ is-fullwidth-code-point@3.0.0: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-interactive@1.0.0: {}
+
+ is-number@7.0.0: {}
+
+ is-promise@2.2.2: {}
+
+ is-stream@2.0.1: {}
+
+ is-unicode-supported@0.1.0: {}
+
+ isexe@2.0.0: {}
+
+ isomorphic-fetch@3.0.0:
+ dependencies:
+ node-fetch: 2.7.0
+ whatwg-fetch: 3.6.20
+ transitivePeerDependencies:
+ - encoding
+
+ js-tokens@4.0.0: {}
+
+ js-yaml@4.1.0:
+ dependencies:
+ argparse: 2.0.1
+
+ json-schema-compare@0.2.2:
+ dependencies:
+ lodash: 4.17.21
+
+ json-schema-merge-allof@0.8.1:
+ dependencies:
+ compute-lcm: 1.1.2
+ json-schema-compare: 0.2.2
+ lodash: 4.17.21
+
+ json-schema-to-ts@2.12.0:
+ dependencies:
+ '@babel/runtime': 7.24.5
+ '@types/json-schema': 7.0.15
+ ts-algebra: 1.2.2
+
+ json-schema-traverse@1.0.0: {}
+
+ json-to-ast@2.1.0:
+ dependencies:
+ code-error-fragment: 0.0.230
+ grapheme-splitter: 1.0.4
+
+ jsonc-parser@3.2.0: {}
+
+ jsonpath-plus@7.2.0: {}
+
+ jsonpointer@5.0.1: {}
+
+ kleur@3.0.3: {}
+
+ leven@3.1.0: {}
+
+ locate-path@5.0.0:
+ dependencies:
+ p-locate: 4.1.0
+
+ lodash.camelcase@4.3.0: {}
+
+ lodash.deburr@4.1.0: {}
+
+ lodash.merge@4.6.2: {}
+
+ lodash.setwith@4.3.2: {}
+
+ lodash.snakecase@4.1.1: {}
+
+ lodash.startcase@4.4.0: {}
+
+ lodash@4.17.21: {}
+
+ log-symbols@4.1.0:
+ dependencies:
+ chalk: 4.1.2
+ is-unicode-supported: 0.1.0
+
+ long@4.0.0: {}
+
+ lru-queue@0.1.0:
+ dependencies:
+ es5-ext: 0.10.64
+
+ magic-bytes.js@1.10.0: {}
+
+ make-dir@3.1.0:
+ dependencies:
+ semver: 6.3.1
+
+ marked@4.3.0: {}
+
+ memoizee@0.4.15:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+ es6-weak-map: 2.0.3
+ event-emitter: 0.3.5
+ is-promise: 2.2.2
+ lru-queue: 0.1.0
+ next-tick: 1.1.0
+ timers-ext: 0.1.7
+
+ merge-stream@2.0.0: {}
+
+ merge2@1.4.1: {}
+
+ micromatch@4.0.5:
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ mimer@2.0.2: {}
+
+ mimic-fn@2.1.0: {}
+
+ mimic-response@3.1.0: {}
+
+ minimatch@3.1.2:
+ dependencies:
+ brace-expansion: 1.1.11
+
+ minimatch@5.1.6:
+ dependencies:
+ brace-expansion: 2.0.1
+
+ minimist@1.2.8: {}
+
+ minipass@2.9.0:
+ dependencies:
+ safe-buffer: 5.2.1
+ yallist: 3.1.1
+
+ minipass@3.3.6:
+ dependencies:
+ yallist: 4.0.0
+
+ minipass@5.0.0: {}
+
+ minipass@7.1.1: {}
+
+ minizlib@1.3.3:
+ dependencies:
+ minipass: 2.9.0
+
+ minizlib@2.1.2:
+ dependencies:
+ minipass: 3.3.6
+ yallist: 4.0.0
+
+ mkdirp-classic@0.5.3: {}
+
+ mkdirp@0.5.6:
+ dependencies:
+ minimist: 1.2.8
+
+ mkdirp@1.0.4: {}
+
+ moment@2.30.1: {}
+
+ ms@2.1.2: {}
+
+ ms@2.1.3: {}
+
+ mustache@4.2.0: {}
+
+ napi-build-utils@1.0.2: {}
+
+ next-tick@1.1.0: {}
+
+ node-abi@3.62.0:
+ dependencies:
+ semver: 7.6.2
+
+ node-abort-controller@3.1.1: {}
+
+ node-domexception@1.0.0: {}
+
+ node-fetch-h2@2.3.0:
+ dependencies:
+ http2-client: 1.3.5
+
+ node-fetch@2.6.13:
+ dependencies:
+ whatwg-url: 5.0.0
+
+ node-fetch@2.7.0:
+ dependencies:
+ whatwg-url: 5.0.0
+
+ node-readfiles@0.2.0:
+ dependencies:
+ es6-promise: 3.3.1
+
+ nopt@5.0.0:
+ dependencies:
+ abbrev: 1.1.1
+
+ npm-run-path@4.0.1:
+ dependencies:
+ path-key: 3.1.1
+
+ npmlog@5.0.1:
+ dependencies:
+ are-we-there-yet: 2.0.0
+ console-control-strings: 1.1.0
+ gauge: 3.0.2
+ set-blocking: 2.0.0
+
+ nsfwjs@4.1.0(@tensorflow/tfjs@4.19.0(seedrandom@3.0.5)):
+ dependencies:
+ '@tensorflow/tfjs': 4.19.0(seedrandom@3.0.5)
+
+ oas-kit-common@1.0.8:
+ dependencies:
+ fast-safe-stringify: 2.1.1
+
+ oas-linter@3.2.2:
+ dependencies:
+ '@exodus/schemasafe': 1.3.0
+ should: 13.2.3
+ yaml: 1.10.2
+
+ oas-normalize@8.4.1:
+ dependencies:
+ '@readme/openapi-parser': 2.5.1(openapi-types@12.1.3)
+ '@readme/postman-to-openapi': 4.1.0
+ js-yaml: 4.1.0
+ node-fetch: 2.7.0
+ openapi-types: 12.1.3
+ swagger2openapi: 7.0.8
+ transitivePeerDependencies:
+ - encoding
+
+ oas-resolver@2.5.6:
+ dependencies:
+ node-fetch-h2: 2.3.0
+ oas-kit-common: 1.0.8
+ reftools: 1.1.9
+ yaml: 1.10.2
+ yargs: 17.7.2
+
+ oas-schema-walker@1.1.5: {}
+
+ oas-validator@5.0.8:
+ dependencies:
+ call-me-maybe: 1.0.2
+ oas-kit-common: 1.0.8
+ oas-linter: 3.2.2
+ oas-resolver: 2.5.6
+ oas-schema-walker: 1.1.5
+ reftools: 1.1.9
+ should: 13.2.3
+ yaml: 1.10.2
+
+ oas@20.10.3:
+ dependencies:
+ '@readme/json-schema-ref-parser': 1.2.0
+ '@types/json-schema': 7.0.15
+ json-schema-merge-allof: 0.8.1
+ jsonpath-plus: 7.2.0
+ jsonpointer: 5.0.1
+ memoizee: 0.4.15
+ oas-normalize: 8.4.1
+ openapi-types: 12.1.3
+ path-to-regexp: 6.2.2
+ remove-undefined-objects: 3.0.0
+ transitivePeerDependencies:
+ - encoding
+
+ object-assign@4.1.1: {}
+
+ object-inspect@1.13.1: {}
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ onetime@5.1.2:
+ dependencies:
+ mimic-fn: 2.1.0
+
+ openapi-types@12.1.3: {}
+
+ ora@5.4.1:
+ dependencies:
+ bl: 4.1.0
+ chalk: 4.1.2
+ cli-cursor: 3.1.0
+ cli-spinners: 2.9.2
+ is-interactive: 1.0.0
+ is-unicode-supported: 0.1.0
+ log-symbols: 4.1.0
+ strip-ansi: 6.0.1
+ wcwidth: 1.0.1
+
+ os@0.1.2: {}
+
+ p-limit@2.3.0:
+ dependencies:
+ p-try: 2.2.0
+
+ p-locate@4.1.0:
+ dependencies:
+ p-limit: 2.3.0
+
+ p-try@2.2.0: {}
+
+ path-browserify@1.0.1: {}
+
+ path-exists@4.0.0: {}
+
+ path-is-absolute@1.0.1: {}
+
+ path-key@3.1.1: {}
+
+ path-to-regexp@6.2.2: {}
+
+ picocolors@1.0.1: {}
+
+ picomatch@2.3.1: {}
+
+ pkg-dir@4.2.0:
+ dependencies:
+ find-up: 4.1.0
+
+ prebuild-install@7.1.2:
+ dependencies:
+ detect-libc: 2.0.3
+ expand-template: 2.0.3
+ github-from-package: 0.0.0
+ minimist: 1.2.8
+ mkdirp-classic: 0.5.3
+ napi-build-utils: 1.0.2
+ node-abi: 3.62.0
+ pump: 3.0.0
+ rc: 1.2.8
+ simple-get: 4.0.1
+ tar-fs: 2.1.1
+ tunnel-agent: 0.6.0
+
+ prettier@3.2.5: {}
+
+ progress@2.0.3: {}
+
+ prompts@2.4.2:
+ dependencies:
+ kleur: 3.0.3
+ sisteransi: 1.0.5
+
+ proxy-from-env@1.1.0: {}
+
+ pump@3.0.0:
+ dependencies:
+ end-of-stream: 1.4.4
+ once: 1.4.0
+
+ punycode@2.3.1: {}
+
+ qs@6.12.1:
+ dependencies:
+ side-channel: 1.0.6
+
+ queue-microtask@1.2.3: {}
+
+ queue@6.0.2:
+ dependencies:
+ inherits: 2.0.4
+
+ quick.db@9.1.7:
+ dependencies:
+ lodash: 4.17.21
+
+ rc@1.2.8:
+ dependencies:
+ deep-extend: 0.6.0
+ ini: 1.3.8
+ minimist: 1.2.8
+ strip-json-comments: 2.0.1
+
+ readable-stream@3.6.2:
+ dependencies:
+ inherits: 2.0.4
+ string_decoder: 1.3.0
+ util-deprecate: 1.0.2
+
+ reftools@1.1.9: {}
+
+ regenerator-runtime@0.13.11: {}
+
+ regenerator-runtime@0.14.1: {}
+
+ remove-undefined-objects@2.0.2: {}
+
+ remove-undefined-objects@3.0.0: {}
+
+ require-directory@2.1.1: {}
+
+ require-from-string@2.0.2: {}
+
+ restore-cursor@3.1.0:
+ dependencies:
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+
+ reusify@1.0.4: {}
+
+ rimraf@2.7.1:
+ dependencies:
+ glob: 7.2.3
+
+ rimraf@3.0.2:
+ dependencies:
+ glob: 7.2.3
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ safe-buffer@5.2.1: {}
+
+ seedrandom@3.0.5: {}
+
+ semver@6.3.1: {}
+
+ semver@7.6.2: {}
+
+ set-blocking@2.0.0: {}
+
+ set-function-length@1.2.2:
+ dependencies:
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.4
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.2
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ should-equal@2.0.0:
+ dependencies:
+ should-type: 1.4.0
+
+ should-format@3.0.3:
+ dependencies:
+ should-type: 1.4.0
+ should-type-adaptors: 1.1.0
+
+ should-type-adaptors@1.1.0:
+ dependencies:
+ should-type: 1.4.0
+ should-util: 1.0.1
+
+ should-type@1.4.0: {}
+
+ should-util@1.0.1: {}
+
+ should@13.2.3:
+ dependencies:
+ should-equal: 2.0.0
+ should-format: 3.0.3
+ should-type: 1.4.0
+ should-type-adaptors: 1.1.0
+ should-util: 1.0.1
+
+ side-channel@1.0.6:
+ dependencies:
+ call-bind: 1.0.7
+ es-errors: 1.3.0
+ get-intrinsic: 1.2.4
+ object-inspect: 1.13.1
+
+ signal-exit@3.0.7: {}
+
+ simple-concat@1.0.1: {}
+
+ simple-get@4.0.1:
+ dependencies:
+ decompress-response: 6.0.0
+ once: 1.4.0
+ simple-concat: 1.0.1
+
+ sisteransi@1.0.5: {}
+
+ sprintf-js@1.0.3: {}
+
+ ssri@10.0.6:
+ dependencies:
+ minipass: 7.1.1
+
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ string_decoder@1.3.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
+ strip-final-newline@2.0.0: {}
+
+ strip-json-comments@2.0.1: {}
+
+ supports-color@5.5.0:
+ dependencies:
+ has-flag: 3.0.0
+
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
+ swagger2openapi@7.0.8:
+ dependencies:
+ call-me-maybe: 1.0.2
+ node-fetch: 2.7.0
+ node-fetch-h2: 2.3.0
+ node-readfiles: 0.2.0
+ oas-kit-common: 1.0.8
+ oas-resolver: 2.5.6
+ oas-schema-walker: 1.1.5
+ oas-validator: 5.0.8
+ reftools: 1.1.9
+ yaml: 1.10.2
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - encoding
+
+ tar-fs@2.1.1:
+ dependencies:
+ chownr: 1.1.4
+ mkdirp-classic: 0.5.3
+ pump: 3.0.0
+ tar-stream: 2.2.0
+
+ tar-stream@2.2.0:
+ dependencies:
+ bl: 4.1.0
+ end-of-stream: 1.4.4
+ fs-constants: 1.0.0
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+
+ tar@4.4.19:
+ dependencies:
+ chownr: 1.1.4
+ fs-minipass: 1.2.7
+ minipass: 2.9.0
+ minizlib: 1.3.3
+ mkdirp: 0.5.6
+ safe-buffer: 5.2.1
+ yallist: 3.1.1
+
+ tar@6.2.1:
+ dependencies:
+ chownr: 2.0.0
+ fs-minipass: 2.1.0
+ minipass: 5.0.0
+ minizlib: 2.1.2
+ mkdirp: 1.0.4
+ yallist: 4.0.0
+
+ timers-ext@0.1.7:
+ dependencies:
+ es5-ext: 0.10.64
+ next-tick: 1.1.0
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ tr46@0.0.3: {}
+
+ ts-algebra@1.2.2: {}
+
+ ts-mixer@6.0.4: {}
+
+ ts-morph@17.0.1:
+ dependencies:
+ '@ts-morph/common': 0.18.1
+ code-block-writer: 11.0.3
+
+ tslib@2.6.2: {}
+
+ tunnel-agent@0.6.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ type@2.7.2: {}
+
+ undici-types@5.26.5: {}
+
+ undici@5.28.4:
+ dependencies:
+ '@fastify/busboy': 2.1.1
+
+ undici@6.13.0: {}
+
+ uri-js@4.4.1:
+ dependencies:
+ punycode: 2.3.1
+
+ util-deprecate@1.0.2: {}
+
+ validate-npm-package-name@5.0.1: {}
+
+ validate.io-array@1.0.6: {}
+
+ validate.io-function@1.0.2: {}
+
+ validate.io-integer-array@1.0.0:
+ dependencies:
+ validate.io-array: 1.0.6
+ validate.io-integer: 1.0.5
+
+ validate.io-integer@1.0.5:
+ dependencies:
+ validate.io-number: 1.0.3
+
+ validate.io-number@1.0.3: {}
+
+ wcwidth@1.0.1:
+ dependencies:
+ defaults: 1.0.4
+
+ web-streams-polyfill@4.0.0-beta.3: {}
+
+ webidl-conversions@3.0.1: {}
+
+ whatwg-fetch@3.6.20: {}
+
+ whatwg-url@5.0.0:
+ dependencies:
+ tr46: 0.0.3
+ webidl-conversions: 3.0.1
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ wide-align@1.1.5:
+ dependencies:
+ string-width: 4.2.3
+
+ wrap-ansi@7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrappy@1.0.2: {}
+
+ ws@8.17.0: {}
+
+ y18n@5.0.8: {}
+
+ yallist@3.1.1: {}
+
+ yallist@4.0.0: {}
+
+ yaml@1.10.2: {}
+
+ yargs-parser@20.2.9: {}
+
+ yargs-parser@21.1.1: {}
+
+ yargs@16.2.0:
+ dependencies:
+ cliui: 7.0.4
+ escalade: 3.1.2
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 20.2.9
+
+ yargs@17.7.2:
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.1.2
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
diff --git a/start.mjs b/start.mjs
index bb06e74..4c364af 100644
--- a/start.mjs
+++ b/start.mjs
@@ -8,7 +8,7 @@ import figlet from "figlet";
// Create a screen object.
const screen = blessed.screen({
smartCSR: true,
- title: "Taurus Bot Console"
+ title: "Taurus Bot Console",
});
// Create a box that fills the entire screen.
@@ -20,15 +20,15 @@ const box = blessed.box({
content: "",
tags: true,
border: {
- type: "line"
+ type: "line",
},
style: {
fg: "white",
bg: "black",
border: {
- fg: "#ff0000" // Red
- }
- }
+ fg: "#ff0000", // Red
+ },
+ },
});
// Create a console box at the top right.
@@ -40,15 +40,15 @@ const consoleBox = blessed.box({
content: "{underline}Taurus Console{/underline}",
tags: true,
border: {
- type: "line"
+ type: "line",
},
style: {
fg: "white",
bg: "black",
border: {
- fg: "#ff0000" // Red
- }
- }
+ fg: "#ff0000", // Red
+ },
+ },
});
// Append our boxes to the screen.
@@ -62,13 +62,15 @@ let botStatus = "Offline";
// Function to start the Discord bot.
function startBot() {
if (bot) {
- writeToConsole(chalk.red("Bot is already running. Please stop the bot first."));
+ writeToConsole(
+ chalk.red("Bot is already running. Please stop the bot first."),
+ );
return;
}
// Modify this line to start your bot with the correct command and arguments
bot = spawn("node", ["bot.js"], {
- stdio: ["pipe", "pipe", "pipe", "pipe", "pipe", "pipe", process.stderr]
+ stdio: ["pipe", "pipe", "pipe", "pipe", "pipe", "pipe", process.stderr],
});
botStartTime = moment();
@@ -93,7 +95,9 @@ function startBot() {
// Function to stop the Discord bot.
function stopBot() {
if (!bot) {
- writeToConsole(chalk.red("Bot is not running. Please start the bot first."));
+ writeToConsole(
+ chalk.red("Bot is not running. Please start the bot first."),
+ );
return;
}
@@ -111,24 +115,43 @@ function stopBot() {
// Function to restart the Discord bot.
function restartBot() {
- stopBot();
- const gitPull = spawn('git', ['pull']);
-
- gitPull.stdout.on('data', (data) => {
- writeToConsole(chalk.italic(`[GIT] stdout: ${data}`));
- });
-
- gitPull.stderr.on('data', (data) => {
- writeToConsole(chalk.italic(`[GIT] stderr: ${data}`));
- });
-
- gitPull.on('close', (code) => {
- writeToConsole(chalk.italic(`[GIT] child process exited with code ${code}`));
- setTimeout(() => {
- startBot();
- writeToConsole(chalk.red("Bot restarted."));
- }, 1000);
- });
+ stopBot();
+ const gitPull = spawn("git", ["pull"]);
+
+ gitPull.stdout.on("data", (data) => {
+ writeToConsole(chalk.italic(`[GIT] stdout: ${data}`));
+ });
+
+ gitPull.stderr.on("data", (data) => {
+ writeToConsole(chalk.italic(`[GIT] stderr: ${data}`));
+ });
+
+ gitPull.on("close", (code) => {
+ writeToConsole(
+ chalk.italic(`[GIT] child process exited with code ${code}`),
+ );
+
+ const pnpmInstall = spawn("pnpm", ["install"], { shell: true });
+
+ pnpmInstall.stdout.on("data", (data) => {
+ const message = data.toString().trim();
+ message && writeToConsole(chalk.italic(`[PNPM] stdout: ${message}`));
+ });
+
+ pnpmInstall.stderr.on("data", (data) => {
+ writeToConsole(chalk.italic(`[PNPM] stderr: ${data}`));
+ });
+
+ pnpmInstall.on("close", (code) => {
+ writeToConsole(
+ chalk.italic(`[PNPM] child process exited with code ${code}`),
+ );
+ setTimeout(() => {
+ startBot();
+ writeToConsole(chalk.red("Bot restarted."));
+ }, 1000);
+ });
+ });
}
// Function to refresh the console.
@@ -139,20 +162,24 @@ function refreshConsole() {
}
let title = "";
-figlet.text("Taurus", {
- font: "Standard",
- horizontalLayout: "default",
- verticalLayout: "default",
- width: 100,
- whitespaceBreak: true
-}, function(err, data) {
- if (err) {
- console.log("Something went wrong...");
- console.dir(err);
- return;
- }
- title = chalk.red(data); // Red
-});
+figlet.text(
+ "Taurus",
+ {
+ font: "Standard",
+ horizontalLayout: "default",
+ verticalLayout: "default",
+ width: 100,
+ whitespaceBreak: true,
+ },
+ function (err, data) {
+ if (err) {
+ console.log("Something went wrong...");
+ console.dir(err);
+ return;
+ }
+ title = chalk.red(data); // Red
+ },
+);
// Function to update the box content with system and bot stats
function updateStats() {
@@ -162,25 +189,27 @@ function updateStats() {
const cpuCores = os.cpus().length.toString();
const osInfo = `${os.type()} (${os.release()})`;
- const botUptime = botStartTime ? moment.duration(moment().diff(botStartTime)).humanize() : "Not available";
- const botMemoryUsage = (process.memoryUsage().heapUsed / 1024 / 1024 / 1024).toFixed(2) + " GB";
-
- box.setContent(`${title}\n\n` +
- `${chalk.red("Bot Status:")} ${botStatus === "Online" ? chalk.green(botStatus) : chalk.red(botStatus)}\n\n` +
- `${chalk.red("VPS Uptime:")} ${chalk.white(serverUptime)}\n` +
- `${chalk.red("Total Memory:")} ${chalk.white(totalMemory)}\n` +
- `${chalk.red("Bot Uptime:")} ${chalk.white(botUptime)}\n` +
- `${chalk.red("Bot Memory Usage:")} ${chalk.white(botMemoryUsage)}\n` +
- `${chalk.red("CPU Threads:")} ${chalk.white(cpuCores)}\n` +
- `${chalk.red("OS Info:")} ${chalk.white(osInfo)}\n\n` +
- `${chalk.red("Commands:")}\n` +
-
- `${chalk.green("S")} - ${chalk.white("Start Bot")}\n` +
- `${chalk.green("X")} - ${chalk.white("Stop Bot")}\n` +
- `${chalk.green("R")} - ${chalk.white("Restart & Update Bot")}\n` +
- `${chalk.green("L")} - ${chalk.white("Refresh Console")}\n\n` +
-
- `${chalk.red("Press")} ${chalk.white("Ctrl+C")} ${chalk.red("to stop the bot and exit.")}\n\n\n`
+ const botUptime = botStartTime
+ ? moment.duration(moment().diff(botStartTime)).humanize()
+ : "Not available";
+ const botMemoryUsage =
+ (process.memoryUsage().heapUsed / 1024 / 1024 / 1024).toFixed(2) + " GB";
+
+ box.setContent(
+ `${title}\n\n` +
+ `${chalk.red("Bot Status:")} ${botStatus === "Online" ? chalk.green(botStatus) : chalk.red(botStatus)}\n\n` +
+ `${chalk.red("VPS Uptime:")} ${chalk.white(serverUptime)}\n` +
+ `${chalk.red("Total Memory:")} ${chalk.white(totalMemory)}\n` +
+ `${chalk.red("Bot Uptime:")} ${chalk.white(botUptime)}\n` +
+ `${chalk.red("Bot Memory Usage:")} ${chalk.white(botMemoryUsage)}\n` +
+ `${chalk.red("CPU Threads:")} ${chalk.white(cpuCores)}\n` +
+ `${chalk.red("OS Info:")} ${chalk.white(osInfo)}\n\n` +
+ `${chalk.red("Commands:")}\n` +
+ `${chalk.green("S")} - ${chalk.white("Start Bot")}\n` +
+ `${chalk.green("X")} - ${chalk.white("Stop Bot")}\n` +
+ `${chalk.green("R")} - ${chalk.white("Restart & Update Bot")}\n` +
+ `${chalk.green("L")} - ${chalk.white("Refresh Console")}\n\n` +
+ `${chalk.red("Press")} ${chalk.white("Ctrl+C")} ${chalk.red("to stop the bot and exit.")}\n\n\n`,
);
screen.render();
}
@@ -208,7 +237,6 @@ process.on("SIGINT", () => {
// Start the bot when script is run initially.
startBot();
-
// Listen for keystrokes and map them to commands.
screen.key(["S", "s"], () => {
startBot();
@@ -226,9 +254,9 @@ screen.key(["L", "l"], () => {
refreshConsole();
});
-screen.key(["escape", "q", "C-c"], function(ch, key) {
+screen.key(["escape", "q", "C-c"], function (ch, key) {
return process.exit(0);
});
// Render the screen.
-screen.render();
\ No newline at end of file
+screen.render();
diff --git a/startbot.bat b/startbot.bat
index 4ce816c..8ff2226 100644
--- a/startbot.bat
+++ b/startbot.bat
@@ -1,7 +1,8 @@
@echo off
set "SCRIPT_DIR=%~dp0"
cd "%SCRIPT_DIR%"
-call npm install
+call npm install -g pnpm
+call pnpm install
pause
node start.mjs
pause
\ No newline at end of file
diff --git a/startbot.sh b/startbot.sh
index 4cf9cfe..858f855 100644
--- a/startbot.sh
+++ b/startbot.sh
@@ -1,5 +1,6 @@
SCRIPT_DIR="$( cd "$(dirname "$0")" ; pwd -P )"
cd "$SCRIPT_DIR"
-npm install
+npm install -g pnpm
+pnpm install
node start.mjs
read -p "Press Enter to exit"
\ No newline at end of file
diff --git a/typings.d.ts b/typings.d.ts
index 85c0395..4d18b5d 100644
--- a/typings.d.ts
+++ b/typings.d.ts
@@ -56,7 +56,7 @@ export interface LegacyCommand {
*/
execute(
message: Discord.Message & { client: Client },
- args: string[]
+ args: string[],
): void | Promise;
}
@@ -84,7 +84,7 @@ export interface SlashInteractionCommand {
* @param interaction The interaction that triggered this command.
*/
execute(
- interaction: Discord.ChatInputCommandInteraction & { client: Client }
+ interaction: Discord.ChatInputCommandInteraction & { client: Client },
): void | Promise;
}
@@ -102,7 +102,7 @@ export interface ButtonInteractionCommand {
* @param interaction The interaction that triggered this command.
*/
execute(
- interaction: Discord.ButtonInteraction & { client: Client }
+ interaction: Discord.ButtonInteraction & { client: Client },
): void | Promise;
}
@@ -120,7 +120,7 @@ export interface SelectInteractionCommand {
* @param interaction The interaction that triggered this command.
*/
execute(
- interaction: Discord.SelectMenuInteraction & { client: Client }
+ interaction: Discord.SelectMenuInteraction & { client: Client },
): void | Promise;
}
@@ -155,7 +155,7 @@ export interface ContextInteractionCommand {
* @param interaction The interaction that triggered this command.
*/
execute(
- interaction: Discord.ContextMenuCommandInteraction & { client: Client }
+ interaction: Discord.ContextMenuCommandInteraction & { client: Client },
): void | Promise;
}
@@ -173,7 +173,7 @@ export interface ModalInteractionCommand {
* @param interaction The interaction that triggered this command.
*/
execute(
- interaction: Discord.ModalSubmitInteraction & { client: Client }
+ interaction: Discord.ModalSubmitInteraction & { client: Client },
): void | Promise;
}
@@ -192,7 +192,7 @@ export interface TriggerCommand {
*/
execute(
message: Discord.Message & { client: Client },
- args: string[]
+ args: string[],
): void | Promise;
}
@@ -210,7 +210,7 @@ export interface AutocompleteInteraction {
* @param interaction The interaction that triggered this command.
*/
execute(
- interaction: Discord.AutocompleteInteraction & { client: Client }
+ interaction: Discord.AutocompleteInteraction & { client: Client },
): void | Promise;
}