From 591d4dd00a0cdded34ba60d2590d62e3b30ec7ae Mon Sep 17 00:00:00 2001 From: Shane C Date: Tue, 2 Jul 2024 10:08:47 -0400 Subject: [PATCH] initial commit --- .forgejo/workflows/build_check.yml | 27 + .gitignore | 28 + README.md | 10 + bun.lockb | Bin 0 -> 55925 bytes commands/misc/ping.ts | 37 + config.example.yml | 1 + discordjs.d.ts | 12 + 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 | 115 +++ package.json | 28 + pnpm-lock.yaml | 1244 ++++++++++++++++++++++++++++ tsconfig.json | 37 + types.ts | 59 ++ utils/context.ts | 14 + 19 files changed, 1947 insertions(+) create mode 100644 .forgejo/workflows/build_check.yml 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 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 tsconfig.json create mode 100644 types.ts create mode 100644 utils/context.ts diff --git a/.forgejo/workflows/build_check.yml b/.forgejo/workflows/build_check.yml new file mode 100644 index 0000000..a1b4df8 --- /dev/null +++ b/.forgejo/workflows/build_check.yml @@ -0,0 +1,27 @@ +name: Build Check +on: + push: + branches: ["main"] + +jobs: + build: + name: Test Build + runs-on: node20-bookworm + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup NodeJS + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Install PNPM + run: | + corepack enable + corepack prepare pnpm@latest --activate + npm i -g typescript + - name: Install packages + run: pnpm i + - name: TypeScript Build + run: tsc + - name: ESLint Check + run: pnpm run lint \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3099e10 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# build output +dist/ + +# IDE related +.vscode +.idea + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# configs +test_config.yml +test_config.yaml +config.yml +config.yaml + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8f1de59 --- /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 does not include a database ORM within it. + +## 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..92766e2ed86c86f6e1f7fb12631fbb5cbbae3464 GIT binary patch literal 55925 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 EPvVnF1poj5 literal 0 HcmV?d00001 diff --git a/commands/misc/ping.ts b/commands/misc/ping.ts new file mode 100644 index 0000000..40c8143 --- /dev/null +++ b/commands/misc/ping.ts @@ -0,0 +1,37 @@ +import { ChatInputCommandInteraction, 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: ChatInputCommandInteraction) { + + 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 ] }); + + } + +} \ No newline at end of file diff --git a/config.example.yml b/config.example.yml new file mode 100644 index 0000000..7589b3d --- /dev/null +++ b/config.example.yml @@ -0,0 +1 @@ +token: \ No newline at end of file diff --git a/discordjs.d.ts b/discordjs.d.ts new file mode 100644 index 0000000..96a6ed6 --- /dev/null +++ b/discordjs.d.ts @@ -0,0 +1,12 @@ +import type { Command, Interaction as InteractionHandler } from './types.ts'; + +declare module 'discord.js' { + interface Client { + commands: Map; + interactionHandlers: Map; + commandDir: string; + + contexts: Map; + getContext(contextName: string): Map; + } +} \ No newline at end of file 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..93d1add --- /dev/null +++ b/index.ts @@ -0,0 +1,115 @@ +/* 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 { 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; + +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..ef69c02 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "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": { + "commander": "^12.1.0", + "discord.js": "^14.15.3", + "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..16b46cb --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1244 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + commander: + specifier: ^12.1.0 + version: 12.1.0 + discord.js: + specifier: ^14.15.3 + version: 14.15.3 + 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'} + + '@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'} + + 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 + + '@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: {} + + 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/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