From 29c6cb9c4a96506ac5b1626e87c22672fa82ea82 Mon Sep 17 00:00:00 2001 From: Shane C Date: Tue, 2 Jul 2024 10:20:16 -0400 Subject: [PATCH] initial commit --- .gitignore | 3 + README.md | 10 + bun.lockb | Bin 0 -> 58802 bytes commands/misc/ping.ts | 37 + config.example.yml | 1 + discordjs.d.ts | 14 + dist/commands/misc/ping.js | 25 + dist/events/interactionCreate.js | 23 + dist/events/ready.js | 18 + dist/handlers/loaders/command.js | 42 + dist/handlers/loaders/event.js | 31 + dist/handlers/loaders/interactions.js | 31 + dist/index.js | 85 ++ dist/types.js | 28 + dist/utils/context.js | 8 + eslint.config.mjs | 106 ++ events/interactionCreate.ts | 33 + events/ready.ts | 27 + handlers/loaders/command.ts | 70 ++ handlers/loaders/event.ts | 46 + handlers/loaders/interactions.ts | 53 + index.ts | 124 +++ package.json | 30 + pnpm-lock.yaml | 1308 +++++++++++++++++++++++++ prisma/schema.prisma | 14 + tsconfig.json | 37 + types.ts | 59 ++ utils/context.ts | 14 + 28 files changed, 2277 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 bun.lockb create mode 100644 commands/misc/ping.ts create mode 100644 config.example.yml create mode 100644 discordjs.d.ts create mode 100644 dist/commands/misc/ping.js create mode 100644 dist/events/interactionCreate.js create mode 100644 dist/events/ready.js create mode 100644 dist/handlers/loaders/command.js create mode 100644 dist/handlers/loaders/event.js create mode 100644 dist/handlers/loaders/interactions.js create mode 100644 dist/index.js create mode 100644 dist/types.js create mode 100644 dist/utils/context.js create mode 100644 eslint.config.mjs create mode 100644 events/interactionCreate.ts create mode 100644 events/ready.ts create mode 100644 handlers/loaders/command.ts create mode 100644 handlers/loaders/event.ts create mode 100644 handlers/loaders/interactions.ts create mode 100644 index.ts create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 prisma/schema.prisma create mode 100644 tsconfig.json create mode 100644 types.ts create mode 100644 utils/context.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..11ddd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +# Keep environment variables out of version control +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..5bb7d9b --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Discord.JS v14 Typescript Template + +This is a Discord.JS v14 bot template using TypeScript, this version includes the Prisma ORM. + +## Features + - Command Handler + - Event Handler + - Interaction Handler + - Contexts + - Bun supported \ No newline at end of file diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..e89275edb502b1f14361049452b2c44e6c5407dc GIT binary patch literal 58802 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 \ No newline at end of file diff --git a/discordjs.d.ts b/discordjs.d.ts new file mode 100644 index 0000000..f8fb90f --- /dev/null +++ b/discordjs.d.ts @@ -0,0 +1,14 @@ +import type { Command, Interaction as InteractionHandler } from './types.ts'; +import type { PrismaClient } from '@prisma/client'; + +declare module 'discord.js' { + interface Client { + commands: Map; + interactionHandlers: Map; + commandDir: string; + db: PrismaClient; + + contexts: Map; + getContext(contextName: string): Map; + } +} \ No newline at end of file diff --git a/dist/commands/misc/ping.js b/dist/commands/misc/ping.js new file mode 100644 index 0000000..5ffbed5 --- /dev/null +++ b/dist/commands/misc/ping.js @@ -0,0 +1,25 @@ +import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; +import { Command } from '../../types.js'; +export default class PingCommand extends Command { + constructor() { + super(new SlashCommandBuilder() + .setName('ping') + .setDescription('Current latency of bot.') + .setDMPermission(false)); + } + async execute(interaction) { + const pingEmbed = new EmbedBuilder() + .addFields({ + name: 'REST Latency:', + value: `${Math.round(Date.now() - interaction.createdTimestamp)}ms`, + inline: true, + }, { + name: 'WS Latency:', + value: `${Math.round(this.client.ws.ping)}ms`, + inline: true, + }) + .setTimestamp() + .setColor('Green'); + await interaction.reply({ embeds: [pingEmbed] }); + } +} diff --git a/dist/events/interactionCreate.js b/dist/events/interactionCreate.js new file mode 100644 index 0000000..710f061 --- /dev/null +++ b/dist/events/interactionCreate.js @@ -0,0 +1,23 @@ +import { Event } from '../types.js'; +import { Events } from 'discord.js'; +export default class InteractionCreateEvent extends Event { + constructor() { + super(Events.InteractionCreate, false); + } + async execute(interaction) { + if (interaction.isMessageComponent() || interaction.isModalSubmit()) { + const interactionHandler = this.client.interactionHandlers.get(interaction.customId); + if (!interactionHandler) + return; + interactionHandler.client = this.client; + await interactionHandler.execute(interaction); + } + if (!interaction.isChatInputCommand()) + return; + const command = this.client.commands?.get(interaction.commandName); + if (!command) + return; + command.client = this.client; + await command.execute(interaction); + } +} diff --git a/dist/events/ready.js b/dist/events/ready.js new file mode 100644 index 0000000..4b5b4a6 --- /dev/null +++ b/dist/events/ready.js @@ -0,0 +1,18 @@ +import { ActivityType, Events } from 'discord.js'; +import { Event } from '../types.js'; +import { loadCommands } from '../handlers/loaders/command.js'; +export default class ReadyEvent extends Event { + constructor() { + super(Events.ClientReady, true); + } + async execute(_client) { + this.client.user?.setActivity({ + type: ActivityType.Custom, + state: 'Creating bugs...', + name: 'hello', + }); + this.client.user?.setStatus('dnd'); + this.client.commands = await loadCommands(this.client); + console.log(`Logged in as ${this.client.user?.tag}`); + } +} diff --git a/dist/handlers/loaders/command.js b/dist/handlers/loaders/command.js new file mode 100644 index 0000000..f4a5cfe --- /dev/null +++ b/dist/handlers/loaders/command.js @@ -0,0 +1,42 @@ +import { readdirSync, statSync } from 'node:fs'; +import path from 'node:path'; +import { Routes } from 'discord.js'; +export async function loadCommands(client) { + const currentAppCommands = await client.rest.get(Routes.applicationCommands(client.application.id)); + const commandMap = new Map(); + const baseCmdDir = readdirSync(client.commandDir); + for (const baseCmdDirFile of baseCmdDir) { + const combinedDirs = path.join(client.commandDir, baseCmdDirFile); + const fileInfo = statSync(combinedDirs); + if (fileInfo.isDirectory()) { + const categoryDir = readdirSync(combinedDirs).filter(file => process.versions.bun ? file.endsWith('.ts') : file.endsWith('.js')); + for (const cmdFile of categoryDir) { + const combinedCmdDir = path.join(combinedDirs, cmdFile); + try { + const commandClass = await import(combinedCmdDir); + const command = new commandClass.default(); + command.filePath = combinedCmdDir; + const commandDataJSON = command.commandData.toJSON(); + for (const currentAppCommand of currentAppCommands) { + if (currentAppCommand.name === commandDataJSON.name) { + await client.rest.patch(Routes.applicationCommand(client.application.id, currentAppCommand.id), { body: commandDataJSON }); + break; + } + } + commandMap.set(command.commandData.name, command); + await client.rest.post(Routes.applicationCommands(client.application.id), { body: commandDataJSON }); + } + catch (e) { + console.log('Invalid command'); + console.error(`error ${e}`); + } + } + } + } + for (const currentAppCommand of currentAppCommands) { + if (!commandMap.has(currentAppCommand.name)) { + await client.rest.delete(Routes.applicationCommand(client.application.id, currentAppCommand.id)); + } + } + return commandMap; +} diff --git a/dist/handlers/loaders/event.js b/dist/handlers/loaders/event.js new file mode 100644 index 0000000..805b916 --- /dev/null +++ b/dist/handlers/loaders/event.js @@ -0,0 +1,31 @@ +import { readdirSync } from 'node:fs'; +import path from 'node:path'; +export async function loadEvents(client, eventDir) { + const eventMap = new Map(); + const baseEvtDir = readdirSync(eventDir); + for (const evtFile of baseEvtDir) { + const combinedEvtDir = path.join(eventDir, evtFile); + try { + const eventClass = await import(combinedEvtDir); + const event = new eventClass.default(); + event.filePath = combinedEvtDir; + eventMap.set(event.eventName, event); + if (event.once) { + client.once(event.eventName, (...e) => { + event.client = client; + event.execute(...e); + }); + } + else { + client.on(event.eventName, (...e) => { + event.client = client; + event.execute(...e); + }); + } + } + catch (e) { + console.log('Invalid event'); + console.error(`error ${e}`); + } + } +} diff --git a/dist/handlers/loaders/interactions.js b/dist/handlers/loaders/interactions.js new file mode 100644 index 0000000..300db00 --- /dev/null +++ b/dist/handlers/loaders/interactions.js @@ -0,0 +1,31 @@ +import { readdirSync } from 'fs'; +import path from 'node:path'; +import { statSync } from 'node:fs'; +export async function loadInteractions(client, interDir) { + const interMap = new Map(); + const baseInterDir = readdirSync(interDir); + for (const file of baseInterDir) { + const combinedDirs = path.join(interDir, file); + const fileInfo = statSync(combinedDirs); + if (fileInfo.isDirectory()) { + const categoryDir = readdirSync(combinedDirs).filter(catFile => process.versions.bun ? catFile.endsWith('.ts') : catFile.endsWith('.js')); + for (const interFile of categoryDir) { + const combinedInterDir = path.join(combinedDirs, interFile); + try { + const interClass = await import(combinedInterDir); + const interaction = new interClass.default(); + interaction.filePath = combinedInterDir; + interaction.client = client; + for (const id of interaction.id) { + interMap.set(id, interaction); + } + } + catch (e) { + console.log('Invalid interaction'); + console.error(`error ${e}`); + } + } + } + } + return interMap; +} diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..c677a12 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,85 @@ +/* eslint-disable no-inline-comments */ +import { Client, GatewayIntentBits } from 'discord.js'; +import { program } from 'commander'; +import { parse } from 'yaml'; +import path from 'node:path'; +import { PrismaClient } from '@prisma/client'; +import { loadEvents } from './handlers/loaders/event.js'; +import { loadInteractions } from './handlers/loaders/interactions.js'; +import { getContext } from './utils/context.js'; +program + .option('-c, --config ', 'Path to config file (e.g. /opt/config.yml)'); +program.parse(process.argv); +let configPath = program.opts().config; +if (!configPath) { + configPath = 'config.yml'; +} +let config; +if (process.versions.bun) { // Try to use bun native things if possible. + const configFile = Bun.file(configPath); + config = parse(await configFile.text()); +} +else { + const { readFileSync } = await import('node:fs'); + const configFile = readFileSync(configPath, 'utf8'); + config = parse(configFile); +} +if (!config.token) { + throw Error('Please provide a token!'); // throw seems to be the only way to exit in this situation, possibly a function would be better. +} +const client = new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.AutoModerationConfiguration, + GatewayIntentBits.AutoModerationExecution, + GatewayIntentBits.DirectMessageReactions, + GatewayIntentBits.DirectMessageTyping, + GatewayIntentBits.DirectMessages, + GatewayIntentBits.GuildEmojisAndStickers, + GatewayIntentBits.GuildIntegrations, + GatewayIntentBits.GuildInvites, + GatewayIntentBits.GuildMembers, + GatewayIntentBits.GuildMessageReactions, + GatewayIntentBits.GuildMessageTyping, + GatewayIntentBits.GuildModeration, + GatewayIntentBits.GuildPresences, // PRIVILEGED + GatewayIntentBits.GuildWebhooks, + GatewayIntentBits.MessageContent, // PRIVILEGED + ], +}); +client.contexts = new Map(); +client.getContext = getContext; +client.db = new PrismaClient(); +await client.db.$connect(); +process.on('exit', async () => { + await client.db.$disconnect(); + await client.destroy(); + process.reallyExit(0); +}); +let eventDir; +if (process.versions.bun) { + eventDir = path.join(path.dirname(Bun.main), 'events'); +} +else { + const { fileURLToPath } = await import('node:url'); + eventDir = path.join(path.dirname(fileURLToPath(import.meta.url)), 'events'); +} +if (process.versions.bun) { + client.commandDir = path.join(path.dirname(Bun.main), 'commands'); +} +else { + const { fileURLToPath } = await import('node:url'); + client.commandDir = path.join(path.dirname(fileURLToPath(import.meta.url)), 'commands'); +} +let interDir; +if (process.versions.bun) { + interDir = path.join(path.dirname(Bun.main), 'interactions'); +} +else { + const { fileURLToPath } = await import('node:url'); + interDir = path.join(path.dirname(fileURLToPath(import.meta.url)), 'interactions'); +} +client.interactionHandlers = await loadInteractions(client, interDir); +await loadEvents(client, eventDir); +await client.login(config.token); diff --git a/dist/types.js b/dist/types.js new file mode 100644 index 0000000..97c47da --- /dev/null +++ b/dist/types.js @@ -0,0 +1,28 @@ +// Unpopular opinion, I like using classes for commands. +export class Command { + id; + client; + commandData; + filePath; + constructor(appCommandData) { + this.commandData = appCommandData; + } +} +export class Event { + eventName; + filePath; + client; + once; + constructor(eventName, once = false) { + this.eventName = eventName; + this.once = once; + } +} +export class Interaction { + id; + filePath; + client; + constructor(...interactionID) { + this.id = interactionID; + } +} diff --git a/dist/utils/context.js b/dist/utils/context.js new file mode 100644 index 0000000..754d19d --- /dev/null +++ b/dist/utils/context.js @@ -0,0 +1,8 @@ +export function getContext(contextName) { + // @ts-expect-error Some TypeScript issues. + const client = this; + if (!client.contexts.has(contextName)) { + client.contexts.set(contextName, new Map()); + } + return client.contexts.get(contextName); +} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..3038f34 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,106 @@ +import typescriptEslint from '@typescript-eslint/eslint-plugin'; +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import js from '@eslint/js'; +import { FlatCompat } from '@eslint/eslintrc'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +export default [{ + ignores: ['**/dist/'], +}, ...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended'), { + plugins: { + '@typescript-eslint': typescriptEslint, + }, + + languageOptions: { + globals: { + ...globals.node, + }, + + parser: tsParser, + ecmaVersion: 2022, + sourceType: 'module', + }, + + rules: { + 'arrow-spacing': ['warn', { + before: true, + after: true, + }], + + 'brace-style': ['error', 'stroustrup', { + allowSingleLine: true, + }], + + 'comma-dangle': ['error', 'always-multiline'], + 'comma-spacing': 'error', + 'comma-style': 'error', + curly: ['error', 'multi-line', 'consistent'], + 'dot-location': ['error', 'property'], + 'handle-callback-err': 'off', + indent: ['error', 'tab'], + 'keyword-spacing': 'error', + + 'max-nested-callbacks': ['error', { + max: 4, + }], + + 'max-statements-per-line': ['error', { + max: 2, + }], + + 'no-console': 'off', + 'no-empty-function': 'error', + 'no-floating-decimal': 'error', + 'no-inline-comments': 'error', + 'no-lonely-if': 'error', + 'no-multi-spaces': 'error', + + 'no-multiple-empty-lines': ['error', { + max: 2, + maxEOF: 1, + maxBOF: 0, + }], + + 'no-shadow': ['error', { + allow: ['err', 'resolve', 'reject'], + }], + + 'no-trailing-spaces': ['error'], + 'no-var': 'error', + + '@typescript-eslint/no-unused-vars': ['error', { + argsIgnorePattern: '^_', + destructuredArrayIgnorePattern: '^_', + varsIgnorePattern: '^_', + }], + + 'no-unused-vars': 'off', + 'object-curly-spacing': ['error', 'always'], + 'prefer-const': 'error', + quotes: ['error', 'single'], + semi: ['error', 'always'], + 'space-before-blocks': 'error', + + 'space-before-function-paren': ['error', { + anonymous: 'never', + named: 'never', + asyncArrow: 'always', + }], + + 'space-in-parens': 'error', + 'space-infix-ops': 'error', + 'space-unary-ops': 'error', + 'spaced-comment': 'error', + yoda: 'error', + }, +}]; \ No newline at end of file diff --git a/events/interactionCreate.ts b/events/interactionCreate.ts new file mode 100644 index 0000000..44036c7 --- /dev/null +++ b/events/interactionCreate.ts @@ -0,0 +1,33 @@ +import { Event } from '../types.js'; +import { Events, Interaction } from 'discord.js'; + +export default class InteractionCreateEvent extends Event { + + constructor() { + super(Events.InteractionCreate, false); + } + + async execute(interaction: Interaction) { + + if (interaction.isMessageComponent() || interaction.isModalSubmit()) { + + const interactionHandler = this.client.interactionHandlers.get(interaction.customId); + if (!interactionHandler) return; + + interactionHandler.client = this.client; + + await interactionHandler.execute(interaction); + + } + + if (!interaction.isChatInputCommand()) return; + + const command = this.client.commands?.get(interaction.commandName); + if (!command) return; + + command.client = this.client; + await command.execute(interaction); + + } + +} \ No newline at end of file diff --git a/events/ready.ts b/events/ready.ts new file mode 100644 index 0000000..b0e2ad0 --- /dev/null +++ b/events/ready.ts @@ -0,0 +1,27 @@ +import { ActivityType, Client, Events } from 'discord.js'; +import { Event } from '../types.js'; +import { loadCommands } from '../handlers/loaders/command.js'; + +export default class ReadyEvent extends Event { + + constructor() { + super(Events.ClientReady, true); + } + + async execute(_client: Client) { + + this.client.user?.setActivity({ + type: ActivityType.Custom, + state: 'Creating bugs...', + name: 'hello', + }); + + this.client.user?.setStatus('dnd'); + + this.client.commands = await loadCommands(this.client); + + console.log(`Logged in as ${this.client.user?.tag}`); + + } + +} \ No newline at end of file diff --git a/handlers/loaders/command.ts b/handlers/loaders/command.ts new file mode 100644 index 0000000..93df299 --- /dev/null +++ b/handlers/loaders/command.ts @@ -0,0 +1,70 @@ +import { Command } from '../../types.js'; +import { readdirSync, statSync } from 'node:fs'; +import path from 'node:path'; +import { Client, RESTGetAPIApplicationCommandsResult, Routes } from 'discord.js'; + + +export async function loadCommands(client: Client): Promise> { + + const currentAppCommands : RESTGetAPIApplicationCommandsResult = await client.rest.get(Routes.applicationCommands(client.application!.id)) as RESTGetAPIApplicationCommandsResult; + + const commandMap: Map = new Map(); + + const baseCmdDir = readdirSync(client.commandDir); + + for (const baseCmdDirFile of baseCmdDir) { + + const combinedDirs = path.join(client.commandDir, baseCmdDirFile); + + const fileInfo = statSync(combinedDirs); + + if (fileInfo.isDirectory()) { + + const categoryDir = readdirSync(combinedDirs).filter(file => process.versions.bun ? file.endsWith('.ts') : file.endsWith('.js')); + + for (const cmdFile of categoryDir) { + + const combinedCmdDir = path.join(combinedDirs, cmdFile); + + try { + const commandClass = await import(combinedCmdDir); + + const command : Command = new commandClass.default(); + command.filePath = combinedCmdDir; + + const commandDataJSON = command.commandData.toJSON(); + + for (const currentAppCommand of currentAppCommands) { + + if (currentAppCommand.name === commandDataJSON.name) { + await client.rest.patch(Routes.applicationCommand(client.application!.id, currentAppCommand.id), { body: commandDataJSON }); + break; + } + } + + commandMap.set(command.commandData.name, command); + + await client.rest.post(Routes.applicationCommands(client.application!.id), { body: commandDataJSON }); + + } + catch (e) { + console.log('Invalid command'); + console.error(`error ${e}`); + } + + + } + + } + + } + + for (const currentAppCommand of currentAppCommands) { + if (!commandMap.has(currentAppCommand.name)) { + await client.rest.delete(Routes.applicationCommand(client.application!.id, currentAppCommand.id)); + } + } + + return commandMap; + +} \ No newline at end of file diff --git a/handlers/loaders/event.ts b/handlers/loaders/event.ts new file mode 100644 index 0000000..2b7e4fe --- /dev/null +++ b/handlers/loaders/event.ts @@ -0,0 +1,46 @@ +import { Client } from 'discord.js'; +import { Event } from '../../types.js'; +import { readdirSync } from 'node:fs'; +import path from 'node:path'; + +export async function loadEvents(client: Client, eventDir: string): Promise { + + const eventMap: Map = new Map(); + + const baseEvtDir = readdirSync(eventDir); + + for (const evtFile of baseEvtDir) { + + const combinedEvtDir = path.join(eventDir, evtFile); + + try { + + const eventClass = await import(combinedEvtDir); + + const event : Event = new eventClass.default(); + event.filePath = combinedEvtDir; + + eventMap.set(event.eventName, event); + + if (event.once) { + client.once(event.eventName, (...e) => { + event.client = client; + event.execute(...e); + }); + } + else { + client.on(event.eventName, (...e) => { + event.client = client; + event.execute(...e); + }); + } + + } + catch (e) { + console.log('Invalid event'); + console.error(`error ${e}`); + } + + } + +} \ No newline at end of file diff --git a/handlers/loaders/interactions.ts b/handlers/loaders/interactions.ts new file mode 100644 index 0000000..7009f93 --- /dev/null +++ b/handlers/loaders/interactions.ts @@ -0,0 +1,53 @@ +import { Interaction } from '../../types.js'; +import { readdirSync } from 'fs'; +import path from 'node:path'; +import { statSync } from 'node:fs'; +import { Client } from 'discord.js'; + +export async function loadInteractions(client: Client, interDir: string): Promise> { + + const interMap: Map = new Map(); + + const baseInterDir = readdirSync(interDir); + + for (const file of baseInterDir) { + + const combinedDirs = path.join(interDir, file); + + const fileInfo = statSync(combinedDirs); + + if (fileInfo.isDirectory()) { + + const categoryDir = readdirSync(combinedDirs).filter(catFile => process.versions.bun ? catFile.endsWith('.ts') : catFile.endsWith('.js')); + + for (const interFile of categoryDir) { + + const combinedInterDir = path.join(combinedDirs, interFile); + + try { + const interClass = await import(combinedInterDir); + + const interaction: Interaction = new interClass.default(); + interaction.filePath = combinedInterDir; + interaction.client = client; + + for (const id of interaction.id) { + interMap.set(id, interaction); + } + + } + catch (e) { + console.log('Invalid interaction'); + console.error(`error ${e}`); + } + + } + + + } + + } + + return interMap; + +} \ No newline at end of file diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..d1713aa --- /dev/null +++ b/index.ts @@ -0,0 +1,124 @@ +/* eslint-disable no-inline-comments */ +import { Client, GatewayIntentBits } from 'discord.js'; +import { Config } from './types.js'; +import { program } from 'commander'; +import { parse } from 'yaml'; +import path from 'node:path'; +import { PrismaClient } from '@prisma/client'; +import { loadEvents } from './handlers/loaders/event.js'; +import { loadInteractions } from './handlers/loaders/interactions.js'; +import { getContext } from './utils/context.js'; + +program + .option('-c, --config ', 'Path to config file (e.g. /opt/config.yml)'); + +program.parse(process.argv); + +let configPath : string | undefined = program.opts().config; + +if (!configPath) { + configPath = 'config.yml'; +} + +let config : Config; + +if (process.versions.bun) { // Try to use bun native things if possible. + + const configFile = Bun.file(configPath); + config = parse(await configFile.text()); + +} +else { + + const { readFileSync } = await import('node:fs'); + + const configFile = readFileSync(configPath, 'utf8'); + config = parse(configFile); + +} + + +if (!config.token) { + throw Error('Please provide a token!'); // throw seems to be the only way to exit in this situation, possibly a function would be better. +} + +const client = new Client({ // We probably don't need all of these intents. But for now this is okay. + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.AutoModerationConfiguration, + GatewayIntentBits.AutoModerationExecution, + GatewayIntentBits.DirectMessageReactions, + GatewayIntentBits.DirectMessageTyping, + GatewayIntentBits.DirectMessages, + GatewayIntentBits.GuildEmojisAndStickers, + GatewayIntentBits.GuildIntegrations, + GatewayIntentBits.GuildInvites, + GatewayIntentBits.GuildMembers, + GatewayIntentBits.GuildMessageReactions, + GatewayIntentBits.GuildMessageTyping, + GatewayIntentBits.GuildModeration, + GatewayIntentBits.GuildPresences, // PRIVILEGED + GatewayIntentBits.GuildWebhooks, + GatewayIntentBits.MessageContent, // PRIVILEGED + ], +}); + +client.contexts = new Map(); +client.getContext = getContext; + +client.db = new PrismaClient(); +await client.db.$connect(); + +process.on('exit', async () => { + await client.db.$disconnect(); + await client.destroy(); + process.reallyExit(0); +}); + +let eventDir : string; + +if (process.versions.bun) { + + eventDir = path.join(path.dirname(Bun.main), 'events'); + +} +else { + + const { fileURLToPath } = await import('node:url'); + eventDir = path.join(path.dirname(fileURLToPath(import.meta.url)), 'events'); + +} + + +if (process.versions.bun) { + + client.commandDir = path.join(path.dirname(Bun.main), 'commands'); + +} +else { + + const { fileURLToPath } = await import('node:url'); + client.commandDir = path.join(path.dirname(fileURLToPath(import.meta.url)), 'commands'); + +} + +let interDir : string; + +if (process.versions.bun) { + + interDir = path.join(path.dirname(Bun.main), 'interactions'); + +} +else { + + const { fileURLToPath } = await import('node:url'); + interDir = path.join(path.dirname(fileURLToPath(import.meta.url)), 'interactions'); + +} + +client.interactionHandlers = await loadInteractions(client, interDir); + +await loadEvents(client, eventDir); + +await client.login(config.token); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..3b36c08 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "ts-core", + "version": "1.2.4", + "main": "dist/index.ts", + "type": "module", + "scripts": { + "start": "tsc && node dist/index.js", + "lint": "eslint .", + "lint:fix": "eslint . --fix" + }, + "dependencies": { + "@prisma/client": "5.16.1", + "commander": "^12.1.0", + "discord.js": "^14.15.3", + "prisma": "^5.16.1", + "yaml": "^2.4.5" + }, + "devDependencies": { + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.6.0", + "@types/node": "^20.14.9", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", + "bun-types": "^1.1.17", + "eslint": "^9.6.0", + "globals": "^15.8.0", + "typescript": "^5.5.3" + }, + "packageManager": "pnpm@9.4.0+sha512.f549b8a52c9d2b8536762f99c0722205efc5af913e77835dbccc3b0b0b2ca9e7dc8022b78062c17291c48e88749c70ce88eb5a74f1fa8c4bf5e18bb46c8bd83a" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..56752b6 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1308 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@prisma/client': + specifier: 5.16.1 + version: 5.16.1(prisma@5.16.1) + commander: + specifier: ^12.1.0 + version: 12.1.0 + discord.js: + specifier: ^14.15.3 + version: 14.15.3 + prisma: + specifier: ^5.16.1 + version: 5.16.1 + yaml: + specifier: ^2.4.5 + version: 2.4.5 + devDependencies: + '@eslint/eslintrc': + specifier: ^3.1.0 + version: 3.1.0 + '@eslint/js': + specifier: ^9.6.0 + version: 9.6.0 + '@types/node': + specifier: ^20.14.9 + version: 20.14.9 + '@typescript-eslint/eslint-plugin': + specifier: ^7.15.0 + version: 7.15.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0)(typescript@5.5.3) + '@typescript-eslint/parser': + specifier: ^7.15.0 + version: 7.15.0(eslint@9.6.0)(typescript@5.5.3) + bun-types: + specifier: ^1.1.17 + version: 1.1.17 + eslint: + specifier: ^9.6.0 + version: 9.6.0 + globals: + specifier: ^15.8.0 + version: 15.8.0 + typescript: + specifier: ^5.5.3 + version: 5.5.3 + +packages: + + '@discordjs/builders@1.8.2': + resolution: {integrity: sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g==} + 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.1': + resolution: {integrity: sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==} + engines: {node: '>=16.11.0'} + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.11.0': + resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.17.0': + resolution: {integrity: sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.1.0': + resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.6.0': + resolution: {integrity: sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.4': + resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.0': + resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + engines: {node: '>=18.18'} + + '@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'} + + '@prisma/client@5.16.1': + resolution: {integrity: sha512-wM9SKQjF0qLxdnOZIVAIMKiz6Hu7vDt4FFAih85K1dk/Rr2mdahy6d3QP41K62N9O0DJJA//gUDA3Mp49xsKIg==} + engines: {node: '>=16.13'} + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + + '@prisma/debug@5.16.1': + resolution: {integrity: sha512-JsNgZAg6BD9RInLSrg7ZYzo11N7cVvYArq3fHGSD89HSgtN0VDdjV6bib7YddbcO6snzjchTiLfjeTqBjtArVQ==} + + '@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303': + resolution: {integrity: sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==} + + '@prisma/engines@5.16.1': + resolution: {integrity: sha512-KkyF3eIUtBIyp5A/rJHCtwQO18OjpGgx18PzjyGcJDY/+vNgaVyuVd+TgwBgeq6NLdd1XMwRCI+58vinHsAdfA==} + + '@prisma/fetch-engine@5.16.1': + resolution: {integrity: sha512-oOkjaPU1lhcA/Rvr4GVfd1NLJBwExgNBE36Ueq7dr71kTMwy++a3U3oLd2ZwrV9dj9xoP6LjCcky799D9nEt4w==} + + '@prisma/get-platform@5.16.1': + resolution: {integrity: sha512-R4IKnWnMkR2nUAbU5gjrPehdQYUUd7RENFD2/D+xXTNhcqczp0N+WEGQ3ViyI3+6mtVcjjNIMdnUTNyu3GxIgA==} + + '@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'} + + '@types/node@20.12.14': + resolution: {integrity: sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==} + + '@types/node@20.14.9': + resolution: {integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==} + + '@types/ws@8.5.10': + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + + '@typescript-eslint/eslint-plugin@7.15.0': + resolution: {integrity: sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@7.15.0': + resolution: {integrity: sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@7.15.0': + resolution: {integrity: sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/type-utils@7.15.0': + resolution: {integrity: sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@7.15.0': + resolution: {integrity: sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/typescript-estree@7.15.0': + resolution: {integrity: sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@7.15.0': + resolution: {integrity: sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + + '@typescript-eslint/visitor-keys@7.15.0': + resolution: {integrity: sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@vladfrangu/async_event_emitter@2.4.0': + resolution: {integrity: sha512-eNb/9DMwNvhhgn1UuQ8Rl90jhj9PBkYH4oQ522TkiWUVWRfbh3PjdOTFkVGNKs5+xUXalkgFrUSwtY8u0g0S4g==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.12.0: + resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + bun-types@1.1.17: + resolution: {integrity: sha512-Z4+OplcSd/YZq7ZsrfD00DKJeCwuNY96a1IDJyR73+cTBaFIS7SC6LhpY/W3AMEXO9iYq5NJ58WAwnwL1p5vKg==} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + discord-api-types@0.37.83: + resolution: {integrity: sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==} + + discord.js@14.15.3: + resolution: {integrity: sha512-/UJDQO10VuU6wQPglA4kz2bw2ngeeSbogiIPx/TsnctfzV/tNf+q+i1HlgtX1OGpeOBpJH9erZQNO5oRM2uAtQ==} + engines: {node: '>=16.11.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-scope@8.0.1: + resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.0.0: + resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.6.0: + resolution: {integrity: sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + + espree@10.1.0: + resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + 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-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.8.0: + resolution: {integrity: sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==} + engines: {node: '>=18'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + magic-bytes.js@1.10.0: + resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prisma@5.16.1: + resolution: {integrity: sha512-Z1Uqodk44diztImxALgJJfNl2Uisl9xDRvqybMKEBYJLNKNhDfAHf+ZIJbZyYiBhLMbKU9cYGdDVG5IIXEnL2Q==} + engines: {node: '>=16.13'} + hasBin: true + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + engines: {node: '>=10'} + hasBin: true + + 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'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + ts-api-utils@1.3.0: + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + ts-mixer@6.0.4: + resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} + + tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici@6.13.0: + resolution: {integrity: sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==} + engines: {node: '>=18.0'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + 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 + + yaml@2.4.5: + resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==} + engines: {node: '>= 14'} + hasBin: true + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@discordjs/builders@1.8.2': + 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.4.0 + 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.1': + 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.4.0 + discord-api-types: 0.37.83 + tslib: 2.6.2 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@eslint-community/eslint-utils@4.4.0(eslint@9.6.0)': + dependencies: + eslint: 9.6.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.11.0': {} + + '@eslint/config-array@0.17.0': + dependencies: + '@eslint/object-schema': 2.1.4 + debug: 4.3.5 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/eslintrc@3.1.0': + dependencies: + ajv: 6.12.6 + debug: 4.3.5 + espree: 10.1.0 + globals: 14.0.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.6.0': {} + + '@eslint/object-schema@2.1.4': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.0': {} + + '@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 + + '@prisma/client@5.16.1(prisma@5.16.1)': + optionalDependencies: + prisma: 5.16.1 + + '@prisma/debug@5.16.1': {} + + '@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303': {} + + '@prisma/engines@5.16.1': + dependencies: + '@prisma/debug': 5.16.1 + '@prisma/engines-version': 5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303 + '@prisma/fetch-engine': 5.16.1 + '@prisma/get-platform': 5.16.1 + + '@prisma/fetch-engine@5.16.1': + dependencies: + '@prisma/debug': 5.16.1 + '@prisma/engines-version': 5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303 + '@prisma/get-platform': 5.16.1 + + '@prisma/get-platform@5.16.1': + dependencies: + '@prisma/debug': 5.16.1 + + '@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': {} + + '@types/node@20.12.14': + dependencies: + undici-types: 5.26.5 + + '@types/node@20.14.9': + dependencies: + undici-types: 5.26.5 + + '@types/ws@8.5.10': + dependencies: + '@types/node': 20.14.9 + + '@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0)(typescript@5.5.3)': + dependencies: + '@eslint-community/regexpp': 4.11.0 + '@typescript-eslint/parser': 7.15.0(eslint@9.6.0)(typescript@5.5.3) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/type-utils': 7.15.0(eslint@9.6.0)(typescript@5.5.3) + '@typescript-eslint/utils': 7.15.0(eslint@9.6.0)(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.15.0 + eslint: 9.6.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + ts-api-utils: 1.3.0(typescript@5.5.3) + optionalDependencies: + typescript: 5.5.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3)': + dependencies: + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.15.0 + debug: 4.3.5 + eslint: 9.6.0 + optionalDependencies: + typescript: 5.5.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@7.15.0': + dependencies: + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 + + '@typescript-eslint/type-utils@7.15.0(eslint@9.6.0)(typescript@5.5.3)': + dependencies: + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + '@typescript-eslint/utils': 7.15.0(eslint@9.6.0)(typescript@5.5.3) + debug: 4.3.5 + eslint: 9.6.0 + ts-api-utils: 1.3.0(typescript@5.5.3) + optionalDependencies: + typescript: 5.5.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@7.15.0': {} + + '@typescript-eslint/typescript-estree@7.15.0(typescript@5.5.3)': + dependencies: + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 + debug: 4.3.5 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.2 + ts-api-utils: 1.3.0(typescript@5.5.3) + optionalDependencies: + typescript: 5.5.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@7.15.0(eslint@9.6.0)(typescript@5.5.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.6.0) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + eslint: 9.6.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@7.15.0': + dependencies: + '@typescript-eslint/types': 7.15.0 + eslint-visitor-keys: 3.4.3 + + '@vladfrangu/async_event_emitter@2.4.0': {} + + acorn-jsx@5.3.2(acorn@8.12.0): + dependencies: + acorn: 8.12.0 + + acorn@8.12.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + array-union@2.1.0: {} + + balanced-match@1.0.2: {} + + 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.3: + dependencies: + fill-range: 7.1.1 + + bun-types@1.1.17: + dependencies: + '@types/node': 20.12.14 + '@types/ws': 8.5.10 + + callsites@3.1.0: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + commander@12.1.0: {} + + concat-map@0.0.1: {} + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + debug@4.3.5: + dependencies: + ms: 2.1.2 + + deep-is@0.1.4: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + discord-api-types@0.37.83: {} + + discord.js@14.15.3: + dependencies: + '@discordjs/builders': 1.8.2 + '@discordjs/collection': 1.5.3 + '@discordjs/formatters': 0.4.0 + '@discordjs/rest': 2.3.0 + '@discordjs/util': 1.1.0 + '@discordjs/ws': 1.1.1 + '@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 + + escape-string-regexp@4.0.0: {} + + eslint-scope@8.0.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.0.0: {} + + eslint@9.6.0: + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.6.0) + '@eslint-community/regexpp': 4.11.0 + '@eslint/config-array': 0.17.0 + '@eslint/eslintrc': 3.1.0 + '@eslint/js': 9.6.0 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.3.0 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.5 + escape-string-regexp: 4.0.0 + eslint-scope: 8.0.1 + eslint-visitor-keys: 4.0.0 + espree: 10.1.0 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + espree@10.1.0: + dependencies: + acorn: 8.12.0 + acorn-jsx: 5.3.2(acorn@8.12.0) + eslint-visitor-keys: 4.0.0 + + esquery@1.5.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + 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.7 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + + flatted@3.3.1: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@14.0.0: {} + + globals@15.8.0: {} + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + + graphemer@1.4.0: {} + + has-flag@4.0.0: {} + + ignore@5.3.1: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-path-inside@3.0.3: {} + + isexe@2.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + lodash.snakecase@4.1.1: {} + + lodash@4.17.21: {} + + magic-bytes.js@1.10.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.7: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + ms@2.1.2: {} + + natural-compare@1.4.0: {} + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-type@4.0.0: {} + + picomatch@2.3.1: {} + + prelude-ls@1.2.1: {} + + prisma@5.16.1: + dependencies: + '@prisma/engines': 5.16.1 + + punycode@2.3.1: {} + + queue-microtask@1.2.3: {} + + resolve-from@4.0.0: {} + + reusify@1.0.4: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + semver@7.6.2: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + slash@3.0.0: {} + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + text-table@0.2.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + ts-api-utils@1.3.0(typescript@5.5.3): + dependencies: + typescript: 5.5.3 + + ts-mixer@6.0.4: {} + + tslib@2.6.2: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typescript@5.5.3: {} + + undici-types@5.26.5: {} + + undici@6.13.0: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + ws@8.17.1: {} + + yaml@2.4.5: {} + + yocto-queue@0.1.0: {} diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..ee282c7 --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,14 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? +// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..19e8e5b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,37 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "NodeNext", + "types": [ + "bun-types" + ], + "outDir": "./dist", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "useUnknownInCatchVariables": true, + "alwaysStrict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "skipLibCheck": true + }, + "include": [ + "./**/*.ts", + "discordjs.d.ts" + ], + "exclude": [ + "node_modules/**/*" + ] +} \ No newline at end of file diff --git a/types.ts b/types.ts new file mode 100644 index 0000000..28197ca --- /dev/null +++ b/types.ts @@ -0,0 +1,59 @@ +import { + ChatInputCommandInteraction, + Client, + ClientEvents, + MessageComponentInteraction, ModalSubmitInteraction, + SlashCommandBuilder, + Interaction as DiscordInteraction, +} from 'discord.js'; + +export interface Config { + token: string, +} + +// Unpopular opinion, I like using classes for commands. +export abstract class Command { + + public id!: string; + public client!: Client; + public commandData: SlashCommandBuilder | Omit; + public filePath: string | undefined; + + protected constructor(appCommandData: SlashCommandBuilder | Omit) { + this.commandData = appCommandData; + } + + abstract execute(interaction: ChatInputCommandInteraction): Promise; + +} + +export abstract class Event { + + public eventName: keyof ClientEvents; + public filePath: string | undefined; + public client!: Client; + public once: boolean; + + protected constructor(eventName: keyof ClientEvents, once: boolean = false) { + this.eventName = eventName; + this.once = once; + } + + abstract execute(...args: unknown[]): Promise; + +} + +export abstract class Interaction { + + public id: string[]; + public filePath: string | undefined; + public client!: Client; + + protected constructor(...interactionID: string[]) { + this.id = interactionID; + } + + abstract beforeExecute?(interaction: DiscordInteraction | MessageComponentInteraction): Promise; + abstract execute(interaction: MessageComponentInteraction | ModalSubmitInteraction): Promise; + +} \ No newline at end of file diff --git a/utils/context.ts b/utils/context.ts new file mode 100644 index 0000000..680d291 --- /dev/null +++ b/utils/context.ts @@ -0,0 +1,14 @@ +import { Client } from 'discord.js'; + +export function getContext(contextName: string): Map { + + // @ts-expect-error Some TypeScript issues. + const client = this as Client; + + if (!client.contexts.has(contextName)) { + client.contexts.set(contextName, new Map()); + } + + return client.contexts.get(contextName); + +} \ No newline at end of file