From 87a42229d7848f21d6ed7319f4bc5a9c6d3ceff1 Mon Sep 17 00:00:00 2001 From: Thijn <thijnkroon@gmail.com> Date: Thu, 7 Nov 2024 11:42:57 +0100 Subject: [PATCH 1/6] feat: convert to deno --- .eslintrc.json | 38 - .github/workflows/build.yml | 44 - .github/workflows/check.yml | 26 + .github/workflows/format.yml | 44 - .gitignore | 9 +- .prettierignore | 2 - .prettierrc.json | 7 - deno.json | 34 + deno.lock | 149 + nodemon.json | 12 - package-lock.json | 3747 -------------------- package.json | 34 - src/client/index.ts | 9 +- src/commands/debug/index.ts | 6 +- src/commands/debug/ping.ts | 16 +- src/commands/general/help.ts | 16 +- src/commands/general/index.ts | 12 +- src/commands/general/info.ts | 93 +- src/commands/index.ts | 4 +- src/constants/index.ts | 2 - src/constants/namespaces.ts | 4 - src/constants/style.ts | 13 - src/env.ts | 17 +- src/events/index.ts | 4 +- src/events/interactionCreate/commands.ts | 22 +- src/events/interactionCreate/help.ts | 5 +- src/events/interactionCreate/index.ts | 6 +- src/events/interactionCreate/pagination.ts | 5 +- src/events/ready.ts | 4 +- src/index.ts | 7 +- src/scripts/clear.ts | 13 +- src/scripts/deploy.ts | 23 +- src/types/commands.ts | 8 +- src/types/context.ts | 4 +- src/types/events.ts | 4 +- src/types/index.ts | 6 +- src/types/pagination.ts | 4 +- src/utils/command.ts | 2 +- src/utils/constants.ts | 18 + src/utils/event.ts | 11 +- src/utils/help.ts | 26 +- src/utils/index.ts | 23 +- src/utils/pagination.ts | 33 +- src/utils/paginators/help.ts | 36 +- src/utils/paginators/index.ts | 18 +- src/utils/replies.ts | 32 +- src/utils/split.ts | 10 +- tsconfig.json | 21 - 48 files changed, 474 insertions(+), 4209 deletions(-) delete mode 100644 .eslintrc.json delete mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/check.yml delete mode 100644 .github/workflows/format.yml delete mode 100644 .prettierignore delete mode 100644 .prettierrc.json create mode 100644 deno.json create mode 100644 deno.lock delete mode 100644 nodemon.json delete mode 100644 package-lock.json delete mode 100644 package.json delete mode 100644 src/constants/index.ts delete mode 100644 src/constants/namespaces.ts delete mode 100644 src/constants/style.ts create mode 100644 src/utils/constants.ts delete mode 100644 tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 8e23169..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "env": { - "browser": true, - "es2021": true - }, - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - "overrides": [ - { - "env": { - "node": true - }, - "files": [".eslintrc.{js,cjs}"], - "parserOptions": { - "sourceType": "script" - } - } - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": ["@typescript-eslint"], - "rules": { - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": [ - "warn", - { - "vars": "all", - "varsIgnorePattern": "^_", - "args": "after-used", - "argsIgnorePattern": "^_" - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-empty-interface": "off" - } -} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 436a97f..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Build Check - -on: - workflow_dispatch: - push: - branches: ['main'] - pull_request: - branches: ['main'] - -jobs: - # Install and cache npm dependencies - install-cache: - runs-on: ubuntu-latest - steps: - - name: Checkout Commit - uses: actions/checkout@v3 - - name: Cache node modules - uses: actions/cache@v3 - id: npm-cache - with: - path: | - **/node_modules - key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-build - - name: Install dependencies if cache invalid - if: steps.npm-cache.outputs.cache-hit != 'true' - run: npm ci - build: - runs-on: ubuntu-latest - needs: install-cache - steps: - - uses: actions/checkout@v3 - - name: Restore npm cache - uses: actions/cache@v3 - id: npm-cache - with: - path: | - **/node_modules - key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-build - - name: Run build - run: npm run build diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..48ce076 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,26 @@ +name: Check + +on: + workflow_dispatch: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + type-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: denoland/setup-deno@v2 + with: + deno-version: v2.x + - run: deno task check + format-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: denoland/setup-deno@v2 + with: + deno-version: v2.x + - run: deno fmt --check diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml deleted file mode 100644 index 106510e..0000000 --- a/.github/workflows/format.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Format Check - -on: - workflow_dispatch: - push: - branches: ['main'] - pull_request: - branches: ['main'] - -jobs: - # Install and cache npm dependencies - install-cache: - runs-on: ubuntu-latest - steps: - - name: Checkout Commit - uses: actions/checkout@v3 - - name: Cache node modules - uses: actions/cache@v3 - id: npm-cache - with: - path: | - **/node_modules - key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-build - - name: Install dependencies if cache invalid - if: steps.npm-cache.outputs.cache-hit != 'true' - run: npm ci - format-check: - runs-on: ubuntu-latest - needs: install-cache - steps: - - uses: actions/checkout@v3 - - name: Restore npm cache - uses: actions/cache@v3 - id: npm-cache - with: - path: | - **/node_modules - key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-build - - name: Run Prettier formatting check - run: npx prettier --check ./src diff --git a/.gitignore b/.gitignore index f94630c..7889494 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ -node_modules/ -dist/ -.env \ No newline at end of file +.env + +/.vs/ +/.vscode/ +/node_modules/ +/dist/ diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index db4c6d9..0000000 --- a/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -dist -node_modules \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index dbf0f21..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "endOfLine": "auto", - "semi": true, - "singleQuote": true, - "tabWidth": 2, - "trailingComma": "es5" -} diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..1a05525 --- /dev/null +++ b/deno.json @@ -0,0 +1,34 @@ +{ + "tasks": { + "dev": "deno run --watch --env-file --allow-net --allow-read src/index.ts", + "check": "deno check src/index.ts", + "lint": "deno lint --fix", + "fmt": "deno fmt", + "fmt:check": "deno fmt --check", + "deploy": "deno run --env-file --allow-net --allow-read src/scripts/deploy.ts", + "clear": "deno run --env-file --allow-net --allow-read src/scripts/clear.ts" + }, + "lint": { + "include": ["src/"], + "rules": { + "tags": ["recommended"] + } + }, + "fmt": { + "lineWidth": 80, + "indentWidth": 2, + "semiColons": true, + "singleQuote": true, + "include": ["src/"] + }, + "exclude": ["node_modules/", "dist/"], + "imports": { + "env": "./src/env.ts", + "client": "./src/client/index.ts", + "commands": "./src/commands/index.ts", + "types": "./src/types/index.ts", + "utils": "./src/utils/index.ts", + "discord.js": "npm:discord.js@^14.16.3" + }, + "nodeModulesDir": "auto" +} diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..6e5575f --- /dev/null +++ b/deno.lock @@ -0,0 +1,149 @@ +{ + "version": "4", + "specifiers": { + "npm:discord.js@^14.16.3": "14.16.3" + }, + "npm": { + "@discordjs/builders@1.9.0": { + "integrity": "sha512-0zx8DePNVvQibh5ly5kCEei5wtPBIUbSoE9n+91Rlladz4tgtFbJ36PZMxxZrTEOQ7AHMZ/b0crT/0fCy6FTKg==", + "dependencies": [ + "@discordjs/formatters", + "@discordjs/util", + "@sapphire/shapeshift", + "discord-api-types@0.37.97", + "fast-deep-equal", + "ts-mixer", + "tslib" + ] + }, + "@discordjs/collection@1.5.3": { + "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==" + }, + "@discordjs/collection@2.1.1": { + "integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==" + }, + "@discordjs/formatters@0.5.0": { + "integrity": "sha512-98b3i+Y19RFq1Xke4NkVY46x8KjJQjldHUuEbCqMvp1F5Iq9HgnGpu91jOi/Ufazhty32eRsKnnzS8n4c+L93g==", + "dependencies": [ + "discord-api-types@0.37.97" + ] + }, + "@discordjs/rest@2.4.0": { + "integrity": "sha512-Xb2irDqNcq+O8F0/k/NaDp7+t091p+acb51iA4bCKfIn+WFWd6HrNvcsSbMMxIR9NjcMZS6NReTKygqiQN+ntw==", + "dependencies": [ + "@discordjs/collection@2.1.1", + "@discordjs/util", + "@sapphire/async-queue", + "@sapphire/snowflake", + "@vladfrangu/async_event_emitter", + "discord-api-types@0.37.97", + "magic-bytes.js", + "tslib", + "undici" + ] + }, + "@discordjs/util@1.1.1": { + "integrity": "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==" + }, + "@discordjs/ws@1.1.1": { + "integrity": "sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==", + "dependencies": [ + "@discordjs/collection@2.1.1", + "@discordjs/rest", + "@discordjs/util", + "@sapphire/async-queue", + "@types/ws", + "@vladfrangu/async_event_emitter", + "discord-api-types@0.37.83", + "tslib", + "ws" + ] + }, + "@sapphire/async-queue@1.5.4": { + "integrity": "sha512-id65RxAx34DCk8KAVTPWwcephJSkStiS9M15F87+zvK2gK47wf7yeRIo8WiuKeXQS6bsyo/uQ/t0QW1cLmSb+A==" + }, + "@sapphire/shapeshift@4.0.0": { + "integrity": "sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==", + "dependencies": [ + "fast-deep-equal", + "lodash" + ] + }, + "@sapphire/snowflake@3.5.3": { + "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==" + }, + "@types/node@22.5.4": { + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dependencies": [ + "undici-types" + ] + }, + "@types/ws@8.5.13": { + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "dependencies": [ + "@types/node" + ] + }, + "@vladfrangu/async_event_emitter@2.4.6": { + "integrity": "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==" + }, + "discord-api-types@0.37.100": { + "integrity": "sha512-a8zvUI0GYYwDtScfRd/TtaNBDTXwP5DiDVX7K5OmE+DRT57gBqKnwtOC5Ol8z0mRW8KQfETIgiB8U0YZ9NXiCA==" + }, + "discord-api-types@0.37.83": { + "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==" + }, + "discord-api-types@0.37.97": { + "integrity": "sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA==" + }, + "discord.js@14.16.3": { + "integrity": "sha512-EPCWE9OkA9DnFFNrO7Kl1WHHDYFXu3CNVFJg63bfU7hVtjZGyhShwZtSBImINQRWxWP2tgo2XI+QhdXx28r0aA==", + "dependencies": [ + "@discordjs/builders", + "@discordjs/collection@1.5.3", + "@discordjs/formatters", + "@discordjs/rest", + "@discordjs/util", + "@discordjs/ws", + "@sapphire/snowflake", + "discord-api-types@0.37.100", + "fast-deep-equal", + "lodash.snakecase", + "tslib", + "undici" + ] + }, + "fast-deep-equal@3.1.3": { + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "lodash.snakecase@4.1.1": { + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" + }, + "lodash@4.17.21": { + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "magic-bytes.js@1.10.0": { + "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==" + }, + "ts-mixer@6.0.4": { + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==" + }, + "tslib@2.8.1": { + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "undici-types@6.19.8": { + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "undici@6.19.8": { + "integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==" + }, + "ws@8.18.0": { + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==" + } + }, + "workspace": { + "dependencies": [ + "npm:discord.js@^14.16.3" + ] + } +} diff --git a/nodemon.json b/nodemon.json deleted file mode 100644 index 1f316f7..0000000 --- a/nodemon.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "restartable": "rs", - "ignore": ["node_modules/"], - "watch": ["src/"], - "execMap": { - "ts": "node -r ts-node/register" - }, - "env": { - "NODE_ENV": "development" - }, - "ext": "js,json,ts" -} diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 83cb157..0000000 --- a/package-lock.json +++ /dev/null @@ -1,3747 +0,0 @@ -{ - "name": "discord-bot-template", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "discord-bot-template", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "cross-env": "^7.0.3", - "discord.js": "^14.15.3", - "dotenv": "^16.4.5" - }, - "devDependencies": { - "@types/node": "^20.14.10", - "@typescript-eslint/eslint-plugin": "^7.16.0", - "@typescript-eslint/parser": "^7.16.0", - "eslint": "^8.56.0", - "nodemon": "^3.1.4", - "prettier": "^3.3.2", - "ts-node": "^10.9.2", - "typescript": "^5.5.3" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@discordjs/builders": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.8.2.tgz", - "integrity": "sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g==", - "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" - }, - "engines": { - "node": ">=16.11.0" - }, - "funding": { - "url": "https://github.com/discordjs/discord.js?sponsor" - } - }, - "node_modules/@discordjs/collection": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz", - "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==", - "engines": { - "node": ">=16.11.0" - } - }, - "node_modules/@discordjs/formatters": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.4.0.tgz", - "integrity": "sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==", - "dependencies": { - "discord-api-types": "0.37.83" - }, - "engines": { - "node": ">=16.11.0" - }, - "funding": { - "url": "https://github.com/discordjs/discord.js?sponsor" - } - }, - "node_modules/@discordjs/rest": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.3.0.tgz", - "integrity": "sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==", - "dependencies": { - "@discordjs/collection": "^2.1.0", - "@discordjs/util": "^1.1.0", - "@sapphire/async-queue": "^1.5.2", - "@sapphire/snowflake": "^3.5.3", - "@vladfrangu/async_event_emitter": "^2.2.4", - "discord-api-types": "0.37.83", - "magic-bytes.js": "^1.10.0", - "tslib": "^2.6.2", - "undici": "6.13.0" - }, - "engines": { - "node": ">=16.11.0" - }, - "funding": { - "url": "https://github.com/discordjs/discord.js?sponsor" - } - }, - "node_modules/@discordjs/rest/node_modules/@discordjs/collection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", - "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/discordjs/discord.js?sponsor" - } - }, - "node_modules/@discordjs/util": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.0.tgz", - "integrity": "sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==", - "engines": { - "node": ">=16.11.0" - }, - "funding": { - "url": "https://github.com/discordjs/discord.js?sponsor" - } - }, - "node_modules/@discordjs/ws": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.1.1.tgz", - "integrity": "sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==", - "dependencies": { - "@discordjs/collection": "^2.1.0", - "@discordjs/rest": "^2.3.0", - "@discordjs/util": "^1.1.0", - "@sapphire/async-queue": "^1.5.2", - "@types/ws": "^8.5.10", - "@vladfrangu/async_event_emitter": "^2.2.4", - "discord-api-types": "0.37.83", - "tslib": "^2.6.2", - "ws": "^8.16.0" - }, - "engines": { - "node": ">=16.11.0" - }, - "funding": { - "url": "https://github.com/discordjs/discord.js?sponsor" - } - }, - "node_modules/@discordjs/ws/node_modules/@discordjs/collection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", - "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/discordjs/discord.js?sponsor" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@sapphire/async-queue": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.2.tgz", - "integrity": "sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg==", - "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@sapphire/shapeshift": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.7.tgz", - "integrity": "sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "lodash": "^4.17.21" - }, - "engines": { - "node": ">=v16" - } - }, - "node_modules/@sapphire/snowflake": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz", - "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==", - "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@vladfrangu/async_event_emitter": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.3.tgz", - "integrity": "sha512-wn15EJHUk2RDtCw6wVJndUhFbfJYwyNhSD9s+yiQi5c2MmXDy3KLWvZ5LrcOzt3CHdscoAnaJrxIRKBI1QQgGw==", - "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", - "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/discord-api-types": { - "version": "0.37.83", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz", - "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==" - }, - "node_modules/discord.js": { - "version": "14.15.3", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.15.3.tgz", - "integrity": "sha512-/UJDQO10VuU6wQPglA4kz2bw2ngeeSbogiIPx/TsnctfzV/tNf+q+i1HlgtX1OGpeOBpJH9erZQNO5oRM2uAtQ==", - "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" - }, - "engines": { - "node": ">=16.11.0" - }, - "funding": { - "url": "https://github.com/discordjs/discord.js?sponsor" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "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.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" - }, - "node_modules/magic-bytes.js": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz", - "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==" - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/nodemon": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", - "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^4", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^7.5.3", - "simple-update-notifier": "^2.0.0", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "dependencies": { - "nopt": "~1.0.10" - }, - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-mixer": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", - "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==" - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "node_modules/undici": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.13.0.tgz", - "integrity": "sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==", - "engines": { - "node": ">=18.0" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "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 - } - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - } - }, - "@discordjs/builders": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.8.2.tgz", - "integrity": "sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g==", - "requires": { - "@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": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz", - "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==" - }, - "@discordjs/formatters": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.4.0.tgz", - "integrity": "sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==", - "requires": { - "discord-api-types": "0.37.83" - } - }, - "@discordjs/rest": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.3.0.tgz", - "integrity": "sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==", - "requires": { - "@discordjs/collection": "^2.1.0", - "@discordjs/util": "^1.1.0", - "@sapphire/async-queue": "^1.5.2", - "@sapphire/snowflake": "^3.5.3", - "@vladfrangu/async_event_emitter": "^2.2.4", - "discord-api-types": "0.37.83", - "magic-bytes.js": "^1.10.0", - "tslib": "^2.6.2", - "undici": "6.13.0" - }, - "dependencies": { - "@discordjs/collection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", - "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==" - } - } - }, - "@discordjs/util": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.0.tgz", - "integrity": "sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==" - }, - "@discordjs/ws": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.1.1.tgz", - "integrity": "sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==", - "requires": { - "@discordjs/collection": "^2.1.0", - "@discordjs/rest": "^2.3.0", - "@discordjs/util": "^1.1.0", - "@sapphire/async-queue": "^1.5.2", - "@types/ws": "^8.5.10", - "@vladfrangu/async_event_emitter": "^2.2.4", - "discord-api-types": "0.37.83", - "tslib": "^2.6.2", - "ws": "^8.16.0" - }, - "dependencies": { - "@discordjs/collection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz", - "integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==" - } - } - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@sapphire/async-queue": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.2.tgz", - "integrity": "sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg==" - }, - "@sapphire/shapeshift": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.7.tgz", - "integrity": "sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==", - "requires": { - "fast-deep-equal": "^3.1.3", - "lodash": "^4.17.21" - } - }, - "@sapphire/snowflake": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz", - "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==" - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true - }, - "@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", - "requires": { - "undici-types": "~5.26.4" - } - }, - "@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "requires": { - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.16.0", - "eslint-visitor-keys": "^3.4.3" - } - }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "@vladfrangu/async_event_emitter": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.3.tgz", - "integrity": "sha512-wn15EJHUk2RDtCw6wVJndUhFbfJYwyNhSD9s+yiQi5c2MmXDy3KLWvZ5LrcOzt3CHdscoAnaJrxIRKBI1QQgGw==" - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "acorn": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", - "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "requires": { - "fill-range": "^7.1.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "requires": { - "cross-spawn": "^7.0.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "discord-api-types": { - "version": "0.37.83", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz", - "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==" - }, - "discord.js": { - "version": "14.15.3", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.15.3.tgz", - "integrity": "sha512-/UJDQO10VuU6wQPglA4kz2bw2ngeeSbogiIPx/TsnctfzV/tNf+q+i1HlgtX1OGpeOBpJH9erZQNO5oRM2uAtQ==", - "requires": { - "@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" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "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.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - } - } - }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "requires": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true - }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" - }, - "magic-bytes.js": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz", - "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==" - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, - "requires": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "nodemon": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", - "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", - "dev": true, - "requires": { - "chokidar": "^3.5.2", - "debug": "^4", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^7.5.3", - "simple-update-notifier": "^2.0.0", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - } - }, - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", - "dev": true - }, - "pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "requires": { - "semver": "^7.5.3" - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "requires": { - "nopt": "~1.0.10" - } - }, - "ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "requires": {} - }, - "ts-mixer": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", - "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==" - }, - "ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "dev": true - }, - "undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "undici": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.13.0.tgz", - "integrity": "sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==" - }, - "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "requires": {} - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 9211a05..0000000 --- a/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "discord-bot-template", - "version": "1.0.0", - "description": "Discord bot created from a TypeScript template", - "main": "dist/index.js", - "scripts": { - "build": "tsc", - "start": "node .", - "dev": "nodemon --config nodemon.json src/index.ts", - "deploy": "cross-env IS_SCRIPT=true ts-node src/scripts/deploy", - "deploy:prod": "cross-env NODE_ENV=production npm run deploy", - "clear": "cross-env IS_SCRIPT=true ts-node src/scripts/clear", - "format": "prettier --write ./src", - "format:check": "prettier --check ./src" - }, - "keywords": [], - "author": "", - "license": "MIT", - "devDependencies": { - "@types/node": "^20.14.10", - "@typescript-eslint/eslint-plugin": "^7.16.0", - "@typescript-eslint/parser": "^7.16.0", - "eslint": "^8.56.0", - "nodemon": "^3.1.4", - "prettier": "^3.3.2", - "ts-node": "^10.9.2", - "typescript": "^5.5.3" - }, - "dependencies": { - "cross-env": "^7.0.3", - "discord.js": "^14.15.3", - "dotenv": "^16.4.5" - } -} diff --git a/src/client/index.ts b/src/client/index.ts index b57e4a2..61c29d0 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1,13 +1,14 @@ -import { Client, GatewayIntentBits } from 'discord.js'; -import { log } from '../utils'; -import { ENV } from '../env'; +import process from "node:process"; +import { Client, GatewayIntentBits } from "discord.js"; +import { log } from "utils"; +import ENV from "env"; const client = new Client({ intents: [GatewayIntentBits.Guilds], }); client.login(ENV.BOT_TOKEN).catch((err) => { - log.error('login', err); + log.error("login", err); process.exit(1); }); diff --git a/src/commands/debug/index.ts b/src/commands/debug/index.ts index bcefe36..05c347c 100644 --- a/src/commands/debug/index.ts +++ b/src/commands/debug/index.ts @@ -1,7 +1,7 @@ -import { category } from '../../utils'; -import ping from './ping'; +import { category } from "utils"; +import ping from "./ping.ts"; export default category( - { name: 'Debug', description: 'Commands used for debugging.', emoji: '🐛' }, + { name: "Debug", description: "Commands used for debugging.", emoji: "🐛" }, [ping] ); diff --git a/src/commands/debug/ping.ts b/src/commands/debug/ping.ts index 623e0a7..2abb65c 100644 --- a/src/commands/debug/ping.ts +++ b/src/commands/debug/ping.ts @@ -1,13 +1,13 @@ -import { SlashCommandBuilder } from 'discord.js'; -import { command, reply } from '../../utils'; +import { SlashCommandBuilder } from "discord.js"; +import { command, reply } from "utils"; const meta = new SlashCommandBuilder() - .setName('ping') - .setDescription('Ping the bot for a response.') + .setName("ping") + .setDescription("Ping the bot for a response.") .addStringOption((option) => option - .setName('message') - .setDescription('Provide the bot a message to respond with.') + .setName("message") + .setDescription("Provide the bot a message to respond with.") .setMinLength(1) .setMaxLength(2000) .setRequired(false) @@ -17,11 +17,11 @@ export default command({ meta, private: true, exec: async ({ client, interaction }) => { - const message = interaction.options.getString('message'); + const message = interaction.options.getString("message"); await reply(interaction, { ephemeral: true, - content: `${message ?? 'Pong!'} (${client.ws.ping}ms)`, + content: `${message ?? "Pong!"} (${client.ws.ping}ms)`, }); }, }); diff --git a/src/commands/general/help.ts b/src/commands/general/help.ts index caea298..f292c3b 100644 --- a/src/commands/general/help.ts +++ b/src/commands/general/help.ts @@ -1,25 +1,25 @@ -import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; -import { command, helpSelectComponent, reply } from '../../utils'; -import { COLORS } from '../../constants'; +import { EmbedBuilder, SlashCommandBuilder } from "discord.js"; +import { command, helpSelectComponent, reply } from "utils"; +import { COLORS } from "utils"; const meta = new SlashCommandBuilder() - .setName('help') - .setDescription('Get a list of all commands for the bot.'); + .setName("help") + .setDescription("Get a list of all commands for the bot."); export default command({ meta, exec: async ({ interaction }) => { const embed = new EmbedBuilder() - .setTitle('Help Menu') + .setTitle("Help Menu") .setDescription( - 'Browse through all available commands by selecting a category below.' + "Browse through all available commands by selecting a category below." ) .setColor(COLORS.embed); const helpSelectMenu = helpSelectComponent(interaction); if (!helpSelectMenu) { embed.setDescription( - 'There are no commands available for you to use in this server.' + "There are no commands available for you to use in this server." ); return await reply(interaction, { embeds: [embed], diff --git a/src/commands/general/index.ts b/src/commands/general/index.ts index ae55fa2..53a6e84 100644 --- a/src/commands/general/index.ts +++ b/src/commands/general/index.ts @@ -1,12 +1,12 @@ -import { category } from '../../utils'; -import help from './help'; -import info from './info'; +import { category } from "utils"; +import help from "./help.ts"; +import info from "./info.ts"; export default category( { - name: 'General', - description: 'General bot commands.', - emoji: '📖', + name: "General", + description: "General bot commands.", + emoji: "📖", }, [help, info] ); diff --git a/src/commands/general/info.ts b/src/commands/general/info.ts index 6637116..7153a82 100644 --- a/src/commands/general/info.ts +++ b/src/commands/general/info.ts @@ -2,32 +2,31 @@ import { EmbedBuilder, SlashCommandBuilder, SlashCommandSubcommandBuilder, -} from 'discord.js'; -import { command, formatDate, reply } from '../../utils'; -import { COLORS } from '../../constants'; -import { CommandContext } from '../../types'; +} from "discord.js"; +import { command, formatDate, reply, COLORS } from "utils"; +import { CommandContext } from "types"; const server = new SlashCommandSubcommandBuilder() - .setName('server') - .setDescription('Get some info about this server.'); + .setName("server") + .setDescription("Get some info about this server."); const bot = new SlashCommandSubcommandBuilder() - .setName('bot') - .setDescription('Get some info about this bot.'); + .setName("bot") + .setDescription("Get some info about this bot."); const user = new SlashCommandSubcommandBuilder() - .setName('user') - .setDescription('Get some info about a user.') + .setName("user") + .setDescription("Get some info about a user.") .addUserOption((option) => option - .setName('user') - .setDescription('The user to get info about.') + .setName("user") + .setDescription("The user to get info about.") .setRequired(true) ); const meta = new SlashCommandBuilder() - .setName('info') - .setDescription('Get some info about various things.') + .setName("info") + .setDescription("Get some info about various things.") .addSubcommand(server) .addSubcommand(bot) .addSubcommand(user); @@ -38,11 +37,11 @@ export default command({ await interaction.deferReply({ ephemeral: true }); switch (interaction.options.getSubcommand()) { - case 'server': + case "server": return await getServerInfo({ interaction, ...ctx }); - case 'bot': + case "bot": return await getBotInfo({ interaction, ...ctx }); - case 'user': + case "user": return await getUserInfo({ interaction, ...ctx }); } }, @@ -53,41 +52,41 @@ const getServerInfo = async ({ interaction }: CommandContext) => { const channels = await interaction.guild?.channels.fetch(); const embed = new EmbedBuilder() - .setTitle('Server Info') + .setTitle("Server Info") .setDescription(`Info about ***${interaction.guild?.name}***`) .setColor(COLORS.embed) .setThumbnail(interaction.guild?.iconURL() ?? null) .setFields([ { - name: 'Guild ID', - value: interaction.guildId ?? 'Unknown', + name: "Guild ID", + value: interaction.guildId ?? "Unknown", inline: false, }, { - name: 'Owner', - value: owner?.user.username ?? 'Unknown', + name: "Owner", + value: owner?.user.username ?? "Unknown", inline: true, }, { - name: 'Created', + name: "Created", value: interaction.guild ? formatDate(interaction.guild?.createdAt) - : 'Unknown', + : "Unknown", inline: true, }, { - name: 'Members', - value: interaction.guild?.memberCount?.toString() ?? 'Unknown', + name: "Members", + value: interaction.guild?.memberCount?.toString() ?? "Unknown", inline: true, }, { - name: 'Channels', - value: channels?.size?.toString() ?? 'Unknown', + name: "Channels", + value: channels?.size?.toString() ?? "Unknown", inline: true, }, { - name: 'Roles', - value: interaction.guild?.roles.cache.size?.toString() ?? 'Unknown', + name: "Roles", + value: interaction.guild?.roles.cache.size?.toString() ?? "Unknown", inline: true, }, ]); @@ -97,24 +96,24 @@ const getServerInfo = async ({ interaction }: CommandContext) => { const getBotInfo = async ({ interaction }: CommandContext) => { const embed = new EmbedBuilder() - .setTitle('Bot Info') + .setTitle("Bot Info") .setDescription(`Info about ***${interaction.client.user?.username}***`) .setColor(COLORS.embed) .setThumbnail(interaction.client.user?.avatarURL() ?? null) .setFields([ { - name: 'Bot ID', - value: interaction.client.user?.id ?? 'Unknown', + name: "Bot ID", + value: interaction.client.user?.id ?? "Unknown", inline: false, }, { - name: 'Created', - value: formatDate(interaction.client.user?.createdAt) ?? 'Unknown', + name: "Created", + value: formatDate(interaction.client.user?.createdAt) ?? "Unknown", inline: true, }, { - name: 'Guilds', - value: interaction.client.guilds.cache.size?.toString() ?? 'Unknown', + name: "Guilds", + value: interaction.client.guilds.cache.size?.toString() ?? "Unknown", inline: true, }, ]); @@ -123,30 +122,30 @@ const getBotInfo = async ({ interaction }: CommandContext) => { }; const getUserInfo = async ({ interaction }: CommandContext) => { - const user = interaction.options.getUser('user', true); + const user = interaction.options.getUser("user", true); const member = await interaction.guild?.members.fetch(user.id); - if (!member) reply.error(interaction, { content: 'User not found' }); + if (!member) reply.error(interaction, { content: "User not found" }); const embed = new EmbedBuilder() - .setTitle('User Info') + .setTitle("User Info") .setDescription(`Info about ***${user.username}***`) .setColor(COLORS.embed) - .setThumbnail(user.avatarURL() ?? '') + .setThumbnail(user.avatarURL() ?? "") .setFields([ { - name: 'User ID', - value: user.id ?? 'Unknown', + name: "User ID", + value: user.id ?? "Unknown", inline: false, }, { - name: 'Created', - value: formatDate(user.createdAt) ?? 'Unknown', + name: "Created", + value: formatDate(user.createdAt) ?? "Unknown", inline: true, }, { - name: 'Joined', + name: "Joined", value: - member && member.joinedAt ? formatDate(member.joinedAt) : 'Unknown', + member && member.joinedAt ? formatDate(member.joinedAt) : "Unknown", inline: true, }, ]); diff --git a/src/commands/index.ts b/src/commands/index.ts index 11eba4f..6cfbb89 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -1,4 +1,4 @@ -import debug from './debug'; -import general from './general'; +import debug from "./debug/index.ts"; +import general from "./general/index.ts"; export default [debug, general]; diff --git a/src/constants/index.ts b/src/constants/index.ts deleted file mode 100644 index 7c8fff2..0000000 --- a/src/constants/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './namespaces'; -export * from './style'; diff --git a/src/constants/namespaces.ts b/src/constants/namespaces.ts deleted file mode 100644 index 0bc1deb..0000000 --- a/src/constants/namespaces.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const NAMESPACES = { - pagination: 'pagination', - help: 'help', -}; diff --git a/src/constants/style.ts b/src/constants/style.ts deleted file mode 100644 index c2a4112..0000000 --- a/src/constants/style.ts +++ /dev/null @@ -1,13 +0,0 @@ -export const COLORS = { - error: '#f54242', - warn: '#f5a742', - embed: '#2b2d31', -} as const; - -export const EMOJIS = { - success: '✅', - error: '❌', - warn: '⚠️', - deny: '🚫', - wait: '⏳', -} as const; diff --git a/src/env.ts b/src/env.ts index fee653e..426d0b1 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,10 +1,11 @@ -import { log } from './utils'; +import process from "node:process"; +import { log } from "utils"; const isDev = - process.env.NODE_ENV !== 'production' && - process.env.NODE_ENV !== 'PRODUCTION'; + process.env.NODE_ENV !== "production" && + process.env.NODE_ENV !== "PRODUCTION"; -export const ENV = { +const ENV = { /** Whether or not the app is running in the development environment */ DEV: isDev, /** @@ -15,15 +16,17 @@ export const ENV = { BOT_TOKEN: (isDev ? process.env.TEST_TOKEN : process.env.BOT_TOKEN) ?? process.env.BOT_TOKEN ?? - '', + "", /** ID of the Discord guild to use for testing */ TEST_GUILD: process.env.TEST_GUILD ?? null, } as const; // Check to make sure no environment variables are missing for (const [key, value] of Object.entries(ENV)) { - if (value === undefined || value === '') { - log.error('env', `Missing environment variable: ${key}`); + if (value === undefined || value === "") { + log.error("env", `Missing environment variable: ${key}`); process.exit(1); } } + +export default ENV; diff --git a/src/events/index.ts b/src/events/index.ts index 901a28e..d61ddfc 100644 --- a/src/events/index.ts +++ b/src/events/index.ts @@ -1,5 +1,5 @@ -import ready from './ready'; -import interactionCreate from './interactionCreate'; +import ready from "./ready.ts"; +import interactionCreate from "./interactionCreate/index.ts"; const events = [...interactionCreate, ready]; diff --git a/src/events/interactionCreate/commands.ts b/src/events/interactionCreate/commands.ts index 5543299..52d6846 100644 --- a/src/events/interactionCreate/commands.ts +++ b/src/events/interactionCreate/commands.ts @@ -2,10 +2,10 @@ import { CommandInteraction, GuildMember, PermissionFlagsBits, -} from 'discord.js'; -import categories from '../../commands'; -import { Command, CommandOptions } from '../../types'; -import { event, Logger, reply } from '../../utils'; +} from "discord.js"; +import categories from "commands"; +import { Command, CommandOptions } from "types"; +import { event, Logger, reply } from "utils"; const commands = new Map<string, Command>( categories @@ -16,14 +16,14 @@ const commands = new Map<string, Command>( const cooldowns = new Map<string, Map<string, number>>(); -export default event('interactionCreate', async ({ client }, interaction) => { +export default event("interactionCreate", async ({ client }, interaction) => { if (interaction.isChatInputCommand()) { const logger = new Logger(`/${interaction.commandName}`); const command = commands.get(interaction.commandName); if (!command) { logger.error(`Command ${interaction.commandName} not found.`); - return await reply.error(interaction, 'Command not found.'); + return await reply.error(interaction, "Command not found."); } const { adminOnly, cooldown } = command.options; @@ -64,14 +64,14 @@ export default event('interactionCreate', async ({ client }, interaction) => { }); const checkCooldown = ( - cooldown: CommandOptions['cooldown'], + cooldown: CommandOptions["cooldown"], interaction: CommandInteraction, isAdmin: boolean ) => { if (!cooldown) return null; - const seconds = typeof cooldown === 'number' ? cooldown : cooldown.seconds; - const scope = typeof cooldown === 'number' ? 'user' : cooldown.scope; + const seconds = typeof cooldown === "number" ? cooldown : cooldown.seconds; + const scope = typeof cooldown === "number" ? "user" : cooldown.scope; if (!interaction.guildId) return null; @@ -80,7 +80,7 @@ const checkCooldown = ( cooldowns.get(interaction.commandName) ?? new Map<string, number>(); const timestamp = timestamps.get( - scope === 'user' ? interaction.user.id : interaction.guildId + scope === "user" ? interaction.user.id : interaction.guildId ) ?? 0; const cooldownEnd = timestamp + seconds * 1000; @@ -88,7 +88,7 @@ const checkCooldown = ( return `Command will be available <t:${Math.floor(cooldownEnd / 1000)}:R>.`; timestamps.set( - scope === 'user' ? interaction.user.id : interaction.guildId, + scope === "user" ? interaction.user.id : interaction.guildId, now ); diff --git a/src/events/interactionCreate/help.ts b/src/events/interactionCreate/help.ts index 53f36ab..634c6b9 100644 --- a/src/events/interactionCreate/help.ts +++ b/src/events/interactionCreate/help.ts @@ -1,7 +1,6 @@ -import { event, paginationReply, parseId } from '../../utils'; -import { NAMESPACES } from '../../constants'; +import { event, paginationReply, parseId, NAMESPACES } from "utils"; -export default event('interactionCreate', async (ctx, interaction) => { +export default event("interactionCreate", async (ctx, interaction) => { if (!interaction.isStringSelectMenu()) return; const [namespace] = parseId(interaction.customId); if (namespace !== NAMESPACES.help) return; diff --git a/src/events/interactionCreate/index.ts b/src/events/interactionCreate/index.ts index 8464d40..cb281e7 100644 --- a/src/events/interactionCreate/index.ts +++ b/src/events/interactionCreate/index.ts @@ -1,6 +1,6 @@ -import commands from './commands'; -import help from './help'; -import pagination from './pagination'; +import commands from "./commands.ts"; +import help from "./help.ts"; +import pagination from "./pagination.ts"; const events = [commands, help, pagination]; diff --git a/src/events/interactionCreate/pagination.ts b/src/events/interactionCreate/pagination.ts index 4d6d4d2..5c90d63 100644 --- a/src/events/interactionCreate/pagination.ts +++ b/src/events/interactionCreate/pagination.ts @@ -1,7 +1,6 @@ -import { createId, event, generatePage, parseId } from '../../utils'; -import { NAMESPACES } from '../../constants'; +import { createId, event, generatePage, parseId, NAMESPACES } from "utils"; -export default event('interactionCreate', async (ctx, interaction) => { +export default event("interactionCreate", async (ctx, interaction) => { if (!interaction.isButton() && !interaction.isStringSelectMenu()) return; const [namespace, paginatorName] = parseId(interaction.customId); if (namespace !== NAMESPACES.pagination) return; diff --git a/src/events/ready.ts b/src/events/ready.ts index e3aac7f..45ae089 100644 --- a/src/events/ready.ts +++ b/src/events/ready.ts @@ -1,6 +1,6 @@ -import { event } from '../utils'; +import { event } from "utils"; -export default event('ready', ({ logger }, client) => { +export default event("ready", ({ logger }, client) => { logger.system( `\x1b[4m${client.user.tag}\x1b[0m\x1b[36m is up and ready to go!` ); diff --git a/src/index.ts b/src/index.ts index e4aef4a..8a65457 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,5 @@ -import 'dotenv/config'; -import client from './client'; -import { registerEvents } from './utils'; -import events from './events'; +import client from "client"; +import { registerEvents } from "utils"; +import events from "./events/index.ts"; registerEvents(client, events); diff --git a/src/scripts/clear.ts b/src/scripts/clear.ts index 132f6b2..5ce3351 100644 --- a/src/scripts/clear.ts +++ b/src/scripts/clear.ts @@ -1,14 +1,13 @@ -import 'dotenv/config'; -import { REST, Routes, APIUser } from 'discord.js'; -import { ENV } from '../env'; -import { Logger } from '../utils'; +import { REST, Routes, APIUser } from "discord.js"; +import ENV from "env"; +import { Logger } from "utils"; -const rest = new REST({ version: '10' }).setToken(ENV.BOT_TOKEN); -const logger = new Logger('clear'); +const rest = new REST({ version: "10" }).setToken(ENV.BOT_TOKEN); +const logger = new Logger("clear"); async function main() { if (!ENV.TEST_GUILD) - throw new Error('Missing environment variable: TEST_GUILD'); + throw new Error("Missing environment variable: TEST_GUILD"); const currentUser = (await rest.get(Routes.user())) as APIUser; await rest.put(Routes.applicationCommands(currentUser.id), { body: [] }); diff --git a/src/scripts/deploy.ts b/src/scripts/deploy.ts index c6c49c8..2088a51 100644 --- a/src/scripts/deploy.ts +++ b/src/scripts/deploy.ts @@ -1,15 +1,14 @@ -import 'dotenv/config'; -import { REST, Routes, APIUser } from 'discord.js'; -import categories from '../commands'; -import { ENV } from '../env'; -import { Logger, extractMeta } from '../utils'; +import { REST, Routes, APIUser } from "discord.js"; +import categories from "commands"; +import ENV from "env"; +import { Logger, extractMeta } from "utils"; -const rest = new REST({ version: '10' }).setToken(ENV.BOT_TOKEN); -const logger = new Logger('deploy'); +const rest = new REST({ version: "10" }).setToken(ENV.BOT_TOKEN); +const logger = new Logger("deploy"); async function main() { if (!ENV.TEST_GUILD) - throw new Error('Missing environment variable: TEST_GUILD'); + throw new Error("Missing environment variable: TEST_GUILD"); const currentUser = (await rest.get(Routes.user())) as APIUser; // In development, all commands are deployed to the test guild. @@ -17,19 +16,19 @@ async function main() { await rest.put( Routes.applicationGuildCommands(currentUser.id, ENV.TEST_GUILD), { - body: extractMeta(categories, 'all'), + body: extractMeta(categories, "all"), } ); // In production, public commmands are deployed globally, and private commands // are deployed to the test guild. else { await rest.put(Routes.applicationCommands(currentUser.id), { - body: extractMeta(categories, 'public'), + body: extractMeta(categories, "public"), }); await rest.put( Routes.applicationGuildCommands(currentUser.id, ENV.TEST_GUILD), { - body: extractMeta(categories, 'private'), + body: extractMeta(categories, "private"), } ); } @@ -42,7 +41,7 @@ main() const tag = `${user.username}#${user.discriminator}`; logger.system( `Commands deployed for \x1b[4m${tag}\x1b[0m\x1b[36m${ - ENV.DEV ? ` in guild ${ENV.TEST_GUILD}` : '' + ENV.DEV ? ` in guild ${ENV.TEST_GUILD}` : "" }!` ); }) diff --git a/src/types/commands.ts b/src/types/commands.ts index 1f45ff3..9b4da0c 100644 --- a/src/types/commands.ts +++ b/src/types/commands.ts @@ -6,8 +6,8 @@ import { SlashCommandSubcommandsOnlyBuilder, AutocompleteInteraction, SlashCommandOptionsOnlyBuilder, -} from 'discord.js'; -import { BaseContext } from './context'; +} from "discord.js"; +import { BaseContext } from "./context.ts"; export interface CommandContext extends BaseContext { interaction: ChatInputCommandInteraction; @@ -52,7 +52,7 @@ export type CommandOptions = { * * `guild` - The cooldown will be on a per-guild basis. */ - scope?: 'user' | 'guild'; + scope?: "user" | "guild"; }; }; export type CommandExec = (ctx: CommandContext) => Awaitable<unknown>; @@ -61,7 +61,7 @@ export type CommandAutocomplete = ( ) => Awaitable<unknown>; export type CommandMeta = | SlashCommandBuilder - | Omit<SlashCommandBuilder, 'addSubcommand' | 'addSubcommandGroup'> + | Omit<SlashCommandBuilder, "addSubcommand" | "addSubcommandGroup"> | SlashCommandSubcommandsOnlyBuilder | SlashCommandOptionsOnlyBuilder; export interface Command { diff --git a/src/types/context.ts b/src/types/context.ts index be64c34..874ff64 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -1,5 +1,5 @@ -import { Client } from 'discord.js'; -import { Logger } from '../utils'; +import { Client } from "discord.js"; +import { Logger } from "utils"; export interface BaseContext { client: Client; diff --git a/src/types/events.ts b/src/types/events.ts index 7af2a15..b4073b5 100644 --- a/src/types/events.ts +++ b/src/types/events.ts @@ -1,5 +1,5 @@ -import { ClientEvents, Awaitable } from 'discord.js'; -import { BaseContext } from './context'; +import { ClientEvents, Awaitable } from "discord.js"; +import { BaseContext } from "./context.ts"; export interface EventContext extends BaseContext {} diff --git a/src/types/index.ts b/src/types/index.ts index ea1f014..7022e85 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,3 @@ -export * from './events'; -export * from './commands'; -export * from './pagination'; +export * from "./events.ts"; +export * from "./commands.ts"; +export * from "./pagination.ts"; diff --git a/src/types/pagination.ts b/src/types/pagination.ts index 3c71ac3..29aa85a 100644 --- a/src/types/pagination.ts +++ b/src/types/pagination.ts @@ -1,5 +1,5 @@ -import { APIEmbedField, BaseInteraction } from 'discord.js'; -import { BaseContext } from './context'; +import { APIEmbedField, BaseInteraction } from "discord.js"; +import { BaseContext } from "./context.ts"; export type PaginationData = APIEmbedField[]; diff --git a/src/utils/command.ts b/src/utils/command.ts index 44a5ce0..3ae2249 100644 --- a/src/utils/command.ts +++ b/src/utils/command.ts @@ -7,7 +7,7 @@ import { CommandExec, CommandMeta, CommandOptions, -} from '../types'; +} from "types"; export function command({ meta, diff --git a/src/utils/constants.ts b/src/utils/constants.ts new file mode 100644 index 0000000..b93585d --- /dev/null +++ b/src/utils/constants.ts @@ -0,0 +1,18 @@ +export const COLORS = { + error: "#f54242", + warn: "#f5a742", + embed: "#2b2d31", +} as const; + +export const EMOJIS = { + success: "✅", + error: "❌", + warn: "⚠️", + deny: "🚫", + wait: "⏳", +} as const; + +export const NAMESPACES = { + pagination: "pagination", + help: "help", +} as const; diff --git a/src/utils/event.ts b/src/utils/event.ts index 8fe79f6..29956fd 100644 --- a/src/utils/event.ts +++ b/src/utils/event.ts @@ -1,7 +1,7 @@ -import { Event, EventExec, EventKeys } from '../types'; -import { Client } from 'discord.js'; -import { Logger } from './logger'; -import { reply } from './replies'; +import { Event, EventExec, EventKeys } from "types"; +import { Client } from "discord.js"; +import { Logger } from "./logger.ts"; +import { reply } from "./replies.ts"; export function event<T extends EventKeys>( id: T, @@ -13,6 +13,7 @@ export function event<T extends EventKeys>( }; } +// deno-lint-ignore no-explicit-any export function registerEvents(client: Client, events: Event<any>[]): void { for (const event of events) client.on(event.id, async (...args) => { @@ -24,7 +25,7 @@ export function registerEvents(client: Client, events: Event<any>[]): void { } catch (error) { logger.error(error); // If the error is thrown in an interaction, reply to it - if (event.id === 'interactionCreate') + if (event.id === "interactionCreate") reply.error(args[0]).catch(console.error); } }); diff --git a/src/utils/help.ts b/src/utils/help.ts index 057f42f..65dd7ff 100644 --- a/src/utils/help.ts +++ b/src/utils/help.ts @@ -3,12 +3,12 @@ import { BaseInteraction, PermissionFlagsBits, StringSelectMenuBuilder, -} from 'discord.js'; -import { NAMESPACES } from '../constants'; -import { createId } from './interaction'; -import categories from '../commands'; -import { ENV } from '../env'; -import { CommandCategoryCommands } from '../types'; +} from "discord.js"; +import { NAMESPACES } from "utils"; +import { createId } from "./interaction.ts"; +import categories from "commands"; +import ENV from "env"; +import { CommandCategoryCommands } from "types"; /** * Filters categories to exclude ones that do not contain commands relevant to the user @@ -27,12 +27,12 @@ const filterCategories = ( /** Pre-filtered command categories */ const cats = { private: { - member: filterCategories('all'), - admin: filterCategories('all', true), + member: filterCategories("all"), + admin: filterCategories("all", true), }, public: { - member: filterCategories('public'), - admin: filterCategories('public', true), + member: filterCategories("public"), + admin: filterCategories("public", true), }, }; @@ -47,15 +47,15 @@ export const helpSelectComponent = ( const guildCats = interaction.guildId === ENV.TEST_GUILD ? cats.private : cats.public; - if (guildCats[isAdmin ? 'admin' : 'member'].length === 0) return null; + if (guildCats[isAdmin ? "admin" : "member"].length === 0) return null; return new ActionRowBuilder<StringSelectMenuBuilder>().addComponents( new StringSelectMenuBuilder() .setCustomId(createId(NAMESPACES.help)) - .setPlaceholder('Select a category...') + .setPlaceholder("Select a category...") .setMaxValues(1) .addOptions( - guildCats[isAdmin ? 'admin' : 'member'].map( + guildCats[isAdmin ? "admin" : "member"].map( ({ name, description, emoji }) => ({ label: name, description, diff --git a/src/utils/index.ts b/src/utils/index.ts index d57704b..6588080 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,11 +1,12 @@ -export * from './event'; -export * from './command'; -export * from './replies'; -export * from './chunk'; -export * from './interaction'; -export * from './logger'; -export * from './help'; -export * from './paginators'; -export * from './pagination'; -export * from './split'; -export * from './date'; +export * from "./event.ts"; +export * from "./command.ts"; +export * from "./replies.ts"; +export * from "./chunk.ts"; +export * from "./interaction.ts"; +export * from "./logger.ts"; +export * from "./help.ts"; +export * from "./paginators/index.ts"; +export * from "./pagination.ts"; +export * from "./split.ts"; +export * from "./date.ts"; +export * from "./constants.ts"; diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts index 88deaad..7876123 100644 --- a/src/utils/pagination.ts +++ b/src/utils/pagination.ts @@ -1,3 +1,4 @@ +import process from "node:process"; import { APIEmbed, ActionRowBuilder, @@ -6,11 +7,11 @@ import { EmbedBuilder, InteractionReplyOptions, StringSelectMenuBuilder, -} from 'discord.js'; -import { createId } from './interaction'; -import { COLORS, NAMESPACES } from '../constants'; -import { Logger } from './logger'; -import { PaginationContext, PaginationData } from '../types'; +} from "discord.js"; +import { createId } from "./interaction.ts"; +import { COLORS, NAMESPACES } from "utils"; +import { Logger } from "./logger.ts"; +import { PaginationContext, PaginationData } from "types"; export class Paginator { name: string; @@ -19,8 +20,8 @@ export class Paginator { * The fields and footer are automatically set by the paginator. */ embedData?: - | Omit<APIEmbed, 'fields' | 'footer'> - | ((ctx: PaginationContext) => Omit<APIEmbed, 'fields' | 'footer'>); + | Omit<APIEmbed, "fields" | "footer"> + | ((ctx: PaginationContext) => Omit<APIEmbed, "fields" | "footer">); /** * The reply to which the pagination embed and its controls are added. * If not specified, the reply is ephemeral by default. @@ -31,7 +32,7 @@ export class Paginator { /** The number of fields to display on a single page (max 25). */ pageLength: number; /** Asynchronous function to fetch the data for the paginator */ - getData: (ctx: PaginationContext) => Promise<PaginationData>; + getData: (ctx: PaginationContext) => PaginationData | Promise<PaginationData>; // #region Cache /** Whether or not to cache the fetched data */ @@ -93,7 +94,7 @@ export class Paginator { // (2 are already being used for back/next buttons and page selector) if ( replyOptions && - typeof replyOptions !== 'function' && + typeof replyOptions !== "function" && replyOptions.components && replyOptions.components.length > 3 ) { @@ -105,7 +106,7 @@ export class Paginator { // (1 is already being used for the pagination embed) if ( replyOptions && - typeof replyOptions !== 'function' && + typeof replyOptions !== "function" && replyOptions.embeds && replyOptions.embeds.length > 4 ) { @@ -176,7 +177,7 @@ export class Paginator { const pageCount = Math.ceil(data.length / this.pageLength); const embedData = this.embedData - ? typeof this.embedData === 'function' + ? typeof this.embedData === "function" ? this.embedData(ctx) : this.embedData : undefined; @@ -184,7 +185,7 @@ export class Paginator { .setFields(fields) .setColor(embedData?.color ?? COLORS.embed); - if (fields.length === 0) embed.setDescription('No results found!'); + if (fields.length === 0) embed.setDescription("No results found!"); else embed.setFooter({ text: `Page ${currentPage} / ${pageCount}`, @@ -198,7 +199,7 @@ export class Paginator { ); const backButton = new ButtonBuilder() .setCustomId(backId) - .setLabel('Back') + .setLabel("Back") .setStyle(ButtonStyle.Primary) .setDisabled(offset <= 0); @@ -210,14 +211,14 @@ export class Paginator { ); const nextButton = new ButtonBuilder() .setCustomId(nextId) - .setLabel('Next') + .setLabel("Next") .setStyle(ButtonStyle.Primary) .setDisabled(currentPage >= pageCount); const selectId = createId(NAMESPACES.pagination, this.name); const pageSelector = new StringSelectMenuBuilder() .setCustomId(selectId) - .setPlaceholder('Select a page...') + .setPlaceholder("Select a page...") .setMaxValues(1) .setOptions( Array.from(Array(pageCount).keys()).map((i) => ({ @@ -236,7 +237,7 @@ export class Paginator { ); const replyOptions = this.replyOptions - ? typeof this.replyOptions === 'function' + ? typeof this.replyOptions === "function" ? this.replyOptions(ctx) : this.replyOptions : undefined; diff --git a/src/utils/paginators/help.ts b/src/utils/paginators/help.ts index a74655e..e88402c 100644 --- a/src/utils/paginators/help.ts +++ b/src/utils/paginators/help.ts @@ -2,17 +2,17 @@ import { APIApplicationCommandOption, ApplicationCommandOptionType, PermissionFlagsBits, -} from 'discord.js'; -import categories from '../../commands'; +} from "discord.js"; +import categories from "commands"; import { Command, CommandCategoryCommands, CommandOptions, PaginationData, -} from '../../types'; -import { helpSelectComponent } from '../help'; -import { Paginator } from '../pagination'; -import { ENV } from '../../env'; +} from "types"; +import { helpSelectComponent } from "../help.ts"; +import { Paginator } from "../pagination.ts"; +import ENV from "env"; /** * Extracts subcommands from a command option recursively @@ -31,8 +31,8 @@ const extractSubcommandsRecursive = ( name: `/${name} ${option.name}`, value: ` ${option.description} - ${cmdOpts.adminOnly ? '🛡️ _admin only_' : ''}${ - cmdOpts.private ? `${cmdOpts.adminOnly ? '\n' : ''}🔒 _private_` : '' + ${cmdOpts.adminOnly ? "🛡️ _admin only_" : ""}${ + cmdOpts.private ? `${cmdOpts.adminOnly ? "\n" : ""}🔒 _private_` : "" } `, }); @@ -65,10 +65,10 @@ const getCommands = (command: Command): PaginationData => { name: `/${command.meta.name}`, value: ` ${command.meta.description} - ${command.options.adminOnly ? '🛡️ _admin only_' : ''}${ + ${command.options.adminOnly ? "🛡️ _admin only_" : ""}${ command.options.private - ? `${command.options.adminOnly ? '\n' : ''}🔒 _private_` - : '' + ? `${command.options.adminOnly ? "\n" : ""}🔒 _private_` + : "" } `, }); @@ -97,15 +97,15 @@ const helpPaginators: Paginator[] = // Separate commands into different categories depending on the guild and member that the command is used in/by const cmds = { private: { - member: filterCommands(category.commands, 'all'), - admin: filterCommands(category.commands, 'all', true), + member: filterCommands(category.commands, "all"), + admin: filterCommands(category.commands, "all", true), }, public: { - member: filterCommands(category.commands, 'public'), - admin: filterCommands(category.commands, 'public', true), + member: filterCommands(category.commands, "public"), + admin: filterCommands(category.commands, "public", true), }, }; - const emoji = category.emoji ? `${category.emoji} ` : ''; + const emoji = category.emoji ? `${category.emoji} ` : ""; return new Paginator(category.name, { embedData: { @@ -113,7 +113,7 @@ const helpPaginators: Paginator[] = description: category.description ?? `Browse through ${category.commands.public.length} command${ - category.commands.public.length > 1 ? 's' : '' + category.commands.public.length > 1 ? "s" : "" } in ${emoji}${category.name}`, }, replyOptions: ({ interaction }) => { @@ -123,7 +123,7 @@ const helpPaginators: Paginator[] = }; }, pageLength: 10, - getData: async ({ interaction }) => { + getData: ({ interaction }) => { const guildCmds = interaction.guildId === ENV.TEST_GUILD ? cmds.private : cmds.public; if ( diff --git a/src/utils/paginators/index.ts b/src/utils/paginators/index.ts index e4350fa..0228e2b 100644 --- a/src/utils/paginators/index.ts +++ b/src/utils/paginators/index.ts @@ -1,9 +1,9 @@ -import { InteractionReplyOptions } from 'discord.js'; -import { Paginator } from '../pagination'; -import helpPaginators from './help'; -import { createId, parseId } from '../interaction'; -import { NAMESPACES } from '../../constants'; -import { PaginationContext } from '../../types'; +import { InteractionReplyOptions } from "discord.js"; +import { Paginator } from "../pagination.ts"; +import helpPaginators from "./help.ts"; +import { createId, parseId } from "../interaction.ts"; +import { NAMESPACES } from "utils"; +import { PaginationContext } from "types"; // Add new paginators here const paginators: Paginator[] = [...helpPaginators /*, otherPaginator */]; @@ -17,7 +17,7 @@ const paginatorMap = new Map<string, Paginator>( * @param interactionId The interactionId to generate the page for * @returns The generated embed */ -export async function generatePage( +export function generatePage( interactionId: string, ctx: PaginationContext ): Promise<InteractionReplyOptions> { @@ -29,8 +29,8 @@ export async function generatePage( let offset = parseInt(offsetString); // Page selected from select menu - if (offsetString && offsetString.startsWith('select-')) { - let targetPage = parseInt(offsetString.split('-')[1]); + if (offsetString && offsetString.startsWith("select-")) { + let targetPage = parseInt(offsetString.split("-")[1]); if (isNaN(targetPage)) targetPage = 0; offset = targetPage * paginator.pageLength; } diff --git a/src/utils/replies.ts b/src/utils/replies.ts index 9660729..93da115 100644 --- a/src/utils/replies.ts +++ b/src/utils/replies.ts @@ -2,8 +2,8 @@ import { InteractionReplyOptions, InteractionEditReplyOptions, BaseInteraction, -} from 'discord.js'; -import { EMOJIS } from '../constants'; +} from "discord.js"; +import { EMOJIS } from "utils"; export interface DeferableInteraction extends BaseInteraction { deferred: boolean; @@ -13,12 +13,12 @@ export interface DeferableInteraction extends BaseInteraction { } export enum ReplyType { - Default = 'default', - Success = 'success', - Error = 'error', - Warn = 'warn', - Deny = 'deny', - Wait = 'wait', + Default = "default", + Success = "success", + Error = "error", + Warn = "warn", + Deny = "deny", + Wait = "wait", } /** @@ -31,11 +31,11 @@ const getOptions = ( options: InteractionReplyOptions | string, type: ReplyType ): InteractionReplyOptions => { - if (typeof options === 'string') + if (typeof options === "string") return getOptions({ content: options }, type); const { content, ephemeral } = options; - const emoji = type === ReplyType.Default ? '' : EMOJIS[type]; + const emoji = type === ReplyType.Default ? "" : EMOJIS[type]; return { ...options, @@ -57,17 +57,17 @@ export const reply = <T extends DeferableInteraction>( type: ReplyType = ReplyType.Default ) => { if (!interaction.reply || !interaction.editReply) - return Promise.reject('Invalid interaction'); + return Promise.reject("Invalid interaction"); if ( !options || - (typeof options === 'object' && + (typeof options === "object" && !options.content && !options.embeds && !options.files) ) - return Promise.reject('Cannot send an empty message'); + return Promise.reject("Cannot send an empty message"); - if (interaction.replied) return Promise.reject('Interaction already replied'); + if (interaction.replied) return Promise.reject("Interaction already replied"); const alteredOptions = getOptions(options, type); if (interaction.deferred) return interaction.editReply(alteredOptions); @@ -81,7 +81,7 @@ reply.success = <T extends DeferableInteraction>( reply.error = <T extends DeferableInteraction>( interaction: T, - options: InteractionReplyOptions | string = 'Oops. Something went wrong!' + options: InteractionReplyOptions | string = "Oops. Something went wrong!" ) => reply(interaction, options, ReplyType.Error); reply.warn = <T extends DeferableInteraction>( @@ -93,7 +93,7 @@ reply.deny = <T extends DeferableInteraction>( interaction: T, options: | InteractionReplyOptions - | string = 'You do not have permission to do that!' + | string = "You do not have permission to do that!" ) => reply(interaction, options, ReplyType.Deny); reply.wait = <T extends DeferableInteraction>( diff --git a/src/utils/split.ts b/src/utils/split.ts index fea765f..7554c04 100644 --- a/src/utils/split.ts +++ b/src/utils/split.ts @@ -1,5 +1,5 @@ -import { CommandInteraction, EmbedBuilder } from 'discord.js'; -import { COLORS } from '../constants'; +import { CommandInteraction, EmbedBuilder } from "discord.js"; +import { COLORS } from "utils"; /** The maximum character length of an embed to send */ const MAX_EMBED_LENGTH = 2048 as const; @@ -19,8 +19,10 @@ export async function splitSend( title: string, msg: string ) { - if (!interaction.channel) throw new Error('No channel found'); - if (interaction.replied) throw new Error('Interaction already replied'); + if (!interaction.channel) throw new Error("No channel found"); + if (!interaction.channel.isSendable()) + throw new Error("Channel is not sendable"); + if (interaction.replied) throw new Error("Interaction already replied"); if (!interaction.deferred) await interaction.deferReply(); // Split the input into multiple embed descriptions diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 7149c9c..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to learn about all posibilities for the tsconfig */ - "target": "ESNext", - "useDefineForClassFields": true, - "lib": ["ESNext"], - "outDir": "./dist", - "allowJs": false, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "CommonJS", - "moduleResolution": "Node", - "resolveJsonModule": true, - "isolatedModules": true - }, - "include": ["**/*.ts", "src"], - "exclude": ["node_modules", "dist"] -} From 83f1ba7afc64c1f7d8d7b71de349849add917fc3 Mon Sep 17 00:00:00 2001 From: Thijn <thijnkroon@gmail.com> Date: Thu, 7 Nov 2024 13:28:03 +0100 Subject: [PATCH 2/6] chore: run format --- .gitignore | 1 + deno.json | 6 +- src/client/index.ts | 10 +- src/commands/debug/index.ts | 8 +- src/commands/debug/ping.ts | 16 +-- src/commands/general/help.ts | 16 +-- src/commands/general/index.ts | 14 +-- src/commands/general/info.ts | 95 ++++++++-------- src/commands/index.ts | 4 +- src/env.ts | 18 ++- src/events/index.ts | 4 +- src/events/interactionCreate/commands.ts | 41 +++---- src/events/interactionCreate/help.ts | 6 +- src/events/interactionCreate/index.ts | 6 +- src/events/interactionCreate/pagination.ts | 11 +- src/events/ready.ts | 6 +- src/index.ts | 6 +- src/scripts/clear.ts | 17 +-- src/scripts/deploy.ts | 35 +++--- src/types/commands.ts | 44 ++++---- src/types/context.ts | 4 +- src/types/events.ts | 4 +- src/types/index.ts | 6 +- src/types/pagination.ts | 4 +- src/utils/chunk.ts | 3 +- src/utils/command.ts | 6 +- src/utils/constants.ts | 20 ++-- src/utils/date.ts | 8 +- src/utils/event.ts | 16 +-- src/utils/help.ts | 44 ++++---- src/utils/index.ts | 24 ++-- src/utils/logger.ts | 4 +- src/utils/pagination.ts | 67 +++++------ src/utils/paginators/help.ts | 122 +++++++++++---------- src/utils/paginators/index.ts | 20 ++-- src/utils/replies.ts | 53 ++++----- src/utils/split.ts | 20 ++-- 37 files changed, 405 insertions(+), 384 deletions(-) diff --git a/.gitignore b/.gitignore index 7889494..ef27776 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .env +.prettierrc.json /.vs/ /.vscode/ diff --git a/deno.json b/deno.json index 1a05525..7d40ae0 100644 --- a/deno.json +++ b/deno.json @@ -1,12 +1,12 @@ { "tasks": { - "dev": "deno run --watch --env-file --allow-net --allow-read src/index.ts", + "dev": "deno run --watch --env-file --allow-env --allow-net --allow-read src/index.ts", "check": "deno check src/index.ts", "lint": "deno lint --fix", "fmt": "deno fmt", "fmt:check": "deno fmt --check", - "deploy": "deno run --env-file --allow-net --allow-read src/scripts/deploy.ts", - "clear": "deno run --env-file --allow-net --allow-read src/scripts/clear.ts" + "deploy": "deno run --env-file --allow-env --allow-net --allow-read src/scripts/deploy.ts", + "clear": "deno run --env-file --allow-env --allow-net --allow-read src/scripts/clear.ts" }, "lint": { "include": ["src/"], diff --git a/src/client/index.ts b/src/client/index.ts index 61c29d0..5c69f8f 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1,14 +1,14 @@ -import process from "node:process"; -import { Client, GatewayIntentBits } from "discord.js"; -import { log } from "utils"; -import ENV from "env"; +import process from 'node:process'; +import { Client, GatewayIntentBits } from 'discord.js'; +import { log } from 'utils'; +import ENV from 'env'; const client = new Client({ intents: [GatewayIntentBits.Guilds], }); client.login(ENV.BOT_TOKEN).catch((err) => { - log.error("login", err); + log.error('login', err); process.exit(1); }); diff --git a/src/commands/debug/index.ts b/src/commands/debug/index.ts index 05c347c..f48e02c 100644 --- a/src/commands/debug/index.ts +++ b/src/commands/debug/index.ts @@ -1,7 +1,7 @@ -import { category } from "utils"; -import ping from "./ping.ts"; +import { category } from 'utils'; +import ping from './ping.ts'; export default category( - { name: "Debug", description: "Commands used for debugging.", emoji: "🐛" }, - [ping] + { name: 'Debug', description: 'Commands used for debugging.', emoji: '🐛' }, + [ping], ); diff --git a/src/commands/debug/ping.ts b/src/commands/debug/ping.ts index 2abb65c..94613aa 100644 --- a/src/commands/debug/ping.ts +++ b/src/commands/debug/ping.ts @@ -1,13 +1,13 @@ -import { SlashCommandBuilder } from "discord.js"; -import { command, reply } from "utils"; +import { SlashCommandBuilder } from 'discord.js'; +import { command, reply } from 'utils'; const meta = new SlashCommandBuilder() - .setName("ping") - .setDescription("Ping the bot for a response.") + .setName('ping') + .setDescription('Ping the bot for a response.') .addStringOption((option) => option - .setName("message") - .setDescription("Provide the bot a message to respond with.") + .setName('message') + .setDescription('Provide the bot a message to respond with.') .setMinLength(1) .setMaxLength(2000) .setRequired(false) @@ -17,11 +17,11 @@ export default command({ meta, private: true, exec: async ({ client, interaction }) => { - const message = interaction.options.getString("message"); + const message = interaction.options.getString('message'); await reply(interaction, { ephemeral: true, - content: `${message ?? "Pong!"} (${client.ws.ping}ms)`, + content: `${message ?? 'Pong!'} (${client.ws.ping}ms)`, }); }, }); diff --git a/src/commands/general/help.ts b/src/commands/general/help.ts index f292c3b..54595d4 100644 --- a/src/commands/general/help.ts +++ b/src/commands/general/help.ts @@ -1,25 +1,25 @@ -import { EmbedBuilder, SlashCommandBuilder } from "discord.js"; -import { command, helpSelectComponent, reply } from "utils"; -import { COLORS } from "utils"; +import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'; +import { command, helpSelectComponent, reply } from 'utils'; +import { COLORS } from 'utils'; const meta = new SlashCommandBuilder() - .setName("help") - .setDescription("Get a list of all commands for the bot."); + .setName('help') + .setDescription('Get a list of all commands for the bot.'); export default command({ meta, exec: async ({ interaction }) => { const embed = new EmbedBuilder() - .setTitle("Help Menu") + .setTitle('Help Menu') .setDescription( - "Browse through all available commands by selecting a category below." + 'Browse through all available commands by selecting a category below.', ) .setColor(COLORS.embed); const helpSelectMenu = helpSelectComponent(interaction); if (!helpSelectMenu) { embed.setDescription( - "There are no commands available for you to use in this server." + 'There are no commands available for you to use in this server.', ); return await reply(interaction, { embeds: [embed], diff --git a/src/commands/general/index.ts b/src/commands/general/index.ts index 53a6e84..f748999 100644 --- a/src/commands/general/index.ts +++ b/src/commands/general/index.ts @@ -1,12 +1,12 @@ -import { category } from "utils"; -import help from "./help.ts"; -import info from "./info.ts"; +import { category } from 'utils'; +import help from './help.ts'; +import info from './info.ts'; export default category( { - name: "General", - description: "General bot commands.", - emoji: "📖", + name: 'General', + description: 'General bot commands.', + emoji: '📖', }, - [help, info] + [help, info], ); diff --git a/src/commands/general/info.ts b/src/commands/general/info.ts index 7153a82..2df712e 100644 --- a/src/commands/general/info.ts +++ b/src/commands/general/info.ts @@ -2,31 +2,31 @@ import { EmbedBuilder, SlashCommandBuilder, SlashCommandSubcommandBuilder, -} from "discord.js"; -import { command, formatDate, reply, COLORS } from "utils"; -import { CommandContext } from "types"; +} from 'discord.js'; +import { COLORS, command, formatDate, reply } from 'utils'; +import { CommandContext } from 'types'; const server = new SlashCommandSubcommandBuilder() - .setName("server") - .setDescription("Get some info about this server."); + .setName('server') + .setDescription('Get some info about this server.'); const bot = new SlashCommandSubcommandBuilder() - .setName("bot") - .setDescription("Get some info about this bot."); + .setName('bot') + .setDescription('Get some info about this bot.'); const user = new SlashCommandSubcommandBuilder() - .setName("user") - .setDescription("Get some info about a user.") + .setName('user') + .setDescription('Get some info about a user.') .addUserOption((option) => option - .setName("user") - .setDescription("The user to get info about.") + .setName('user') + .setDescription('The user to get info about.') .setRequired(true) ); const meta = new SlashCommandBuilder() - .setName("info") - .setDescription("Get some info about various things.") + .setName('info') + .setDescription('Get some info about various things.') .addSubcommand(server) .addSubcommand(bot) .addSubcommand(user); @@ -37,11 +37,11 @@ export default command({ await interaction.deferReply({ ephemeral: true }); switch (interaction.options.getSubcommand()) { - case "server": + case 'server': return await getServerInfo({ interaction, ...ctx }); - case "bot": + case 'bot': return await getBotInfo({ interaction, ...ctx }); - case "user": + case 'user': return await getUserInfo({ interaction, ...ctx }); } }, @@ -52,41 +52,41 @@ const getServerInfo = async ({ interaction }: CommandContext) => { const channels = await interaction.guild?.channels.fetch(); const embed = new EmbedBuilder() - .setTitle("Server Info") + .setTitle('Server Info') .setDescription(`Info about ***${interaction.guild?.name}***`) .setColor(COLORS.embed) .setThumbnail(interaction.guild?.iconURL() ?? null) .setFields([ { - name: "Guild ID", - value: interaction.guildId ?? "Unknown", + name: 'Guild ID', + value: interaction.guildId ?? 'Unknown', inline: false, }, { - name: "Owner", - value: owner?.user.username ?? "Unknown", + name: 'Owner', + value: owner?.user.username ?? 'Unknown', inline: true, }, { - name: "Created", + name: 'Created', value: interaction.guild ? formatDate(interaction.guild?.createdAt) - : "Unknown", + : 'Unknown', inline: true, }, { - name: "Members", - value: interaction.guild?.memberCount?.toString() ?? "Unknown", + name: 'Members', + value: interaction.guild?.memberCount?.toString() ?? 'Unknown', inline: true, }, { - name: "Channels", - value: channels?.size?.toString() ?? "Unknown", + name: 'Channels', + value: channels?.size?.toString() ?? 'Unknown', inline: true, }, { - name: "Roles", - value: interaction.guild?.roles.cache.size?.toString() ?? "Unknown", + name: 'Roles', + value: interaction.guild?.roles.cache.size?.toString() ?? 'Unknown', inline: true, }, ]); @@ -96,24 +96,24 @@ const getServerInfo = async ({ interaction }: CommandContext) => { const getBotInfo = async ({ interaction }: CommandContext) => { const embed = new EmbedBuilder() - .setTitle("Bot Info") + .setTitle('Bot Info') .setDescription(`Info about ***${interaction.client.user?.username}***`) .setColor(COLORS.embed) .setThumbnail(interaction.client.user?.avatarURL() ?? null) .setFields([ { - name: "Bot ID", - value: interaction.client.user?.id ?? "Unknown", + name: 'Bot ID', + value: interaction.client.user?.id ?? 'Unknown', inline: false, }, { - name: "Created", - value: formatDate(interaction.client.user?.createdAt) ?? "Unknown", + name: 'Created', + value: formatDate(interaction.client.user?.createdAt) ?? 'Unknown', inline: true, }, { - name: "Guilds", - value: interaction.client.guilds.cache.size?.toString() ?? "Unknown", + name: 'Guilds', + value: interaction.client.guilds.cache.size?.toString() ?? 'Unknown', inline: true, }, ]); @@ -122,30 +122,31 @@ const getBotInfo = async ({ interaction }: CommandContext) => { }; const getUserInfo = async ({ interaction }: CommandContext) => { - const user = interaction.options.getUser("user", true); + const user = interaction.options.getUser('user', true); const member = await interaction.guild?.members.fetch(user.id); - if (!member) reply.error(interaction, { content: "User not found" }); + if (!member) reply.error(interaction, { content: 'User not found' }); const embed = new EmbedBuilder() - .setTitle("User Info") + .setTitle('User Info') .setDescription(`Info about ***${user.username}***`) .setColor(COLORS.embed) - .setThumbnail(user.avatarURL() ?? "") + .setThumbnail(user.avatarURL() ?? '') .setFields([ { - name: "User ID", - value: user.id ?? "Unknown", + name: 'User ID', + value: user.id ?? 'Unknown', inline: false, }, { - name: "Created", - value: formatDate(user.createdAt) ?? "Unknown", + name: 'Created', + value: formatDate(user.createdAt) ?? 'Unknown', inline: true, }, { - name: "Joined", - value: - member && member.joinedAt ? formatDate(member.joinedAt) : "Unknown", + name: 'Joined', + value: member && member.joinedAt + ? formatDate(member.joinedAt) + : 'Unknown', inline: true, }, ]); diff --git a/src/commands/index.ts b/src/commands/index.ts index 6cfbb89..1854824 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -1,4 +1,4 @@ -import debug from "./debug/index.ts"; -import general from "./general/index.ts"; +import debug from './debug/index.ts'; +import general from './general/index.ts'; export default [debug, general]; diff --git a/src/env.ts b/src/env.ts index 426d0b1..392fbcb 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,9 +1,8 @@ -import process from "node:process"; -import { log } from "utils"; +import process from 'node:process'; +import { log } from 'utils'; -const isDev = - process.env.NODE_ENV !== "production" && - process.env.NODE_ENV !== "PRODUCTION"; +const isDev = process.env.NODE_ENV !== 'production' && + process.env.NODE_ENV !== 'PRODUCTION'; const ENV = { /** Whether or not the app is running in the development environment */ @@ -13,18 +12,17 @@ const ENV = { * * If `DEV` is true, the `TEST_TOKEN` environment variable will be used instead (if it exists, otherwise `BOT_TOKEN` will still be used). */ - BOT_TOKEN: - (isDev ? process.env.TEST_TOKEN : process.env.BOT_TOKEN) ?? + BOT_TOKEN: (isDev ? process.env.TEST_TOKEN : process.env.BOT_TOKEN) ?? process.env.BOT_TOKEN ?? - "", + '', /** ID of the Discord guild to use for testing */ TEST_GUILD: process.env.TEST_GUILD ?? null, } as const; // Check to make sure no environment variables are missing for (const [key, value] of Object.entries(ENV)) { - if (value === undefined || value === "") { - log.error("env", `Missing environment variable: ${key}`); + if (value === undefined || value === '') { + log.error('env', `Missing environment variable: ${key}`); process.exit(1); } } diff --git a/src/events/index.ts b/src/events/index.ts index d61ddfc..5b9ae6e 100644 --- a/src/events/index.ts +++ b/src/events/index.ts @@ -1,5 +1,5 @@ -import ready from "./ready.ts"; -import interactionCreate from "./interactionCreate/index.ts"; +import ready from './ready.ts'; +import interactionCreate from './interactionCreate/index.ts'; const events = [...interactionCreate, ready]; diff --git a/src/events/interactionCreate/commands.ts b/src/events/interactionCreate/commands.ts index 52d6846..41d63af 100644 --- a/src/events/interactionCreate/commands.ts +++ b/src/events/interactionCreate/commands.ts @@ -2,33 +2,33 @@ import { CommandInteraction, GuildMember, PermissionFlagsBits, -} from "discord.js"; -import categories from "commands"; -import { Command, CommandOptions } from "types"; -import { event, Logger, reply } from "utils"; +} from 'discord.js'; +import categories from 'commands'; +import { Command, CommandOptions } from 'types'; +import { event, Logger, reply } from 'utils'; const commands = new Map<string, Command>( categories .map(({ commands }) => commands.all) .flat() - .map((c) => [c.meta.name, c]) + .map((c) => [c.meta.name, c]), ); const cooldowns = new Map<string, Map<string, number>>(); -export default event("interactionCreate", async ({ client }, interaction) => { +export default event('interactionCreate', async ({ client }, interaction) => { if (interaction.isChatInputCommand()) { const logger = new Logger(`/${interaction.commandName}`); const command = commands.get(interaction.commandName); if (!command) { logger.error(`Command ${interaction.commandName} not found.`); - return await reply.error(interaction, "Command not found."); + return await reply.error(interaction, 'Command not found.'); } const { adminOnly, cooldown } = command.options; const isAdmin = (interaction.member as GuildMember).permissions.has( - PermissionFlagsBits.Administrator + PermissionFlagsBits.Administrator, ); // If the command is marked as adminOnly, check if the user is an admin @@ -47,13 +47,15 @@ export default event("interactionCreate", async ({ client }, interaction) => { const logger = new Logger(`/${interaction.commandName}`); const command = commands.get(interaction.commandName); - if (!command) + if (!command) { return logger.error(`Command ${interaction.commandName} not found.`); + } - if (!command.autocomplete) + if (!command.autocomplete) { return logger.error( - `Missing autocomplete handler for ${interaction.commandName}.` + `Missing autocomplete handler for ${interaction.commandName}.`, ); + } await command.autocomplete({ client, @@ -64,14 +66,14 @@ export default event("interactionCreate", async ({ client }, interaction) => { }); const checkCooldown = ( - cooldown: CommandOptions["cooldown"], + cooldown: CommandOptions['cooldown'], interaction: CommandInteraction, - isAdmin: boolean + isAdmin: boolean, ) => { if (!cooldown) return null; - const seconds = typeof cooldown === "number" ? cooldown : cooldown.seconds; - const scope = typeof cooldown === "number" ? "user" : cooldown.scope; + const seconds = typeof cooldown === 'number' ? cooldown : cooldown.seconds; + const scope = typeof cooldown === 'number' ? 'user' : cooldown.scope; if (!interaction.guildId) return null; @@ -80,16 +82,17 @@ const checkCooldown = ( cooldowns.get(interaction.commandName) ?? new Map<string, number>(); const timestamp = timestamps.get( - scope === "user" ? interaction.user.id : interaction.guildId + scope === 'user' ? interaction.user.id : interaction.guildId, ) ?? 0; const cooldownEnd = timestamp + seconds * 1000; - if (now < cooldownEnd && !isAdmin) + if (now < cooldownEnd && !isAdmin) { return `Command will be available <t:${Math.floor(cooldownEnd / 1000)}:R>.`; + } timestamps.set( - scope === "user" ? interaction.user.id : interaction.guildId, - now + scope === 'user' ? interaction.user.id : interaction.guildId, + now, ); cooldowns.set(interaction.commandName, timestamps); diff --git a/src/events/interactionCreate/help.ts b/src/events/interactionCreate/help.ts index 634c6b9..1117cb2 100644 --- a/src/events/interactionCreate/help.ts +++ b/src/events/interactionCreate/help.ts @@ -1,6 +1,6 @@ -import { event, paginationReply, parseId, NAMESPACES } from "utils"; +import { event, NAMESPACES, paginationReply, parseId } from 'utils'; -export default event("interactionCreate", async (ctx, interaction) => { +export default event('interactionCreate', async (ctx, interaction) => { if (!interaction.isStringSelectMenu()) return; const [namespace] = parseId(interaction.customId); if (namespace !== NAMESPACES.help) return; @@ -10,6 +10,6 @@ export default event("interactionCreate", async (ctx, interaction) => { await paginationReply(interaction.values[0], { ...ctx, interaction, - }) + }), ); }); diff --git a/src/events/interactionCreate/index.ts b/src/events/interactionCreate/index.ts index cb281e7..e3f0d20 100644 --- a/src/events/interactionCreate/index.ts +++ b/src/events/interactionCreate/index.ts @@ -1,6 +1,6 @@ -import commands from "./commands.ts"; -import help from "./help.ts"; -import pagination from "./pagination.ts"; +import commands from './commands.ts'; +import help from './help.ts'; +import pagination from './pagination.ts'; const events = [commands, help, pagination]; diff --git a/src/events/interactionCreate/pagination.ts b/src/events/interactionCreate/pagination.ts index 5c90d63..b9b9418 100644 --- a/src/events/interactionCreate/pagination.ts +++ b/src/events/interactionCreate/pagination.ts @@ -1,20 +1,21 @@ -import { createId, event, generatePage, parseId, NAMESPACES } from "utils"; +import { createId, event, generatePage, NAMESPACES, parseId } from 'utils'; -export default event("interactionCreate", async (ctx, interaction) => { +export default event('interactionCreate', async (ctx, interaction) => { if (!interaction.isButton() && !interaction.isStringSelectMenu()) return; const [namespace, paginatorName] = parseId(interaction.customId); if (namespace !== NAMESPACES.pagination) return; await interaction.deferUpdate(); let interactionId = interaction.customId; - if (interaction.isStringSelectMenu()) + if (interaction.isStringSelectMenu()) { interactionId = createId( namespace, paginatorName, - `select-${interaction.values[0]}` + `select-${interaction.values[0]}`, ); + } return await interaction.editReply( - await generatePage(interactionId, { ...ctx, interaction }) + await generatePage(interactionId, { ...ctx, interaction }), ); }); diff --git a/src/events/ready.ts b/src/events/ready.ts index 45ae089..f672033 100644 --- a/src/events/ready.ts +++ b/src/events/ready.ts @@ -1,7 +1,7 @@ -import { event } from "utils"; +import { event } from 'utils'; -export default event("ready", ({ logger }, client) => { +export default event('ready', ({ logger }, client) => { logger.system( - `\x1b[4m${client.user.tag}\x1b[0m\x1b[36m is up and ready to go!` + `\x1b[4m${client.user.tag}\x1b[0m\x1b[36m is up and ready to go!`, ); }); diff --git a/src/index.ts b/src/index.ts index 8a65457..256e401 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ -import client from "client"; -import { registerEvents } from "utils"; -import events from "./events/index.ts"; +import client from 'client'; +import { registerEvents } from 'utils'; +import events from './events/index.ts'; registerEvents(client, events); diff --git a/src/scripts/clear.ts b/src/scripts/clear.ts index 5ce3351..e00a68d 100644 --- a/src/scripts/clear.ts +++ b/src/scripts/clear.ts @@ -1,19 +1,20 @@ -import { REST, Routes, APIUser } from "discord.js"; -import ENV from "env"; -import { Logger } from "utils"; +import { APIUser, REST, Routes } from 'discord.js'; +import ENV from 'env'; +import { Logger } from 'utils'; -const rest = new REST({ version: "10" }).setToken(ENV.BOT_TOKEN); -const logger = new Logger("clear"); +const rest = new REST({ version: '10' }).setToken(ENV.BOT_TOKEN); +const logger = new Logger('clear'); async function main() { - if (!ENV.TEST_GUILD) - throw new Error("Missing environment variable: TEST_GUILD"); + if (!ENV.TEST_GUILD) { + throw new Error('Missing environment variable: TEST_GUILD'); + } const currentUser = (await rest.get(Routes.user())) as APIUser; await rest.put(Routes.applicationCommands(currentUser.id), { body: [] }); await rest.put( Routes.applicationGuildCommands(currentUser.id, ENV.TEST_GUILD), - { body: [] } + { body: [] }, ); return currentUser; diff --git a/src/scripts/deploy.ts b/src/scripts/deploy.ts index 2088a51..b1b5707 100644 --- a/src/scripts/deploy.ts +++ b/src/scripts/deploy.ts @@ -1,35 +1,36 @@ -import { REST, Routes, APIUser } from "discord.js"; -import categories from "commands"; -import ENV from "env"; -import { Logger, extractMeta } from "utils"; +import { APIUser, REST, Routes } from 'discord.js'; +import categories from 'commands'; +import ENV from 'env'; +import { extractMeta, Logger } from 'utils'; -const rest = new REST({ version: "10" }).setToken(ENV.BOT_TOKEN); -const logger = new Logger("deploy"); +const rest = new REST({ version: '10' }).setToken(ENV.BOT_TOKEN); +const logger = new Logger('deploy'); async function main() { - if (!ENV.TEST_GUILD) - throw new Error("Missing environment variable: TEST_GUILD"); + if (!ENV.TEST_GUILD) { + throw new Error('Missing environment variable: TEST_GUILD'); + } const currentUser = (await rest.get(Routes.user())) as APIUser; // In development, all commands are deployed to the test guild. - if (ENV.DEV) + if (ENV.DEV) { await rest.put( Routes.applicationGuildCommands(currentUser.id, ENV.TEST_GUILD), { - body: extractMeta(categories, "all"), - } + body: extractMeta(categories, 'all'), + }, ); - // In production, public commmands are deployed globally, and private commands + } // In production, public commmands are deployed globally, and private commands // are deployed to the test guild. else { await rest.put(Routes.applicationCommands(currentUser.id), { - body: extractMeta(categories, "public"), + body: extractMeta(categories, 'public'), }); await rest.put( Routes.applicationGuildCommands(currentUser.id, ENV.TEST_GUILD), { - body: extractMeta(categories, "private"), - } + body: extractMeta(categories, 'private'), + }, ); } @@ -41,8 +42,8 @@ main() const tag = `${user.username}#${user.discriminator}`; logger.system( `Commands deployed for \x1b[4m${tag}\x1b[0m\x1b[36m${ - ENV.DEV ? ` in guild ${ENV.TEST_GUILD}` : "" - }!` + ENV.DEV ? ` in guild ${ENV.TEST_GUILD}` : '' + }!`, ); }) .catch((e) => logger.error(e)); diff --git a/src/types/commands.ts b/src/types/commands.ts index 9b4da0c..f615018 100644 --- a/src/types/commands.ts +++ b/src/types/commands.ts @@ -1,13 +1,13 @@ import { + APIEmbedField, + AutocompleteInteraction, Awaitable, ChatInputCommandInteraction, SlashCommandBuilder, - APIEmbedField, - SlashCommandSubcommandsOnlyBuilder, - AutocompleteInteraction, SlashCommandOptionsOnlyBuilder, -} from "discord.js"; -import { BaseContext } from "./context.ts"; + SlashCommandSubcommandsOnlyBuilder, +} from 'discord.js'; +import { BaseContext } from './context.ts'; export interface CommandContext extends BaseContext { interaction: ChatInputCommandInteraction; @@ -39,29 +39,29 @@ export type CommandOptions = { cooldown?: | number | { - /** - * The number of seconds this command will be on cooldown for. - */ - seconds: number; - /** - * The scope of the cooldown. - * @default user - * - * @values - * `user` - The cooldown will be on a per-user basis. - * - * `guild` - The cooldown will be on a per-guild basis. - */ - scope?: "user" | "guild"; - }; + /** + * The number of seconds this command will be on cooldown for. + */ + seconds: number; + /** + * The scope of the cooldown. + * @default user + * + * @values + * `user` - The cooldown will be on a per-user basis. + * + * `guild` - The cooldown will be on a per-guild basis. + */ + scope?: 'user' | 'guild'; + }; }; export type CommandExec = (ctx: CommandContext) => Awaitable<unknown>; export type CommandAutocomplete = ( - ctx: AutocompleteContext + ctx: AutocompleteContext, ) => Awaitable<unknown>; export type CommandMeta = | SlashCommandBuilder - | Omit<SlashCommandBuilder, "addSubcommand" | "addSubcommandGroup"> + | Omit<SlashCommandBuilder, 'addSubcommand' | 'addSubcommandGroup'> | SlashCommandSubcommandsOnlyBuilder | SlashCommandOptionsOnlyBuilder; export interface Command { diff --git a/src/types/context.ts b/src/types/context.ts index 874ff64..5c3e2ff 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -1,5 +1,5 @@ -import { Client } from "discord.js"; -import { Logger } from "utils"; +import { Client } from 'discord.js'; +import { Logger } from 'utils'; export interface BaseContext { client: Client; diff --git a/src/types/events.ts b/src/types/events.ts index b4073b5..97151c8 100644 --- a/src/types/events.ts +++ b/src/types/events.ts @@ -1,5 +1,5 @@ -import { ClientEvents, Awaitable } from "discord.js"; -import { BaseContext } from "./context.ts"; +import { Awaitable, ClientEvents } from 'discord.js'; +import { BaseContext } from './context.ts'; export interface EventContext extends BaseContext {} diff --git a/src/types/index.ts b/src/types/index.ts index 7022e85..402425f 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,3 @@ -export * from "./events.ts"; -export * from "./commands.ts"; -export * from "./pagination.ts"; +export * from './events.ts'; +export * from './commands.ts'; +export * from './pagination.ts'; diff --git a/src/types/pagination.ts b/src/types/pagination.ts index 29aa85a..310265b 100644 --- a/src/types/pagination.ts +++ b/src/types/pagination.ts @@ -1,5 +1,5 @@ -import { APIEmbedField, BaseInteraction } from "discord.js"; -import { BaseContext } from "./context.ts"; +import { APIEmbedField, BaseInteraction } from 'discord.js'; +import { BaseContext } from './context.ts'; export type PaginationData = APIEmbedField[]; diff --git a/src/utils/chunk.ts b/src/utils/chunk.ts index 6a12ef1..f93df62 100644 --- a/src/utils/chunk.ts +++ b/src/utils/chunk.ts @@ -8,8 +8,9 @@ export function chunk<T>(items: T[], chunk: number): T[][] { const chunks: T[][] = []; - for (let i = 0; i < items.length; i += chunk) + for (let i = 0; i < items.length; i += chunk) { chunks.push(items.slice(i, i + chunk)); + } return chunks; } diff --git a/src/utils/command.ts b/src/utils/command.ts index 3ae2249..e58ad22 100644 --- a/src/utils/command.ts +++ b/src/utils/command.ts @@ -7,7 +7,7 @@ import { CommandExec, CommandMeta, CommandOptions, -} from "types"; +} from 'types'; export function command({ meta, @@ -29,7 +29,7 @@ export function command({ export function category( metadata: CommandCategoryMetadata, - commands: Command[] + commands: Command[], ): CommandCategory { return { ...metadata, @@ -49,7 +49,7 @@ export function category( */ export function extractMeta( categories: CommandCategory[], - type: keyof CommandCategoryCommands + type: keyof CommandCategoryCommands, ) { return categories.flatMap(({ commands }) => commands[type].map(({ meta }) => meta) diff --git a/src/utils/constants.ts b/src/utils/constants.ts index b93585d..4ce1892 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1,18 +1,18 @@ export const COLORS = { - error: "#f54242", - warn: "#f5a742", - embed: "#2b2d31", + error: '#f54242', + warn: '#f5a742', + embed: '#2b2d31', } as const; export const EMOJIS = { - success: "✅", - error: "❌", - warn: "⚠️", - deny: "🚫", - wait: "⏳", + success: '✅', + error: '❌', + warn: '⚠️', + deny: '🚫', + wait: '⏳', } as const; export const NAMESPACES = { - pagination: "pagination", - help: "help", + pagination: 'pagination', + help: 'help', } as const; diff --git a/src/utils/date.ts b/src/utils/date.ts index e3393ac..044f03d 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -5,6 +5,8 @@ * @note This is very basic and only supports the format `dd/mm/yyyy`, for more in-depth formatting, it is recommneded to use a library such as [date-fns](https://date-fns.org/) */ export const formatDate = (date: Date) => - `${date.getDate().toString().padStart(2, '0')}/${(date.getMonth() + 1) - .toString() - .padStart(2, '0')}/${date.getFullYear()}`; + `${date.getDate().toString().padStart(2, '0')}/${ + (date.getMonth() + 1) + .toString() + .padStart(2, '0') + }/${date.getFullYear()}`; diff --git a/src/utils/event.ts b/src/utils/event.ts index 29956fd..2993467 100644 --- a/src/utils/event.ts +++ b/src/utils/event.ts @@ -1,11 +1,11 @@ -import { Event, EventExec, EventKeys } from "types"; -import { Client } from "discord.js"; -import { Logger } from "./logger.ts"; -import { reply } from "./replies.ts"; +import { Event, EventExec, EventKeys } from 'types'; +import { Client } from 'discord.js'; +import { Logger } from './logger.ts'; +import { reply } from './replies.ts'; export function event<T extends EventKeys>( id: T, - exec: EventExec<T> + exec: EventExec<T>, ): Event<T> { return { id, @@ -15,7 +15,7 @@ export function event<T extends EventKeys>( // deno-lint-ignore no-explicit-any export function registerEvents(client: Client, events: Event<any>[]): void { - for (const event of events) + for (const event of events) { client.on(event.id, async (...args) => { const logger = new Logger(event.id); @@ -25,8 +25,10 @@ export function registerEvents(client: Client, events: Event<any>[]): void { } catch (error) { logger.error(error); // If the error is thrown in an interaction, reply to it - if (event.id === "interactionCreate") + if (event.id === 'interactionCreate') { reply.error(args[0]).catch(console.error); + } } }); + } } diff --git a/src/utils/help.ts b/src/utils/help.ts index 65dd7ff..9d0e59d 100644 --- a/src/utils/help.ts +++ b/src/utils/help.ts @@ -3,12 +3,12 @@ import { BaseInteraction, PermissionFlagsBits, StringSelectMenuBuilder, -} from "discord.js"; -import { NAMESPACES } from "utils"; -import { createId } from "./interaction.ts"; -import categories from "commands"; -import ENV from "env"; -import { CommandCategoryCommands } from "types"; +} from 'discord.js'; +import { NAMESPACES } from 'utils'; +import { createId } from './interaction.ts'; +import categories from 'commands'; +import ENV from 'env'; +import { CommandCategoryCommands } from 'types'; /** * Filters categories to exclude ones that do not contain commands relevant to the user @@ -18,7 +18,7 @@ import { CommandCategoryCommands } from "types"; */ const filterCategories = ( cmdType: keyof CommandCategoryCommands, - isAdmin = false + isAdmin = false, ) => categories?.filter((c) => c.commands[cmdType].some((cmd) => !cmd.options.adminOnly || isAdmin) @@ -27,42 +27,42 @@ const filterCategories = ( /** Pre-filtered command categories */ const cats = { private: { - member: filterCategories("all"), - admin: filterCategories("all", true), + member: filterCategories('all'), + admin: filterCategories('all', true), }, public: { - member: filterCategories("public"), - admin: filterCategories("public", true), + member: filterCategories('public'), + admin: filterCategories('public', true), }, }; /** Select menu for the help embed */ export const helpSelectComponent = ( - interaction: BaseInteraction + interaction: BaseInteraction, ): ActionRowBuilder<StringSelectMenuBuilder> | null => { - const isAdmin = - interaction.memberPermissions && + const isAdmin = interaction.memberPermissions && interaction.memberPermissions.has(PermissionFlagsBits.Administrator); // Categories specific to this guild (test guild or not) - const guildCats = - interaction.guildId === ENV.TEST_GUILD ? cats.private : cats.public; + const guildCats = interaction.guildId === ENV.TEST_GUILD + ? cats.private + : cats.public; - if (guildCats[isAdmin ? "admin" : "member"].length === 0) return null; + if (guildCats[isAdmin ? 'admin' : 'member'].length === 0) return null; return new ActionRowBuilder<StringSelectMenuBuilder>().addComponents( new StringSelectMenuBuilder() .setCustomId(createId(NAMESPACES.help)) - .setPlaceholder("Select a category...") + .setPlaceholder('Select a category...') .setMaxValues(1) .addOptions( - guildCats[isAdmin ? "admin" : "member"].map( + guildCats[isAdmin ? 'admin' : 'member'].map( ({ name, description, emoji }) => ({ label: name, description, emoji, value: name, - }) - ) - ) + }), + ), + ), ); }; diff --git a/src/utils/index.ts b/src/utils/index.ts index 6588080..b0f17b3 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,12 +1,12 @@ -export * from "./event.ts"; -export * from "./command.ts"; -export * from "./replies.ts"; -export * from "./chunk.ts"; -export * from "./interaction.ts"; -export * from "./logger.ts"; -export * from "./help.ts"; -export * from "./paginators/index.ts"; -export * from "./pagination.ts"; -export * from "./split.ts"; -export * from "./date.ts"; -export * from "./constants.ts"; +export * from './event.ts'; +export * from './command.ts'; +export * from './replies.ts'; +export * from './chunk.ts'; +export * from './interaction.ts'; +export * from './logger.ts'; +export * from './help.ts'; +export * from './paginators/index.ts'; +export * from './pagination.ts'; +export * from './split.ts'; +export * from './date.ts'; +export * from './constants.ts'; diff --git a/src/utils/logger.ts b/src/utils/logger.ts index d0e4de1..93fb4ee 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -74,11 +74,11 @@ export class Logger { export const log = ( category: string, message: unknown, - type: LogType = LogType.Default + type: LogType = LogType.Default, ) => console.log( getTextColor(type), - `[${type}] ${category.toLowerCase()} - ${message}` + `[${type}] ${category.toLowerCase()} - ${message}`, ); log.error = (category: string, message: unknown) => diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts index 7876123..b6b385f 100644 --- a/src/utils/pagination.ts +++ b/src/utils/pagination.ts @@ -1,17 +1,17 @@ -import process from "node:process"; +import process from 'node:process'; import { - APIEmbed, ActionRowBuilder, + APIEmbed, ButtonBuilder, ButtonStyle, EmbedBuilder, InteractionReplyOptions, StringSelectMenuBuilder, -} from "discord.js"; -import { createId } from "./interaction.ts"; -import { COLORS, NAMESPACES } from "utils"; -import { Logger } from "./logger.ts"; -import { PaginationContext, PaginationData } from "types"; +} from 'discord.js'; +import { createId } from './interaction.ts'; +import { COLORS, NAMESPACES } from 'utils'; +import { Logger } from './logger.ts'; +import { PaginationContext, PaginationData } from 'types'; export class Paginator { name: string; @@ -20,8 +20,8 @@ export class Paginator { * The fields and footer are automatically set by the paginator. */ embedData?: - | Omit<APIEmbed, "fields" | "footer"> - | ((ctx: PaginationContext) => Omit<APIEmbed, "fields" | "footer">); + | Omit<APIEmbed, 'fields' | 'footer'> + | ((ctx: PaginationContext) => Omit<APIEmbed, 'fields' | 'footer'>); /** * The reply to which the pagination embed and its controls are added. * If not specified, the reply is ephemeral by default. @@ -78,14 +78,14 @@ export class Paginator { * (ctx) => `${ctx.interaction.user.id}-${ctx.interaction.guildId}` */ getCacheKey?: typeof Paginator.prototype.getCacheKey; - } + }, ) { this.logger = new Logger(`paginators/${name}`); // Page length can be at most 25 due to limit of 25 fields per embed if (pageLength > 25) { this.logger.error( - `Paginator "${name}" has a page length greater than 25` + `Paginator "${name}" has a page length greater than 25`, ); process.exit(1); } @@ -94,7 +94,7 @@ export class Paginator { // (2 are already being used for back/next buttons and page selector) if ( replyOptions && - typeof replyOptions !== "function" && + typeof replyOptions !== 'function' && replyOptions.components && replyOptions.components.length > 3 ) { @@ -106,7 +106,7 @@ export class Paginator { // (1 is already being used for the pagination embed) if ( replyOptions && - typeof replyOptions !== "function" && + typeof replyOptions !== 'function' && replyOptions.embeds && replyOptions.embeds.length > 4 ) { @@ -117,7 +117,7 @@ export class Paginator { // If caching is enabled, the cache key function must be specified if (cacheData && !getCacheKey) { this.logger.error( - `Paginator "${name}" has caching enabled but no cache key function specified` + `Paginator "${name}" has caching enabled but no cache key function specified`, ); process.exit(1); } @@ -138,7 +138,7 @@ export class Paginator { */ public async getPage( offset: number, - ctx: PaginationContext + ctx: PaginationContext, ): Promise<InteractionReplyOptions> { // If caching is enabled, try to get the data from the cache and fetch otherwise const cacheKey = this.getCacheKey(ctx); @@ -170,14 +170,14 @@ export class Paginator { protected formatPage( offset: number, data: PaginationData, - ctx: PaginationContext + ctx: PaginationContext, ): InteractionReplyOptions { const fields = data.slice(offset, offset + this.pageLength); const currentPage = Math.floor(offset / this.pageLength) + 1; const pageCount = Math.ceil(data.length / this.pageLength); const embedData = this.embedData - ? typeof this.embedData === "function" + ? typeof this.embedData === 'function' ? this.embedData(ctx) : this.embedData : undefined; @@ -185,21 +185,22 @@ export class Paginator { .setFields(fields) .setColor(embedData?.color ?? COLORS.embed); - if (fields.length === 0) embed.setDescription("No results found!"); - else + if (fields.length === 0) embed.setDescription('No results found!'); + else { embed.setFooter({ text: `Page ${currentPage} / ${pageCount}`, }); + } // Back button const backId = createId( NAMESPACES.pagination, this.name, - offset - this.pageLength + offset - this.pageLength, ); const backButton = new ButtonBuilder() .setCustomId(backId) - .setLabel("Back") + .setLabel('Back') .setStyle(ButtonStyle.Primary) .setDisabled(offset <= 0); @@ -207,45 +208,47 @@ export class Paginator { const nextId = createId( NAMESPACES.pagination, this.name, - offset + this.pageLength + offset + this.pageLength, ); const nextButton = new ButtonBuilder() .setCustomId(nextId) - .setLabel("Next") + .setLabel('Next') .setStyle(ButtonStyle.Primary) .setDisabled(currentPage >= pageCount); const selectId = createId(NAMESPACES.pagination, this.name); const pageSelector = new StringSelectMenuBuilder() .setCustomId(selectId) - .setPlaceholder("Select a page...") + .setPlaceholder('Select a page...') .setMaxValues(1) .setOptions( Array.from(Array(pageCount).keys()).map((i) => ({ label: `Page ${i + 1}`, value: i.toString(), - })) + })), ); const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents( backButton, - nextButton + nextButton, ); - const selectMenu = - new ActionRowBuilder<StringSelectMenuBuilder>().addComponents( - pageSelector + const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>() + .addComponents( + pageSelector, ); const replyOptions = this.replyOptions - ? typeof this.replyOptions === "function" + ? typeof this.replyOptions === 'function' ? this.replyOptions(ctx) : this.replyOptions : undefined; - if (replyOptions?.components && replyOptions.components.length > 3) + if (replyOptions?.components && replyOptions.components.length > 3) { throw new Error(`Paginator "${this.name}" has more than 3 components`); - if (replyOptions?.embeds && replyOptions.embeds.length > 4) + } + if (replyOptions?.embeds && replyOptions.embeds.length > 4) { throw new Error(`Paginator "${this.name}" has more than 4 embeds`); + } return { ...this.replyOptions, diff --git a/src/utils/paginators/help.ts b/src/utils/paginators/help.ts index e88402c..fd4a645 100644 --- a/src/utils/paginators/help.ts +++ b/src/utils/paginators/help.ts @@ -2,17 +2,17 @@ import { APIApplicationCommandOption, ApplicationCommandOptionType, PermissionFlagsBits, -} from "discord.js"; -import categories from "commands"; +} from 'discord.js'; +import categories from 'commands'; import { Command, CommandCategoryCommands, CommandOptions, PaginationData, -} from "types"; -import { helpSelectComponent } from "../help.ts"; -import { Paginator } from "../pagination.ts"; -import ENV from "env"; +} from 'types'; +import { helpSelectComponent } from '../help.ts'; +import { Paginator } from '../pagination.ts'; +import ENV from 'env'; /** * Extracts subcommands from a command option recursively @@ -23,25 +23,26 @@ import ENV from "env"; const extractSubcommandsRecursive = ( option: APIApplicationCommandOption, name: string, - cmdOpts: CommandOptions + cmdOpts: CommandOptions, ): PaginationData => { const result: PaginationData = []; - if (option.type === ApplicationCommandOptionType.Subcommand) + if (option.type === ApplicationCommandOptionType.Subcommand) { result.push({ name: `/${name} ${option.name}`, value: ` ${option.description} - ${cmdOpts.adminOnly ? "🛡️ _admin only_" : ""}${ - cmdOpts.private ? `${cmdOpts.adminOnly ? "\n" : ""}🔒 _private_` : "" + ${cmdOpts.adminOnly ? '🛡️ _admin only_' : ''}${ + cmdOpts.private ? `${cmdOpts.adminOnly ? '\n' : ''}🔒 _private_` : '' } `, }); - else if (option.type === ApplicationCommandOptionType.SubcommandGroup) + } else if (option.type === ApplicationCommandOptionType.SubcommandGroup) { option.options?.forEach((sub) => result.push( - ...extractSubcommandsRecursive(sub, `${name} ${option.name}`, cmdOpts) + ...extractSubcommandsRecursive(sub, `${name} ${option.name}`, cmdOpts), ) ); + } return result; }; @@ -55,23 +56,24 @@ const getCommands = (command: Command): PaginationData => { extractSubcommandsRecursive( option.toJSON(), command.meta.name, - command.options + command.options, ) ); // If no subcommands are found, this command is a standalone command - if (result.length === 0) + if (result.length === 0) { result.push({ name: `/${command.meta.name}`, value: ` ${command.meta.description} - ${command.options.adminOnly ? "🛡️ _admin only_" : ""}${ + ${command.options.adminOnly ? '🛡️ _admin only_' : ''}${ command.options.private - ? `${command.options.adminOnly ? "\n" : ""}🔒 _private_` - : "" + ? `${command.options.adminOnly ? '\n' : ''}🔒 _private_` + : '' } `, }); + } return result; }; @@ -85,55 +87,55 @@ const getCommands = (command: Command): PaginationData => { const filterCommands = ( commands: CommandCategoryCommands, type: keyof CommandCategoryCommands, - isAdmin = false + isAdmin = false, ) => commands[type] .sort((a, b) => a.meta.name.localeCompare(b.meta.name)) .filter((c) => !c.options.adminOnly || isAdmin) .flatMap((c) => getCommands(c)); -const helpPaginators: Paginator[] = - categories?.map((category) => { - // Separate commands into different categories depending on the guild and member that the command is used in/by - const cmds = { - private: { - member: filterCommands(category.commands, "all"), - admin: filterCommands(category.commands, "all", true), - }, - public: { - member: filterCommands(category.commands, "public"), - admin: filterCommands(category.commands, "public", true), - }, - }; - const emoji = category.emoji ? `${category.emoji} ` : ""; +const helpPaginators: Paginator[] = categories?.map((category) => { + // Separate commands into different categories depending on the guild and member that the command is used in/by + const cmds = { + private: { + member: filterCommands(category.commands, 'all'), + admin: filterCommands(category.commands, 'all', true), + }, + public: { + member: filterCommands(category.commands, 'public'), + admin: filterCommands(category.commands, 'public', true), + }, + }; + const emoji = category.emoji ? `${category.emoji} ` : ''; - return new Paginator(category.name, { - embedData: { - title: `${emoji}${category.name} Commands`, - description: - category.description ?? - `Browse through ${category.commands.public.length} command${ - category.commands.public.length > 1 ? "s" : "" - } in ${emoji}${category.name}`, - }, - replyOptions: ({ interaction }) => { - const helpSelectMenu = helpSelectComponent(interaction); - return { - components: helpSelectMenu ? [helpSelectMenu] : [], - }; - }, - pageLength: 10, - getData: ({ interaction }) => { - const guildCmds = - interaction.guildId === ENV.TEST_GUILD ? cmds.private : cmds.public; - if ( - interaction.memberPermissions && - interaction.memberPermissions.has(PermissionFlagsBits.Administrator) - ) - return guildCmds.admin; - return guildCmds.member; - }, - }); - }) ?? []; + return new Paginator(category.name, { + embedData: { + title: `${emoji}${category.name} Commands`, + description: category.description ?? + `Browse through ${category.commands.public.length} command${ + category.commands.public.length > 1 ? 's' : '' + } in ${emoji}${category.name}`, + }, + replyOptions: ({ interaction }) => { + const helpSelectMenu = helpSelectComponent(interaction); + return { + components: helpSelectMenu ? [helpSelectMenu] : [], + }; + }, + pageLength: 10, + getData: ({ interaction }) => { + const guildCmds = interaction.guildId === ENV.TEST_GUILD + ? cmds.private + : cmds.public; + if ( + interaction.memberPermissions && + interaction.memberPermissions.has(PermissionFlagsBits.Administrator) + ) { + return guildCmds.admin; + } + return guildCmds.member; + }, + }); +}) ?? []; export default helpPaginators; diff --git a/src/utils/paginators/index.ts b/src/utils/paginators/index.ts index 0228e2b..8196cbd 100644 --- a/src/utils/paginators/index.ts +++ b/src/utils/paginators/index.ts @@ -1,15 +1,15 @@ -import { InteractionReplyOptions } from "discord.js"; -import { Paginator } from "../pagination.ts"; -import helpPaginators from "./help.ts"; -import { createId, parseId } from "../interaction.ts"; -import { NAMESPACES } from "utils"; -import { PaginationContext } from "types"; +import { InteractionReplyOptions } from 'discord.js'; +import { Paginator } from '../pagination.ts'; +import helpPaginators from './help.ts'; +import { createId, parseId } from '../interaction.ts'; +import { NAMESPACES } from 'utils'; +import { PaginationContext } from 'types'; // Add new paginators here const paginators: Paginator[] = [...helpPaginators /*, otherPaginator */]; const paginatorMap = new Map<string, Paginator>( - paginators.map((p) => [p.name, p]) + paginators.map((p) => [p.name, p]), ); /** @@ -19,7 +19,7 @@ const paginatorMap = new Map<string, Paginator>( */ export function generatePage( interactionId: string, - ctx: PaginationContext + ctx: PaginationContext, ): Promise<InteractionReplyOptions> { // Extract metadata from interactionId const [_namespace, paginatorName, offsetString] = parseId(interactionId); @@ -29,8 +29,8 @@ export function generatePage( let offset = parseInt(offsetString); // Page selected from select menu - if (offsetString && offsetString.startsWith("select-")) { - let targetPage = parseInt(offsetString.split("-")[1]); + if (offsetString && offsetString.startsWith('select-')) { + let targetPage = parseInt(offsetString.split('-')[1]); if (isNaN(targetPage)) targetPage = 0; offset = targetPage * paginator.pageLength; } diff --git a/src/utils/replies.ts b/src/utils/replies.ts index 93da115..0505984 100644 --- a/src/utils/replies.ts +++ b/src/utils/replies.ts @@ -1,9 +1,9 @@ import { - InteractionReplyOptions, - InteractionEditReplyOptions, BaseInteraction, -} from "discord.js"; -import { EMOJIS } from "utils"; + InteractionEditReplyOptions, + InteractionReplyOptions, +} from 'discord.js'; +import { EMOJIS } from 'utils'; export interface DeferableInteraction extends BaseInteraction { deferred: boolean; @@ -13,12 +13,12 @@ export interface DeferableInteraction extends BaseInteraction { } export enum ReplyType { - Default = "default", - Success = "success", - Error = "error", - Warn = "warn", - Deny = "deny", - Wait = "wait", + Default = 'default', + Success = 'success', + Error = 'error', + Warn = 'warn', + Deny = 'deny', + Wait = 'wait', } /** @@ -29,13 +29,14 @@ export enum ReplyType { */ const getOptions = ( options: InteractionReplyOptions | string, - type: ReplyType + type: ReplyType, ): InteractionReplyOptions => { - if (typeof options === "string") + if (typeof options === 'string') { return getOptions({ content: options }, type); + } const { content, ephemeral } = options; - const emoji = type === ReplyType.Default ? "" : EMOJIS[type]; + const emoji = type === ReplyType.Default ? '' : EMOJIS[type]; return { ...options, @@ -54,20 +55,22 @@ const getOptions = ( export const reply = <T extends DeferableInteraction>( interaction: T, options: InteractionReplyOptions | string, - type: ReplyType = ReplyType.Default + type: ReplyType = ReplyType.Default, ) => { - if (!interaction.reply || !interaction.editReply) - return Promise.reject("Invalid interaction"); + if (!interaction.reply || !interaction.editReply) { + return Promise.reject('Invalid interaction'); + } if ( !options || - (typeof options === "object" && + (typeof options === 'object' && !options.content && !options.embeds && !options.files) - ) - return Promise.reject("Cannot send an empty message"); + ) { + return Promise.reject('Cannot send an empty message'); + } - if (interaction.replied) return Promise.reject("Interaction already replied"); + if (interaction.replied) return Promise.reject('Interaction already replied'); const alteredOptions = getOptions(options, type); if (interaction.deferred) return interaction.editReply(alteredOptions); @@ -76,27 +79,27 @@ export const reply = <T extends DeferableInteraction>( reply.success = <T extends DeferableInteraction>( interaction: T, - options: InteractionReplyOptions | string + options: InteractionReplyOptions | string, ) => reply(interaction, options, ReplyType.Success); reply.error = <T extends DeferableInteraction>( interaction: T, - options: InteractionReplyOptions | string = "Oops. Something went wrong!" + options: InteractionReplyOptions | string = 'Oops. Something went wrong!', ) => reply(interaction, options, ReplyType.Error); reply.warn = <T extends DeferableInteraction>( interaction: T, - options: InteractionReplyOptions | string + options: InteractionReplyOptions | string, ) => reply(interaction, options, ReplyType.Warn); reply.deny = <T extends DeferableInteraction>( interaction: T, options: | InteractionReplyOptions - | string = "You do not have permission to do that!" + | string = 'You do not have permission to do that!', ) => reply(interaction, options, ReplyType.Deny); reply.wait = <T extends DeferableInteraction>( interaction: T, - options: InteractionReplyOptions | string + options: InteractionReplyOptions | string, ) => reply(interaction, options, ReplyType.Wait); diff --git a/src/utils/split.ts b/src/utils/split.ts index 7554c04..88eb349 100644 --- a/src/utils/split.ts +++ b/src/utils/split.ts @@ -1,5 +1,5 @@ -import { CommandInteraction, EmbedBuilder } from "discord.js"; -import { COLORS } from "utils"; +import { CommandInteraction, EmbedBuilder } from 'discord.js'; +import { COLORS } from 'utils'; /** The maximum character length of an embed to send */ const MAX_EMBED_LENGTH = 2048 as const; @@ -17,12 +17,13 @@ export async function splitSend( input: string[], seperator: string, title: string, - msg: string + msg: string, ) { - if (!interaction.channel) throw new Error("No channel found"); - if (!interaction.channel.isSendable()) - throw new Error("Channel is not sendable"); - if (interaction.replied) throw new Error("Interaction already replied"); + if (!interaction.channel) throw new Error('No channel found'); + if (!interaction.channel.isSendable()) { + throw new Error('Channel is not sendable'); + } + if (interaction.replied) throw new Error('Interaction already replied'); if (!interaction.deferred) await interaction.deferReply(); // Split the input into multiple embed descriptions @@ -48,7 +49,7 @@ export async function splitSend( .setTitle( `${title} ${ descriptions.length > 1 ? `(${i + 1}/${descriptions.length})` : `` - }` + }`, ) .setDescription(description); messageEmbeds[index].push(embed); @@ -62,6 +63,7 @@ export async function splitSend( .send({ embeds: messageEmbeds[i] }) .catch(console.log); } - } else + } else { await interaction.editReply({ embeds: messageEmbeds[0], content: msg }); + } } From 3559aead01cbed56bac4f07f6b66819ec8b1eb37 Mon Sep 17 00:00:00 2001 From: Thijn <thijnkroon@gmail.com> Date: Thu, 7 Nov 2024 14:19:18 +0100 Subject: [PATCH 3/6] fix: resolve import conflicts --- src/index.ts | 3 +- src/utils/help.ts | 56 +++++++++++++--------- src/utils/pagination.ts | 5 +- src/utils/paginators/help.ts | 89 ++++++++++++++++++----------------- src/utils/paginators/index.ts | 8 +++- 5 files changed, 90 insertions(+), 71 deletions(-) diff --git a/src/index.ts b/src/index.ts index 256e401..f23ac85 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ import client from 'client'; -import { registerEvents } from 'utils'; +import { initPaginators, registerEvents } from 'utils'; import events from './events/index.ts'; registerEvents(client, events); +initPaginators(); diff --git a/src/utils/help.ts b/src/utils/help.ts index 9d0e59d..a6baff9 100644 --- a/src/utils/help.ts +++ b/src/utils/help.ts @@ -8,7 +8,7 @@ import { NAMESPACES } from 'utils'; import { createId } from './interaction.ts'; import categories from 'commands'; import ENV from 'env'; -import { CommandCategoryCommands } from 'types'; +import { CommandCategory, CommandCategoryCommands } from 'types'; /** * Filters categories to exclude ones that do not contain commands relevant to the user @@ -21,33 +21,47 @@ const filterCategories = ( isAdmin = false, ) => categories?.filter((c) => - c.commands[cmdType].some((cmd) => !cmd.options.adminOnly || isAdmin) + c.commands[cmdType].some((cmd) => !cmd.options.adminOnly || isAdmin), ); -/** Pre-filtered command categories */ -const cats = { +/** Cached filtered command categories */ +// deno-lint-ignore prefer-const +let cats = { private: { - member: filterCategories('all'), - admin: filterCategories('all', true), + member: null as null | CommandCategory[], + admin: null as null | CommandCategory[], }, public: { - member: filterCategories('public'), - admin: filterCategories('public', true), + member: null as null | CommandCategory[], + admin: null as null | CommandCategory[], }, }; +const getCategories = ( + scope: 'private' | 'public', + access: 'admin' | 'member', +) => { + if (!cats[scope][access]) + cats[scope][access] = filterCategories( + scope === 'private' ? 'all' : 'public', + access === 'admin', + ); + return cats[scope][access]; +}; /** Select menu for the help embed */ export const helpSelectComponent = ( interaction: BaseInteraction, ): ActionRowBuilder<StringSelectMenuBuilder> | null => { - const isAdmin = interaction.memberPermissions && + const isAdmin = + interaction.memberPermissions && interaction.memberPermissions.has(PermissionFlagsBits.Administrator); - // Categories specific to this guild (test guild or not) - const guildCats = interaction.guildId === ENV.TEST_GUILD - ? cats.private - : cats.public; - if (guildCats[isAdmin ? 'admin' : 'member'].length === 0) return null; + // Categories specific to this guild (test guild or not) + const guildCats = getCategories( + interaction.guildId === ENV.TEST_GUILD ? 'private' : 'public', + isAdmin ? 'admin' : 'member', + ); + if (guildCats.length === 0) return null; return new ActionRowBuilder<StringSelectMenuBuilder>().addComponents( new StringSelectMenuBuilder() @@ -55,14 +69,12 @@ export const helpSelectComponent = ( .setPlaceholder('Select a category...') .setMaxValues(1) .addOptions( - guildCats[isAdmin ? 'admin' : 'member'].map( - ({ name, description, emoji }) => ({ - label: name, - description, - emoji, - value: name, - }), - ), + guildCats.map(({ name, description, emoji }) => ({ + label: name, + description, + emoji, + value: name, + })), ), ); }; diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts index b6b385f..119a7bf 100644 --- a/src/utils/pagination.ts +++ b/src/utils/pagination.ts @@ -143,7 +143,6 @@ export class Paginator { // If caching is enabled, try to get the data from the cache and fetch otherwise const cacheKey = this.getCacheKey(ctx); if (this.cacheData && this.cachedData.has(cacheKey)) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return this.formatPage(offset, this.cachedData.get(cacheKey)!, ctx); } @@ -232,8 +231,8 @@ export class Paginator { backButton, nextButton, ); - const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>() - .addComponents( + const selectMenu = + new ActionRowBuilder<StringSelectMenuBuilder>().addComponents( pageSelector, ); diff --git a/src/utils/paginators/help.ts b/src/utils/paginators/help.ts index fd4a645..dc427d8 100644 --- a/src/utils/paginators/help.ts +++ b/src/utils/paginators/help.ts @@ -40,7 +40,7 @@ const extractSubcommandsRecursive = ( option.options?.forEach((sub) => result.push( ...extractSubcommandsRecursive(sub, `${name} ${option.name}`, cmdOpts), - ) + ), ); } return result; @@ -57,7 +57,7 @@ const getCommands = (command: Command): PaginationData => { option.toJSON(), command.meta.name, command.options, - ) + ), ); // If no subcommands are found, this command is a standalone command @@ -94,48 +94,49 @@ const filterCommands = ( .filter((c) => !c.options.adminOnly || isAdmin) .flatMap((c) => getCommands(c)); -const helpPaginators: Paginator[] = categories?.map((category) => { - // Separate commands into different categories depending on the guild and member that the command is used in/by - const cmds = { - private: { - member: filterCommands(category.commands, 'all'), - admin: filterCommands(category.commands, 'all', true), - }, - public: { - member: filterCommands(category.commands, 'public'), - admin: filterCommands(category.commands, 'public', true), - }, - }; - const emoji = category.emoji ? `${category.emoji} ` : ''; +const helpPaginators = () => + categories?.map((category) => { + // Separate commands into different categories depending on the guild and member that the command is used in/by + const cmds = { + private: { + member: filterCommands(category.commands, 'all'), + admin: filterCommands(category.commands, 'all', true), + }, + public: { + member: filterCommands(category.commands, 'public'), + admin: filterCommands(category.commands, 'public', true), + }, + }; + const emoji = category.emoji ? `${category.emoji} ` : ''; - return new Paginator(category.name, { - embedData: { - title: `${emoji}${category.name} Commands`, - description: category.description ?? - `Browse through ${category.commands.public.length} command${ - category.commands.public.length > 1 ? 's' : '' - } in ${emoji}${category.name}`, - }, - replyOptions: ({ interaction }) => { - const helpSelectMenu = helpSelectComponent(interaction); - return { - components: helpSelectMenu ? [helpSelectMenu] : [], - }; - }, - pageLength: 10, - getData: ({ interaction }) => { - const guildCmds = interaction.guildId === ENV.TEST_GUILD - ? cmds.private - : cmds.public; - if ( - interaction.memberPermissions && - interaction.memberPermissions.has(PermissionFlagsBits.Administrator) - ) { - return guildCmds.admin; - } - return guildCmds.member; - }, - }); -}) ?? []; + return new Paginator(category.name, { + embedData: { + title: `${emoji}${category.name} Commands`, + description: + category.description ?? + `Browse through ${category.commands.public.length} command${ + category.commands.public.length > 1 ? 's' : '' + } in ${emoji}${category.name}`, + }, + replyOptions: ({ interaction }) => { + const helpSelectMenu = helpSelectComponent(interaction); + return { + components: helpSelectMenu ? [helpSelectMenu] : [], + }; + }, + pageLength: 10, + getData: ({ interaction }) => { + const guildCmds = + interaction.guildId === ENV.TEST_GUILD ? cmds.private : cmds.public; + if ( + interaction.memberPermissions && + interaction.memberPermissions.has(PermissionFlagsBits.Administrator) + ) { + return guildCmds.admin; + } + return guildCmds.member; + }, + }); + }) ?? []; export default helpPaginators; diff --git a/src/utils/paginators/index.ts b/src/utils/paginators/index.ts index 8196cbd..12bc10a 100644 --- a/src/utils/paginators/index.ts +++ b/src/utils/paginators/index.ts @@ -6,12 +6,18 @@ import { NAMESPACES } from 'utils'; import { PaginationContext } from 'types'; // Add new paginators here -const paginators: Paginator[] = [...helpPaginators /*, otherPaginator */]; +// If they need to be initialized, add them to the initPaginators function +const paginators: Paginator[] = []; const paginatorMap = new Map<string, Paginator>( paginators.map((p) => [p.name, p]), ); +export function initPaginators() { + for (const paginator of helpPaginators()) + paginatorMap.set(paginator.name, paginator); +} + /** * Generate the embed for a specific page of a paginator * @param interactionId The interactionId to generate the page for From e2762c582aedf1851e16c950349452aaa06fd3e1 Mon Sep 17 00:00:00 2001 From: Thijn <thijnkroon@gmail.com> Date: Sat, 9 Nov 2024 09:54:10 +0100 Subject: [PATCH 4/6] docs: update README for deno --- README.md | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 5a36983..457ed1b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # Discord bot template -[](https://discord.js.org/) +[](https://discord.js.org/) [](https://github.com/ThijnK/discord-bot-template-ts/stargazers) [](https://github.com/ThijnK/discord-bot-template-ts/graphs/contributors) [](https://github.com/ThijnK/discord-bot-template-ts/releases) -[](https://github.com/ThijnK/discord-bot-template-ts/actions) +[](https://github.com/ThijnK/discord-bot-template-ts/actions) [](./LICENSE) -A _TypeScript_ template for a **Discord bot**, using the [discord.js](https://discord.js.org/) library. +A _TypeScript_ template for a **Discord bot**, now powered by **Deno**! ## Features @@ -25,8 +25,7 @@ A _TypeScript_ template for a **Discord bot**, using the [discord.js](https://di Some knowledge of TypeScript and Discord.js is recommended, and you'll need the following installed: -- [Node.js](https://nodejs.org/en/) (v16.11.0 or higher) -- [npm](https://www.npmjs.com/) (should come with Node.js) +- [Deno](https://deno.com/) (v2.0 or higher) You will need a Discord bot token, which you can get by creating a new application in the [Discord developer portal](https://discord.com/developers/applications) by following the steps outlined in the [Discord developer documentation](https://discord.com/developers/docs/getting-started). @@ -38,8 +37,8 @@ Set the required environment variables (see section [Environment variables](#env Then run the following commands to install the dependencies and start the bot (in development mode): ```sh -npm i -npm run dev +deno install +deno task dev ``` ## Environment variables @@ -133,12 +132,12 @@ Command cooldowns can be set using the `cooldown` field in the command's [option ```ts export default command( // This command has a cooldown of 30 seconds, and works on a per-user basis - { meta, cooldown: 30 /* ... */ } + { meta, cooldown: 30 /* ... */ }, ); export default command( // This command has a cooldown of 60 seconds, and works on a guild-wide basis - { meta, cooldown: { seconds: 60, scope: 'guild' } /* ... */ } + { meta, cooldown: { seconds: 60, scope: 'guild' } /* ... */ }, ); ``` @@ -165,7 +164,7 @@ const meta = new SlashCommandBuilder() .setName('example-option') .setDescription('Example option.') .setRequired(true) - .setAutocomplete(true) + .setAutocomplete(true), ); export default command({ @@ -183,10 +182,10 @@ export default command({ 'Popular Topics: Embed preview', ]; const filtered = choices.filter((choice) => - choice.toLowerCase().startsWith(focusedValue.toLowerCase()) + choice.toLowerCase().startsWith(focusedValue.toLowerCase()), ); await interaction.respond( - filtered.map((choice) => ({ name: choice, value: choice })) + filtered.map((choice) => ({ name: choice, value: choice })), ); }, }); @@ -210,7 +209,7 @@ import { event } from '../utils'; export default event('ready', ({ logger }, client) => { logger.system( - `\x1b[4m${client.user.tag}\x1b[0m\x1b[36m is up and ready to go!` + `\x1b[4m${client.user.tag}\x1b[0m\x1b[36m is up and ready to go!`, ); }); ``` @@ -350,7 +349,7 @@ admin.initializeApp({ export const db = admin.database(); ``` -Don't forget to add the `FIREBASE_SDK` and `DB_URL` environment variables to your `.env` and `env.ts` files if you use the above snippet. You'll also have to install the `firebase-admin` package using `npm i firebase-admin`. +Don't forget to add the `FIREBASE_SDK` and `DB_URL` environment variables to your `.env` and `env.ts` files if you use the above snippet. You'll also have to install the `firebase-admin` package using `deno add firebase-admin`. ## Server @@ -393,13 +392,25 @@ src ## Code style -This template uses the [Prettier](https://prettier.io/) code formatter to automatically format the code. -A command, `npm run format`, is provided to run Prettier on all files in the `src` folder and immediately fix any issues. -You can also use the Prettier extension for your editor of choice to automatically format the code on save. - -A [`.prettierrc.json`](./.prettierrc.json) config file is provided to configure Prettier. +This template uses the Deno built-in code formatter to automatically format the code. +A command, `deno task fmt`, is provided to run the Deno formatter on all files in the `src` folder and immediately fix any issues. +You can also use the Deno extension, with some [VS Code settings](https://stackoverflow.com/questions/66207931/how-to-format-on-save-with-the-deno-vscode-extension) to automatically format the code on save. + +If you prefer to use [Prettier](https://prettier.io/), you may include a `.prettierrc.json` file in the root of the project. +The file will be ignored by git. +To achieve the same formatting as the current settings in [deno.json](./deno.json), you can use the following configuration: + +```json +{ + "endOfLine": "auto", + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all" +} +``` -The project also uses [ESLint](https://eslint.org/) to lint the code, a config for which is included in the [`.eslintrc.json`](./.eslintrc.json) file. +The linter used is also the Deno built-in linter, which can be run using the `deno task lint` command (which is really just `deno lint --fix`). ## Contributing From 53d79f86c7327e4265719126dde3c4b816fd7011 Mon Sep 17 00:00:00 2001 From: Thijn <thijnkroon@gmail.com> Date: Sat, 9 Nov 2024 10:03:56 +0100 Subject: [PATCH 5/6] chore: remove json extension from .prettierrc --- .gitignore | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index ef27776..7e600bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ .env -.prettierrc.json +.prettierrc /.vs/ /.vscode/ diff --git a/README.md b/README.md index 457ed1b..4bec51b 100644 --- a/README.md +++ b/README.md @@ -396,7 +396,7 @@ This template uses the Deno built-in code formatter to automatically format the A command, `deno task fmt`, is provided to run the Deno formatter on all files in the `src` folder and immediately fix any issues. You can also use the Deno extension, with some [VS Code settings](https://stackoverflow.com/questions/66207931/how-to-format-on-save-with-the-deno-vscode-extension) to automatically format the code on save. -If you prefer to use [Prettier](https://prettier.io/), you may include a `.prettierrc.json` file in the root of the project. +If you prefer to use [Prettier](https://prettier.io/), you may include a `.prettierrc` file in the root of the project. The file will be ignored by git. To achieve the same formatting as the current settings in [deno.json](./deno.json), you can use the following configuration: From 71f2745ba87b2e53f3a46a9a7a68836a35045131 Mon Sep 17 00:00:00 2001 From: Thijn <thijnkroon@gmail.com> Date: Sat, 9 Nov 2024 10:14:03 +0100 Subject: [PATCH 6/6] chore: format code --- src/events/interactionCreate/commands.ts | 11 +++++------ src/utils/help.ts | 8 ++++---- src/utils/pagination.ts | 4 ++-- src/utils/paginators/help.ts | 12 ++++++------ src/utils/paginators/index.ts | 3 ++- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/events/interactionCreate/commands.ts b/src/events/interactionCreate/commands.ts index 41d63af..30bbd85 100644 --- a/src/events/interactionCreate/commands.ts +++ b/src/events/interactionCreate/commands.ts @@ -78,12 +78,11 @@ const checkCooldown = ( if (!interaction.guildId) return null; const now = Date.now(); - const timestamps = - cooldowns.get(interaction.commandName) ?? new Map<string, number>(); - const timestamp = - timestamps.get( - scope === 'user' ? interaction.user.id : interaction.guildId, - ) ?? 0; + const timestamps = cooldowns.get(interaction.commandName) ?? + new Map<string, number>(); + const timestamp = timestamps.get( + scope === 'user' ? interaction.user.id : interaction.guildId, + ) ?? 0; const cooldownEnd = timestamp + seconds * 1000; if (now < cooldownEnd && !isAdmin) { diff --git a/src/utils/help.ts b/src/utils/help.ts index a6baff9..a3bd664 100644 --- a/src/utils/help.ts +++ b/src/utils/help.ts @@ -21,7 +21,7 @@ const filterCategories = ( isAdmin = false, ) => categories?.filter((c) => - c.commands[cmdType].some((cmd) => !cmd.options.adminOnly || isAdmin), + c.commands[cmdType].some((cmd) => !cmd.options.adminOnly || isAdmin) ); /** Cached filtered command categories */ @@ -40,11 +40,12 @@ const getCategories = ( scope: 'private' | 'public', access: 'admin' | 'member', ) => { - if (!cats[scope][access]) + if (!cats[scope][access]) { cats[scope][access] = filterCategories( scope === 'private' ? 'all' : 'public', access === 'admin', ); + } return cats[scope][access]; }; @@ -52,8 +53,7 @@ const getCategories = ( export const helpSelectComponent = ( interaction: BaseInteraction, ): ActionRowBuilder<StringSelectMenuBuilder> | null => { - const isAdmin = - interaction.memberPermissions && + const isAdmin = interaction.memberPermissions && interaction.memberPermissions.has(PermissionFlagsBits.Administrator); // Categories specific to this guild (test guild or not) diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts index 119a7bf..9f946b3 100644 --- a/src/utils/pagination.ts +++ b/src/utils/pagination.ts @@ -231,8 +231,8 @@ export class Paginator { backButton, nextButton, ); - const selectMenu = - new ActionRowBuilder<StringSelectMenuBuilder>().addComponents( + const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>() + .addComponents( pageSelector, ); diff --git a/src/utils/paginators/help.ts b/src/utils/paginators/help.ts index dc427d8..0edc22d 100644 --- a/src/utils/paginators/help.ts +++ b/src/utils/paginators/help.ts @@ -40,7 +40,7 @@ const extractSubcommandsRecursive = ( option.options?.forEach((sub) => result.push( ...extractSubcommandsRecursive(sub, `${name} ${option.name}`, cmdOpts), - ), + ) ); } return result; @@ -57,7 +57,7 @@ const getCommands = (command: Command): PaginationData => { option.toJSON(), command.meta.name, command.options, - ), + ) ); // If no subcommands are found, this command is a standalone command @@ -112,8 +112,7 @@ const helpPaginators = () => return new Paginator(category.name, { embedData: { title: `${emoji}${category.name} Commands`, - description: - category.description ?? + description: category.description ?? `Browse through ${category.commands.public.length} command${ category.commands.public.length > 1 ? 's' : '' } in ${emoji}${category.name}`, @@ -126,8 +125,9 @@ const helpPaginators = () => }, pageLength: 10, getData: ({ interaction }) => { - const guildCmds = - interaction.guildId === ENV.TEST_GUILD ? cmds.private : cmds.public; + const guildCmds = interaction.guildId === ENV.TEST_GUILD + ? cmds.private + : cmds.public; if ( interaction.memberPermissions && interaction.memberPermissions.has(PermissionFlagsBits.Administrator) diff --git a/src/utils/paginators/index.ts b/src/utils/paginators/index.ts index 12bc10a..2a57257 100644 --- a/src/utils/paginators/index.ts +++ b/src/utils/paginators/index.ts @@ -14,8 +14,9 @@ const paginatorMap = new Map<string, Paginator>( ); export function initPaginators() { - for (const paginator of helpPaginators()) + for (const paginator of helpPaginators()) { paginatorMap.set(paginator.name, paginator); + } } /**