diff --git a/.editorconfig b/.editorconfig
index ec34d4a5..cef82d52 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,8 +1,19 @@
+root = true
+
[*]
charset = utf-8
indent_size = 4
indent_style = space
insert_final_newline = true
-max_line_length = 120
tab_width = 4
-trim_trailing_whitespace = true
+
+[*.{js,jsx,ts,tsx}]
+indent_size = 2
+insert_final_newline = true
+tab_width = 2
+
+# YAML is usually 2 spaces
+# Markdown will cause weird formating with 4 spaces
+[*.{md,yml,yaml}]
+indent_size = 2
+tab_width = 2
diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index f86e4cb5..00000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "root": true,
- "env": { "browser": true },
- "extends": "@flybywiresim/eslint-config",
- "plugins": ["@typescript-eslint"],
- "parser": "@typescript-eslint/parser",
- "parserOptions": {
- "ecmaVersion": 2021,
- "sourceType": "script",
- "requireConfigFile": false
- },
- "settings": {
- "import/resolver": {
- "node": {
- "extensions": [".js", ".jsx", ".ts", ".tsx"]
- }
- }
- },
- "overrides": [
- {
- "files": ["*.mjs", "*.ts", "*.d.ts"],
- "parserOptions": { "sourceType": "module" }
- },
- {
- "files": ["*.ts", "*.tsx"],
- "rules": {
- "no-undef": "off"
- }
- }
- ],
- // overrides airbnb, use sparingly
- "rules": {
- "linebreak-style": "off",
- "object-curly-newline": ["error", { "multiline": true }],
- "max-len": "off",
- "spaced-comment": "off"
- }
-}
diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index 1fb25560..346b6224 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -1,24 +1,24 @@
## Changelog
-Update _ October 2024
+Update \_ October 2024
- feat: Prefix Command Management (28/10/2024)
- fix: role assignment typo for server announcements (22/10/2024)
-Update _ August 2024
+Update \_ August 2024
- feat: add runway information to simbriefdata (08/08/2024)
- chore: add vscode editor settings (08/08/2024)
- fix: temporarily pin typescript version to v5.4.x (see https://github.com/flybywiresim/discord-bot-utils/issues/78) (07/10/2024)
-Update _ July 2024
+Update \_ July 2024
- fix: resolve security vulnerabilities in 3rd-party packages (27/07/2024)
- fix: corrected typo in the embed for simbrief-data support-request (27/07/2024)
- docs: updated the Ground Rules on the Contributing guide page (27/07/2024)
- feat: add optional description to `/locate` panels. (27/07/2024)
-Update _ May 2024
+Update \_ May 2024
- fix: keep footer on embed expire (29/05/2024)
- feat: /clear-messages command (29/05/2024)
@@ -34,12 +34,12 @@ Update _ May 2024
- fix: lint workflow failing silently (18/05/2024)
- chore: fix eol issues on Windows (17/05/2024)
-Update _ April 2024
+Update \_ April 2024
- fix: clarify errors in timeout command (30/04/2024)
- fix: adds mod alerts to the config requirements (30/04/2024)
-Update _ March 2024
+Update \_ March 2024
- fix: birthday handler user caching issue (23/03/2024)
- feat: adds github issue command (18/03/2024)
@@ -47,7 +47,7 @@ Update _ March 2024
- fix: multiple plus symbols in zulu command (18/03/2024)
- feat: add infractions counts to buttons in list infractions command (18/03/2024)
-Update _ February 2024
+Update \_ February 2024
- fix: report message logging bug (18/02/2024)
- feat: command to list users in a role (18/02/2024)
@@ -58,7 +58,7 @@ Update _ February 2024
- fix: message edit and delete crash (01/02/2024)
- feat: add heartbeat mechanism for monitoring (01/02/2024)
-Update _ January 2024
+Update \_ January 2024
- fix: defer interaction for cache update (28/01/2024)
- fix: defer interaction on birthday list command (28/01/2024)
@@ -68,7 +68,7 @@ Update _ January 2024
- fix: ScamLog - Ignore messages entirely unless it has everyone (28/01/2024)
- fix: command names (28/01/2024)
- fix: ignore Dyno bot (27/01/2024)
-- fix: use - instead of _ in command names (27/01/2024)
+- fix: use - instead of \_ in command names (27/01/2024)
- feat: auto-generation of the command table (24/01/2024)
- feat: migrate reportedIssues command (22/01/2024)
- feat: docSearch command (22/01/2024)
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index fd689d44..d5eb8297 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -183,7 +183,7 @@ Some commands may require additional tokens. If you would like to test them out
## Adding a New Command
->Please note, this will only show the basics of adding a command.
+> Please note, this will only show the basics of adding a command.
1. Create a new file in the relevant folder within `src/commands/` and name it appropriately. `yourcommand.ts`.
2. Create your command.
@@ -224,42 +224,49 @@ import { ApplicationCommandOptionType, ApplicationCommandType } from 'discord.js
import { slashCommand, slashCommandStructure, AutocompleteCallback, makeEmbed } from '../../lib';
const data = slashCommandStructure({
- name: 'ping',
- description: 'Ping the bot for a response.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Optional command permission - always use MANAGE_SERVER and add a comment to specify overrides needed (roles, channels etc.)
- dm_permission: false, // Optional, this sets if commands can be run in DMs (global commands only)
- options: [{ // Optional, this is where you can add options to your command
- name: 'message',
- description: 'Provide some text to send back.',
- type: ApplicationCommandOptionType.String,
- max_length: 100,
- required: false,
- autocomplete: true, // Optional - This is only required if you plan on using autocomplete for your command.
- }],
+ name: 'ping',
+ description: 'Ping the bot for a response.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Optional command permission - always use MANAGE_SERVER and add a comment to specify overrides needed (roles, channels etc.)
+ dm_permission: false, // Optional, this sets if commands can be run in DMs (global commands only)
+ options: [
+ {
+ // Optional, this is where you can add options to your command
+ name: 'message',
+ description: 'Provide some text to send back.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 100,
+ required: false,
+ autocomplete: true, // Optional - This is only required if you plan on using autocomplete for your command.
+ },
+ ],
});
// Optional - This is only required if you plan on using autocomplete for your command.
const autocompleteCallback: AutocompleteCallback = ({ interaction }) => {
- // Autocomplete logic goes here
- const choices = [
- {
- name: 'Display Name',
- value: 'Value that is actually sent to your bot.'
- },
- ];
-
- // If you can't autocomplete anything respond with an empty array.
- return interaction.respond(choices);
+ // Autocomplete logic goes here
+ const choices = [
+ {
+ name: 'Display Name',
+ value: 'Value that is actually sent to your bot.',
+ },
+ ];
+
+ // If you can't autocomplete anything respond with an empty array.
+ return interaction.respond(choices);
};
-export default slashCommand(data, async ({ interaction }) => {
+export default slashCommand(
+ data,
+ async ({ interaction }) => {
const msg = interaction.options.getString('message') ?? 'Pong 🏓';
const pongEmbed = makeEmbed({ description: msg });
return interaction.reply({ embeds: [pongEmbed] });
-}, autocompleteCallback); // Optional - This is only required if you plan on using autocomplete for your command.
+ },
+ autocompleteCallback,
+); // Optional - This is only required if you plan on using autocomplete for your command.
```
## Command Permissions
diff --git a/.github/ISSUE_TEMPLATE/bug_report_beta.yaml b/.github/ISSUE_TEMPLATE/bug_report_beta.yaml
index 70fffaca..39270b0f 100644
--- a/.github/ISSUE_TEMPLATE/bug_report_beta.yaml
+++ b/.github/ISSUE_TEMPLATE/bug_report_beta.yaml
@@ -4,7 +4,7 @@ labels: [Bug]
body:
- type: markdown
attributes:
- value: "# FlyByWire Discord bot Bug Report Form"
+ value: '# FlyByWire Discord bot Bug Report Form'
- type: dropdown
id: type
attributes:
diff --git a/.github/ISSUE_TEMPLATE/feature_request_beta.yaml b/.github/ISSUE_TEMPLATE/feature_request_beta.yaml
index 09f80de0..22c8ddae 100644
--- a/.github/ISSUE_TEMPLATE/feature_request_beta.yaml
+++ b/.github/ISSUE_TEMPLATE/feature_request_beta.yaml
@@ -4,7 +4,7 @@ labels: [Request]
body:
- type: markdown
attributes:
- value: "# FBW Discord Bot Feature Request Form"
+ value: '# FBW Discord Bot Feature Request Form'
- type: dropdown
id: type
attributes:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 742f23e8..496872db 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,15 +1,15 @@
version: 2
updates:
- - package-ecosystem: npm
- directory: /
- schedule:
- interval: monthly
- commit-message:
- prefix: "chore"
- include: scope
- ignore:
- - dependency-name: "*"
- update-types: ["version-update:semver-minor", "version-update:semver-patch"]
- open-pull-requests-limit: 10
- target-branch: staging
+ - package-ecosystem: npm
+ directory: /
+ schedule:
+ interval: monthly
+ commit-message:
+ prefix: 'chore'
+ include: scope
+ ignore:
+ - dependency-name: '*'
+ update-types: ['version-update:semver-minor', 'version-update:semver-patch']
+ open-pull-requests-limit: 10
+ target-branch: staging
diff --git a/.github/workflows/cdn-upload-production.yaml b/.github/workflows/cdn-upload-production.yaml
index 5cd033cc..375118c7 100644
--- a/.github/workflows/cdn-upload-production.yaml
+++ b/.github/workflows/cdn-upload-production.yaml
@@ -1,25 +1,25 @@
name: CDN Upload - Production
on:
- workflow_dispatch:
- push:
- branches:
- - production
- paths:
- - 'assets/images**'
+ workflow_dispatch:
+ push:
+ branches:
+ - production
+ paths:
+ - 'assets/images**'
jobs:
- cdn_upload:
- if: github.repository_owner == 'flybywiresim' # Prevent running this on forks
- runs-on: ubuntu-latest
- steps:
- - name: checkout
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
- - name: Upload to CloudFlare CDN
- env:
- CLOUDFLARE_CDN_URL: ${{ secrets.CLOUDFLARE_CDN_URL_PRODUCTION }}
- CLOUDFLARE_ACCESS_KEY: ${{ secrets.CLOUDFLARE_ACCESS_KEY_PRODUCTION }}
- run: |
- ./.github/workflow_scripts/cf-cdn.sh
+ cdn_upload:
+ if: github.repository_owner == 'flybywiresim' # Prevent running this on forks
+ runs-on: ubuntu-latest
+ steps:
+ - name: checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Upload to CloudFlare CDN
+ env:
+ CLOUDFLARE_CDN_URL: ${{ secrets.CLOUDFLARE_CDN_URL_PRODUCTION }}
+ CLOUDFLARE_ACCESS_KEY: ${{ secrets.CLOUDFLARE_ACCESS_KEY_PRODUCTION }}
+ run: |
+ ./.github/workflow_scripts/cf-cdn.sh
diff --git a/.github/workflows/cdn-upload-staging.yaml b/.github/workflows/cdn-upload-staging.yaml
index 7e774ebf..71154f56 100644
--- a/.github/workflows/cdn-upload-staging.yaml
+++ b/.github/workflows/cdn-upload-staging.yaml
@@ -1,25 +1,25 @@
name: CDN Upload - Staging
on:
- workflow_dispatch:
- push:
- branches:
- - staging
- paths:
- - 'assets/images**'
+ workflow_dispatch:
+ push:
+ branches:
+ - staging
+ paths:
+ - 'assets/images**'
jobs:
- cdn_upload:
- if: github.repository_owner == 'flybywiresim' # Prevent running this on forks
- runs-on: ubuntu-latest
- steps:
- - name: checkout
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
- - name: Upload to CloudFlare CDN
- env:
- CLOUDFLARE_CDN_URL: ${{ secrets.CLOUDFLARE_CDN_URL_STAGING }}
- CLOUDFLARE_ACCESS_KEY: ${{ secrets.CLOUDFLARE_ACCESS_KEY_STAGING }}
- run: |
- ./.github/workflow_scripts/cf-cdn.sh
+ cdn_upload:
+ if: github.repository_owner == 'flybywiresim' # Prevent running this on forks
+ runs-on: ubuntu-latest
+ steps:
+ - name: checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Upload to CloudFlare CDN
+ env:
+ CLOUDFLARE_CDN_URL: ${{ secrets.CLOUDFLARE_CDN_URL_STAGING }}
+ CLOUDFLARE_ACCESS_KEY: ${{ secrets.CLOUDFLARE_ACCESS_KEY_STAGING }}
+ run: |
+ ./.github/workflow_scripts/cf-cdn.sh
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index e4f2729f..6fc283f2 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -1,33 +1,48 @@
name: PR
on:
- pull_request:
- types:
- - opened
- - synchronize
- - reopened
- - ready_for_review
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ - ready_for_review
jobs:
- lint:
- runs-on: ubuntu-latest
- if: github.event.pull_request.draft == false
- steps:
- - name: Checkout source
- uses: actions/checkout@v3
- - name: install
- run: npm install --no-optional
- - name: Check Lint
- run: npm run lint
- build:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - name: Use Node.js 18.x
- uses: actions/setup-node@v3
- with:
- node-version: '18.x'
- - name: Install dependencies
- run: npm ci
- - name: Build
- run: npm run build --if-present
+ lint:
+ name: Lint
+ runs-on: ubuntu-latest
+ if: github.event.pull_request.draft == false
+ steps:
+ - name: Checkout source
+ uses: actions/checkout@v4
+ - name: install
+ run: npm ci
+ - name: Check Lint
+ run: npm run lint
+
+ prettier:
+ name: Prettier
+ runs-on: ubuntu-latest
+ if: github.event.pull_request.draft == false
+ steps:
+ - name: Checkout source
+ uses: actions/checkout@v4
+ - name: Install dependencies
+ run: npm ci
+ - name: Run Prettier
+ run: npm run prettier:check
+
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Use Node.js 18.x
+ uses: actions/setup-node@v3
+ with:
+ node-version: '18.x'
+ - name: Install dependencies
+ run: npm ci
+ - name: Build
+ run: npm run build --if-present
diff --git a/.github/workflows/verify-changelog.yml b/.github/workflows/verify-changelog.yml
index 2c838c61..5fab6037 100644
--- a/.github/workflows/verify-changelog.yml
+++ b/.github/workflows/verify-changelog.yml
@@ -1,29 +1,29 @@
name: Verify Changelog
on:
- pull_request:
- types:
- - opened
- - synchronize
- - reopened
- - ready_for_review
- - labeled
- - unlabeled
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ - ready_for_review
+ - labeled
+ - unlabeled
jobs:
- verify:
- runs-on: ubuntu-latest
- if: ${{ github.event.pull_request.draft == false && github.repository_owner == 'flybywiresim' }} # Prevent running on forks
- steps:
- - name: checkout
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
- - name: Verify changelog
- uses: Zomzog/changelog-checker@v1.2.0
- with:
- fileName: CHANGELOG.md
- checkNotification: Simple
- noChangelogLabel: skip changelog
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ verify:
+ runs-on: ubuntu-latest
+ if: ${{ github.event.pull_request.draft == false && github.repository_owner == 'flybywiresim' }} # Prevent running on forks
+ steps:
+ - name: checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Verify changelog
+ uses: Zomzog/changelog-checker@v1.2.0
+ with:
+ fileName: CHANGELOG.md
+ checkNotification: Simple
+ noChangelogLabel: skip changelog
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 00000000..7e2f179b
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1 @@
+assets
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 00000000..05e23b16
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "singleQuote": true,
+ "printWidth": 120,
+ "endOfLine": "auto"
+}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 1e672ee6..604a8694 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,6 +1,3 @@
{
- "recommendations": [
- "editorconfig.editorconfig",
- "dbaeumer.vscode-eslint"
- ]
+ "recommendations": ["editorconfig.editorconfig", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 3e533af7..e596331e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,26 +1,31 @@
{
"typescript.tsdk": "node_modules\\typescript\\lib",
"eslint.lintTask.enable": true,
+ "eslint.useFlatConfig": true,
"eslint.format.enable": true,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"typescript.preferences.quoteStyle": "single",
+ "[yaml]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "editor.formatOnSave": true
+ },
"[markdown]": {
- "editor.defaultFormatter": "vscode.markdown-language-features",
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[json]": {
- "editor.defaultFormatter": "vscode.json-language-features",
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[typescript]": {
- "editor.defaultFormatter": "dbaeumer.vscode-eslint",
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[javascript]": {
- "editor.defaultFormatter": "dbaeumer.vscode-eslint",
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
- },
+ }
}
diff --git a/README.md b/README.md
index c67439a3..496a7f6c 100644
--- a/README.md
+++ b/README.md
@@ -13,8 +13,8 @@ This is the repository for the FlyByWire Simulations Discord Bot. You can find t
## Best Practices
-* Please use clear names for your PR's and commands.
-* Check the #discord-bot channel for regular discussions about the repository and what is being worked on.
+- Please use clear names for your PR's and commands.
+- Check the #discord-bot channel for regular discussions about the repository and what is being worked on.
## Contributing
diff --git a/config/production.json b/config/production.json
index d7288b0a..e6d14737 100644
--- a/config/production.json
+++ b/config/production.json
@@ -1,127 +1,108 @@
{
- "aircraftTypeList": {
- "a32nx": "32:1044695612337168494",
- "a380x": "38:1044695718348210177"
- },
- "channels": {
- "A32NX_SUPPORT": "785976111875751956",
- "FAQ": "751774575464939580",
- "FLIGHT_SCHOOL": "887806920252076053",
- "KNOWN_ISSUES": "771435594445226005",
- "MOD_ALERTS": "1058416774716067921",
- "MOD_LOGS": "783996780181585921",
- "ROLES": "751780817772216401",
- "SCAM_REPORT_LOGS": "932687046315737149",
- "TEAM": "846470774361161808",
- "USER_LOGS": "779944761699729418",
- "VIDEOS": "739224482945826946"
- },
- "colors": {
- "FBW_CYAN": "0x00E0FE"
- },
- "commandPermission": {
- "MANAGE_SERVER": "32"
- },
- "guildId": "738864299392630914",
- "modLogExclude": [
- "910632773117702185",
- "1195041929570832475",
- "1195045377431322754",
- "1163130801131634868",
- "1021464464928809022"
- ],
- "prefixCommandPrefix": ".",
- "prefixCommandPermissionDelay": 10000,
- "roleAssignmentIds": [
- {
- "group": "interestedIn",
- "roles": [
- {
- "id": "INTERESTED_IN_PROGRAMMING",
- "label": "Interested in Programming"
- },
- {
- "id": "INTERESTED_IN_MODELLING",
- "label": "Interested in Modelling/Design"
- }
- ]
+ "aircraftTypeList": {
+ "a32nx": "32:1044695612337168494",
+ "a380x": "38:1044695718348210177"
},
- {
- "group": "mediaAnnouncements",
- "roles": [
- {
- "id": "SERVER_ANNOUNCEMENTS",
- "label": "Server Announcements"
- },
- {
- "id": "A32NX_RELEASES",
- "label": "A32NX Releases"
- },
+ "channels": {
+ "A32NX_SUPPORT": "785976111875751956",
+ "FAQ": "751774575464939580",
+ "FLIGHT_SCHOOL": "887806920252076053",
+ "KNOWN_ISSUES": "771435594445226005",
+ "MOD_ALERTS": "1058416774716067921",
+ "MOD_LOGS": "783996780181585921",
+ "ROLES": "751780817772216401",
+ "SCAM_REPORT_LOGS": "932687046315737149",
+ "TEAM": "846470774361161808",
+ "USER_LOGS": "779944761699729418",
+ "VIDEOS": "739224482945826946"
+ },
+ "colors": {
+ "FBW_CYAN": "0x00E0FE"
+ },
+ "commandPermission": {
+ "MANAGE_SERVER": "32"
+ },
+ "guildId": "738864299392630914",
+ "modLogExclude": [
+ "910632773117702185",
+ "1195041929570832475",
+ "1195045377431322754",
+ "1163130801131634868",
+ "1021464464928809022"
+ ],
+ "prefixCommandPrefix": ".",
+ "prefixCommandPermissionDelay": 10000,
+ "roleAssignmentIds": [
{
- "id": "PROGRESS",
- "label": "Progress Updates"
+ "group": "interestedIn",
+ "roles": [
+ {
+ "id": "INTERESTED_IN_PROGRAMMING",
+ "label": "Interested in Programming"
+ },
+ {
+ "id": "INTERESTED_IN_MODELLING",
+ "label": "Interested in Modelling/Design"
+ }
+ ]
},
{
- "id": "MEDIA_ANNOUNCEMENTS",
- "label": "Media Announcements (FBW Youtube)"
+ "group": "mediaAnnouncements",
+ "roles": [
+ {
+ "id": "SERVER_ANNOUNCEMENTS",
+ "label": "Server Announcements"
+ },
+ {
+ "id": "A32NX_RELEASES",
+ "label": "A32NX Releases"
+ },
+ {
+ "id": "PROGRESS",
+ "label": "Progress Updates"
+ },
+ {
+ "id": "MEDIA_ANNOUNCEMENTS",
+ "label": "Media Announcements (FBW Youtube)"
+ }
+ ]
}
- ]
- }
- ],
- "roleGroups": {
- "BOT": [
- "ADMIN_TEAM",
- "MODERATION_TEAM",
- "BOT_DEVELOPER"
- ],
- "STAFF": [
- "ADMIN_TEAM",
- "MODERATION_TEAM"
- ],
- "SUPPORT": [
- "ADMIN_TEAM",
- "MODERATION_TEAM",
- "DEVELOPMENT_TEAM",
- "MEDIA_TEAM",
- "COMMUNITY_SUPPORT"
],
- "TEAM": [
- "ADMIN_TEAM",
- "MODERATION_TEAM",
- "DEVELOPMENT_TEAM",
- "MEDIA_TEAM",
- "FBW_EMERITUS"
+ "roleGroups": {
+ "BOT": ["ADMIN_TEAM", "MODERATION_TEAM", "BOT_DEVELOPER"],
+ "STAFF": ["ADMIN_TEAM", "MODERATION_TEAM"],
+ "SUPPORT": ["ADMIN_TEAM", "MODERATION_TEAM", "DEVELOPMENT_TEAM", "MEDIA_TEAM", "COMMUNITY_SUPPORT"],
+ "TEAM": ["ADMIN_TEAM", "MODERATION_TEAM", "DEVELOPMENT_TEAM", "MEDIA_TEAM", "FBW_EMERITUS"]
+ },
+ "roles": {
+ "A32NX_RELEASES": "748938423045193728",
+ "ADMIN_TEAM": "738864824305319936",
+ "BOT_DEVELOPER": "768888763929591818",
+ "COMMUNITY_SUPPORT": "870394933926830100",
+ "DEVELOPMENT_TEAM": "747571237475057815",
+ "FBW_EMERITUS": "878635657680027678",
+ "INTERESTED_IN_MODELLING": "739301752066801834",
+ "INTERESTED_IN_PROGRAMMING": "738865243681193994",
+ "MEDIA_ANNOUNCEMENTS": "779383764756594691",
+ "MEDIA_TEAM": "756972770214281346",
+ "MODERATION_TEAM": "739187150909866137",
+ "PROGRESS": "748938549516042281",
+ "SERVER_ANNOUNCEMENTS": "748938140701687969"
+ },
+ "threads": {
+ "BIRTHDAY_THREAD": "930923893206679573",
+ "COUNT_THREAD": "877049017102659654"
+ },
+ "units": {
+ "CELSIUS": "\u2103",
+ "DEGREES": "\u00B0"
+ },
+ "userLogExclude": [
+ "628400349979344919",
+ "910632773117702185",
+ "1195041929570832475",
+ "1195045377431322754",
+ "1163130801131634868",
+ "1021464464928809022"
]
- },
- "roles": {
- "A32NX_RELEASES": "748938423045193728",
- "ADMIN_TEAM": "738864824305319936",
- "BOT_DEVELOPER": "768888763929591818",
- "COMMUNITY_SUPPORT": "870394933926830100",
- "DEVELOPMENT_TEAM": "747571237475057815",
- "FBW_EMERITUS": "878635657680027678",
- "INTERESTED_IN_MODELLING": "739301752066801834",
- "INTERESTED_IN_PROGRAMMING": "738865243681193994",
- "MEDIA_ANNOUNCEMENTS": "779383764756594691",
- "MEDIA_TEAM": "756972770214281346",
- "MODERATION_TEAM": "739187150909866137",
- "PROGRESS": "748938549516042281",
- "SERVER_ANNOUNCEMENTS": "748938140701687969"
- },
- "threads": {
- "BIRTHDAY_THREAD": "930923893206679573",
- "COUNT_THREAD": "877049017102659654"
- },
- "units": {
- "CELSIUS": "\u2103",
- "DEGREES": "\u00B0"
- },
- "userLogExclude": [
- "628400349979344919",
- "910632773117702185",
- "1195041929570832475",
- "1195045377431322754",
- "1163130801131634868",
- "1021464464928809022"
- ]
}
diff --git a/config/staging.json b/config/staging.json
index 69be73e6..5c06576f 100644
--- a/config/staging.json
+++ b/config/staging.json
@@ -1,122 +1,103 @@
{
- "aircraftTypeList": {
- "a32nx": "32:1044695612337168494",
- "a380x": "38:1044695718348210177"
- },
- "channels": {
- "A32NX_SUPPORT": "1162805236390449202",
- "FAQ": "1162805304396877995",
- "FLIGHT_SCHOOL": "1162805386378747934",
- "KNOWN_ISSUES": "1162805409250291803",
- "MOD_ALERTS": "1208403625672450089",
- "MOD_LOGS": "1162804981338996756",
- "ROLES": "1162805319966138519",
- "SCAM_REPORT_LOGS": "1162805088813854932",
- "TEAM": "1162805139363610664",
- "USER_LOGS": "1162805003728212040",
- "VIDEOS": "1162821497795133500"
- },
- "colors": {
- "FBW_CYAN": "0x00E0FE"
- },
- "commandPermission": {
- "MANAGE_SERVER": "32"
- },
- "guildId": "1162804406681608252",
- "modLogExclude": [
- "628400349979344919",
- "910632773117702185",
- "1195041929570832475",
- "1195045377431322754",
- "1163130801131634868",
- "1021464464928809022"
- ],
- "prefixCommandPrefix": ".",
- "prefixCommandPermissionDelay": 10000,
- "roleAssignmentIds": [
- {
- "group": "interestedIn",
- "roles": [
- {
- "id": "TESTER",
- "label": "Tester"
- },
- {
- "id": "BOT_DEVELOPER",
- "label": "Bot Developer"
- },
- {
- "id": "INTERESTED_IN_PROGRAMMING",
- "label": "Interested in Programming"
- }
- ]
+ "aircraftTypeList": {
+ "a32nx": "32:1044695612337168494",
+ "a380x": "38:1044695718348210177"
+ },
+ "channels": {
+ "A32NX_SUPPORT": "1162805236390449202",
+ "FAQ": "1162805304396877995",
+ "FLIGHT_SCHOOL": "1162805386378747934",
+ "KNOWN_ISSUES": "1162805409250291803",
+ "MOD_ALERTS": "1208403625672450089",
+ "MOD_LOGS": "1162804981338996756",
+ "ROLES": "1162805319966138519",
+ "SCAM_REPORT_LOGS": "1162805088813854932",
+ "TEAM": "1162805139363610664",
+ "USER_LOGS": "1162805003728212040",
+ "VIDEOS": "1162821497795133500"
+ },
+ "colors": {
+ "FBW_CYAN": "0x00E0FE"
},
- {
- "group": "mediaAnnouncements",
- "roles": [
+ "commandPermission": {
+ "MANAGE_SERVER": "32"
+ },
+ "guildId": "1162804406681608252",
+ "modLogExclude": [
+ "628400349979344919",
+ "910632773117702185",
+ "1195041929570832475",
+ "1195045377431322754",
+ "1163130801131634868",
+ "1021464464928809022"
+ ],
+ "prefixCommandPrefix": ".",
+ "prefixCommandPermissionDelay": 10000,
+ "roleAssignmentIds": [
{
- "id": "SERVER_ANNOUNCEMENTS",
- "label": "Server Announcements"
+ "group": "interestedIn",
+ "roles": [
+ {
+ "id": "TESTER",
+ "label": "Tester"
+ },
+ {
+ "id": "BOT_DEVELOPER",
+ "label": "Bot Developer"
+ },
+ {
+ "id": "INTERESTED_IN_PROGRAMMING",
+ "label": "Interested in Programming"
+ }
+ ]
},
{
- "id": "PROGRESS_ANNOUNCEMENT",
- "label": "Progress Announcements"
+ "group": "mediaAnnouncements",
+ "roles": [
+ {
+ "id": "SERVER_ANNOUNCEMENTS",
+ "label": "Server Announcements"
+ },
+ {
+ "id": "PROGRESS_ANNOUNCEMENT",
+ "label": "Progress Announcements"
+ }
+ ]
}
- ]
- }
- ],
- "roleGroups": {
- "BOT": [
- "ADMIN_TEAM",
- "MODERATION_TEAM",
- "BOT_DEVELOPER"
- ],
- "STAFF": [
- "ADMIN_TEAM",
- "MODERATION_TEAM"
- ],
- "SUPPORT": [
- "ADMIN_TEAM",
- "MODERATION_TEAM",
- "DEVELOPMENT_TEAM",
- "MEDIA_TEAM",
- "COMMUNITY_SUPPORT"
],
- "TEAM": [
- "ADMIN_TEAM",
- "MODERATION_TEAM",
- "DEVELOPMENT_TEAM",
- "MEDIA_TEAM",
- "FBW_EMERITUS"
+ "roleGroups": {
+ "BOT": ["ADMIN_TEAM", "MODERATION_TEAM", "BOT_DEVELOPER"],
+ "STAFF": ["ADMIN_TEAM", "MODERATION_TEAM"],
+ "SUPPORT": ["ADMIN_TEAM", "MODERATION_TEAM", "DEVELOPMENT_TEAM", "MEDIA_TEAM", "COMMUNITY_SUPPORT"],
+ "TEAM": ["ADMIN_TEAM", "MODERATION_TEAM", "DEVELOPMENT_TEAM", "MEDIA_TEAM", "FBW_EMERITUS"]
+ },
+ "roles": {
+ "ADMIN_TEAM": "1162821800225419272",
+ "BOT_DEVELOPER": "1162822853306101901",
+ "COMMUNITY_SUPPORT": "1162822911745347594",
+ "DEVELOPMENT_TEAM": "1162822704248930455",
+ "FBW_EMERITUS": "1162822804832522290",
+ "INTERESTED_IN_PROGRAMMING": "1162823114753855559",
+ "MEDIA_TEAM": "1162822767079588000",
+ "MODERATION_TEAM": "1162821885202006188",
+ "PROGRESS_ANNOUNCEMENT": "1162823072089387150",
+ "SERVER_ANNOUNCEMENTS": "1162823032092495892",
+ "TESTER": "1162822140391850006"
+ },
+ "threads": {
+ "BIRTHDAY_THREAD": "1162805202487873596",
+ "COUNT_THREAD": "1162805582961594438"
+ },
+ "units": {
+ "CELSIUS": "\u2103",
+ "DEGREES": "\u00B0"
+ },
+ "userLogExclude": [
+ "628400349979344919",
+ "910632773117702185",
+ "1195041929570832475",
+ "1195045377431322754",
+ "1163130801131634868",
+ "1021464464928809022"
]
- },
- "roles": {
- "ADMIN_TEAM": "1162821800225419272",
- "BOT_DEVELOPER": "1162822853306101901",
- "COMMUNITY_SUPPORT": "1162822911745347594",
- "DEVELOPMENT_TEAM": "1162822704248930455",
- "FBW_EMERITUS": "1162822804832522290",
- "INTERESTED_IN_PROGRAMMING": "1162823114753855559",
- "MEDIA_TEAM": "1162822767079588000",
- "MODERATION_TEAM": "1162821885202006188",
- "PROGRESS_ANNOUNCEMENT": "1162823072089387150",
- "SERVER_ANNOUNCEMENTS": "1162823032092495892",
- "TESTER": "1162822140391850006"
- },
- "threads": {
- "BIRTHDAY_THREAD": "1162805202487873596",
- "COUNT_THREAD": "1162805582961594438"
- },
- "units": {
- "CELSIUS": "\u2103",
- "DEGREES": "\u00B0"
- },
- "userLogExclude": [
- "628400349979344919",
- "910632773117702185",
- "1195041929570832475",
- "1195045377431322754",
- "1163130801131634868",
- "1021464464928809022"
- ]
}
diff --git a/docs/prefix-commands.md b/docs/prefix-commands.md
index c44ca048..221daf37 100644
--- a/docs/prefix-commands.md
+++ b/docs/prefix-commands.md
@@ -68,19 +68,19 @@ These commands are not hard coded in the bot, and instead they are configured th
Additionally, there's a set of features that make these commands very flexible in use:
- **Categories**
- Commands are categorized for identifying the purpose or use of the command. Categories are manage dynamically through `/`-commands and stored in MongoDB.
+ Commands are categorized for identifying the purpose or use of the command. Categories are manage dynamically through `/`-commands and stored in MongoDB.
- **Versions**
- The content of commands are defined per Version. A version can be used to provide different content based on the context in which the command is executed. By default, there is a hard-coded `GENERIC` version available, more can be added and managed dynamically through `/`-commands and stored in MongoDB. If multiple versions exist, and no version is specified during the execution, the `GENERIC` version is shown, with buttons to select the version to be shown.
+ The content of commands are defined per Version. A version can be used to provide different content based on the context in which the command is executed. By default, there is a hard-coded `GENERIC` version available, more can be added and managed dynamically through `/`-commands and stored in MongoDB. If multiple versions exist, and no version is specified during the execution, the `GENERIC` version is shown, with buttons to select the version to be shown.
- **Content**
- For each version, it is possible (but not a must) to set the content of a command. The content is static information that is managed with `/`-commands and stored in MongoDB. Depending on the version requested, the content is loaded and shown. Content contains a Title, Body and Image.
+ For each version, it is possible (but not a must) to set the content of a command. The content is static information that is managed with `/`-commands and stored in MongoDB. Depending on the version requested, the content is loaded and shown. Content contains a Title, Body and Image.
- **Permissions**
- Two types of permissions exist: Channel permissions and Role permissions. Using permissions it is possible to block or allow the use of a command in certain channels or by certain roles.
+ Two types of permissions exist: Channel permissions and Role permissions. Using permissions it is possible to block or allow the use of a command in certain channels or by certain roles.
- **Channel Default Versions**
- For every channel, a specific version can be set as the default. In this case, even if there are multiple versions, if the command is executed without a version specified, the version set as the default for that channel is shown.
+ For every channel, a specific version can be set as the default. In this case, even if there are multiple versions, if the command is executed without a version specified, the version set as the default for that channel is shown.
### Detailed Concepts
@@ -89,17 +89,17 @@ Additionally, there's a set of features that make these commands very flexible i
Commands only contain the basic information that is needed to use them:
- `name`
- A command has a name, this is the main way to execute the command, in combination with the configured prefix. This is a required attribute.
+ A command has a name, this is the main way to execute the command, in combination with the configured prefix. This is a required attribute.
- `category`
- The category a command belongs to, a command can only belong to a single category. This is a required attribute.
+ The category a command belongs to, a command can only belong to a single category. This is a required attribute.
- `description`
- The description of commands gives a short and brief overview of what the command is used for. This is a required attribute.
+ The description of commands gives a short and brief overview of what the command is used for. This is a required attribute.
- `aliases`
- A comma separated list for aliases for this command, each alias can be used to call the command instead of the name of the command. This is an optional attribute. Default value is empty.
+ A comma separated list for aliases for this command, each alias can be used to call the command instead of the name of the command. This is an optional attribute. Default value is empty.
- `is_embed`
- A boolean attribute that identifies if the output should be posted as an Embed. If set to `False`, it will be shown as a regular text output, which is useful for simple image commands, or for simple links. This is an optional attribute. Default value is `False`.
+ A boolean attribute that identifies if the output should be posted as an Embed. If set to `False`, it will be shown as a regular text output, which is useful for simple image commands, or for simple links. This is an optional attribute. Default value is `False`.
- `embed_color`
- Embeds in Discord have a color to the left, which can be used to give it a special look. By setting this value, you can change the default `FBW_CYAN` to other special colors. Colors are defined in the Config JSON file. This is an optional attribute. Default value is `FBW_CYAN` (only value currently in the `production.json` config file).
+ Embeds in Discord have a color to the left, which can be used to give it a special look. By setting this value, you can change the default `FBW_CYAN` to other special colors. Colors are defined in the Config JSON file. This is an optional attribute. Default value is `FBW_CYAN` (only value currently in the `production.json` config file).
Note that a Command does not contain any information about the content itself. This is because the content is specific per version and is described below.
@@ -108,13 +108,13 @@ Note that a Command does not contain any information about the content itself. T
Content contains the actual information that is shown to the user when executing the command. Depending on the configuration of the command itself, this content will be displayed as an Embed or as standard text. The following attributes are available:
- `version`
- The version this content applies to, this is a reference to one of the existing versions in the bot. This is a required attribute.
+ The version this content applies to, this is a reference to one of the existing versions in the bot. This is a required attribute.
- `title`
- The title of the content, this will be shown as the title of the Embed, or as the first bold line of the text output in case the command is not an embed. This is a required attribute.
+ The title of the content, this will be shown as the title of the Embed, or as the first bold line of the text output in case the command is not an embed. This is a required attribute.
- `content`
- A markdown capable string that identifies the actual content of the specified version. It can be up to 2048 Unicode characters, including emojis. This is an optional attribute. The default value is an empty (`null`), in which case it will not be shown as part of the output.
+ A markdown capable string that identifies the actual content of the specified version. It can be up to 2048 Unicode characters, including emojis. This is an optional attribute. The default value is an empty (`null`), in which case it will not be shown as part of the output.
- `image`
- A URL that refers to an image that should be shown as part of the content if the command is an Embed. For text-style commands, the URL should be part of the content itself so Discord automatically loads it as a preview. This is an optional attribute. The default value is empty (`null`).
+ A URL that refers to an image that should be shown as part of the content if the command is an Embed. For text-style commands, the URL should be part of the content itself so Discord automatically loads it as a preview. This is an optional attribute. The default value is empty (`null`).
The `image` behavior can be surprising, but is chosen because it is not possible to just 'add' a message to a text-style response, unless if it is uploaded, and the decision was made to not upload an image very time the command is executed. What can be done is use markdown to load the image using the link syntax. Discord will then automatically load it as a preview.
@@ -123,96 +123,96 @@ The `image` behavior can be surprising, but is chosen because it is not possible
Categories are used to group commands together. This is mostly useful for when the help command is called to get the list of available commands for a specific category. It groups them together and makes it easy to identify. Categories have the following attributes:
- `name`
- The name as how it should be shown to the users and in any output. This is a required attribute.
+ The name as how it should be shown to the users and in any output. This is a required attribute.
- `emoji`
- An emoji to identify the category, this will be shown next to the category whenever shown. This is an optional attribute. The default value is empty (`null`), in which case it isn't shown.
+ An emoji to identify the category, this will be shown next to the category whenever shown. This is an optional attribute. The default value is empty (`null`), in which case it isn't shown.
#### Version
Versions are useful if you want the same command to have different contents based on the context in which it is executed. An example use for FlyByWire Simulations is to use it to have a single command that gives different output based on the product for which it is requested. Later the impact of Versions will be described more. Versions have the following attributes:
- `name`
- A name for the version, this is how the version is identified in the different commands on how to manage the content of commands. This is a required attribute.
+ A name for the version, this is how the version is identified in the different commands on how to manage the content of commands. This is a required attribute.
- `emoji`
- The emoji associated with the version. When a command is executed without any version context, a GENERIC content will be displayed that offers the user the choice to get the details for a specific version. It does so by showing the emojis as buttons for the user to select. This is a required attribute.
+ The emoji associated with the version. When a command is executed without any version context, a GENERIC content will be displayed that offers the user the choice to get the details for a specific version. It does so by showing the emojis as buttons for the user to select. This is a required attribute.
- `alias`
- This is a command alias for the version. By executing ` `, the user can get the content for a specific version directly, instead of going through the GENERIC content. This is a required attribute.
+ This is a command alias for the version. By executing ` `, the user can get the content for a specific version directly, instead of going through the GENERIC content. This is a required attribute.
- `is_enabled`
- A boolean attribute that can enable or disable a version. When this is set to `False`, the version will not be exposed to users. It will not show up in the selection of versions for the GENERIC content, and the alias will not work. This allows for versions and the content for those versions to be created ahead of enabling them. This is an optional attribute. The default value is `False`.
+ A boolean attribute that can enable or disable a version. When this is set to `False`, the version will not be exposed to users. It will not show up in the selection of versions for the GENERIC content, and the alias will not work. This allows for versions and the content for those versions to be created ahead of enabling them. This is an optional attribute. The default value is `False`.
#### Version Behavior
Users can execute commands in two different ways, and they each result in different behavior. Any time a non-GENERIC version is mentioned, it must be enabled. Disable versions will never show up:
- ``
- This is the direct way of executing a command, depending on the available content, several things might happen:
+ This is the direct way of executing a command, depending on the available content, several things might happen:
- If no Channel Default Version is configured for the channel in which the command is executed:
- GENERIC version and one or more other versions have content:
- The GENERIC content is shown and the user is given a choice underneath it with buttons containing the emjois of the other versions with content. When the user clicks on one of the buttons, the GENERIC content is removed and a new message is send with the content of the selected version.
+ The GENERIC content is shown and the user is given a choice underneath it with buttons containing the emjois of the other versions with content. When the user clicks on one of the buttons, the GENERIC content is removed and a new message is send with the content of the selected version.
- Only GENERIC version has content:
- The GENERIC content is shown, and the user is not given a choice of other versions, as there is no choice available.
+ The GENERIC content is shown, and the user is not given a choice of other versions, as there is no choice available.
- No GENERIC content is set:
- No response is given to the user:
+ No response is given to the user:
- No content is set at all:
- No response is given to the user.
+ No response is given to the user.
- If a Channel Default Version is configured for the channel in which the command is executed:
- Content is set for the Channel Default Version:
- The content for that version is shown to the user directly.
+ The content for that version is shown to the user directly.
- No content is set for the Channel Default Version, but it does exist for the GENERIC version:
- The content for the GENERIC version is shown, but no selection buttons are shown.
+ The content for the GENERIC version is shown, but no selection buttons are shown.
- No content is set for the Channel Default version, and no content exists for the GENERIC version:
- No response is given to the user.
+ No response is given to the user.
- No content is set at all:
- No response is given to the user.
+ No response is given to the user.
- ` `
- This directly requests the content for the specified version:
+ This directly requests the content for the specified version:
- Content is set for the specified version:
- The content for the specified version is shown to the user directly.
+ The content for the specified version is shown to the user directly.
- No content is set for the specified version, GENERIC version and one or more other versions have content:
- The GENERIC content is shown and the user is given a choice underneath it with buttons containing the emjois of the other versions with content. When the user clicks on one of the buttons, the GENERIC content is removed and a new message is send with the content of the selected version.
+ The GENERIC content is shown and the user is given a choice underneath it with buttons containing the emjois of the other versions with content. When the user clicks on one of the buttons, the GENERIC content is removed and a new message is send with the content of the selected version.
- Content is not set for the specified version and only GENERIC version has content:
- The GENERIC content is shown, and the user is not given a choice of other versions, as there is no choice available.
+ The GENERIC content is shown, and the user is not given a choice of other versions, as there is no choice available.
- No content is set for the specified version and no GENERIC content is set:
- No response is given to the user.
+ No response is given to the user.
- No content is set at all:
- No response is given to the user.
+ No response is given to the user.
#### Channel Default Version
It is possible to set a version as the default for a specific channel. By doing so, whenever someone executes the command directly (`` in that channel, it will automatically default to that version and not first post the GENERIC version with choices. This bypasses the choice menu and allows for an optimized experience for users. Two attributes need to be provided during configuration:
- `channel`
- The Discord channel to which the version should be defaulted to. This is a required attribute.
+ The Discord channel to which the version should be defaulted to. This is a required attribute.
- `version`
- The version that should be the default for this channel. It is possible to select a disabled version for this, but if you do so and the command is executed in the channel, no output will be shown. This is a required attribute.
+ The version that should be the default for this channel. It is possible to select a disabled version for this, but if you do so and the command is executed in the channel, no output will be shown. This is a required attribute.
#### Permission
Permissions can be set on commands so there are limitations to who can use the command and/or in which channels they can be used. The permission behavior is described below. Permissions have the following attributes:
- `roles`
- A list of Discord roles that either have access or do not have access to the command. This is an optional attribute. The default is an empty list, which results in the roles of the user not being checked.
+ A list of Discord roles that either have access or do not have access to the command. This is an optional attribute. The default is an empty list, which results in the roles of the user not being checked.
- `role-blocklist`
- A boolean attribute that identifies if the list of roles is blocked from using the command (`True`) or allowed to use the command (`False`). This is an optional attribute. The default value is `False`, meaning that if a `roles` list is set, only users with at least one of those roles can execute the command.
+ A boolean attribute that identifies if the list of roles is blocked from using the command (`True`) or allowed to use the command (`False`). This is an optional attribute. The default value is `False`, meaning that if a `roles` list is set, only users with at least one of those roles can execute the command.
- `channels`
- A list of Disord channels in which the command can either be executed or not executed. This is an optional attirubute. The default is an empty list, which results in the channel not being checked.
+ A list of Disord channels in which the command can either be executed or not executed. This is an optional attirubute. The default is an empty list, which results in the channel not being checked.
- `channel-blocklist`
- A boolean attribute that identifies if the list of channels is blocked from command execution (`True`) or allowed to execute the command in (`False`). This is an optional attribute. The default value is `False`, meaning that if a `channels` list is set, the command is only allowed to be executed in one of those channels.
+ A boolean attribute that identifies if the list of channels is blocked from command execution (`True`) or allowed to execute the command in (`False`). This is an optional attribute. The default value is `False`, meaning that if a `channels` list is set, the command is only allowed to be executed in one of those channels.
- `quiet-errors`
- A boolean attribute, which if set to `True` will not display any warning to the user and will quietly fail the command execution if the permissions do not allow the execution of the command. This is an optional attribute. The default value is `False`.
+ A boolean attribute, which if set to `True` will not display any warning to the user and will quietly fail the command execution if the permissions do not allow the execution of the command. This is an optional attribute. The default value is `False`.
- `verbose-errors`
- A boolean attribute, which if set to `True` will show detailed output about the permission violated and who (role violation) or where (channel violation) the command can be executed. This is an optional attribute. The default value is `False`.
+ A boolean attribute, which if set to `True` will show detailed output about the permission violated and who (role violation) or where (channel violation) the command can be executed. This is an optional attribute. The default value is `False`.
##### Permission Behavior
Permissions are checked in the following flow:
- If there is a list of `roles` defined, the user is checked if they have any of the roles.
- - If `role-blocklist` is `False` and the user *does not* have any of the roles, the execution of the command is blocked.
- - If `role-blocklist` is `True` and the user *does* have any of the roles, the execution of the command is blocked.
+ - If `role-blocklist` is `False` and the user _does not_ have any of the roles, the execution of the command is blocked.
+ - If `role-blocklist` is `True` and the user _does_ have any of the roles, the execution of the command is blocked.
- If there is a list of `channels` defined, the list is checked to see if the channel in which the command is executed, is part of the list.
- - If `channel-blocklist` is `False` and the command *is not* executed in any of the channels, the execution of the command is blocked.
- - If `channel-blocklist` is `True` and the command *is* executed in any of the channels, the execution of the command is blocked.
+ - If `channel-blocklist` is `False` and the command _is not_ executed in any of the channels, the execution of the command is blocked.
+ - If `channel-blocklist` is `True` and the command _is_ executed in any of the channels, the execution of the command is blocked.
##### Errors
@@ -231,14 +231,15 @@ If both are set to `True`, `quiet-errors` takes precedence.
The bot will require a MongoDB environment set up. There are a few settings to configure:
- **Config JSON**:
+
- `prefixCommandPrefix`
- A String that will be the prefix for command that will be used by the user to execute commands. For example `.` to execute commands like `.help`
+ A String that will be the prefix for command that will be used by the user to execute commands. For example `.` to execute commands like `.help`
- `prefixCommandPermissionDelay`
- A number in milliseconds that identifies the delay before the message about invalid permissions is deleted.
+ A number in milliseconds that identifies the delay before the message about invalid permissions is deleted.
- **Environment Variable**:
- `CACHE_REFRESH_INTERVAL`
- A number in milliseconds that is used to automatically refresh the cache from the database, to make sure the cache remains up to date.
+ A number in milliseconds that is used to automatically refresh the cache from the database, to make sure the cache remains up to date.
### Management Capabilities
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 00000000..e378eae1
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,47 @@
+import eslint from '@eslint/js';
+import tseslint from 'typescript-eslint';
+import recommendedConfig from 'eslint-plugin-prettier/recommended';
+
+export default tseslint.config(
+ eslint.configs.recommended,
+ ...tseslint.configs.recommendedTypeChecked,
+ recommendedConfig,
+ {
+ name: 'Main Config',
+ languageOptions: {
+ parserOptions: {
+ project: true,
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+ rules: {
+ 'prettier/prettier': ['error', {}, { usePrettierrc: true }],
+
+ 'no-unused-vars': 'off', // Ensure eslint doesn't care about unused variables.
+ '@typescript-eslint/no-unused-vars': [
+ 'error',
+ {
+ varsIgnorePattern: '^_',
+ argsIgnorePattern: '^_',
+ caughtErrorsIgnorePattern: '^_',
+ destructuredArrayIgnorePattern: '^_',
+ },
+ ],
+
+ // The rules below are proposed to best leverage eslint's capabilities and reduce work during code review.
+ 'no-await-in-loop': 'error', // possible performance impact - see: https://eslint.org/docs/latest/rules/no-await-in-loop
+ 'no-constructor-return': 'error', // Returning values from constructors is bad practice and can be confusing as constructors always return the object they instantiated (this).
+ 'no-self-compare': 'error', // Saves time during code review. (https://eslint.org/docs/latest/rules/no-self-compare)
+ 'no-unreachable-loop': 'error', // Saves time during code review by preventing unnecessary one-time-loops. (https://eslint.org/docs/latest/rules/no-unreachable-loop)
+ 'no-console': 'warn', // Using winston should be preferred over direct console.log statements.
+ },
+ },
+ {
+ files: ['**/*.mjs', '**/*.cjs', '**/*.js'],
+ extends: [tseslint.configs.disableTypeChecked],
+ },
+ {
+ // DO NOT ADD ANY PROPERTIES TO THIS OBJECT
+ ignores: ['node_modules', 'build', 'assets'],
+ },
+);
diff --git a/nodemon.json b/nodemon.json
index 923402ab..253e4449 100644
--- a/nodemon.json
+++ b/nodemon.json
@@ -1,9 +1,9 @@
{
- "restartable": "rs",
- "ignore": ["node_modules/"],
- "watch": ["src/"],
- "execMap": {
- "ts": "ts-node"
- },
- "ext": "js,json,ts"
+ "restartable": "rs",
+ "ignore": ["node_modules/"],
+ "watch": ["src/"],
+ "execMap": {
+ "ts": "ts-node"
+ },
+ "ext": "js,json,ts"
}
diff --git a/package-lock.json b/package-lock.json
index 28533493..76678cb8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,7735 +1,5960 @@
{
- "name": "fbw-discord-bot",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "fbw-discord-bot",
- "version": "1.0.0",
- "license": "AGPL-3.0",
- "dependencies": {
- "@aws-sdk/client-s3": "^3.499.0",
- "@aws-sdk/lib-storage": "^3.499.0",
- "@hokify/agenda": "^6.0.0",
- "@octokit/request": "^8.1.1",
- "bad-words": "^3.0.4",
- "cache-manager": "^5.7.6",
- "config": "^3.3.9",
- "discord.js": "^14.11.0",
- "jsdom": "^23.2.0",
- "moment": "^2.29.4",
- "mongoose": "^8.0.3",
- "node-fetch": "^2.6.10",
- "winston": "^3.3.4"
- },
- "devDependencies": {
- "@flybywiresim/eslint-config": "^0.1.0",
- "@types/bad-words": "^3.0.3",
- "@types/config": "^3.3.1",
- "@types/jsdom": "^21.1.6",
- "@types/node": "^18.0.0",
- "@types/node-fetch": "^2.6.10",
- "@typescript-eslint/eslint-plugin": "^6.18.0",
- "@typescript-eslint/parser": "^6.18.0",
- "dotenv": "^16.0.0",
- "eslint": "^7.29.0",
- "nodemon": "^3.0.2",
- "ts-node": "^10.4.0",
- "typescript": "~5.4.5"
- },
- "engines": {
- "node": "18.x"
- }
- },
- "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/@asamuzakjp/dom-selector": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-2.0.2.tgz",
- "integrity": "sha512-x1KXOatwofR6ZAYzXRBL5wrdV0vwNxlTCK9NCuLqAzQYARqGcvFwiJA6A1ERuh+dgeA4Dxm3JBYictIes+SqUQ==",
- "dependencies": {
- "bidi-js": "^1.0.3",
- "css-tree": "^2.3.1",
- "is-potential-custom-element-name": "^1.0.1"
- }
- },
- "node_modules/@aws-crypto/crc32": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz",
- "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==",
- "dependencies": {
- "@aws-crypto/util": "^3.0.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/crc32/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/crc32c": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz",
- "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==",
- "dependencies": {
- "@aws-crypto/util": "^3.0.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/crc32c/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/ie11-detection": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz",
- "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==",
- "dependencies": {
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/sha1-browser": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz",
- "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==",
- "dependencies": {
- "@aws-crypto/ie11-detection": "^3.0.0",
- "@aws-crypto/supports-web-crypto": "^3.0.0",
- "@aws-crypto/util": "^3.0.0",
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-locate-window": "^3.0.0",
- "@aws-sdk/util-utf8-browser": "^3.0.0",
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/sha1-browser/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/sha256-browser": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz",
- "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==",
- "dependencies": {
- "@aws-crypto/ie11-detection": "^3.0.0",
- "@aws-crypto/sha256-js": "^3.0.0",
- "@aws-crypto/supports-web-crypto": "^3.0.0",
- "@aws-crypto/util": "^3.0.0",
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-locate-window": "^3.0.0",
- "@aws-sdk/util-utf8-browser": "^3.0.0",
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/sha256-js": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz",
- "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==",
- "dependencies": {
- "@aws-crypto/util": "^3.0.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/sha256-js/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/supports-web-crypto": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz",
- "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==",
- "dependencies": {
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/util": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz",
- "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==",
- "dependencies": {
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-utf8-browser": "^3.0.0",
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-sdk/client-cognito-identity": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.485.0.tgz",
- "integrity": "sha512-1SYhvRu/dNqQ5HcIgm7wIpyn1FsthbgG04o6QyVAnfOxmawFt4nqCEtNCwsmlX7o1ZCTYY+qNrozb7XZy+GKSQ==",
- "optional": true,
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/client-sts": "3.485.0",
- "@aws-sdk/core": "3.485.0",
- "@aws-sdk/credential-provider-node": "3.485.0",
- "@aws-sdk/middleware-host-header": "3.485.0",
- "@aws-sdk/middleware-logger": "3.485.0",
- "@aws-sdk/middleware-recursion-detection": "3.485.0",
- "@aws-sdk/middleware-signing": "3.485.0",
- "@aws-sdk/middleware-user-agent": "3.485.0",
- "@aws-sdk/region-config-resolver": "3.485.0",
- "@aws-sdk/types": "3.485.0",
- "@aws-sdk/util-endpoints": "3.485.0",
- "@aws-sdk/util-user-agent-browser": "3.485.0",
- "@aws-sdk/util-user-agent-node": "3.485.0",
- "@smithy/config-resolver": "^2.0.23",
- "@smithy/core": "^1.2.2",
- "@smithy/fetch-http-handler": "^2.3.2",
- "@smithy/hash-node": "^2.0.18",
- "@smithy/invalid-dependency": "^2.0.16",
- "@smithy/middleware-content-length": "^2.0.18",
- "@smithy/middleware-endpoint": "^2.3.0",
- "@smithy/middleware-retry": "^2.0.26",
- "@smithy/middleware-serde": "^2.0.16",
- "@smithy/middleware-stack": "^2.0.10",
- "@smithy/node-config-provider": "^2.1.9",
- "@smithy/node-http-handler": "^2.2.2",
- "@smithy/protocol-http": "^3.0.12",
- "@smithy/smithy-client": "^2.2.1",
- "@smithy/types": "^2.8.0",
- "@smithy/url-parser": "^2.0.16",
- "@smithy/util-base64": "^2.0.1",
- "@smithy/util-body-length-browser": "^2.0.1",
- "@smithy/util-body-length-node": "^2.1.0",
- "@smithy/util-defaults-mode-browser": "^2.0.24",
- "@smithy/util-defaults-mode-node": "^2.0.32",
- "@smithy/util-endpoints": "^1.0.8",
- "@smithy/util-retry": "^2.0.9",
- "@smithy/util-utf8": "^2.0.2",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3": {
- "version": "3.499.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.499.0.tgz",
- "integrity": "sha512-4ssQqde/iY5fTJbWuFPzPuECtihdCAA9tfluv6fXYCJS3wMLf9x21qp6b7fIbUf6vjOJ2edmYd+DXk+0CMnTFg==",
- "dependencies": {
- "@aws-crypto/sha1-browser": "3.0.0",
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/client-sts": "3.499.0",
- "@aws-sdk/core": "3.496.0",
- "@aws-sdk/credential-provider-node": "3.499.0",
- "@aws-sdk/middleware-bucket-endpoint": "3.496.0",
- "@aws-sdk/middleware-expect-continue": "3.496.0",
- "@aws-sdk/middleware-flexible-checksums": "3.496.0",
- "@aws-sdk/middleware-host-header": "3.496.0",
- "@aws-sdk/middleware-location-constraint": "3.496.0",
- "@aws-sdk/middleware-logger": "3.496.0",
- "@aws-sdk/middleware-recursion-detection": "3.496.0",
- "@aws-sdk/middleware-sdk-s3": "3.499.0",
- "@aws-sdk/middleware-signing": "3.496.0",
- "@aws-sdk/middleware-ssec": "3.498.0",
- "@aws-sdk/middleware-user-agent": "3.496.0",
- "@aws-sdk/region-config-resolver": "3.496.0",
- "@aws-sdk/signature-v4-multi-region": "3.499.0",
- "@aws-sdk/types": "3.496.0",
- "@aws-sdk/util-endpoints": "3.496.0",
- "@aws-sdk/util-user-agent-browser": "3.496.0",
- "@aws-sdk/util-user-agent-node": "3.496.0",
- "@aws-sdk/xml-builder": "3.496.0",
- "@smithy/config-resolver": "^2.1.1",
- "@smithy/core": "^1.3.1",
- "@smithy/eventstream-serde-browser": "^2.1.1",
- "@smithy/eventstream-serde-config-resolver": "^2.1.1",
- "@smithy/eventstream-serde-node": "^2.1.1",
- "@smithy/fetch-http-handler": "^2.4.1",
- "@smithy/hash-blob-browser": "^2.1.1",
- "@smithy/hash-node": "^2.1.1",
- "@smithy/hash-stream-node": "^2.1.1",
- "@smithy/invalid-dependency": "^2.1.1",
- "@smithy/md5-js": "^2.1.1",
- "@smithy/middleware-content-length": "^2.1.1",
- "@smithy/middleware-endpoint": "^2.4.1",
- "@smithy/middleware-retry": "^2.1.1",
- "@smithy/middleware-serde": "^2.1.1",
- "@smithy/middleware-stack": "^2.1.1",
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/node-http-handler": "^2.3.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/smithy-client": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "@smithy/url-parser": "^2.1.1",
- "@smithy/util-base64": "^2.1.1",
- "@smithy/util-body-length-browser": "^2.1.1",
- "@smithy/util-body-length-node": "^2.2.1",
- "@smithy/util-defaults-mode-browser": "^2.1.1",
- "@smithy/util-defaults-mode-node": "^2.1.1",
- "@smithy/util-endpoints": "^1.1.1",
- "@smithy/util-retry": "^2.1.1",
- "@smithy/util-stream": "^2.1.1",
- "@smithy/util-utf8": "^2.1.1",
- "@smithy/util-waiter": "^2.1.1",
- "fast-xml-parser": "4.2.5",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sso": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.496.0.tgz",
- "integrity": "sha512-fuaMuxKg7CMUsP9l3kxYWCOxFsBjdA0xj5nlikaDm1661/gB4KkAiGqRY8LsQkpNXvXU8Nj+f7oCFADFyGYzyw==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/core": "3.496.0",
- "@aws-sdk/middleware-host-header": "3.496.0",
- "@aws-sdk/middleware-logger": "3.496.0",
- "@aws-sdk/middleware-recursion-detection": "3.496.0",
- "@aws-sdk/middleware-user-agent": "3.496.0",
- "@aws-sdk/region-config-resolver": "3.496.0",
- "@aws-sdk/types": "3.496.0",
- "@aws-sdk/util-endpoints": "3.496.0",
- "@aws-sdk/util-user-agent-browser": "3.496.0",
- "@aws-sdk/util-user-agent-node": "3.496.0",
- "@smithy/config-resolver": "^2.1.1",
- "@smithy/core": "^1.3.1",
- "@smithy/fetch-http-handler": "^2.4.1",
- "@smithy/hash-node": "^2.1.1",
- "@smithy/invalid-dependency": "^2.1.1",
- "@smithy/middleware-content-length": "^2.1.1",
- "@smithy/middleware-endpoint": "^2.4.1",
- "@smithy/middleware-retry": "^2.1.1",
- "@smithy/middleware-serde": "^2.1.1",
- "@smithy/middleware-stack": "^2.1.1",
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/node-http-handler": "^2.3.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/smithy-client": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "@smithy/url-parser": "^2.1.1",
- "@smithy/util-base64": "^2.1.1",
- "@smithy/util-body-length-browser": "^2.1.1",
- "@smithy/util-body-length-node": "^2.2.1",
- "@smithy/util-defaults-mode-browser": "^2.1.1",
- "@smithy/util-defaults-mode-node": "^2.1.1",
- "@smithy/util-endpoints": "^1.1.1",
- "@smithy/util-retry": "^2.1.1",
- "@smithy/util-utf8": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sts": {
- "version": "3.499.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.499.0.tgz",
- "integrity": "sha512-Eyj9STw2DXMtXL5V/v0HYHO6+JjGPi257M5IYyxwqlvRchq6jbOsedobfxclB/gBUyBRtZdnyAIS8uCKjb4kpA==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/core": "3.496.0",
- "@aws-sdk/credential-provider-node": "3.499.0",
- "@aws-sdk/middleware-host-header": "3.496.0",
- "@aws-sdk/middleware-logger": "3.496.0",
- "@aws-sdk/middleware-recursion-detection": "3.496.0",
- "@aws-sdk/middleware-user-agent": "3.496.0",
- "@aws-sdk/region-config-resolver": "3.496.0",
- "@aws-sdk/types": "3.496.0",
- "@aws-sdk/util-endpoints": "3.496.0",
- "@aws-sdk/util-user-agent-browser": "3.496.0",
- "@aws-sdk/util-user-agent-node": "3.496.0",
- "@smithy/config-resolver": "^2.1.1",
- "@smithy/core": "^1.3.1",
- "@smithy/fetch-http-handler": "^2.4.1",
- "@smithy/hash-node": "^2.1.1",
- "@smithy/invalid-dependency": "^2.1.1",
- "@smithy/middleware-content-length": "^2.1.1",
- "@smithy/middleware-endpoint": "^2.4.1",
- "@smithy/middleware-retry": "^2.1.1",
- "@smithy/middleware-serde": "^2.1.1",
- "@smithy/middleware-stack": "^2.1.1",
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/node-http-handler": "^2.3.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/smithy-client": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "@smithy/url-parser": "^2.1.1",
- "@smithy/util-base64": "^2.1.1",
- "@smithy/util-body-length-browser": "^2.1.1",
- "@smithy/util-body-length-node": "^2.2.1",
- "@smithy/util-defaults-mode-browser": "^2.1.1",
- "@smithy/util-defaults-mode-node": "^2.1.1",
- "@smithy/util-endpoints": "^1.1.1",
- "@smithy/util-middleware": "^2.1.1",
- "@smithy/util-retry": "^2.1.1",
- "@smithy/util-utf8": "^2.1.1",
- "fast-xml-parser": "4.2.5",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/core": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.496.0.tgz",
- "integrity": "sha512-yT+ug7Cw/3eJi7x2es0+46x12+cIJm5Xv+GPWsrTFD1TKgqO/VPEgfDtHFagDNbFmjNQA65Ygc/kEdIX9ICX/A==",
- "dependencies": {
- "@smithy/core": "^1.3.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/signature-v4": "^2.1.1",
- "@smithy/smithy-client": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-env": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.496.0.tgz",
- "integrity": "sha512-lukQMJ8SWWP5RqkRNOHi/H+WMhRvSWa3Fc5Jf/VP6xHiPLfF1XafcvthtV91e0VwPCiseI+HqChrcGq8pvnxHw==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/property-provider": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.496.0.tgz",
- "integrity": "sha512-2nD1jp1sIwcQaWK1y/9ruQOkW16RUxZpzgjbW/gnK3iiUXwx+/FNQWxshud+GTSx3Q4x6eIhqsbjtP4VVPPuUA==",
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.496.0",
- "@aws-sdk/credential-provider-process": "3.496.0",
- "@aws-sdk/credential-provider-sso": "3.496.0",
- "@aws-sdk/credential-provider-web-identity": "3.496.0",
- "@aws-sdk/types": "3.496.0",
- "@smithy/credential-provider-imds": "^2.2.1",
- "@smithy/property-provider": "^2.1.1",
- "@smithy/shared-ini-file-loader": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-node": {
- "version": "3.499.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.499.0.tgz",
- "integrity": "sha512-EsiSevVmcVSMIq7D9siSH/XVc5I0vMntg1rx6KQdng1Fq8X/RBL5t9wSWEwOl7KFo5HlEsWrLWIpo1WHuzIL/w==",
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.496.0",
- "@aws-sdk/credential-provider-ini": "3.496.0",
- "@aws-sdk/credential-provider-process": "3.496.0",
- "@aws-sdk/credential-provider-sso": "3.496.0",
- "@aws-sdk/credential-provider-web-identity": "3.496.0",
- "@aws-sdk/types": "3.496.0",
- "@smithy/credential-provider-imds": "^2.2.1",
- "@smithy/property-provider": "^2.1.1",
- "@smithy/shared-ini-file-loader": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-process": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.496.0.tgz",
- "integrity": "sha512-/YZscCTGOKVmGr916Th4XF8Sz6JDtZ/n2loHG9exok9iy/qIbACsTRNLP9zexPxhPoue/oZqecY5xbVljfY34A==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/property-provider": "^2.1.1",
- "@smithy/shared-ini-file-loader": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-sso": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.496.0.tgz",
- "integrity": "sha512-eP7GxpT2QYubSDG7uk1GJW4eNymZCq65IxDyEFCXOP/kfqkxriCY+iVEFG6/Mo3LxvgrgHXU4jxrCAXMAWN43g==",
- "dependencies": {
- "@aws-sdk/client-sso": "3.496.0",
- "@aws-sdk/token-providers": "3.496.0",
- "@aws-sdk/types": "3.496.0",
- "@smithy/property-provider": "^2.1.1",
- "@smithy/shared-ini-file-loader": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-web-identity": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.496.0.tgz",
- "integrity": "sha512-IbP+qLlvJSpNPj+zW6TtFuLRTK5Tf0hW+2pom4vFyi5YSH4pn8UOC136UdewX8vhXGS9BJQ5zBDMasIyl5VeGQ==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/property-provider": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-host-header": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.496.0.tgz",
- "integrity": "sha512-jUdPpSJeqCYXf6hSjfwsfHway7peIV8Vz51w/BN91bF4vB/bYwAC5o9/iJiK/EoByp5asxA8fg9wFOyGjzdbLg==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-logger": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.496.0.tgz",
- "integrity": "sha512-EwMVSY6iBMeGbVnvwdaFl/ClMS/YWtxCAo+bcEtgk8ltRuo7qgbJem8Km/fvWC1vdWvIbe4ArdJ8iGzq62ffAw==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-recursion-detection": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.496.0.tgz",
- "integrity": "sha512-+IuOcFsfqg2WAnaEzH6KhVbicqCxtOq9w3DH2jwTpddRlCx2Kqf6wCzg8luhHRGyjBZdsbIS+OXwyMevoppawA==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-signing": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.496.0.tgz",
- "integrity": "sha512-Oq73Brs4IConvWnRlh8jM1V7LHoTw9SVQklu/QW2FPlNrB3B8fuTdWHHYIWv7ybw1bykXoCY99v865Mmq/Or/g==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/property-provider": "^2.1.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/signature-v4": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-middleware": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-user-agent": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.496.0.tgz",
- "integrity": "sha512-+iMtRxFk0GmFWNUF4ilxylOQd9PZdR4ZC9jkcPIh1PZlvKtpCyFywKlk5RRZKklSoJ/CttcqwhMvOXTNbWm/0w==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@aws-sdk/util-endpoints": "3.496.0",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/region-config-resolver": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.496.0.tgz",
- "integrity": "sha512-URrNVOPHPgEDm6QFu6lDC2cUFs+Jx23mA3jEwCvoKlXiEY/ZoWjH8wlX3OMUlLrF1qoUTuD03jjrJzF6zoCgug==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-config-provider": "^2.2.1",
- "@smithy/util-middleware": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/token-providers": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.496.0.tgz",
- "integrity": "sha512-fyi8RcObEa1jNETJdc2H6q9VHrrdKCj/b6+fbLvymb7mUVRd0aWUn+24SNUImnSOnrwYnwaMfyyEC388X4MbFQ==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/middleware-host-header": "3.496.0",
- "@aws-sdk/middleware-logger": "3.496.0",
- "@aws-sdk/middleware-recursion-detection": "3.496.0",
- "@aws-sdk/middleware-user-agent": "3.496.0",
- "@aws-sdk/region-config-resolver": "3.496.0",
- "@aws-sdk/types": "3.496.0",
- "@aws-sdk/util-endpoints": "3.496.0",
- "@aws-sdk/util-user-agent-browser": "3.496.0",
- "@aws-sdk/util-user-agent-node": "3.496.0",
- "@smithy/config-resolver": "^2.1.1",
- "@smithy/fetch-http-handler": "^2.4.1",
- "@smithy/hash-node": "^2.1.1",
- "@smithy/invalid-dependency": "^2.1.1",
- "@smithy/middleware-content-length": "^2.1.1",
- "@smithy/middleware-endpoint": "^2.4.1",
- "@smithy/middleware-retry": "^2.1.1",
- "@smithy/middleware-serde": "^2.1.1",
- "@smithy/middleware-stack": "^2.1.1",
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/node-http-handler": "^2.3.1",
- "@smithy/property-provider": "^2.1.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/shared-ini-file-loader": "^2.3.1",
- "@smithy/smithy-client": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "@smithy/url-parser": "^2.1.1",
- "@smithy/util-base64": "^2.1.1",
- "@smithy/util-body-length-browser": "^2.1.1",
- "@smithy/util-body-length-node": "^2.2.1",
- "@smithy/util-defaults-mode-browser": "^2.1.1",
- "@smithy/util-defaults-mode-node": "^2.1.1",
- "@smithy/util-endpoints": "^1.1.1",
- "@smithy/util-retry": "^2.1.1",
- "@smithy/util-utf8": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/types": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
- "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-endpoints": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.496.0.tgz",
- "integrity": "sha512-1QzOiWHi383ZwqSi/R2KgKCd7M+6DxkxI5acqLPm8mvDRDP2jRjrnVaC0g9/tlttWousGEemDUWStwrD2mVYSw==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/types": "^2.9.1",
- "@smithy/util-endpoints": "^1.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-user-agent-browser": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.496.0.tgz",
- "integrity": "sha512-4j2spN+h0I0qfSMsGvJXTfQBu1e18rPdekKvzsGJxhaAE1tNgUfUT4nbvc5uVn0sNjZmirskmJ3kfbzVOrqIFg==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/types": "^2.9.1",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-user-agent-node": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.496.0.tgz",
- "integrity": "sha512-h0Ax0jlDc7UIo3KoSI4C4tVLBFoiAdx3+DhTVfgLS7x93d41dMlziPoBX2RgdcFn37qnzw6AQKTVTMwDbRCGpg==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "aws-crt": ">=1.0.0"
- },
- "peerDependenciesMeta": {
- "aws-crt": {
- "optional": true
- }
- }
- },
- "node_modules/@aws-sdk/client-sso": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.485.0.tgz",
- "integrity": "sha512-apN2bEn0PZs0jD4jAfvwO3dlWqw9YIQJ6TAudM1bd3S5vzWqlBBcLfQpK6taHoQaI+WqgUWXLuOf7gRFbGXKPg==",
- "optional": true,
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/core": "3.485.0",
- "@aws-sdk/middleware-host-header": "3.485.0",
- "@aws-sdk/middleware-logger": "3.485.0",
- "@aws-sdk/middleware-recursion-detection": "3.485.0",
- "@aws-sdk/middleware-user-agent": "3.485.0",
- "@aws-sdk/region-config-resolver": "3.485.0",
- "@aws-sdk/types": "3.485.0",
- "@aws-sdk/util-endpoints": "3.485.0",
- "@aws-sdk/util-user-agent-browser": "3.485.0",
- "@aws-sdk/util-user-agent-node": "3.485.0",
- "@smithy/config-resolver": "^2.0.23",
- "@smithy/core": "^1.2.2",
- "@smithy/fetch-http-handler": "^2.3.2",
- "@smithy/hash-node": "^2.0.18",
- "@smithy/invalid-dependency": "^2.0.16",
- "@smithy/middleware-content-length": "^2.0.18",
- "@smithy/middleware-endpoint": "^2.3.0",
- "@smithy/middleware-retry": "^2.0.26",
- "@smithy/middleware-serde": "^2.0.16",
- "@smithy/middleware-stack": "^2.0.10",
- "@smithy/node-config-provider": "^2.1.9",
- "@smithy/node-http-handler": "^2.2.2",
- "@smithy/protocol-http": "^3.0.12",
- "@smithy/smithy-client": "^2.2.1",
- "@smithy/types": "^2.8.0",
- "@smithy/url-parser": "^2.0.16",
- "@smithy/util-base64": "^2.0.1",
- "@smithy/util-body-length-browser": "^2.0.1",
- "@smithy/util-body-length-node": "^2.1.0",
- "@smithy/util-defaults-mode-browser": "^2.0.24",
- "@smithy/util-defaults-mode-node": "^2.0.32",
- "@smithy/util-endpoints": "^1.0.8",
- "@smithy/util-retry": "^2.0.9",
- "@smithy/util-utf8": "^2.0.2",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-sts": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.485.0.tgz",
- "integrity": "sha512-PI4q36kVF0fpIPZyeQhrwwJZ6SRkOGvU3rX5Qn4b5UY5X+Ct1aLhqSX8/OB372UZIcnh6eSvERu8POHleDO7Jw==",
- "optional": true,
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/core": "3.485.0",
- "@aws-sdk/credential-provider-node": "3.485.0",
- "@aws-sdk/middleware-host-header": "3.485.0",
- "@aws-sdk/middleware-logger": "3.485.0",
- "@aws-sdk/middleware-recursion-detection": "3.485.0",
- "@aws-sdk/middleware-user-agent": "3.485.0",
- "@aws-sdk/region-config-resolver": "3.485.0",
- "@aws-sdk/types": "3.485.0",
- "@aws-sdk/util-endpoints": "3.485.0",
- "@aws-sdk/util-user-agent-browser": "3.485.0",
- "@aws-sdk/util-user-agent-node": "3.485.0",
- "@smithy/config-resolver": "^2.0.23",
- "@smithy/core": "^1.2.2",
- "@smithy/fetch-http-handler": "^2.3.2",
- "@smithy/hash-node": "^2.0.18",
- "@smithy/invalid-dependency": "^2.0.16",
- "@smithy/middleware-content-length": "^2.0.18",
- "@smithy/middleware-endpoint": "^2.3.0",
- "@smithy/middleware-retry": "^2.0.26",
- "@smithy/middleware-serde": "^2.0.16",
- "@smithy/middleware-stack": "^2.0.10",
- "@smithy/node-config-provider": "^2.1.9",
- "@smithy/node-http-handler": "^2.2.2",
- "@smithy/protocol-http": "^3.0.12",
- "@smithy/smithy-client": "^2.2.1",
- "@smithy/types": "^2.8.0",
- "@smithy/url-parser": "^2.0.16",
- "@smithy/util-base64": "^2.0.1",
- "@smithy/util-body-length-browser": "^2.0.1",
- "@smithy/util-body-length-node": "^2.1.0",
- "@smithy/util-defaults-mode-browser": "^2.0.24",
- "@smithy/util-defaults-mode-node": "^2.0.32",
- "@smithy/util-endpoints": "^1.0.8",
- "@smithy/util-middleware": "^2.0.9",
- "@smithy/util-retry": "^2.0.9",
- "@smithy/util-utf8": "^2.0.2",
- "fast-xml-parser": "4.2.5",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/core": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.485.0.tgz",
- "integrity": "sha512-Yvi80DQcbjkYCft471ClE3HuetuNVqntCs6eFOomDcrJaqdOFrXv2kJAxky84MRA/xb7bGlDGAPbTuj1ICputg==",
- "optional": true,
- "dependencies": {
- "@smithy/core": "^1.2.2",
- "@smithy/protocol-http": "^3.0.12",
- "@smithy/signature-v4": "^2.0.0",
- "@smithy/smithy-client": "^2.2.1",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-cognito-identity": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.485.0.tgz",
- "integrity": "sha512-XIy5h1AcDiY3V286X7KrLA5HAxLfzLGrUGBPFY+GTJGYetDhlJwFz12q6BOkIfeAhUbT2Umb4ptujX9eqpZJHQ==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/client-cognito-identity": "3.485.0",
- "@aws-sdk/types": "3.485.0",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-env": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.485.0.tgz",
- "integrity": "sha512-3XkFgwVU1XOB33dV7t9BKJ/ptdl2iS+0dxE7ecq8aqT2/gsfKmLCae1G17P8WmdD3z0kMDTvnqM2aWgUnSOkmg==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-http": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.485.0.tgz",
- "integrity": "sha512-2/2Y3Z7cpKf8vbQ+FzoBPxRyb0hGJZB1YrnH7hptVi5gSVe1NiwV5ZtsDnv4cwUfOBqEu97nMXw5IrRO26S0DA==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/fetch-http-handler": "^2.3.2",
- "@smithy/node-http-handler": "^2.2.2",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/protocol-http": "^3.0.12",
- "@smithy/smithy-client": "^2.2.1",
- "@smithy/types": "^2.8.0",
- "@smithy/util-stream": "^2.0.24",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.485.0.tgz",
- "integrity": "sha512-cFYF/Bdw7EnT4viSxYpNIv3IBkri/Yb+JpQXl8uDq7bfVJfAN5qZmK07vRkg08xL6TC4F41wshhMSAucGdTwIw==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.485.0",
- "@aws-sdk/credential-provider-process": "3.485.0",
- "@aws-sdk/credential-provider-sso": "3.485.0",
- "@aws-sdk/credential-provider-web-identity": "3.485.0",
- "@aws-sdk/types": "3.485.0",
- "@smithy/credential-provider-imds": "^2.0.0",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/shared-ini-file-loader": "^2.0.6",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-node": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.485.0.tgz",
- "integrity": "sha512-2DwzO2azkSzngifKDT61W/DL0tSzewuaFHiLJWdfc8Et3mdAQJ9x3KAj8u7XFpjIcGNqk7FiKjN+zeGUuNiEhA==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.485.0",
- "@aws-sdk/credential-provider-ini": "3.485.0",
- "@aws-sdk/credential-provider-process": "3.485.0",
- "@aws-sdk/credential-provider-sso": "3.485.0",
- "@aws-sdk/credential-provider-web-identity": "3.485.0",
- "@aws-sdk/types": "3.485.0",
- "@smithy/credential-provider-imds": "^2.0.0",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/shared-ini-file-loader": "^2.0.6",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-process": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.485.0.tgz",
- "integrity": "sha512-X9qS6ZO/rDKYDgWqD1YmSX7sAUUHax9HbXlgGiTTdtfhZvQh1ZmnH6wiPu5WNliafHZFtZT2W07kgrDLPld/Ug==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/shared-ini-file-loader": "^2.0.6",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-sso": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.485.0.tgz",
- "integrity": "sha512-l0oC8GTrWh+LFQQfSmG1Jai1PX7Mhj9arb/CaS1/tmeZE0hgIXW++tvljYs/Dds4LGXUlaWG+P7BrObf6OyIXA==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/client-sso": "3.485.0",
- "@aws-sdk/token-providers": "3.485.0",
- "@aws-sdk/types": "3.485.0",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/shared-ini-file-loader": "^2.0.6",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-web-identity": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.485.0.tgz",
- "integrity": "sha512-WpBFZFE0iXtnibH5POMEKITj/hR0YV5l2n9p8BEvKjdJ63s3Xke1RN20ZdIyKDaRDwj8adnKDgNPEnAKdS4kLw==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-providers": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.485.0.tgz",
- "integrity": "sha512-SpGEmiVr+C9Dtc5tZFfFYXSNxbl1jShLlyZPWERHBn4QwGvdXcgPB96I0yvUuitBKrM0winHsCWH7CR/z24kmg==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/client-cognito-identity": "3.485.0",
- "@aws-sdk/client-sso": "3.485.0",
- "@aws-sdk/client-sts": "3.485.0",
- "@aws-sdk/credential-provider-cognito-identity": "3.485.0",
- "@aws-sdk/credential-provider-env": "3.485.0",
- "@aws-sdk/credential-provider-http": "3.485.0",
- "@aws-sdk/credential-provider-ini": "3.485.0",
- "@aws-sdk/credential-provider-node": "3.485.0",
- "@aws-sdk/credential-provider-process": "3.485.0",
- "@aws-sdk/credential-provider-sso": "3.485.0",
- "@aws-sdk/credential-provider-web-identity": "3.485.0",
- "@aws-sdk/types": "3.485.0",
- "@smithy/credential-provider-imds": "^2.0.0",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/lib-storage": {
- "version": "3.499.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.499.0.tgz",
- "integrity": "sha512-rL++Re7Oed8uwkMSafpeG6ryB1vzW0dQLi5L3IWPhllWaokrXiEJ1lT1sg8vtyoMaZ4HNGE9jeyxMCRIa52Enw==",
- "dependencies": {
- "@smithy/abort-controller": "^2.1.1",
- "@smithy/middleware-endpoint": "^2.4.1",
- "@smithy/smithy-client": "^2.3.1",
- "buffer": "5.6.0",
- "events": "3.3.0",
- "stream-browserify": "3.0.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "@aws-sdk/client-s3": "^3.0.0"
- }
- },
- "node_modules/@aws-sdk/lib-storage/node_modules/buffer": {
- "version": "5.6.0",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
- "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
- "dependencies": {
- "base64-js": "^1.0.2",
- "ieee754": "^1.1.4"
- }
- },
- "node_modules/@aws-sdk/middleware-bucket-endpoint": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.496.0.tgz",
- "integrity": "sha512-B+ilBMSs3+LJuo2bl2KB8GFdu+8PPVtYEWtwhNkmnaU8iMisgMBp5uuM8sUDvJX7I4iSF0WbgnhguX4cJqfAew==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@aws-sdk/util-arn-parser": "3.495.0",
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-config-provider": "^2.2.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@aws-sdk/types": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
- "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-expect-continue": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.496.0.tgz",
- "integrity": "sha512-+exo5DVc+BeDus2iI6Fz1thefHGDXxUhHZ+4VHQ6HkStMy3Y22HugyEGHSQZmtRL86Hjr7dFbEWFsC47a2ItGA==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-expect-continue/node_modules/@aws-sdk/types": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
- "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-flexible-checksums": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.496.0.tgz",
- "integrity": "sha512-yQIWfjEMvgsAJ7ku224vXDjXPD+f9zfKZFialJva8VUlEr7hQp4CQ0rxV3YThSaixKEDDs5k6kOjWAd2BPGr2A==",
- "dependencies": {
- "@aws-crypto/crc32": "3.0.0",
- "@aws-crypto/crc32c": "3.0.0",
- "@aws-sdk/types": "3.496.0",
- "@smithy/is-array-buffer": "^2.1.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-utf8": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-sdk/types": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
- "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-host-header": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.485.0.tgz",
- "integrity": "sha512-1mAUX9dQNGo2RIKseVj7SI/D5abQJQ/Os8hQ0NyVAyyVYF+Yjx5PphKgfhM5yoBwuwZUl6q71XPYEGNx7be6SA==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/protocol-http": "^3.0.12",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-location-constraint": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.496.0.tgz",
- "integrity": "sha512-i4ocJ2Zs86OtPREbB18InFukhqg2qtBxb5gywv79IHDPVmpOYE4m/3v3yGUrkjfF2GTlUL0k5FskNNqw41yfng==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-location-constraint/node_modules/@aws-sdk/types": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
- "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-logger": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.485.0.tgz",
- "integrity": "sha512-O8IgJ0LHi5wTs5GlpI7nqmmSSagkVdd1shpGgQWY2h0kMSCII8CJZHBG97dlFFpGTvx5EDlhPNek7rl/6F4dRw==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-recursion-detection": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.485.0.tgz",
- "integrity": "sha512-ZeVNATGNFcqkWDut3luVszROTUzkU5u+rJpB/xmeMoenlDAjPRiHt/ca3WkI5wAnIJ1VSNGpD2sOFLMCH+EWag==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/protocol-http": "^3.0.12",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-s3": {
- "version": "3.499.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.499.0.tgz",
- "integrity": "sha512-thTb47U1hYHk5ei+yO0D0aehbgQXeAcgvyyxOID9/HDuRfWuTvKdclWh/goIeDfvSS87VBukEAjnCa5JYBwzug==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@aws-sdk/util-arn-parser": "3.495.0",
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/signature-v4": "^2.1.1",
- "@smithy/smithy-client": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-config-provider": "^2.2.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@aws-sdk/types": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
- "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-signing": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.485.0.tgz",
- "integrity": "sha512-41xzT2p1sOibhsLkdE5rwPJkNbBtKD8Gp36/ySfu0KE415wfXKacElSVxAaBw39/j7iSWDYqqybeEYbAzk+3GQ==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/protocol-http": "^3.0.12",
- "@smithy/signature-v4": "^2.0.0",
- "@smithy/types": "^2.8.0",
- "@smithy/util-middleware": "^2.0.9",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-ssec": {
- "version": "3.498.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.498.0.tgz",
- "integrity": "sha512-sWujXgzeTqMZzj/pRYEnnEbSzhBosqw9DXHOY1Mg2igI9NEfGlB7lPARp6aKmCaYlP3Bcj2X86vKCqF53mbyig==",
- "dependencies": {
- "@aws-sdk/types": "3.496.0",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-ssec/node_modules/@aws-sdk/types": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
- "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-user-agent": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.485.0.tgz",
- "integrity": "sha512-CddCVOn+OPQ0CcchketIg+WF6v+MDLAf3GOYTR2htUxxIm7HABuRd6R3kvQ5Jny9CV8gMt22G1UZITsFexSJlQ==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@aws-sdk/util-endpoints": "3.485.0",
- "@smithy/protocol-http": "^3.0.12",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/region-config-resolver": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.485.0.tgz",
- "integrity": "sha512-2FB2EQ0sIE+YgFqGtkE1lDIMIL6nYe6MkOHBwBM7bommadKIrbbr2L22bPZGs3ReTsxiJabjzxbuCAVhrpHmhg==",
- "optional": true,
- "dependencies": {
- "@smithy/node-config-provider": "^2.1.9",
- "@smithy/types": "^2.8.0",
- "@smithy/util-config-provider": "^2.1.0",
- "@smithy/util-middleware": "^2.0.9",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/signature-v4-multi-region": {
- "version": "3.499.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.499.0.tgz",
- "integrity": "sha512-8HSFnZErRm7lAfk+Epxrf4QNdQEamg1CnbLybtKQQEjmvxLuXYvj16KlpYEZIwEENOMEvnCqMc7syTPkmjVhJA==",
- "dependencies": {
- "@aws-sdk/middleware-sdk-s3": "3.499.0",
- "@aws-sdk/types": "3.496.0",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/signature-v4": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@aws-sdk/types": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
- "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/token-providers": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.485.0.tgz",
- "integrity": "sha512-kOXA1WKIVIFNRqHL8ynVZ3hCKLsgnEmGr2iDR6agDNw5fYIlCO/6N2xR6QdGcLTvUUbwOlz4OvKLUQnWMKAnnA==",
- "optional": true,
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/middleware-host-header": "3.485.0",
- "@aws-sdk/middleware-logger": "3.485.0",
- "@aws-sdk/middleware-recursion-detection": "3.485.0",
- "@aws-sdk/middleware-user-agent": "3.485.0",
- "@aws-sdk/region-config-resolver": "3.485.0",
- "@aws-sdk/types": "3.485.0",
- "@aws-sdk/util-endpoints": "3.485.0",
- "@aws-sdk/util-user-agent-browser": "3.485.0",
- "@aws-sdk/util-user-agent-node": "3.485.0",
- "@smithy/config-resolver": "^2.0.23",
- "@smithy/fetch-http-handler": "^2.3.2",
- "@smithy/hash-node": "^2.0.18",
- "@smithy/invalid-dependency": "^2.0.16",
- "@smithy/middleware-content-length": "^2.0.18",
- "@smithy/middleware-endpoint": "^2.3.0",
- "@smithy/middleware-retry": "^2.0.26",
- "@smithy/middleware-serde": "^2.0.16",
- "@smithy/middleware-stack": "^2.0.10",
- "@smithy/node-config-provider": "^2.1.9",
- "@smithy/node-http-handler": "^2.2.2",
- "@smithy/property-provider": "^2.0.0",
- "@smithy/protocol-http": "^3.0.12",
- "@smithy/shared-ini-file-loader": "^2.0.6",
- "@smithy/smithy-client": "^2.2.1",
- "@smithy/types": "^2.8.0",
- "@smithy/url-parser": "^2.0.16",
- "@smithy/util-base64": "^2.0.1",
- "@smithy/util-body-length-browser": "^2.0.1",
- "@smithy/util-body-length-node": "^2.1.0",
- "@smithy/util-defaults-mode-browser": "^2.0.24",
- "@smithy/util-defaults-mode-node": "^2.0.32",
- "@smithy/util-endpoints": "^1.0.8",
- "@smithy/util-retry": "^2.0.9",
- "@smithy/util-utf8": "^2.0.2",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/types": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.485.0.tgz",
- "integrity": "sha512-+QW32YQdvZRDOwrAQPo/qCyXoSjgXB6RwJwCwkd8ebJXRXw6tmGKIHaZqYHt/LtBymvnaBgBBADNa4+qFvlOFw==",
- "dependencies": {
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-arn-parser": {
- "version": "3.495.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.495.0.tgz",
- "integrity": "sha512-hwdA3XAippSEUxs7jpznwD63YYFR+LtQvlEcebPTgWR9oQgG9TfS+39PUfbnEeje1ICuOrN3lrFqFbmP9uzbMg==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-endpoints": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.485.0.tgz",
- "integrity": "sha512-dTd642F7nJisApF8YjniqQ6U59CP/DCtar11fXf1nG9YNBCBsNNVw5ZfZb5nSNzaIdy27mQioWTCV18JEj1mxg==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/util-endpoints": "^1.0.8",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-locate-window": {
- "version": "3.465.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.465.0.tgz",
- "integrity": "sha512-f+QNcWGswredzC1ExNAB/QzODlxwaTdXkNT5cvke2RLX8SFU5pYk6h4uCtWC0vWPELzOfMfloBrJefBzlarhsw==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-user-agent-browser": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.485.0.tgz",
- "integrity": "sha512-QliWbjg0uOhGTcWgWTKPMY0SBi07g253DjwrCINT1auqDrdQPxa10xozpZExBYjAK2KuhYDNUzni127ae6MHOw==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/types": "^2.8.0",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/util-user-agent-node": {
- "version": "3.485.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.485.0.tgz",
- "integrity": "sha512-QF+aQ9jnDlPUlFBxBRqOylPf86xQuD3aEPpOErR+50qJawVvKa94uiAFdvtI9jv6hnRZmuFsTj2rsyytnbAYBA==",
- "optional": true,
- "dependencies": {
- "@aws-sdk/types": "3.485.0",
- "@smithy/node-config-provider": "^2.1.9",
- "@smithy/types": "^2.8.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "aws-crt": ">=1.0.0"
- },
- "peerDependenciesMeta": {
- "aws-crt": {
- "optional": true
- }
- }
- },
- "node_modules/@aws-sdk/util-utf8-browser": {
- "version": "3.259.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz",
- "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==",
- "dependencies": {
- "tslib": "^2.3.1"
- }
- },
- "node_modules/@aws-sdk/xml-builder": {
- "version": "3.496.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.496.0.tgz",
- "integrity": "sha512-GvEjh537IIeOw1ZkZuB37sV12u+ipS5Z1dwjEC/HAvhl5ac23ULtTr1/n+U1gLNN+BAKSWjKiQ2ksj8DiUzeyw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
- "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
- "dev": true,
- "dependencies": {
- "@babel/highlight": "^7.10.4"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.22.20",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
- "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight": {
- "version": "7.23.4",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
- "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
- "dev": true,
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.22.20",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/@babel/highlight/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/@babel/highlight/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/@babel/highlight/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/@babel/runtime": {
- "version": "7.23.8",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz",
- "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==",
- "dev": true,
- "dependencies": {
- "regenerator-runtime": "^0.14.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@colors/colors": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
- "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
- "engines": {
- "node": ">=0.1.90"
- }
- },
- "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/@dabh/diagnostics": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
- "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
- "dependencies": {
- "colorspace": "1.1.x",
- "enabled": "2.0.x",
- "kuler": "^2.0.0"
- }
- },
- "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": "0.4.3",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
- "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==",
- "dev": true,
- "dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.1.1",
- "espree": "^7.3.0",
- "globals": "^13.9.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.2.1",
- "js-yaml": "^3.13.1",
- "minimatch": "^3.0.4",
- "strip-json-comments": "^3.1.1"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/ignore": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
- "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
- "dev": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/@eslint/eslintrc/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/@flybywiresim/eslint-config": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/@flybywiresim/eslint-config/-/eslint-config-0.1.0.tgz",
- "integrity": "sha512-j+uT0ZtI2vjfSVSr57vZxNMaT9i3Y4BIf2ucx6NdOaeBn9hWUWBrrPMKPSRE68vjRvBQd7cqWvJyFwvswNS5dA==",
- "dev": true,
- "dependencies": {
- "eslint-config-airbnb": "^18.2.1",
- "eslint-plugin-import": "^2.22.1",
- "eslint-plugin-jsx-a11y": "^6.3.1",
- "eslint-plugin-react": "^7.21.5"
- },
- "peerDependencies": {
- "eslint": "^7.21.0"
- }
- },
- "node_modules/@hokify/agenda": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/@hokify/agenda/-/agenda-6.3.0.tgz",
- "integrity": "sha512-fWrKMDe/8QHJXLOdEsMogb6cb213Z82iNsnU7nFrSIMFifEXSkXNTyCZ99FV3KLf+Du1gS/M9/8uTC6FHyWRZQ==",
- "dependencies": {
- "cron-parser": "^4",
- "date.js": "~0.3.3",
- "debug": "~4",
- "human-interval": "~2",
- "luxon": "^3",
- "mongodb": "^4"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@humanwhocodes/config-array": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
- "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==",
- "dev": true,
- "dependencies": {
- "@humanwhocodes/object-schema": "^1.2.0",
- "debug": "^4.1.1",
- "minimatch": "^3.0.4"
- },
- "engines": {
- "node": ">=10.10.0"
- }
- },
- "node_modules/@humanwhocodes/config-array/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/@humanwhocodes/config-array/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/@humanwhocodes/object-schema": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
- "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
- "dev": true
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
- "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.15",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
- "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/@mongodb-js/saslprep": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.3.tgz",
- "integrity": "sha512-SyCxhJfmK6MoLNV5SbDpNdUy9SDv5H7y9/9rl3KpnwgTHWuNNMc87zWqbcIZXNWY+aUjxLGLEcvHoLagG4tWCg==",
- "dependencies": {
- "sparse-bitfield": "^3.0.3"
- }
- },
- "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/@octokit/endpoint": {
- "version": "9.0.4",
- "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.4.tgz",
- "integrity": "sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==",
- "dependencies": {
- "@octokit/types": "^12.0.0",
- "universal-user-agent": "^6.0.0"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/@octokit/openapi-types": {
- "version": "19.1.0",
- "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.1.0.tgz",
- "integrity": "sha512-6G+ywGClliGQwRsjvqVYpklIfa7oRPA0vyhPQG/1Feh+B+wU0vGH1JiJ5T25d3g1JZYBHzR2qefLi9x8Gt+cpw=="
- },
- "node_modules/@octokit/request": {
- "version": "8.1.6",
- "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.6.tgz",
- "integrity": "sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==",
- "dependencies": {
- "@octokit/endpoint": "^9.0.0",
- "@octokit/request-error": "^5.0.0",
- "@octokit/types": "^12.0.0",
- "universal-user-agent": "^6.0.0"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/@octokit/request-error": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz",
- "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==",
- "dependencies": {
- "@octokit/types": "^12.0.0",
- "deprecation": "^2.0.0",
- "once": "^1.4.0"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/@octokit/types": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.4.0.tgz",
- "integrity": "sha512-FLWs/AvZllw/AGVs+nJ+ELCDZZJk+kY0zMen118xhL2zD0s1etIUHm1odgjP7epxYU1ln7SZxEUWYop5bhsdgQ==",
- "dependencies": {
- "@octokit/openapi-types": "^19.1.0"
- }
- },
- "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/@smithy/abort-controller": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.1.1.tgz",
- "integrity": "sha512-1+qdrUqLhaALYL0iOcN43EP6yAXXQ2wWZ6taf4S2pNGowmOc5gx+iMQv+E42JizNJjB0+gEadOXeV1Bf7JWL1Q==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/chunked-blob-reader": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.1.1.tgz",
- "integrity": "sha512-NjNFCKxC4jVvn+lUr3Yo4/PmUJj3tbyqH6GNHueyTGS5Q27vlEJ1MkNhUDV8QGxJI7Bodnc2pD18lU2zRfhHlQ==",
- "dependencies": {
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@smithy/chunked-blob-reader-native": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.1.1.tgz",
- "integrity": "sha512-zNW+43dltfNMUrBEYLMWgI8lQr0uhtTcUyxkgC9EP4j17WREzgSFMPUFVrVV6Rc2+QtWERYjb4tzZnQGa7R9fQ==",
- "dependencies": {
- "@smithy/util-base64": "^2.1.1",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@smithy/config-resolver": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.1.1.tgz",
- "integrity": "sha512-lxfLDpZm+AWAHPFZps5JfDoO9Ux1764fOgvRUBpHIO8HWHcSN1dkgsago1qLRVgm1BZ8RCm8cgv99QvtaOWIhw==",
- "dependencies": {
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-config-provider": "^2.2.1",
- "@smithy/util-middleware": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/core": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@smithy/core/-/core-1.3.1.tgz",
- "integrity": "sha512-tf+NIu9FkOh312b6M9G4D68is4Xr7qptzaZGZUREELF8ysE1yLKphqt7nsomjKZVwW7WE5pDDex9idowNGRQ/Q==",
- "dependencies": {
- "@smithy/middleware-endpoint": "^2.4.1",
- "@smithy/middleware-retry": "^2.1.1",
- "@smithy/middleware-serde": "^2.1.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/smithy-client": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-middleware": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/credential-provider-imds": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.2.1.tgz",
- "integrity": "sha512-7XHjZUxmZYnONheVQL7j5zvZXga+EWNgwEAP6OPZTi7l8J4JTeNh9aIOfE5fKHZ/ee2IeNOh54ZrSna+Vc6TFA==",
- "dependencies": {
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/property-provider": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "@smithy/url-parser": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/eventstream-codec": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.1.1.tgz",
- "integrity": "sha512-E8KYBxBIuU4c+zrpR22VsVrOPoEDzk35bQR3E+xm4k6Pa6JqzkDOdMyf9Atac5GPNKHJBdVaQ4JtjdWX2rl/nw==",
- "dependencies": {
- "@aws-crypto/crc32": "3.0.0",
- "@smithy/types": "^2.9.1",
- "@smithy/util-hex-encoding": "^2.1.1",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-browser": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.1.1.tgz",
- "integrity": "sha512-JvEdCmGlZUay5VtlT8/kdR6FlvqTDUiJecMjXsBb0+k1H/qc9ME5n2XKPo8q/MZwEIA1GmGgYMokKGjVvMiDow==",
- "dependencies": {
- "@smithy/eventstream-serde-universal": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-config-resolver": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.1.1.tgz",
- "integrity": "sha512-EqNqXYp3+dk//NmW3NAgQr9bEQ7fsu/CcxQmTiq07JlaIcne/CBWpMZETyXm9w5LXkhduBsdXdlMscfDUDn2fA==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-node": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.1.1.tgz",
- "integrity": "sha512-LF882q/aFidFNDX7uROAGxq3H0B7rjyPkV6QDn6/KDQ+CG7AFkRccjxRf1xqajq/Pe4bMGGr+VKAaoF6lELIQw==",
- "dependencies": {
- "@smithy/eventstream-serde-universal": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-universal": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.1.1.tgz",
- "integrity": "sha512-LR0mMT+XIYTxk4k2fIxEA1BPtW3685QlqufUEUAX1AJcfFfxNDKEvuCRZbO8ntJb10DrIFVJR9vb0MhDCi0sAQ==",
- "dependencies": {
- "@smithy/eventstream-codec": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/fetch-http-handler": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.4.1.tgz",
- "integrity": "sha512-VYGLinPsFqH68lxfRhjQaSkjXM7JysUOJDTNjHBuN/ykyRb2f1gyavN9+VhhPTWCy32L4yZ2fdhpCs/nStEicg==",
- "dependencies": {
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/querystring-builder": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-base64": "^2.1.1",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@smithy/hash-blob-browser": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-2.1.1.tgz",
- "integrity": "sha512-jizu1+2PAUjiGIfRtlPEU8Yo6zn+d78ti/ZHDesdf1SUn2BuZW433JlPoCOLH3dBoEEvTgLvQ8tUGSoTTALA+A==",
- "dependencies": {
- "@smithy/chunked-blob-reader": "^2.1.1",
- "@smithy/chunked-blob-reader-native": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@smithy/hash-node": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.1.1.tgz",
- "integrity": "sha512-Qhoq0N8f2OtCnvUpCf+g1vSyhYQrZjhSwvJ9qvR8BUGOtTXiyv2x1OD2e6jVGmlpC4E4ax1USHoyGfV9JFsACg==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "@smithy/util-buffer-from": "^2.1.1",
- "@smithy/util-utf8": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/hash-stream-node": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-2.1.1.tgz",
- "integrity": "sha512-VgDaKcfCy0iHcmtAZgZ3Yw9g37Gkn2JsQiMtFQXUh8Wmo3GfNgDwLOtdhJ272pOT7DStzpe9cNr+eV5Au8KfQA==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "@smithy/util-utf8": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/invalid-dependency": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.1.1.tgz",
- "integrity": "sha512-7WTgnKw+VPg8fxu2v9AlNOQ5yaz6RA54zOVB4f6vQuR0xFKd+RzlCpt0WidYTsye7F+FYDIaS/RnJW4pxjNInw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@smithy/is-array-buffer": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.1.1.tgz",
- "integrity": "sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/md5-js": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-2.1.1.tgz",
- "integrity": "sha512-L3MbIYBIdLlT+MWTYrdVSv/dow1+6iZ1Ad7xS0OHxTTs17d753ZcpOV4Ro7M7tRAVWML/sg2IAp/zzCb6aAttg==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "@smithy/util-utf8": "^2.1.1",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@smithy/middleware-content-length": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.1.1.tgz",
- "integrity": "sha512-rSr9ezUl9qMgiJR0UVtVOGEZElMdGFyl8FzWEF5iEKTlcWxGr2wTqGfDwtH3LAB7h+FPkxqv4ZU4cpuCN9Kf/g==",
- "dependencies": {
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/middleware-endpoint": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.4.1.tgz",
- "integrity": "sha512-XPZTb1E2Oav60Ven3n2PFx+rX9EDsU/jSTA8VDamt7FXks67ekjPY/XrmmPDQaFJOTUHJNKjd8+kZxVO5Ael4Q==",
- "dependencies": {
- "@smithy/middleware-serde": "^2.1.1",
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/shared-ini-file-loader": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "@smithy/url-parser": "^2.1.1",
- "@smithy/util-middleware": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/middleware-retry": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.1.1.tgz",
- "integrity": "sha512-eMIHOBTXro6JZ+WWzZWd/8fS8ht5nS5KDQjzhNMHNRcG5FkNTqcKpYhw7TETMYzbLfhO5FYghHy1vqDWM4FLDA==",
- "dependencies": {
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/service-error-classification": "^2.1.1",
- "@smithy/smithy-client": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-middleware": "^2.1.1",
- "@smithy/util-retry": "^2.1.1",
- "tslib": "^2.5.0",
- "uuid": "^8.3.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/middleware-serde": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.1.1.tgz",
- "integrity": "sha512-D8Gq0aQBeE1pxf3cjWVkRr2W54t+cdM2zx78tNrVhqrDykRA7asq8yVJij1u5NDtKzKqzBSPYh7iW0svUKg76g==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/middleware-stack": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.1.1.tgz",
- "integrity": "sha512-KPJhRlhsl8CjgGXK/DoDcrFGfAqoqvuwlbxy+uOO4g2Azn1dhH+GVfC3RAp+6PoL5PWPb+vt6Z23FP+Mr6qeCw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/node-config-provider": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.2.1.tgz",
- "integrity": "sha512-epzK3x1xNxA9oJgHQ5nz+2j6DsJKdHfieb+YgJ7ATWxzNcB7Hc+Uya2TUck5MicOPhDV8HZImND7ZOecVr+OWg==",
- "dependencies": {
- "@smithy/property-provider": "^2.1.1",
- "@smithy/shared-ini-file-loader": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/node-http-handler": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.3.1.tgz",
- "integrity": "sha512-gLA8qK2nL9J0Rk/WEZSvgin4AppvuCYRYg61dcUo/uKxvMZsMInL5I5ZdJTogOvdfVug3N2dgI5ffcUfS4S9PA==",
- "dependencies": {
- "@smithy/abort-controller": "^2.1.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/querystring-builder": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/property-provider": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.1.1.tgz",
- "integrity": "sha512-FX7JhhD/o5HwSwg6GLK9zxrMUrGnb3PzNBrcthqHKBc3dH0UfgEAU24xnJ8F0uow5mj17UeBEOI6o3CF2k7Mhw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/protocol-http": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.1.1.tgz",
- "integrity": "sha512-6ZRTSsaXuSL9++qEwH851hJjUA0OgXdQFCs+VDw4tGH256jQ3TjYY/i34N4vd24RV3nrjNsgd1yhb57uMoKbzQ==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/querystring-builder": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.1.1.tgz",
- "integrity": "sha512-C/ko/CeEa8jdYE4gt6nHO5XDrlSJ3vdCG0ZAc6nD5ZIE7LBp0jCx4qoqp7eoutBu7VrGMXERSRoPqwi1WjCPbg==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "@smithy/util-uri-escape": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/querystring-parser": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.1.1.tgz",
- "integrity": "sha512-H4+6jKGVhG1W4CIxfBaSsbm98lOO88tpDWmZLgkJpt8Zkk/+uG0FmmqMuCAc3HNM2ZDV+JbErxr0l5BcuIf/XQ==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/service-error-classification": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.1.1.tgz",
- "integrity": "sha512-txEdZxPUgM1PwGvDvHzqhXisrc5LlRWYCf2yyHfvITWioAKat7srQvpjMAvgzf0t6t7j8yHrryXU9xt7RZqFpw==",
- "dependencies": {
- "@smithy/types": "^2.9.1"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/shared-ini-file-loader": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.3.1.tgz",
- "integrity": "sha512-2E2kh24igmIznHLB6H05Na4OgIEilRu0oQpYXo3LCNRrawHAcfDKq9004zJs+sAMt2X5AbY87CUCJ7IpqpSgdw==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/signature-v4": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.1.1.tgz",
- "integrity": "sha512-Hb7xub0NHuvvQD3YwDSdanBmYukoEkhqBjqoxo+bSdC0ryV9cTfgmNjuAQhTPYB6yeU7hTR+sPRiFMlxqv6kmg==",
- "dependencies": {
- "@smithy/eventstream-codec": "^2.1.1",
- "@smithy/is-array-buffer": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-hex-encoding": "^2.1.1",
- "@smithy/util-middleware": "^2.1.1",
- "@smithy/util-uri-escape": "^2.1.1",
- "@smithy/util-utf8": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/smithy-client": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.3.1.tgz",
- "integrity": "sha512-YsTdU8xVD64r2pLEwmltrNvZV6XIAC50LN6ivDopdt+YiF/jGH6PY9zUOu0CXD/d8GMB8gbhnpPsdrjAXHS9QA==",
- "dependencies": {
- "@smithy/middleware-endpoint": "^2.4.1",
- "@smithy/middleware-stack": "^2.1.1",
- "@smithy/protocol-http": "^3.1.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-stream": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/types": {
- "version": "2.9.1",
- "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.9.1.tgz",
- "integrity": "sha512-vjXlKNXyprDYDuJ7UW5iobdmyDm6g8dDG+BFUncAg/3XJaN45Gy5RWWWUVgrzIK7S4R1KWgIX5LeJcfvSI24bw==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/url-parser": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.1.1.tgz",
- "integrity": "sha512-qC9Bv8f/vvFIEkHsiNrUKYNl8uKQnn4BdhXl7VzQRP774AwIjiSMMwkbT+L7Fk8W8rzYVifzJNYxv1HwvfBo3Q==",
- "dependencies": {
- "@smithy/querystring-parser": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@smithy/util-base64": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.1.1.tgz",
- "integrity": "sha512-UfHVpY7qfF/MrgndI5PexSKVTxSZIdz9InghTFa49QOvuu9I52zLPLUHXvHpNuMb1iD2vmc6R+zbv/bdMipR/g==",
- "dependencies": {
- "@smithy/util-buffer-from": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/util-body-length-browser": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.1.1.tgz",
- "integrity": "sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag==",
- "dependencies": {
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@smithy/util-body-length-node": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.2.1.tgz",
- "integrity": "sha512-/ggJG+ta3IDtpNVq4ktmEUtOkH1LW64RHB5B0hcr5ZaWBmo96UX2cIOVbjCqqDickTXqBWZ4ZO0APuaPrD7Abg==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/util-buffer-from": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.1.1.tgz",
- "integrity": "sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg==",
- "dependencies": {
- "@smithy/is-array-buffer": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/util-config-provider": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.2.1.tgz",
- "integrity": "sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/util-defaults-mode-browser": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.1.1.tgz",
- "integrity": "sha512-lqLz/9aWRO6mosnXkArtRuQqqZBhNpgI65YDpww4rVQBuUT7qzKbDLG5AmnQTCiU4rOquaZO/Kt0J7q9Uic7MA==",
- "dependencies": {
- "@smithy/property-provider": "^2.1.1",
- "@smithy/smithy-client": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@smithy/util-defaults-mode-node": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.1.1.tgz",
- "integrity": "sha512-tYVrc+w+jSBfBd267KDnvSGOh4NMz+wVH7v4CClDbkdPfnjvImBZsOURncT5jsFwR9KCuDyPoSZq4Pa6+eCUrA==",
- "dependencies": {
- "@smithy/config-resolver": "^2.1.1",
- "@smithy/credential-provider-imds": "^2.2.1",
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/property-provider": "^2.1.1",
- "@smithy/smithy-client": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@smithy/util-endpoints": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.1.1.tgz",
- "integrity": "sha512-sI4d9rjoaekSGEtq3xSb2nMjHMx8QXcz2cexnVyRWsy4yQ9z3kbDpX+7fN0jnbdOp0b3KSTZJZ2Yb92JWSanLw==",
- "dependencies": {
- "@smithy/node-config-provider": "^2.2.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">= 14.0.0"
- }
- },
- "node_modules/@smithy/util-hex-encoding": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.1.1.tgz",
- "integrity": "sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/util-middleware": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.1.1.tgz",
- "integrity": "sha512-mKNrk8oz5zqkNcbcgAAepeJbmfUW6ogrT2Z2gDbIUzVzNAHKJQTYmH9jcy0jbWb+m7ubrvXKb6uMjkSgAqqsFA==",
- "dependencies": {
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/util-retry": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.1.1.tgz",
- "integrity": "sha512-Mg+xxWPTeSPrthpC5WAamJ6PW4Kbo01Fm7lWM1jmGRvmrRdsd3192Gz2fBXAMURyXpaNxyZf6Hr/nQ4q70oVEA==",
- "dependencies": {
- "@smithy/service-error-classification": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">= 14.0.0"
- }
- },
- "node_modules/@smithy/util-stream": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.1.1.tgz",
- "integrity": "sha512-J7SMIpUYvU4DQN55KmBtvaMc7NM3CZ2iWICdcgaovtLzseVhAqFRYqloT3mh0esrFw+3VEK6nQFteFsTqZSECQ==",
- "dependencies": {
- "@smithy/fetch-http-handler": "^2.4.1",
- "@smithy/node-http-handler": "^2.3.1",
- "@smithy/types": "^2.9.1",
- "@smithy/util-base64": "^2.1.1",
- "@smithy/util-buffer-from": "^2.1.1",
- "@smithy/util-hex-encoding": "^2.1.1",
- "@smithy/util-utf8": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/util-uri-escape": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.1.1.tgz",
- "integrity": "sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/util-utf8": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.1.1.tgz",
- "integrity": "sha512-BqTpzYEcUMDwAKr7/mVRUtHDhs6ZoXDi9NypMvMfOr/+u1NW7JgqodPDECiiLboEm6bobcPcECxzjtQh865e9A==",
- "dependencies": {
- "@smithy/util-buffer-from": "^2.1.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@smithy/util-waiter": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.1.1.tgz",
- "integrity": "sha512-kYy6BLJJNif+uqNENtJqWdXcpqo1LS+nj1AfXcDhOpqpSHJSAkVySLyZV9fkmuVO21lzGoxjvd1imGGJHph/IA==",
- "dependencies": {
- "@smithy/abort-controller": "^2.1.1",
- "@smithy/types": "^2.9.1",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.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.4",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
- "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
- "dev": true
- },
- "node_modules/@types/bad-words": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@types/bad-words/-/bad-words-3.0.3.tgz",
- "integrity": "sha512-jYdpTxDOJ+EENnsCwt8cOZhV/+4+qcwhks1igrOSg4zwwA17rsPqLsZpTo1l+OwViNu+5SPus0v5g7iGx+ofzA==",
- "dev": true
- },
- "node_modules/@types/config": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/@types/config/-/config-3.3.3.tgz",
- "integrity": "sha512-BB8DBAud88EgiAKlz8WQStzI771Kb6F3j4dioRJ4GD+tP4tzcZyMlz86aXuZT4s9hyesFORehMQE6eqtA5O+Vg==",
- "dev": true
- },
- "node_modules/@types/jsdom": {
- "version": "21.1.6",
- "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.6.tgz",
- "integrity": "sha512-/7kkMsC+/kMs7gAYmmBR9P0vGTnOoLhQhyhQJSlXGI5bzTHp6xdo0TtKWQAsz6pmSAeVqKSbqeyP6hytqr9FDw==",
- "dev": true,
- "dependencies": {
- "@types/node": "*",
- "@types/tough-cookie": "*",
- "parse5": "^7.0.0"
- }
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true
- },
- "node_modules/@types/json5": {
- "version": "0.0.29",
- "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
- "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
- "dev": true
- },
- "node_modules/@types/node": {
- "version": "18.19.6",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.6.tgz",
- "integrity": "sha512-X36s5CXMrrJOs2lQCdDF68apW4Rfx9ixYMawlepwmE4Anezv/AV2LSpKD1Ub8DAc+urp5bk0BGZ6NtmBitfnsg==",
- "dependencies": {
- "undici-types": "~5.26.4"
- }
- },
- "node_modules/@types/node-fetch": {
- "version": "2.6.10",
- "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.10.tgz",
- "integrity": "sha512-PPpPK6F9ALFTn59Ka3BaL+qGuipRfxNE8qVgkp0bVixeiR2c2/L+IVOiBdu9JhhT22sWnQEp6YyHGI2b2+CMcA==",
- "dev": true,
- "dependencies": {
- "@types/node": "*",
- "form-data": "^4.0.0"
- }
- },
- "node_modules/@types/semver": {
- "version": "7.5.6",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz",
- "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==",
- "dev": true
- },
- "node_modules/@types/tough-cookie": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
- "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
- "dev": true
- },
- "node_modules/@types/triple-beam": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
- "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="
- },
- "node_modules/@types/webidl-conversions": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
- "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
- },
- "node_modules/@types/whatwg-url": {
- "version": "8.2.2",
- "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz",
- "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==",
- "dependencies": {
- "@types/node": "*",
- "@types/webidl-conversions": "*"
- }
- },
- "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": "6.18.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz",
- "integrity": "sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==",
- "dev": true,
- "dependencies": {
- "@eslint-community/regexpp": "^4.5.1",
- "@typescript-eslint/scope-manager": "6.18.1",
- "@typescript-eslint/type-utils": "6.18.1",
- "@typescript-eslint/utils": "6.18.1",
- "@typescript-eslint/visitor-keys": "6.18.1",
- "debug": "^4.3.4",
- "graphemer": "^1.4.0",
- "ignore": "^5.2.4",
- "natural-compare": "^1.4.0",
- "semver": "^7.5.4",
- "ts-api-utils": "^1.0.1"
- },
- "engines": {
- "node": "^16.0.0 || >=18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
- "eslint": "^7.0.0 || ^8.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/parser": {
- "version": "6.18.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.1.tgz",
- "integrity": "sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/scope-manager": "6.18.1",
- "@typescript-eslint/types": "6.18.1",
- "@typescript-eslint/typescript-estree": "6.18.1",
- "@typescript-eslint/visitor-keys": "6.18.1",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": "^16.0.0 || >=18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^7.0.0 || ^8.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "6.18.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz",
- "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "6.18.1",
- "@typescript-eslint/visitor-keys": "6.18.1"
- },
- "engines": {
- "node": "^16.0.0 || >=18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/type-utils": {
- "version": "6.18.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz",
- "integrity": "sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/typescript-estree": "6.18.1",
- "@typescript-eslint/utils": "6.18.1",
- "debug": "^4.3.4",
- "ts-api-utils": "^1.0.1"
- },
- "engines": {
- "node": "^16.0.0 || >=18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^7.0.0 || ^8.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/types": {
- "version": "6.18.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz",
- "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==",
- "dev": true,
- "engines": {
- "node": "^16.0.0 || >=18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "6.18.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz",
- "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "6.18.1",
- "@typescript-eslint/visitor-keys": "6.18.1",
- "debug": "^4.3.4",
- "globby": "^11.1.0",
- "is-glob": "^4.0.3",
- "minimatch": "9.0.3",
- "semver": "^7.5.4",
- "ts-api-utils": "^1.0.1"
- },
- "engines": {
- "node": "^16.0.0 || >=18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/utils": {
- "version": "6.18.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz",
- "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.4.0",
- "@types/json-schema": "^7.0.12",
- "@types/semver": "^7.5.0",
- "@typescript-eslint/scope-manager": "6.18.1",
- "@typescript-eslint/types": "6.18.1",
- "@typescript-eslint/typescript-estree": "6.18.1",
- "semver": "^7.5.4"
- },
- "engines": {
- "node": "^16.0.0 || >=18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "6.18.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz",
- "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "6.18.1",
- "eslint-visitor-keys": "^3.4.1"
- },
- "engines": {
- "node": "^16.0.0 || >=18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@vladfrangu/async_event_emitter": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.3.0.tgz",
- "integrity": "sha512-pmkbRGAqTM3N7R4KCObOAqqoZzeURR6oC11amaXmY4ZLShu4MdLymm1/F0fZssYKAsSE79TibRbdXwfvYMIt0Q==",
- "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": "7.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
- "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
- "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.3.1",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz",
- "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/agent-base": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",
- "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==",
- "dependencies": {
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "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-colors": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
- "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "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.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "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": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
- "dependencies": {
- "sprintf-js": "~1.0.2"
- }
- },
- "node_modules/aria-query": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
- "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
- "dev": true,
- "dependencies": {
- "dequal": "^2.0.3"
- }
- },
- "node_modules/array-buffer-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
- "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "is-array-buffer": "^3.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array-includes": {
- "version": "3.1.7",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz",
- "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "is-string": "^1.0.7"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/array.prototype.findlastindex": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz",
- "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "es-shim-unscopables": "^1.0.0",
- "get-intrinsic": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array.prototype.flat": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
- "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "es-shim-unscopables": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array.prototype.flatmap": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
- "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "es-shim-unscopables": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array.prototype.tosorted": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz",
- "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "es-shim-unscopables": "^1.0.0",
- "get-intrinsic": "^1.2.1"
- }
- },
- "node_modules/arraybuffer.prototype.slice": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
- "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
- "dev": true,
- "dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "is-array-buffer": "^3.0.2",
- "is-shared-array-buffer": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/ast-types-flow": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
- "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
- "dev": true
- },
- "node_modules/astral-regex": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
- "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/async": {
- "version": "3.2.5",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
- "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
- },
- "node_modules/asynciterator.prototype": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
- "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.3"
- }
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
- },
- "node_modules/available-typed-arrays": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/axe-core": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz",
- "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/axobject-query": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
- "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
- "dev": true,
- "dependencies": {
- "dequal": "^2.0.3"
- }
- },
- "node_modules/bad-words": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/bad-words/-/bad-words-3.0.4.tgz",
- "integrity": "sha512-v/Q9uRPH4+yzDVLL4vR1+S9KoFgOEUl5s4axd6NIAq8SV2mradgi4E8lma/Y0cw1ltVdvyegCQQKffCPRCp8fg==",
- "dependencies": {
- "badwords-list": "^1.0.0"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/badwords-list": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/badwords-list/-/badwords-list-1.0.0.tgz",
- "integrity": "sha512-oWhaSG67e+HQj3OGHQt2ucP+vAPm1wTbdp2aDHeuh4xlGXBdWwzZ//pfu6swf5gZ8iX0b7JgmSo8BhgybbqszA=="
- },
- "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/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "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/bidi-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
- "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
- "dependencies": {
- "require-from-string": "^2.0.2"
- }
- },
- "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/bowser": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
- "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
- },
- "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/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/bson": {
- "version": "4.7.2",
- "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz",
- "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==",
- "dependencies": {
- "buffer": "^5.6.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "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": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
- }
- },
- "node_modules/cache-manager": {
- "version": "5.7.6",
- "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.7.6.tgz",
- "integrity": "sha512-wBxnBHjDxF1RXpHCBD6HGvKER003Ts7IIm0CHpggliHzN1RZditb7rXoduE1rplc2DEFYKxhLKgFuchXMJje9w==",
- "dependencies": {
- "eventemitter3": "^5.0.1",
- "lodash.clonedeep": "^4.5.0",
- "lru-cache": "^10.2.2",
- "promise-coalesce": "^1.1.2"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/cache-manager/node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
- },
- "node_modules/call-bind": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
- "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.1",
- "set-function-length": "^1.1.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/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": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
- "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
- "dependencies": {
- "color-convert": "^1.9.3",
- "color-string": "^1.6.0"
- }
- },
- "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=="
- },
- "node_modules/color-string": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
- "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
- "dependencies": {
- "color-name": "^1.0.0",
- "simple-swizzle": "^0.2.2"
- }
- },
- "node_modules/color/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/color/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
- },
- "node_modules/colorspace": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
- "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
- "dependencies": {
- "color": "^3.1.3",
- "text-hex": "1.0.x"
- }
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "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/config": {
- "version": "3.3.10",
- "resolved": "https://registry.npmjs.org/config/-/config-3.3.10.tgz",
- "integrity": "sha512-9Kl3LpQ6zj93KaqgfIMTcpwTpgozFOqNl/Dk7mjras1BgGIOlqxWkyIGeU1my+sRuskRYwrCATgCk1RjAnRPGA==",
- "dependencies": {
- "json5": "^2.2.3"
- },
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/confusing-browser-globals": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz",
- "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==",
- "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/cron-parser": {
- "version": "4.9.0",
- "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz",
- "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==",
- "dependencies": {
- "luxon": "^3.2.1"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "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==",
- "dev": true,
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/css-tree": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
- "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
- "dependencies": {
- "mdn-data": "2.0.30",
- "source-map-js": "^1.0.1"
- },
- "engines": {
- "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
- }
- },
- "node_modules/cssstyle": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz",
- "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==",
- "dependencies": {
- "rrweb-cssom": "^0.6.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/damerau-levenshtein": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
- "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
- "dev": true
- },
- "node_modules/data-urls": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
- "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
- "dependencies": {
- "whatwg-mimetype": "^4.0.0",
- "whatwg-url": "^14.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/data-urls/node_modules/tr46": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz",
- "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==",
- "dependencies": {
- "punycode": "^2.3.1"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/data-urls/node_modules/whatwg-url": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz",
- "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==",
- "dependencies": {
- "tr46": "^5.0.0",
- "webidl-conversions": "^7.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/date.js": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/date.js/-/date.js-0.3.3.tgz",
- "integrity": "sha512-HgigOS3h3k6HnW011nAb43c5xx5rBXk8P2v/WIT9Zv4koIaVXiH2BURguI78VVp+5Qc076T7OR378JViCnZtBw==",
- "dependencies": {
- "debug": "~3.1.0"
- }
- },
- "node_modules/date.js/node_modules/debug": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
- "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/date.js/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
- },
- "node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decimal.js": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
- "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
- },
- "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/define-data-property": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
- "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.2.1",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/define-properties": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
- "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
- "dev": true,
- "dependencies": {
- "define-data-property": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/deprecation": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
- "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
- },
- "node_modules/dequal": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
- "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "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.3.1",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
- "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/motdotla/dotenv?sponsor=1"
- }
- },
- "node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
- },
- "node_modules/enabled": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
- "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
- },
- "node_modules/enquirer": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
- "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
- "dev": true,
- "dependencies": {
- "ansi-colors": "^4.1.1",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/entities": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
- "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
- "engines": {
- "node": ">=0.12"
- },
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
- "node_modules/es-abstract": {
- "version": "1.22.3",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
- "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==",
- "dev": true,
- "dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "arraybuffer.prototype.slice": "^1.0.2",
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.5",
- "es-set-tostringtag": "^2.0.1",
- "es-to-primitive": "^1.2.1",
- "function.prototype.name": "^1.1.6",
- "get-intrinsic": "^1.2.2",
- "get-symbol-description": "^1.0.0",
- "globalthis": "^1.0.3",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "hasown": "^2.0.0",
- "internal-slot": "^1.0.5",
- "is-array-buffer": "^3.0.2",
- "is-callable": "^1.2.7",
- "is-negative-zero": "^2.0.2",
- "is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.2",
- "is-string": "^1.0.7",
- "is-typed-array": "^1.1.12",
- "is-weakref": "^1.0.2",
- "object-inspect": "^1.13.1",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.5.1",
- "safe-array-concat": "^1.0.1",
- "safe-regex-test": "^1.0.0",
- "string.prototype.trim": "^1.2.8",
- "string.prototype.trimend": "^1.0.7",
- "string.prototype.trimstart": "^1.0.7",
- "typed-array-buffer": "^1.0.0",
- "typed-array-byte-length": "^1.0.0",
- "typed-array-byte-offset": "^1.0.0",
- "typed-array-length": "^1.0.4",
- "unbox-primitive": "^1.0.2",
- "which-typed-array": "^1.1.13"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/es-iterator-helpers": {
- "version": "1.0.15",
- "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz",
- "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==",
- "dev": true,
- "dependencies": {
- "asynciterator.prototype": "^1.0.0",
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.22.1",
- "es-set-tostringtag": "^2.0.1",
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.2.1",
- "globalthis": "^1.0.3",
- "has-property-descriptors": "^1.0.0",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.5",
- "iterator.prototype": "^1.1.2",
- "safe-array-concat": "^1.0.1"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz",
- "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.2.2",
- "has-tostringtag": "^1.0.0",
- "hasown": "^2.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-shim-unscopables": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
- "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
- "dev": true,
- "dependencies": {
- "hasown": "^2.0.0"
- }
- },
- "node_modules/es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "dependencies": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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": "7.32.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz",
- "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "7.12.11",
- "@eslint/eslintrc": "^0.4.3",
- "@humanwhocodes/config-array": "^0.5.0",
- "ajv": "^6.10.0",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.0.1",
- "doctrine": "^3.0.0",
- "enquirer": "^2.3.5",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^5.1.1",
- "eslint-utils": "^2.1.0",
- "eslint-visitor-keys": "^2.0.0",
- "espree": "^7.3.1",
- "esquery": "^1.4.0",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^5.1.2",
- "globals": "^13.6.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.0.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "js-yaml": "^3.13.1",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.0.4",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
- "progress": "^2.0.0",
- "regexpp": "^3.1.0",
- "semver": "^7.2.1",
- "strip-ansi": "^6.0.0",
- "strip-json-comments": "^3.1.0",
- "table": "^6.0.9",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
- },
- "bin": {
- "eslint": "bin/eslint.js"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-config-airbnb": {
- "version": "18.2.1",
- "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-18.2.1.tgz",
- "integrity": "sha512-glZNDEZ36VdlZWoxn/bUR1r/sdFKPd1mHPbqUtkctgNG4yT2DLLtJ3D+yCV+jzZCc2V1nBVkmdknOJBZ5Hc0fg==",
- "dev": true,
- "dependencies": {
- "eslint-config-airbnb-base": "^14.2.1",
- "object.assign": "^4.1.2",
- "object.entries": "^1.1.2"
- },
- "engines": {
- "node": ">= 6"
- },
- "peerDependencies": {
- "eslint": "^5.16.0 || ^6.8.0 || ^7.2.0",
- "eslint-plugin-import": "^2.22.1",
- "eslint-plugin-jsx-a11y": "^6.4.1",
- "eslint-plugin-react": "^7.21.5",
- "eslint-plugin-react-hooks": "^4 || ^3 || ^2.3.0 || ^1.7.0"
- }
- },
- "node_modules/eslint-config-airbnb-base": {
- "version": "14.2.1",
- "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz",
- "integrity": "sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==",
- "dev": true,
- "dependencies": {
- "confusing-browser-globals": "^1.0.10",
- "object.assign": "^4.1.2",
- "object.entries": "^1.1.2"
- },
- "engines": {
- "node": ">= 6"
- },
- "peerDependencies": {
- "eslint": "^5.16.0 || ^6.8.0 || ^7.2.0",
- "eslint-plugin-import": "^2.22.1"
- }
- },
- "node_modules/eslint-import-resolver-node": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
- "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
- "dev": true,
- "dependencies": {
- "debug": "^3.2.7",
- "is-core-module": "^2.13.0",
- "resolve": "^1.22.4"
- }
- },
- "node_modules/eslint-import-resolver-node/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/eslint-module-utils": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
- "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
- "dev": true,
- "dependencies": {
- "debug": "^3.2.7"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependenciesMeta": {
- "eslint": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-module-utils/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/eslint-plugin-import": {
- "version": "2.29.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz",
- "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==",
- "dev": true,
- "dependencies": {
- "array-includes": "^3.1.7",
- "array.prototype.findlastindex": "^1.2.3",
- "array.prototype.flat": "^1.3.2",
- "array.prototype.flatmap": "^1.3.2",
- "debug": "^3.2.7",
- "doctrine": "^2.1.0",
- "eslint-import-resolver-node": "^0.3.9",
- "eslint-module-utils": "^2.8.0",
- "hasown": "^2.0.0",
- "is-core-module": "^2.13.1",
- "is-glob": "^4.0.3",
- "minimatch": "^3.1.2",
- "object.fromentries": "^2.0.7",
- "object.groupby": "^1.0.1",
- "object.values": "^1.1.7",
- "semver": "^6.3.1",
- "tsconfig-paths": "^3.15.0"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependencies": {
- "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
- }
- },
- "node_modules/eslint-plugin-import/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/eslint-plugin-import/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/eslint-plugin-import/node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/eslint-plugin-import/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/eslint-plugin-import/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/eslint-plugin-jsx-a11y": {
- "version": "6.8.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz",
- "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==",
- "dev": true,
- "dependencies": {
- "@babel/runtime": "^7.23.2",
- "aria-query": "^5.3.0",
- "array-includes": "^3.1.7",
- "array.prototype.flatmap": "^1.3.2",
- "ast-types-flow": "^0.0.8",
- "axe-core": "=4.7.0",
- "axobject-query": "^3.2.1",
- "damerau-levenshtein": "^1.0.8",
- "emoji-regex": "^9.2.2",
- "es-iterator-helpers": "^1.0.15",
- "hasown": "^2.0.0",
- "jsx-ast-utils": "^3.3.5",
- "language-tags": "^1.0.9",
- "minimatch": "^3.1.2",
- "object.entries": "^1.1.7",
- "object.fromentries": "^2.0.7"
- },
- "engines": {
- "node": ">=4.0"
- },
- "peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
- }
- },
- "node_modules/eslint-plugin-jsx-a11y/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/eslint-plugin-jsx-a11y/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/eslint-plugin-react": {
- "version": "7.33.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz",
- "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==",
- "dev": true,
- "dependencies": {
- "array-includes": "^3.1.6",
- "array.prototype.flatmap": "^1.3.1",
- "array.prototype.tosorted": "^1.1.1",
- "doctrine": "^2.1.0",
- "es-iterator-helpers": "^1.0.12",
- "estraverse": "^5.3.0",
- "jsx-ast-utils": "^2.4.1 || ^3.0.0",
- "minimatch": "^3.1.2",
- "object.entries": "^1.1.6",
- "object.fromentries": "^2.0.6",
- "object.hasown": "^1.1.2",
- "object.values": "^1.1.6",
- "prop-types": "^15.8.1",
- "resolve": "^2.0.0-next.4",
- "semver": "^6.3.1",
- "string.prototype.matchall": "^4.0.8"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
- }
- },
- "node_modules/eslint-plugin-react-hooks": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
- "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
- "dev": true,
- "peer": true,
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
- }
- },
- "node_modules/eslint-plugin-react/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/eslint-plugin-react/node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/eslint-plugin-react/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/eslint-plugin-react/node_modules/resolve": {
- "version": "2.0.0-next.5",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
- "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
- "dev": true,
- "dependencies": {
- "is-core-module": "^2.13.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/eslint-scope": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
- "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
- "dev": true,
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^4.1.1"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/eslint-scope/node_modules/estraverse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
- "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/eslint-utils": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
- "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
- "dev": true,
- "dependencies": {
- "eslint-visitor-keys": "^1.1.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/mysticatea"
- }
- },
- "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
- "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "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/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/eslint/node_modules/eslint-visitor-keys": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
- "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/eslint/node_modules/ignore": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
- "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
- "dev": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/eslint/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/espree": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
- "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
- "dev": true,
- "dependencies": {
- "acorn": "^7.4.0",
- "acorn-jsx": "^5.3.1",
- "eslint-visitor-keys": "^1.3.0"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "node_modules/espree/node_modules/eslint-visitor-keys": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
- "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "dev": true,
- "bin": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "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/eventemitter3": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
- "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
- },
- "node_modules/events": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
- "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
- "engines": {
- "node": ">=0.8.x"
- }
- },
- "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/fast-xml-parser": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz",
- "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==",
- "funding": [
- {
- "type": "paypal",
- "url": "https://paypal.me/naturalintelligence"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "dependencies": {
- "strnum": "^1.0.5"
- },
- "bin": {
- "fxparser": "src/cli/cli.js"
- }
- },
- "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/fecha": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
- "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="
- },
- "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/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/fn.name": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
- "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
- },
- "node_modules/for-each": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
- "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
- "dev": true,
- "dependencies": {
- "is-callable": "^1.1.3"
- }
- },
- "node_modules/form-data": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
- "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "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.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/function.prototype.name": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
- "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "functions-have-names": "^1.2.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
- "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
- "dev": true
- },
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
- "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.2",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "hasown": "^2.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-symbol-description": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
- "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/glob/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/glob/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/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/globalthis": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
- "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
- "dev": true,
- "dependencies": {
- "define-properties": "^1.1.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/gopd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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-bigints": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
- "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/has-property-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
- "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.2.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
- "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
- "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
- "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/html-encoding-sniffer": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
- "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
- "dependencies": {
- "whatwg-encoding": "^3.1.1"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/http-proxy-agent": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz",
- "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==",
- "dependencies": {
- "agent-base": "^7.1.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/https-proxy-agent": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz",
- "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==",
- "dependencies": {
- "agent-base": "^7.0.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/human-interval": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/human-interval/-/human-interval-2.0.1.tgz",
- "integrity": "sha512-r4Aotzf+OtKIGQCB3odUowy4GfUDTy3aTWTfLd7ZF2gBCy3XW3v/dJLRefZnOFFnjqs5B1TypvS8WarpBkYUNQ==",
- "dependencies": {
- "numbered": "^1.1.0"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "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/ignore": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
- "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
- "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=="
- },
- "node_modules/internal-slot": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz",
- "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.2.2",
- "hasown": "^2.0.0",
- "side-channel": "^1.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/ip-address": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
- "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
- "dependencies": {
- "jsbn": "1.1.0",
- "sprintf-js": "^1.1.3"
- },
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/ip-address/node_modules/sprintf-js": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
- "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
- },
- "node_modules/is-array-buffer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
- "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.0",
- "is-typed-array": "^1.1.10"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-arrayish": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
- "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
- },
- "node_modules/is-async-function": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
- "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-bigint": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
- "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
- "dev": true,
- "dependencies": {
- "has-bigints": "^1.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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-boolean-object": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
- "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.13.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
- "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
- "dev": true,
- "dependencies": {
- "hasown": "^2.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-date-object": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
- "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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-finalizationregistry": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
- "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-generator-function": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
- "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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-map": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
- "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-negative-zero": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
- "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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-number-object": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
- "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-potential-custom-element-name": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
- "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="
- },
- "node_modules/is-regex": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
- "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-set": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
- "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
- "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-string": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
- "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-symbol": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
- "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-typed-array": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
- "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
- "dev": true,
- "dependencies": {
- "which-typed-array": "^1.1.11"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakmap": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
- "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakref": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
- "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakset": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
- "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
- "node_modules/iterator.prototype": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
- "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
- "dev": true,
- "dependencies": {
- "define-properties": "^1.2.1",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
- "reflect.getprototypeof": "^1.0.4",
- "set-function-name": "^2.0.1"
- }
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
- },
- "node_modules/js-yaml": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
- "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
- "dev": true,
- "dependencies": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/jsbn": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
- "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
- },
- "node_modules/jsdom": {
- "version": "23.2.0",
- "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.2.0.tgz",
- "integrity": "sha512-L88oL7D/8ufIES+Zjz7v0aes+oBMh2Xnh3ygWvL0OaICOomKEPKuPnIfBJekiXr+BHbbMjrWn/xqrDQuxFTeyA==",
- "dependencies": {
- "@asamuzakjp/dom-selector": "^2.0.1",
- "cssstyle": "^4.0.1",
- "data-urls": "^5.0.0",
- "decimal.js": "^10.4.3",
- "form-data": "^4.0.0",
- "html-encoding-sniffer": "^4.0.0",
- "http-proxy-agent": "^7.0.0",
- "https-proxy-agent": "^7.0.2",
- "is-potential-custom-element-name": "^1.0.1",
- "parse5": "^7.1.2",
- "rrweb-cssom": "^0.6.0",
- "saxes": "^6.0.0",
- "symbol-tree": "^3.2.4",
- "tough-cookie": "^4.1.3",
- "w3c-xmlserializer": "^5.0.0",
- "webidl-conversions": "^7.0.0",
- "whatwg-encoding": "^3.1.1",
- "whatwg-mimetype": "^4.0.0",
- "whatwg-url": "^14.0.0",
- "ws": "^8.16.0",
- "xml-name-validator": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "peerDependencies": {
- "canvas": "^2.11.2"
- },
- "peerDependenciesMeta": {
- "canvas": {
- "optional": true
- }
- }
- },
- "node_modules/jsdom/node_modules/tr46": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz",
- "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==",
- "dependencies": {
- "punycode": "^2.3.1"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/jsdom/node_modules/whatwg-url": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz",
- "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==",
- "dependencies": {
- "tr46": "^5.0.0",
- "webidl-conversions": "^7.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "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/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/jsx-ast-utils": {
- "version": "3.3.5",
- "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
- "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
- "dev": true,
- "dependencies": {
- "array-includes": "^3.1.6",
- "array.prototype.flat": "^1.3.1",
- "object.assign": "^4.1.4",
- "object.values": "^1.1.6"
- },
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/kareem": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz",
- "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==",
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "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/kuler": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
- "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
- },
- "node_modules/language-subtag-registry": {
- "version": "0.3.22",
- "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
- "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
- "dev": true
- },
- "node_modules/language-tags": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
- "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
- "dev": true,
- "dependencies": {
- "language-subtag-registry": "^0.3.20"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "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/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
- },
- "node_modules/lodash.clonedeep": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
- "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
- },
- "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/lodash.truncate": {
- "version": "4.4.2",
- "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
- "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
- "dev": true
- },
- "node_modules/logform": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz",
- "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==",
- "dependencies": {
- "@colors/colors": "1.6.0",
- "@types/triple-beam": "^1.3.2",
- "fecha": "^4.2.0",
- "ms": "^2.1.1",
- "safe-stable-stringify": "^2.3.1",
- "triple-beam": "^1.3.0"
- },
- "engines": {
- "node": ">= 12.0.0"
- }
- },
- "node_modules/loose-envify": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
- "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
- "dev": true,
- "dependencies": {
- "js-tokens": "^3.0.0 || ^4.0.0"
- },
- "bin": {
- "loose-envify": "cli.js"
- }
- },
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dev": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/luxon": {
- "version": "3.4.4",
- "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz",
- "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==",
- "engines": {
- "node": ">=12"
- }
- },
- "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/mdn-data": {
- "version": "2.0.30",
- "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
- "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
- },
- "node_modules/memory-pager": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
- "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
- },
- "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.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
- "dependencies": {
- "braces": "^3.0.2",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/minimatch": {
- "version": "9.0.3",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
- "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/moment": {
- "version": "2.30.1",
- "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
- "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/mongodb": {
- "version": "4.17.2",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.2.tgz",
- "integrity": "sha512-mLV7SEiov2LHleRJPMPrK2PMyhXFZt2UQLC4VD4pnth3jMjYKHhtqfwwkkvS/NXuo/Fp3vbhaNcXrIDaLRb9Tg==",
- "dependencies": {
- "bson": "^4.7.2",
- "mongodb-connection-string-url": "^2.6.0",
- "socks": "^2.7.1"
- },
- "engines": {
- "node": ">=12.9.0"
- },
- "optionalDependencies": {
- "@aws-sdk/credential-providers": "^3.186.0",
- "@mongodb-js/saslprep": "^1.1.0"
- }
- },
- "node_modules/mongodb-connection-string-url": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz",
- "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==",
- "dependencies": {
- "@types/whatwg-url": "^8.2.1",
- "whatwg-url": "^11.0.0"
- }
- },
- "node_modules/mongoose": {
- "version": "8.0.4",
- "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.0.4.tgz",
- "integrity": "sha512-wN9qvdevX3+922VnLT7CpaZRT3jmVCBOK2QMHMGeScQxDRnFMPpkuI9StEPpZo/3x8t+kbzH7F8RMPsyNwyM4w==",
- "dependencies": {
- "bson": "^6.2.0",
- "kareem": "2.5.1",
- "mongodb": "6.2.0",
- "mpath": "0.9.0",
- "mquery": "5.0.0",
- "ms": "2.1.3",
- "sift": "16.0.1"
- },
- "engines": {
- "node": ">=16.20.1"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/mongoose"
- }
- },
- "node_modules/mongoose/node_modules/bson": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/bson/-/bson-6.2.0.tgz",
- "integrity": "sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==",
- "engines": {
- "node": ">=16.20.1"
- }
- },
- "node_modules/mongoose/node_modules/mongodb": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.2.0.tgz",
- "integrity": "sha512-d7OSuGjGWDZ5usZPqfvb36laQ9CPhnWkAGHT61x5P95p/8nMVeH8asloMwW6GcYFeB0Vj4CB/1wOTDG2RA9BFA==",
- "dependencies": {
- "@mongodb-js/saslprep": "^1.1.0",
- "bson": "^6.2.0",
- "mongodb-connection-string-url": "^2.6.0"
- },
- "engines": {
- "node": ">=16.20.1"
- },
- "peerDependencies": {
- "@aws-sdk/credential-providers": "^3.188.0",
- "@mongodb-js/zstd": "^1.1.0",
- "gcp-metadata": "^5.2.0",
- "kerberos": "^2.0.1",
- "mongodb-client-encryption": ">=6.0.0 <7",
- "snappy": "^7.2.2",
- "socks": "^2.7.1"
- },
- "peerDependenciesMeta": {
- "@aws-sdk/credential-providers": {
- "optional": true
- },
- "@mongodb-js/zstd": {
- "optional": true
- },
- "gcp-metadata": {
- "optional": true
- },
- "kerberos": {
- "optional": true
- },
- "mongodb-client-encryption": {
- "optional": true
- },
- "snappy": {
- "optional": true
- },
- "socks": {
- "optional": true
- }
- }
- },
- "node_modules/mongoose/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/mpath": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
- "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/mquery": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz",
- "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==",
- "dependencies": {
- "debug": "4.x"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "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=="
- },
- "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/node-fetch": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
- "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
- "dependencies": {
- "whatwg-url": "^5.0.0"
- },
- "engines": {
- "node": "4.x || >=6.0.0"
- },
- "peerDependencies": {
- "encoding": "^0.1.0"
- },
- "peerDependenciesMeta": {
- "encoding": {
- "optional": true
- }
- }
- },
- "node_modules/node-fetch/node_modules/tr46": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
- },
- "node_modules/node-fetch/node_modules/webidl-conversions": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
- },
- "node_modules/node-fetch/node_modules/whatwg-url": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
- "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "dependencies": {
- "tr46": "~0.0.3",
- "webidl-conversions": "^3.0.0"
- }
- },
- "node_modules/nodemon": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.2.tgz",
- "integrity": "sha512-9qIN2LNTrEzpOPBaWHTm4Asy1LxXLSickZStAQ4IZe7zsoIpD/A7LWxhZV3t4Zu352uBcqVnRsDXSMR2Sc3lTA==",
- "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/nodemon/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/nodemon/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/nodemon/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/nodemon/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/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/numbered": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/numbered/-/numbered-1.1.0.tgz",
- "integrity": "sha512-pv/ue2Odr7IfYOO0byC1KgBI10wo5YDauLhxY6/saNzAdAs0r1SotGCPzzCLNPL0xtrAwWRialLu23AAu9xO1g=="
- },
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-inspect": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
- "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object.assign": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
- "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.5",
- "define-properties": "^1.2.1",
- "has-symbols": "^1.0.3",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object.entries": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz",
- "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object.fromentries": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz",
- "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object.groupby": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz",
- "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1"
- }
- },
- "node_modules/object.hasown": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz",
- "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==",
- "dev": true,
- "dependencies": {
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object.values": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz",
- "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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==",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/one-time": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
- "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
- "dependencies": {
- "fn.name": "1.x.x"
- }
- },
- "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/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/parse5": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
- "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "dependencies": {
- "entities": "^4.4.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
- }
- },
- "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==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
- },
- "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/progress": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
- "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/promise-coalesce": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/promise-coalesce/-/promise-coalesce-1.1.2.tgz",
- "integrity": "sha512-zLaJ9b8hnC564fnJH6NFSOGZYYdzrAJn2JUUIwzoQb32fG2QAakpDNM+CZo1km6keXkRXRM+hml1BFAPVnPkxg==",
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/prop-types": {
- "version": "15.8.1",
- "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
- "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "dev": true,
- "dependencies": {
- "loose-envify": "^1.4.0",
- "object-assign": "^4.1.1",
- "react-is": "^16.13.1"
- }
- },
- "node_modules/psl": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
- "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
- },
- "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==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/querystringify": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
- "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
- },
- "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/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true
- },
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "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/reflect.getprototypeof": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz",
- "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "globalthis": "^1.0.3",
- "which-builtin-type": "^1.1.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/regenerator-runtime": {
- "version": "0.14.1",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
- "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
- "dev": true
- },
- "node_modules/regexp.prototype.flags": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
- "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "set-function-name": "^2.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/regexpp": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
- "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/mysticatea"
- }
- },
- "node_modules/require-from-string": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
- "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/requires-port": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
- "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
- },
- "node_modules/resolve": {
- "version": "1.22.8",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
- "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
- "dev": true,
- "dependencies": {
- "is-core-module": "^2.13.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/rrweb-cssom": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz",
- "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw=="
- },
- "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/safe-array-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
- "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
- "isarray": "^2.0.5"
- },
- "engines": {
- "node": ">=0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "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/safe-regex-test": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.1.tgz",
- "integrity": "sha512-Y5NejJTTliTyY4H7sipGqY+RX5P87i3F7c4Rcepy72nq+mNLhIsD0W4c7kEmduMDQCSqtPsXPlSTsFhh2LQv+g==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.5",
- "get-intrinsic": "^1.2.2",
- "is-regex": "^1.1.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/safe-stable-stringify": {
- "version": "2.4.3",
- "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz",
- "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
- },
- "node_modules/saxes": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
- "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
- "dependencies": {
- "xmlchars": "^2.2.0"
- },
- "engines": {
- "node": ">=v12.22.7"
- }
- },
- "node_modules/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/set-function-length": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
- "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
- "dev": true,
- "dependencies": {
- "define-data-property": "^1.1.1",
- "get-intrinsic": "^1.2.1",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/set-function-name": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
- "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
- "dev": true,
- "dependencies": {
- "define-data-property": "^1.0.1",
- "functions-have-names": "^1.2.3",
- "has-property-descriptors": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/sift": {
- "version": "16.0.1",
- "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz",
- "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ=="
- },
- "node_modules/simple-swizzle": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
- "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
- "dependencies": {
- "is-arrayish": "^0.3.1"
- }
- },
- "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/slice-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
- "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "astral-regex": "^2.0.0",
- "is-fullwidth-code-point": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/slice-ansi?sponsor=1"
- }
- },
- "node_modules/smart-buffer": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
- "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
- "engines": {
- "node": ">= 6.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks": {
- "version": "2.8.3",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
- "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
- "dependencies": {
- "ip-address": "^9.0.5",
- "smart-buffer": "^4.2.0"
- },
- "engines": {
- "node": ">= 10.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/sparse-bitfield": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
- "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
- "dependencies": {
- "memory-pager": "^1.0.2"
- }
- },
- "node_modules/sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
- "dev": true
- },
- "node_modules/stack-trace": {
- "version": "0.0.10",
- "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
- "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/stream-browserify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
- "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
- "dependencies": {
- "inherits": "~2.0.4",
- "readable-stream": "^3.5.0"
- }
- },
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "node_modules/string.prototype.matchall": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz",
- "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.5",
- "regexp.prototype.flags": "^1.5.0",
- "set-function-name": "^2.0.0",
- "side-channel": "^1.0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trim": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
- "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimend": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
- "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimstart": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
- "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "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/strnum": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
- "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
- },
- "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/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/symbol-tree": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
- "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
- },
- "node_modules/table": {
- "version": "6.8.1",
- "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
- "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==",
- "dev": true,
- "dependencies": {
- "ajv": "^8.0.1",
- "lodash.truncate": "^4.4.2",
- "slice-ansi": "^4.0.0",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/table/node_modules/ajv": {
- "version": "8.12.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
- "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/table/node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "dev": true
- },
- "node_modules/text-hex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
- "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
- },
- "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/tough-cookie": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
- "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
- "dependencies": {
- "psl": "^1.1.33",
- "punycode": "^2.1.1",
- "universalify": "^0.2.0",
- "url-parse": "^1.5.3"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tr46": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
- "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
- "dependencies": {
- "punycode": "^2.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/triple-beam": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
- "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
- "engines": {
- "node": ">= 14.0.0"
- }
- },
- "node_modules/ts-api-utils": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
- "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
- "dev": true,
- "engines": {
- "node": ">=16.13.0"
- },
- "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/ts-node/node_modules/acorn": {
- "version": "8.11.3",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
- "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/tsconfig-paths": {
- "version": "3.15.0",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
- "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
- "dev": true,
- "dependencies": {
- "@types/json5": "^0.0.29",
- "json5": "^1.0.2",
- "minimist": "^1.2.6",
- "strip-bom": "^3.0.0"
- }
- },
- "node_modules/tsconfig-paths/node_modules/json5": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
- "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
- "dev": true,
- "dependencies": {
- "minimist": "^1.2.0"
- },
- "bin": {
- "json5": "lib/cli.js"
- }
- },
- "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/typed-array-buffer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
- "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/typed-array-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
- "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "has-proto": "^1.0.1",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typed-array-byte-offset": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
- "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
- "dev": true,
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "has-proto": "^1.0.1",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typed-array-length": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
- "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "is-typed-array": "^1.1.9"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typescript": {
- "version": "5.4.5",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
- "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/unbox-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
- "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-bigints": "^1.0.2",
- "has-symbols": "^1.0.3",
- "which-boxed-primitive": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/universal-user-agent": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",
- "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="
- },
- "node_modules/universalify": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
- "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
- "engines": {
- "node": ">= 4.0.0"
- }
- },
- "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/url-parse": {
- "version": "1.5.10",
- "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
- "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
- "dependencies": {
- "querystringify": "^2.1.1",
- "requires-port": "^1.0.0"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
- },
- "node_modules/uuid": {
- "version": "8.3.2",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
- "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
- "node_modules/v8-compile-cache": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz",
- "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==",
- "dev": true
- },
- "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/w3c-xmlserializer": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
- "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
- "dependencies": {
- "xml-name-validator": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/webidl-conversions": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
- "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/whatwg-encoding": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
- "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
- "dependencies": {
- "iconv-lite": "0.6.3"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/whatwg-mimetype": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
- "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/whatwg-url": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
- "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
- "dependencies": {
- "tr46": "^3.0.0",
- "webidl-conversions": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/which-boxed-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
- "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
- "dev": true,
- "dependencies": {
- "is-bigint": "^1.0.1",
- "is-boolean-object": "^1.1.0",
- "is-number-object": "^1.0.4",
- "is-string": "^1.0.5",
- "is-symbol": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-builtin-type": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
- "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
- "dev": true,
- "dependencies": {
- "function.prototype.name": "^1.1.5",
- "has-tostringtag": "^1.0.0",
- "is-async-function": "^2.0.0",
- "is-date-object": "^1.0.5",
- "is-finalizationregistry": "^1.0.2",
- "is-generator-function": "^1.0.10",
- "is-regex": "^1.1.4",
- "is-weakref": "^1.0.2",
- "isarray": "^2.0.5",
- "which-boxed-primitive": "^1.0.2",
- "which-collection": "^1.0.1",
- "which-typed-array": "^1.1.9"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-collection": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
- "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
- "dev": true,
- "dependencies": {
- "is-map": "^2.0.1",
- "is-set": "^2.0.1",
- "is-weakmap": "^2.0.1",
- "is-weakset": "^2.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-typed-array": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
- "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
- "dev": true,
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.4",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/winston": {
- "version": "3.11.0",
- "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz",
- "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==",
- "dependencies": {
- "@colors/colors": "^1.6.0",
- "@dabh/diagnostics": "^2.0.2",
- "async": "^3.2.3",
- "is-stream": "^2.0.0",
- "logform": "^2.4.0",
- "one-time": "^1.0.0",
- "readable-stream": "^3.4.0",
- "safe-stable-stringify": "^2.3.1",
- "stack-trace": "0.0.x",
- "triple-beam": "^1.3.0",
- "winston-transport": "^4.5.0"
- },
- "engines": {
- "node": ">= 12.0.0"
- }
- },
- "node_modules/winston-transport": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.6.0.tgz",
- "integrity": "sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==",
- "dependencies": {
- "logform": "^2.3.2",
- "readable-stream": "^3.6.0",
- "triple-beam": "^1.3.0"
- },
- "engines": {
- "node": ">= 12.0.0"
- }
- },
- "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=="
- },
- "node_modules/ws": {
- "version": "8.17.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
- "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
+ "name": "fbw-discord-bot",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "fbw-discord-bot",
+ "version": "1.0.0",
+ "license": "AGPL-3.0",
+ "dependencies": {
+ "@aws-sdk/client-s3": "^3.499.0",
+ "@aws-sdk/lib-storage": "^3.499.0",
+ "@hokify/agenda": "^6.0.0",
+ "@octokit/request": "^8.1.1",
+ "bad-words": "^3.0.4",
+ "cache-manager": "^5.7.6",
+ "config": "^3.3.9",
+ "discord.js": "^14.11.0",
+ "jsdom": "^23.2.0",
+ "moment": "^2.29.4",
+ "mongoose": "^8.0.3",
+ "node-fetch": "^2.6.10",
+ "winston": "^3.3.4"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.13.0",
+ "@types/bad-words": "^3.0.3",
+ "@types/config": "^3.3.1",
+ "@types/eslint__js": "^8.42.3",
+ "@types/jsdom": "^21.1.6",
+ "@types/node": "^18.0.0",
+ "@types/node-fetch": "^2.6.10",
+ "dotenv": "^16.0.0",
+ "eslint": "^9.13.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.2.1",
+ "nodemon": "^3.0.2",
+ "prettier": "^3.3.3",
+ "ts-node": "^10.4.0",
+ "typescript": "~5.4.5",
+ "typescript-eslint": "^8.12.1"
+ },
+ "engines": {
+ "node": "18.x"
+ }
+ },
+ "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/@asamuzakjp/dom-selector": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-2.0.2.tgz",
+ "integrity": "sha512-x1KXOatwofR6ZAYzXRBL5wrdV0vwNxlTCK9NCuLqAzQYARqGcvFwiJA6A1ERuh+dgeA4Dxm3JBYictIes+SqUQ==",
+ "dependencies": {
+ "bidi-js": "^1.0.3",
+ "css-tree": "^2.3.1",
+ "is-potential-custom-element-name": "^1.0.1"
+ }
+ },
+ "node_modules/@aws-crypto/crc32": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz",
+ "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==",
+ "dependencies": {
+ "@aws-crypto/util": "^3.0.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/crc32/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/crc32c": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz",
+ "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==",
+ "dependencies": {
+ "@aws-crypto/util": "^3.0.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/crc32c/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/ie11-detection": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz",
+ "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==",
+ "dependencies": {
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/sha1-browser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz",
+ "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==",
+ "dependencies": {
+ "@aws-crypto/ie11-detection": "^3.0.0",
+ "@aws-crypto/supports-web-crypto": "^3.0.0",
+ "@aws-crypto/util": "^3.0.0",
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-locate-window": "^3.0.0",
+ "@aws-sdk/util-utf8-browser": "^3.0.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/sha256-browser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz",
+ "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==",
+ "dependencies": {
+ "@aws-crypto/ie11-detection": "^3.0.0",
+ "@aws-crypto/sha256-js": "^3.0.0",
+ "@aws-crypto/supports-web-crypto": "^3.0.0",
+ "@aws-crypto/util": "^3.0.0",
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-locate-window": "^3.0.0",
+ "@aws-sdk/util-utf8-browser": "^3.0.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/sha256-js": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz",
+ "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==",
+ "dependencies": {
+ "@aws-crypto/util": "^3.0.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-js/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/supports-web-crypto": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz",
+ "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==",
+ "dependencies": {
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/util": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz",
+ "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==",
+ "dependencies": {
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-utf8-browser": "^3.0.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/util/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-sdk/client-cognito-identity": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.485.0.tgz",
+ "integrity": "sha512-1SYhvRu/dNqQ5HcIgm7wIpyn1FsthbgG04o6QyVAnfOxmawFt4nqCEtNCwsmlX7o1ZCTYY+qNrozb7XZy+GKSQ==",
+ "optional": true,
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/client-sts": "3.485.0",
+ "@aws-sdk/core": "3.485.0",
+ "@aws-sdk/credential-provider-node": "3.485.0",
+ "@aws-sdk/middleware-host-header": "3.485.0",
+ "@aws-sdk/middleware-logger": "3.485.0",
+ "@aws-sdk/middleware-recursion-detection": "3.485.0",
+ "@aws-sdk/middleware-signing": "3.485.0",
+ "@aws-sdk/middleware-user-agent": "3.485.0",
+ "@aws-sdk/region-config-resolver": "3.485.0",
+ "@aws-sdk/types": "3.485.0",
+ "@aws-sdk/util-endpoints": "3.485.0",
+ "@aws-sdk/util-user-agent-browser": "3.485.0",
+ "@aws-sdk/util-user-agent-node": "3.485.0",
+ "@smithy/config-resolver": "^2.0.23",
+ "@smithy/core": "^1.2.2",
+ "@smithy/fetch-http-handler": "^2.3.2",
+ "@smithy/hash-node": "^2.0.18",
+ "@smithy/invalid-dependency": "^2.0.16",
+ "@smithy/middleware-content-length": "^2.0.18",
+ "@smithy/middleware-endpoint": "^2.3.0",
+ "@smithy/middleware-retry": "^2.0.26",
+ "@smithy/middleware-serde": "^2.0.16",
+ "@smithy/middleware-stack": "^2.0.10",
+ "@smithy/node-config-provider": "^2.1.9",
+ "@smithy/node-http-handler": "^2.2.2",
+ "@smithy/protocol-http": "^3.0.12",
+ "@smithy/smithy-client": "^2.2.1",
+ "@smithy/types": "^2.8.0",
+ "@smithy/url-parser": "^2.0.16",
+ "@smithy/util-base64": "^2.0.1",
+ "@smithy/util-body-length-browser": "^2.0.1",
+ "@smithy/util-body-length-node": "^2.1.0",
+ "@smithy/util-defaults-mode-browser": "^2.0.24",
+ "@smithy/util-defaults-mode-node": "^2.0.32",
+ "@smithy/util-endpoints": "^1.0.8",
+ "@smithy/util-retry": "^2.0.9",
+ "@smithy/util-utf8": "^2.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3": {
+ "version": "3.499.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.499.0.tgz",
+ "integrity": "sha512-4ssQqde/iY5fTJbWuFPzPuECtihdCAA9tfluv6fXYCJS3wMLf9x21qp6b7fIbUf6vjOJ2edmYd+DXk+0CMnTFg==",
+ "dependencies": {
+ "@aws-crypto/sha1-browser": "3.0.0",
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/client-sts": "3.499.0",
+ "@aws-sdk/core": "3.496.0",
+ "@aws-sdk/credential-provider-node": "3.499.0",
+ "@aws-sdk/middleware-bucket-endpoint": "3.496.0",
+ "@aws-sdk/middleware-expect-continue": "3.496.0",
+ "@aws-sdk/middleware-flexible-checksums": "3.496.0",
+ "@aws-sdk/middleware-host-header": "3.496.0",
+ "@aws-sdk/middleware-location-constraint": "3.496.0",
+ "@aws-sdk/middleware-logger": "3.496.0",
+ "@aws-sdk/middleware-recursion-detection": "3.496.0",
+ "@aws-sdk/middleware-sdk-s3": "3.499.0",
+ "@aws-sdk/middleware-signing": "3.496.0",
+ "@aws-sdk/middleware-ssec": "3.498.0",
+ "@aws-sdk/middleware-user-agent": "3.496.0",
+ "@aws-sdk/region-config-resolver": "3.496.0",
+ "@aws-sdk/signature-v4-multi-region": "3.499.0",
+ "@aws-sdk/types": "3.496.0",
+ "@aws-sdk/util-endpoints": "3.496.0",
+ "@aws-sdk/util-user-agent-browser": "3.496.0",
+ "@aws-sdk/util-user-agent-node": "3.496.0",
+ "@aws-sdk/xml-builder": "3.496.0",
+ "@smithy/config-resolver": "^2.1.1",
+ "@smithy/core": "^1.3.1",
+ "@smithy/eventstream-serde-browser": "^2.1.1",
+ "@smithy/eventstream-serde-config-resolver": "^2.1.1",
+ "@smithy/eventstream-serde-node": "^2.1.1",
+ "@smithy/fetch-http-handler": "^2.4.1",
+ "@smithy/hash-blob-browser": "^2.1.1",
+ "@smithy/hash-node": "^2.1.1",
+ "@smithy/hash-stream-node": "^2.1.1",
+ "@smithy/invalid-dependency": "^2.1.1",
+ "@smithy/md5-js": "^2.1.1",
+ "@smithy/middleware-content-length": "^2.1.1",
+ "@smithy/middleware-endpoint": "^2.4.1",
+ "@smithy/middleware-retry": "^2.1.1",
+ "@smithy/middleware-serde": "^2.1.1",
+ "@smithy/middleware-stack": "^2.1.1",
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/node-http-handler": "^2.3.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/url-parser": "^2.1.1",
+ "@smithy/util-base64": "^2.1.1",
+ "@smithy/util-body-length-browser": "^2.1.1",
+ "@smithy/util-body-length-node": "^2.2.1",
+ "@smithy/util-defaults-mode-browser": "^2.1.1",
+ "@smithy/util-defaults-mode-node": "^2.1.1",
+ "@smithy/util-endpoints": "^1.1.1",
+ "@smithy/util-retry": "^2.1.1",
+ "@smithy/util-stream": "^2.1.1",
+ "@smithy/util-utf8": "^2.1.1",
+ "@smithy/util-waiter": "^2.1.1",
+ "fast-xml-parser": "4.2.5",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sso": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.496.0.tgz",
+ "integrity": "sha512-fuaMuxKg7CMUsP9l3kxYWCOxFsBjdA0xj5nlikaDm1661/gB4KkAiGqRY8LsQkpNXvXU8Nj+f7oCFADFyGYzyw==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/core": "3.496.0",
+ "@aws-sdk/middleware-host-header": "3.496.0",
+ "@aws-sdk/middleware-logger": "3.496.0",
+ "@aws-sdk/middleware-recursion-detection": "3.496.0",
+ "@aws-sdk/middleware-user-agent": "3.496.0",
+ "@aws-sdk/region-config-resolver": "3.496.0",
+ "@aws-sdk/types": "3.496.0",
+ "@aws-sdk/util-endpoints": "3.496.0",
+ "@aws-sdk/util-user-agent-browser": "3.496.0",
+ "@aws-sdk/util-user-agent-node": "3.496.0",
+ "@smithy/config-resolver": "^2.1.1",
+ "@smithy/core": "^1.3.1",
+ "@smithy/fetch-http-handler": "^2.4.1",
+ "@smithy/hash-node": "^2.1.1",
+ "@smithy/invalid-dependency": "^2.1.1",
+ "@smithy/middleware-content-length": "^2.1.1",
+ "@smithy/middleware-endpoint": "^2.4.1",
+ "@smithy/middleware-retry": "^2.1.1",
+ "@smithy/middleware-serde": "^2.1.1",
+ "@smithy/middleware-stack": "^2.1.1",
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/node-http-handler": "^2.3.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/url-parser": "^2.1.1",
+ "@smithy/util-base64": "^2.1.1",
+ "@smithy/util-body-length-browser": "^2.1.1",
+ "@smithy/util-body-length-node": "^2.2.1",
+ "@smithy/util-defaults-mode-browser": "^2.1.1",
+ "@smithy/util-defaults-mode-node": "^2.1.1",
+ "@smithy/util-endpoints": "^1.1.1",
+ "@smithy/util-retry": "^2.1.1",
+ "@smithy/util-utf8": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sts": {
+ "version": "3.499.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.499.0.tgz",
+ "integrity": "sha512-Eyj9STw2DXMtXL5V/v0HYHO6+JjGPi257M5IYyxwqlvRchq6jbOsedobfxclB/gBUyBRtZdnyAIS8uCKjb4kpA==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/core": "3.496.0",
+ "@aws-sdk/credential-provider-node": "3.499.0",
+ "@aws-sdk/middleware-host-header": "3.496.0",
+ "@aws-sdk/middleware-logger": "3.496.0",
+ "@aws-sdk/middleware-recursion-detection": "3.496.0",
+ "@aws-sdk/middleware-user-agent": "3.496.0",
+ "@aws-sdk/region-config-resolver": "3.496.0",
+ "@aws-sdk/types": "3.496.0",
+ "@aws-sdk/util-endpoints": "3.496.0",
+ "@aws-sdk/util-user-agent-browser": "3.496.0",
+ "@aws-sdk/util-user-agent-node": "3.496.0",
+ "@smithy/config-resolver": "^2.1.1",
+ "@smithy/core": "^1.3.1",
+ "@smithy/fetch-http-handler": "^2.4.1",
+ "@smithy/hash-node": "^2.1.1",
+ "@smithy/invalid-dependency": "^2.1.1",
+ "@smithy/middleware-content-length": "^2.1.1",
+ "@smithy/middleware-endpoint": "^2.4.1",
+ "@smithy/middleware-retry": "^2.1.1",
+ "@smithy/middleware-serde": "^2.1.1",
+ "@smithy/middleware-stack": "^2.1.1",
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/node-http-handler": "^2.3.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/url-parser": "^2.1.1",
+ "@smithy/util-base64": "^2.1.1",
+ "@smithy/util-body-length-browser": "^2.1.1",
+ "@smithy/util-body-length-node": "^2.2.1",
+ "@smithy/util-defaults-mode-browser": "^2.1.1",
+ "@smithy/util-defaults-mode-node": "^2.1.1",
+ "@smithy/util-endpoints": "^1.1.1",
+ "@smithy/util-middleware": "^2.1.1",
+ "@smithy/util-retry": "^2.1.1",
+ "@smithy/util-utf8": "^2.1.1",
+ "fast-xml-parser": "4.2.5",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/core": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.496.0.tgz",
+ "integrity": "sha512-yT+ug7Cw/3eJi7x2es0+46x12+cIJm5Xv+GPWsrTFD1TKgqO/VPEgfDtHFagDNbFmjNQA65Ygc/kEdIX9ICX/A==",
+ "dependencies": {
+ "@smithy/core": "^1.3.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/signature-v4": "^2.1.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.496.0.tgz",
+ "integrity": "sha512-lukQMJ8SWWP5RqkRNOHi/H+WMhRvSWa3Fc5Jf/VP6xHiPLfF1XafcvthtV91e0VwPCiseI+HqChrcGq8pvnxHw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.496.0.tgz",
+ "integrity": "sha512-2nD1jp1sIwcQaWK1y/9ruQOkW16RUxZpzgjbW/gnK3iiUXwx+/FNQWxshud+GTSx3Q4x6eIhqsbjtP4VVPPuUA==",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.496.0",
+ "@aws-sdk/credential-provider-process": "3.496.0",
+ "@aws-sdk/credential-provider-sso": "3.496.0",
+ "@aws-sdk/credential-provider-web-identity": "3.496.0",
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/credential-provider-imds": "^2.2.1",
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/shared-ini-file-loader": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-node": {
+ "version": "3.499.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.499.0.tgz",
+ "integrity": "sha512-EsiSevVmcVSMIq7D9siSH/XVc5I0vMntg1rx6KQdng1Fq8X/RBL5t9wSWEwOl7KFo5HlEsWrLWIpo1WHuzIL/w==",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.496.0",
+ "@aws-sdk/credential-provider-ini": "3.496.0",
+ "@aws-sdk/credential-provider-process": "3.496.0",
+ "@aws-sdk/credential-provider-sso": "3.496.0",
+ "@aws-sdk/credential-provider-web-identity": "3.496.0",
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/credential-provider-imds": "^2.2.1",
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/shared-ini-file-loader": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-process": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.496.0.tgz",
+ "integrity": "sha512-/YZscCTGOKVmGr916Th4XF8Sz6JDtZ/n2loHG9exok9iy/qIbACsTRNLP9zexPxhPoue/oZqecY5xbVljfY34A==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/shared-ini-file-loader": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-sso": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.496.0.tgz",
+ "integrity": "sha512-eP7GxpT2QYubSDG7uk1GJW4eNymZCq65IxDyEFCXOP/kfqkxriCY+iVEFG6/Mo3LxvgrgHXU4jxrCAXMAWN43g==",
+ "dependencies": {
+ "@aws-sdk/client-sso": "3.496.0",
+ "@aws-sdk/token-providers": "3.496.0",
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/shared-ini-file-loader": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-web-identity": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.496.0.tgz",
+ "integrity": "sha512-IbP+qLlvJSpNPj+zW6TtFuLRTK5Tf0hW+2pom4vFyi5YSH4pn8UOC136UdewX8vhXGS9BJQ5zBDMasIyl5VeGQ==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.496.0.tgz",
+ "integrity": "sha512-jUdPpSJeqCYXf6hSjfwsfHway7peIV8Vz51w/BN91bF4vB/bYwAC5o9/iJiK/EoByp5asxA8fg9wFOyGjzdbLg==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.496.0.tgz",
+ "integrity": "sha512-EwMVSY6iBMeGbVnvwdaFl/ClMS/YWtxCAo+bcEtgk8ltRuo7qgbJem8Km/fvWC1vdWvIbe4ArdJ8iGzq62ffAw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.496.0.tgz",
+ "integrity": "sha512-+IuOcFsfqg2WAnaEzH6KhVbicqCxtOq9w3DH2jwTpddRlCx2Kqf6wCzg8luhHRGyjBZdsbIS+OXwyMevoppawA==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-signing": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.496.0.tgz",
+ "integrity": "sha512-Oq73Brs4IConvWnRlh8jM1V7LHoTw9SVQklu/QW2FPlNrB3B8fuTdWHHYIWv7ybw1bykXoCY99v865Mmq/Or/g==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/signature-v4": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-middleware": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.496.0.tgz",
+ "integrity": "sha512-+iMtRxFk0GmFWNUF4ilxylOQd9PZdR4ZC9jkcPIh1PZlvKtpCyFywKlk5RRZKklSoJ/CttcqwhMvOXTNbWm/0w==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@aws-sdk/util-endpoints": "3.496.0",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.496.0.tgz",
+ "integrity": "sha512-URrNVOPHPgEDm6QFu6lDC2cUFs+Jx23mA3jEwCvoKlXiEY/ZoWjH8wlX3OMUlLrF1qoUTuD03jjrJzF6zoCgug==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-config-provider": "^2.2.1",
+ "@smithy/util-middleware": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/token-providers": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.496.0.tgz",
+ "integrity": "sha512-fyi8RcObEa1jNETJdc2H6q9VHrrdKCj/b6+fbLvymb7mUVRd0aWUn+24SNUImnSOnrwYnwaMfyyEC388X4MbFQ==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/middleware-host-header": "3.496.0",
+ "@aws-sdk/middleware-logger": "3.496.0",
+ "@aws-sdk/middleware-recursion-detection": "3.496.0",
+ "@aws-sdk/middleware-user-agent": "3.496.0",
+ "@aws-sdk/region-config-resolver": "3.496.0",
+ "@aws-sdk/types": "3.496.0",
+ "@aws-sdk/util-endpoints": "3.496.0",
+ "@aws-sdk/util-user-agent-browser": "3.496.0",
+ "@aws-sdk/util-user-agent-node": "3.496.0",
+ "@smithy/config-resolver": "^2.1.1",
+ "@smithy/fetch-http-handler": "^2.4.1",
+ "@smithy/hash-node": "^2.1.1",
+ "@smithy/invalid-dependency": "^2.1.1",
+ "@smithy/middleware-content-length": "^2.1.1",
+ "@smithy/middleware-endpoint": "^2.4.1",
+ "@smithy/middleware-retry": "^2.1.1",
+ "@smithy/middleware-serde": "^2.1.1",
+ "@smithy/middleware-stack": "^2.1.1",
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/node-http-handler": "^2.3.1",
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/shared-ini-file-loader": "^2.3.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/url-parser": "^2.1.1",
+ "@smithy/util-base64": "^2.1.1",
+ "@smithy/util-body-length-browser": "^2.1.1",
+ "@smithy/util-body-length-node": "^2.2.1",
+ "@smithy/util-defaults-mode-browser": "^2.1.1",
+ "@smithy/util-defaults-mode-node": "^2.1.1",
+ "@smithy/util-endpoints": "^1.1.1",
+ "@smithy/util-retry": "^2.1.1",
+ "@smithy/util-utf8": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/types": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
+ "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.496.0.tgz",
+ "integrity": "sha512-1QzOiWHi383ZwqSi/R2KgKCd7M+6DxkxI5acqLPm8mvDRDP2jRjrnVaC0g9/tlttWousGEemDUWStwrD2mVYSw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-endpoints": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.496.0.tgz",
+ "integrity": "sha512-4j2spN+h0I0qfSMsGvJXTfQBu1e18rPdekKvzsGJxhaAE1tNgUfUT4nbvc5uVn0sNjZmirskmJ3kfbzVOrqIFg==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/types": "^2.9.1",
+ "bowser": "^2.11.0",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.496.0.tgz",
+ "integrity": "sha512-h0Ax0jlDc7UIo3KoSI4C4tVLBFoiAdx3+DhTVfgLS7x93d41dMlziPoBX2RgdcFn37qnzw6AQKTVTMwDbRCGpg==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "aws-crt": ">=1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws-crt": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@aws-sdk/client-sso": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.485.0.tgz",
+ "integrity": "sha512-apN2bEn0PZs0jD4jAfvwO3dlWqw9YIQJ6TAudM1bd3S5vzWqlBBcLfQpK6taHoQaI+WqgUWXLuOf7gRFbGXKPg==",
+ "optional": true,
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/core": "3.485.0",
+ "@aws-sdk/middleware-host-header": "3.485.0",
+ "@aws-sdk/middleware-logger": "3.485.0",
+ "@aws-sdk/middleware-recursion-detection": "3.485.0",
+ "@aws-sdk/middleware-user-agent": "3.485.0",
+ "@aws-sdk/region-config-resolver": "3.485.0",
+ "@aws-sdk/types": "3.485.0",
+ "@aws-sdk/util-endpoints": "3.485.0",
+ "@aws-sdk/util-user-agent-browser": "3.485.0",
+ "@aws-sdk/util-user-agent-node": "3.485.0",
+ "@smithy/config-resolver": "^2.0.23",
+ "@smithy/core": "^1.2.2",
+ "@smithy/fetch-http-handler": "^2.3.2",
+ "@smithy/hash-node": "^2.0.18",
+ "@smithy/invalid-dependency": "^2.0.16",
+ "@smithy/middleware-content-length": "^2.0.18",
+ "@smithy/middleware-endpoint": "^2.3.0",
+ "@smithy/middleware-retry": "^2.0.26",
+ "@smithy/middleware-serde": "^2.0.16",
+ "@smithy/middleware-stack": "^2.0.10",
+ "@smithy/node-config-provider": "^2.1.9",
+ "@smithy/node-http-handler": "^2.2.2",
+ "@smithy/protocol-http": "^3.0.12",
+ "@smithy/smithy-client": "^2.2.1",
+ "@smithy/types": "^2.8.0",
+ "@smithy/url-parser": "^2.0.16",
+ "@smithy/util-base64": "^2.0.1",
+ "@smithy/util-body-length-browser": "^2.0.1",
+ "@smithy/util-body-length-node": "^2.1.0",
+ "@smithy/util-defaults-mode-browser": "^2.0.24",
+ "@smithy/util-defaults-mode-node": "^2.0.32",
+ "@smithy/util-endpoints": "^1.0.8",
+ "@smithy/util-retry": "^2.0.9",
+ "@smithy/util-utf8": "^2.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sts": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.485.0.tgz",
+ "integrity": "sha512-PI4q36kVF0fpIPZyeQhrwwJZ6SRkOGvU3rX5Qn4b5UY5X+Ct1aLhqSX8/OB372UZIcnh6eSvERu8POHleDO7Jw==",
+ "optional": true,
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/core": "3.485.0",
+ "@aws-sdk/credential-provider-node": "3.485.0",
+ "@aws-sdk/middleware-host-header": "3.485.0",
+ "@aws-sdk/middleware-logger": "3.485.0",
+ "@aws-sdk/middleware-recursion-detection": "3.485.0",
+ "@aws-sdk/middleware-user-agent": "3.485.0",
+ "@aws-sdk/region-config-resolver": "3.485.0",
+ "@aws-sdk/types": "3.485.0",
+ "@aws-sdk/util-endpoints": "3.485.0",
+ "@aws-sdk/util-user-agent-browser": "3.485.0",
+ "@aws-sdk/util-user-agent-node": "3.485.0",
+ "@smithy/config-resolver": "^2.0.23",
+ "@smithy/core": "^1.2.2",
+ "@smithy/fetch-http-handler": "^2.3.2",
+ "@smithy/hash-node": "^2.0.18",
+ "@smithy/invalid-dependency": "^2.0.16",
+ "@smithy/middleware-content-length": "^2.0.18",
+ "@smithy/middleware-endpoint": "^2.3.0",
+ "@smithy/middleware-retry": "^2.0.26",
+ "@smithy/middleware-serde": "^2.0.16",
+ "@smithy/middleware-stack": "^2.0.10",
+ "@smithy/node-config-provider": "^2.1.9",
+ "@smithy/node-http-handler": "^2.2.2",
+ "@smithy/protocol-http": "^3.0.12",
+ "@smithy/smithy-client": "^2.2.1",
+ "@smithy/types": "^2.8.0",
+ "@smithy/url-parser": "^2.0.16",
+ "@smithy/util-base64": "^2.0.1",
+ "@smithy/util-body-length-browser": "^2.0.1",
+ "@smithy/util-body-length-node": "^2.1.0",
+ "@smithy/util-defaults-mode-browser": "^2.0.24",
+ "@smithy/util-defaults-mode-node": "^2.0.32",
+ "@smithy/util-endpoints": "^1.0.8",
+ "@smithy/util-middleware": "^2.0.9",
+ "@smithy/util-retry": "^2.0.9",
+ "@smithy/util-utf8": "^2.0.2",
+ "fast-xml-parser": "4.2.5",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/core": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.485.0.tgz",
+ "integrity": "sha512-Yvi80DQcbjkYCft471ClE3HuetuNVqntCs6eFOomDcrJaqdOFrXv2kJAxky84MRA/xb7bGlDGAPbTuj1ICputg==",
+ "optional": true,
+ "dependencies": {
+ "@smithy/core": "^1.2.2",
+ "@smithy/protocol-http": "^3.0.12",
+ "@smithy/signature-v4": "^2.0.0",
+ "@smithy/smithy-client": "^2.2.1",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-cognito-identity": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.485.0.tgz",
+ "integrity": "sha512-XIy5h1AcDiY3V286X7KrLA5HAxLfzLGrUGBPFY+GTJGYetDhlJwFz12q6BOkIfeAhUbT2Umb4ptujX9eqpZJHQ==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/client-cognito-identity": "3.485.0",
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.485.0.tgz",
+ "integrity": "sha512-3XkFgwVU1XOB33dV7t9BKJ/ptdl2iS+0dxE7ecq8aqT2/gsfKmLCae1G17P8WmdD3z0kMDTvnqM2aWgUnSOkmg==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-http": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.485.0.tgz",
+ "integrity": "sha512-2/2Y3Z7cpKf8vbQ+FzoBPxRyb0hGJZB1YrnH7hptVi5gSVe1NiwV5ZtsDnv4cwUfOBqEu97nMXw5IrRO26S0DA==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/fetch-http-handler": "^2.3.2",
+ "@smithy/node-http-handler": "^2.2.2",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/protocol-http": "^3.0.12",
+ "@smithy/smithy-client": "^2.2.1",
+ "@smithy/types": "^2.8.0",
+ "@smithy/util-stream": "^2.0.24",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.485.0.tgz",
+ "integrity": "sha512-cFYF/Bdw7EnT4viSxYpNIv3IBkri/Yb+JpQXl8uDq7bfVJfAN5qZmK07vRkg08xL6TC4F41wshhMSAucGdTwIw==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.485.0",
+ "@aws-sdk/credential-provider-process": "3.485.0",
+ "@aws-sdk/credential-provider-sso": "3.485.0",
+ "@aws-sdk/credential-provider-web-identity": "3.485.0",
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/credential-provider-imds": "^2.0.0",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/shared-ini-file-loader": "^2.0.6",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-node": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.485.0.tgz",
+ "integrity": "sha512-2DwzO2azkSzngifKDT61W/DL0tSzewuaFHiLJWdfc8Et3mdAQJ9x3KAj8u7XFpjIcGNqk7FiKjN+zeGUuNiEhA==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.485.0",
+ "@aws-sdk/credential-provider-ini": "3.485.0",
+ "@aws-sdk/credential-provider-process": "3.485.0",
+ "@aws-sdk/credential-provider-sso": "3.485.0",
+ "@aws-sdk/credential-provider-web-identity": "3.485.0",
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/credential-provider-imds": "^2.0.0",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/shared-ini-file-loader": "^2.0.6",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-process": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.485.0.tgz",
+ "integrity": "sha512-X9qS6ZO/rDKYDgWqD1YmSX7sAUUHax9HbXlgGiTTdtfhZvQh1ZmnH6wiPu5WNliafHZFtZT2W07kgrDLPld/Ug==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/shared-ini-file-loader": "^2.0.6",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-sso": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.485.0.tgz",
+ "integrity": "sha512-l0oC8GTrWh+LFQQfSmG1Jai1PX7Mhj9arb/CaS1/tmeZE0hgIXW++tvljYs/Dds4LGXUlaWG+P7BrObf6OyIXA==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/client-sso": "3.485.0",
+ "@aws-sdk/token-providers": "3.485.0",
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/shared-ini-file-loader": "^2.0.6",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-web-identity": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.485.0.tgz",
+ "integrity": "sha512-WpBFZFE0iXtnibH5POMEKITj/hR0YV5l2n9p8BEvKjdJ63s3Xke1RN20ZdIyKDaRDwj8adnKDgNPEnAKdS4kLw==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-providers": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.485.0.tgz",
+ "integrity": "sha512-SpGEmiVr+C9Dtc5tZFfFYXSNxbl1jShLlyZPWERHBn4QwGvdXcgPB96I0yvUuitBKrM0winHsCWH7CR/z24kmg==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/client-cognito-identity": "3.485.0",
+ "@aws-sdk/client-sso": "3.485.0",
+ "@aws-sdk/client-sts": "3.485.0",
+ "@aws-sdk/credential-provider-cognito-identity": "3.485.0",
+ "@aws-sdk/credential-provider-env": "3.485.0",
+ "@aws-sdk/credential-provider-http": "3.485.0",
+ "@aws-sdk/credential-provider-ini": "3.485.0",
+ "@aws-sdk/credential-provider-node": "3.485.0",
+ "@aws-sdk/credential-provider-process": "3.485.0",
+ "@aws-sdk/credential-provider-sso": "3.485.0",
+ "@aws-sdk/credential-provider-web-identity": "3.485.0",
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/credential-provider-imds": "^2.0.0",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/lib-storage": {
+ "version": "3.499.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.499.0.tgz",
+ "integrity": "sha512-rL++Re7Oed8uwkMSafpeG6ryB1vzW0dQLi5L3IWPhllWaokrXiEJ1lT1sg8vtyoMaZ4HNGE9jeyxMCRIa52Enw==",
+ "dependencies": {
+ "@smithy/abort-controller": "^2.1.1",
+ "@smithy/middleware-endpoint": "^2.4.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "buffer": "5.6.0",
+ "events": "3.3.0",
+ "stream-browserify": "3.0.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "@aws-sdk/client-s3": "^3.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/lib-storage/node_modules/buffer": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
+ "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
+ "dependencies": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-bucket-endpoint": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.496.0.tgz",
+ "integrity": "sha512-B+ilBMSs3+LJuo2bl2KB8GFdu+8PPVtYEWtwhNkmnaU8iMisgMBp5uuM8sUDvJX7I4iSF0WbgnhguX4cJqfAew==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@aws-sdk/util-arn-parser": "3.495.0",
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-config-provider": "^2.2.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@aws-sdk/types": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
+ "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-expect-continue": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.496.0.tgz",
+ "integrity": "sha512-+exo5DVc+BeDus2iI6Fz1thefHGDXxUhHZ+4VHQ6HkStMy3Y22HugyEGHSQZmtRL86Hjr7dFbEWFsC47a2ItGA==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-expect-continue/node_modules/@aws-sdk/types": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
+ "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-flexible-checksums": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.496.0.tgz",
+ "integrity": "sha512-yQIWfjEMvgsAJ7ku224vXDjXPD+f9zfKZFialJva8VUlEr7hQp4CQ0rxV3YThSaixKEDDs5k6kOjWAd2BPGr2A==",
+ "dependencies": {
+ "@aws-crypto/crc32": "3.0.0",
+ "@aws-crypto/crc32c": "3.0.0",
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/is-array-buffer": "^2.1.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-utf8": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-sdk/types": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
+ "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.485.0.tgz",
+ "integrity": "sha512-1mAUX9dQNGo2RIKseVj7SI/D5abQJQ/Os8hQ0NyVAyyVYF+Yjx5PphKgfhM5yoBwuwZUl6q71XPYEGNx7be6SA==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/protocol-http": "^3.0.12",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-location-constraint": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.496.0.tgz",
+ "integrity": "sha512-i4ocJ2Zs86OtPREbB18InFukhqg2qtBxb5gywv79IHDPVmpOYE4m/3v3yGUrkjfF2GTlUL0k5FskNNqw41yfng==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-location-constraint/node_modules/@aws-sdk/types": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
+ "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.485.0.tgz",
+ "integrity": "sha512-O8IgJ0LHi5wTs5GlpI7nqmmSSagkVdd1shpGgQWY2h0kMSCII8CJZHBG97dlFFpGTvx5EDlhPNek7rl/6F4dRw==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.485.0.tgz",
+ "integrity": "sha512-ZeVNATGNFcqkWDut3luVszROTUzkU5u+rJpB/xmeMoenlDAjPRiHt/ca3WkI5wAnIJ1VSNGpD2sOFLMCH+EWag==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/protocol-http": "^3.0.12",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-s3": {
+ "version": "3.499.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.499.0.tgz",
+ "integrity": "sha512-thTb47U1hYHk5ei+yO0D0aehbgQXeAcgvyyxOID9/HDuRfWuTvKdclWh/goIeDfvSS87VBukEAjnCa5JYBwzug==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@aws-sdk/util-arn-parser": "3.495.0",
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/signature-v4": "^2.1.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-config-provider": "^2.2.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@aws-sdk/types": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
+ "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-signing": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.485.0.tgz",
+ "integrity": "sha512-41xzT2p1sOibhsLkdE5rwPJkNbBtKD8Gp36/ySfu0KE415wfXKacElSVxAaBw39/j7iSWDYqqybeEYbAzk+3GQ==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/protocol-http": "^3.0.12",
+ "@smithy/signature-v4": "^2.0.0",
+ "@smithy/types": "^2.8.0",
+ "@smithy/util-middleware": "^2.0.9",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-ssec": {
+ "version": "3.498.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.498.0.tgz",
+ "integrity": "sha512-sWujXgzeTqMZzj/pRYEnnEbSzhBosqw9DXHOY1Mg2igI9NEfGlB7lPARp6aKmCaYlP3Bcj2X86vKCqF53mbyig==",
+ "dependencies": {
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-ssec/node_modules/@aws-sdk/types": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
+ "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.485.0.tgz",
+ "integrity": "sha512-CddCVOn+OPQ0CcchketIg+WF6v+MDLAf3GOYTR2htUxxIm7HABuRd6R3kvQ5Jny9CV8gMt22G1UZITsFexSJlQ==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@aws-sdk/util-endpoints": "3.485.0",
+ "@smithy/protocol-http": "^3.0.12",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.485.0.tgz",
+ "integrity": "sha512-2FB2EQ0sIE+YgFqGtkE1lDIMIL6nYe6MkOHBwBM7bommadKIrbbr2L22bPZGs3ReTsxiJabjzxbuCAVhrpHmhg==",
+ "optional": true,
+ "dependencies": {
+ "@smithy/node-config-provider": "^2.1.9",
+ "@smithy/types": "^2.8.0",
+ "@smithy/util-config-provider": "^2.1.0",
+ "@smithy/util-middleware": "^2.0.9",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/signature-v4-multi-region": {
+ "version": "3.499.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.499.0.tgz",
+ "integrity": "sha512-8HSFnZErRm7lAfk+Epxrf4QNdQEamg1CnbLybtKQQEjmvxLuXYvj16KlpYEZIwEENOMEvnCqMc7syTPkmjVhJA==",
+ "dependencies": {
+ "@aws-sdk/middleware-sdk-s3": "3.499.0",
+ "@aws-sdk/types": "3.496.0",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/signature-v4": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@aws-sdk/types": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.496.0.tgz",
+ "integrity": "sha512-umkGadK4QuNQaMoDICMm7NKRI/mYSXiyPjcn3d53BhsuArYU/52CebGQKdt4At7SwwsiVJZw9RNBHyN5Mm0HVw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/token-providers": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.485.0.tgz",
+ "integrity": "sha512-kOXA1WKIVIFNRqHL8ynVZ3hCKLsgnEmGr2iDR6agDNw5fYIlCO/6N2xR6QdGcLTvUUbwOlz4OvKLUQnWMKAnnA==",
+ "optional": true,
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/middleware-host-header": "3.485.0",
+ "@aws-sdk/middleware-logger": "3.485.0",
+ "@aws-sdk/middleware-recursion-detection": "3.485.0",
+ "@aws-sdk/middleware-user-agent": "3.485.0",
+ "@aws-sdk/region-config-resolver": "3.485.0",
+ "@aws-sdk/types": "3.485.0",
+ "@aws-sdk/util-endpoints": "3.485.0",
+ "@aws-sdk/util-user-agent-browser": "3.485.0",
+ "@aws-sdk/util-user-agent-node": "3.485.0",
+ "@smithy/config-resolver": "^2.0.23",
+ "@smithy/fetch-http-handler": "^2.3.2",
+ "@smithy/hash-node": "^2.0.18",
+ "@smithy/invalid-dependency": "^2.0.16",
+ "@smithy/middleware-content-length": "^2.0.18",
+ "@smithy/middleware-endpoint": "^2.3.0",
+ "@smithy/middleware-retry": "^2.0.26",
+ "@smithy/middleware-serde": "^2.0.16",
+ "@smithy/middleware-stack": "^2.0.10",
+ "@smithy/node-config-provider": "^2.1.9",
+ "@smithy/node-http-handler": "^2.2.2",
+ "@smithy/property-provider": "^2.0.0",
+ "@smithy/protocol-http": "^3.0.12",
+ "@smithy/shared-ini-file-loader": "^2.0.6",
+ "@smithy/smithy-client": "^2.2.1",
+ "@smithy/types": "^2.8.0",
+ "@smithy/url-parser": "^2.0.16",
+ "@smithy/util-base64": "^2.0.1",
+ "@smithy/util-body-length-browser": "^2.0.1",
+ "@smithy/util-body-length-node": "^2.1.0",
+ "@smithy/util-defaults-mode-browser": "^2.0.24",
+ "@smithy/util-defaults-mode-node": "^2.0.32",
+ "@smithy/util-endpoints": "^1.0.8",
+ "@smithy/util-retry": "^2.0.9",
+ "@smithy/util-utf8": "^2.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/types": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.485.0.tgz",
+ "integrity": "sha512-+QW32YQdvZRDOwrAQPo/qCyXoSjgXB6RwJwCwkd8ebJXRXw6tmGKIHaZqYHt/LtBymvnaBgBBADNa4+qFvlOFw==",
+ "dependencies": {
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-arn-parser": {
+ "version": "3.495.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.495.0.tgz",
+ "integrity": "sha512-hwdA3XAippSEUxs7jpznwD63YYFR+LtQvlEcebPTgWR9oQgG9TfS+39PUfbnEeje1ICuOrN3lrFqFbmP9uzbMg==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.485.0.tgz",
+ "integrity": "sha512-dTd642F7nJisApF8YjniqQ6U59CP/DCtar11fXf1nG9YNBCBsNNVw5ZfZb5nSNzaIdy27mQioWTCV18JEj1mxg==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/util-endpoints": "^1.0.8",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-locate-window": {
+ "version": "3.465.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.465.0.tgz",
+ "integrity": "sha512-f+QNcWGswredzC1ExNAB/QzODlxwaTdXkNT5cvke2RLX8SFU5pYk6h4uCtWC0vWPELzOfMfloBrJefBzlarhsw==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.485.0.tgz",
+ "integrity": "sha512-QliWbjg0uOhGTcWgWTKPMY0SBi07g253DjwrCINT1auqDrdQPxa10xozpZExBYjAK2KuhYDNUzni127ae6MHOw==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/types": "^2.8.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.485.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.485.0.tgz",
+ "integrity": "sha512-QF+aQ9jnDlPUlFBxBRqOylPf86xQuD3aEPpOErR+50qJawVvKa94uiAFdvtI9jv6hnRZmuFsTj2rsyytnbAYBA==",
+ "optional": true,
+ "dependencies": {
+ "@aws-sdk/types": "3.485.0",
+ "@smithy/node-config-provider": "^2.1.9",
+ "@smithy/types": "^2.8.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "aws-crt": ">=1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws-crt": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@aws-sdk/util-utf8-browser": {
+ "version": "3.259.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz",
+ "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==",
+ "dependencies": {
+ "tslib": "^2.3.1"
+ }
+ },
+ "node_modules/@aws-sdk/xml-builder": {
+ "version": "3.496.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.496.0.tgz",
+ "integrity": "sha512-GvEjh537IIeOw1ZkZuB37sV12u+ipS5Z1dwjEC/HAvhl5ac23ULtTr1/n+U1gLNN+BAKSWjKiQ2ksj8DiUzeyw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@colors/colors": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
+ "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "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/@dabh/diagnostics": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
+ "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
+ "dependencies": {
+ "colorspace": "1.1.x",
+ "enabled": "2.0.x",
+ "kuler": "^2.0.0"
+ }
+ },
+ "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.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
+ "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz",
+ "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.4",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-array/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,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/config-array/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,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz",
+ "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz",
+ "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.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": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/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,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/eslintrc/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,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.13.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz",
+ "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz",
+ "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz",
+ "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@hokify/agenda": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/@hokify/agenda/-/agenda-6.3.0.tgz",
+ "integrity": "sha512-fWrKMDe/8QHJXLOdEsMogb6cb213Z82iNsnU7nFrSIMFifEXSkXNTyCZ99FV3KLf+Du1gS/M9/8uTC6FHyWRZQ==",
+ "dependencies": {
+ "cron-parser": "^4",
+ "date.js": "~0.3.3",
+ "debug": "~4",
+ "human-interval": "~2",
+ "luxon": "^3",
+ "mongodb": "^4"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.6",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+ "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18.18.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,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+ "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/@mongodb-js/saslprep": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.3.tgz",
+ "integrity": "sha512-SyCxhJfmK6MoLNV5SbDpNdUy9SDv5H7y9/9rl3KpnwgTHWuNNMc87zWqbcIZXNWY+aUjxLGLEcvHoLagG4tWCg==",
+ "dependencies": {
+ "sparse-bitfield": "^3.0.3"
+ }
+ },
+ "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/@octokit/endpoint": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.4.tgz",
+ "integrity": "sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==",
+ "dependencies": {
+ "@octokit/types": "^12.0.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/openapi-types": {
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.1.0.tgz",
+ "integrity": "sha512-6G+ywGClliGQwRsjvqVYpklIfa7oRPA0vyhPQG/1Feh+B+wU0vGH1JiJ5T25d3g1JZYBHzR2qefLi9x8Gt+cpw=="
+ },
+ "node_modules/@octokit/request": {
+ "version": "8.1.6",
+ "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.6.tgz",
+ "integrity": "sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==",
+ "dependencies": {
+ "@octokit/endpoint": "^9.0.0",
+ "@octokit/request-error": "^5.0.0",
+ "@octokit/types": "^12.0.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/request-error": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz",
+ "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==",
+ "dependencies": {
+ "@octokit/types": "^12.0.0",
+ "deprecation": "^2.0.0",
+ "once": "^1.4.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/types": {
+ "version": "12.4.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.4.0.tgz",
+ "integrity": "sha512-FLWs/AvZllw/AGVs+nJ+ELCDZZJk+kY0zMen118xhL2zD0s1etIUHm1odgjP7epxYU1ln7SZxEUWYop5bhsdgQ==",
+ "dependencies": {
+ "@octokit/openapi-types": "^19.1.0"
+ }
+ },
+ "node_modules/@pkgr/core": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
+ "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "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/@smithy/abort-controller": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.1.1.tgz",
+ "integrity": "sha512-1+qdrUqLhaALYL0iOcN43EP6yAXXQ2wWZ6taf4S2pNGowmOc5gx+iMQv+E42JizNJjB0+gEadOXeV1Bf7JWL1Q==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/chunked-blob-reader": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.1.1.tgz",
+ "integrity": "sha512-NjNFCKxC4jVvn+lUr3Yo4/PmUJj3tbyqH6GNHueyTGS5Q27vlEJ1MkNhUDV8QGxJI7Bodnc2pD18lU2zRfhHlQ==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/chunked-blob-reader-native": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.1.1.tgz",
+ "integrity": "sha512-zNW+43dltfNMUrBEYLMWgI8lQr0uhtTcUyxkgC9EP4j17WREzgSFMPUFVrVV6Rc2+QtWERYjb4tzZnQGa7R9fQ==",
+ "dependencies": {
+ "@smithy/util-base64": "^2.1.1",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/config-resolver": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.1.1.tgz",
+ "integrity": "sha512-lxfLDpZm+AWAHPFZps5JfDoO9Ux1764fOgvRUBpHIO8HWHcSN1dkgsago1qLRVgm1BZ8RCm8cgv99QvtaOWIhw==",
+ "dependencies": {
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-config-provider": "^2.2.1",
+ "@smithy/util-middleware": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/core": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-1.3.1.tgz",
+ "integrity": "sha512-tf+NIu9FkOh312b6M9G4D68is4Xr7qptzaZGZUREELF8ysE1yLKphqt7nsomjKZVwW7WE5pDDex9idowNGRQ/Q==",
+ "dependencies": {
+ "@smithy/middleware-endpoint": "^2.4.1",
+ "@smithy/middleware-retry": "^2.1.1",
+ "@smithy/middleware-serde": "^2.1.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-middleware": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/credential-provider-imds": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.2.1.tgz",
+ "integrity": "sha512-7XHjZUxmZYnONheVQL7j5zvZXga+EWNgwEAP6OPZTi7l8J4JTeNh9aIOfE5fKHZ/ee2IeNOh54ZrSna+Vc6TFA==",
+ "dependencies": {
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/url-parser": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-codec": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.1.1.tgz",
+ "integrity": "sha512-E8KYBxBIuU4c+zrpR22VsVrOPoEDzk35bQR3E+xm4k6Pa6JqzkDOdMyf9Atac5GPNKHJBdVaQ4JtjdWX2rl/nw==",
+ "dependencies": {
+ "@aws-crypto/crc32": "3.0.0",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-hex-encoding": "^2.1.1",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-browser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.1.1.tgz",
+ "integrity": "sha512-JvEdCmGlZUay5VtlT8/kdR6FlvqTDUiJecMjXsBb0+k1H/qc9ME5n2XKPo8q/MZwEIA1GmGgYMokKGjVvMiDow==",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-config-resolver": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.1.1.tgz",
+ "integrity": "sha512-EqNqXYp3+dk//NmW3NAgQr9bEQ7fsu/CcxQmTiq07JlaIcne/CBWpMZETyXm9w5LXkhduBsdXdlMscfDUDn2fA==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.1.1.tgz",
+ "integrity": "sha512-LF882q/aFidFNDX7uROAGxq3H0B7rjyPkV6QDn6/KDQ+CG7AFkRccjxRf1xqajq/Pe4bMGGr+VKAaoF6lELIQw==",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-universal": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.1.1.tgz",
+ "integrity": "sha512-LR0mMT+XIYTxk4k2fIxEA1BPtW3685QlqufUEUAX1AJcfFfxNDKEvuCRZbO8ntJb10DrIFVJR9vb0MhDCi0sAQ==",
+ "dependencies": {
+ "@smithy/eventstream-codec": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/fetch-http-handler": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.4.1.tgz",
+ "integrity": "sha512-VYGLinPsFqH68lxfRhjQaSkjXM7JysUOJDTNjHBuN/ykyRb2f1gyavN9+VhhPTWCy32L4yZ2fdhpCs/nStEicg==",
+ "dependencies": {
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/querystring-builder": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-base64": "^2.1.1",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/hash-blob-browser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-2.1.1.tgz",
+ "integrity": "sha512-jizu1+2PAUjiGIfRtlPEU8Yo6zn+d78ti/ZHDesdf1SUn2BuZW433JlPoCOLH3dBoEEvTgLvQ8tUGSoTTALA+A==",
+ "dependencies": {
+ "@smithy/chunked-blob-reader": "^2.1.1",
+ "@smithy/chunked-blob-reader-native": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/hash-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.1.1.tgz",
+ "integrity": "sha512-Qhoq0N8f2OtCnvUpCf+g1vSyhYQrZjhSwvJ9qvR8BUGOtTXiyv2x1OD2e6jVGmlpC4E4ax1USHoyGfV9JFsACg==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-buffer-from": "^2.1.1",
+ "@smithy/util-utf8": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-stream-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-2.1.1.tgz",
+ "integrity": "sha512-VgDaKcfCy0iHcmtAZgZ3Yw9g37Gkn2JsQiMtFQXUh8Wmo3GfNgDwLOtdhJ272pOT7DStzpe9cNr+eV5Au8KfQA==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-utf8": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/invalid-dependency": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.1.1.tgz",
+ "integrity": "sha512-7WTgnKw+VPg8fxu2v9AlNOQ5yaz6RA54zOVB4f6vQuR0xFKd+RzlCpt0WidYTsye7F+FYDIaS/RnJW4pxjNInw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/is-array-buffer": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.1.1.tgz",
+ "integrity": "sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/md5-js": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-2.1.1.tgz",
+ "integrity": "sha512-L3MbIYBIdLlT+MWTYrdVSv/dow1+6iZ1Ad7xS0OHxTTs17d753ZcpOV4Ro7M7tRAVWML/sg2IAp/zzCb6aAttg==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-utf8": "^2.1.1",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/middleware-content-length": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.1.1.tgz",
+ "integrity": "sha512-rSr9ezUl9qMgiJR0UVtVOGEZElMdGFyl8FzWEF5iEKTlcWxGr2wTqGfDwtH3LAB7h+FPkxqv4ZU4cpuCN9Kf/g==",
+ "dependencies": {
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-endpoint": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.4.1.tgz",
+ "integrity": "sha512-XPZTb1E2Oav60Ven3n2PFx+rX9EDsU/jSTA8VDamt7FXks67ekjPY/XrmmPDQaFJOTUHJNKjd8+kZxVO5Ael4Q==",
+ "dependencies": {
+ "@smithy/middleware-serde": "^2.1.1",
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/shared-ini-file-loader": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/url-parser": "^2.1.1",
+ "@smithy/util-middleware": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-retry": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.1.1.tgz",
+ "integrity": "sha512-eMIHOBTXro6JZ+WWzZWd/8fS8ht5nS5KDQjzhNMHNRcG5FkNTqcKpYhw7TETMYzbLfhO5FYghHy1vqDWM4FLDA==",
+ "dependencies": {
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/service-error-classification": "^2.1.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-middleware": "^2.1.1",
+ "@smithy/util-retry": "^2.1.1",
+ "tslib": "^2.5.0",
+ "uuid": "^8.3.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-serde": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.1.1.tgz",
+ "integrity": "sha512-D8Gq0aQBeE1pxf3cjWVkRr2W54t+cdM2zx78tNrVhqrDykRA7asq8yVJij1u5NDtKzKqzBSPYh7iW0svUKg76g==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-stack": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.1.1.tgz",
+ "integrity": "sha512-KPJhRlhsl8CjgGXK/DoDcrFGfAqoqvuwlbxy+uOO4g2Azn1dhH+GVfC3RAp+6PoL5PWPb+vt6Z23FP+Mr6qeCw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/node-config-provider": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.2.1.tgz",
+ "integrity": "sha512-epzK3x1xNxA9oJgHQ5nz+2j6DsJKdHfieb+YgJ7ATWxzNcB7Hc+Uya2TUck5MicOPhDV8HZImND7ZOecVr+OWg==",
+ "dependencies": {
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/shared-ini-file-loader": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/node-http-handler": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.3.1.tgz",
+ "integrity": "sha512-gLA8qK2nL9J0Rk/WEZSvgin4AppvuCYRYg61dcUo/uKxvMZsMInL5I5ZdJTogOvdfVug3N2dgI5ffcUfS4S9PA==",
+ "dependencies": {
+ "@smithy/abort-controller": "^2.1.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/querystring-builder": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/property-provider": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.1.1.tgz",
+ "integrity": "sha512-FX7JhhD/o5HwSwg6GLK9zxrMUrGnb3PzNBrcthqHKBc3dH0UfgEAU24xnJ8F0uow5mj17UeBEOI6o3CF2k7Mhw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/protocol-http": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.1.1.tgz",
+ "integrity": "sha512-6ZRTSsaXuSL9++qEwH851hJjUA0OgXdQFCs+VDw4tGH256jQ3TjYY/i34N4vd24RV3nrjNsgd1yhb57uMoKbzQ==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-builder": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.1.1.tgz",
+ "integrity": "sha512-C/ko/CeEa8jdYE4gt6nHO5XDrlSJ3vdCG0ZAc6nD5ZIE7LBp0jCx4qoqp7eoutBu7VrGMXERSRoPqwi1WjCPbg==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-uri-escape": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-parser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.1.1.tgz",
+ "integrity": "sha512-H4+6jKGVhG1W4CIxfBaSsbm98lOO88tpDWmZLgkJpt8Zkk/+uG0FmmqMuCAc3HNM2ZDV+JbErxr0l5BcuIf/XQ==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/service-error-classification": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.1.1.tgz",
+ "integrity": "sha512-txEdZxPUgM1PwGvDvHzqhXisrc5LlRWYCf2yyHfvITWioAKat7srQvpjMAvgzf0t6t7j8yHrryXU9xt7RZqFpw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/shared-ini-file-loader": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.3.1.tgz",
+ "integrity": "sha512-2E2kh24igmIznHLB6H05Na4OgIEilRu0oQpYXo3LCNRrawHAcfDKq9004zJs+sAMt2X5AbY87CUCJ7IpqpSgdw==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/signature-v4": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.1.1.tgz",
+ "integrity": "sha512-Hb7xub0NHuvvQD3YwDSdanBmYukoEkhqBjqoxo+bSdC0ryV9cTfgmNjuAQhTPYB6yeU7hTR+sPRiFMlxqv6kmg==",
+ "dependencies": {
+ "@smithy/eventstream-codec": "^2.1.1",
+ "@smithy/is-array-buffer": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-hex-encoding": "^2.1.1",
+ "@smithy/util-middleware": "^2.1.1",
+ "@smithy/util-uri-escape": "^2.1.1",
+ "@smithy/util-utf8": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/smithy-client": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.3.1.tgz",
+ "integrity": "sha512-YsTdU8xVD64r2pLEwmltrNvZV6XIAC50LN6ivDopdt+YiF/jGH6PY9zUOu0CXD/d8GMB8gbhnpPsdrjAXHS9QA==",
+ "dependencies": {
+ "@smithy/middleware-endpoint": "^2.4.1",
+ "@smithy/middleware-stack": "^2.1.1",
+ "@smithy/protocol-http": "^3.1.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-stream": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/types": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.9.1.tgz",
+ "integrity": "sha512-vjXlKNXyprDYDuJ7UW5iobdmyDm6g8dDG+BFUncAg/3XJaN45Gy5RWWWUVgrzIK7S4R1KWgIX5LeJcfvSI24bw==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/url-parser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.1.1.tgz",
+ "integrity": "sha512-qC9Bv8f/vvFIEkHsiNrUKYNl8uKQnn4BdhXl7VzQRP774AwIjiSMMwkbT+L7Fk8W8rzYVifzJNYxv1HwvfBo3Q==",
+ "dependencies": {
+ "@smithy/querystring-parser": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/util-base64": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.1.1.tgz",
+ "integrity": "sha512-UfHVpY7qfF/MrgndI5PexSKVTxSZIdz9InghTFa49QOvuu9I52zLPLUHXvHpNuMb1iD2vmc6R+zbv/bdMipR/g==",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-browser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.1.1.tgz",
+ "integrity": "sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-node": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.2.1.tgz",
+ "integrity": "sha512-/ggJG+ta3IDtpNVq4ktmEUtOkH1LW64RHB5B0hcr5ZaWBmo96UX2cIOVbjCqqDickTXqBWZ4ZO0APuaPrD7Abg==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-buffer-from": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.1.1.tgz",
+ "integrity": "sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg==",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-config-provider": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.2.1.tgz",
+ "integrity": "sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-browser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.1.1.tgz",
+ "integrity": "sha512-lqLz/9aWRO6mosnXkArtRuQqqZBhNpgI65YDpww4rVQBuUT7qzKbDLG5AmnQTCiU4rOquaZO/Kt0J7q9Uic7MA==",
+ "dependencies": {
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "bowser": "^2.11.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.1.1.tgz",
+ "integrity": "sha512-tYVrc+w+jSBfBd267KDnvSGOh4NMz+wVH7v4CClDbkdPfnjvImBZsOURncT5jsFwR9KCuDyPoSZq4Pa6+eCUrA==",
+ "dependencies": {
+ "@smithy/config-resolver": "^2.1.1",
+ "@smithy/credential-provider-imds": "^2.2.1",
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/property-provider": "^2.1.1",
+ "@smithy/smithy-client": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/@smithy/util-endpoints": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.1.1.tgz",
+ "integrity": "sha512-sI4d9rjoaekSGEtq3xSb2nMjHMx8QXcz2cexnVyRWsy4yQ9z3kbDpX+7fN0jnbdOp0b3KSTZJZ2Yb92JWSanLw==",
+ "dependencies": {
+ "@smithy/node-config-provider": "^2.2.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-hex-encoding": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.1.1.tgz",
+ "integrity": "sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-middleware": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.1.1.tgz",
+ "integrity": "sha512-mKNrk8oz5zqkNcbcgAAepeJbmfUW6ogrT2Z2gDbIUzVzNAHKJQTYmH9jcy0jbWb+m7ubrvXKb6uMjkSgAqqsFA==",
+ "dependencies": {
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-retry": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.1.1.tgz",
+ "integrity": "sha512-Mg+xxWPTeSPrthpC5WAamJ6PW4Kbo01Fm7lWM1jmGRvmrRdsd3192Gz2fBXAMURyXpaNxyZf6Hr/nQ4q70oVEA==",
+ "dependencies": {
+ "@smithy/service-error-classification": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-stream": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.1.1.tgz",
+ "integrity": "sha512-J7SMIpUYvU4DQN55KmBtvaMc7NM3CZ2iWICdcgaovtLzseVhAqFRYqloT3mh0esrFw+3VEK6nQFteFsTqZSECQ==",
+ "dependencies": {
+ "@smithy/fetch-http-handler": "^2.4.1",
+ "@smithy/node-http-handler": "^2.3.1",
+ "@smithy/types": "^2.9.1",
+ "@smithy/util-base64": "^2.1.1",
+ "@smithy/util-buffer-from": "^2.1.1",
+ "@smithy/util-hex-encoding": "^2.1.1",
+ "@smithy/util-utf8": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-uri-escape": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.1.1.tgz",
+ "integrity": "sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-utf8": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.1.1.tgz",
+ "integrity": "sha512-BqTpzYEcUMDwAKr7/mVRUtHDhs6ZoXDi9NypMvMfOr/+u1NW7JgqodPDECiiLboEm6bobcPcECxzjtQh865e9A==",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-waiter": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.1.1.tgz",
+ "integrity": "sha512-kYy6BLJJNif+uqNENtJqWdXcpqo1LS+nj1AfXcDhOpqpSHJSAkVySLyZV9fkmuVO21lzGoxjvd1imGGJHph/IA==",
+ "dependencies": {
+ "@smithy/abort-controller": "^2.1.1",
+ "@smithy/types": "^2.9.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.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.4",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
+ "dev": true
+ },
+ "node_modules/@types/bad-words": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/bad-words/-/bad-words-3.0.3.tgz",
+ "integrity": "sha512-jYdpTxDOJ+EENnsCwt8cOZhV/+4+qcwhks1igrOSg4zwwA17rsPqLsZpTo1l+OwViNu+5SPus0v5g7iGx+ofzA==",
+ "dev": true
+ },
+ "node_modules/@types/config": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/@types/config/-/config-3.3.3.tgz",
+ "integrity": "sha512-BB8DBAud88EgiAKlz8WQStzI771Kb6F3j4dioRJ4GD+tP4tzcZyMlz86aXuZT4s9hyesFORehMQE6eqtA5O+Vg==",
+ "dev": true
+ },
+ "node_modules/@types/eslint": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
+ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/eslint__js": {
+ "version": "8.42.3",
+ "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz",
+ "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/eslint": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/jsdom": {
+ "version": "21.1.6",
+ "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.6.tgz",
+ "integrity": "sha512-/7kkMsC+/kMs7gAYmmBR9P0vGTnOoLhQhyhQJSlXGI5bzTHp6xdo0TtKWQAsz6pmSAeVqKSbqeyP6hytqr9FDw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "@types/tough-cookie": "*",
+ "parse5": "^7.0.0"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "18.19.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.6.tgz",
+ "integrity": "sha512-X36s5CXMrrJOs2lQCdDF68apW4Rfx9ixYMawlepwmE4Anezv/AV2LSpKD1Ub8DAc+urp5bk0BGZ6NtmBitfnsg==",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/node-fetch": {
+ "version": "2.6.10",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.10.tgz",
+ "integrity": "sha512-PPpPK6F9ALFTn59Ka3BaL+qGuipRfxNE8qVgkp0bVixeiR2c2/L+IVOiBdu9JhhT22sWnQEp6YyHGI2b2+CMcA==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "form-data": "^4.0.0"
+ }
+ },
+ "node_modules/@types/tough-cookie": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
+ "dev": true
+ },
+ "node_modules/@types/triple-beam": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
+ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="
+ },
+ "node_modules/@types/webidl-conversions": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
+ "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
+ },
+ "node_modules/@types/whatwg-url": {
+ "version": "8.2.2",
+ "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz",
+ "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/webidl-conversions": "*"
+ }
+ },
+ "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/type-utils": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.12.1.tgz",
+ "integrity": "sha512-zJzrvbDVjIzVKV2TGHcjembEhws8RWXJhmqfO9hS2gRXBN0gDwGhRPEdJ6AZglzfJ+YA1q09EWpSLSXjBJpIMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "8.12.1",
+ "@typescript-eslint/utils": "8.12.1",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.1.tgz",
+ "integrity": "sha512-anMS4es5lxBe4UVcDXOkcDb3csnm5BvaNIbOFfvy/pJEohorsggdVB8MFbl5EZiEuBnZZ0ei1z7W5b6FdFiV1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.1.tgz",
+ "integrity": "sha512-k/o9khHOckPeDXilFTIPsP9iAYhhdMh3OsOL3i2072PNpFqhqzRHx472/0DeC8H/WZee3bZG0z2ddGRSPgeOKw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "8.12.1",
+ "@typescript-eslint/visitor-keys": "8.12.1",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.3.2",
+ "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.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.1.tgz",
+ "integrity": "sha512-2RwdwnNGuOQKdGjuhujQHUqBZhEuodg2sLVPvOfWktvA9sOXOVqARjOyHSyhN2LiJGKxV6c8oOcmOtRcAnEeFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.12.1",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/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,
+ "license": "ISC",
+ "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": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.1.tgz",
+ "integrity": "sha512-sDv9yFHrhKe1WN8EYuzfhKCh/sFRupe9P+m/lZ5YgVvPoCUGHNN50IO4llSu7JAbftUM/QcCh+GeCortXPrBYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "8.12.1",
+ "@typescript-eslint/types": "8.12.1",
+ "@typescript-eslint/typescript-estree": "8.12.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.1.tgz",
+ "integrity": "sha512-bma6sD1iViTt+y9MAwDlBdPTMCqoH/BNdcQk4rKhIZWv3eM0xHmzeSrPJA663PAqFqfpOmtdugycpr0E1mZDVA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.12.1",
+ "@typescript-eslint/visitor-keys": "8.12.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.1.tgz",
+ "integrity": "sha512-anMS4es5lxBe4UVcDXOkcDb3csnm5BvaNIbOFfvy/pJEohorsggdVB8MFbl5EZiEuBnZZ0ei1z7W5b6FdFiV1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.1.tgz",
+ "integrity": "sha512-k/o9khHOckPeDXilFTIPsP9iAYhhdMh3OsOL3i2072PNpFqhqzRHx472/0DeC8H/WZee3bZG0z2ddGRSPgeOKw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "8.12.1",
+ "@typescript-eslint/visitor-keys": "8.12.1",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.3.2",
+ "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.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.1.tgz",
+ "integrity": "sha512-2RwdwnNGuOQKdGjuhujQHUqBZhEuodg2sLVPvOfWktvA9sOXOVqARjOyHSyhN2LiJGKxV6c8oOcmOtRcAnEeFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.12.1",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/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,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@vladfrangu/async_event_emitter": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.3.0.tgz",
+ "integrity": "sha512-pmkbRGAqTM3N7R4KCObOAqqoZzeURR6oC11amaXmY4ZLShu4MdLymm1/F0fZssYKAsSE79TibRbdXwfvYMIt0Q==",
+ "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.14.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "dev": true,
+ "license": "MIT",
+ "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,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz",
+ "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz",
+ "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "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-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.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "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,
+ "license": "Python-2.0"
+ },
+ "node_modules/async": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
+ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/bad-words": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/bad-words/-/bad-words-3.0.4.tgz",
+ "integrity": "sha512-v/Q9uRPH4+yzDVLL4vR1+S9KoFgOEUl5s4axd6NIAq8SV2mradgi4E8lma/Y0cw1ltVdvyegCQQKffCPRCp8fg==",
+ "dependencies": {
+ "badwords-list": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/badwords-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/badwords-list/-/badwords-list-1.0.0.tgz",
+ "integrity": "sha512-oWhaSG67e+HQj3OGHQt2ucP+vAPm1wTbdp2aDHeuh4xlGXBdWwzZ//pfu6swf5gZ8iX0b7JgmSo8BhgybbqszA=="
+ },
+ "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/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "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/bidi-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
+ "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
+ "dependencies": {
+ "require-from-string": "^2.0.2"
+ }
+ },
+ "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/bowser": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
+ "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
+ },
+ "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/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/bson": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz",
+ "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==",
+ "dependencies": {
+ "buffer": "^5.6.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "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": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/cache-manager": {
+ "version": "5.7.6",
+ "resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.7.6.tgz",
+ "integrity": "sha512-wBxnBHjDxF1RXpHCBD6HGvKER003Ts7IIm0CHpggliHzN1RZditb7rXoduE1rplc2DEFYKxhLKgFuchXMJje9w==",
+ "license": "MIT",
+ "dependencies": {
+ "eventemitter3": "^5.0.1",
+ "lodash.clonedeep": "^4.5.0",
+ "lru-cache": "^10.2.2",
+ "promise-coalesce": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/cache-manager/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "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,
+ "license": "MIT",
+ "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/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": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
+ "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
+ "dependencies": {
+ "color-convert": "^1.9.3",
+ "color-string": "^1.6.0"
+ }
+ },
+ "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=="
+ },
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "node_modules/color/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/colorspace": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
+ "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
+ "dependencies": {
+ "color": "^3.1.3",
+ "text-hex": "1.0.x"
+ }
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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/config": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/config/-/config-3.3.10.tgz",
+ "integrity": "sha512-9Kl3LpQ6zj93KaqgfIMTcpwTpgozFOqNl/Dk7mjras1BgGIOlqxWkyIGeU1my+sRuskRYwrCATgCk1RjAnRPGA==",
+ "dependencies": {
+ "json5": "^2.2.3"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "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/cron-parser": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz",
+ "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==",
+ "dependencies": {
+ "luxon": "^3.2.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/css-tree": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
+ "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
+ "dependencies": {
+ "mdn-data": "2.0.30",
+ "source-map-js": "^1.0.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+ }
+ },
+ "node_modules/cssstyle": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz",
+ "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==",
+ "dependencies": {
+ "rrweb-cssom": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/data-urls": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
+ "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
+ "dependencies": {
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/data-urls/node_modules/tr46": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz",
+ "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==",
+ "dependencies": {
+ "punycode": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/data-urls/node_modules/whatwg-url": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz",
+ "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==",
+ "dependencies": {
+ "tr46": "^5.0.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/date.js": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/date.js/-/date.js-0.3.3.tgz",
+ "integrity": "sha512-HgigOS3h3k6HnW011nAb43c5xx5rBXk8P2v/WIT9Zv4koIaVXiH2BURguI78VVp+5Qc076T7OR378JViCnZtBw==",
+ "dependencies": {
+ "debug": "~3.1.0"
+ }
+ },
+ "node_modules/date.js/node_modules/debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/date.js/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decimal.js": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
+ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
+ },
+ "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/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/deprecation": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
+ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
+ },
+ "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/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/dotenv": {
+ "version": "16.3.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
+ "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/motdotla/dotenv?sponsor=1"
+ }
+ },
+ "node_modules/enabled": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
+ "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "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": "9.13.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz",
+ "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.11.0",
+ "@eslint/config-array": "^0.18.0",
+ "@eslint/core": "^0.7.0",
+ "@eslint/eslintrc": "^3.1.0",
+ "@eslint/js": "9.13.0",
+ "@eslint/plugin-kit": "^0.2.0",
+ "@humanfs/node": "^0.16.5",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.3.1",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.1.0",
+ "eslint-visitor-keys": "^4.1.0",
+ "espree": "^10.2.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
+ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz",
+ "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.9.1"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": "*",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz",
+ "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.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/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/eslint/node_modules/eslint-visitor-keys": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz",
+ "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.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,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/eslint/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/espree": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz",
+ "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.12.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz",
+ "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.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,
+ "license": "BSD-2-Clause",
+ "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/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "license": "MIT"
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "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-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "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,
+ "license": "MIT"
+ },
+ "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/fast-xml-parser": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz",
+ "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==",
+ "funding": [
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/naturalintelligence"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "dependencies": {
+ "strnum": "^1.0.5"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
+ "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/fecha": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
+ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.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,
+ "license": "MIT",
+ "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": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fn.name": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
+ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "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": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "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": "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/html-encoding-sniffer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
+ "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
+ "dependencies": {
+ "whatwg-encoding": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz",
+ "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/human-interval": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/human-interval/-/human-interval-2.0.1.tgz",
+ "integrity": "sha512-r4Aotzf+OtKIGQCB3odUowy4GfUDTy3aTWTfLd7ZF2gBCy3XW3v/dJLRefZnOFFnjqs5B1TypvS8WarpBkYUNQ==",
+ "dependencies": {
+ "numbered": "^1.1.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "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/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "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,
+ "license": "MIT",
+ "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/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/ip-address": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
+ "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+ "dependencies": {
+ "jsbn": "1.1.0",
+ "sprintf-js": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/ip-address/node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
+ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+ },
+ "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-potential-custom-element-name": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "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,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsbn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
+ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
+ },
+ "node_modules/jsdom": {
+ "version": "23.2.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.2.0.tgz",
+ "integrity": "sha512-L88oL7D/8ufIES+Zjz7v0aes+oBMh2Xnh3ygWvL0OaICOomKEPKuPnIfBJekiXr+BHbbMjrWn/xqrDQuxFTeyA==",
+ "dependencies": {
+ "@asamuzakjp/dom-selector": "^2.0.1",
+ "cssstyle": "^4.0.1",
+ "data-urls": "^5.0.0",
+ "decimal.js": "^10.4.3",
+ "form-data": "^4.0.0",
+ "html-encoding-sniffer": "^4.0.0",
+ "http-proxy-agent": "^7.0.0",
+ "https-proxy-agent": "^7.0.2",
+ "is-potential-custom-element-name": "^1.0.1",
+ "parse5": "^7.1.2",
+ "rrweb-cssom": "^0.6.0",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^4.1.3",
+ "w3c-xmlserializer": "^5.0.0",
+ "webidl-conversions": "^7.0.0",
+ "whatwg-encoding": "^3.1.1",
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0",
+ "ws": "^8.16.0",
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "canvas": "^2.11.2"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jsdom/node_modules/tr46": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz",
+ "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==",
+ "dependencies": {
+ "punycode": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/jsdom/node_modules/whatwg-url": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz",
+ "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==",
+ "dependencies": {
+ "tr46": "^5.0.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "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,
+ "license": "MIT"
+ },
+ "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,
+ "license": "MIT"
+ },
+ "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/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/kareem": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz",
+ "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kuler": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
+ "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
+ },
+ "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,
+ "license": "MIT",
+ "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.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
+ "license": "MIT"
+ },
+ "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/logform": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz",
+ "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==",
+ "dependencies": {
+ "@colors/colors": "1.6.0",
+ "@types/triple-beam": "^1.3.2",
+ "fecha": "^4.2.0",
+ "ms": "^2.1.1",
+ "safe-stable-stringify": "^2.3.1",
+ "triple-beam": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/luxon": {
+ "version": "3.4.4",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz",
+ "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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/mdn-data": {
+ "version": "2.0.30",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
+ "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
+ },
+ "node_modules/memory-pager": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
+ "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
+ },
+ "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.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/moment": {
+ "version": "2.30.1",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
+ "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mongodb": {
+ "version": "4.17.2",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.2.tgz",
+ "integrity": "sha512-mLV7SEiov2LHleRJPMPrK2PMyhXFZt2UQLC4VD4pnth3jMjYKHhtqfwwkkvS/NXuo/Fp3vbhaNcXrIDaLRb9Tg==",
+ "dependencies": {
+ "bson": "^4.7.2",
+ "mongodb-connection-string-url": "^2.6.0",
+ "socks": "^2.7.1"
+ },
+ "engines": {
+ "node": ">=12.9.0"
+ },
+ "optionalDependencies": {
+ "@aws-sdk/credential-providers": "^3.186.0",
+ "@mongodb-js/saslprep": "^1.1.0"
+ }
+ },
+ "node_modules/mongodb-connection-string-url": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz",
+ "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==",
+ "dependencies": {
+ "@types/whatwg-url": "^8.2.1",
+ "whatwg-url": "^11.0.0"
+ }
+ },
+ "node_modules/mongoose": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.0.4.tgz",
+ "integrity": "sha512-wN9qvdevX3+922VnLT7CpaZRT3jmVCBOK2QMHMGeScQxDRnFMPpkuI9StEPpZo/3x8t+kbzH7F8RMPsyNwyM4w==",
+ "dependencies": {
+ "bson": "^6.2.0",
+ "kareem": "2.5.1",
+ "mongodb": "6.2.0",
+ "mpath": "0.9.0",
+ "mquery": "5.0.0",
+ "ms": "2.1.3",
+ "sift": "16.0.1"
+ },
+ "engines": {
+ "node": ">=16.20.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mongoose"
+ }
+ },
+ "node_modules/mongoose/node_modules/bson": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/bson/-/bson-6.2.0.tgz",
+ "integrity": "sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==",
+ "engines": {
+ "node": ">=16.20.1"
+ }
+ },
+ "node_modules/mongoose/node_modules/mongodb": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.2.0.tgz",
+ "integrity": "sha512-d7OSuGjGWDZ5usZPqfvb36laQ9CPhnWkAGHT61x5P95p/8nMVeH8asloMwW6GcYFeB0Vj4CB/1wOTDG2RA9BFA==",
+ "dependencies": {
+ "@mongodb-js/saslprep": "^1.1.0",
+ "bson": "^6.2.0",
+ "mongodb-connection-string-url": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=16.20.1"
+ },
+ "peerDependencies": {
+ "@aws-sdk/credential-providers": "^3.188.0",
+ "@mongodb-js/zstd": "^1.1.0",
+ "gcp-metadata": "^5.2.0",
+ "kerberos": "^2.0.1",
+ "mongodb-client-encryption": ">=6.0.0 <7",
+ "snappy": "^7.2.2",
+ "socks": "^2.7.1"
+ },
+ "peerDependenciesMeta": {
+ "@aws-sdk/credential-providers": {
+ "optional": true
+ },
+ "@mongodb-js/zstd": {
+ "optional": true
+ },
+ "gcp-metadata": {
+ "optional": true
+ },
+ "kerberos": {
+ "optional": true
+ },
+ "mongodb-client-encryption": {
+ "optional": true
+ },
+ "snappy": {
+ "optional": true
+ },
+ "socks": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/mongoose/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/mpath": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
+ "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/mquery": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz",
+ "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==",
+ "dependencies": {
+ "debug": "4.x"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "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=="
+ },
+ "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/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-fetch/node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
+ "node_modules/node-fetch/node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "node_modules/node-fetch/node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/nodemon": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.2.tgz",
+ "integrity": "sha512-9qIN2LNTrEzpOPBaWHTm4Asy1LxXLSickZStAQ4IZe7zsoIpD/A7LWxhZV3t4Zu352uBcqVnRsDXSMR2Sc3lTA==",
+ "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/nodemon/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/nodemon/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/nodemon/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/nodemon/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/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/numbered": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/numbered/-/numbered-1.1.0.tgz",
+ "integrity": "sha512-pv/ue2Odr7IfYOO0byC1KgBI10wo5YDauLhxY6/saNzAdAs0r1SotGCPzzCLNPL0xtrAwWRialLu23AAu9xO1g=="
+ },
+ "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==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/one-time": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
+ "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
+ "dependencies": {
+ "fn.name": "1.x.x"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "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,
+ "license": "MIT",
+ "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,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "dependencies": {
+ "entities": "^4.4.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "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.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
+ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/promise-coalesce": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/promise-coalesce/-/promise-coalesce-1.1.2.tgz",
+ "integrity": "sha512-zLaJ9b8hnC564fnJH6NFSOGZYYdzrAJn2JUUIwzoQb32fG2QAakpDNM+CZo1km6keXkRXRM+hml1BFAPVnPkxg==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/psl": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
+ },
+ "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==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
+ },
+ "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/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
+ },
+ "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,
+ "license": "MIT",
+ "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/rrweb-cssom": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz",
+ "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw=="
+ },
+ "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/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "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/safe-stable-stringify": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz",
+ "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/saxes": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+ "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=v12.22.7"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/sift": {
+ "version": "16.0.1",
+ "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz",
+ "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ=="
+ },
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "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/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
+ "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
+ "dependencies": {
+ "ip-address": "^9.0.5",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sparse-bitfield": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
+ "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
+ "dependencies": {
+ "memory-pager": "^1.0.2"
+ }
+ },
+ "node_modules/stack-trace": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
+ "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/stream-browserify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
+ "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
+ "dependencies": {
+ "inherits": "~2.0.4",
+ "readable-stream": "^3.5.0"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strnum": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
+ "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
+ },
+ "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/symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
+ },
+ "node_modules/synckit": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
+ "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@pkgr/core": "^0.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/text-hex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
+ "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
+ },
+ "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/tough-cookie": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
+ "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
+ "dependencies": {
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
+ "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
+ "dependencies": {
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/triple-beam": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
+ "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "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/typescript": {
+ "version": "5.4.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
+ "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-eslint": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.12.1.tgz",
+ "integrity": "sha512-SsKedZnq4TStkrpqnk+OqTnmkC9CkYBRNKjQ965CLpFruGcRkPF5UhKxbcbF6c/m2r6YAgKw/UtQxdlMjh3mug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.12.1",
+ "@typescript-eslint/parser": "8.12.1",
+ "@typescript-eslint/utils": "8.12.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.1.tgz",
+ "integrity": "sha512-gNg/inLRcPoBsKKIe4Vv38SVSOhk4BKWNO0T56sVff33gRqtTpOsrhHtiOKD1lmIOmCtZMPaW2x/h2FlM+sCEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.12.1",
+ "@typescript-eslint/type-utils": "8.12.1",
+ "@typescript-eslint/utils": "8.12.1",
+ "@typescript-eslint/visitor-keys": "8.12.1",
+ "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.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.1.tgz",
+ "integrity": "sha512-I/I9Bg7qFa8rOgBnUUHIWTgzbB5wVkSLX+04xGUzTcJUtdq/I2uHWR9mbW6qUYJG/UmkuDcTax5JHvoEWOAHOQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.12.1",
+ "@typescript-eslint/types": "8.12.1",
+ "@typescript-eslint/typescript-estree": "8.12.1",
+ "@typescript-eslint/visitor-keys": "8.12.1",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.1.tgz",
+ "integrity": "sha512-bma6sD1iViTt+y9MAwDlBdPTMCqoH/BNdcQk4rKhIZWv3eM0xHmzeSrPJA663PAqFqfpOmtdugycpr0E1mZDVA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.12.1",
+ "@typescript-eslint/visitor-keys": "8.12.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.1.tgz",
+ "integrity": "sha512-anMS4es5lxBe4UVcDXOkcDb3csnm5BvaNIbOFfvy/pJEohorsggdVB8MFbl5EZiEuBnZZ0ei1z7W5b6FdFiV1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.1.tgz",
+ "integrity": "sha512-k/o9khHOckPeDXilFTIPsP9iAYhhdMh3OsOL3i2072PNpFqhqzRHx472/0DeC8H/WZee3bZG0z2ddGRSPgeOKw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "8.12.1",
+ "@typescript-eslint/visitor-keys": "8.12.1",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.3.2",
+ "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.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.1.tgz",
+ "integrity": "sha512-2RwdwnNGuOQKdGjuhujQHUqBZhEuodg2sLVPvOfWktvA9sOXOVqARjOyHSyhN2LiJGKxV6c8oOcmOtRcAnEeFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.12.1",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/typescript-eslint/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,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "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/universal-user-agent": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",
+ "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="
+ },
+ "node_modules/universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "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,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "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/w3c-xmlserializer": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
+ "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
+ "dependencies": {
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
+ "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
+ "dependencies": {
+ "tr46": "^3.0.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/winston": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz",
+ "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==",
+ "dependencies": {
+ "@colors/colors": "^1.6.0",
+ "@dabh/diagnostics": "^2.0.2",
+ "async": "^3.2.3",
+ "is-stream": "^2.0.0",
+ "logform": "^2.4.0",
+ "one-time": "^1.0.0",
+ "readable-stream": "^3.4.0",
+ "safe-stable-stringify": "^2.3.1",
+ "stack-trace": "0.0.x",
+ "triple-beam": "^1.3.0",
+ "winston-transport": "^4.5.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/winston-transport": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.6.0.tgz",
+ "integrity": "sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==",
+ "dependencies": {
+ "logform": "^2.3.2",
+ "readable-stream": "^3.6.0",
+ "triple-beam": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "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=="
+ },
+ "node_modules/ws": {
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xml-name-validator": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
+ "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
- }
- },
- "node_modules/xml-name-validator": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
- "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/xmlchars": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
- "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
- },
- "node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": 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"
- }
}
- }
}
diff --git a/package.json b/package.json
index 8c34b285..2ebee6da 100644
--- a/package.json
+++ b/package.json
@@ -1,50 +1,55 @@
{
- "name": "fbw-discord-bot",
- "version": "1.0.0",
- "description": "Moderation, utility and support bot for the FlyByWire Simulations Discord server",
- "main": "./build/index.js",
- "exports": "./build/index.js",
- "scripts": {
- "start": "node .",
- "dev": "nodemon --config nodemon.json src/index.ts",
- "build": "tsc",
- "build:digitalocean": "npm ci --include=dev && npm run build",
- "lint": "eslint \"src/**/**/*.ts\"",
- "lint-fix": "eslint \"src/**/**/*.ts\" --fix"
- },
- "author": "FlyByWire Simulations",
- "license": "AGPL-3.0",
- "dependencies": {
- "@aws-sdk/client-s3": "^3.499.0",
- "@aws-sdk/lib-storage": "^3.499.0",
- "@hokify/agenda": "^6.0.0",
- "@octokit/request": "^8.1.1",
- "bad-words": "^3.0.4",
- "cache-manager": "^5.7.6",
- "config": "^3.3.9",
- "discord.js": "^14.11.0",
- "jsdom": "^23.2.0",
- "moment": "^2.29.4",
- "mongoose": "^8.0.3",
- "node-fetch": "^2.6.10",
- "winston": "^3.3.4"
- },
- "devDependencies": {
- "@flybywiresim/eslint-config": "^0.1.0",
- "@types/bad-words": "^3.0.3",
- "@types/config": "^3.3.1",
- "@types/jsdom": "^21.1.6",
- "@types/node": "^18.0.0",
- "@types/node-fetch": "^2.6.10",
- "@typescript-eslint/eslint-plugin": "^6.18.0",
- "@typescript-eslint/parser": "^6.18.0",
- "dotenv": "^16.0.0",
- "eslint": "^7.29.0",
- "nodemon": "^3.0.2",
- "ts-node": "^10.4.0",
- "typescript": "~5.4.5"
- },
- "engines": {
- "node": "18.x"
- }
+ "name": "fbw-discord-bot",
+ "version": "1.0.0",
+ "description": "Moderation, utility and support bot for the FlyByWire Simulations Discord server",
+ "main": "./build/index.js",
+ "exports": "./build/index.js",
+ "scripts": {
+ "start": "node .",
+ "dev": "nodemon --config nodemon.json src/index.ts",
+ "build": "tsc",
+ "build:digitalocean": "npm ci --include=dev && npm run build",
+ "lint": "eslint",
+ "lint-fix": "eslint --fix",
+ "prettier:check": "prettier . --check",
+ "prettier:write": "prettier . --write"
+ },
+ "author": "FlyByWire Simulations",
+ "license": "AGPL-3.0",
+ "dependencies": {
+ "@aws-sdk/client-s3": "^3.499.0",
+ "@aws-sdk/lib-storage": "^3.499.0",
+ "@hokify/agenda": "^6.0.0",
+ "@octokit/request": "^8.1.1",
+ "bad-words": "^3.0.4",
+ "cache-manager": "^5.7.6",
+ "config": "^3.3.9",
+ "discord.js": "^14.11.0",
+ "jsdom": "^23.2.0",
+ "moment": "^2.29.4",
+ "mongoose": "^8.0.3",
+ "node-fetch": "^2.6.10",
+ "winston": "^3.3.4"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.13.0",
+ "@types/bad-words": "^3.0.3",
+ "@types/config": "^3.3.1",
+ "@types/eslint__js": "^8.42.3",
+ "@types/jsdom": "^21.1.6",
+ "@types/node": "^18.0.0",
+ "@types/node-fetch": "^2.6.10",
+ "dotenv": "^16.0.0",
+ "eslint": "^9.13.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.2.1",
+ "nodemon": "^3.0.2",
+ "prettier": "^3.3.3",
+ "ts-node": "^10.4.0",
+ "typescript": "~5.4.5",
+ "typescript-eslint": "^8.12.1"
+ },
+ "engines": {
+ "node": "18.x"
+ }
}
diff --git a/src/client.ts b/src/client.ts
index 3801d69a..eb5bd449 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -3,48 +3,51 @@ import { constantsConfig, closeMongooseConnection, registerEvents, Logger } from
import Events from './events/index';
if (!process.env.BOT_SECRET) {
- Logger.error('Missing BOT_SECRET environment variable. Exiting...');
- process.exit(1);
+ Logger.error('Missing BOT_SECRET environment variable. Exiting...');
+ process.exit(1);
}
if (!constantsConfig.guildId) {
- Logger.error('Missing guildId configuration constant. Exiting...');
- process.exit(1);
+ Logger.error('Missing guildId configuration constant. Exiting...');
+ process.exit(1);
}
export const client = new Client({
- intents: [
- GatewayIntentBits.Guilds,
- GatewayIntentBits.GuildMembers,
- GatewayIntentBits.GuildMessages,
- GatewayIntentBits.MessageContent,
- GatewayIntentBits.GuildMessageReactions,
- GatewayIntentBits.GuildBans,
- GatewayIntentBits.GuildPresences,
- ],
+ intents: [
+ GatewayIntentBits.Guilds,
+ GatewayIntentBits.GuildMembers,
+ GatewayIntentBits.GuildMessages,
+ GatewayIntentBits.MessageContent,
+ GatewayIntentBits.GuildMessageReactions,
+ GatewayIntentBits.GuildBans,
+ GatewayIntentBits.GuildPresences,
+ ],
});
registerEvents(client, Events);
-client.login(process.env.BOT_SECRET)
- .catch((e) => {
- Logger.error(e);
- process.exit(1);
- });
+client.login(process.env.BOT_SECRET).catch((e) => {
+ Logger.error(e);
+ process.exit(1);
+});
const handleTermination = async () => {
- Logger.info('Terminating bot...');
- try {
- client.removeAllListeners();
- await closeMongooseConnection();
- await client.destroy();
- Logger.info('Cleanup complete. Exiting...');
- process.exit(0);
- } catch (error) {
- Logger.error('Error during termination:', error);
- process.exit(1);
- }
+ Logger.info('Terminating bot...');
+ try {
+ client.removeAllListeners();
+ await closeMongooseConnection();
+ await client.destroy();
+ Logger.info('Cleanup complete. Exiting...');
+ process.exit(0);
+ } catch (error) {
+ Logger.error('Error during termination:', error);
+ process.exit(1);
+ }
};
+// FIXME: this entire behavior seems to be not working as expected. "Cleanup complete. Exiting..." is not logged to the console. The process seems to exit prematurely.
+// This is probably caused by the process not waiting for the promises but it requires a deeper investigation.
+/* eslint-disable @typescript-eslint/no-misused-promises */
process.on('SIGINT', handleTermination);
process.on('SIGTERM', handleTermination);
+/* eslint-enable @typescript-eslint/no-misused-promises */
diff --git a/src/commands/context/index.ts b/src/commands/context/index.ts
index 1346d3e3..d3e875a0 100644
--- a/src/commands/context/index.ts
+++ b/src/commands/context/index.ts
@@ -3,10 +3,6 @@ import userInfo from './user/userInfo';
import reportMessage from './message/reportMessage';
import listInfractions from './user/listInfractions';
-const contextArray: ContextMenuCommand[] = [
- userInfo,
- reportMessage,
- listInfractions,
-];
+const contextArray: ContextMenuCommand[] = [userInfo, reportMessage, listInfractions];
export default contextArray;
diff --git a/src/commands/context/message/reportMessage.ts b/src/commands/context/message/reportMessage.ts
index ef85cd0b..116e001b 100644
--- a/src/commands/context/message/reportMessage.ts
+++ b/src/commands/context/message/reportMessage.ts
@@ -1,307 +1,322 @@
import {
- ActionRowBuilder,
- ApplicationCommandType,
- ContextMenuCommandInteraction,
- ModalBuilder, TextChannel,
- TextInputBuilder,
- TextInputStyle,
- Colors,
+ ActionRowBuilder,
+ ApplicationCommandType,
+ ContextMenuCommandInteraction,
+ ModalBuilder,
+ TextChannel,
+ TextInputBuilder,
+ TextInputStyle,
+ Colors,
+ Message,
+ ModalSubmitInteraction,
} from 'discord.js';
import moment from 'moment/moment';
import { constantsConfig, contextMenuCommand, contextMenuCommandStructure, Logger, makeEmbed } from '../../../lib';
const data = contextMenuCommandStructure({
- name: 'Report Message',
- type: ApplicationCommandType.Message,
+ name: 'Report Message',
+ type: ApplicationCommandType.Message,
});
-const reportedMessageEmbed = (targetMessage: any, interaction: ContextMenuCommandInteraction<'cached'>, messageContent: string, commentContent: string, formattedDate: string) => makeEmbed({
+const reportedMessageEmbed = (
+ targetMessage: Message,
+ interaction: ContextMenuCommandInteraction<'cached'>,
+ messageContent: string,
+ commentContent: string,
+ formattedDate: string,
+) =>
+ makeEmbed({
author: {
- name: `[REPORTED MESSAGE] ${targetMessage.author.tag}`,
- iconURL: targetMessage.author.displayAvatarURL(),
+ name: `[REPORTED MESSAGE] ${targetMessage.author.tag}`,
+ iconURL: targetMessage.author.displayAvatarURL(),
},
fields: [
- {
- name: 'Reported by',
- value: interaction.user.toString(),
- inline: true,
- },
- {
- name: 'Message Author',
- value: targetMessage.author.toString(),
- inline: true,
- },
- {
- name: 'Message Content',
- value: messageContent,
- inline: false,
- },
- {
- name: 'Link to Message',
- value: targetMessage.url,
- inline: false,
- },
- {
- name: 'Additional Comments',
- value: commentContent,
- inline: false,
- },
- {
- name: 'Reported at',
- value: formattedDate,
- inline: false,
- },
+ {
+ name: 'Reported by',
+ value: interaction.user.toString(),
+ inline: true,
+ },
+ {
+ name: 'Message Author',
+ value: targetMessage.author.toString(),
+ inline: true,
+ },
+ {
+ name: 'Message Content',
+ value: messageContent,
+ inline: false,
+ },
+ {
+ name: 'Link to Message',
+ value: targetMessage.url,
+ inline: false,
+ },
+ {
+ name: 'Additional Comments',
+ value: commentContent,
+ inline: false,
+ },
+ {
+ name: 'Reported at',
+ value: formattedDate,
+ inline: false,
+ },
],
color: Colors.Red,
footer: { text: `Reported Users ID: ${targetMessage.author.id}` },
-});
+ });
export default contextMenuCommand(data, async ({ interaction }) => {
- const currentDate = new Date();
- const formattedDate: string = moment(currentDate)
- .utcOffset(0)
- .format();
- const scamReportLogs = interaction.guild.channels.resolve(constantsConfig.channels.SCAM_REPORT_LOGS) as TextChannel;
- const modRoleId = constantsConfig.roles.MODERATION_TEAM;
-
- if (!scamReportLogs) {
- await interaction.reply({
- content: 'Unable to find the reporting channel. Please contact a Moderator.',
- ephemeral: true,
- });
- return;
- }
+ const currentDate = new Date();
+ const formattedDate: string = moment(currentDate).utcOffset(0).format();
+ const scamReportLogs = interaction.guild.channels.resolve(constantsConfig.channels.SCAM_REPORT_LOGS) as TextChannel;
+ const modRoleId = constantsConfig.roles.MODERATION_TEAM;
+
+ if (!scamReportLogs) {
+ await interaction.reply({
+ content: 'Unable to find the reporting channel. Please contact a Moderator.',
+ ephemeral: true,
+ });
+ return;
+ }
- const targetMessageId = interaction.targetId;
+ const targetMessageId = interaction.targetId;
- if (!interaction.channel || !targetMessageId) {
- await interaction.reply({
- content: 'Unable to find the target message.',
- ephemeral: true,
- });
- return;
- }
+ if (!interaction.channel || !targetMessageId) {
+ await interaction.reply({
+ content: 'Unable to find the target message.',
+ ephemeral: true,
+ });
+ return;
+ }
- const targetMessage = await interaction.channel.messages.fetch(targetMessageId);
+ const targetMessage = await interaction.channel.messages.fetch(targetMessageId);
- if (!targetMessage) {
- await interaction.reply({
- content: 'Unable to find the target message.',
- ephemeral: true,
- });
- return;
- }
+ if (!targetMessage) {
+ await interaction.reply({
+ content: 'Unable to find the target message.',
+ ephemeral: true,
+ });
+ return;
+ }
- let messageContent;
- if (targetMessage.embeds.length === 0) {
- if (targetMessage.content.length <= 1024) {
- messageContent = targetMessage.content;
- } else {
- messageContent = 'Message is longer than 1024 characters. Please check the link below.';
- }
+ let messageContent;
+ if (targetMessage.embeds.length === 0) {
+ if (targetMessage.content.length <= 1024) {
+ messageContent = targetMessage.content;
} else {
- messageContent = 'Message is an embed. Please check the link below.';
+ messageContent = 'Message is longer than 1024 characters. Please check the link below.';
}
+ } else {
+ messageContent = 'Message is an embed. Please check the link below.';
+ }
- //Create and send the modal
+ //Create and send the modal
- const modal = new ModalBuilder({
- customId: 'reportMessageModal',
- title: 'Report a Message',
- });
+ const modal = new ModalBuilder({
+ customId: 'reportMessageModal',
+ title: 'Report a Message',
+ });
- const reportMessageComments = new TextInputBuilder()
- .setCustomId('reportMessageComments')
- .setLabel('Comments')
- .setPlaceholder('Please provide any additional comments about your report here. You may leave this blank.')
- .setStyle(TextInputStyle.Paragraph)
- .setMaxLength(500)
- .setRequired(false);
+ const reportMessageComments = new TextInputBuilder()
+ .setCustomId('reportMessageComments')
+ .setLabel('Comments')
+ .setPlaceholder('Please provide any additional comments about your report here. You may leave this blank.')
+ .setStyle(TextInputStyle.Paragraph)
+ .setMaxLength(500)
+ .setRequired(false);
- const actionRow = new ActionRowBuilder().addComponents(reportMessageComments);
+ const actionRow = new ActionRowBuilder().addComponents(reportMessageComments);
- modal.addComponents(actionRow);
+ modal.addComponents(actionRow);
- await interaction.showModal(modal);
+ await interaction.showModal(modal);
- //Modal sent
+ //Modal sent
- const filter = (interaction: {
- customId: string;
- user: { id: any; };
- }) => interaction.customId === 'reportMessageModal' && interaction.user.id;
+ const filter = (interaction: ModalSubmitInteraction) =>
+ !!interaction.user.id && interaction.customId === 'reportMessageModal';
- let commentContent = 'No additional comments provided.';
+ let commentContent = 'No additional comments provided.';
- try {
- //Await a modal response
- const modalSubmitInteraction = await interaction.awaitModalSubmit({
- filter,
- time: 120000,
- });
+ try {
+ //Await a modal response
+ const modalSubmitInteraction = await interaction.awaitModalSubmit({
+ filter,
+ time: 120000,
+ });
- //Respond to the user once they have submitted the modal
- await modalSubmitInteraction.reply({
- content: `Thank you for reporting the message from ${targetMessage.author.toString()}, the <@&${modRoleId}> will review your report as soon as possible.`,
- ephemeral: true,
- });
+ //Respond to the user once they have submitted the modal
+ await modalSubmitInteraction.reply({
+ content: `Thank you for reporting the message from ${targetMessage.author.toString()}, the <@&${modRoleId}> will review your report as soon as possible.`,
+ ephemeral: true,
+ });
- commentContent = modalSubmitInteraction.fields.getTextInputValue('reportMessageComments');
- commentContent = commentContent.trim() || 'No additional comments provided.';
+ commentContent = modalSubmitInteraction.fields.getTextInputValue('reportMessageComments');
+ commentContent = commentContent.trim() || 'No additional comments provided.';
+ } catch (error) {
+ //Handle the error if the user does not respond in time
+ Logger.error(error);
+ await interaction.followUp({
+ content: 'You did not provide any comments in time. Your report has been cancelled.',
+ ephemeral: true,
+ });
+ return;
+ }
+
+ //Send a follow-up message to the user if they are part of the staff role group
+
+ if (
+ constantsConfig.roleGroups.SUPPORT &&
+ constantsConfig.roleGroups.SUPPORT.some((role) => interaction.member.roles.cache.has(role))
+ ) {
+ await interaction.followUp({
+ content: `Is your report urgent and requires immediate attention from the <@&${modRoleId}>? If so please click yes and I will ping the <@&${modRoleId}>. If not, click no.`,
+ components: [
+ {
+ type: 1,
+ components: [
+ {
+ type: 2,
+ style: 3,
+ label: 'Yes',
+ customId: 'pingModerationTeamYes',
+ },
+ {
+ type: 2,
+ style: 4,
+ label: 'No',
+ customId: 'pingModerationTeamNo',
+ },
+ ],
+ },
+ ],
+ ephemeral: true,
+ });
+
+ try {
+ // Handle the button interactions
+ const modPingButtonInteraction = await interaction.channel.awaitMessageComponent({
+ filter: (i) => i.customId === 'pingModerationTeamYes' || i.customId === 'pingModerationTeamNo',
+ time: 60000,
+ });
+
+ let pingModerationTeam = false;
+
+ if (modPingButtonInteraction.customId === 'pingModerationTeamYes') {
+ pingModerationTeam = true;
+ }
+
+ // Respond based on the user's choice
+ let responseMessage;
+
+ if (pingModerationTeam) {
+ // Ping the moderation team
+ await scamReportLogs.send({ content: `<@&${modRoleId}>` });
+ responseMessage = `I will also ping the <@&${modRoleId}>.`;
+ } else {
+ // Do not ping the moderation team
+ responseMessage = `I will not ping the <@&${modRoleId}>.`;
+ }
+
+ // Respond to the user
+ await modPingButtonInteraction.reply({
+ content: responseMessage,
+ ephemeral: true,
+ });
} catch (error) {
- //Handle the error if the user does not respond in time
- Logger.error(error);
- await interaction.followUp({
- content: 'You did not provide any comments in time. Your report has been cancelled.',
- ephemeral: true,
- });
- return;
+ Logger.error(error);
+ // Handle the error if the user does not respond in time
+ await interaction.followUp({
+ content: `You did not choose an option in time. Your report has been submitted without pinging the <@&${modRoleId}>.`,
+ ephemeral: true,
+ });
}
- //Send a follow-up message to the user if they are part of the staff role group
-
- if (constantsConfig.roleGroups.SUPPORT && constantsConfig.roleGroups.SUPPORT.some((role) => interaction.member.roles.cache.has(role))) {
- await interaction.followUp({
- content: `Is your report urgent and requires immediate attention from the <@&${modRoleId}>? If so please click yes and I will ping the <@&${modRoleId}>. If not, click no.`,
- components: [
- {
- type: 1,
- components: [
- {
- type: 2,
- style: 3,
- label: 'Yes',
- customId: 'pingModerationTeamYes',
- },
- {
- type: 2,
- style: 4,
- label: 'No',
- customId: 'pingModerationTeamNo',
- },
- ],
- },
- ],
- ephemeral: true,
- });
+ const modAlertsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_ALERTS) as TextChannel;
+
+ if (!modAlertsChannel) {
+ await interaction.followUp({
+ content: 'Unable to find the mod alerts channel. Please contact a Moderator.',
+ ephemeral: true,
+ });
+ await scamReportLogs.send({
+ embeds: [reportedMessageEmbed(targetMessage, interaction, messageContent, commentContent, formattedDate)],
+ });
+ return;
+ }
+
+ await interaction.followUp({
+ content: `Would you like to share this report in ${modAlertsChannel.toString()}? If you do not respond in 15 seconds, I will assume you do not want to share this report.`,
+ components: [
+ {
+ type: 1,
+ components: [
+ {
+ type: 2,
+ style: 3,
+ label: 'Yes',
+ customId: 'shareReportYes',
+ },
+ {
+ type: 2,
+ style: 4,
+ label: 'No',
+ customId: 'shareReportNo',
+ },
+ ],
+ },
+ ],
+ ephemeral: true,
+ });
- try {
- // Handle the button interactions
- const modPingButtonInteraction = await interaction.channel.awaitMessageComponent({
- filter: (i) => i.customId === 'pingModerationTeamYes' || i.customId === 'pingModerationTeamNo',
- time: 60000,
- });
-
- let pingModerationTeam = false;
-
- if (modPingButtonInteraction.customId === 'pingModerationTeamYes') {
- pingModerationTeam = true;
- }
-
- // Respond based on the user's choice
- let responseMessage;
-
- if (pingModerationTeam) {
- // Ping the moderation team
- await scamReportLogs.send({ content: `<@&${modRoleId}>` });
- responseMessage = `I will also ping the <@&${modRoleId}>.`;
- } else {
- // Do not ping the moderation team
- responseMessage = `I will not ping the <@&${modRoleId}>.`;
- }
-
- // Respond to the user
- await modPingButtonInteraction.reply({
- content: responseMessage,
- ephemeral: true,
- });
- } catch (error) {
- Logger.error(error);
- // Handle the error if the user does not respond in time
- await interaction.followUp({
- content: `You did not choose an option in time. Your report has been submitted without pinging the <@&${modRoleId}>.`,
- ephemeral: true,
- });
- }
-
- const modAlertsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_ALERTS) as TextChannel;
-
- if (!modAlertsChannel) {
- await interaction.followUp({
- content: 'Unable to find the mod alerts channel. Please contact a Moderator.',
- ephemeral: true,
- });
- await scamReportLogs.send({ embeds: [reportedMessageEmbed(targetMessage, interaction, messageContent, commentContent, formattedDate)] });
- return;
- }
-
- await interaction.followUp({
- content: `Would you like to share this report in ${modAlertsChannel}? If you do not respond in 15 seconds, I will assume you do not want to share this report.`,
- components: [
- {
- type: 1,
- components: [
- {
- type: 2,
- style: 3,
- label: 'Yes',
- customId: 'shareReportYes',
- },
- {
- type: 2,
- style: 4,
- label: 'No',
- customId: 'shareReportNo',
- },
- ],
- },
- ],
- ephemeral: true,
+ try {
+ const shareReportButtonInteraction = await interaction.channel.awaitMessageComponent({
+ filter: (i) => i.customId === 'shareReportYes' || i.customId === 'shareReportNo',
+ time: 15000,
+ });
+
+ const sharedReportEmbed = makeEmbed({
+ title: '[REPORTED MESSAGE]',
+ description: `A message has been reported in ${interaction.channel.toString()}.`,
+ fields: [
+ {
+ name: 'Link to Message',
+ value: targetMessage.url,
+ },
+ {
+ name: 'Reported At',
+ value: formattedDate,
+ },
+ ],
+ });
+
+ if (shareReportButtonInteraction.customId === 'shareReportYes') {
+ await modAlertsChannel.send({ embeds: [sharedReportEmbed] });
+ await shareReportButtonInteraction.reply({
+ content: `Your report has been submitted and shared in ${modAlertsChannel.toString()}.`,
+ ephemeral: true,
});
+ await scamReportLogs.send({
+ content: `Reported message from ${interaction.user.toString()} has been shared in ${modAlertsChannel.toString()}.`,
+ });
+ }
- try {
- const shareReportButtonInteraction = await interaction.channel.awaitMessageComponent({
- filter: (i) => i.customId === 'shareReportYes' || i.customId === 'shareReportNo',
- time: 15000,
- });
-
- const sharedReportEmbed = makeEmbed({
- title: '[REPORTED MESSAGE]',
- description: `A message has been reported in ${interaction.channel}.`,
- fields: [
- {
- name: 'Link to Message',
- value: targetMessage.url,
- },
- {
- name: 'Reported At',
- value: formattedDate,
- },
- ],
- });
-
- if (shareReportButtonInteraction.customId === 'shareReportYes') {
- await modAlertsChannel.send({ embeds: [sharedReportEmbed] });
- await shareReportButtonInteraction.reply({
- content: `Your report has been submitted and shared in ${modAlertsChannel}.`,
- ephemeral: true,
- });
- await scamReportLogs.send({ content: `Reported message from ${interaction.user.toString()} has been shared in ${modAlertsChannel}.` });
- }
-
- if (shareReportButtonInteraction.customId === 'shareReportNo') {
- await shareReportButtonInteraction.reply({
- content: `Your report has been submitted without sharing in ${modAlertsChannel}.`,
- ephemeral: true,
- });
- }
- } catch (error) {
- Logger.error(error);
- await interaction.followUp({
- content: `Your report has been submitted without sharing in ${modAlertsChannel}.`,
- ephemeral: true,
- });
- }
+ if (shareReportButtonInteraction.customId === 'shareReportNo') {
+ await shareReportButtonInteraction.reply({
+ content: `Your report has been submitted without sharing in ${modAlertsChannel.toString()}.`,
+ ephemeral: true,
+ });
+ }
+ } catch (error) {
+ Logger.error(error);
+ await interaction.followUp({
+ content: `Your report has been submitted without sharing in ${modAlertsChannel.toString()}.`,
+ ephemeral: true,
+ });
}
- await scamReportLogs.send({ embeds: [reportedMessageEmbed(targetMessage, interaction, messageContent, commentContent, formattedDate)] });
+ }
+ await scamReportLogs.send({
+ embeds: [reportedMessageEmbed(targetMessage, interaction, messageContent, commentContent, formattedDate)],
+ });
});
diff --git a/src/commands/context/user/listInfractions.ts b/src/commands/context/user/listInfractions.ts
index d487d488..743e9890 100644
--- a/src/commands/context/user/listInfractions.ts
+++ b/src/commands/context/user/listInfractions.ts
@@ -3,14 +3,14 @@ import { constantsConfig, contextMenuCommand, contextMenuCommandStructure } from
import { handleListInfraction } from '../../moderation/infractions/functions/listInfractions';
const data = contextMenuCommandStructure({
- name: 'List Infractions',
- type: ApplicationCommandType.User,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, // Overrides need to be added for admin and moderator roles
- dm_permission: false,
+ name: 'List Infractions',
+ type: ApplicationCommandType.User,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, // Overrides need to be added for admin and moderator roles
+ dm_permission: false,
});
export default contextMenuCommand(data, async ({ interaction }) => {
- const userID = interaction.targetId;
+ const userID = interaction.targetId;
- await handleListInfraction(interaction, userID, true);
+ await handleListInfraction(interaction, userID, true);
});
diff --git a/src/commands/context/user/userInfo.ts b/src/commands/context/user/userInfo.ts
index 0d25a548..d2bd4a49 100644
--- a/src/commands/context/user/userInfo.ts
+++ b/src/commands/context/user/userInfo.ts
@@ -1,76 +1,90 @@
-import { ApplicationCommandType } from 'discord.js';
+import { ApplicationCommandType, Colors, GuildMember, RoleMention } from 'discord.js';
import moment from 'moment/moment';
import { constantsConfig, contextMenuCommand, contextMenuCommandStructure, makeEmbed } from '../../../lib';
-const data = contextMenuCommandStructure({
- name: 'User Info',
- type: ApplicationCommandType.User,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER,
- dm_permission: false,
+const whoisEmbed = (targetMember: GuildMember, status: string, listedRoles: RoleMention[]) =>
+ makeEmbed({
+ author: {
+ name: targetMember.user.username,
+ iconURL: targetMember.user.avatarURL()!,
+ },
+ description: `${targetMember.toString()}`,
+ thumbnail: { url: targetMember.user.avatarURL()! },
+ fields: [
+ {
+ name: 'Username',
+ value: targetMember.user.tag,
+ inline: true,
+ },
+ {
+ name: 'Status',
+ value: status,
+ inline: true,
+ },
+ {
+ name: 'Joined',
+ value: moment(targetMember.joinedTimestamp).format('llll'),
+ inline: true,
+ },
+ {
+ name: 'Registered',
+ value: moment(targetMember.user.createdTimestamp).format('llll'),
+ inline: false,
+ },
+ {
+ name: 'Roles',
+ value: `\u200B${listedRoles.join(', ')}`,
+ },
+ {
+ name: 'Permissions',
+ value: targetMember.permissions
+ .toArray()
+ .join(', ')
+ .toLowerCase()
+ .replace(/_/g, ' ')
+ .replace(/(^\w)|(\s+\w)/g, (char) => char.toUpperCase()),
+ },
+ ],
+ footer: { text: `User ID: ${targetMember.id}` },
+ });
+
+const memberNotFoundEmbed = makeEmbed({
+ description: 'Could not find the requested member.',
+ color: Colors.Red,
});
const beautifiedStatus: { [key: string]: string } = {
- ONLINE: 'Online',
- IDLE: 'Idle',
- DND: 'Do Not Disturb',
- OFFLINE: 'Offline',
+ ONLINE: 'Online',
+ IDLE: 'Idle',
+ DND: 'Do Not Disturb',
+ OFFLINE: 'Offline',
};
+const data = contextMenuCommandStructure({
+ name: 'User Info',
+ type: ApplicationCommandType.User,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER,
+ dm_permission: false,
+});
+
export default contextMenuCommand(data, async ({ interaction }) => {
- const targetMember = interaction.guild?.members.cache.get(interaction.targetId)!;
+ const targetMember = interaction.guild.members.cache.get(interaction.targetId);
- const filteredRoles = targetMember.roles.cache.filter((role) => role.id !== interaction.guild.id);
- const listedRoles = filteredRoles.sort((a, b) => b.position - a.position).map((role) => role.toString());
+ if (!targetMember) {
+ return interaction.reply({ embeds: [memberNotFoundEmbed], ephemeral: true });
+ }
- const onlineStatus = beautifiedStatus[targetMember.presence?.status?.toUpperCase() ?? 'OFFLINE'];
+ const filteredRoles = targetMember.roles.cache.filter((role) => role.id !== interaction.guild.id);
+ const listedRoles = filteredRoles.sort((a, b) => b.position - a.position).map((role) => role.toString());
- let status;
- if (targetMember.presence == null) {
- status = 'Offline';
- } else {
- status = onlineStatus;
- }
+ const onlineStatus = beautifiedStatus[targetMember.presence?.status?.toUpperCase() ?? 'OFFLINE'];
- const whoisEmbed = makeEmbed({
- author: {
- name: targetMember.user.username,
- iconURL: targetMember.user.avatarURL()!,
- },
- description: `${targetMember}`,
- thumbnail: { url: targetMember.user.avatarURL()! },
- fields: [
- {
- name: 'Username',
- value: targetMember.user.tag,
- inline: true,
- },
- {
- name: 'Status',
- value: status,
- inline: true,
- },
- {
- name: 'Joined',
- value: moment(targetMember.joinedTimestamp).format('llll'),
- inline: true,
- },
- {
- name: 'Registered',
- value: moment(targetMember.user.createdTimestamp).format('llll'),
- inline: false,
- },
- {
- name: 'Roles',
- value: `\u200B${listedRoles.join(', ')}`,
- },
- {
- name: 'Permissions',
- value: targetMember.permissions.toArray().join(', ').toLowerCase().replace(/_/g, ' ')
- .replace(/(^\w)|(\s+\w)/g, (char) => char.toUpperCase()),
- },
- ],
- footer: { text: `User ID: ${targetMember.id}` },
- });
+ let status: string;
+ if (targetMember.presence == null) {
+ status = 'Offline';
+ } else {
+ status = onlineStatus;
+ }
- return interaction.reply({ embeds: [whoisEmbed] });
+ return interaction.reply({ embeds: [whoisEmbed(targetMember, status, listedRoles)] });
});
diff --git a/src/commands/index.ts b/src/commands/index.ts
index 244171fe..572a6e32 100644
--- a/src/commands/index.ts
+++ b/src/commands/index.ts
@@ -37,42 +37,42 @@ import prefixCommandCacheUpdate from './moderation/prefixCommands/prefixCommandC
import prefixHelp from './utils/prefixHelp';
const commandArray: SlashCommand[] = [
- ping,
- deployCommands,
- avatar,
- liveFlights,
- memberCount,
- metar,
- github,
- roleInfo,
- simbriefData,
- station,
- taf,
- wolframAlpha,
- zulu,
- cacheUpdate,
- infractions,
- slowmode,
- whois,
- faq,
- rules,
- welcome,
- searchFaq,
- roleAssignment,
- birthday,
- count,
- vatsim,
- help,
- docSearch,
- reportedIssues,
- commandTable,
- listRoleUsers,
- clearMessages,
- locate,
- prefixCommands,
- prefixCommandPermissions,
- prefixCommandCacheUpdate,
- prefixHelp,
+ ping,
+ deployCommands,
+ avatar,
+ liveFlights,
+ memberCount,
+ metar,
+ github,
+ roleInfo,
+ simbriefData,
+ station,
+ taf,
+ wolframAlpha,
+ zulu,
+ cacheUpdate,
+ infractions,
+ slowmode,
+ whois,
+ faq,
+ rules,
+ welcome,
+ searchFaq,
+ roleAssignment,
+ birthday,
+ count,
+ vatsim,
+ help,
+ docSearch,
+ reportedIssues,
+ commandTable,
+ listRoleUsers,
+ clearMessages,
+ locate,
+ prefixCommands,
+ prefixCommandPermissions,
+ prefixCommandCacheUpdate,
+ prefixHelp,
];
export default commandArray;
diff --git a/src/commands/moderation/cacheUpdate.ts b/src/commands/moderation/cacheUpdate.ts
index f16c3d72..e9947b22 100644
--- a/src/commands/moderation/cacheUpdate.ts
+++ b/src/commands/moderation/cacheUpdate.ts
@@ -1,123 +1,145 @@
-import { ApplicationCommandOptionType, ApplicationCommandType, Colors, EmbedField, TextChannel } from 'discord.js';
-import { constantsConfig, slashCommand, slashCommandStructure, makeEmbed } from '../../lib';
+import {
+ APIEmbedField,
+ ApplicationCommandOptionType,
+ ApplicationCommandType,
+ Colors,
+ EmbedField,
+ TextChannel,
+} from 'discord.js';
+import { constantsConfig, makeEmbed, slashCommand, slashCommandStructure } from '../../lib';
const data = slashCommandStructure({
- name: 'cache-update',
- description: 'Updates the cache of the bot for a specific cache type.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin, moderator and bot developer roles
- dm_permission: false,
- options: [
- {
- name: 'bans',
- description: 'Updates the bans cache by fetching all bans.',
- type: ApplicationCommandOptionType.Subcommand,
- },
- {
- name: 'channels',
- description: 'Updates the channels cache by fetching all channels.',
- type: ApplicationCommandOptionType.Subcommand,
- },
- {
- name: 'members',
- description: 'Updates the members cache by fetching all members.',
- type: ApplicationCommandOptionType.Subcommand,
- },
- {
- name: 'roles',
- description: 'Updates the roles cache by fetching all roles.',
- type: ApplicationCommandOptionType.Subcommand,
- },
- ],
+ name: 'cache-update',
+ description: 'Updates the cache of the bot for a specific cache type.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin, moderator and bot developer roles
+ dm_permission: false,
+ options: [
+ {
+ name: 'bans',
+ description: 'Updates the bans cache by fetching all bans.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ {
+ name: 'channels',
+ description: 'Updates the channels cache by fetching all channels.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ {
+ name: 'members',
+ description: 'Updates the members cache by fetching all members.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ {
+ name: 'roles',
+ description: 'Updates the roles cache by fetching all roles.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ ],
});
-const cacheUpdateEmbed = (action: string, fields: any, color: number) => makeEmbed({
+const cacheUpdateEmbed = (action: string, fields: APIEmbedField[], color: number) =>
+ makeEmbed({
title: `Cache Update - ${action}`,
fields,
color,
-});
+ });
-const noChannelEmbed = (action:string, channelName: string) => makeEmbed({
+const noChannelEmbed = (action: string, channelName: string) =>
+ makeEmbed({
title: `Sticky Message - ${action} - No ${channelName} channel`,
description: `The command was successful, but no message to ${channelName} was sent. Please check the channel still exists.`,
color: Colors.Yellow,
-});
+ });
-const cacheUpdateEmbedField = (moderator: string, cacheType: string, cacheSize: string, duration: string): EmbedField[] => [
- {
- name: 'Type',
- value: cacheType,
- inline: true,
- },
- {
- name: 'Count',
- value: cacheSize,
- inline: true,
- },
- {
- name: 'Moderator',
- value: moderator,
- inline: true,
- },
- {
- name: 'Duration',
- value: `${duration}s`,
- inline: true,
- },
+const cacheUpdateEmbedField = (
+ moderator: string,
+ cacheType: string,
+ cacheSize: string,
+ duration: string,
+): EmbedField[] => [
+ {
+ name: 'Type',
+ value: cacheType,
+ inline: true,
+ },
+ {
+ name: 'Count',
+ value: cacheSize,
+ inline: true,
+ },
+ {
+ name: 'Moderator',
+ value: moderator,
+ inline: true,
+ },
+ {
+ name: 'Duration',
+ value: `${duration}s`,
+ inline: true,
+ },
];
export default slashCommand(data, async ({ interaction }) => {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- let cacheSize: number | undefined;
- const start = new Date().getTime();
- const { bans, channels, members, roles } = interaction.guild;
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ let cacheSize: number | undefined;
+ const start = new Date().getTime();
+ const { bans, channels, members, roles } = interaction.guild;
- if (interaction.options.getSubcommand() === 'bans') {
- await bans.fetch();
- cacheSize = bans.cache.size;
- }
- if (interaction.options.getSubcommand() === 'channels') {
- await channels.fetch();
- cacheSize = channels.cache.size;
- }
- if (interaction.options.getSubcommand() === 'members') {
- await members.fetch();
- cacheSize = members.cache.size;
- }
- if (interaction.options.getSubcommand() === 'roles') {
- await roles.fetch();
- cacheSize = roles.cache.size;
- }
+ if (interaction.options.getSubcommand() === 'bans') {
+ await bans.fetch();
+ cacheSize = bans.cache.size;
+ }
+ if (interaction.options.getSubcommand() === 'channels') {
+ await channels.fetch();
+ cacheSize = channels.cache.size;
+ }
+ if (interaction.options.getSubcommand() === 'members') {
+ await members.fetch();
+ cacheSize = members.cache.size;
+ }
+ if (interaction.options.getSubcommand() === 'roles') {
+ await roles.fetch();
+ cacheSize = roles.cache.size;
+ }
- const duration = ((new Date().getTime() - start) / 1000).toFixed(2);
+ const duration = ((new Date().getTime() - start) / 1000).toFixed(2);
- if (cacheSize !== undefined) {
- await interaction.editReply({
- embeds: [cacheUpdateEmbed(interaction.options.getSubcommand(),
- cacheUpdateEmbedField(
- interaction.user.tag,
- interaction.options.getSubcommand(),
- cacheSize.toString(),
- duration,
- ),
- Colors.Green)],
- });
+ if (cacheSize !== undefined) {
+ await interaction.editReply({
+ embeds: [
+ cacheUpdateEmbed(
+ interaction.options.getSubcommand(),
+ cacheUpdateEmbedField(
+ interaction.user.tag,
+ interaction.options.getSubcommand(),
+ cacheSize.toString(),
+ duration,
+ ),
+ Colors.Green,
+ ),
+ ],
+ });
- try {
- await modLogsChannel.send({
- embeds: [cacheUpdateEmbed(interaction.options.getSubcommand(),
- cacheUpdateEmbedField(
- interaction.user.tag,
- interaction.options.getSubcommand(),
- cacheSize.toString(),
- duration,
- ),
- Colors.Green)],
- });
- } catch (error) {
- await interaction.followUp({ embeds: [noChannelEmbed(interaction.options.getSubcommand(), 'mod-log')] });
- }
+ try {
+ await modLogsChannel.send({
+ embeds: [
+ cacheUpdateEmbed(
+ interaction.options.getSubcommand(),
+ cacheUpdateEmbedField(
+ interaction.user.tag,
+ interaction.options.getSubcommand(),
+ cacheSize.toString(),
+ duration,
+ ),
+ Colors.Green,
+ ),
+ ],
+ });
+ } catch {
+ await interaction.followUp({ embeds: [noChannelEmbed(interaction.options.getSubcommand(), 'mod-log')] });
}
+ }
});
diff --git a/src/commands/moderation/clearMessages.ts b/src/commands/moderation/clearMessages.ts
index f5b34eca..23bba86e 100644
--- a/src/commands/moderation/clearMessages.ts
+++ b/src/commands/moderation/clearMessages.ts
@@ -1,114 +1,127 @@
-import { ApplicationCommandOptionType, ApplicationCommandType, TextChannel, Colors, ActionRowBuilder, ButtonBuilder, ButtonStyle, Interaction } from 'discord.js';
+import {
+ ApplicationCommandOptionType,
+ ApplicationCommandType,
+ TextChannel,
+ Colors,
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ Interaction,
+} from 'discord.js';
import { slashCommand, slashCommandStructure, makeEmbed, constantsConfig, Logger } from '../../lib';
const data = slashCommandStructure({
- name: 'clear-messages',
- description: 'Clear a specified number of messages in the current channel.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
- dm_permission: false,
- options: [{
- name: 'amount',
- description: 'Number of messages to clear (1-100).',
- type: ApplicationCommandOptionType.Integer,
- required: true,
- min_value: 1,
- max_value: 100,
- }],
+ name: 'clear-messages',
+ description: 'Clear a specified number of messages in the current channel.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
+ dm_permission: false,
+ options: [
+ {
+ name: 'amount',
+ description: 'Number of messages to clear (1-100).',
+ type: ApplicationCommandOptionType.Integer,
+ required: true,
+ min_value: 1,
+ max_value: 100,
+ },
+ ],
});
export default slashCommand(data, async ({ interaction }) => {
- const confirmButton = new ButtonBuilder()
- .setCustomId('clearMessages_confirm')
- .setLabel('Confirm')
- .setStyle(ButtonStyle.Danger);
+ const confirmButton = new ButtonBuilder()
+ .setCustomId('clearMessages_confirm')
+ .setLabel('Confirm')
+ .setStyle(ButtonStyle.Danger);
- const cancelButton = new ButtonBuilder()
- .setCustomId('clearMessages_cancel')
- .setLabel('Cancel')
- .setStyle(ButtonStyle.Secondary);
+ const cancelButton = new ButtonBuilder()
+ .setCustomId('clearMessages_cancel')
+ .setLabel('Cancel')
+ .setStyle(ButtonStyle.Secondary);
- const buttonRow = new ActionRowBuilder().addComponents(cancelButton, confirmButton);
+ const buttonRow = new ActionRowBuilder().addComponents(cancelButton, confirmButton);
- const amount = interaction.options.getInteger('amount');
+ const amount = interaction.options.getInteger('amount');
- if (!amount) {
- return interaction.reply({ content: 'Please specify the number of messages to clear.', ephemeral: true });
- }
-
- const { channel, user } = interaction;
- if (!channel) {
- return interaction.reply({ content: 'The channel could not be resolved.', ephemeral: true });
- }
+ if (!amount) {
+ return interaction.reply({ content: 'Please specify the number of messages to clear.', ephemeral: true });
+ }
- const confirmEmbed = makeEmbed({
- title: 'Confirm or Cancel',
- description: `You are about to clear **${amount}** message${amount > 1 ? 's' : ''}. This action **cannot** be undone.`,
- color: Colors.Red,
- footer: { text: 'Please confirm or cancel this action within 2 minutes.' },
- });
+ const { channel, user } = interaction;
+ if (!channel) {
+ return interaction.reply({ content: 'The channel could not be resolved.', ephemeral: true });
+ }
- const response = await interaction.reply({
- embeds: [confirmEmbed],
- components: [buttonRow],
- ephemeral: true,
- });
+ const confirmEmbed = makeEmbed({
+ title: 'Confirm or Cancel',
+ description: `You are about to clear **${amount}** message${amount > 1 ? 's' : ''}. This action **cannot** be undone.`,
+ color: Colors.Red,
+ footer: { text: 'Please confirm or cancel this action within 2 minutes.' },
+ });
- const filter = (buttonInteraction: Interaction) => buttonInteraction.user.id === interaction.user.id;
+ const response = await interaction.reply({
+ embeds: [confirmEmbed],
+ components: [buttonRow],
+ ephemeral: true,
+ });
- try {
- const confirmation = await response.awaitMessageComponent({ filter, time: 120_000 });
- if (confirmation.customId === 'clearMessages_confirm') {
- try {
- const messages = await (channel as TextChannel).bulkDelete(amount, true);
- const replyEmbed = makeEmbed({
- title: 'Messages Cleared',
- description: `Successfully cleared **${messages.size}** message${amount > 1 ? 's' : ''}.`,
- color: Colors.Green,
- timestamp: new Date(),
- });
+ const filter = (buttonInteraction: Interaction) => buttonInteraction.user.id === interaction.user.id;
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- const modLogEmbed = makeEmbed({
- title: '🧹 Messages Cleared',
- description: 'Messages have been cleared.',
- color: Colors.Green,
- fields: [
- { name: 'Moderator', value: `<@${user.id}>`, inline: true },
- { name: 'Channel', value: `<#${channel.id}>`, inline: true },
- { name: 'Amount', value: `${messages.size}`, inline: true },
- ],
- footer: { text: `Moderator ID: ${user.id}`, iconURL: user.displayAvatarURL() },
- timestamp: new Date(),
- });
+ try {
+ const confirmation = await response.awaitMessageComponent({ filter, time: 120_000 });
+ if (confirmation.customId === 'clearMessages_confirm') {
+ try {
+ const messages = await (channel as TextChannel).bulkDelete(amount, true);
+ const replyEmbed = makeEmbed({
+ title: 'Messages Cleared',
+ description: `Successfully cleared **${messages.size}** message${amount > 1 ? 's' : ''}.`,
+ color: Colors.Green,
+ timestamp: new Date(),
+ });
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed] });
- } catch (e) {
- Logger.error('An error occurred while trying to send the mod log:', e);
- }
- setTimeout(async () => {
- try {
- return interaction.deleteReply();
- } catch (error) {
- Logger.error('Failed to delete the reply message:', error);
- return interaction.editReply({ content: 'Failed to delete the reply message.' });
- }
- }, 5000);
- return interaction.editReply({ content: '', embeds: [replyEmbed], components: [] });
- } catch (error) {
- Logger.error('Error clearing messages:', error);
- return interaction.editReply({ content: 'There was an error trying to clear messages in this channel. The error has been logged.' });
- }
- } else {
- const canceledEmbed = makeEmbed({
- title: 'Interaction canceled.',
- color: Colors.Yellow,
- });
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const modLogEmbed = makeEmbed({
+ title: '🧹 Messages Cleared',
+ description: 'Messages have been cleared.',
+ color: Colors.Green,
+ fields: [
+ { name: 'Moderator', value: `<@${user.id}>`, inline: true },
+ { name: 'Channel', value: `<#${channel.id}>`, inline: true },
+ { name: 'Amount', value: `${messages.size}`, inline: true },
+ ],
+ footer: { text: `Moderator ID: ${user.id}`, iconURL: user.displayAvatarURL() },
+ timestamp: new Date(),
+ });
- return interaction.editReply({ embeds: [canceledEmbed], components: [] });
+ try {
+ await modLogsChannel.send({ embeds: [modLogEmbed] });
+ } catch (e) {
+ Logger.error('An error occurred while trying to send the mod log:', e);
}
- } catch (e) {
- return interaction.editReply({ content: 'The command timed out.', components: [] });
+ setTimeout(() => {
+ try {
+ void interaction.deleteReply();
+ } catch (error) {
+ Logger.error('Failed to delete the reply message:', error);
+ void interaction.editReply({ content: 'Failed to delete the reply message.' });
+ }
+ }, 5000);
+ return interaction.editReply({ content: '', embeds: [replyEmbed], components: [] });
+ } catch (error) {
+ Logger.error('Error clearing messages:', error);
+ return interaction.editReply({
+ content: 'There was an error trying to clear messages in this channel. The error has been logged.',
+ });
+ }
+ } else {
+ const canceledEmbed = makeEmbed({
+ title: 'Interaction canceled.',
+ color: Colors.Yellow,
+ });
+
+ return interaction.editReply({ embeds: [canceledEmbed], components: [] });
}
+ } catch {
+ return interaction.editReply({ content: 'The command timed out.', components: [] });
+ }
});
diff --git a/src/commands/moderation/commandTable.ts b/src/commands/moderation/commandTable.ts
index 8c98eb4c..26eb71da 100644
--- a/src/commands/moderation/commandTable.ts
+++ b/src/commands/moderation/commandTable.ts
@@ -3,115 +3,119 @@ import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { slashCommand, slashCommandStructure, Logger, constantsConfig } from '../../lib';
const data = slashCommandStructure({
- name: 'generate-command-table',
- description: 'Generates the command table.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin, moderator bot developer and docs team roles
- dm_permission: false,
+ name: 'generate-command-table',
+ description: 'Generates the command table.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin, moderator bot developer and docs team roles
+ dm_permission: false,
});
export default slashCommand(data, async ({ interaction }: { interaction: CommandInteraction }) => {
- try {
- // Fetch all commands from the API based on the environment
- let commands;
-
- if (process.env.NODE_ENV === 'production') {
- commands = await interaction.client.application?.commands.fetch();
- } else {
- commands = await interaction.guild?.commands.fetch();
- }
-
- // Check if the commands were fetched successfully
- if (!commands) {
- return interaction.reply({
- content: 'An error occurred while fetching commands.',
- ephemeral: true,
- });
- }
-
- // Convert the iterable of commands into an array
- const commandArray = Array.from(commands.values());
-
- // Sort the commands alphabetically by name
- const sortedCommands = commandArray.sort((a, b) => a.name.localeCompare(b.name));
-
- // Build the Markdown table
- let table = '## Bot Commands\n\n| Command | Description | Subcommand and Groups |\n| --- | --- | --- |\n';
-
- for (const command of sortedCommands) {
- // eslint-disable-next-line prefer-const
- let { name, description, type } = command;
-
- const subcommandList = command.options?.filter((option) => option.type === ApplicationCommandOptionType.Subcommand || option.type === ApplicationCommandOptionType.SubcommandGroup);
-
- let subcommandDescription = '';
-
- if (subcommandList && subcommandList.length > 0) {
- subcommandDescription = subcommandList
- .map((subcommand) => {
- if (subcommand.type === ApplicationCommandOptionType.Subcommand) {
- return subcommand.name;
- }
- if (subcommand.type === ApplicationCommandOptionType.SubcommandGroup) {
- const groupSubcommands = subcommand.options?.filter((sub) => sub.type === ApplicationCommandOptionType.Subcommand);
- if (groupSubcommands && groupSubcommands.length > 0) {
- return `${subcommand.name} [${groupSubcommands
- .map((sub) => sub.name)
- .join(', ')}]`;
- }
- return `${subcommand.name} [None]`;
- }
- return '';
- })
- .join(', ');
- }
+ try {
+ // Fetch all commands from the API based on the environment
+ let commands;
+
+ if (process.env.NODE_ENV === 'production') {
+ commands = await interaction.client.application?.commands.fetch();
+ } else {
+ commands = await interaction.guild?.commands.fetch();
+ }
+
+ // Check if the commands were fetched successfully
+ if (!commands) {
+ return interaction.reply({
+ content: 'An error occurred while fetching commands.',
+ ephemeral: true,
+ });
+ }
+
+ // Convert the iterable of commands into an array
+ const commandArray = Array.from(commands.values());
+
+ // Sort the commands alphabetically by name
+ const sortedCommands = commandArray.sort((a, b) => a.name.localeCompare(b.name));
+
+ // Build the Markdown table
+ let table = '## Bot Commands\n\n| Command | Description | Subcommand and Groups |\n| --- | --- | --- |\n';
- // Denote context-specific commands in the description
- if (type === ApplicationCommandType.User || type === ApplicationCommandType.Message) {
- description += `(Context Command - ${type === ApplicationCommandType.User ? 'User' : 'Message'})`;
+ for (const command of sortedCommands) {
+ // eslint-disable-next-line prefer-const
+ let { name, description, type } = command;
+
+ const subcommandList = command.options?.filter(
+ (option) =>
+ option.type === ApplicationCommandOptionType.Subcommand ||
+ option.type === ApplicationCommandOptionType.SubcommandGroup,
+ );
+
+ let subcommandDescription = '';
+
+ if (subcommandList && subcommandList.length > 0) {
+ subcommandDescription = subcommandList
+ .map((subcommand) => {
+ if (subcommand.type === ApplicationCommandOptionType.Subcommand) {
+ return subcommand.name;
+ }
+ if (subcommand.type === ApplicationCommandOptionType.SubcommandGroup) {
+ const groupSubcommands = subcommand.options?.filter(
+ (sub) => sub.type === ApplicationCommandOptionType.Subcommand,
+ );
+ if (groupSubcommands && groupSubcommands.length > 0) {
+ return `${subcommand.name} [${groupSubcommands.map((sub) => sub.name).join(', ')}]`;
+ }
+ return `${subcommand.name} [None]`;
}
+ return '';
+ })
+ .join(', ');
+ }
+
+ // Denote context-specific commands in the description
+ if (type === ApplicationCommandType.User || type === ApplicationCommandType.Message) {
+ description += `(Context Command - ${type === ApplicationCommandType.User ? 'User' : 'Message'})`;
+ }
+
+ // Append subcommands to the Subcommands column
+ table += `| ${name} | ${description} | ${subcommandDescription} |\n`;
+ }
+
+ // Upload the file to Cloudflare R2
+ const uploadParams = {
+ Bucket: process.env.CLOUDFLARE_BUCKET_NAME,
+ Key: 'utils/commands_table.md',
+ Body: table,
+ };
- // Append subcommands to the Subcommands column
- table += `| ${name} | ${description} | ${subcommandDescription} |\n`;
- }
-
- // Upload the file to Cloudflare R2
- const uploadParams = {
- Bucket: process.env.CLOUDFLARE_BUCKET_NAME,
- Key: 'utils/commands_table.md',
- Body: table,
- };
-
- try {
- const S3 = new S3Client({
- region: 'auto',
- endpoint: `https://${process.env.CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com`,
- credentials: {
- accessKeyId: process.env.CLOUDFLARE_ACCESS_KEY_ID!,
- secretAccessKey: process.env.CLOUDFLARE_SECRET_ACCESS_KEY!,
- },
- });
-
- const commandTableUpload = new PutObjectCommand(uploadParams);
- await S3.send(commandTableUpload);
- Logger.info('Successfully uploaded commands table to Cloudflare R2.');
- } catch (error) {
- Logger.error(error);
- return interaction.reply({
- content: 'An error occurred while uploading to Cloudflare R2.',
- ephemeral: true,
- });
- }
-
- return interaction.reply({
- content: 'Markdown table has been saved and uploaded to Cloudflare R2.',
- ephemeral: true,
- });
+ try {
+ const S3 = new S3Client({
+ region: 'auto',
+ endpoint: `https://${process.env.CLOUDFLARE_ACCOUNT_ID}.r2.cloudflarestorage.com`,
+ credentials: {
+ accessKeyId: process.env.CLOUDFLARE_ACCESS_KEY_ID!,
+ secretAccessKey: process.env.CLOUDFLARE_SECRET_ACCESS_KEY!,
+ },
+ });
+
+ const commandTableUpload = new PutObjectCommand(uploadParams);
+ await S3.send(commandTableUpload);
+ Logger.info('Successfully uploaded commands table to Cloudflare R2.');
} catch (error) {
- Logger.error(error);
- return interaction.reply({
- content: 'An error occurred while generating the Markdown file.',
- ephemeral: true,
- });
+ Logger.error(error);
+ return interaction.reply({
+ content: 'An error occurred while uploading to Cloudflare R2.',
+ ephemeral: true,
+ });
}
+
+ return interaction.reply({
+ content: 'Markdown table has been saved and uploaded to Cloudflare R2.',
+ ephemeral: true,
+ });
+ } catch (error) {
+ Logger.error(error);
+ return interaction.reply({
+ content: 'An error occurred while generating the Markdown file.',
+ ephemeral: true,
+ });
+ }
});
diff --git a/src/commands/moderation/deployCommands.ts b/src/commands/moderation/deployCommands.ts
index 45da2ba4..2ccf3f39 100644
--- a/src/commands/moderation/deployCommands.ts
+++ b/src/commands/moderation/deployCommands.ts
@@ -6,57 +6,58 @@ import contextArray from '../context/index';
import { client } from '../../client';
const data = slashCommandStructure({
- name: 'deploy-commands',
- description: 'Deploy commands to the server or globally.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin, moderator and bot developer roles
- dm_permission: false,
+ name: 'deploy-commands',
+ description: 'Deploy commands to the server or globally.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin, moderator and bot developer roles
+ dm_permission: false,
});
export default slashCommand(data, async ({ interaction }) => {
- if (interaction.guild) {
- try {
- await deployCommands(commandArray, contextArray)
- .then(async (user) => {
- const bot = `<@${user.id}>`;
+ if (interaction.guild) {
+ try {
+ await deployCommands(commandArray, contextArray).then(async (user) => {
+ const bot = `<@${user.id}>`;
- const guildID = constantsConfig.guildId;
- if (!guildID) {
- await interaction.reply('guildId configuration constant is not defined.');
- return;
- }
+ const guildID = constantsConfig.guildId;
+ if (!guildID) {
+ await interaction.reply('guildId configuration constant is not defined.');
+ return;
+ }
- const guildName = client.guilds.cache.get(guildID);
+ const guildName = client.guilds.cache.get(guildID);
- let response;
- //If the bot is deployed to a guild and can resolve the name, use the guild name in the response
- if (guildName) {
- response = process.env.NODE_ENV === 'production'
- ? `Deployed ${commandArray.length} commands and ${contextArray.length} contexts globally as ${bot}!`
- : `Deployed ${commandArray.length} commands and ${contextArray.length} contexts to \`${guildName}\` as ${bot}!`;
- } else {
- //If the bot can't gather the guild name, use the ID in the response
- response = process.env.NODE_ENV === 'production'
- ? `Deployed ${commandArray.length} commands and ${contextArray.length} contexts globally as ${bot}!`
- : `Deployed ${commandArray.length} commands and ${contextArray.length} contexts to \`<@${guildID}>\` as ${bot}!`;
- }
- Logger.info(response);
- await interaction.reply({
- content: response,
- ephemeral: true,
- });
- });
- } catch (error) {
- await interaction.reply({
- content: 'Failed to deploy commands!',
- ephemeral: true,
- });
- Logger.error(error);
+ let response;
+ //If the bot is deployed to a guild and can resolve the name, use the guild name in the response
+ if (guildName) {
+ response =
+ process.env.NODE_ENV === 'production'
+ ? `Deployed ${commandArray.length} commands and ${contextArray.length} contexts globally as ${bot}!`
+ : `Deployed ${commandArray.length} commands and ${contextArray.length} contexts to \`${guildName.name}\` as ${bot}!`;
+ } else {
+ //If the bot can't gather the guild name, use the ID in the response
+ response =
+ process.env.NODE_ENV === 'production'
+ ? `Deployed ${commandArray.length} commands and ${contextArray.length} contexts globally as ${bot}!`
+ : `Deployed ${commandArray.length} commands and ${contextArray.length} contexts to \`<@${guildID}>\` as ${bot}!`;
}
- } else {
+ Logger.info(response);
await interaction.reply({
- content: 'This command can only be used in a guild!',
- ephemeral: true,
+ content: response,
+ ephemeral: true,
});
+ });
+ } catch (error) {
+ await interaction.reply({
+ content: 'Failed to deploy commands!',
+ ephemeral: true,
+ });
+ Logger.error(error);
}
+ } else {
+ await interaction.reply({
+ content: 'This command can only be used in a guild!',
+ ephemeral: true,
+ });
+ }
});
diff --git a/src/commands/moderation/faq/faq.ts b/src/commands/moderation/faq/faq.ts
index cccc208f..454cbfaf 100644
--- a/src/commands/moderation/faq/faq.ts
+++ b/src/commands/moderation/faq/faq.ts
@@ -6,77 +6,77 @@ import { handleListFaq } from './functions/listFaq';
import { handlePrintAllFAQ } from './functions/faqPrintAll';
const data = slashCommandStructure({
- name: 'faq',
- description: 'Command to manage FAQ messages.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator
- dm_permission: false,
- options: [
+ name: 'faq',
+ description: 'Command to manage FAQ messages.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator
+ dm_permission: false,
+ options: [
+ {
+ name: 'add',
+ description: 'Adds an FAQ.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ {
+ name: 'remove',
+ description: 'Removes an FAQ.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
{
- name: 'add',
- description: 'Adds an FAQ.',
- type: ApplicationCommandOptionType.Subcommand,
+ name: 'faq_id',
+ description: 'ID of FAQ to remove.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
},
- {
- name: 'remove',
- description: 'Removes an FAQ.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'faq_id',
- description: 'ID of FAQ to remove.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- ],
- },
- {
- name: 'list',
- description: 'Lists all FAQs.',
- type: ApplicationCommandOptionType.Subcommand,
- },
- {
- name: 'print-all',
- description: 'Prints all FAQs.',
- type: ApplicationCommandOptionType.Subcommand,
- },
- ],
+ ],
+ },
+ {
+ name: 'list',
+ description: 'Lists all FAQs.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ {
+ name: 'print-all',
+ description: 'Prints all FAQs.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ ],
});
const noConnEmbed = makeEmbed({
- title: 'FAQ - No Connection',
- description: 'Could not connect to the database',
- color: Colors.Red,
+ title: 'FAQ - No Connection',
+ description: 'Could not connect to the database',
+ color: Colors.Red,
});
export default slashCommand(data, async ({ interaction }) => {
- const conn = getConn();
+ const conn = getConn();
- if (!conn) {
- await interaction.reply({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ if (!conn) {
+ await interaction.reply({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const subcommandName = interaction.options.getSubcommand();
+ const subcommandName = interaction.options.getSubcommand();
- const faqID = interaction.options.getString('faq_id')!;
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const faqID = interaction.options.getString('faq_id')!;
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- switch (subcommandName) {
+ switch (subcommandName) {
case 'add':
- await handleAddFaq(interaction, modLogsChannel);
- break;
+ await handleAddFaq(interaction, modLogsChannel);
+ break;
case 'remove':
- await handleRemoveFaq(interaction, faqID, modLogsChannel);
- break;
+ await handleRemoveFaq(interaction, faqID, modLogsChannel);
+ break;
case 'list':
- await handleListFaq(interaction);
- break;
+ await handleListFaq(interaction);
+ break;
case 'print-all':
- await handlePrintAllFAQ(interaction);
- break;
+ await handlePrintAllFAQ(interaction);
+ break;
default:
- await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
- }
+ await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
+ }
});
diff --git a/src/commands/moderation/faq/functions/addFaq.ts b/src/commands/moderation/faq/functions/addFaq.ts
index 72fa12ec..b700d0a3 100644
--- a/src/commands/moderation/faq/functions/addFaq.ts
+++ b/src/commands/moderation/faq/functions/addFaq.ts
@@ -1,133 +1,139 @@
import {
- ActionRowBuilder,
- ChatInputCommandInteraction,
- Colors,
- ModalBuilder,
- TextChannel,
- TextInputBuilder,
- TextInputStyle,
- User,
+ ActionRowBuilder,
+ ChatInputCommandInteraction,
+ Colors,
+ ModalBuilder,
+ ModalSubmitInteraction,
+ TextChannel,
+ TextInputBuilder,
+ TextInputStyle,
+ User,
} from 'discord.js';
import { Logger, makeEmbed, FAQ } from '../../../../lib';
-const faqAddedEmbed = (discordUser: User, question: string, answer: string) => makeEmbed({
+const faqAddedEmbed = (discordUser: User, question: string, answer: string) =>
+ makeEmbed({
author: {
- name: `[FAQ Added] ${discordUser.tag}`,
- iconURL: discordUser.displayAvatarURL(),
+ name: `[FAQ Added] ${discordUser.tag}`,
+ iconURL: discordUser.displayAvatarURL(),
},
fields: [
- {
- inline: false,
- name: 'Question',
- value: question,
- },
- {
- inline: false,
- name: 'Answer',
- value: answer,
- },
+ {
+ inline: false,
+ name: 'Question',
+ value: question,
+ },
+ {
+ inline: false,
+ name: 'Answer',
+ value: answer,
+ },
],
color: Colors.Green,
-});
+ });
export async function handleAddFaq(interaction: ChatInputCommandInteraction<'cached'>, modLogsChannel: TextChannel) {
- const modal = new ModalBuilder({
- customId: 'faqAddModal',
- title: 'Add an FAQ entry',
+ const modal = new ModalBuilder({
+ customId: 'faqAddModal',
+ title: 'Add an FAQ entry',
+ });
+
+ const faqTitleInput = new TextInputBuilder({
+ customId: 'faqTitleInput',
+ label: 'Title',
+ placeholder: 'Please enter the title of the FAQ.',
+ style: TextInputStyle.Short,
+ maxLength: 500,
+ required: true,
+ });
+
+ const faqAnswerInput = new TextInputBuilder({
+ customId: 'faqAnswerInput',
+ label: 'Answer',
+ placeholder: 'If you wish to mention a role or channel use <@&*ID*> or <#*ID*> respectively.',
+ style: TextInputStyle.Paragraph,
+ maxLength: 1000,
+ required: true,
+ });
+
+ const titleActionRow = new ActionRowBuilder().addComponents(faqTitleInput);
+ const answerActionRow = new ActionRowBuilder().addComponents(faqAnswerInput);
+
+ modal.addComponents(titleActionRow, answerActionRow);
+
+ await interaction.showModal(modal);
+
+ //Modal sent
+
+ const filter = (interaction: ModalSubmitInteraction) =>
+ !!interaction.user.id && interaction.customId === 'faqAddModal';
+
+ try {
+ //Await a modal response
+ const modalSubmitInteraction = await interaction.awaitModalSubmit({
+ filter,
+ time: 120000,
});
- const faqTitleInput = new TextInputBuilder(
- {
- customId: 'faqTitleInput',
- label: 'Title',
- placeholder: 'Please enter the title of the FAQ.',
- style: TextInputStyle.Short,
- maxLength: 500,
- required: true,
- },
- );
-
- const faqAnswerInput = new TextInputBuilder(
- {
- customId: 'faqAnswerInput',
- label: 'Answer',
- placeholder: 'If you wish to mention a role or channel use <@&*ID*> or <#*ID*> respectively.',
- style: TextInputStyle.Paragraph,
- maxLength: 1000,
- required: true,
- },
- );
-
- const titleActionRow = new ActionRowBuilder().addComponents(faqTitleInput);
- const answerActionRow = new ActionRowBuilder().addComponents(faqAnswerInput);
-
- modal.addComponents(titleActionRow, answerActionRow);
-
- await interaction.showModal(modal);
-
- //Modal sent
-
- const filter = (interaction: {
- customId: string;
- user: { id: any; };
- }) => interaction.customId === 'faqAddModal' && interaction.user.id;
+ //Respond to the user once they have submitted the modal
+ await modalSubmitInteraction.reply({
+ content: 'FAQ Modal Submitted! I will try and add the FAQ to the database.',
+ ephemeral: true,
+ });
+
+ const faqTitle = modalSubmitInteraction.fields.getTextInputValue('faqTitleInput');
+ const faqAnswer = modalSubmitInteraction.fields.getTextInputValue('faqAnswerInput');
+
+ const discordUser = interaction.user;
+ const currentDate = new Date();
+
+ let faqData = await FAQ.findOne({ faqTitle });
+
+ if (!faqData) {
+ faqData = new FAQ({
+ faqTitle: faqTitle,
+ faqAnswer: faqAnswer,
+ moderatorID: discordUser.id,
+ dateSet: currentDate,
+ });
+ } else {
+ await interaction.followUp({
+ content: 'FAQ with this title already exists. Please choose another title',
+ ephemeral: true,
+ });
+ return;
+ }
try {
- //Await a modal response
- const modalSubmitInteraction = await interaction.awaitModalSubmit({
- filter,
- time: 120000,
- });
-
- //Respond to the user once they have submitted the modal
- await modalSubmitInteraction.reply({
- content: 'FAQ Modal Submitted! I will try and add the FAQ to the database.',
- ephemeral: true,
- });
-
- const faqTitle = modalSubmitInteraction.fields.getTextInputValue('faqTitleInput');
- const faqAnswer = modalSubmitInteraction.fields.getTextInputValue('faqAnswerInput');
-
- const discordUser = interaction.user;
- const currentDate = new Date();
-
- let faqData = await FAQ.findOne({ faqTitle });
-
- if (!faqData) {
- faqData = new FAQ({
- faqTitle: faqTitle!,
- faqAnswer: faqAnswer!,
- moderatorID: discordUser.id,
- dateSet: currentDate,
- });
- } else {
- await interaction.followUp({ content: 'FAQ with this title already exists. Please choose another title', ephemeral: true });
- return;
- }
-
- try {
- await faqData.save();
- } catch (error) {
- Logger.error(error);
- await interaction.followUp({ content: 'Could not add FAQ, error has been logged, please notify the bot team.', ephemeral: true });
- return;
- }
-
- try {
- await modLogsChannel.send({ embeds: [faqAddedEmbed(discordUser, faqTitle, faqAnswer)] });
- } catch (error) {
- Logger.error(error);
- await interaction.followUp({ content: 'FAQ added successfully, but could not send mod log, error has been logged, please notify the bot team.', ephemeral: true });
- return;
- }
-
- await interaction.followUp({ content: 'FAQ added successfully.', ephemeral: true });
+ await faqData.save();
} catch (error) {
- //Handle the error if the user does not respond in time
- Logger.error(error);
- await interaction.followUp({
- content: 'You did not provide a response in time. Please try again.',
- ephemeral: true,
- });
+ Logger.error(error);
+ await interaction.followUp({
+ content: 'Could not add FAQ, error has been logged, please notify the bot team.',
+ ephemeral: true,
+ });
+ return;
}
+
+ try {
+ await modLogsChannel.send({ embeds: [faqAddedEmbed(discordUser, faqTitle, faqAnswer)] });
+ } catch (error) {
+ Logger.error(error);
+ await interaction.followUp({
+ content:
+ 'FAQ added successfully, but could not send mod log, error has been logged, please notify the bot team.',
+ ephemeral: true,
+ });
+ return;
+ }
+
+ await interaction.followUp({ content: 'FAQ added successfully.', ephemeral: true });
+ } catch (error) {
+ //Handle the error if the user does not respond in time
+ Logger.error(error);
+ await interaction.followUp({
+ content: 'You did not provide a response in time. Please try again.',
+ ephemeral: true,
+ });
+ }
}
diff --git a/src/commands/moderation/faq/functions/faqPrintAll.ts b/src/commands/moderation/faq/functions/faqPrintAll.ts
index e9f573ea..23a07ea8 100644
--- a/src/commands/moderation/faq/functions/faqPrintAll.ts
+++ b/src/commands/moderation/faq/functions/faqPrintAll.ts
@@ -4,69 +4,71 @@ import { constantsConfig, imageBaseUrl, Logger, makeEmbed, FAQ } from '../../../
const FLIGHT_DECK_IMAGE_URL = `${imageBaseUrl}/moderation/faq.png`;
const linksEmbed = makeEmbed({
- title: 'Useful Links',
- fields: [
- {
- name: '**Docs FAQ**',
- value: 'https://docs.flybywiresim.com/fbw-a32nx/faq/',
- },
- {
- name: '**Beginners Guide**',
- value: 'https://docs.flybywiresim.com/pilots-corner/beginner-guide/overview/',
- },
- {
- name: '**Flight School**',
- value: `<#${constantsConfig.channels.FLIGHT_SCHOOL}>`,
- },
- {
- name: '**Support**',
- value: `<#${constantsConfig.channels.A32NX_SUPPORT}>`,
- },
- ],
+ title: 'Useful Links',
+ fields: [
+ {
+ name: '**Docs FAQ**',
+ value: 'https://docs.flybywiresim.com/fbw-a32nx/faq/',
+ },
+ {
+ name: '**Beginners Guide**',
+ value: 'https://docs.flybywiresim.com/pilots-corner/beginner-guide/overview/',
+ },
+ {
+ name: '**Flight School**',
+ value: `<#${constantsConfig.channels.FLIGHT_SCHOOL}>`,
+ },
+ {
+ name: '**Support**',
+ value: `<#${constantsConfig.channels.A32NX_SUPPORT}>`,
+ },
+ ],
});
export async function handlePrintAllFAQ(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- try {
- // Fetch all FAQs from the database
- const faqs = await FAQ.find();
+ try {
+ // Fetch all FAQs from the database
+ const faqs = await FAQ.find();
- if (faqs.length === 0) {
- return interaction.followUp('No FAQs found.');
- } if (interaction.channel) {
- await interaction.channel.send({ files: [FLIGHT_DECK_IMAGE_URL] });
+ if (faqs.length === 0) {
+ return interaction.followUp('No FAQs found.');
+ }
+ if (interaction.channel) {
+ await interaction.channel.send({ files: [FLIGHT_DECK_IMAGE_URL] });
- // Divide the FAQs into sets of 5
- const faqSets = [];
- for (let i = 0; i < faqs.length; i += 5) {
- const faqSet = faqs.slice(i, i + 5);
- faqSets.push(faqSet);
- }
+ // Divide the FAQs into sets of 5
+ const faqSets = [];
+ for (let i = 0; i < faqs.length; i += 5) {
+ const faqSet = faqs.slice(i, i + 5);
+ faqSets.push(faqSet);
+ }
- // Send an embed for each set of FAQs
- for (let i = 0; i < faqSets.length; i++) {
- const faqSet = faqSets[i];
- const faqEmbed = makeEmbed({
- title: `Frequently Asked Questions (${i + 1}/${faqSets.length})`,
- fields: faqSet.map((faq) => ({
- name: `**${faq.faqTitle}**`,
- value: `${faq.faqAnswer}`,
- })),
- });
+ // Send an embed for each set of FAQs
+ for (let i = 0; i < faqSets.length; i++) {
+ const faqSet = faqSets[i];
+ const faqEmbed = makeEmbed({
+ title: `Frequently Asked Questions (${i + 1}/${faqSets.length})`,
+ fields: faqSet.map((faq) => ({
+ name: `**${faq.faqTitle}**`,
+ value: `${faq.faqAnswer}`,
+ })),
+ });
- // eslint-disable-next-line no-await-in-loop
- await interaction.channel.send({ embeds: [faqEmbed] });
- }
+ // This is intended to be sequential
+ // eslint-disable-next-line no-await-in-loop
+ await interaction.channel.send({ embeds: [faqEmbed] });
+ }
- await interaction.channel.send({ embeds: [linksEmbed] });
- } else {
- return interaction.followUp({ content: 'FAQs can only be printed in a text channel.', ephemeral: true });
- }
- } catch (error) {
- Logger.error('Error fetching FAQs:', error);
- return interaction.followUp('An error occurred while fetching FAQs.');
+ await interaction.channel.send({ embeds: [linksEmbed] });
+ } else {
+ return interaction.followUp({ content: 'FAQs can only be printed in a text channel.', ephemeral: true });
}
+ } catch (error) {
+ Logger.error('Error fetching FAQs:', error);
+ return interaction.followUp('An error occurred while fetching FAQs.');
+ }
- return interaction.followUp({ content: 'FAQs printed successfully.', ephemeral: true });
+ return interaction.followUp({ content: 'FAQs printed successfully.', ephemeral: true });
}
diff --git a/src/commands/moderation/faq/functions/listFaq.ts b/src/commands/moderation/faq/functions/listFaq.ts
index 965d87dd..17306f7e 100644
--- a/src/commands/moderation/faq/functions/listFaq.ts
+++ b/src/commands/moderation/faq/functions/listFaq.ts
@@ -2,75 +2,79 @@ import { ChatInputCommandInteraction } from 'discord.js';
import moment from 'moment/moment';
import { Logger, makeEmbed, FAQ, createPaginatedEmbedHandler } from '../../../../lib';
-const faqListEmbed = (faqFields: { name: string; value: string; }[], currentPage: number, totalPages: number) => makeEmbed({
+const faqListEmbed = (faqFields: { name: string; value: string }[], currentPage: number, totalPages: number) =>
+ makeEmbed({
title: `FAQ List (Page ${currentPage} of ${totalPages})`,
fields: faqFields,
-});
+ });
export async function handleListFaq(interaction: ChatInputCommandInteraction<'cached'>) {
- try {
- const faqs = await FAQ.find({});
+ try {
+ const faqs = await FAQ.find({});
- if (!faqs.length) {
- await interaction.reply({ content: 'No FAQs exist.', ephemeral: true });
- return;
- }
-
- const pageLimit = 5;
- const embeds = [];
- let currentPage = 1;
- let faqsAddedToPage = 0;
- const faqFields: { name: string; value: string; }[] = [];
+ if (!faqs.length) {
+ await interaction.reply({ content: 'No FAQs exist.', ephemeral: true });
+ return;
+ }
- const moderatorPromises = faqs.map((currentFaq) => interaction.client.users.fetch(currentFaq.moderatorID!)
- // Added for better readability
- // eslint-disable-next-line arrow-body-style
- .catch(() => {
- return new Promise((resolve) => {
- resolve(`I can't find the moderator, here is the stored ID: ${currentFaq.moderatorID}`);
- });
- }));
- const moderatorUsers = await Promise.all(moderatorPromises);
+ const pageLimit = 5;
+ const embeds = [];
+ let currentPage = 1;
+ let faqsAddedToPage = 0;
+ const faqFields: { name: string; value: string }[] = [];
- for (let i = 0; i < faqs.length; i++) {
- const formattedDate = moment(faqs[i].dateSet).utcOffset(0).format();
+ const moderatorUsers = await Promise.all(
+ faqs.map(async (currentFaq) => {
+ try {
+ return await interaction.client.users.fetch(currentFaq.moderatorID!);
+ } catch {
+ return `I can't find the moderator, here is the stored ID: ${currentFaq.moderatorID}`;
+ }
+ }),
+ );
- faqFields.push(
- {
- name: `**Title:** ${faqs[i].faqTitle}`,
- value:
- `**Answer:** ${faqs[i].faqAnswer}\n`
- + `**Moderator:** ${moderatorUsers[i]}\n`
- + `**Date Set:** ${formattedDate}\n`
- + `**FAQ ID:** ${faqs[i].id}\n`,
- },
- {
- name: '',
- value: '----------------------------------------',
- },
- );
+ for (let i = 0; i < faqs.length; i++) {
+ const formattedDate = moment(faqs[i].dateSet).utcOffset(0).format();
- faqsAddedToPage++;
- if (faqsAddedToPage >= pageLimit) {
- embeds.push(faqListEmbed(faqFields, currentPage, Math.ceil(faqs.length / pageLimit)));
- faqsAddedToPage = 0;
- faqFields.length = 0;
- currentPage++;
- }
- }
+ faqFields.push(
+ {
+ name: `**Title:** ${faqs[i].faqTitle}`,
+ value:
+ `**Answer:** ${faqs[i].faqAnswer}\n` +
+ `**Moderator:** ${moderatorUsers[i].toString()}\n` +
+ `**Date Set:** ${formattedDate}\n` +
+ `**FAQ ID:** ${faqs[i].id}\n`,
+ },
+ {
+ name: '',
+ value: '----------------------------------------',
+ },
+ );
- if (faqFields.length > 0) {
- embeds.push(faqListEmbed(faqFields, currentPage, Math.ceil(faqs.length / pageLimit)));
- }
+ faqsAddedToPage++;
+ if (faqsAddedToPage >= pageLimit) {
+ embeds.push(faqListEmbed(faqFields, currentPage, Math.ceil(faqs.length / pageLimit)));
+ faqsAddedToPage = 0;
+ faqFields.length = 0;
+ currentPage++;
+ }
+ }
- if (embeds.length === 0) {
- await interaction.reply({ content: 'No FAQs exist.', ephemeral: true });
- return;
- }
+ if (faqFields.length > 0) {
+ embeds.push(faqListEmbed(faqFields, currentPage, Math.ceil(faqs.length / pageLimit)));
+ }
- await createPaginatedEmbedHandler(interaction, embeds);
- } catch (error) {
- Logger.error(error);
- await interaction.reply({ content: 'Could not list FAQs, error has been logged, please notify the bot team.', ephemeral: true });
+ if (embeds.length === 0) {
+ await interaction.reply({ content: 'No FAQs exist.', ephemeral: true });
+ return;
}
+
+ await createPaginatedEmbedHandler(interaction, embeds);
+ } catch (error) {
+ Logger.error(error);
+ await interaction.reply({
+ content: 'Could not list FAQs, error has been logged, please notify the bot team.',
+ ephemeral: true,
+ });
+ }
}
diff --git a/src/commands/moderation/faq/functions/removeFaq.ts b/src/commands/moderation/faq/functions/removeFaq.ts
index 80fb2937..185ffd94 100644
--- a/src/commands/moderation/faq/functions/removeFaq.ts
+++ b/src/commands/moderation/faq/functions/removeFaq.ts
@@ -1,54 +1,66 @@
import { ChatInputCommandInteraction, Colors, TextChannel, User } from 'discord.js';
import { Logger, makeEmbed, FAQ } from '../../../../lib';
-const faqRemovedEmbed = (discordUser: User, faqQuestion: string, faqAnswer: string) => makeEmbed({
+const faqRemovedEmbed = (discordUser: User, faqQuestion: string, faqAnswer: string) =>
+ makeEmbed({
author: {
- name: `[FAQ Removed] ${discordUser.tag}`,
- iconURL: discordUser.displayAvatarURL(),
+ name: `[FAQ Removed] ${discordUser.tag}`,
+ iconURL: discordUser.displayAvatarURL(),
},
fields: [
- {
- inline: false,
- name: 'Question',
- value: faqQuestion,
- },
- {
- inline: false,
- name: 'Answer',
- value: faqAnswer,
- },
+ {
+ inline: false,
+ name: 'Question',
+ value: faqQuestion,
+ },
+ {
+ inline: false,
+ name: 'Answer',
+ value: faqAnswer,
+ },
],
color: Colors.Red,
-});
-
-export async function handleRemoveFaq(interaction: ChatInputCommandInteraction<'cached'>, faqID: string, modLogsChannel: TextChannel) {
- const discordUser = interaction.user;
-
- const faqEntry = await FAQ.findOne({ _id: faqID });
-
- if (!faqEntry) {
- await interaction.reply({ content: 'FAQ with this ID does not exist.', ephemeral: true });
- return;
- }
-
- const faqTitle = faqEntry.faqTitle || 'Unknown';
- const faqAnswer = faqEntry.faqAnswer || 'Unknown';
-
- try {
- await faqEntry.deleteOne();
- } catch (error) {
- Logger.error(error);
- await interaction.reply({ content: 'Could not remove FAQ, error has been logged, please notify the bot team.', ephemeral: true });
- return;
- }
-
- try {
- await modLogsChannel.send({ embeds: [faqRemovedEmbed(discordUser, faqTitle, faqAnswer)] });
- } catch (error) {
- Logger.error(error);
- await interaction.reply({ content: 'FAQ removed successfully, but could not send mod log, error has been logged, please notify the bot team.', ephemeral: true });
- return;
- }
-
- await interaction.reply({ content: 'FAQ removed successfully.', ephemeral: true });
+ });
+
+export async function handleRemoveFaq(
+ interaction: ChatInputCommandInteraction<'cached'>,
+ faqID: string,
+ modLogsChannel: TextChannel,
+) {
+ const discordUser = interaction.user;
+
+ const faqEntry = await FAQ.findOne({ _id: faqID });
+
+ if (!faqEntry) {
+ await interaction.reply({ content: 'FAQ with this ID does not exist.', ephemeral: true });
+ return;
+ }
+
+ const faqTitle = faqEntry.faqTitle || 'Unknown';
+ const faqAnswer = faqEntry.faqAnswer || 'Unknown';
+
+ try {
+ await faqEntry.deleteOne();
+ } catch (error) {
+ Logger.error(error);
+ await interaction.reply({
+ content: 'Could not remove FAQ, error has been logged, please notify the bot team.',
+ ephemeral: true,
+ });
+ return;
+ }
+
+ try {
+ await modLogsChannel.send({ embeds: [faqRemovedEmbed(discordUser, faqTitle, faqAnswer)] });
+ } catch (error) {
+ Logger.error(error);
+ await interaction.reply({
+ content:
+ 'FAQ removed successfully, but could not send mod log, error has been logged, please notify the bot team.',
+ ephemeral: true,
+ });
+ return;
+ }
+
+ await interaction.reply({ content: 'FAQ removed successfully.', ephemeral: true });
}
diff --git a/src/commands/moderation/infractions/functions/ban.ts b/src/commands/moderation/infractions/functions/ban.ts
index e141df53..59a388dc 100644
--- a/src/commands/moderation/infractions/functions/ban.ts
+++ b/src/commands/moderation/infractions/functions/ban.ts
@@ -4,187 +4,199 @@ import mongoose from 'mongoose';
import { constantsConfig, getConn, Infraction, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Ban - No Connection',
- description: 'Could not connect to the database. I will still try to ban the user.',
- color: Colors.Red,
+ title: 'Ban - No Connection',
+ description: 'Could not connect to the database. I will still try to ban the user.',
+ color: Colors.Red,
});
const moderatableFailEmbed = makeEmbed({
- color: Colors.Red,
- description: 'You can\'t ban a moderator!',
+ color: Colors.Red,
+ description: "You can't ban a moderator!",
});
-const failedBanEmbed = (discordUser: User) => makeEmbed({
+const failedBanEmbed = (discordUser: User) =>
+ makeEmbed({
title: 'Ban - Failed',
description: `Failed to Ban ${discordUser.toString()}`,
color: Colors.Red,
-});
+ });
-const DMEmbed = (moderator: User, banReason: string, guild: Guild) => makeEmbed({
+const DMEmbed = (moderator: User, banReason: string, guild: Guild) =>
+ makeEmbed({
title: `You have been banned from ${guild.name}`,
description: 'This ban is also logged against your record.',
fields: [
- {
- inline: true,
- name: 'Moderator',
- value: moderator.toString(),
- },
- {
- inline: false,
- name: 'Reason',
- value: banReason,
- },
- {
- inline: false,
- name: 'Appeal',
- value: `If you would like to appeal your ban, please fill out [this form.](${process.env.BAN_APPEAL_URL})`,
- },
+ {
+ inline: true,
+ name: 'Moderator',
+ value: moderator.toString(),
+ },
+ {
+ inline: false,
+ name: 'Reason',
+ value: banReason,
+ },
+ {
+ inline: false,
+ name: 'Appeal',
+ value: `If you would like to appeal your ban, please fill out [this form.](${process.env.BAN_APPEAL_URL})`,
+ },
],
-});
+ });
-const banEmbed = (discordUser: User) => makeEmbed({
+const banEmbed = (discordUser: User) =>
+ makeEmbed({
title: `${discordUser.tag} was banned successfully`,
color: Colors.Green,
-});
+ });
-const DMFailed = (discordUser: User) => makeEmbed({
+const DMFailed = (discordUser: User) =>
+ makeEmbed({
title: 'Ban - DM not sent',
description: `DM was not sent to ${discordUser.toString()}, they either have DMs closed or share no mutual servers with the bot.`,
color: Colors.Red,
-});
-
-const modLogEmbed = (moderator: User, discordUser: User, banReason: string, daysDeletedNumber: number, formattedDate: string) => makeEmbed({
+ });
+
+const modLogEmbed = (
+ moderator: User,
+ discordUser: User,
+ banReason: string,
+ daysDeletedNumber: number,
+ formattedDate: string,
+) =>
+ makeEmbed({
author: {
- name: `[BANNED] ${discordUser.tag}`,
- iconURL: discordUser.displayAvatarURL(),
+ name: `[BANNED] ${discordUser.tag}`,
+ iconURL: discordUser.displayAvatarURL(),
},
fields: [
- {
- name: 'User',
- value: discordUser.toString(),
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Reason',
- value: `\u200B${banReason}`,
- },
- {
- name: 'Days of messages deleted',
- value: daysDeletedNumber.toString(),
- },
- {
- name: 'Date',
- value: formattedDate,
- },
+ {
+ name: 'User',
+ value: discordUser.toString(),
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Reason',
+ value: `\u200B${banReason}`,
+ },
+ {
+ name: 'Days of messages deleted',
+ value: daysDeletedNumber.toString(),
+ },
+ {
+ name: 'Date',
+ value: formattedDate,
+ },
],
footer: { text: `User ID: ${discordUser.id}` },
color: Colors.Red,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Ban - No Mod Log',
- description: 'I can\'t find the mod logs channel. I will still try to ban the user. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Ban - No Mod Log',
+ description:
+ "I can't find the mod logs channel. I will still try to ban the user. Please check the channel still exists.",
+ color: Colors.Red,
});
const logFailed = makeEmbed({
- title: 'Ban - Failed to log',
- description: 'Failed to log the ban to the database.',
- color: Colors.Red,
+ title: 'Ban - Failed to log',
+ description: 'Failed to log the ban to the database.',
+ color: Colors.Red,
});
export async function handleBanInfraction(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
-
- const conn = getConn();
+ await interaction.deferReply({ ephemeral: true });
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- }
+ const conn = getConn();
- const userID = interaction.options.getUser('tag_or_id')!.id;
- const banReason = interaction.options.getString('reason')!;
- const daysDeletedNumber = interaction.options.getInteger('days_deleted') || 0;
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ }
- const discordUser = await interaction.guild.members.fetch(userID);
- const moderator = interaction.user;
- const currentDate = new Date();
- const formattedDate: string = moment(currentDate)
- .utcOffset(0)
- .format();
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const userID = interaction.options.getUser('tag_or_id')!.id;
+ const banReason = interaction.options.getString('reason')!;
+ const daysDeletedNumber = interaction.options.getInteger('days_deleted') || 0;
- //Check if the user is a moderator
+ const discordUser = await interaction.guild.members.fetch(userID);
+ const moderator = interaction.user;
+ const currentDate = new Date();
+ const formattedDate: string = moment(currentDate).utcOffset(0).format();
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- if (!discordUser.moderatable) {
- await interaction.followUp({ embeds: [moderatableFailEmbed], ephemeral: true });
- return;
- }
+ //Check if the user is a moderator
- //Check if the mod logs channel exists
+ if (!discordUser.moderatable) {
+ await interaction.followUp({ embeds: [moderatableFailEmbed], ephemeral: true });
+ return;
+ }
- if (!modLogsChannel) {
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
- //DM the user
+ if (!modLogsChannel) {
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- try {
- await discordUser.send({ embeds: [DMEmbed(moderator, banReason, interaction.guild)] });
- } catch {
- if (modLogsChannel) {
- await interaction.followUp({ embeds: [DMFailed(discordUser.user)], ephemeral: true });
- }
- }
+ //DM the user
- //Ban the user
-
- try {
- await interaction.guild.members.ban(discordUser, { deleteMessageDays: daysDeletedNumber, reason: banReason });
- if (modLogsChannel) {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, discordUser.user, banReason, daysDeletedNumber, formattedDate)] });
- }
- await interaction.followUp({ embeds: [banEmbed(discordUser.user)], ephemeral: true });
- } catch (error) {
- Logger.error(error);
- await interaction.followUp({ embeds: [failedBanEmbed(discordUser.user)], ephemeral: true });
+ try {
+ await discordUser.send({ embeds: [DMEmbed(moderator, banReason, interaction.guild)] });
+ } catch {
+ if (modLogsChannel) {
+ await interaction.followUp({ embeds: [DMFailed(discordUser.user)], ephemeral: true });
}
+ }
- //Log to the DB
- Logger.info('Starting Infraction process');
-
- const newInfraction = {
- infractionType: 'Ban',
- moderatorID: moderator.id,
- reason: banReason,
- date: currentDate,
- infractionID: new mongoose.Types.ObjectId(),
- };
-
- let userData = await Infraction.findOne({ userID });
+ //Ban the user
- Logger.info(userData);
-
- if (!userData) {
- userData = new Infraction({
- userID,
- infractions: [newInfraction],
- });
- Logger.info(userData);
- Logger.info('New user data created');
- } else {
- userData.infractions.push(newInfraction);
- Logger.info('User data updated');
- }
-
- try {
- await userData.save();
- Logger.info('Infraction process complete');
- } catch (error) {
- await interaction.followUp({ embeds: [logFailed], ephemeral: true });
- Logger.error(error);
+ try {
+ await interaction.guild.members.ban(discordUser, { deleteMessageDays: daysDeletedNumber, reason: banReason });
+ if (modLogsChannel) {
+ await modLogsChannel.send({
+ embeds: [modLogEmbed(moderator, discordUser.user, banReason, daysDeletedNumber, formattedDate)],
+ });
}
+ await interaction.followUp({ embeds: [banEmbed(discordUser.user)], ephemeral: true });
+ } catch (error) {
+ Logger.error(error);
+ await interaction.followUp({ embeds: [failedBanEmbed(discordUser.user)], ephemeral: true });
+ }
+
+ //Log to the DB
+ Logger.info('Starting Infraction process');
+
+ const newInfraction = {
+ infractionType: 'Ban',
+ moderatorID: moderator.id,
+ reason: banReason,
+ date: currentDate,
+ infractionID: new mongoose.Types.ObjectId(),
+ };
+
+ let userData = await Infraction.findOne({ userID });
+
+ Logger.info(userData);
+
+ if (!userData) {
+ userData = new Infraction({
+ userID,
+ infractions: [newInfraction],
+ });
+ Logger.info(userData);
+ Logger.info('New user data created');
+ } else {
+ userData.infractions.push(newInfraction);
+ Logger.info('User data updated');
+ }
+
+ try {
+ await userData.save();
+ Logger.info('Infraction process complete');
+ } catch (error) {
+ await interaction.followUp({ embeds: [logFailed], ephemeral: true });
+ Logger.error(error);
+ }
}
diff --git a/src/commands/moderation/infractions/functions/deleteInfractions.ts b/src/commands/moderation/infractions/functions/deleteInfractions.ts
index d2bd7539..90896b6c 100644
--- a/src/commands/moderation/infractions/functions/deleteInfractions.ts
+++ b/src/commands/moderation/infractions/functions/deleteInfractions.ts
@@ -2,113 +2,116 @@ import { ChatInputCommandInteraction, Colors, TextChannel, User } from 'discord.
import { constantsConfig, getConn, Infraction, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Delete - No Connection',
- description: 'Could not connect to the database',
- color: Colors.Red,
+ title: 'Delete - No Connection',
+ description: 'Could not connect to the database',
+ color: Colors.Red,
});
const noInfractionEmbed = makeEmbed({
- title: 'Delete - Infraction not found',
- description: 'This user has no infractions, please check the user ID and try again.',
- color: Colors.Red,
+ title: 'Delete - Infraction not found',
+ description: 'This user has no infractions, please check the user ID and try again.',
+ color: Colors.Red,
});
const successEmbed = makeEmbed({
- title: 'Delete - Success',
- description: 'Infraction deleted successfully',
- color: Colors.Green,
+ title: 'Delete - Success',
+ description: 'Infraction deleted successfully',
+ color: Colors.Green,
});
const noSpecificInfractionEmbed = makeEmbed({
- title: 'Delete - Infraction not found',
- description: 'This user has no infractions with that ID, please check the Infraction ID and try again.',
- color: Colors.Red,
+ title: 'Delete - Infraction not found',
+ description: 'This user has no infractions with that ID, please check the Infraction ID and try again.',
+ color: Colors.Red,
});
const errorEmbed = makeEmbed({
- title: 'Delete - Error',
- description: 'An error occurred while deleting the infraction, the error has been logged.',
- color: Colors.Red,
+ title: 'Delete - Error',
+ description: 'An error occurred while deleting the infraction, the error has been logged.',
+ color: Colors.Red,
});
-const modLogEmbed = (moderator: string, discordUser: User, infractionType: string, infractionReason: string) => makeEmbed({
+const modLogEmbed = (moderator: string, discordUser: User, infractionType: string, infractionReason: string) =>
+ makeEmbed({
author: {
- name: `[INFRACTION DELETE] ${discordUser.tag}`,
- iconURL: discordUser.displayAvatarURL(),
+ name: `[INFRACTION DELETE] ${discordUser.tag}`,
+ iconURL: discordUser.displayAvatarURL(),
},
fields: [
- {
- inline: false,
- name: 'Deleted by:',
- value: moderator,
- },
- {
- inline: false,
- name: 'Infraction user:',
- value: discordUser.toString(),
- },
- {
- inline: false,
- name: 'Infraction type:',
- value: infractionType,
- },
- {
- inline: false,
- name: 'Reason',
- value: infractionReason,
- },
+ {
+ inline: false,
+ name: 'Deleted by:',
+ value: moderator,
+ },
+ {
+ inline: false,
+ name: 'Infraction user:',
+ value: discordUser.toString(),
+ },
+ {
+ inline: false,
+ name: 'Infraction type:',
+ value: infractionType,
+ },
+ {
+ inline: false,
+ name: 'Reason',
+ value: infractionReason,
+ },
],
color: Colors.Green,
-});
+ });
export async function handleDeleteInfraction(interaction: ChatInputCommandInteraction<'cached'>) {
- const conn = getConn();
+ const conn = getConn();
- if (!conn) {
- await interaction.reply({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ if (!conn) {
+ await interaction.reply({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const userID = interaction.options.getUser('tag_or_id')!.id;
+ const userID = interaction.options.getUser('tag_or_id')!.id;
- const discordUser = await interaction.client.users.fetch(userID);
+ const discordUser = await interaction.client.users.fetch(userID);
- const infractionID = interaction.options.getString('infraction_id');
+ const infractionID = interaction.options.getString('infraction_id');
- try {
- const infraction = await Infraction.findOne({ userID });
+ try {
+ const infraction = await Infraction.findOne({ userID });
- if (!infraction) {
- await interaction.reply({ embeds: [noInfractionEmbed], ephemeral: true });
- return;
- }
+ if (!infraction) {
+ await interaction.reply({ embeds: [noInfractionEmbed], ephemeral: true });
+ return;
+ }
- const existingInfractionIndex = infraction.infractions.findIndex(
- (item) => String(item.infractionID) === infractionID,
- );
+ const existingInfractionIndex = infraction.infractions.findIndex(
+ (item) => String(item.infractionID) === infractionID,
+ );
- if (existingInfractionIndex === -1) {
- await interaction.reply({ embeds: [noSpecificInfractionEmbed], ephemeral: true });
- return;
- }
+ if (existingInfractionIndex === -1) {
+ await interaction.reply({ embeds: [noSpecificInfractionEmbed], ephemeral: true });
+ return;
+ }
- const infractionType = infraction.infractions[existingInfractionIndex].infractionType || 'Unknown';
+ const infractionType = infraction.infractions[existingInfractionIndex].infractionType || 'Unknown';
- const infractionReason = infraction.infractions[existingInfractionIndex].reason || 'Unknown';
+ const infractionReason = infraction.infractions[existingInfractionIndex].reason || 'Unknown';
- infraction.infractions.splice(existingInfractionIndex, 1);
+ infraction.infractions.splice(existingInfractionIndex, 1);
- await infraction.save();
+ await infraction.save();
- await interaction.reply({ embeds: [successEmbed], ephemeral: true });
+ await interaction.reply({ embeds: [successEmbed], ephemeral: true });
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- if (modLogsChannel) {
- await modLogsChannel.send({ embeds: [modLogEmbed(interaction.user.toString(), discordUser, infractionType, infractionReason)] });
- }
- } catch (error) {
- await interaction.reply({ embeds: [errorEmbed], ephemeral: true });
- Logger.error(error);
+ if (modLogsChannel) {
+ await modLogsChannel.send({
+ embeds: [modLogEmbed(interaction.user.toString(), discordUser, infractionType, infractionReason)],
+ });
}
+ } catch (error) {
+ await interaction.reply({ embeds: [errorEmbed], ephemeral: true });
+ Logger.error(error);
+ }
}
diff --git a/src/commands/moderation/infractions/functions/listInfractions.ts b/src/commands/moderation/infractions/functions/listInfractions.ts
index 52820386..623c9a50 100644
--- a/src/commands/moderation/infractions/functions/listInfractions.ts
+++ b/src/commands/moderation/infractions/functions/listInfractions.ts
@@ -1,370 +1,365 @@
-import { Colors, CommandInteraction } from 'discord.js';
+import { Colors, CommandInteraction, User } from 'discord.js';
import moment from 'moment';
import { getConn, Infraction, makeEmbed, createPaginatedInfractionEmbedHandler } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'List - No Connection',
- description: 'Could not connect to the database',
- color: Colors.Red,
+ title: 'List - No Connection',
+ description: 'Could not connect to the database',
+ color: Colors.Red,
});
-export async function handleListInfraction(interaction: CommandInteraction, userID: string | undefined, ephemeral = false) {
- const conn = getConn();
+export async function handleListInfraction(
+ interaction: CommandInteraction,
+ userID: string | undefined,
+ ephemeral = false,
+) {
+ const conn = getConn();
+
+ if (!conn) {
+ await interaction.reply({ embeds: [noConnEmbed], ephemeral });
+ return;
+ }
+
+ if (!userID) {
+ await interaction.reply({ content: 'Please provide a user tag or ID.', ephemeral });
+ return;
+ }
+
+ const id = userID;
+
+ try {
+ const discordUser = await interaction.client.users.fetch(id);
+
+ const avatarURL = discordUser.displayAvatarURL();
+
+ const user = await Infraction.findOne({ userID: id });
+ if (!user) {
+ const infractionsNotFound = makeEmbed({
+ color: Colors.Red,
+ author: {
+ name: `${discordUser.tag}'s Infractions not found`,
+ iconURL: avatarURL || undefined,
+ },
+ description: 'This user has no infractions stored in the database',
+ footer: { text: `UserID: ${discordUser.id}` },
+ });
+
+ await interaction.reply({ embeds: [infractionsNotFound], ephemeral });
+
+ return;
+ }
+
+ //Grab infractions from DB and make embeds
+
+ const warnInfractions = user.infractions.filter((infraction) => infraction.infractionType === 'Warn');
+ const timeoutInfractions = user.infractions.filter((infraction) => infraction.infractionType === 'Timeout');
+ const scamLogInfractions = user.infractions.filter((infraction) => infraction.infractionType === 'ScamLog');
+ const banInfractions = user.infractions.filter((infraction) => infraction.infractionType === 'Ban');
+ const unbanInfractions = user.infractions.filter((infraction) => infraction.infractionType === 'Unban');
+ const userNotes = user.infractions.filter((infraction) => infraction.infractionType === 'Note');
+
+ const infractionsLengths = {
+ warnsLength: warnInfractions.length.toString(),
+ timeoutsLength: timeoutInfractions.length.toString(),
+ scamLogsLength: scamLogInfractions.length.toString(),
+ bansLength: banInfractions.length.toString(),
+ unbansLength: unbanInfractions.length.toString(),
+ notesLength: userNotes.length.toString(),
+ };
+
+ // Added for future compatibility with other types.
+ /* eslint-disable @typescript-eslint/no-duplicate-type-constituents */
+ type InfractionArray =
+ | typeof warnInfractions
+ | typeof timeoutInfractions
+ | typeof scamLogInfractions
+ | typeof banInfractions
+ | typeof unbanInfractions
+ | typeof userNotes;
+ /* eslint-enable @typescript-eslint/no-duplicate-type-constituents */
+
+ const fetchModerators = async (infractions: InfractionArray): Promise<(User | string)[]> => {
+ return Promise.all(
+ infractions.map(async (infraction) => {
+ try {
+ return await interaction.client.users.fetch(infraction.moderatorID!);
+ } catch {
+ return `I can't find the moderator, here is the stored ID: ${infraction.moderatorID}`;
+ }
+ }),
+ );
+ };
+
+ // Warns
+ const warnFields: { name: string; value: string }[] = [];
+ const warnModeratorUsers = await fetchModerators(warnInfractions);
+
+ for (let i = 0; i < warnInfractions.length; i++) {
+ const formattedDate: string = moment(warnInfractions[i].date).utcOffset(0).format();
+
+ warnFields.push(
+ {
+ name: `Warn #${i + 1}`,
+ value:
+ `**Type:** ${warnInfractions[i].infractionType}\n` +
+ `**Moderator:** ${warnModeratorUsers[i].toString()}\n` +
+ `**Reason:** ${warnInfractions[i].reason}\n` +
+ `**Date:** ${formattedDate}\n` +
+ `**Infraction ID:** ${warnInfractions[i].infractionID?.toString() ?? 'n/a'}`,
+ },
+ {
+ name: '',
+ value: '----------------------------------------',
+ },
+ );
+ }
+
+ const warnsEmbed = makeEmbed({
+ author: {
+ name: `${discordUser.tag}'s Warns`,
+ iconURL: avatarURL || undefined,
+ },
+ description: warnFields.length > 0 ? '' : 'This user has no warns logged',
+ fields: warnFields.flat(),
+ footer: { text: `UserID: ${user.userID}` },
+ });
+
+ //Timeouts
+ const timeoutFields: { name: string; value: string }[] = [];
+ const timeoutModeratorUsers = await fetchModerators(timeoutInfractions);
+
+ for (let i = 0; i < timeoutInfractions.length; i++) {
+ const formattedDate: string = moment(timeoutInfractions[i].date).utcOffset(0).format();
+
+ timeoutFields.push(
+ {
+ name: `Timeout #${i + 1}`,
+ value:
+ `**Type:** ${timeoutInfractions[i].infractionType}\n` +
+ `**Moderator:** ${timeoutModeratorUsers[i].toString()}\n` +
+ `**Reason:** ${timeoutInfractions[i].reason}\n` +
+ `**Duration:** ${timeoutInfractions[i].duration !== undefined ? timeoutInfractions[i].duration : 'No duration specified, this user was timed out before the bot upgrade!'}\n` +
+ `**Date:** ${formattedDate}\n` +
+ `**Infraction ID:** ${timeoutInfractions[i].infractionID?.toString() ?? 'n/a'}`,
+ },
+ {
+ name: '',
+ value: '----------------------------------------',
+ },
+ );
+ }
+
+ const timeoutsEmbed = makeEmbed({
+ author: {
+ name: `${discordUser.tag}'s Timeouts`,
+ iconURL: avatarURL || undefined,
+ },
+ description: timeoutFields.length > 0 ? '' : 'This user has no timeouts logged',
+ fields: timeoutFields.flat(),
+ footer: { text: `UserID: ${user.userID}` },
+ });
+
+ //ScamLogs
+ const scamLogFields: { name: string; value: string }[] = [];
+ const scamLogModerators = await fetchModerators(scamLogInfractions);
+
+ for (let i = 0; i < scamLogInfractions.length; i++) {
+ const formattedDate: string = moment(scamLogInfractions[i].date).utcOffset(0).format();
+
+ scamLogFields.push(
+ {
+ name: `Scam Log #${i + 1}`,
+ value:
+ `**Type:** ${scamLogInfractions[i].infractionType}\n` +
+ `**Moderator:** ${scamLogModerators[i].toString()}\n` +
+ `**Message Content:** ${scamLogInfractions[i].reason}\n` +
+ `**Date:** ${formattedDate}\n` +
+ `**Infraction ID:** ${scamLogInfractions[i].infractionID?.toString() ?? 'n/a'}`,
+ },
+ {
+ name: '',
+ value: '----------------------------------------',
+ },
+ );
+ }
- if (!conn) {
- await interaction.reply({ embeds: [noConnEmbed], ephemeral });
- return;
+ const scamLogEmbed = makeEmbed({
+ author: {
+ name: `${discordUser.tag}'s Scam Log Entries`,
+ iconURL: avatarURL || undefined,
+ },
+ description: scamLogFields.length > 0 ? '' : 'This user has no scam log entries logged',
+ fields: scamLogFields.flat(),
+ footer: { text: `UserID: ${user.userID}` },
+ });
+
+ //Bans
+ const banFields: { name: string; value: string }[] = [];
+ const banModerators = await fetchModerators(banInfractions);
+
+ for (let i = 0; i < banInfractions.length; i++) {
+ const formattedDate: string = moment(banInfractions[i].date).utcOffset(0).format();
+
+ banFields.push(
+ {
+ name: `Ban #${i + 1}`,
+ value:
+ `**Type:** ${banInfractions[i].infractionType}\n` +
+ `**Moderator:** ${banModerators[i].toString()}\n` +
+ `**Reason:** ${banInfractions[i].reason}\n` +
+ `**Date:** ${formattedDate}\n` +
+ `**Infraction ID:** ${banInfractions[i].infractionID?.toString() ?? 'n/a'}`,
+ },
+ {
+ name: '',
+ value: '----------------------------------------',
+ },
+ );
}
- if (!userID) {
- await interaction.reply({ content: 'Please provide a user tag or ID.', ephemeral });
- return;
+ const banEmbed = makeEmbed({
+ author: {
+ name: `${discordUser.tag}'s Bans`,
+ iconURL: avatarURL || undefined,
+ },
+ description: banFields.length > 0 ? '' : 'This user has no bans logged',
+ fields: banFields.flat(),
+ footer: { text: `UserID: ${user.userID}` },
+ });
+
+ //Unbans
+ const unbanFields: { name: string; value: string }[] = [];
+ const unbanModerators = await fetchModerators(unbanInfractions);
+ for (let i = 0; i < unbanInfractions.length; i++) {
+ const formattedDate: string = moment(unbanInfractions[i].date).utcOffset(0).format();
+
+ unbanFields.push(
+ {
+ name: `Unban #${i + 1}`,
+ value:
+ `**Type:** ${unbanInfractions[i].infractionType}\n` +
+ `**Moderator:** ${unbanModerators[i].toString()}\n` +
+ `**Reason:** ${unbanInfractions[i].reason}\n` +
+ `**Date:** ${formattedDate}\n` +
+ `**Infraction ID:** ${unbanInfractions[i].infractionID?.toString() ?? 'n/a'}`,
+ },
+ {
+ name: '',
+ value: '----------------------------------------',
+ },
+ );
}
- const id = userID;
-
- try {
- const discordUser = await interaction.client.users.fetch(id);
-
- const avatarURL = discordUser.displayAvatarURL();
-
- const user = await Infraction.findOne({ userID: id });
- if (!user) {
- const infractionsNotFound = makeEmbed({
- color: Colors.Red,
- author: {
- name: `${discordUser.tag}'s Infractions not found`,
- iconURL: avatarURL || undefined,
- },
- description: 'This user has no infractions stored in the database',
- footer: { text: `UserID: ${discordUser.id}` },
- });
-
- await interaction.reply({ embeds: [infractionsNotFound], ephemeral });
-
- return;
- }
-
- //Grab infractions from DB and make embeds
-
- const warnInfractions = user.infractions.filter((infraction) => infraction.infractionType === 'Warn');
- const timeoutInfractions = user.infractions.filter((infraction) => infraction.infractionType === 'Timeout');
- const scamLogInfractions = user.infractions.filter((infraction) => infraction.infractionType === 'ScamLog');
- const banInfractions = user.infractions.filter((infraction) => infraction.infractionType === 'Ban');
- const unbanInfractions = user.infractions.filter((infraction) => infraction.infractionType === 'Unban');
- const userNotes = user.infractions.filter((infraction) => infraction.infractionType === 'Note');
-
- const infractionsLengths = {
- warnsLength: warnInfractions.length.toString(),
- timeoutsLength: timeoutInfractions.length.toString(),
- scamLogsLength: scamLogInfractions.length.toString(),
- bansLength: banInfractions.length.toString(),
- unbansLength: unbanInfractions.length.toString(),
- notesLength: userNotes.length.toString(),
- };
-
- type InfractionArray = typeof warnInfractions
- | typeof timeoutInfractions
- | typeof scamLogInfractions
- | typeof banInfractions
- | typeof unbanInfractions
- | typeof userNotes;
-
- const fetchModerators = (infractions: InfractionArray) => {
- const moderatorPromises = infractions.map((infraction) => interaction.client.users.fetch(infraction.moderatorID!)
- // Disabled for readability
- // eslint-disable-next-line arrow-body-style
- .catch(() => {
- return new Promise((resolve) => {
- resolve(`I can't find the moderator, here is the stored ID: ${infraction.moderatorID}`);
- });
- }));
-
- return Promise.all(moderatorPromises);
- };
-
- // Warns
- const warnFields: { name: string; value: string }[] = [];
- const warnModeratorUsers = await fetchModerators(warnInfractions);
-
- for (let i = 0; i < warnInfractions.length; i++) {
- const formattedDate: string = moment(warnInfractions[i].date)
- .utcOffset(0)
- .format();
-
- warnFields.push(
- {
- name: `Warn #${i + 1}`,
- value:
- `**Type:** ${warnInfractions[i].infractionType}\n`
- + `**Moderator:** ${warnModeratorUsers[i]}\n`
- + `**Reason:** ${warnInfractions[i].reason}\n`
- + `**Date:** ${formattedDate}\n`
- + `**Infraction ID:** ${warnInfractions[i].infractionID}`,
- },
- {
- name: '',
- value: '----------------------------------------',
- },
- );
- }
-
- const warnsEmbed = makeEmbed({
- author: {
- name: `${discordUser.tag}'s Warns`,
- iconURL: avatarURL || undefined,
- },
- description: warnFields.length > 0 ? '' : 'This user has no warns logged',
- fields: warnFields.flat(),
- footer: { text: `UserID: ${user.userID}` },
- });
-
- //Timeouts
- const timeoutFields: { name: string; value: string }[] = [];
- const timeoutModeratorUsers = await fetchModerators(timeoutInfractions);
-
- for (let i = 0; i < timeoutInfractions.length; i++) {
- const formattedDate: string = moment(timeoutInfractions[i].date)
- .utcOffset(0)
- .format();
-
- timeoutFields.push(
- {
- name: `Timeout #${i + 1}`,
- value:
- `**Type:** ${timeoutInfractions[i].infractionType}\n`
- + `**Moderator:** ${timeoutModeratorUsers[i]}\n`
- + `**Reason:** ${timeoutInfractions[i].reason}\n`
- + `**Duration:** ${timeoutInfractions[i].duration !== undefined ? timeoutInfractions[i].duration : 'No duration specified, this user was timed out before the bot upgrade!'}\n`
- + `**Date:** ${formattedDate}\n`
- + `**Infraction ID:** ${timeoutInfractions[i].infractionID}`,
- },
- {
- name: '',
- value: '----------------------------------------',
- },
- );
- }
-
- const timeoutsEmbed = makeEmbed({
- author: {
- name: `${discordUser.tag}'s Timeouts`,
- iconURL: avatarURL || undefined,
- },
- description: timeoutFields.length > 0 ? '' : 'This user has no timeouts logged',
- fields: timeoutFields.flat(),
- footer: { text: `UserID: ${user.userID}` },
- });
-
- //ScamLogs
- const scamLogFields: { name: string; value: string }[] = [];
- const scamLogModerators = await fetchModerators(scamLogInfractions);
-
- for (let i = 0; i < scamLogInfractions.length; i++) {
- const formattedDate: string = moment(scamLogInfractions[i].date)
- .utcOffset(0)
- .format();
-
- scamLogFields.push(
- {
- name: `Scam Log #${i + 1}`,
- value:
- `**Type:** ${scamLogInfractions[i].infractionType}\n`
- + `**Moderator:** ${scamLogModerators[i]}\n`
- + `**Message Content:** ${scamLogInfractions[i].reason}\n`
- + `**Date:** ${formattedDate}\n`
- + `**Infraction ID:** ${scamLogInfractions[i].infractionID}`,
- },
- {
- name: '',
- value: '----------------------------------------',
- },
- );
- }
-
- const scamLogEmbed = makeEmbed({
- author: {
- name: `${discordUser.tag}'s Scam Log Entries`,
- iconURL: avatarURL || undefined,
- },
- description: scamLogFields.length > 0 ? '' : 'This user has no scam log entries logged',
- fields: scamLogFields.flat(),
- footer: { text: `UserID: ${user.userID}` },
- });
-
- //Bans
- const banFields: { name: string; value: string }[] = [];
- const banModerators = await fetchModerators(banInfractions);
-
- for (let i = 0; i < banInfractions.length; i++) {
- const formattedDate: string = moment(banInfractions[i].date)
- .utcOffset(0)
- .format();
-
- banFields.push(
- {
- name: `Ban #${i + 1}`,
- value:
- `**Type:** ${banInfractions[i].infractionType}\n`
- + `**Moderator:** ${banModerators[i]}\n`
- + `**Reason:** ${banInfractions[i].reason}\n`
- + `**Date:** ${formattedDate}\n`
- + `**Infraction ID:** ${banInfractions[i].infractionID}`,
- },
- {
- name: '',
- value: '----------------------------------------',
- },
- );
- }
-
- const banEmbed = makeEmbed({
- author: {
- name: `${discordUser.tag}'s Bans`,
- iconURL: avatarURL || undefined,
- },
- description: banFields.length > 0 ? '' : 'This user has no bans logged',
- fields: banFields.flat(),
- footer: { text: `UserID: ${user.userID}` },
- });
-
- //Unbans
- const unbanFields: { name: string; value: string }[] = [];
- const unbanModerators = await fetchModerators(unbanInfractions);
- for (let i = 0; i < unbanInfractions.length; i++) {
- const formattedDate: string = moment(unbanInfractions[i].date)
- .utcOffset(0)
- .format();
-
- unbanFields.push(
- {
- name: `Unban #${i + 1}`,
- value:
- `**Type:** ${unbanInfractions[i].infractionType}\n`
- + `**Moderator:** ${unbanModerators[i]}\n`
- + `**Reason:** ${unbanInfractions[i].reason}\n`
- + `**Date:** ${formattedDate}\n`
- + `**Infraction ID:** ${unbanInfractions[i].infractionID}`,
- },
- {
- name: '',
- value: '----------------------------------------',
- },
- );
- }
-
- const unbanEmbed = makeEmbed({
- author: {
- name: `${discordUser.tag}'s Unbans`,
- iconURL: avatarURL || undefined,
- },
- description: unbanFields.length > 0 ? '' : 'This user has no unbans logged',
- fields: unbanFields.flat(),
- footer: { text: `UserID: ${user.userID}` },
- });
-
- //Notes
- const noteFields: { name: string; value: string }[] = [];
- const userNodeModerators = await fetchModerators(userNotes);
-
- for (let i = 0; i < userNotes.length; i++) {
- const formattedDate: string = moment(userNotes[i].date)
- .utcOffset(0)
- .format();
-
- noteFields.push(
- {
- name: `Note #${i + 1}`,
- value:
- `**Type:** ${userNotes[i].infractionType}\n`
- + `**Moderator:** ${userNodeModerators[i]}\n`
- + `**Note:** ${userNotes[i].reason}\n`
- + `**Date:** ${formattedDate}\n`
- + `**Infraction ID:** ${userNotes[i].infractionID}`,
- },
- {
- name: '',
- value: '----------------------------------------',
- },
- );
- }
-
- const userNoteEmbed = makeEmbed({
- author: {
- name: `${discordUser.tag}'s Notes`,
- iconURL: avatarURL || undefined,
- },
- description: noteFields.length > 0 ? '' : 'This user has no notes logged',
- fields: noteFields.flat(),
- footer: { text: `UserID: ${user.userID}` },
- });
-
- //Make the about embed
- const aboutEmbed = makeEmbed({
- author: {
- name: `${discordUser.tag}'s Infractions`,
- iconURL: avatarURL || undefined,
- },
- description: 'Click the buttons below to view the user\'s infractions in detail.',
- fields: [
- {
- name: 'UserID',
- value: user.userID!,
- inline: false,
- },
- {
- name: 'User Tag',
- value: `<@${user.userID!}>`,
- inline: false,
- },
- {
- name: 'Warns',
- value: infractionsLengths.warnsLength,
- inline: true,
- },
- {
- name: 'Timeouts',
- value: infractionsLengths.timeoutsLength,
- inline: true,
- },
- {
- name: 'Scam Log Entries',
- value: infractionsLengths.scamLogsLength,
- inline: true,
- },
- {
- name: 'Bans',
- value: infractionsLengths.bansLength,
- inline: true,
- },
- {
- name: 'Unbans',
- value: infractionsLengths.unbansLength,
- inline: true,
- },
- {
- name: 'Notes',
- value: infractionsLengths.notesLength,
- inline: true,
- },
- ],
- footer: { text: 'This embed will expire in two minutes from command execution.' },
- });
-
- //Collect embeds and send with the paginator
- const embeds = [aboutEmbed, warnsEmbed, timeoutsEmbed, scamLogEmbed, banEmbed, unbanEmbed, userNoteEmbed];
- await interaction.deferReply({ ephemeral });
-
- await createPaginatedInfractionEmbedHandler(interaction, interaction.user.id, embeds, infractionsLengths);
- } catch (error) {
- //Error handling - User is no longer on discord (Or ID doesn't exist)
-
- const userNotFound = makeEmbed({
- color: Colors.Red,
- title: 'User not found',
- description: 'An error occurred while fetching user information, please check the userID. If the ID is correct, this user may not exist on Discord anymore - If you need to view their infractions anyway one of the bot team can search the DB manually.',
- });
-
- await interaction.followUp({ embeds: [userNotFound], ephemeral });
+ const unbanEmbed = makeEmbed({
+ author: {
+ name: `${discordUser.tag}'s Unbans`,
+ iconURL: avatarURL || undefined,
+ },
+ description: unbanFields.length > 0 ? '' : 'This user has no unbans logged',
+ fields: unbanFields.flat(),
+ footer: { text: `UserID: ${user.userID}` },
+ });
+
+ //Notes
+ const noteFields: { name: string; value: string }[] = [];
+ const userNodeModerators = await fetchModerators(userNotes);
+
+ for (let i = 0; i < userNotes.length; i++) {
+ const formattedDate: string = moment(userNotes[i].date).utcOffset(0).format();
+
+ noteFields.push(
+ {
+ name: `Note #${i + 1}`,
+ value:
+ `**Type:** ${userNotes[i].infractionType}\n` +
+ `**Moderator:** ${userNodeModerators[i].toString()}\n` +
+ `**Note:** ${userNotes[i].reason}\n` +
+ `**Date:** ${formattedDate}\n` +
+ `**Infraction ID:** ${userNotes[i].infractionID?.toString() ?? 'n/a'}`,
+ },
+ {
+ name: '',
+ value: '----------------------------------------',
+ },
+ );
}
+
+ const userNoteEmbed = makeEmbed({
+ author: {
+ name: `${discordUser.tag}'s Notes`,
+ iconURL: avatarURL || undefined,
+ },
+ description: noteFields.length > 0 ? '' : 'This user has no notes logged',
+ fields: noteFields.flat(),
+ footer: { text: `UserID: ${user.userID}` },
+ });
+
+ //Make the about embed
+ const aboutEmbed = makeEmbed({
+ author: {
+ name: `${discordUser.tag}'s Infractions`,
+ iconURL: avatarURL || undefined,
+ },
+ description: "Click the buttons below to view the user's infractions in detail.",
+ fields: [
+ {
+ name: 'UserID',
+ value: user.userID!,
+ inline: false,
+ },
+ {
+ name: 'User Tag',
+ value: `<@${user.userID!}>`,
+ inline: false,
+ },
+ {
+ name: 'Warns',
+ value: infractionsLengths.warnsLength,
+ inline: true,
+ },
+ {
+ name: 'Timeouts',
+ value: infractionsLengths.timeoutsLength,
+ inline: true,
+ },
+ {
+ name: 'Scam Log Entries',
+ value: infractionsLengths.scamLogsLength,
+ inline: true,
+ },
+ {
+ name: 'Bans',
+ value: infractionsLengths.bansLength,
+ inline: true,
+ },
+ {
+ name: 'Unbans',
+ value: infractionsLengths.unbansLength,
+ inline: true,
+ },
+ {
+ name: 'Notes',
+ value: infractionsLengths.notesLength,
+ inline: true,
+ },
+ ],
+ footer: { text: 'This embed will expire in two minutes from command execution.' },
+ });
+
+ //Collect embeds and send with the paginator
+ const embeds = [aboutEmbed, warnsEmbed, timeoutsEmbed, scamLogEmbed, banEmbed, unbanEmbed, userNoteEmbed];
+ await interaction.deferReply({ ephemeral });
+
+ await createPaginatedInfractionEmbedHandler(interaction, interaction.user.id, embeds, infractionsLengths);
+ } catch {
+ //Error handling - User is no longer on discord (Or ID doesn't exist)
+ const userNotFound = makeEmbed({
+ color: Colors.Red,
+ title: 'User not found',
+ description:
+ 'An error occurred while fetching user information, please check the userID. If the ID is correct, this user may not exist on Discord anymore - If you need to view their infractions anyway one of the bot team can search the DB manually.',
+ });
+
+ await interaction.followUp({ embeds: [userNotFound], ephemeral });
+ }
}
diff --git a/src/commands/moderation/infractions/functions/removeTimeout.ts b/src/commands/moderation/infractions/functions/removeTimeout.ts
index 211778a9..61e93b00 100644
--- a/src/commands/moderation/infractions/functions/removeTimeout.ts
+++ b/src/commands/moderation/infractions/functions/removeTimeout.ts
@@ -2,85 +2,89 @@ import { ChatInputCommandInteraction, Colors, TextChannel, User } from 'discord.
import moment from 'moment';
import { constantsConfig, Logger, makeEmbed } from '../../../../lib';
-const notTimedOutEmbed = (discordUser: User) => makeEmbed({
+const notTimedOutEmbed = (discordUser: User) =>
+ makeEmbed({
title: 'Remove Timeout - Failed',
description: `${discordUser.toString()} is not currently timed out.`,
color: Colors.Red,
-});
+ });
-const failedRemoveTimeoutEmbed = (discordUser: User) => makeEmbed({
+const failedRemoveTimeoutEmbed = (discordUser: User) =>
+ makeEmbed({
title: 'Remove Timeout - Failed',
description: `Failed to remove timeout for ${discordUser.toString()}`,
color: Colors.Red,
-});
+ });
-const modLogEmbed = (moderator: User, discordUser: User, date: string) => makeEmbed({
+const modLogEmbed = (moderator: User, discordUser: User, date: string) =>
+ makeEmbed({
author: {
- name: `[TIMEOUT REMOVED] ${discordUser.tag}`,
- iconURL: discordUser.displayAvatarURL(),
+ name: `[TIMEOUT REMOVED] ${discordUser.tag}`,
+ iconURL: discordUser.displayAvatarURL(),
},
fields: [
- {
- inline: true,
- name: 'Moderator',
- value: moderator.toString(),
- },
- {
- inline: true,
- name: 'User',
- value: discordUser.toString(),
- },
- {
- inline: false,
- name: 'Date',
- value: date,
- },
+ {
+ inline: true,
+ name: 'Moderator',
+ value: moderator.toString(),
+ },
+ {
+ inline: true,
+ name: 'User',
+ value: discordUser.toString(),
+ },
+ {
+ inline: false,
+ name: 'Date',
+ value: date,
+ },
],
footer: { text: `User ID: ${discordUser.id}` },
color: Colors.Green,
-});
+ });
-const timeoutRemovedEmbed = (discordUser: User) => makeEmbed({
+const timeoutRemovedEmbed = (discordUser: User) =>
+ makeEmbed({
title: `${discordUser.tag} was successfully removed from timeout`,
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Remove Timeout - No Mod Log',
- description: 'The user was removed from timeout, but no mod log was sent. Please check the channel still exists',
- color: Colors.Red,
+ title: 'Remove Timeout - No Mod Log',
+ description: 'The user was removed from timeout, but no mod log was sent. Please check the channel still exists',
+ color: Colors.Red,
});
export async function handleRemoveTimeoutInfraction(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const userID = interaction.options.getUser('tag_or_id')!.id;
- const discordUser = await interaction.guild.members.fetch(userID);
- const moderator = interaction.user;
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- const currentDate = new Date();
- const formattedDate: string = moment(currentDate).utcOffset(0).format();
+ const userID = interaction.options.getUser('tag_or_id')!.id;
+ const discordUser = await interaction.guild.members.fetch(userID);
+ const moderator = interaction.user;
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const currentDate = new Date();
+ const formattedDate: string = moment(currentDate).utcOffset(0).format();
- // Check if the user is currently timed out
- if (!discordUser.isCommunicationDisabled()) {
- await interaction.followUp({ embeds: [notTimedOutEmbed(discordUser.user)], ephemeral: true });
- return;
- }
+ // Check if the user is currently timed out
+ if (!discordUser.isCommunicationDisabled()) {
+ await interaction.followUp({ embeds: [notTimedOutEmbed(discordUser.user)], ephemeral: true });
+ return;
+ }
- // Remove the timeout for the user
- try {
- await discordUser.timeout(1); // Set the duration to 0 to remove the timeout
- } catch (error) {
- Logger.error(error);
- await interaction.followUp({ embeds: [failedRemoveTimeoutEmbed(discordUser.user)], ephemeral: true });
- return;
- }
+ // Remove the timeout for the user
+ try {
+ await discordUser.timeout(1); // Set the duration to 0 to remove the timeout
+ } catch (error) {
+ Logger.error(error);
+ await interaction.followUp({ embeds: [failedRemoveTimeoutEmbed(discordUser.user)], ephemeral: true });
+ return;
+ }
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, discordUser.user, formattedDate)] });
- } catch {
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ try {
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, discordUser.user, formattedDate)] });
+ } catch {
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- await interaction.followUp({ embeds: [timeoutRemovedEmbed(discordUser.user)], ephemeral: true });
+ await interaction.followUp({ embeds: [timeoutRemovedEmbed(discordUser.user)], ephemeral: true });
}
diff --git a/src/commands/moderation/infractions/functions/timeout.ts b/src/commands/moderation/infractions/functions/timeout.ts
index 54af02b6..8a453138 100644
--- a/src/commands/moderation/infractions/functions/timeout.ts
+++ b/src/commands/moderation/infractions/functions/timeout.ts
@@ -4,190 +4,211 @@ import mongoose from 'mongoose';
import { constantsConfig, durationInEnglish, getConn, Infraction, Logger, makeEmbed, makeLines } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Timeout - No Connection',
- description: 'Could not connect to the database. I will still try to timeout the user',
- color: Colors.Red,
+ title: 'Timeout - No Connection',
+ description: 'Could not connect to the database. I will still try to timeout the user',
+ color: Colors.Red,
});
-const failedTimeoutEmbed = (discordUser: User, error: any) => makeEmbed({
+const failedTimeoutEmbed = (discordUser: User, error: Error) =>
+ makeEmbed({
title: 'Timeout - Failed',
- description: makeLines([
- `Failed to timeout ${discordUser.toString()}`,
- '',
- error,
- ]),
+ description: makeLines([`Failed to timeout ${discordUser.toString()}`, '', error.message]),
color: Colors.Red,
-});
+ });
-const DMEmbed = (moderator: User, timeoutDuration: string, reason: string, guild: Guild, timedOutUntil: Date) => makeEmbed({
+const DMEmbed = (moderator: User, timeoutDuration: string, reason: string, guild: Guild, timedOutUntil: Date) =>
+ makeEmbed({
title: `You have been timed out in ${guild.name}`,
description: 'This timeout is also logged against your record.',
fields: [
- {
- inline: true,
- name: 'Duration',
- value: durationInEnglish(timeoutDuration),
- },
- {
- inline: true,
- name: 'Moderator',
- value: moderator.toString(),
- },
- {
- inline: false,
- name: 'Reason',
- value: reason,
- },
+ {
+ inline: true,
+ name: 'Duration',
+ value: durationInEnglish(Number.parseInt(timeoutDuration)),
+ },
+ {
+ inline: true,
+ name: 'Moderator',
+ value: moderator.toString(),
+ },
+ {
+ inline: false,
+ name: 'Reason',
+ value: reason,
+ },
],
footer: { text: `Your timeout will be lifted on ${timedOutUntil.toUTCString()}` },
-});
+ });
-const timeoutEmbed = (discordUser: User) => makeEmbed({
+const timeoutEmbed = (discordUser: User) =>
+ makeEmbed({
title: `${discordUser.tag} was timed out successfully`,
color: Colors.Green,
-});
+ });
-const DMFailed = (discordUser: User) => makeEmbed({
+const DMFailed = (discordUser: User) =>
+ makeEmbed({
title: 'Timeout - DM not sent',
description: `DM was not sent to ${discordUser.toString()}, they either have DMs closed or share no mutual servers with the bot.`,
color: Colors.Red,
-});
-
-const modLogEmbed = (moderator: User, discordUser: User, timeoutReason: string, timeoutDuration: string, formattedDate: string) => makeEmbed({
+ });
+
+const modLogEmbed = (
+ moderator: User,
+ discordUser: User,
+ timeoutReason: string,
+ timeoutDuration: string,
+ formattedDate: string,
+) =>
+ makeEmbed({
author: {
- name: `[TIMED OUT] ${discordUser.tag}`,
- iconURL: discordUser.displayAvatarURL(),
+ name: `[TIMED OUT] ${discordUser.tag}`,
+ iconURL: discordUser.displayAvatarURL(),
},
fields: [
- {
- name: 'User',
- value: discordUser.toString(),
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Reason',
- value: `\u200B${timeoutReason}`,
- },
- {
- name: 'Duration',
- value: durationInEnglish(timeoutDuration),
- },
- {
- name: 'Date',
- value: formattedDate,
- },
+ {
+ name: 'User',
+ value: discordUser.toString(),
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Reason',
+ value: `\u200B${timeoutReason}`,
+ },
+ {
+ name: 'Duration',
+ value: durationInEnglish(Number.parseInt(timeoutDuration)),
+ },
+ {
+ name: 'Date',
+ value: formattedDate,
+ },
],
footer: { text: `User ID: ${discordUser.id}` },
color: Colors.Red,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Timeout - No Mod Log',
- description: 'The user was timed out, but no mod log was sent. Please check the channel still exists',
- color: Colors.Red,
+ title: 'Timeout - No Mod Log',
+ description: 'The user was timed out, but no mod log was sent. Please check the channel still exists',
+ color: Colors.Red,
});
const logFailed = makeEmbed({
- title: 'Timeot - Failed to log',
- description: 'Failed to log the timeout to the database.',
- color: Colors.Red,
+ title: 'Timeot - Failed to log',
+ description: 'Failed to log the timeout to the database.',
+ color: Colors.Red,
});
-const communicationNotDisabledEmbed = (discordUser: User) => makeEmbed({
+const communicationNotDisabledEmbed = (discordUser: User) =>
+ makeEmbed({
title: 'Timeout - Communication not disabled',
description: `Bot has not detected that ${discordUser.toString()} was successfully timed out. Timeout may have failed.`,
color: Colors.Red,
-});
+ });
export async function handleTimeoutInfraction(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
+ const conn = getConn();
- if (!conn) {
- await interaction.editReply({ embeds: [noConnEmbed] });
- return;
- }
+ if (!conn) {
+ await interaction.editReply({ embeds: [noConnEmbed] });
+ return;
+ }
- const userID = interaction.options.getUser('tag_or_id')!.id;
- const timeoutDuration = interaction.options.getNumber('duration')!;
- const timeoutReason = interaction.options.getString('reason')!;
+ const userID = interaction.options.getUser('tag_or_id')!.id;
+ const timeoutDuration = interaction.options.getNumber('duration')!;
+ const timeoutReason = interaction.options.getString('reason')!;
- const discordUser = await interaction.guild.members.fetch(userID);
- const moderator = interaction.user;
- const currentDate = new Date();
- const formattedDate: string = moment(currentDate)
- .utcOffset(0)
- .format();
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const discordUser = await interaction.guild.members.fetch(userID);
+ const moderator = interaction.user;
+ const currentDate = new Date();
+ const formattedDate: string = moment(currentDate).utcOffset(0).format();
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- //Try to timeout the user
+ //Try to timeout the user
+ try {
+ await discordUser.timeout(timeoutDuration, timeoutReason);
+ } catch (error) {
+ if (error instanceof Error) {
+ await interaction.editReply({ embeds: [failedTimeoutEmbed(discordUser.user, error)] });
+ }
+ Logger.error(error);
+ return;
+ }
+
+ if (discordUser.isCommunicationDisabled()) {
+ //Timeout was successful
+ await interaction.editReply({ embeds: [timeoutEmbed(discordUser.user)] });
+ //Try and send a Dm to the user
try {
- await discordUser.timeout(timeoutDuration, timeoutReason);
- } catch (error) {
- await interaction.editReply({ embeds: [failedTimeoutEmbed(discordUser.user, error)] });
- Logger.error(error);
- return;
+ await discordUser.send({
+ embeds: [
+ DMEmbed(
+ moderator,
+ timeoutDuration.toString(),
+ timeoutReason,
+ interaction.guild,
+ discordUser.communicationDisabledUntil,
+ ),
+ ],
+ });
+ } catch {
+ if (modLogsChannel) {
+ await interaction.followUp({ embeds: [DMFailed(discordUser.user)], ephemeral: true });
+ }
}
-
- if (discordUser.isCommunicationDisabled()) { //Timeout was successful
- await interaction.editReply({ embeds: [timeoutEmbed(discordUser.user)] });
- //Try and send a Dm to the user
- try {
- await discordUser.send({ embeds: [DMEmbed(moderator, timeoutDuration.toString(), timeoutReason, interaction.guild, discordUser.communicationDisabledUntil)] });
- } catch {
- if (modLogsChannel) {
- await interaction.followUp({ embeds: [DMFailed(discordUser.user)], ephemeral: true });
- }
- }
- //Send a mod log to the mod logs channel
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, discordUser.user, timeoutReason, timeoutDuration.toString(), formattedDate)] });
- } catch {
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- return;
- }
- //Log to the DB
-
- Logger.info('Starting Infraction process');
-
- const newInfraction = {
- infractionType: 'Timeout',
- moderatorID: moderator.id,
- reason: timeoutReason,
- duration: durationInEnglish(timeoutDuration),
- date: currentDate,
- infractionID: new mongoose.Types.ObjectId(),
- };
-
- let userData = await Infraction.findOne({ userID });
-
- Logger.info(userData);
-
- if (!userData) {
- userData = new Infraction({
- userID,
- infractions: [newInfraction],
- });
- Logger.info(userData);
- Logger.info('New user data created');
- } else {
- userData.infractions.push(newInfraction);
- Logger.info('User data updated');
- }
-
- try {
- await userData.save();
- Logger.info('Infraction process complete');
- } catch (error) {
- await interaction.followUp({ embeds: [logFailed], ephemeral: true });
- Logger.error(error);
- }
+ //Send a mod log to the mod logs channel
+ try {
+ await modLogsChannel.send({
+ embeds: [modLogEmbed(moderator, discordUser.user, timeoutReason, timeoutDuration.toString(), formattedDate)],
+ });
+ } catch {
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ return;
+ }
+ //Log to the DB
+
+ Logger.info('Starting Infraction process');
+
+ const newInfraction = {
+ infractionType: 'Timeout',
+ moderatorID: moderator.id,
+ reason: timeoutReason,
+ duration: durationInEnglish(timeoutDuration),
+ date: currentDate,
+ infractionID: new mongoose.Types.ObjectId(),
+ };
+
+ let userData = await Infraction.findOne({ userID });
+
+ Logger.info(userData);
+
+ if (!userData) {
+ userData = new Infraction({
+ userID,
+ infractions: [newInfraction],
+ });
+ Logger.info(userData);
+ Logger.info('New user data created');
} else {
- await interaction.followUp({ embeds: [communicationNotDisabledEmbed(discordUser.user)], ephemeral: true });
+ userData.infractions.push(newInfraction);
+ Logger.info('User data updated');
+ }
+
+ try {
+ await userData.save();
+ Logger.info('Infraction process complete');
+ } catch (error) {
+ await interaction.followUp({ embeds: [logFailed], ephemeral: true });
+ Logger.error(error);
}
+ } else {
+ await interaction.followUp({ embeds: [communicationNotDisabledEmbed(discordUser.user)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/infractions/functions/unbanInfractions.ts b/src/commands/moderation/infractions/functions/unbanInfractions.ts
index 48894f24..5e5addfa 100644
--- a/src/commands/moderation/infractions/functions/unbanInfractions.ts
+++ b/src/commands/moderation/infractions/functions/unbanInfractions.ts
@@ -4,129 +4,131 @@ import mongoose from 'mongoose';
import { constantsConfig, getConn, Infraction, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Unban - No Connection',
- description: 'Could not connect to the database. I will still try to unban the user',
- color: Colors.Red,
+ title: 'Unban - No Connection',
+ description: 'Could not connect to the database. I will still try to unban the user',
+ color: Colors.Red,
});
-const failedUnbanEmbed = (userID: string) => makeEmbed({
+const failedUnbanEmbed = (userID: string) =>
+ makeEmbed({
title: 'Unban - Failed',
description: `Failed to Unban ${userID}, this user may not be banned.`,
color: Colors.Red,
-});
+ });
-const unbanEmbed = (userID: string) => makeEmbed({
+const unbanEmbed = (userID: string) =>
+ makeEmbed({
title: `${userID} was unbanned successfully`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, userID: string, banReason: string, formattedDate: string) => makeEmbed({
+const modLogEmbed = (moderator: User, userID: string, banReason: string, formattedDate: string) =>
+ makeEmbed({
author: { name: `[UNBANNED] ${userID}` },
fields: [
- {
- name: 'User',
- value: userID,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Reason',
- value: `\u200B${banReason}`,
- },
- {
- name: 'Date',
- value: formattedDate,
- },
+ {
+ name: 'User',
+ value: userID,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Reason',
+ value: `\u200B${banReason}`,
+ },
+ {
+ name: 'Date',
+ value: formattedDate,
+ },
],
footer: { text: `User ID: ${userID}` },
color: Colors.Red,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Unban - No Mod Log',
- description: 'I can\'t find the mod logs channel. I will still try to unban the user. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Unban - No Mod Log',
+ description:
+ "I can't find the mod logs channel. I will still try to unban the user. Please check the channel still exists.",
+ color: Colors.Red,
});
const logFailed = makeEmbed({
- title: 'Unban - Failed to log',
- description: 'Failed to log the unban to the database.',
- color: Colors.Red,
+ title: 'Unban - Failed to log',
+ description: 'Failed to log the unban to the database.',
+ color: Colors.Red,
});
export async function handleUnbanInfraction(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
+ const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const userID = interaction.options.getUser('id')!.id;
+ const userID = interaction.options.getUser('id')!.id;
- const unbanReason = interaction.options.getString('reason')!;
+ const unbanReason = interaction.options.getString('reason')!;
- const moderator = interaction.user;
- const currentDate = new Date();
- const formattedDate: string = moment(currentDate)
- .utcOffset(0)
- .format();
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const moderator = interaction.user;
+ const currentDate = new Date();
+ const formattedDate: string = moment(currentDate).utcOffset(0).format();
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- //Check if the mod logs channel exists
+ //Check if the mod logs channel exists
- if (!modLogsChannel) {
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ if (!modLogsChannel) {
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- try {
- await interaction.guild.members.unban(userID, unbanReason);
- if (modLogsChannel) {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, userID, unbanReason, formattedDate)] });
- }
- await interaction.followUp({ embeds: [unbanEmbed(userID)], ephemeral: true });
- } catch (error) {
- Logger.error(error);
- await interaction.followUp({ embeds: [failedUnbanEmbed(userID)], ephemeral: true });
- return;
+ try {
+ await interaction.guild.members.unban(userID, unbanReason);
+ if (modLogsChannel) {
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, userID, unbanReason, formattedDate)] });
}
-
- //Log to the DB
- Logger.info('Starting Infraction process');
-
- const newInfraction = {
- infractionType: 'Unban',
- moderatorID: moderator.id,
- reason: unbanReason,
- date: currentDate,
- infractionID: new mongoose.Types.ObjectId(),
- };
-
- let userData = await Infraction.findOne({ userID });
-
+ await interaction.followUp({ embeds: [unbanEmbed(userID)], ephemeral: true });
+ } catch (error) {
+ Logger.error(error);
+ await interaction.followUp({ embeds: [failedUnbanEmbed(userID)], ephemeral: true });
+ return;
+ }
+
+ //Log to the DB
+ Logger.info('Starting Infraction process');
+
+ const newInfraction = {
+ infractionType: 'Unban',
+ moderatorID: moderator.id,
+ reason: unbanReason,
+ date: currentDate,
+ infractionID: new mongoose.Types.ObjectId(),
+ };
+
+ let userData = await Infraction.findOne({ userID });
+
+ Logger.info(userData);
+
+ if (!userData) {
+ userData = new Infraction({
+ userID,
+ infractions: [newInfraction],
+ });
Logger.info(userData);
-
- if (!userData) {
- userData = new Infraction({
- userID,
- infractions: [newInfraction],
- });
- Logger.info(userData);
- Logger.info('New user data created');
- } else {
- userData.infractions.push(newInfraction);
- Logger.info('User data updated');
- }
-
- try {
- await userData.save();
- Logger.info('Infraction process complete');
- } catch (error) {
- await interaction.followUp({ embeds: [logFailed], ephemeral: true });
- Logger.error(error);
- }
+ Logger.info('New user data created');
+ } else {
+ userData.infractions.push(newInfraction);
+ Logger.info('User data updated');
+ }
+
+ try {
+ await userData.save();
+ Logger.info('Infraction process complete');
+ } catch (error) {
+ await interaction.followUp({ embeds: [logFailed], ephemeral: true });
+ Logger.error(error);
+ }
}
diff --git a/src/commands/moderation/infractions/functions/userNote.ts b/src/commands/moderation/infractions/functions/userNote.ts
index 30d58cad..f58e024e 100644
--- a/src/commands/moderation/infractions/functions/userNote.ts
+++ b/src/commands/moderation/infractions/functions/userNote.ts
@@ -4,134 +4,136 @@ import mongoose from 'mongoose';
import { constantsConfig, getConn, Infraction, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Note - No Connection',
- description: 'Could not connect to the database',
- color: Colors.Red,
+ title: 'Note - No Connection',
+ description: 'Could not connect to the database',
+ color: Colors.Red,
});
const noteFailed = makeEmbed({
- title: 'Note - Failed',
- description: 'Failed to add user note, doc not saved to mongoDB',
- color: Colors.Red,
+ title: 'Note - Failed',
+ description: 'Failed to add user note, doc not saved to mongoDB',
+ color: Colors.Red,
});
-const modLogEmbed = (formattedDate: any, moderator: User, discordUser: User, note: string) => makeEmbed({
+const modLogEmbed = (formattedDate: string, moderator: User, discordUser: User, note: string) =>
+ makeEmbed({
author: {
- name: `[NOTE] ${discordUser.tag}`,
- iconURL: discordUser.displayAvatarURL(),
+ name: `[NOTE] ${discordUser.tag}`,
+ iconURL: discordUser.displayAvatarURL(),
},
fields: [
- {
- inline: false,
- name: 'User',
- value: discordUser.toString(),
- },
- {
- inline: false,
- name: 'Moderator',
- value: moderator.toString(),
- },
- {
- inline: false,
- name: 'Note',
- value: note,
- },
- {
- inline: false,
- name: 'Date',
- value: formattedDate,
- },
+ {
+ inline: false,
+ name: 'User',
+ value: discordUser.toString(),
+ },
+ {
+ inline: false,
+ name: 'Moderator',
+ value: moderator.toString(),
+ },
+ {
+ inline: false,
+ name: 'Note',
+ value: note,
+ },
+ {
+ inline: false,
+ name: 'Date',
+ value: formattedDate,
+ },
],
footer: { text: `User ID: ${discordUser.id}` },
color: Colors.Red,
-});
+ });
-const noteEmbed = (user: User) => makeEmbed({
+const noteEmbed = (user: User) =>
+ makeEmbed({
title: `Note for ${user.tag} has been added successfully`,
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Note - No Mod Log',
- description: 'The user note was added, but no mod log was sent. Please check the channel still exists',
- color: Colors.Red,
+ title: 'Note - No Mod Log',
+ description: 'The user note was added, but no mod log was sent. Please check the channel still exists',
+ color: Colors.Red,
});
export async function handleUserNoteInfraction(interaction: ChatInputCommandInteraction<'cached'>) {
- const conn = getConn();
+ const conn = getConn();
- if (!conn) {
- await interaction.reply({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ if (!conn) {
+ await interaction.reply({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const userID = interaction.options.getUser('tag_or_id')?.id;
+ const userID = interaction.options.getUser('tag_or_id')?.id;
- if (!userID) {
- await interaction.reply({ content: 'Please provide a user tag or ID.', ephemeral: true });
- return;
- }
+ if (!userID) {
+ await interaction.reply({ content: 'Please provide a user tag or ID.', ephemeral: true });
+ return;
+ }
- const note = interaction.options.getString('note');
+ const note = interaction.options.getString('note');
- if (!note) {
- await interaction.reply({ content: 'Please provide a note.', ephemeral: true });
- return;
- }
+ if (!note) {
+ await interaction.reply({ content: 'Please provide a note.', ephemeral: true });
+ return;
+ }
- const discordUser = await interaction.client.users.fetch(userID);
+ const discordUser = await interaction.client.users.fetch(userID);
- const moderator = interaction.user;
+ const moderator = interaction.user;
- const currentDate = new Date();
+ const currentDate = new Date();
- const formattedDate: string = moment(currentDate).utcOffset(0).format();
+ const formattedDate: string = moment(currentDate).utcOffset(0).format();
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- //Try to save to the database
+ //Try to save to the database
- Logger.info('Starting Infraction process');
+ Logger.info('Starting Infraction process');
- const newInfraction = {
- infractionType: 'Note',
- moderatorID: moderator.id,
- reason: note,
- date: currentDate,
- infractionID: new mongoose.Types.ObjectId(),
- };
+ const newInfraction = {
+ infractionType: 'Note',
+ moderatorID: moderator.id,
+ reason: note,
+ date: currentDate,
+ infractionID: new mongoose.Types.ObjectId(),
+ };
- let userData = await Infraction.findOne({ userID });
+ let userData = await Infraction.findOne({ userID });
- Logger.info(userData);
+ Logger.info(userData);
- if (!userData) {
- userData = new Infraction({
- userID,
- infractions: [newInfraction],
- });
- Logger.info(userData);
- Logger.info('New user data created');
- } else {
- userData.infractions.push(newInfraction);
- Logger.info('User data updated');
- }
-
- try {
- await userData.save();
- Logger.info('Infraction process complete');
- } catch (error) {
- await interaction.reply({ embeds: [noteFailed], ephemeral: true });
- Logger.error(error);
- }
-
- //Send embed to mod-logs channel
-
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(formattedDate, moderator, discordUser, note)] });
- } catch {
- await interaction.reply({ embeds: [noModLogs], ephemeral: true });
- return;
- }
- await interaction.reply({ embeds: [noteEmbed(discordUser)], ephemeral: true });
+ if (!userData) {
+ userData = new Infraction({
+ userID,
+ infractions: [newInfraction],
+ });
+ Logger.info(userData);
+ Logger.info('New user data created');
+ } else {
+ userData.infractions.push(newInfraction);
+ Logger.info('User data updated');
+ }
+
+ try {
+ await userData.save();
+ Logger.info('Infraction process complete');
+ } catch (error) {
+ await interaction.reply({ embeds: [noteFailed], ephemeral: true });
+ Logger.error(error);
+ }
+
+ //Send embed to mod-logs channel
+
+ try {
+ await modLogsChannel.send({ embeds: [modLogEmbed(formattedDate, moderator, discordUser, note)] });
+ } catch {
+ await interaction.reply({ embeds: [noModLogs], ephemeral: true });
+ return;
+ }
+ await interaction.reply({ embeds: [noteEmbed(discordUser)], ephemeral: true });
}
diff --git a/src/commands/moderation/infractions/functions/warn.ts b/src/commands/moderation/infractions/functions/warn.ts
index 120e89f8..16216dac 100644
--- a/src/commands/moderation/infractions/functions/warn.ts
+++ b/src/commands/moderation/infractions/functions/warn.ts
@@ -4,172 +4,177 @@ import mongoose from 'mongoose';
import { constantsConfig, getConn, Infraction, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Warn - No Connection',
- description: 'Could not connect to the database',
- color: Colors.Red,
+ title: 'Warn - No Connection',
+ description: 'Could not connect to the database',
+ color: Colors.Red,
});
-const warnFailed = (discordUser: User) => makeEmbed({
+const warnFailed = (discordUser: User) =>
+ makeEmbed({
title: 'Warn - Failed',
description: `Failed to warn ${discordUser.toString()}, doc not saved to mongoDB`,
color: Colors.Red,
-});
+ });
-const dmEmbed = (guild: Guild, formattedDate: any, moderator: User, reason: string) => makeEmbed({
+const dmEmbed = (guild: Guild, formattedDate: string, moderator: User, reason: string) =>
+ makeEmbed({
title: `You have been warned in ${guild.name}`,
fields: [
- {
- inline: false,
- name: 'Moderator',
- value: moderator.toString(),
- },
- {
- inline: false,
- name: 'Reason',
- value: reason,
- },
- {
- inline: false,
- name: 'Date',
- value: formattedDate,
- },
+ {
+ inline: false,
+ name: 'Moderator',
+ value: moderator.toString(),
+ },
+ {
+ inline: false,
+ name: 'Reason',
+ value: reason,
+ },
+ {
+ inline: false,
+ name: 'Date',
+ value: formattedDate,
+ },
],
-});
+ });
-const noDM = (discordUser: User) => makeEmbed({
+const noDM = (discordUser: User) =>
+ makeEmbed({
title: 'Warn - DM not sent',
description: `DM was not sent to ${discordUser.toString()}, they either have DMs closed or share no mutual servers with the bot.`,
color: Colors.Red,
-});
+ });
-const modLogEmbed = (formattedDate: any, moderator: User, discordUser: User, reason: string) => makeEmbed({
+const modLogEmbed = (formattedDate: string, moderator: User, discordUser: User, reason: string) =>
+ makeEmbed({
author: {
- name: `[WARNED] ${discordUser.tag}`,
- iconURL: discordUser.displayAvatarURL(),
+ name: `[WARNED] ${discordUser.tag}`,
+ iconURL: discordUser.displayAvatarURL(),
},
fields: [
- {
- inline: false,
- name: 'User',
- value: discordUser.toString(),
- },
- {
- inline: false,
- name: 'Moderator',
- value: moderator.toString(),
- },
- {
- inline: false,
- name: 'Reason',
- value: reason,
- },
- {
- inline: false,
- name: 'Date',
- value: formattedDate,
- },
+ {
+ inline: false,
+ name: 'User',
+ value: discordUser.toString(),
+ },
+ {
+ inline: false,
+ name: 'Moderator',
+ value: moderator.toString(),
+ },
+ {
+ inline: false,
+ name: 'Reason',
+ value: reason,
+ },
+ {
+ inline: false,
+ name: 'Date',
+ value: formattedDate,
+ },
],
footer: { text: `User ID: ${discordUser.id}` },
color: Colors.Red,
-});
+ });
-const warnEmbed = (discordUser: User) => makeEmbed({
+const warnEmbed = (discordUser: User) =>
+ makeEmbed({
title: `${discordUser.tag} was warned successfully`,
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Warn - No Mod Log',
- description: 'The user was warned, but no mod log was sent. Please check the channel still exists',
- color: Colors.Red,
+ title: 'Warn - No Mod Log',
+ description: 'The user was warned, but no mod log was sent. Please check the channel still exists',
+ color: Colors.Red,
});
export async function handleWarnInfraction(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
+ const conn = getConn();
- if (!conn) {
- await interaction.editReply({ embeds: [noConnEmbed] });
- return;
- }
+ if (!conn) {
+ await interaction.editReply({ embeds: [noConnEmbed] });
+ return;
+ }
- const userID = interaction.options.getUser('tag_or_id')?.id;
+ const userID = interaction.options.getUser('tag_or_id')?.id;
- if (!userID) {
- await interaction.editReply({ content: 'Please provide a user tag or ID.' });
- return;
- }
+ if (!userID) {
+ await interaction.editReply({ content: 'Please provide a user tag or ID.' });
+ return;
+ }
- const reason = interaction.options.getString('reason');
+ const reason = interaction.options.getString('reason');
- if (!reason) {
- await interaction.editReply({ content: 'Please provide a reason.' });
- return;
- }
+ if (!reason) {
+ await interaction.editReply({ content: 'Please provide a reason.' });
+ return;
+ }
- const discordUser = await interaction.client.users.fetch(userID);
+ const discordUser = await interaction.client.users.fetch(userID);
- const moderator = interaction.user;
+ const moderator = interaction.user;
- const currentDate = new Date();
+ const currentDate = new Date();
- const formattedDate: string = moment(currentDate).utcOffset(0).format();
+ const formattedDate: string = moment(currentDate).utcOffset(0).format();
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- //Try to save to the database
+ //Try to save to the database
- Logger.info('Starting Infraction process');
+ Logger.info('Starting Infraction process');
- const newInfraction = {
- infractionType: 'Warn',
- moderatorID: moderator.id,
- reason,
- date: currentDate,
- infractionID: new mongoose.Types.ObjectId(),
- };
+ const newInfraction = {
+ infractionType: 'Warn',
+ moderatorID: moderator.id,
+ reason,
+ date: currentDate,
+ infractionID: new mongoose.Types.ObjectId(),
+ };
- let userData = await Infraction.findOne({ userID });
+ let userData = await Infraction.findOne({ userID });
- Logger.info(userData);
+ Logger.info(userData);
- if (!userData) {
- userData = new Infraction({
- userID,
- infractions: [newInfraction],
- });
- Logger.info(userData);
- Logger.info('New user data created');
- } else {
- userData.infractions.push(newInfraction);
- Logger.info('User data updated');
- }
-
- try {
- await userData.save();
- Logger.info('Infraction process complete');
- } catch (error) {
- await interaction.editReply({ embeds: [warnFailed(discordUser)] });
- Logger.error(error);
- return;
- }
-
- await interaction.editReply({ embeds: [warnEmbed(discordUser)] });
-
- //Send DM to user
-
- try {
- await discordUser.send({ embeds: [dmEmbed(interaction.guild, formattedDate, moderator, reason)] });
- } catch {
- await interaction.followUp({ embeds: [noDM(discordUser)], ephemeral: true });
- }
-
- //Send embed to mod-logs channel
-
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(formattedDate, moderator, discordUser, reason)] });
- } catch {
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ if (!userData) {
+ userData = new Infraction({
+ userID,
+ infractions: [newInfraction],
+ });
+ Logger.info(userData);
+ Logger.info('New user data created');
+ } else {
+ userData.infractions.push(newInfraction);
+ Logger.info('User data updated');
+ }
+
+ try {
+ await userData.save();
+ Logger.info('Infraction process complete');
+ } catch (error) {
+ await interaction.editReply({ embeds: [warnFailed(discordUser)] });
+ Logger.error(error);
+ return;
+ }
+
+ await interaction.editReply({ embeds: [warnEmbed(discordUser)] });
+
+ //Send DM to user
+
+ try {
+ await discordUser.send({ embeds: [dmEmbed(interaction.guild, formattedDate, moderator, reason)] });
+ } catch {
+ await interaction.followUp({ embeds: [noDM(discordUser)], ephemeral: true });
+ }
+
+ //Send embed to mod-logs channel
+
+ try {
+ await modLogsChannel.send({ embeds: [modLogEmbed(formattedDate, moderator, discordUser, reason)] });
+ } catch {
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/infractions/infractions.ts b/src/commands/moderation/infractions/infractions.ts
index 4da67f02..9b64c43e 100644
--- a/src/commands/moderation/infractions/infractions.ts
+++ b/src/commands/moderation/infractions/infractions.ts
@@ -14,216 +14,217 @@ import { handleUnbanInfraction } from './functions/unbanInfractions';
// Unban
const data = slashCommandStructure({
- name: 'infractions',
- description: 'Command to manage infractions.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
- dm_permission: false,
- options: [
- {
- name: 'list',
- description: 'Get infractions for a user.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'tag_or_id',
- description: 'Please provide a user tag or ID.',
- type: ApplicationCommandOptionType.User,
- required: true,
- },
- ],
- },
- {
- name: 'delete',
- description: 'Deletes the specified infraction.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'tag_or_id',
- description: 'Please provide the user tag or ID for the user of the infraction you wish to delete.',
- type: ApplicationCommandOptionType.User,
- required: true,
- },
- {
- name: 'infraction_id',
- description: 'Please provide the ID of the infraction you wish to delete.',
- type: ApplicationCommandOptionType.String,
- max_length: 100,
- required: true,
- },
- ],
- },
- {
- name: 'note',
- description: 'Adds a logging note to a user.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'tag_or_id',
- description: 'Please provide a user tag or ID.',
- type: ApplicationCommandOptionType.User,
- required: true,
- },
- {
- name: 'note',
- description: 'Please provide a note.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- ],
- },
- {
- name: 'warn',
- description: 'Warns a user.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'tag_or_id',
- description: 'Please provide a user tag or ID.',
- type: ApplicationCommandOptionType.User,
- required: true,
- },
- {
- name: 'reason',
- description: 'Please provide a reason.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- ],
- },
- {
- name: 'timeout',
- description: 'Timeouts a user.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'tag_or_id',
- description: 'Please provide a user tag or ID.',
- type: ApplicationCommandOptionType.User,
- required: true,
- },
- {
- name: 'duration',
- description: 'Please provide a duration.',
- type: ApplicationCommandOptionType.Number,
- required: true,
- choices: [
- { name: '1 minute', value: 60000 },
- { name: '5 minutes', value: 300000 },
- { name: '15 minutes', value: 900000 },
- { name: '30 minutes', value: 1800000 },
- { name: '1 hour', value: 3600000 },
- { name: '6 hours', value: 21600000 },
- { name: '12 hours', value: 43200000 },
- { name: '1 day', value: 86400000 },
- { name: '3 days', value: 259200000 },
- { name: '1 week', value: 604800000 },
- { name: '2 weeks', value: 1209600000 },
- { name: '3 weeks', value: 1814400000 },
- { name: '4 weeks', value: 2419200000 },
- ],
- },
- {
- name: 'reason',
- description: 'Please provide a reason.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- ],
- },
- {
- name: 'remove-timeout',
- description: 'Removes a timeout from a user.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'tag_or_id',
- description: 'Please provide a user tag or ID.',
- type: ApplicationCommandOptionType.User,
- required: true,
- },
- ],
- },
- {
- name: 'ban',
- description: 'Bans a user.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'tag_or_id',
- description: 'Please provide a user tag or ID.',
- type: ApplicationCommandOptionType.User,
- required: true,
- },
- {
- name: 'reason',
- description: 'Please provide a reason.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- {
- name: 'days_deleted',
- description: 'Please provide the number of days of messages to delete.',
- type: ApplicationCommandOptionType.Integer,
- required: false,
- min_value: 0,
- max_value: 7,
- },
- ],
- },
- {
- name: 'unban',
- description: 'Unbans a user.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'id',
- description: 'Please provide a userID only.',
- type: ApplicationCommandOptionType.User,
- required: true,
- },
- {
- name: 'reason',
- description: 'Please provide a reason.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- ],
- },
- ],
+ name: 'infractions',
+ description: 'Command to manage infractions.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
+ dm_permission: false,
+ options: [
+ {
+ name: 'list',
+ description: 'Get infractions for a user.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'tag_or_id',
+ description: 'Please provide a user tag or ID.',
+ type: ApplicationCommandOptionType.User,
+ required: true,
+ },
+ ],
+ },
+ {
+ name: 'delete',
+ description: 'Deletes the specified infraction.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'tag_or_id',
+ description: 'Please provide the user tag or ID for the user of the infraction you wish to delete.',
+ type: ApplicationCommandOptionType.User,
+ required: true,
+ },
+ {
+ name: 'infraction_id',
+ description: 'Please provide the ID of the infraction you wish to delete.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 100,
+ required: true,
+ },
+ ],
+ },
+ {
+ name: 'note',
+ description: 'Adds a logging note to a user.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'tag_or_id',
+ description: 'Please provide a user tag or ID.',
+ type: ApplicationCommandOptionType.User,
+ required: true,
+ },
+ {
+ name: 'note',
+ description: 'Please provide a note.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ },
+ ],
+ },
+ {
+ name: 'warn',
+ description: 'Warns a user.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'tag_or_id',
+ description: 'Please provide a user tag or ID.',
+ type: ApplicationCommandOptionType.User,
+ required: true,
+ },
+ {
+ name: 'reason',
+ description: 'Please provide a reason.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ },
+ ],
+ },
+ {
+ name: 'timeout',
+ description: 'Timeouts a user.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'tag_or_id',
+ description: 'Please provide a user tag or ID.',
+ type: ApplicationCommandOptionType.User,
+ required: true,
+ },
+ {
+ name: 'duration',
+ description: 'Please provide a duration.',
+ type: ApplicationCommandOptionType.Number,
+ required: true,
+ choices: [
+ { name: '1 minute', value: 60000 },
+ { name: '5 minutes', value: 300000 },
+ { name: '15 minutes', value: 900000 },
+ { name: '30 minutes', value: 1800000 },
+ { name: '1 hour', value: 3600000 },
+ { name: '6 hours', value: 21600000 },
+ { name: '12 hours', value: 43200000 },
+ { name: '1 day', value: 86400000 },
+ { name: '3 days', value: 259200000 },
+ { name: '1 week', value: 604800000 },
+ { name: '2 weeks', value: 1209600000 },
+ { name: '3 weeks', value: 1814400000 },
+ { name: '4 weeks', value: 2419200000 },
+ ],
+ },
+ {
+ name: 'reason',
+ description: 'Please provide a reason.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ },
+ ],
+ },
+ {
+ name: 'remove-timeout',
+ description: 'Removes a timeout from a user.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'tag_or_id',
+ description: 'Please provide a user tag or ID.',
+ type: ApplicationCommandOptionType.User,
+ required: true,
+ },
+ ],
+ },
+ {
+ name: 'ban',
+ description: 'Bans a user.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'tag_or_id',
+ description: 'Please provide a user tag or ID.',
+ type: ApplicationCommandOptionType.User,
+ required: true,
+ },
+ {
+ name: 'reason',
+ description: 'Please provide a reason.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ },
+ {
+ name: 'days_deleted',
+ description: 'Please provide the number of days of messages to delete.',
+ type: ApplicationCommandOptionType.Integer,
+ required: false,
+ min_value: 0,
+ max_value: 7,
+ },
+ ],
+ },
+ {
+ name: 'unban',
+ description: 'Unbans a user.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'id',
+ description: 'Please provide a userID only.',
+ type: ApplicationCommandOptionType.User,
+ required: true,
+ },
+ {
+ name: 'reason',
+ description: 'Please provide a reason.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ },
+ ],
+ },
+ ],
});
export default slashCommand(data, async ({ interaction }) => {
- const subcommandName = interaction.options.getSubcommand();
+ const subcommandName = interaction.options.getSubcommand();
- switch (subcommandName) {
- case 'list':
- const userID = interaction.options.getUser('tag_or_id')?.id;
- await handleListInfraction(interaction, userID, false);
- break;
+ switch (subcommandName) {
+ case 'list': {
+ const userID = interaction.options.getUser('tag_or_id')?.id;
+ await handleListInfraction(interaction, userID, false);
+ break;
+ }
case 'delete':
- await handleDeleteInfraction(interaction);
- break;
+ await handleDeleteInfraction(interaction);
+ break;
case 'note':
- await handleUserNoteInfraction(interaction);
- break;
+ await handleUserNoteInfraction(interaction);
+ break;
case 'warn':
- await handleWarnInfraction(interaction);
- break;
+ await handleWarnInfraction(interaction);
+ break;
case 'timeout':
- await handleTimeoutInfraction(interaction);
- break;
+ await handleTimeoutInfraction(interaction);
+ break;
case 'remove-timeout':
- await handleRemoveTimeoutInfraction(interaction);
- break;
+ await handleRemoveTimeoutInfraction(interaction);
+ break;
case 'ban':
- await handleBanInfraction(interaction);
- break;
+ await handleBanInfraction(interaction);
+ break;
case 'unban':
- await handleUnbanInfraction(interaction);
- break;
+ await handleUnbanInfraction(interaction);
+ break;
default:
- await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
- }
+ await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
+ }
});
diff --git a/src/commands/moderation/listRoleUsers.ts b/src/commands/moderation/listRoleUsers.ts
index 8702463d..763f275d 100644
--- a/src/commands/moderation/listRoleUsers.ts
+++ b/src/commands/moderation/listRoleUsers.ts
@@ -1,71 +1,82 @@
import { ApplicationCommandOptionType, ApplicationCommandType } from 'discord.js';
-import { constantsConfig, Logger, makeEmbed, createPaginatedEmbedHandler, slashCommand, slashCommandStructure } from '../../lib';
+import {
+ constantsConfig,
+ Logger,
+ makeEmbed,
+ createPaginatedEmbedHandler,
+ slashCommand,
+ slashCommandStructure,
+} from '../../lib';
const data = slashCommandStructure({
- name: 'list-role-users',
- description: 'Lists all users with a specific role.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin, moderator roles
- dm_permission: false,
- options: [
- {
- name: 'role',
- description: 'The role to list users for.',
- type: ApplicationCommandOptionType.Role,
- required: true,
- },
- ],
+ name: 'list-role-users',
+ description: 'Lists all users with a specific role.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin, moderator roles
+ dm_permission: false,
+ options: [
+ {
+ name: 'role',
+ description: 'The role to list users for.',
+ type: ApplicationCommandOptionType.Role,
+ required: true,
+ },
+ ],
});
export default slashCommand(data, async ({ interaction }) => {
- await interaction.deferReply();
+ await interaction.deferReply();
- const role = interaction.options.getRole('role');
+ const role = interaction.options.getRole('role');
- if (!role) return interaction.editReply({ content: 'Invalid role!' });
+ if (!role) return interaction.editReply({ content: 'Invalid role!' });
- const roleMembers = role.members.map((member) => ({
- tag: member.user.tag,
- id: member.id,
- }));
+ const roleMembers = role.members.map((member) => ({
+ tag: member.user.tag,
+ id: member.id,
+ }));
- const pageLimit = 50; // 50 per page as discord usernames have a max length of 32 characters. With the ID we don't exceed the 4096 character limit.
- const embeds = [];
- let currentPage = 0;
- let membersAddedToPage = 0;
- let description = '';
- const totalPages = Math.ceil(roleMembers.length / pageLimit);
+ const pageLimit = 50; // 50 per page as discord usernames have a max length of 32 characters. With the ID we don't exceed the 4096 character limit.
+ const embeds = [];
+ let currentPage = 0;
+ let membersAddedToPage = 0;
+ let description = '';
+ const totalPages = Math.ceil(roleMembers.length / pageLimit);
- for (const member of roleMembers) {
- description += `${member.tag} - ID: ${member.id}\n`;
- membersAddedToPage++;
+ for (const member of roleMembers) {
+ description += `${member.tag} - ID: ${member.id}\n`;
+ membersAddedToPage++;
- if (membersAddedToPage >= pageLimit) {
- embeds.push(makeEmbed({
- title: `Role Users | ${role.name} - Page ${currentPage + 1} of ${totalPages}`,
- description,
- }));
- description = '';
- membersAddedToPage = 0;
- currentPage++;
- }
+ if (membersAddedToPage >= pageLimit) {
+ embeds.push(
+ makeEmbed({
+ title: `Role Users | ${role.name} - Page ${currentPage + 1} of ${totalPages}`,
+ description,
+ }),
+ );
+ description = '';
+ membersAddedToPage = 0;
+ currentPage++;
}
+ }
- if (description.trim() !== '') {
- embeds.push(makeEmbed({
- title: `Role Users | ${role.name} - Page ${currentPage + 1} of ${totalPages}`,
- description,
- }));
- }
+ if (description.trim() !== '') {
+ embeds.push(
+ makeEmbed({
+ title: `Role Users | ${role.name} - Page ${currentPage + 1} of ${totalPages}`,
+ description,
+ }),
+ );
+ }
- if (embeds.length === 0) {
- return interaction.editReply({ content: 'No users with this role exist.' });
- }
+ if (embeds.length === 0) {
+ return interaction.editReply({ content: 'No users with this role exist.' });
+ }
- try {
- return createPaginatedEmbedHandler(interaction, embeds);
- } catch (error) {
- Logger.error('Error sending paginated embed', error);
- return interaction.editReply({ content: 'An error occurred while sending the paginated embed.' });
- }
+ try {
+ return createPaginatedEmbedHandler(interaction, embeds);
+ } catch (error) {
+ Logger.error('Error sending paginated embed', error);
+ return interaction.editReply({ content: 'An error occurred while sending the paginated embed.' });
+ }
});
diff --git a/src/commands/moderation/prefixCommands/functions/addCategory.ts b/src/commands/moderation/prefixCommands/functions/addCategory.ts
index 96104d1a..490c7f8b 100644
--- a/src/commands/moderation/prefixCommands/functions/addCategory.ts
+++ b/src/commands/moderation/prefixCommands/functions/addCategory.ts
@@ -1,98 +1,109 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommandCategory, Logger, makeEmbed, loadSinglePrefixCommandCategoryToCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommandCategory,
+ Logger,
+ makeEmbed,
+ loadSinglePrefixCommandCategoryToCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Add Category - No Connection',
- description: 'Could not connect to the database. Unable to add the prefix command category.',
- color: Colors.Red,
+ title: 'Prefix Commands - Add Category - No Connection',
+ description: 'Could not connect to the database. Unable to add the prefix command category.',
+ color: Colors.Red,
});
-const failedEmbed = (category: string) => makeEmbed({
+const failedEmbed = (category: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Category - Failed',
description: `Failed to add the prefix command category ${category}.`,
color: Colors.Red,
-});
+ });
-const alreadyExistsEmbed = (category: string) => makeEmbed({
+const alreadyExistsEmbed = (category: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Category - Already exists',
description: `The prefix command category ${category} already exists. Not adding again.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (category: string) => makeEmbed({
+const successEmbed = (category: string) =>
+ makeEmbed({
title: `Prefix command category ${category} was added successfully.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, category: string, emoji: string, categoryId: string) => makeEmbed({
+const modLogEmbed = (moderator: User, category: string, emoji: string, categoryId: string) =>
+ makeEmbed({
title: 'Prefix command category added',
fields: [
- {
- name: 'Category',
- value: category,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Emoji',
- value: emoji,
- },
+ {
+ name: 'Category',
+ value: category,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Emoji',
+ value: emoji,
+ },
],
footer: { text: `Category ID: ${categoryId}` },
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Add Category - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Add Category - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleAddPrefixCommandCategory(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const name = interaction.options.getString('name')!;
- const emoji = interaction.options.getString('emoji') || '';
- const moderator = interaction.user;
+ const name = interaction.options.getString('name')!;
+ const emoji = interaction.options.getString('emoji') || '';
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- const existingCategory = await PrefixCommandCategory.findOne({ name });
+ const existingCategory = await PrefixCommandCategory.findOne({ name });
- if (!existingCategory) {
- const prefixCommandCategory = new PrefixCommandCategory({
- name,
- emoji,
- });
+ if (!existingCategory) {
+ const prefixCommandCategory = new PrefixCommandCategory({
+ name,
+ emoji,
+ });
+ try {
+ await prefixCommandCategory.save();
+ await loadSinglePrefixCommandCategoryToCache(prefixCommandCategory);
+ await interaction.followUp({ embeds: [successEmbed(name)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await prefixCommandCategory.save();
- await loadSinglePrefixCommandCategoryToCache(prefixCommandCategory);
- await interaction.followUp({ embeds: [successEmbed(name)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name, emoji, prefixCommandCategory.id)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name, emoji, prefixCommandCategory.id)] });
} catch (error) {
- Logger.error(`Failed to add a prefix command category ${name}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(name)], ephemeral: true });
+ Logger.error('Failed to post a message to the mod logs channel:', error);
}
- } else {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(name)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to add a prefix command category ${name}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(name)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [alreadyExistsEmbed(name)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/addChannelPermission.ts b/src/commands/moderation/prefixCommands/functions/addChannelPermission.ts
index 11981a0d..9c92537b 100644
--- a/src/commands/moderation/prefixCommands/functions/addChannelPermission.ts
+++ b/src/commands/moderation/prefixCommands/functions/addChannelPermission.ts
@@ -1,113 +1,125 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommand, Logger, makeEmbed, refreshSinglePrefixCommandCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommand,
+ Logger,
+ makeEmbed,
+ refreshSinglePrefixCommandCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Add Channel - No Connection',
- description: 'Could not connect to the database. Unable to add the prefix command channel.',
- color: Colors.Red,
+ title: 'Prefix Commands - Add Channel - No Connection',
+ description: 'Could not connect to the database. Unable to add the prefix command channel.',
+ color: Colors.Red,
});
-const noCommandEmbed = (command: string) => makeEmbed({
+const noCommandEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Channel - No Command',
description: `Failed to add the prefix command channel for command ${command} as the command does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (command: string, channel: string) => makeEmbed({
+const failedEmbed = (command: string, channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Channel - Failed',
description: `Failed to add the prefix command channel <#${channel}> for command ${command}.`,
color: Colors.Red,
-});
+ });
-const alreadyExistsEmbed = (command: string, channel: string) => makeEmbed({
+const alreadyExistsEmbed = (command: string, channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Channel - Already exists',
description: `A prefix command channel <#${channel}> for command ${command} already exists. Not adding again.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (command: string, channel: string) => makeEmbed({
+const successEmbed = (command: string, channel: string) =>
+ makeEmbed({
title: `Prefix command channel <#${channel}> added for command ${command}.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, command: string, channel: string) => makeEmbed({
+const modLogEmbed = (moderator: User, command: string, channel: string) =>
+ makeEmbed({
title: 'Add prefix command channel permission',
fields: [
- {
- name: 'Command',
- value: command,
- },
- {
- name: 'Channel',
- value: `<#${channel}>`,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
+ {
+ name: 'Command',
+ value: command,
+ },
+ {
+ name: 'Channel',
+ value: `<#${channel}>`,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
],
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Add Channel - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Add Channel - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleAddPrefixCommandChannelPermission(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const command = interaction.options.getString('command')!;
- const channel = interaction.options.getChannel('channel')!;
- const moderator = interaction.user;
+ const command = interaction.options.getString('command')!;
+ const channel = interaction.options.getChannel('channel')!;
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- let foundCommands = await PrefixCommand.find({ name: command });
- if (!foundCommands || foundCommands.length > 1) {
- foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
- }
- if (!foundCommands || foundCommands.length > 1) {
- await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
- return;
- }
- const [foundCommand] = foundCommands;
- const { id: channelId } = channel;
+ let foundCommands = await PrefixCommand.find({ name: command });
+ if (!foundCommands || foundCommands.length > 1) {
+ foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
+ }
+ if (!foundCommands || foundCommands.length > 1) {
+ await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ return;
+ }
+ const [foundCommand] = foundCommands;
+ const { id: channelId } = channel;
- const existingChannelPermission = foundCommand.permissions.channels?.includes(channelId);
- if (!existingChannelPermission) {
- if (!foundCommand.permissions.channels) {
- foundCommand.permissions.channels = [];
- }
- foundCommand.permissions.channels.push(channelId);
+ const existingChannelPermission = foundCommand.permissions.channels?.includes(channelId);
+ if (!existingChannelPermission) {
+ if (!foundCommand.permissions.channels) {
+ foundCommand.permissions.channels = [];
+ }
+ foundCommand.permissions.channels.push(channelId);
+ try {
+ await foundCommand.save();
+ await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
+ await interaction.followUp({ embeds: [successEmbed(command, channelId)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await foundCommand.save();
- await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
- await interaction.followUp({ embeds: [successEmbed(command, channelId)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, channelId)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, channelId)] });
} catch (error) {
- Logger.error(`Failed to add prefix command channel <#${channel}> for command ${command}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(command, channelId)], ephemeral: true });
+ Logger.error('Failed to post a message to the mod logs channel:', error);
}
- } else {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(command, channelId)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to add prefix command channel <#${channel.id}> for command ${command}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(command, channelId)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [alreadyExistsEmbed(command, channelId)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/addCommand.ts b/src/commands/moderation/prefixCommands/functions/addCommand.ts
index 6152db80..493137ac 100644
--- a/src/commands/moderation/prefixCommands/functions/addCommand.ts
+++ b/src/commands/moderation/prefixCommands/functions/addCommand.ts
@@ -1,179 +1,212 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommand, Logger, makeEmbed, PrefixCommandCategory, loadSinglePrefixCommandToCache, PrefixCommandVersion } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommand,
+ Logger,
+ makeEmbed,
+ PrefixCommandCategory,
+ loadSinglePrefixCommandToCache,
+ PrefixCommandVersion,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Add Command - No Connection',
- description: 'Could not connect to the database. Unable to add the prefix command.',
- color: Colors.Red,
+ title: 'Prefix Commands - Add Command - No Connection',
+ description: 'Could not connect to the database. Unable to add the prefix command.',
+ color: Colors.Red,
});
-const failedEmbed = (command: string) => makeEmbed({
+const failedEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Command - Failed',
description: `Failed to add the prefix command ${command}.`,
color: Colors.Red,
-});
+ });
-const wrongFormatEmbed = (invalidString: string) => makeEmbed({
+const wrongFormatEmbed = (invalidString: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Command - Wrong format',
description: `The name and aliases of a command can only contain alphanumerical characters, underscores and dashes. ${invalidString} is invalid.`,
color: Colors.Red,
-});
+ });
-const categoryNotFoundEmbed = (category: string) => makeEmbed({
+const categoryNotFoundEmbed = (category: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Command - Category not found',
description: `The prefix command category ${category} does not exist. Please create it first.`,
color: Colors.Red,
-});
+ });
-const alreadyExistsEmbed = (command: string, reason: string) => makeEmbed({
+const alreadyExistsEmbed = (command: string, reason: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Command - Already exists',
description: `The prefix command ${command} can not be added: ${reason}`,
color: Colors.Red,
-});
+ });
-const successEmbed = (command: string) => makeEmbed({
+const successEmbed = (command: string) =>
+ makeEmbed({
title: `Prefix command ${command} was added successfully.`,
color: Colors.Green,
-});
-
-const modLogEmbed = (moderator: User, command: string, aliases: string[], description: string, isEmbed: boolean, embedColor: string, commandId: string) => makeEmbed({
+ });
+
+const modLogEmbed = (
+ moderator: User,
+ command: string,
+ aliases: string[],
+ description: string,
+ isEmbed: boolean,
+ embedColor: string,
+ commandId: string,
+) =>
+ makeEmbed({
title: 'Prefix command added',
fields: [
- {
- name: 'Command',
- value: command,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Aliases',
- value: aliases.join(','),
- },
- {
- name: 'Description',
- value: description,
- },
- {
- name: 'Is Embed',
- value: isEmbed ? 'Yes' : 'No',
- },
- {
- name: 'Embed Color',
- value: embedColor || '',
- },
+ {
+ name: 'Command',
+ value: command,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Aliases',
+ value: aliases.join(','),
+ },
+ {
+ name: 'Description',
+ value: description,
+ },
+ {
+ name: 'Is Embed',
+ value: isEmbed ? 'Yes' : 'No',
+ },
+ {
+ name: 'Embed Color',
+ value: embedColor || '',
+ },
],
footer: { text: `Command ID: ${commandId}` },
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Add Command - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Add Command - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleAddPrefixCommand(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
-
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
+ await interaction.deferReply({ ephemeral: true });
+
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
+
+ const name = interaction.options.getString('name')?.toLowerCase().trim()!;
+ const category = interaction.options.getString('category')!;
+ const description = interaction.options.getString('description')!;
+ const aliasesString = interaction.options.getString('aliases')?.toLowerCase().trim() || '';
+ const aliases = aliasesString !== '' ? aliasesString.split(',') : [];
+ const isEmbed = interaction.options.getBoolean('is_embed') || false;
+ const embedColor = interaction.options.getString('embed_color') || '';
+ const moderator = interaction.user;
+
+ const nameRegex = /^[\w-]+$/;
+ if (!nameRegex.test(name)) {
+ await interaction.followUp({ embeds: [wrongFormatEmbed(name)], ephemeral: true });
+ return;
+ }
+ for (const alias of aliases) {
+ if (!nameRegex.test(alias)) {
+ // eslint-disable-next-line no-await-in-loop
+ await interaction.followUp({ embeds: [wrongFormatEmbed(alias)], ephemeral: true });
+ return;
}
-
- const name = interaction.options.getString('name')?.toLowerCase().trim()!;
- const category = interaction.options.getString('category')!;
- const description = interaction.options.getString('description')!;
- const aliasesString = interaction.options.getString('aliases')?.toLowerCase().trim() || '';
- const aliases = aliasesString !== '' ? aliasesString.split(',') : [];
- const isEmbed = interaction.options.getBoolean('is_embed') || false;
- const embedColor = interaction.options.getString('embed_color') || '';
- const moderator = interaction.user;
-
- const nameRegex = /^[\w-]+$/;
- if (!nameRegex.test(name)) {
- await interaction.followUp({ embeds: [wrongFormatEmbed(name)], ephemeral: true });
- return;
- }
- for (const alias of aliases) {
- if (!nameRegex.test(alias)) {
- // eslint-disable-next-line no-await-in-loop
- await interaction.followUp({ embeds: [wrongFormatEmbed(alias)], ephemeral: true });
- return;
- }
- }
-
- // Check if command name and alias are unique, additionally check if they do not exist as a version alias.
- const foundCommandName = await PrefixCommand.findOne({
- $or: [
- { name },
- { name: { $in: aliases } },
- { aliases: name },
- { aliases: { $in: aliases } },
- ],
- });
- if (foundCommandName) {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(name, `${name} already exists as a command or alias, or one of the aliases already exists as a command or alias.`)], ephemeral: true });
- return;
- }
- const foundVersion = await PrefixCommandVersion.findOne({
- $or: [
- { alias: name },
- { alias: { $in: aliases } },
- ],
+ }
+
+ // Check if command name and alias are unique, additionally check if they do not exist as a version alias.
+ const foundCommandName = await PrefixCommand.findOne({
+ $or: [{ name }, { name: { $in: aliases } }, { aliases: name }, { aliases: { $in: aliases } }],
+ });
+ if (foundCommandName) {
+ await interaction.followUp({
+ embeds: [
+ alreadyExistsEmbed(
+ name,
+ `${name} already exists as a command or alias, or one of the aliases already exists as a command or alias.`,
+ ),
+ ],
+ ephemeral: true,
});
- if (foundVersion || name.toLowerCase() === 'generic' || aliases.includes('generic')) {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(name, `${name} already exists as a version alias, or one of the aliases already exists as a version alias.`)], ephemeral: true });
- return;
- }
-
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
-
- const foundCategory = await PrefixCommandCategory.findOne({ name: category });
- if (!foundCategory) {
- await interaction.followUp({ embeds: [categoryNotFoundEmbed(category)], ephemeral: true });
- return;
- }
- const { id: categoryId } = foundCategory;
- Logger.info(`categoryId: ${categoryId}`);
-
- const prefixCommand = new PrefixCommand({
- name,
- categoryId,
- aliases,
- description,
- isEmbed,
- embedColor,
- contents: [],
- permissions: {
- roles: [],
- rolesBlocklist: false,
- channels: [],
- channelsBlocklist: false,
- quietErrors: false,
- verboseErrors: false,
- },
+ return;
+ }
+ const foundVersion = await PrefixCommandVersion.findOne({
+ $or: [{ alias: name }, { alias: { $in: aliases } }],
+ });
+ if (foundVersion || name.toLowerCase() === 'generic' || aliases.includes('generic')) {
+ await interaction.followUp({
+ embeds: [
+ alreadyExistsEmbed(
+ name,
+ `${name} already exists as a version alias, or one of the aliases already exists as a version alias.`,
+ ),
+ ],
+ ephemeral: true,
});
- try {
- await prefixCommand.save();
- await loadSinglePrefixCommandToCache(prefixCommand);
- await interaction.followUp({ embeds: [successEmbed(name)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name, aliases, description, isEmbed, embedColor, prefixCommand.id)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
- } catch (error) {
- Logger.error(`Failed to add a prefix command ${name}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(name)], ephemeral: true });
+ return;
+ }
+
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
+
+ const foundCategory = await PrefixCommandCategory.findOne({ name: category });
+ if (!foundCategory) {
+ await interaction.followUp({ embeds: [categoryNotFoundEmbed(category)], ephemeral: true });
+ return;
+ }
+ const { id: categoryId } = foundCategory;
+ Logger.info(`categoryId: ${categoryId}`);
+
+ const prefixCommand = new PrefixCommand({
+ name,
+ categoryId,
+ aliases,
+ description,
+ isEmbed,
+ embedColor,
+ contents: [],
+ permissions: {
+ roles: [],
+ rolesBlocklist: false,
+ channels: [],
+ channelsBlocklist: false,
+ quietErrors: false,
+ verboseErrors: false,
+ },
+ });
+ try {
+ await prefixCommand.save();
+ await loadSinglePrefixCommandToCache(prefixCommand);
+ await interaction.followUp({ embeds: [successEmbed(name)], ephemeral: true });
+ if (modLogsChannel) {
+ try {
+ await modLogsChannel.send({
+ embeds: [modLogEmbed(moderator, name, aliases, description, isEmbed, embedColor, prefixCommand.id)],
+ });
+ } catch (error) {
+ Logger.error('Failed to post a message to the mod logs channel:', error);
+ }
}
+ } catch (error) {
+ Logger.error(`Failed to add a prefix command ${name}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(name)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/addRolePermission.ts b/src/commands/moderation/prefixCommands/functions/addRolePermission.ts
index a0c2b48f..458c9ab5 100644
--- a/src/commands/moderation/prefixCommands/functions/addRolePermission.ts
+++ b/src/commands/moderation/prefixCommands/functions/addRolePermission.ts
@@ -1,113 +1,125 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommand, Logger, makeEmbed, refreshSinglePrefixCommandCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommand,
+ Logger,
+ makeEmbed,
+ refreshSinglePrefixCommandCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Add Role - No Connection',
- description: 'Could not connect to the database. Unable to add the prefix command role.',
- color: Colors.Red,
+ title: 'Prefix Commands - Add Role - No Connection',
+ description: 'Could not connect to the database. Unable to add the prefix command role.',
+ color: Colors.Red,
});
-const noCommandEmbed = (command: string) => makeEmbed({
+const noCommandEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Role - No Command',
description: `Failed to add the prefix command role for command ${command} as the command does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (command: string, roleName: string) => makeEmbed({
+const failedEmbed = (command: string, roleName: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Role - Failed',
description: `Failed to add the prefix command role ${roleName} for command ${command}.`,
color: Colors.Red,
-});
+ });
-const alreadyExistsEmbed = (command: string, roleName: string) => makeEmbed({
+const alreadyExistsEmbed = (command: string, roleName: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Role - Already exists',
description: `A prefix command role ${roleName} for command ${command} already exists. Not adding again.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (command: string, roleName: string) => makeEmbed({
+const successEmbed = (command: string, roleName: string) =>
+ makeEmbed({
title: `Prefix command role ${roleName} added for command ${command}.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, command: string, roleName: string) => makeEmbed({
+const modLogEmbed = (moderator: User, command: string, roleName: string) =>
+ makeEmbed({
title: 'Add prefix command role permission',
fields: [
- {
- name: 'Command',
- value: command,
- },
- {
- name: 'Role',
- value: roleName,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
+ {
+ name: 'Command',
+ value: command,
+ },
+ {
+ name: 'Role',
+ value: roleName,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
],
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Add Role - No Mod Log',
- description: 'I can\'t find the mod logs role. Please check the role still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Add Role - No Mod Log',
+ description: "I can't find the mod logs role. Please check the role still exists.",
+ color: Colors.Red,
});
export async function handleAddPrefixCommandRolePermission(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const command = interaction.options.getString('command')!;
- const role = interaction.options.getRole('role')!;
- const moderator = interaction.user;
+ const command = interaction.options.getString('command')!;
+ const role = interaction.options.getRole('role')!;
+ const moderator = interaction.user;
- //Check if the mod logs role exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs role exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- let foundCommands = await PrefixCommand.find({ name: command });
- if (!foundCommands || foundCommands.length > 1) {
- foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
- }
- if (!foundCommands || foundCommands.length > 1) {
- await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
- return;
- }
- const [foundCommand] = foundCommands;
- const { id: roleId, name: roleName } = role;
+ let foundCommands = await PrefixCommand.find({ name: command });
+ if (!foundCommands || foundCommands.length > 1) {
+ foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
+ }
+ if (!foundCommands || foundCommands.length > 1) {
+ await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ return;
+ }
+ const [foundCommand] = foundCommands;
+ const { id: roleId, name: roleName } = role;
- const existingRolePermission = foundCommand.permissions.roles?.includes(roleId);
- if (!existingRolePermission) {
- if (!foundCommand.permissions.roles) {
- foundCommand.permissions.roles = [];
- }
- foundCommand.permissions.roles.push(roleId);
+ const existingRolePermission = foundCommand.permissions.roles?.includes(roleId);
+ if (!existingRolePermission) {
+ if (!foundCommand.permissions.roles) {
+ foundCommand.permissions.roles = [];
+ }
+ foundCommand.permissions.roles.push(roleId);
+ try {
+ await foundCommand.save();
+ await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
+ await interaction.followUp({ embeds: [successEmbed(command, roleName)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await foundCommand.save();
- await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
- await interaction.followUp({ embeds: [successEmbed(command, roleName)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, roleName)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs role: ${error}`);
- }
- }
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, roleName)] });
} catch (error) {
- Logger.error(`Failed to add prefix command role ${roleName} for command ${command}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(command, roleName)], ephemeral: true });
+ Logger.error('Failed to post a message to the mod logs role:', error);
}
- } else {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(command, roleName)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to add prefix command role ${roleName} for command ${command}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(command, roleName)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [alreadyExistsEmbed(command, roleName)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/addVersion.ts b/src/commands/moderation/prefixCommands/functions/addVersion.ts
index 032232e0..2922e79e 100644
--- a/src/commands/moderation/prefixCommands/functions/addVersion.ts
+++ b/src/commands/moderation/prefixCommands/functions/addVersion.ts
@@ -1,142 +1,164 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommandVersion, Logger, makeEmbed, loadSinglePrefixCommandVersionToCache, PrefixCommand } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommandVersion,
+ Logger,
+ makeEmbed,
+ loadSinglePrefixCommandVersionToCache,
+ PrefixCommand,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Add Version - No Connection',
- description: 'Could not connect to the database. Unable to add the prefix command version.',
- color: Colors.Red,
+ title: 'Prefix Commands - Add Version - No Connection',
+ description: 'Could not connect to the database. Unable to add the prefix command version.',
+ color: Colors.Red,
});
-const failedEmbed = (version: string) => makeEmbed({
+const failedEmbed = (version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Version - Failed',
description: `Failed to add the prefix command version ${version}.`,
color: Colors.Red,
-});
+ });
-const wrongFormatEmbed = (invalidString: string) => makeEmbed({
+const wrongFormatEmbed = (invalidString: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Version - Wrong format',
description: `The name and alias of a version can only contain alphanumerical characters, underscores and dashes. "${invalidString}" is invalid.`,
color: Colors.Red,
-});
+ });
-const alreadyExistsEmbed = (version: string, reason: string) => makeEmbed({
+const alreadyExistsEmbed = (version: string, reason: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Version - Already exists',
description: `The prefix command version ${version} already exists: ${reason}`,
color: Colors.Red,
-});
+ });
-const successEmbed = (version: string) => makeEmbed({
+const successEmbed = (version: string) =>
+ makeEmbed({
title: `Prefix command version ${version} was added successfully.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, version: string, emoji: string, alias: string, enabled: boolean, versionId: string) => makeEmbed({
+const modLogEmbed = (
+ moderator: User,
+ version: string,
+ emoji: string,
+ alias: string,
+ enabled: boolean,
+ versionId: string,
+) =>
+ makeEmbed({
title: 'Prefix command version added',
fields: [
- {
- name: 'Version',
- value: version,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Emoji',
- value: emoji,
- },
- {
- name: 'Alias',
- value: alias,
- },
- {
- name: 'Enabled',
- value: enabled ? 'Yes' : 'No',
- },
+ {
+ name: 'Version',
+ value: version,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Emoji',
+ value: emoji,
+ },
+ {
+ name: 'Alias',
+ value: alias,
+ },
+ {
+ name: 'Enabled',
+ value: enabled ? 'Yes' : 'No',
+ },
],
footer: { text: `Version ID: ${versionId}` },
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Add Version - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Add Version - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleAddPrefixCommandVersion(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const name = interaction.options.getString('name')!;
- const emoji = interaction.options.getString('emoji')!;
- const alias = interaction.options.getString('alias')!.toLowerCase();
- const enabled = interaction.options.getBoolean('is_enabled') || false;
- const moderator = interaction.user;
+ const name = interaction.options.getString('name')!;
+ const emoji = interaction.options.getString('emoji')!;
+ const alias = interaction.options.getString('alias')!.toLowerCase();
+ const enabled = interaction.options.getBoolean('is_enabled') || false;
+ const moderator = interaction.user;
- const nameRegex = /^[\w-]+$/;
- if (!nameRegex.test(name)) {
- await interaction.followUp({ embeds: [wrongFormatEmbed(name)], ephemeral: true });
- return;
- }
- if (!nameRegex.test(alias)) {
- await interaction.followUp({ embeds: [wrongFormatEmbed(alias)], ephemeral: true });
- return;
- }
+ const nameRegex = /^[\w-]+$/;
+ if (!nameRegex.test(name)) {
+ await interaction.followUp({ embeds: [wrongFormatEmbed(name)], ephemeral: true });
+ return;
+ }
+ if (!nameRegex.test(alias)) {
+ await interaction.followUp({ embeds: [wrongFormatEmbed(alias)], ephemeral: true });
+ return;
+ }
- // Check if a command or version exists with the same name or alias
- const foundCommandName = await PrefixCommand.findOne({
- $or: [
- { name: alias },
- { aliases: alias },
- ],
+ // Check if a command or version exists with the same name or alias
+ const foundCommandName = await PrefixCommand.findOne({
+ $or: [{ name: alias }, { aliases: alias }],
+ });
+ if (foundCommandName) {
+ await interaction.followUp({
+ embeds: [alreadyExistsEmbed(name, `${alias} already exists as a command or alias.`)],
+ ephemeral: true,
});
- if (foundCommandName) {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(name, `${alias} already exists as a command or alias.`)], ephemeral: true });
- return;
- }
- const foundVersion = await PrefixCommandVersion.findOne({
- $or: [
- { name },
- { alias },
- ],
+ return;
+ }
+ const foundVersion = await PrefixCommandVersion.findOne({
+ $or: [{ name }, { alias }],
+ });
+ if (foundVersion || name.toLowerCase() === 'generic' || alias === 'generic') {
+ await interaction.followUp({
+ embeds: [alreadyExistsEmbed(name, `${alias} already exists as a version alias.`)],
+ ephemeral: true,
});
- if (foundVersion || name.toLowerCase() === 'generic' || alias === 'generic') {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(name, `${alias} already exists as a version alias.`)], ephemeral: true });
- return;
- }
+ return;
+ }
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- const prefixCommandVersion = new PrefixCommandVersion({
- name,
- emoji,
- enabled,
- alias,
- });
- try {
- await prefixCommandVersion.save();
- await loadSinglePrefixCommandVersionToCache(prefixCommandVersion);
- await interaction.followUp({ embeds: [successEmbed(name)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name, emoji, alias, enabled, prefixCommandVersion.id)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
- } catch (error) {
- Logger.error(`Failed to add a prefix command category ${name}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(name)], ephemeral: true });
+ const prefixCommandVersion = new PrefixCommandVersion({
+ name,
+ emoji,
+ enabled,
+ alias,
+ });
+ try {
+ await prefixCommandVersion.save();
+ await loadSinglePrefixCommandVersionToCache(prefixCommandVersion);
+ await interaction.followUp({ embeds: [successEmbed(name)], ephemeral: true });
+ if (modLogsChannel) {
+ try {
+ await modLogsChannel.send({
+ embeds: [modLogEmbed(moderator, name, emoji, alias, enabled, prefixCommandVersion.id)],
+ });
+ } catch (error) {
+ Logger.error('Failed to post a message to the mod logs channel:', error);
+ }
}
+ } catch (error) {
+ Logger.error(`Failed to add a prefix command category ${name}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(name)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/deleteCategory.ts b/src/commands/moderation/prefixCommands/functions/deleteCategory.ts
index 93ed6a69..09fe259c 100644
--- a/src/commands/moderation/prefixCommands/functions/deleteCategory.ts
+++ b/src/commands/moderation/prefixCommands/functions/deleteCategory.ts
@@ -1,94 +1,105 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommandCategory, Logger, makeEmbed, clearSinglePrefixCommandCategoryCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommandCategory,
+ Logger,
+ makeEmbed,
+ clearSinglePrefixCommandCategoryCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Delete Category - No Connection',
- description: 'Could not connect to the database. Unable to delete the prefix command category.',
- color: Colors.Red,
+ title: 'Prefix Commands - Delete Category - No Connection',
+ description: 'Could not connect to the database. Unable to delete the prefix command category.',
+ color: Colors.Red,
});
-const failedEmbed = (categoryId: string) => makeEmbed({
+const failedEmbed = (categoryId: string) =>
+ makeEmbed({
title: 'Prefix Commands - Delete Category - Failed',
description: `Failed to delete the prefix command category with id ${categoryId}.`,
color: Colors.Red,
-});
+ });
-const doesNotExistsEmbed = (category: string) => makeEmbed({
+const doesNotExistsEmbed = (category: string) =>
+ makeEmbed({
title: 'Prefix Commands - Delete Category - Does not exist',
description: `The prefix command category ${category} does not exists. Cannot delete it.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (category: string, categoryId: string) => makeEmbed({
+const successEmbed = (category: string, categoryId: string) =>
+ makeEmbed({
title: `Prefix command category ${category} (${categoryId}) was deleted successfully.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, category: string, emoji: string, categoryId: string) => makeEmbed({
+const modLogEmbed = (moderator: User, category: string, emoji: string, categoryId: string) =>
+ makeEmbed({
title: 'Prefix command category deleted',
fields: [
- {
- name: 'Category',
- value: category,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Emoji',
- value: emoji,
- },
+ {
+ name: 'Category',
+ value: category,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Emoji',
+ value: emoji,
+ },
],
footer: { text: `Category ID: ${categoryId}` },
color: Colors.Red,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Delete Category - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Delete Category - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleDeletePrefixCommandCategory(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const category = interaction.options.getString('category')!;
- const moderator = interaction.user;
+ const category = interaction.options.getString('category')!;
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- const existingCategory = await PrefixCommandCategory.findOne({ name: category });
+ const existingCategory = await PrefixCommandCategory.findOne({ name: category });
- if (existingCategory) {
- const { id: categoryId, name, emoji } = existingCategory;
+ if (existingCategory) {
+ const { id: categoryId, name, emoji } = existingCategory;
+ try {
+ await clearSinglePrefixCommandCategoryCache(existingCategory);
+ await existingCategory.deleteOne();
+ await interaction.followUp({ embeds: [successEmbed(name || '', categoryId)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await clearSinglePrefixCommandCategoryCache(existingCategory);
- await existingCategory.deleteOne();
- await interaction.followUp({ embeds: [successEmbed(name || '', categoryId)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name || '', emoji || '', categoryId)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name || '', emoji || '', categoryId)] });
} catch (error) {
- Logger.error(`Failed to delete a prefix command category with id ${categoryId}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(categoryId)], ephemeral: true });
+ Logger.error('Failed to post a message to the mod logs channel:', error);
}
- } else {
- await interaction.followUp({ embeds: [doesNotExistsEmbed(category)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to delete a prefix command category with id ${categoryId}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(categoryId)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [doesNotExistsEmbed(category)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/deleteChannelDefaultVersion.ts b/src/commands/moderation/prefixCommands/functions/deleteChannelDefaultVersion.ts
index 8f4c21b8..854b1033 100644
--- a/src/commands/moderation/prefixCommands/functions/deleteChannelDefaultVersion.ts
+++ b/src/commands/moderation/prefixCommands/functions/deleteChannelDefaultVersion.ts
@@ -1,89 +1,102 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommandChannelDefaultVersion, Logger, makeEmbed, clearSinglePrefixCommandChannelDefaultVersionCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommandChannelDefaultVersion,
+ Logger,
+ makeEmbed,
+ clearSinglePrefixCommandChannelDefaultVersionCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Unset Default Channel Version - No Connection',
- description: 'Could not connect to the database. Unable to unset the default channel version.',
- color: Colors.Red,
+ title: 'Prefix Commands - Unset Default Channel Version - No Connection',
+ description: 'Could not connect to the database. Unable to unset the default channel version.',
+ color: Colors.Red,
});
-const failedEmbed = (channel: string) => makeEmbed({
+const failedEmbed = (channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Unset Default Channel Version - Failed',
description: `Failed to unset the default channel version with for ${channel}.`,
color: Colors.Red,
-});
+ });
-const doesNotExistsEmbed = (channel: string) => makeEmbed({
+const doesNotExistsEmbed = (channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Unset Default Channel Version - Does not exist',
description: `The default channel version with for ${channel} does not exists. Can not unset it.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (channel: string) => makeEmbed({
+const successEmbed = (channel: string) =>
+ makeEmbed({
title: `Default channel version for channel ${channel} was unset successfully.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, channel: string) => makeEmbed({
+const modLogEmbed = (moderator: User, channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Default Channel Version unset',
fields: [
- {
- name: 'Channel',
- value: channel,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
+ {
+ name: 'Channel',
+ value: channel,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
],
color: Colors.Red,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Unset Default Channel Version - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Unset Default Channel Version - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
-export async function handleDeletePrefixCommandChannelDefaultVersion(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+export async function handleDeletePrefixCommandChannelDefaultVersion(
+ interaction: ChatInputCommandInteraction<'cached'>,
+) {
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const channel = interaction.options.getChannel('channel')!;
- const moderator = interaction.user;
+ const channel = interaction.options.getChannel('channel')!;
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- const { id: channelId, name: channelName } = channel;
- const existingChannelDefaultVersion = await PrefixCommandChannelDefaultVersion.findOne({ channelId });
+ const { id: channelId, name: channelName } = channel;
+ const existingChannelDefaultVersion = await PrefixCommandChannelDefaultVersion.findOne({ channelId });
- if (existingChannelDefaultVersion) {
+ if (existingChannelDefaultVersion) {
+ try {
+ await clearSinglePrefixCommandChannelDefaultVersionCache(existingChannelDefaultVersion);
+ await existingChannelDefaultVersion.deleteOne();
+ await interaction.followUp({ embeds: [successEmbed(channelName)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await clearSinglePrefixCommandChannelDefaultVersionCache(existingChannelDefaultVersion);
- await existingChannelDefaultVersion.deleteOne();
- await interaction.followUp({ embeds: [successEmbed(channelName)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, channelName)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, channelName)] });
} catch (error) {
- Logger.error(`Failed to unset a default channel version for channel ${channelName}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(channelName)], ephemeral: true });
+ Logger.error('Failed to post a message to the mod logs channel:', error);
}
- } else {
- await interaction.followUp({ embeds: [doesNotExistsEmbed(channelName)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to unset a default channel version for channel ${channelName}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(channelName)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [doesNotExistsEmbed(channelName)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/deleteCommand.ts b/src/commands/moderation/prefixCommands/functions/deleteCommand.ts
index 97a8226b..4f9a185a 100644
--- a/src/commands/moderation/prefixCommands/functions/deleteCommand.ts
+++ b/src/commands/moderation/prefixCommands/functions/deleteCommand.ts
@@ -1,106 +1,129 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommand, Logger, makeEmbed, clearSinglePrefixCommandCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommand,
+ Logger,
+ makeEmbed,
+ clearSinglePrefixCommandCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Delete Command - No Connection',
- description: 'Could not connect to the database. Unable to delete the prefix command.',
- color: Colors.Red,
+ title: 'Prefix Commands - Delete Command - No Connection',
+ description: 'Could not connect to the database. Unable to delete the prefix command.',
+ color: Colors.Red,
});
-const failedEmbed = (commandId: string) => makeEmbed({
+const failedEmbed = (commandId: string) =>
+ makeEmbed({
title: 'Prefix Commands - Delete Command - Failed',
description: `Failed to delete the prefix command with id ${commandId}.`,
color: Colors.Red,
-});
+ });
-const doesNotExistsEmbed = (command: string) => makeEmbed({
+const doesNotExistsEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Delete Command - Does not exist',
description: `The prefix command ${command} does not exists. Cannot delete it.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (command: string, commandId: string) => makeEmbed({
+const successEmbed = (command: string, commandId: string) =>
+ makeEmbed({
title: `Prefix command ${command} (${commandId}) was deleted successfully.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, command: string, aliases: string[], description: string, isEmbed: boolean, embedColor: string, commandId: string) => makeEmbed({
+const modLogEmbed = (
+ moderator: User,
+ command: string,
+ aliases: string[],
+ description: string,
+ isEmbed: boolean,
+ embedColor: string,
+ commandId: string,
+) =>
+ makeEmbed({
title: 'Prefix command deleted',
fields: [
- {
- name: 'Command',
- value: command,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Aliases',
- value: aliases.join(','),
- },
- {
- name: 'Description',
- value: description,
- },
- {
- name: 'Is Embed',
- value: isEmbed ? 'Yes' : 'No',
- },
- {
- name: 'Embed Color',
- value: embedColor || '',
- },
+ {
+ name: 'Command',
+ value: command,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Aliases',
+ value: aliases.join(','),
+ },
+ {
+ name: 'Description',
+ value: description,
+ },
+ {
+ name: 'Is Embed',
+ value: isEmbed ? 'Yes' : 'No',
+ },
+ {
+ name: 'Embed Color',
+ value: embedColor || '',
+ },
],
footer: { text: `Command ID: ${commandId}` },
color: Colors.Red,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Delete Command - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Delete Command - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleDeletePrefixCommand(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const command = interaction.options.getString('command')!;
- const moderator = interaction.user;
+ const command = interaction.options.getString('command')!;
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- const existingCommand = await PrefixCommand.findOne({ name: command });
+ const existingCommand = await PrefixCommand.findOne({ name: command });
- if (existingCommand) {
- const { id: commandId, name, description, aliases, isEmbed, embedColor } = existingCommand;
+ if (existingCommand) {
+ const { id: commandId, name, description, aliases, isEmbed, embedColor } = existingCommand;
+ try {
+ await clearSinglePrefixCommandCache(existingCommand);
+ await existingCommand.deleteOne();
+ await interaction.followUp({ embeds: [successEmbed(name || '', commandId)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await clearSinglePrefixCommandCache(existingCommand);
- await existingCommand.deleteOne();
- await interaction.followUp({ embeds: [successEmbed(name || '', commandId)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name || '', aliases, description, isEmbed || false, embedColor || '', commandId)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({
+ embeds: [
+ modLogEmbed(moderator, name || '', aliases, description, isEmbed || false, embedColor || '', commandId),
+ ],
+ });
} catch (error) {
- Logger.error(`Failed to delete a prefix command command with id ${commandId}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(commandId)], ephemeral: true });
+ Logger.error('Failed to post a message to the mod logs channel:', error);
}
- } else {
- await interaction.followUp({ embeds: [doesNotExistsEmbed(command)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to delete a prefix command command with id ${commandId}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(commandId)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [doesNotExistsEmbed(command)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/deleteContent.ts b/src/commands/moderation/prefixCommands/functions/deleteContent.ts
index 2b27df0c..56843531 100644
--- a/src/commands/moderation/prefixCommands/functions/deleteContent.ts
+++ b/src/commands/moderation/prefixCommands/functions/deleteContent.ts
@@ -1,146 +1,171 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, Logger, makeEmbed, PrefixCommand, PrefixCommandVersion, refreshSinglePrefixCommandCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ Logger,
+ makeEmbed,
+ PrefixCommand,
+ PrefixCommandVersion,
+ refreshSinglePrefixCommandCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Delete Content - No Connection',
- description: 'Could not connect to the database. Unable to delete the prefix command content.',
- color: Colors.Red,
+ title: 'Prefix Commands - Delete Content - No Connection',
+ description: 'Could not connect to the database. Unable to delete the prefix command content.',
+ color: Colors.Red,
});
-const noContentEmbed = (command: string, version: string) => makeEmbed({
+const noContentEmbed = (command: string, version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Delete Content - No Content',
description: `Failed to delete command content for command ${command} and version ${version} as the content does not exist.`,
color: Colors.Red,
-});
+ });
-const noCommandEmbed = (command: string) => makeEmbed({
+const noCommandEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Delete Content - No Command',
description: `Failed to delete command content for command ${command} as the command does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const noVersionEmbed = (version: string) => makeEmbed({
+const noVersionEmbed = (version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Delete Content - No Version',
description: `Failed to delete command content for version ${version} as the version does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (version: string) => makeEmbed({
+const failedEmbed = (version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Delete Content - Failed',
description: `Failed to delete the prefix command content with version ${version}.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (command: string, version: string) => makeEmbed({
+const successEmbed = (command: string, version: string) =>
+ makeEmbed({
title: `Prefix command content for command ${command} and version ${version} was deleted successfully.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, commandName: string, versionName: string, title: string, content: string, image: string) => makeEmbed({
+const modLogEmbed = (
+ moderator: User,
+ commandName: string,
+ versionName: string,
+ title: string,
+ content: string,
+ image: string,
+) =>
+ makeEmbed({
title: 'Prefix command content delete',
fields: [
- {
- name: 'Command',
- value: commandName,
- },
- {
- name: 'Version',
- value: versionName,
- },
- {
- name: 'Title',
- value: title,
- },
- {
- name: 'Content',
- value: content,
- },
- {
- name: 'Image',
- value: image,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
+ {
+ name: 'Command',
+ value: commandName,
+ },
+ {
+ name: 'Version',
+ value: versionName,
+ },
+ {
+ name: 'Title',
+ value: title,
+ },
+ {
+ name: 'Content',
+ value: content,
+ },
+ {
+ name: 'Image',
+ value: image,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
],
color: Colors.Red,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Delete Content - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Delete Content - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleDeletePrefixCommandContent(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const command = interaction.options.getString('command')!;
- const version = interaction.options.getString('version')!;
- const moderator = interaction.user;
+ const command = interaction.options.getString('command')!;
+ const version = interaction.options.getString('version')!;
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- const foundCommand = await PrefixCommand.findOne({ name: command });
- if (!foundCommand) {
- await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
- return;
- }
- let versionId = '';
- let foundVersions = null;
- if (version === 'GENERIC' || version === 'generic') {
- versionId = 'GENERIC';
+ const foundCommand = await PrefixCommand.findOne({ name: command });
+ if (!foundCommand) {
+ await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ return;
+ }
+ let versionId = '';
+ let foundVersions = null;
+ if (version === 'GENERIC' || version === 'generic') {
+ versionId = 'GENERIC';
+ } else {
+ foundVersions = await PrefixCommandVersion.find({ name: version });
+ if (foundVersions && foundVersions.length === 1) {
+ [{ _id: versionId }] = foundVersions;
} else {
- foundVersions = await PrefixCommandVersion.find({ name: version });
- if (foundVersions && foundVersions.length === 1) {
- [{ _id: versionId }] = foundVersions;
- } else {
- await interaction.followUp({ embeds: [noVersionEmbed(version)], ephemeral: true });
- return;
- }
+ await interaction.followUp({ embeds: [noVersionEmbed(version)], ephemeral: true });
+ return;
}
- const existingContent = foundCommand.contents.find((content) => content.versionId.toString() === versionId.toString());
+ }
+ const existingContent = foundCommand.contents.find(
+ (content) => content.versionId.toString() === versionId.toString(),
+ );
- if (foundCommand && existingContent) {
- const { title, content, image } = existingContent;
- const { name: commandName } = foundCommand;
- let versionName = '';
- if (versionId !== 'GENERIC') {
- const foundVersion = await PrefixCommandVersion.findById(versionId);
- if (!foundVersion) {
- return;
- }
- versionName = foundVersion.name || '';
- }
+ if (foundCommand && existingContent) {
+ const { title, content, image } = existingContent;
+ const { name: commandName } = foundCommand;
+ let versionName = '';
+ if (versionId !== 'GENERIC') {
+ const foundVersion = await PrefixCommandVersion.findById(versionId);
+ if (!foundVersion) {
+ return;
+ }
+ versionName = foundVersion.name || '';
+ }
+ try {
+ foundCommand.contents.find((con) => con.versionId.toString() === versionId.toString())?.deleteOne();
+ await foundCommand.save();
+ await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
+ await interaction.followUp({ embeds: [successEmbed(`${commandName}`, `${versionName}`)], ephemeral: true });
+ if (modLogsChannel) {
try {
- foundCommand.contents.find((con) => con.versionId.toString() === versionId.toString())?.deleteOne();
- await foundCommand.save();
- await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
- await interaction.followUp({ embeds: [successEmbed(`${commandName}`, `${versionName}`)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, `${commandName}`, `${versionName}`, `${title}`, `${content}`, `${image}`)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({
+ embeds: [modLogEmbed(moderator, `${commandName}`, `${versionName}`, `${title}`, `${content}`, `${image}`)],
+ });
} catch (error) {
- Logger.error(`Failed to delete a prefix command content with version ${version}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(version)], ephemeral: true });
+ Logger.error('Failed to post a message to the mod logs channel:', error);
}
- } else {
- await interaction.followUp({ embeds: [noContentEmbed(command, version)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to delete a prefix command content with version ${version}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(version)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [noContentEmbed(command, version)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/deleteVersion.ts b/src/commands/moderation/prefixCommands/functions/deleteVersion.ts
index d73cd26f..d494ddfb 100644
--- a/src/commands/moderation/prefixCommands/functions/deleteVersion.ts
+++ b/src/commands/moderation/prefixCommands/functions/deleteVersion.ts
@@ -1,150 +1,180 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommandVersion, Logger, makeEmbed, PrefixCommandChannelDefaultVersion, clearSinglePrefixCommandVersionCache, PrefixCommand, refreshSinglePrefixCommandCache, clearSinglePrefixCommandChannelDefaultVersionCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommandVersion,
+ Logger,
+ makeEmbed,
+ PrefixCommandChannelDefaultVersion,
+ clearSinglePrefixCommandVersionCache,
+ PrefixCommand,
+ refreshSinglePrefixCommandCache,
+ clearSinglePrefixCommandChannelDefaultVersionCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Delete Version - No Connection',
- description: 'Could not connect to the database. Unable to delete the prefix command version.',
- color: Colors.Red,
+ title: 'Prefix Commands - Delete Version - No Connection',
+ description: 'Could not connect to the database. Unable to delete the prefix command version.',
+ color: Colors.Red,
});
const contentPresentEmbed = makeEmbed({
- title: 'Prefix Commands - Delete Version - Content Present',
- description: 'There is content present for this command version. Please delete the content first, or use the `force` option to delete the command version and all the command contents for the version.',
- color: Colors.Red,
+ title: 'Prefix Commands - Delete Version - Content Present',
+ description:
+ 'There is content present for this command version. Please delete the content first, or use the `force` option to delete the command version and all the command contents for the version.',
+ color: Colors.Red,
});
const channelDefaultVersionPresentEmbed = makeEmbed({
- title: 'Prefix Commands - Delete Version - Default Channel Versions Present',
- description: 'There is one or more channel with this version selected as its default version. Please change or unset the default version for those channels first, or use the `force` option to delete the command version and all the default channel versions referencing it (making them default back to the GENERIC version).',
- color: Colors.Red,
+ title: 'Prefix Commands - Delete Version - Default Channel Versions Present',
+ description:
+ 'There is one or more channel with this version selected as its default version. Please change or unset the default version for those channels first, or use the `force` option to delete the command version and all the default channel versions referencing it (making them default back to the GENERIC version).',
+ color: Colors.Red,
});
-const failedEmbed = (versionId: string) => makeEmbed({
+const failedEmbed = (versionId: string) =>
+ makeEmbed({
title: 'Prefix Commands - Delete Version - Failed',
description: `Failed to delete the prefix command version with id ${versionId}.`,
color: Colors.Red,
-});
+ });
-const doesNotExistsEmbed = (version: string) => makeEmbed({
+const doesNotExistsEmbed = (version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Delete Version - Does not exist',
description: `The prefix command version ${version} does not exists. Cannot delete it.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (version: string, versionId: string) => makeEmbed({
+const successEmbed = (version: string, versionId: string) =>
+ makeEmbed({
title: `Prefix command version ${version} (${versionId}) was deleted successfully.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, version: string, emoji: string, alias: string, enabled: boolean, versionId: string) => makeEmbed({
+const modLogEmbed = (
+ moderator: User,
+ version: string,
+ emoji: string,
+ alias: string,
+ enabled: boolean,
+ versionId: string,
+) =>
+ makeEmbed({
title: 'Prefix command version deleted',
fields: [
- {
- name: 'Version',
- value: version,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Emoji',
- value: emoji,
- },
- {
- name: 'Alias',
- value: alias,
- },
- {
- name: 'Enabled',
- value: enabled ? 'Yes' : 'No',
- },
+ {
+ name: 'Version',
+ value: version,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Emoji',
+ value: emoji,
+ },
+ {
+ name: 'Alias',
+ value: alias,
+ },
+ {
+ name: 'Enabled',
+ value: enabled ? 'Yes' : 'No',
+ },
],
footer: { text: `Version ID: ${versionId}` },
color: Colors.Red,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Delete Version - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Delete Version - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleDeletePrefixCommandVersion(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const version = interaction.options.getString('version')!;
- const force = interaction.options.getBoolean('force') || false;
- const moderator = interaction.user;
+ const version = interaction.options.getString('version')!;
+ const force = interaction.options.getBoolean('force') || false;
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- const existingVersion = await PrefixCommandVersion.findOne({ name: version });
- if (!existingVersion) {
- await interaction.followUp({ embeds: [doesNotExistsEmbed(version)], ephemeral: true });
- return;
- }
- const { id: versionId } = existingVersion;
- // Find all PrefixCommands with content where version ID == versionId
- const foundCommandsWithContent = await PrefixCommand.find({ 'contents.versionId': versionId });
- if (foundCommandsWithContent && foundCommandsWithContent.length > 0 && !force) {
- await interaction.followUp({ embeds: [contentPresentEmbed], ephemeral: true });
- return;
- }
- const foundChannelDefaultVersions = await PrefixCommandChannelDefaultVersion.find({ versionId });
- if (foundChannelDefaultVersions && foundChannelDefaultVersions.length > 0 && !force) {
- await interaction.followUp({ embeds: [channelDefaultVersionPresentEmbed], ephemeral: true });
- return;
- }
+ const existingVersion = await PrefixCommandVersion.findOne({ name: version });
+ if (!existingVersion) {
+ await interaction.followUp({ embeds: [doesNotExistsEmbed(version)], ephemeral: true });
+ return;
+ }
+ const { id: versionId } = existingVersion;
+ // Find all PrefixCommands with content where version ID == versionId
+ const foundCommandsWithContent = await PrefixCommand.find({ 'contents.versionId': versionId });
+ if (foundCommandsWithContent && foundCommandsWithContent.length > 0 && !force) {
+ await interaction.followUp({ embeds: [contentPresentEmbed], ephemeral: true });
+ return;
+ }
+ const foundChannelDefaultVersions = await PrefixCommandChannelDefaultVersion.find({ versionId });
+ if (foundChannelDefaultVersions && foundChannelDefaultVersions.length > 0 && !force) {
+ await interaction.followUp({ embeds: [channelDefaultVersionPresentEmbed], ephemeral: true });
+ return;
+ }
- if (existingVersion) {
- const { name, emoji, enabled, alias } = existingVersion;
+ if (existingVersion) {
+ const { name, emoji, enabled, alias } = existingVersion;
+ try {
+ if (foundCommandsWithContent && force) {
+ for (const command of foundCommandsWithContent) {
+ const { _id: commandId } = command;
+ // eslint-disable-next-line no-await-in-loop
+ const updatedCommand = await PrefixCommand.findOneAndUpdate(
+ { _id: commandId },
+ { $pull: { contents: { versionId } } },
+ { new: true },
+ );
+ if (updatedCommand) {
+ // eslint-disable-next-line no-await-in-loop
+ await refreshSinglePrefixCommandCache(command, updatedCommand);
+ }
+ }
+ }
+ if (foundChannelDefaultVersions && force) {
+ for (const channelDefaultVersion of foundChannelDefaultVersions) {
+ // eslint-disable-next-line no-await-in-loop
+ await clearSinglePrefixCommandChannelDefaultVersionCache(channelDefaultVersion);
+ // eslint-disable-next-line no-await-in-loop
+ await channelDefaultVersion.deleteOne();
+ }
+ }
+ await clearSinglePrefixCommandVersionCache(existingVersion);
+ await existingVersion.deleteOne();
+ await interaction.followUp({ embeds: [successEmbed(name || '', versionId)], ephemeral: true });
+ if (modLogsChannel) {
try {
- if (foundCommandsWithContent && force) {
- for (const command of foundCommandsWithContent) {
- const { _id: commandId } = command;
- // eslint-disable-next-line no-await-in-loop
- const updatedCommand = await PrefixCommand.findOneAndUpdate({ _id: commandId }, { $pull: { contents: { versionId } } }, { new: true });
- if (updatedCommand) {
- // eslint-disable-next-line no-await-in-loop
- await refreshSinglePrefixCommandCache(command, updatedCommand);
- }
- }
- }
- if (foundChannelDefaultVersions && force) {
- for (const channelDefaultVersion of foundChannelDefaultVersions) {
- // eslint-disable-next-line no-await-in-loop
- await clearSinglePrefixCommandChannelDefaultVersionCache(channelDefaultVersion);
- // eslint-disable-next-line no-await-in-loop
- await channelDefaultVersion.deleteOne();
- }
- }
- await clearSinglePrefixCommandVersionCache(existingVersion);
- await existingVersion.deleteOne();
- await interaction.followUp({ embeds: [successEmbed(name || '', versionId)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name || '', emoji || '', alias || '', enabled || false, versionId)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({
+ embeds: [modLogEmbed(moderator, name || '', emoji || '', alias || '', enabled || false, versionId)],
+ });
} catch (error) {
- Logger.error(`Failed to delete a prefix command version with id ${versionId}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(versionId)], ephemeral: true });
+ Logger.error('Failed to post a message to the mod logs channel:', error);
}
- } else {
- await interaction.followUp({ embeds: [doesNotExistsEmbed(versionId)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to delete a prefix command version with id ${versionId}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(versionId)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [doesNotExistsEmbed(versionId)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/listCategories.ts b/src/commands/moderation/prefixCommands/functions/listCategories.ts
index 588e0921..46c12f8b 100644
--- a/src/commands/moderation/prefixCommands/functions/listCategories.ts
+++ b/src/commands/moderation/prefixCommands/functions/listCategories.ts
@@ -2,58 +2,61 @@ import { APIEmbedField, ChatInputCommandInteraction, Colors } from 'discord.js';
import { getConn, PrefixCommandCategory, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - List Categories - No Connection',
- description: 'Could not connect to the database. Unable to list the prefix command categories.',
- color: Colors.Red,
+ title: 'Prefix Commands - List Categories - No Connection',
+ description: 'Could not connect to the database. Unable to list the prefix command categories.',
+ color: Colors.Red,
});
-const failedEmbed = (searchText: string) => makeEmbed({
+const failedEmbed = (searchText: string) =>
+ makeEmbed({
title: 'Prefix Commands - List Categories - Failed',
description: `Failed to list the prefix command categories with search text: ${searchText}.`,
color: Colors.Red,
-});
+ });
-const noResultsEmbed = (searchText: string) => makeEmbed({
+const noResultsEmbed = (searchText: string) =>
+ makeEmbed({
title: 'Prefix Commands - List Categories - Does not exist',
description: `No prefix command categories found matching the search text: ${searchText}.`,
-});
+ });
-const successEmbed = (searchText: string, fields: APIEmbedField[]) => makeEmbed({
+const successEmbed = (searchText: string, fields: APIEmbedField[]) =>
+ makeEmbed({
title: 'Prefix Commands - Categories',
description: searchText ? `Matching search: ${searchText} - Maximum of 20 shown` : 'Maximum of 20 shown',
fields,
color: Colors.Green,
-});
+ });
export async function handleListPrefixCommandCategories(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
-
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
+ await interaction.deferReply({ ephemeral: true });
+
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
+
+ const searchText = interaction.options.getString('search_text') || '';
+ const foundCategories = await PrefixCommandCategory.find({ name: { $regex: searchText, $options: 'i' } });
+
+ if (foundCategories) {
+ const embedFields: APIEmbedField[] = [];
+ for (let i = 0; i < foundCategories.length && i < 20; i++) {
+ const category = foundCategories[i];
+ const { id, name, emoji } = category;
+ embedFields.push({
+ name: `${name} - ${emoji}`,
+ value: `${id}`,
+ });
}
-
- const searchText = interaction.options.getString('search_text') || '';
- const foundCategories = await PrefixCommandCategory.find({ name: { $regex: searchText, $options: 'i' } });
-
- if (foundCategories) {
- const embedFields: APIEmbedField[] = [];
- for (let i = 0; i < foundCategories.length && i < 20; i++) {
- const category = foundCategories[i];
- const { id, name, emoji } = category;
- embedFields.push({
- name: `${name} - ${emoji}`,
- value: `${id}`,
- });
- }
- try {
- await interaction.followUp({ embeds: [successEmbed(searchText, embedFields)], ephemeral: false });
- } catch (error) {
- Logger.error(`Failed to list prefix command categories with search ${searchText}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(searchText)], ephemeral: true });
- }
- } else {
- await interaction.followUp({ embeds: [noResultsEmbed(searchText)], ephemeral: true });
+ try {
+ await interaction.followUp({ embeds: [successEmbed(searchText, embedFields)], ephemeral: false });
+ } catch (error) {
+ Logger.error(`Failed to list prefix command categories with search ${searchText}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(searchText)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [noResultsEmbed(searchText)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/listCommands.ts b/src/commands/moderation/prefixCommands/functions/listCommands.ts
index b48c830a..d03e717e 100644
--- a/src/commands/moderation/prefixCommands/functions/listCommands.ts
+++ b/src/commands/moderation/prefixCommands/functions/listCommands.ts
@@ -2,58 +2,61 @@ import { APIEmbedField, ChatInputCommandInteraction, Colors } from 'discord.js';
import { getConn, PrefixCommand, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - List Commands - No Connection',
- description: 'Could not connect to the database. Unable to list the prefix commands.',
- color: Colors.Red,
+ title: 'Prefix Commands - List Commands - No Connection',
+ description: 'Could not connect to the database. Unable to list the prefix commands.',
+ color: Colors.Red,
});
-const failedEmbed = (searchText: string) => makeEmbed({
+const failedEmbed = (searchText: string) =>
+ makeEmbed({
title: 'Prefix Commands - List Commands - Failed',
description: `Failed to list the prefix commands with search text: ${searchText}.`,
color: Colors.Red,
-});
+ });
-const noResultsEmbed = (searchText: string) => makeEmbed({
+const noResultsEmbed = (searchText: string) =>
+ makeEmbed({
title: 'Prefix Commands - List Commands - Does not exist',
description: `No prefix commands found matching the search text: ${searchText}.`,
-});
+ });
-const successEmbed = (searchText: string, fields: APIEmbedField[]) => makeEmbed({
+const successEmbed = (searchText: string, fields: APIEmbedField[]) =>
+ makeEmbed({
title: 'Prefix Commands',
description: searchText ? `Matching search: ${searchText} - Maximum of 20 shown` : 'Maximum of 20 shown',
fields,
color: Colors.Green,
-});
+ });
export async function handleListPrefixCommands(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
-
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
+ await interaction.deferReply({ ephemeral: true });
+
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
+
+ const searchText = interaction.options.getString('search_text') || '';
+ const foundCommands = await PrefixCommand.find({ name: { $regex: searchText, $options: 'i' } });
+
+ if (foundCommands) {
+ const embedFields: APIEmbedField[] = [];
+ for (let i = 0; i < foundCommands.length && i < 20; i++) {
+ const command = foundCommands[i];
+ const { name, description, aliases, isEmbed, embedColor } = command;
+ embedFields.push({
+ name: `${name} - ${aliases.join(',')} - ${isEmbed ? 'Embed' : 'No Embed'} - ${embedColor || 'No Color'}`,
+ value: `${description}`,
+ });
}
-
- const searchText = interaction.options.getString('search_text') || '';
- const foundCommands = await PrefixCommand.find({ name: { $regex: searchText, $options: 'i' } });
-
- if (foundCommands) {
- const embedFields: APIEmbedField[] = [];
- for (let i = 0; i < foundCommands.length && i < 20; i++) {
- const command = foundCommands[i];
- const { name, description, aliases, isEmbed, embedColor } = command;
- embedFields.push({
- name: `${name} - ${aliases.join(',')} - ${isEmbed ? 'Embed' : 'No Embed'} - ${embedColor || 'No Color'}`,
- value: `${description}`,
- });
- }
- try {
- await interaction.followUp({ embeds: [successEmbed(searchText, embedFields)], ephemeral: false });
- } catch (error) {
- Logger.error(`Failed to list prefix command commands with search ${searchText}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(searchText)], ephemeral: true });
- }
- } else {
- await interaction.followUp({ embeds: [noResultsEmbed(searchText)], ephemeral: true });
+ try {
+ await interaction.followUp({ embeds: [successEmbed(searchText, embedFields)], ephemeral: false });
+ } catch (error) {
+ Logger.error(`Failed to list prefix command commands with search ${searchText}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(searchText)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [noResultsEmbed(searchText)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/listVersions.ts b/src/commands/moderation/prefixCommands/functions/listVersions.ts
index f1023038..12d3e31e 100644
--- a/src/commands/moderation/prefixCommands/functions/listVersions.ts
+++ b/src/commands/moderation/prefixCommands/functions/listVersions.ts
@@ -2,58 +2,61 @@ import { APIEmbedField, ChatInputCommandInteraction, Colors } from 'discord.js';
import { getConn, PrefixCommandVersion, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - List Versions - No Connection',
- description: 'Could not connect to the database. Unable to list the prefix command versions.',
- color: Colors.Red,
+ title: 'Prefix Commands - List Versions - No Connection',
+ description: 'Could not connect to the database. Unable to list the prefix command versions.',
+ color: Colors.Red,
});
-const failedEmbed = (searchText: string) => makeEmbed({
+const failedEmbed = (searchText: string) =>
+ makeEmbed({
title: 'Prefix Commands - List Versions - Failed',
description: `Failed to list the prefix command versions with search text: ${searchText}.`,
color: Colors.Red,
-});
+ });
-const noResultsEmbed = (searchText: string) => makeEmbed({
+const noResultsEmbed = (searchText: string) =>
+ makeEmbed({
title: 'Prefix Commands - List Versions - Does not exist',
description: `No prefix command versions found matching the search text: ${searchText}.`,
-});
+ });
-const successEmbed = (searchText: string, fields: APIEmbedField[]) => makeEmbed({
+const successEmbed = (searchText: string, fields: APIEmbedField[]) =>
+ makeEmbed({
title: 'Prefix Commands - Versions',
description: searchText ? `Matching search: ${searchText} - Maximum of 20 shown` : 'Maximum of 20 shown',
fields,
color: Colors.Green,
-});
+ });
export async function handleListPrefixCommandVersions(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
-
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
+ await interaction.deferReply({ ephemeral: true });
+
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
+
+ const searchText = interaction.options.getString('search_text') || '';
+ const foundVersions = await PrefixCommandVersion.find({ name: { $regex: searchText, $options: 'i' } });
+
+ if (foundVersions) {
+ const embedFields: APIEmbedField[] = [];
+ for (let i = 0; i < foundVersions.length && i < 20; i++) {
+ const version = foundVersions[i];
+ const { id, name, emoji, enabled, alias } = version;
+ embedFields.push({
+ name: `${name} - ${emoji} - ${enabled ? 'Enabled' : 'Disabled'} - ${alias}`,
+ value: `${id}`,
+ });
}
-
- const searchText = interaction.options.getString('search_text') || '';
- const foundVersions = await PrefixCommandVersion.find({ name: { $regex: searchText, $options: 'i' } });
-
- if (foundVersions) {
- const embedFields: APIEmbedField[] = [];
- for (let i = 0; i < foundVersions.length && i < 20; i++) {
- const version = foundVersions[i];
- const { id, name, emoji, enabled, alias } = version;
- embedFields.push({
- name: `${name} - ${emoji} - ${enabled ? 'Enabled' : 'Disabled'} - ${alias}`,
- value: `${id}`,
- });
- }
- try {
- await interaction.followUp({ embeds: [successEmbed(searchText, embedFields)], ephemeral: false });
- } catch (error) {
- Logger.error(`Failed to list prefix command versions with search ${searchText}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(searchText)], ephemeral: true });
- }
- } else {
- await interaction.followUp({ embeds: [noResultsEmbed(searchText)], ephemeral: true });
+ try {
+ await interaction.followUp({ embeds: [successEmbed(searchText, embedFields)], ephemeral: false });
+ } catch (error) {
+ Logger.error(`Failed to list prefix command versions with search ${searchText}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(searchText)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [noResultsEmbed(searchText)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/modifyCategory.ts b/src/commands/moderation/prefixCommands/functions/modifyCategory.ts
index 3d2e6a24..93adc2b8 100644
--- a/src/commands/moderation/prefixCommands/functions/modifyCategory.ts
+++ b/src/commands/moderation/prefixCommands/functions/modifyCategory.ts
@@ -1,100 +1,111 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommandCategory, Logger, makeEmbed, refreshSinglePrefixCommandCategoryCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommandCategory,
+ Logger,
+ makeEmbed,
+ refreshSinglePrefixCommandCategoryCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Modify Category - No Connection',
- description: 'Could not connect to the database. Unable to modify the prefix command category.',
- color: Colors.Red,
+ title: 'Prefix Commands - Modify Category - No Connection',
+ description: 'Could not connect to the database. Unable to modify the prefix command category.',
+ color: Colors.Red,
});
-const failedEmbed = (categoryId: string) => makeEmbed({
+const failedEmbed = (categoryId: string) =>
+ makeEmbed({
title: 'Prefix Commands - Modify Category - Failed',
description: `Failed to modify the prefix command category with id ${categoryId}.`,
color: Colors.Red,
-});
+ });
-const doesNotExistsEmbed = (category: string) => makeEmbed({
+const doesNotExistsEmbed = (category: string) =>
+ makeEmbed({
title: 'Prefix Commands - Modify Category - Does not exist',
description: `The prefix command category ${category} does not exists. Cannot modify it.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (category: string, categoryId: string) => makeEmbed({
+const successEmbed = (category: string, categoryId: string) =>
+ makeEmbed({
title: `Prefix command category ${category} (${categoryId}) was modified successfully.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, category: string, emoji: string, categoryId: string) => makeEmbed({
+const modLogEmbed = (moderator: User, category: string, emoji: string, categoryId: string) =>
+ makeEmbed({
title: 'Prefix command category modified',
fields: [
- {
- name: 'Category',
- value: category,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Emoji',
- value: emoji,
- },
+ {
+ name: 'Category',
+ value: category,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Emoji',
+ value: emoji,
+ },
],
footer: { text: `Category ID: ${categoryId}` },
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Modified Category - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Modified Category - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleModifyPrefixCommandCategory(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const category = interaction.options.getString('category')!;
- const name = interaction.options.getString('name') || '';
- const emoji = interaction.options.getString('emoji') || '';
- const moderator = interaction.user;
+ const category = interaction.options.getString('category')!;
+ const name = interaction.options.getString('name') || '';
+ const emoji = interaction.options.getString('emoji') || '';
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- const existingCategory = await PrefixCommandCategory.findOne({ name: category });
+ const existingCategory = await PrefixCommandCategory.findOne({ name: category });
- if (existingCategory) {
- const { id: categoryId } = existingCategory;
- const oldCategory = existingCategory.$clone();
- existingCategory.name = name || existingCategory.name;
- existingCategory.emoji = emoji || existingCategory.emoji;
+ if (existingCategory) {
+ const { id: categoryId } = existingCategory;
+ const oldCategory = existingCategory.$clone();
+ existingCategory.name = name || existingCategory.name;
+ existingCategory.emoji = emoji || existingCategory.emoji;
+ try {
+ await existingCategory.save();
+ const { name, emoji } = existingCategory;
+ await refreshSinglePrefixCommandCategoryCache(oldCategory, existingCategory);
+ await interaction.followUp({ embeds: [successEmbed(name, categoryId)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await existingCategory.save();
- const { name, emoji } = existingCategory;
- await refreshSinglePrefixCommandCategoryCache(oldCategory, existingCategory);
- await interaction.followUp({ embeds: [successEmbed(name, categoryId)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name, emoji || '', categoryId)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name, emoji || '', categoryId)] });
} catch (error) {
- Logger.error(`Failed to modify a prefix command category with id ${categoryId}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(categoryId)], ephemeral: true });
+ Logger.error(`Failed to post a message to the mod logs channel:`, error);
}
- } else {
- await interaction.followUp({ embeds: [doesNotExistsEmbed(category)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to modify a prefix command category with id ${categoryId}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(categoryId)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [doesNotExistsEmbed(category)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/modifyCommand.ts b/src/commands/moderation/prefixCommands/functions/modifyCommand.ts
index 13e85472..543a6628 100644
--- a/src/commands/moderation/prefixCommands/functions/modifyCommand.ts
+++ b/src/commands/moderation/prefixCommands/functions/modifyCommand.ts
@@ -1,205 +1,250 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommand, Logger, makeEmbed, PrefixCommandCategory, refreshSinglePrefixCommandCache, PrefixCommandVersion } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommand,
+ Logger,
+ makeEmbed,
+ PrefixCommandCategory,
+ refreshSinglePrefixCommandCache,
+ PrefixCommandVersion,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Modify Command - No Connection',
- description: 'Could not connect to the database. Unable to modify the prefix command.',
- color: Colors.Red,
+ title: 'Prefix Commands - Modify Command - No Connection',
+ description: 'Could not connect to the database. Unable to modify the prefix command.',
+ color: Colors.Red,
});
-const failedEmbed = (commandId: string) => makeEmbed({
+const failedEmbed = (commandId: string) =>
+ makeEmbed({
title: 'Prefix Commands - Modify Command - Failed',
description: `Failed to modify the prefix command with id ${commandId}.`,
color: Colors.Red,
-});
+ });
-const wrongFormatEmbed = (invalidString: string) => makeEmbed({
+const wrongFormatEmbed = (invalidString: string) =>
+ makeEmbed({
title: 'Prefix Commands - Modify Command - Wrong format',
description: `The name and aliases of a command can only contain alphanumerical characters, underscores and dashes. "${invalidString}" is invalid.`,
color: Colors.Red,
-});
+ });
-const categoryNotFoundEmbed = (category: string) => makeEmbed({
+const categoryNotFoundEmbed = (category: string) =>
+ makeEmbed({
title: 'Prefix Commands - Modify Command - Category not found',
description: `The prefix command category ${category} does not exist. Please create it first.`,
color: Colors.Red,
-});
+ });
-const doesNotExistsEmbed = (command: string) => makeEmbed({
+const doesNotExistsEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Modify Command - Does not exist',
description: `The prefix command ${command} does not exists. Cannot modify it.`,
color: Colors.Red,
-});
+ });
-const alreadyExistsEmbed = (command: string, reason: string) => makeEmbed({
+const alreadyExistsEmbed = (command: string, reason: string) =>
+ makeEmbed({
title: 'Prefix Commands - Modify Command - Already exists',
description: `The prefix command ${command} can not be modified: ${reason}`,
color: Colors.Red,
-});
+ });
-const successEmbed = (command: string, commandId: string) => makeEmbed({
+const successEmbed = (command: string, commandId: string) =>
+ makeEmbed({
title: `Prefix command ${command} (${commandId}) was modified successfully.`,
color: Colors.Green,
-});
-
-const modLogEmbed = (moderator: User, command: string, aliases: string[], description: string, isEmbed: boolean, embedColor: string, commandId: string) => makeEmbed({
+ });
+
+const modLogEmbed = (
+ moderator: User,
+ command: string,
+ aliases: string[],
+ description: string,
+ isEmbed: boolean,
+ embedColor: string,
+ commandId: string,
+) =>
+ makeEmbed({
title: 'Prefix command modified',
fields: [
- {
- name: 'Command',
- value: command,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Aliases',
- value: aliases.join(','),
- },
- {
- name: 'Description',
- value: description,
- },
- {
- name: 'Is Embed',
- value: isEmbed ? 'Yes' : 'No',
- },
- {
- name: 'Embed Color',
- value: embedColor || '',
- },
+ {
+ name: 'Command',
+ value: command,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Aliases',
+ value: aliases.join(','),
+ },
+ {
+ name: 'Description',
+ value: description,
+ },
+ {
+ name: 'Is Embed',
+ value: isEmbed ? 'Yes' : 'No',
+ },
+ {
+ name: 'Embed Color',
+ value: embedColor || '',
+ },
],
footer: { text: `Command ID: ${commandId}` },
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Modified Command - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Modified Command - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleModifyPrefixCommand(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
-
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
-
- const command = interaction.options.getString('command')!;
- const name = interaction.options.getString('name')?.toLowerCase().trim() || '';
- const category = interaction.options.getString('category') || '';
- const description = interaction.options.getString('description') || '';
- const aliasesString = interaction.options.getString('aliases')?.toLowerCase().trim() || '';
- const aliases = aliasesString !== '' ? aliasesString.split(',') : [];
- const isEmbed = interaction.options.getBoolean('is_embed');
- const embedColor = interaction.options.getString('embed_color') || '';
- const moderator = interaction.user;
-
- const nameRegex = /^[\w-]+$/;
- if (name && !nameRegex.test(name)) {
- await interaction.followUp({ embeds: [wrongFormatEmbed(name)], ephemeral: true });
- return;
+ await interaction.deferReply({ ephemeral: true });
+
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
+
+ const command = interaction.options.getString('command')!;
+ const name = interaction.options.getString('name')?.toLowerCase().trim() || '';
+ const category = interaction.options.getString('category') || '';
+ const description = interaction.options.getString('description') || '';
+ const aliasesString = interaction.options.getString('aliases')?.toLowerCase().trim() || '';
+ const aliases = aliasesString !== '' ? aliasesString.split(',') : [];
+ const isEmbed = interaction.options.getBoolean('is_embed');
+ const embedColor = interaction.options.getString('embed_color') || '';
+ const moderator = interaction.user;
+
+ const nameRegex = /^[\w-]+$/;
+ if (name && !nameRegex.test(name)) {
+ await interaction.followUp({ embeds: [wrongFormatEmbed(name)], ephemeral: true });
+ return;
+ }
+ for (const alias of aliases) {
+ if (!nameRegex.test(alias)) {
+ // eslint-disable-next-line no-await-in-loop
+ await interaction.followUp({ embeds: [wrongFormatEmbed(alias)], ephemeral: true });
+ return;
}
- for (const alias of aliases) {
- if (!nameRegex.test(alias)) {
- // eslint-disable-next-line no-await-in-loop
- await interaction.followUp({ embeds: [wrongFormatEmbed(alias)], ephemeral: true });
- return;
- }
+ }
+ // Check if command name and alias are unique, additionally check if they do not exist as a version alias.
+ if (name) {
+ const foundCommandName = await PrefixCommand.findOne({
+ name: { $ne: command },
+ $or: [{ name }, { aliases: name }],
+ });
+ if (foundCommandName) {
+ await interaction.followUp({
+ embeds: [alreadyExistsEmbed(command, `${name} already exists as a different command or alias.`)],
+ ephemeral: true,
+ });
+ return;
}
- // Check if command name and alias are unique, additionally check if they do not exist as a version alias.
- if (name) {
- const foundCommandName = await PrefixCommand.findOne({
- name: { $ne: command },
- $or: [
- { name },
- { aliases: name },
- ],
- });
- if (foundCommandName) {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(command, `${name} already exists as a different command or alias.`)], ephemeral: true });
- return;
- }
- const foundVersion = await PrefixCommandVersion.findOne({
- $or: [
- { alias: name },
- ],
- });
- if (foundVersion || name === 'generic') {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(command, `${name} already exists as a version alias.`)], ephemeral: true });
- return;
- }
+ const foundVersion = await PrefixCommandVersion.findOne({
+ $or: [{ alias: name }],
+ });
+ if (foundVersion || name === 'generic') {
+ await interaction.followUp({
+ embeds: [alreadyExistsEmbed(command, `${name} already exists as a version alias.`)],
+ ephemeral: true,
+ });
+ return;
}
- if (aliases.length > 0) {
- const foundCommandName = await PrefixCommand.findOne({
- name: { $ne: command },
- $or: [
- { name: { $in: aliases } },
- { aliases: { $in: aliases } },
- ],
- });
- if (foundCommandName) {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(command, 'The new aliases contain an alias that already exists as a different command or alias.')], ephemeral: true });
- return;
- }
- const foundVersion = await PrefixCommandVersion.findOne({
- $or: [
- { alias: { $in: aliases } },
- ],
- });
- if (foundVersion || aliases.includes('generic')) {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(command, 'The new aliases contain an alias that already exists as a version alias.')], ephemeral: true });
- return;
- }
+ }
+ if (aliases.length > 0) {
+ const foundCommandName = await PrefixCommand.findOne({
+ name: { $ne: command },
+ $or: [{ name: { $in: aliases } }, { aliases: { $in: aliases } }],
+ });
+ if (foundCommandName) {
+ await interaction.followUp({
+ embeds: [
+ alreadyExistsEmbed(
+ command,
+ 'The new aliases contain an alias that already exists as a different command or alias.',
+ ),
+ ],
+ ephemeral: true,
+ });
+ return;
}
-
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ const foundVersion = await PrefixCommandVersion.findOne({
+ $or: [{ alias: { $in: aliases } }],
+ });
+ if (foundVersion || aliases.includes('generic')) {
+ await interaction.followUp({
+ embeds: [
+ alreadyExistsEmbed(command, 'The new aliases contain an alias that already exists as a version alias.'),
+ ],
+ ephemeral: true,
+ });
+ return;
}
-
- let foundCategory;
- if (category !== '') {
- [foundCategory] = await PrefixCommandCategory.find({ name: category });
- if (!foundCategory) {
- await interaction.followUp({ embeds: [categoryNotFoundEmbed(category)], ephemeral: true });
- return;
- }
+ }
+
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
+
+ let foundCategory;
+ if (category !== '') {
+ [foundCategory] = await PrefixCommandCategory.find({ name: category });
+ if (!foundCategory) {
+ await interaction.followUp({ embeds: [categoryNotFoundEmbed(category)], ephemeral: true });
+ return;
}
- const existingCommand = await PrefixCommand.findOne({ name: command });
-
- if (existingCommand) {
- const { id: commandId } = existingCommand;
- const oldCommand = existingCommand.$clone();
- existingCommand.name = name || existingCommand.name;
- existingCommand.categoryId = foundCategory?.id || existingCommand.categoryId;
- existingCommand.description = description || existingCommand.description;
- existingCommand.aliases = aliases.length > 0 ? aliases : existingCommand.aliases;
- existingCommand.isEmbed = isEmbed !== null ? isEmbed : existingCommand.isEmbed;
- existingCommand.embedColor = embedColor || existingCommand.embedColor;
+ }
+ const existingCommand = await PrefixCommand.findOne({ name: command });
+
+ if (existingCommand) {
+ const { id: commandId } = existingCommand;
+ const oldCommand = existingCommand.$clone();
+ existingCommand.name = name || existingCommand.name;
+ existingCommand.categoryId = foundCategory?.id || existingCommand.categoryId;
+ existingCommand.description = description || existingCommand.description;
+ existingCommand.aliases = aliases.length > 0 ? aliases : existingCommand.aliases;
+ existingCommand.isEmbed = isEmbed !== null ? isEmbed : existingCommand.isEmbed;
+ existingCommand.embedColor = embedColor || existingCommand.embedColor;
+ try {
+ await existingCommand.save();
+ const { name, description, aliases, isEmbed, embedColor } = existingCommand;
+ await refreshSinglePrefixCommandCache(oldCommand, existingCommand);
+ await interaction.followUp({ embeds: [successEmbed(name, commandId)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await existingCommand.save();
- const { name, description, aliases, isEmbed, embedColor } = existingCommand;
- await refreshSinglePrefixCommandCache(oldCommand, existingCommand);
- await interaction.followUp({ embeds: [successEmbed(name, commandId)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name, aliases, description, isEmbed || false, embedColor || '', existingCommand.id)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({
+ embeds: [
+ modLogEmbed(
+ moderator,
+ name,
+ aliases,
+ description,
+ isEmbed || false,
+ embedColor || '',
+ existingCommand.id,
+ ),
+ ],
+ });
} catch (error) {
- Logger.error(`Failed to modify a prefix command command with id ${commandId}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(commandId)], ephemeral: true });
+ Logger.error(`Failed to post a message to the mod logs channel:`, error);
}
- } else {
- await interaction.followUp({ embeds: [doesNotExistsEmbed(command)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to modify a prefix command command with id ${commandId}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(commandId)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [doesNotExistsEmbed(command)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/modifyVersion.ts b/src/commands/moderation/prefixCommands/functions/modifyVersion.ts
index eeceba92..869474f4 100644
--- a/src/commands/moderation/prefixCommands/functions/modifyVersion.ts
+++ b/src/commands/moderation/prefixCommands/functions/modifyVersion.ts
@@ -1,166 +1,195 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommandVersion, Logger, makeEmbed, refreshSinglePrefixCommandVersionCache, PrefixCommand } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommandVersion,
+ Logger,
+ makeEmbed,
+ refreshSinglePrefixCommandVersionCache,
+ PrefixCommand,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Modify Version - No Connection',
- description: 'Could not connect to the database. Unable to modify the prefix command version.',
- color: Colors.Red,
+ title: 'Prefix Commands - Modify Version - No Connection',
+ description: 'Could not connect to the database. Unable to modify the prefix command version.',
+ color: Colors.Red,
});
-const failedEmbed = (versionId: string) => makeEmbed({
+const failedEmbed = (versionId: string) =>
+ makeEmbed({
title: 'Prefix Commands - Modify Version - Failed',
description: `Failed to modify the prefix command version with id ${versionId}.`,
color: Colors.Red,
-});
+ });
-const wrongFormatEmbed = (invalidString: string) => makeEmbed({
+const wrongFormatEmbed = (invalidString: string) =>
+ makeEmbed({
title: 'Prefix Commands - Modify Version - Wrong format',
description: `The name and alias of a version can only contain alphanumerical characters, underscores and dashes. "${invalidString}" is invalid.`,
color: Colors.Red,
-});
+ });
-const doesNotExistsEmbed = (version: string) => makeEmbed({
+const doesNotExistsEmbed = (version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Modify Version - Does not exist',
description: `The prefix command version ${version} does not exists. Cannot modify it.`,
color: Colors.Red,
-});
+ });
-const alreadyExistsEmbed = (version: string, reason: string) => makeEmbed({
+const alreadyExistsEmbed = (version: string, reason: string) =>
+ makeEmbed({
title: 'Prefix Commands - Add Version - Already exists',
description: `The prefix command version ${version} already exists: ${reason}`,
color: Colors.Red,
-});
+ });
-const successEmbed = (version: string, versionId: string) => makeEmbed({
+const successEmbed = (version: string, versionId: string) =>
+ makeEmbed({
title: `Prefix command version ${version} (${versionId}) was modified successfully.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, version: string, emoji: string, alias: string, enabled: boolean, versionId: string) => makeEmbed({
+const modLogEmbed = (
+ moderator: User,
+ version: string,
+ emoji: string,
+ alias: string,
+ enabled: boolean,
+ versionId: string,
+) =>
+ makeEmbed({
title: 'Prefix command version modified',
fields: [
- {
- name: 'Version',
- value: version,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
- {
- name: 'Emoji',
- value: emoji,
- },
- {
- name: 'Alias',
- value: alias,
- },
- {
- name: 'Enabled',
- value: enabled ? 'Yes' : 'No',
- },
+ {
+ name: 'Version',
+ value: version,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
+ {
+ name: 'Emoji',
+ value: emoji,
+ },
+ {
+ name: 'Alias',
+ value: alias,
+ },
+ {
+ name: 'Enabled',
+ value: enabled ? 'Yes' : 'No',
+ },
],
footer: { text: `Version ID: ${versionId}` },
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Modified Version - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Modified Version - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleModifyPrefixCommandVersion(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const version = interaction.options.getString('version')!;
- const name = interaction.options.getString('name') || '';
- const emoji = interaction.options.getString('emoji') || '';
- const alias = interaction.options.getString('alias')?.toLowerCase() || '';
- const enabled = interaction.options.getBoolean('is_enabled');
- const moderator = interaction.user;
+ const version = interaction.options.getString('version')!;
+ const name = interaction.options.getString('name') || '';
+ const emoji = interaction.options.getString('emoji') || '';
+ const alias = interaction.options.getString('alias')?.toLowerCase() || '';
+ const enabled = interaction.options.getBoolean('is_enabled');
+ const moderator = interaction.user;
- const nameRegex = /^[\w-]+$/;
- if (name && !nameRegex.test(name)) {
- await interaction.followUp({ embeds: [wrongFormatEmbed(name)], ephemeral: true });
- return;
+ const nameRegex = /^[\w-]+$/;
+ if (name && !nameRegex.test(name)) {
+ await interaction.followUp({ embeds: [wrongFormatEmbed(name)], ephemeral: true });
+ return;
+ }
+ if (alias && !nameRegex.test(alias)) {
+ await interaction.followUp({ embeds: [wrongFormatEmbed(alias)], ephemeral: true });
+ return;
+ }
+ if (name) {
+ const foundVersion = await PrefixCommandVersion.findOne({
+ name: {
+ $ne: version,
+ $eq: name,
+ },
+ });
+ if (foundVersion || name.toLowerCase() === 'generic') {
+ await interaction.followUp({
+ embeds: [alreadyExistsEmbed(version, `${name} already exists as a version.`)],
+ ephemeral: true,
+ });
+ return;
}
- if (alias && !nameRegex.test(alias)) {
- await interaction.followUp({ embeds: [wrongFormatEmbed(alias)], ephemeral: true });
- return;
+ }
+ if (alias) {
+ const foundVersion = await PrefixCommandVersion.findOne({
+ name: { $ne: version },
+ alias,
+ });
+ if (foundVersion || alias === 'generic') {
+ await interaction.followUp({
+ embeds: [alreadyExistsEmbed(version, `${alias} already exists as a version alias.`)],
+ ephemeral: true,
+ });
+ return;
}
- if (name) {
- const foundVersion = await PrefixCommandVersion.findOne({
- name: {
- $ne: version,
- $eq: name,
- },
- });
- if (foundVersion || name.toLowerCase() === 'generic') {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(version, `${name} already exists as a version.`)], ephemeral: true });
- return;
- }
- }
- if (alias) {
- const foundVersion = await PrefixCommandVersion.findOne({
- name: { $ne: version },
- alias,
- });
- if (foundVersion || alias === 'generic') {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(version, `${alias} already exists as a version alias.`)], ephemeral: true });
- return;
- }
- const foundCommandName = await PrefixCommand.findOne({
- $or: [
- { name: alias },
- { aliases: alias },
- ],
- });
- if (foundCommandName) {
- await interaction.followUp({ embeds: [alreadyExistsEmbed(version, `${alias} already exists as a command or command alias.`)], ephemeral: true });
- return;
- }
+ const foundCommandName = await PrefixCommand.findOne({
+ $or: [{ name: alias }, { aliases: alias }],
+ });
+ if (foundCommandName) {
+ await interaction.followUp({
+ embeds: [alreadyExistsEmbed(version, `${alias} already exists as a command or command alias.`)],
+ ephemeral: true,
+ });
+ return;
}
+ }
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- const existingVersion = await PrefixCommandVersion.findOne({ name: version });
+ const existingVersion = await PrefixCommandVersion.findOne({ name: version });
- if (existingVersion) {
- const { id: versionId } = existingVersion;
- const oldVersion = existingVersion.$clone();
- existingVersion.name = name || existingVersion.name;
- existingVersion.emoji = emoji || existingVersion.emoji;
- existingVersion.alias = alias || existingVersion.alias;
- existingVersion.enabled = enabled !== null ? enabled : existingVersion.enabled;
+ if (existingVersion) {
+ const { id: versionId } = existingVersion;
+ const oldVersion = existingVersion.$clone();
+ existingVersion.name = name || existingVersion.name;
+ existingVersion.emoji = emoji || existingVersion.emoji;
+ existingVersion.alias = alias || existingVersion.alias;
+ existingVersion.enabled = enabled !== null ? enabled : existingVersion.enabled;
+ try {
+ await existingVersion.save();
+ const { name, emoji, alias, enabled } = existingVersion;
+ await refreshSinglePrefixCommandVersionCache(oldVersion, existingVersion);
+ await interaction.followUp({ embeds: [successEmbed(name, versionId)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await existingVersion.save();
- const { name, emoji, alias, enabled } = existingVersion;
- await refreshSinglePrefixCommandVersionCache(oldVersion, existingVersion);
- await interaction.followUp({ embeds: [successEmbed(name, versionId)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, name, emoji, alias, enabled || false, versionId)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({
+ embeds: [modLogEmbed(moderator, name, emoji, alias, enabled || false, versionId)],
+ });
} catch (error) {
- Logger.error(`Failed to modify a prefix command version with id ${versionId}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(versionId)], ephemeral: true });
+ Logger.error(`Failed to post a message to the mod logs channel:`, error);
}
- } else {
- await interaction.followUp({ embeds: [doesNotExistsEmbed(version)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to modify a prefix command version with id ${versionId}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(versionId)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [doesNotExistsEmbed(version)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/removeChannelPermission.ts b/src/commands/moderation/prefixCommands/functions/removeChannelPermission.ts
index 7b930896..ee97fa3e 100644
--- a/src/commands/moderation/prefixCommands/functions/removeChannelPermission.ts
+++ b/src/commands/moderation/prefixCommands/functions/removeChannelPermission.ts
@@ -1,110 +1,122 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommand, Logger, makeEmbed, refreshSinglePrefixCommandCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommand,
+ Logger,
+ makeEmbed,
+ refreshSinglePrefixCommandCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Remove Channel - No Connection',
- description: 'Could not connect to the database. Unable to remove the prefix command channel.',
- color: Colors.Red,
+ title: 'Prefix Commands - Remove Channel - No Connection',
+ description: 'Could not connect to the database. Unable to remove the prefix command channel.',
+ color: Colors.Red,
});
-const noCommandEmbed = (command: string) => makeEmbed({
+const noCommandEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Remove Channel - No Command',
description: `Failed to remove the prefix command channel for command ${command} as the command does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (command: string, channel: string) => makeEmbed({
+const failedEmbed = (command: string, channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Remove Channel- Failed',
description: `Failed to remove the prefix command channel <#${channel}> for command ${command}.`,
color: Colors.Red,
-});
+ });
-const doesNotExistEmbed = (command: string, channel: string) => makeEmbed({
+const doesNotExistEmbed = (command: string, channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Remove Channel - Does not exist',
description: `A prefix command channel <#${channel}> for command ${command} does not exist.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (command: string, channel: string) => makeEmbed({
+const successEmbed = (command: string, channel: string) =>
+ makeEmbed({
title: `Prefix command channel <#${channel}> removed for command ${command}.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, command: string, channel: string) => makeEmbed({
+const modLogEmbed = (moderator: User, command: string, channel: string) =>
+ makeEmbed({
title: 'Remove prefix command channel permission',
fields: [
- {
- name: 'Command',
- value: command,
- },
- {
- name: 'Channel',
- value: `<#${channel}>`,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
+ {
+ name: 'Command',
+ value: command,
+ },
+ {
+ name: 'Channel',
+ value: `<#${channel}>`,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
],
color: Colors.Red,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Remove Channel - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Remove Channel - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleRemovePrefixCommandChannelPermission(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const command = interaction.options.getString('command')!;
- const channel = interaction.options.getChannel('channel')!;
- const moderator = interaction.user;
+ const command = interaction.options.getString('command')!;
+ const channel = interaction.options.getChannel('channel')!;
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- let foundCommands = await PrefixCommand.find({ name: command });
- if (!foundCommands || foundCommands.length > 1) {
- foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
- }
- if (!foundCommands || foundCommands.length > 1) {
- await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
- return;
- }
- const [foundCommand] = foundCommands;
- const { id: channelId } = channel;
+ let foundCommands = await PrefixCommand.find({ name: command });
+ if (!foundCommands || foundCommands.length > 1) {
+ foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
+ }
+ if (!foundCommands || foundCommands.length > 1) {
+ await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ return;
+ }
+ const [foundCommand] = foundCommands;
+ const { id: channelId } = channel;
- const existingChannelPermission = foundCommand.permissions.channels?.includes(channelId);
- if (existingChannelPermission) {
- foundCommand.permissions.channels = foundCommand.permissions.channels?.filter((id) => id !== channelId);
+ const existingChannelPermission = foundCommand.permissions.channels?.includes(channelId);
+ if (existingChannelPermission) {
+ foundCommand.permissions.channels = foundCommand.permissions.channels?.filter((id) => id !== channelId);
+ try {
+ await foundCommand.save();
+ await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
+ await interaction.followUp({ embeds: [successEmbed(command, channelId)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await foundCommand.save();
- await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
- await interaction.followUp({ embeds: [successEmbed(command, channelId)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, channelId)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, channelId)] });
} catch (error) {
- Logger.error(`Failed to remove prefix command channel <#${channel}> for command ${command}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(command, channelId)], ephemeral: true });
+ Logger.error(`Failed to post a message to the mod logs channel:`, error);
}
- } else {
- await interaction.followUp({ embeds: [doesNotExistEmbed(command, channelId)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to remove prefix command channel <#${channel.id}> for command ${command}`, error);
+ await interaction.followUp({ embeds: [failedEmbed(command, channelId)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [doesNotExistEmbed(command, channelId)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/removeRolePermission.ts b/src/commands/moderation/prefixCommands/functions/removeRolePermission.ts
index 7a63c983..b6157ac0 100644
--- a/src/commands/moderation/prefixCommands/functions/removeRolePermission.ts
+++ b/src/commands/moderation/prefixCommands/functions/removeRolePermission.ts
@@ -1,110 +1,122 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommand, Logger, makeEmbed, refreshSinglePrefixCommandCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommand,
+ Logger,
+ makeEmbed,
+ refreshSinglePrefixCommandCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Remove Role - No Connection',
- description: 'Could not connect to the database. Unable to remove the prefix command role.',
- color: Colors.Red,
+ title: 'Prefix Commands - Remove Role - No Connection',
+ description: 'Could not connect to the database. Unable to remove the prefix command role.',
+ color: Colors.Red,
});
-const noCommandEmbed = (command: string) => makeEmbed({
+const noCommandEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Remove Role - No Command',
description: `Failed to remove the prefix command role for command ${command} as the command does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (command: string, roleName: string) => makeEmbed({
+const failedEmbed = (command: string, roleName: string) =>
+ makeEmbed({
title: 'Prefix Commands - Remove Role - Failed',
description: `Failed to remove the prefix command role ${roleName} for command ${command}.`,
color: Colors.Red,
-});
+ });
-const doesNotExistEmbed = (command: string, roleName: string) => makeEmbed({
+const doesNotExistEmbed = (command: string, roleName: string) =>
+ makeEmbed({
title: 'Prefix Commands - Remove Role - Already exists',
description: `A prefix command role ${roleName} for command ${command} and role does not exist.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (command: string, roleName: string) => makeEmbed({
+const successEmbed = (command: string, roleName: string) =>
+ makeEmbed({
title: `Prefix command role ${roleName} removed for command ${command}.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, command: string, roleName: string) => makeEmbed({
+const modLogEmbed = (moderator: User, command: string, roleName: string) =>
+ makeEmbed({
title: 'Remove prefix command role permission',
fields: [
- {
- name: 'Command',
- value: command,
- },
- {
- name: 'Role',
- value: roleName,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
+ {
+ name: 'Command',
+ value: command,
+ },
+ {
+ name: 'Role',
+ value: roleName,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
],
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Remove Role - No Mod Log',
- description: 'I can\'t find the mod logs role. Please check the role still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Remove Role - No Mod Log',
+ description: "I can't find the mod logs role. Please check the role still exists.",
+ color: Colors.Red,
});
export async function handleRemovePrefixCommandRolePermission(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const command = interaction.options.getString('command')!;
- const role = interaction.options.getRole('role')!;
- const moderator = interaction.user;
+ const command = interaction.options.getString('command')!;
+ const role = interaction.options.getRole('role')!;
+ const moderator = interaction.user;
- //Check if the mod logs role exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs role exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- let foundCommands = await PrefixCommand.find({ name: command });
- if (!foundCommands || foundCommands.length > 1) {
- foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
- }
- if (!foundCommands || foundCommands.length > 1) {
- await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
- return;
- }
- const [foundCommand] = foundCommands;
- const { id: roleId, name: roleName } = role;
+ let foundCommands = await PrefixCommand.find({ name: command });
+ if (!foundCommands || foundCommands.length > 1) {
+ foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
+ }
+ if (!foundCommands || foundCommands.length > 1) {
+ await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ return;
+ }
+ const [foundCommand] = foundCommands;
+ const { id: roleId, name: roleName } = role;
- const existingRolePermission = foundCommand.permissions.roles?.includes(roleId);
- if (existingRolePermission) {
- foundCommand.permissions.roles = foundCommand.permissions.roles?.filter((id) => id !== roleId);
+ const existingRolePermission = foundCommand.permissions.roles?.includes(roleId);
+ if (existingRolePermission) {
+ foundCommand.permissions.roles = foundCommand.permissions.roles?.filter((id) => id !== roleId);
+ try {
+ await foundCommand.save();
+ await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
+ await interaction.followUp({ embeds: [successEmbed(command, roleName)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await foundCommand.save();
- await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
- await interaction.followUp({ embeds: [successEmbed(command, roleName)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, roleName)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs role: ${error}`);
- }
- }
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, roleName)] });
} catch (error) {
- Logger.error(`Failed to remove prefix command role ${roleName} for command ${command}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(command, roleName)], ephemeral: true });
+ Logger.error(`Failed to post a message to the mod logs role:`, error);
}
- } else {
- await interaction.followUp({ embeds: [doesNotExistEmbed(command, roleName)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to remove prefix command role ${roleName} for command ${command}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(command, roleName)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [doesNotExistEmbed(command, roleName)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/setChannelDefaultVersion.ts b/src/commands/moderation/prefixCommands/functions/setChannelDefaultVersion.ts
index 1fc531ca..9e123471 100644
--- a/src/commands/moderation/prefixCommands/functions/setChannelDefaultVersion.ts
+++ b/src/commands/moderation/prefixCommands/functions/setChannelDefaultVersion.ts
@@ -1,109 +1,122 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommandVersion, PrefixCommandChannelDefaultVersion, Logger, makeEmbed, loadSinglePrefixCommandChannelDefaultVersionToCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommandVersion,
+ PrefixCommandChannelDefaultVersion,
+ Logger,
+ makeEmbed,
+ loadSinglePrefixCommandChannelDefaultVersionToCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Set Default Channel Version - No Connection',
- description: 'Could not connect to the database. Unable to set the channel default version.',
- color: Colors.Red,
+ title: 'Prefix Commands - Set Default Channel Version - No Connection',
+ description: 'Could not connect to the database. Unable to set the channel default version.',
+ color: Colors.Red,
});
-const noVersionEmbed = (channel: string) => makeEmbed({
+const noVersionEmbed = (channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Show Default Channel Version - No Version',
description: `Failed to show default channel version for channel ${channel} as the configured version does not exist.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (channel: string) => makeEmbed({
+const failedEmbed = (channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Set Default Channel Version - Failed',
description: `Failed to set the channel default version for channel ${channel}.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (channel: string, version: string, emoji: string) => makeEmbed({
+const successEmbed = (channel: string, version: string, emoji: string) =>
+ makeEmbed({
title: `Prefix Command Channel Default version set for channel ${channel} to version ${version} ${emoji}.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, channel: string, version: string, emoji: string) => makeEmbed({
+const modLogEmbed = (moderator: User, channel: string, version: string, emoji: string) =>
+ makeEmbed({
title: 'Prefix channel default version set',
fields: [
- {
- name: 'Channel',
- value: channel,
- },
- {
- name: 'Version',
- value: `${version} - ${emoji}`,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
+ {
+ name: 'Channel',
+ value: channel,
+ },
+ {
+ name: 'Version',
+ value: `${version} - ${emoji}`,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
],
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Set Default Channel Version - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Set Default Channel Version - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleSetPrefixCommandChannelDefaultVersion(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const channel = interaction.options.getChannel('channel')!;
- const version = interaction.options.getString('version')!;
- const moderator = interaction.user;
+ const channel = interaction.options.getChannel('channel')!;
+ const version = interaction.options.getString('version')!;
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- let foundVersion;
- if (version !== 'GENERIC') {
- foundVersion = await PrefixCommandVersion.findOne({ name: version });
- }
+ let foundVersion;
+ if (version !== 'GENERIC') {
+ foundVersion = await PrefixCommandVersion.findOne({ name: version });
+ }
- if (foundVersion || version === 'GENERIC') {
- const { id: channelId, name: channelName } = channel;
- let versionId = '';
- let emoji = '';
- if (version === 'GENERIC') {
- versionId = 'GENERIC';
- emoji = '';
- } else if (foundVersion) {
- versionId = foundVersion.id;
- emoji = foundVersion.emoji;
- }
- const foundChannelDefaultVersion = await PrefixCommandChannelDefaultVersion.findOne({ channelId });
- const channelDefaultVersion = foundChannelDefaultVersion || new PrefixCommandChannelDefaultVersion({ channelId, versionId });
- channelDefaultVersion.versionId = versionId;
+ if (foundVersion || version === 'GENERIC') {
+ const { id: channelId, name: channelName } = channel;
+ let versionId = '';
+ let emoji = '';
+ if (version === 'GENERIC') {
+ versionId = 'GENERIC';
+ emoji = '';
+ } else if (foundVersion) {
+ versionId = foundVersion.id;
+ emoji = foundVersion.emoji;
+ }
+ const foundChannelDefaultVersion = await PrefixCommandChannelDefaultVersion.findOne({ channelId });
+ const channelDefaultVersion =
+ foundChannelDefaultVersion || new PrefixCommandChannelDefaultVersion({ channelId, versionId });
+ channelDefaultVersion.versionId = versionId;
+ try {
+ await channelDefaultVersion.save();
+ await loadSinglePrefixCommandChannelDefaultVersionToCache(channelDefaultVersion);
+ await interaction.followUp({ embeds: [successEmbed(channelName, version, emoji)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await channelDefaultVersion.save();
- await loadSinglePrefixCommandChannelDefaultVersionToCache(channelDefaultVersion);
- await interaction.followUp({ embeds: [successEmbed(channelName, version, emoji)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, channelName, version, emoji)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({ embeds: [modLogEmbed(moderator, channelName, version, emoji)] });
} catch (error) {
- Logger.error(`Failed to set the default channel version for channel ${channelName} to version ${version}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(channelName)], ephemeral: true });
+ Logger.error(`Failed to post a message to the mod logs channel:`, error);
}
- } else {
- await interaction.followUp({ embeds: [noVersionEmbed(version)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to set the default channel version for channel ${channelName} to version ${version}`, error);
+ await interaction.followUp({ embeds: [failedEmbed(channelName)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [noVersionEmbed(version)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/setCommandPermissionSettings.ts b/src/commands/moderation/prefixCommands/functions/setCommandPermissionSettings.ts
index 388fdcd0..c2ce32e6 100644
--- a/src/commands/moderation/prefixCommands/functions/setCommandPermissionSettings.ts
+++ b/src/commands/moderation/prefixCommands/functions/setCommandPermissionSettings.ts
@@ -1,123 +1,144 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
-import { constantsConfig, getConn, Logger, makeEmbed, PrefixCommand, PrefixCommandPermissions, refreshSinglePrefixCommandCache } from '../../../../lib';
+import {
+ constantsConfig,
+ getConn,
+ Logger,
+ makeEmbed,
+ PrefixCommand,
+ PrefixCommandPermissions,
+ refreshSinglePrefixCommandCache,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Set Permission Settings - No Connection',
- description: 'Could not connect to the database. Unable to set the permission settings.',
- color: Colors.Red,
+ title: 'Prefix Commands - Set Permission Settings - No Connection',
+ description: 'Could not connect to the database. Unable to set the permission settings.',
+ color: Colors.Red,
});
-const noCommandEmbed = (command: string) => makeEmbed({
+const noCommandEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Set Permission Settings - No Command',
description: `Failed to set default channel version for command ${command} as the command does not exist.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (command: string) => makeEmbed({
+const failedEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Set Permission Settings - Failed',
description: `Failed to set the permission settings for command ${command}.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (command: string) => makeEmbed({
+const successEmbed = (command: string) =>
+ makeEmbed({
title: `Prefix Command permission settings set for command ${command}.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, command: string, rolesBlocklist: boolean, channelsBlocklist: boolean, quietErrors: boolean, verboseErrors: boolean) => makeEmbed({
+const modLogEmbed = (
+ moderator: User,
+ command: string,
+ rolesBlocklist: boolean,
+ channelsBlocklist: boolean,
+ quietErrors: boolean,
+ verboseErrors: boolean,
+) =>
+ makeEmbed({
title: 'Prefix command permission set',
fields: [
- {
- name: 'Command',
- value: command,
- },
- {
- name: 'Roles Blocklist',
- value: rolesBlocklist ? 'Enabled' : 'Disabled',
- },
- {
- name: 'Channels Blocklist',
- value: channelsBlocklist ? 'Enabled' : 'Disabled',
- },
- {
- name: 'Quiet Errors',
- value: quietErrors ? 'Enabled' : 'Disabled',
- },
- {
- name: 'Verbose Errors',
- value: verboseErrors ? 'Enabled' : 'Disabled',
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
+ {
+ name: 'Command',
+ value: command,
+ },
+ {
+ name: 'Roles Blocklist',
+ value: rolesBlocklist ? 'Enabled' : 'Disabled',
+ },
+ {
+ name: 'Channels Blocklist',
+ value: channelsBlocklist ? 'Enabled' : 'Disabled',
+ },
+ {
+ name: 'Quiet Errors',
+ value: quietErrors ? 'Enabled' : 'Disabled',
+ },
+ {
+ name: 'Verbose Errors',
+ value: verboseErrors ? 'Enabled' : 'Disabled',
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
],
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Set Permission Settings - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Set Permission Settings - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleSetPrefixCommandPermissionSettings(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const command = interaction.options.getString('command')!;
- const rolesBlocklist = interaction.options.getBoolean('roles-blocklist') || false;
- const channelsBlocklist = interaction.options.getBoolean('channels-blocklist') || false;
- const quietErrors = interaction.options.getBoolean('quiet-errors') || false;
- const verboseErrors = interaction.options.getBoolean('verbose-errors') || false;
- const moderator = interaction.user;
+ const command = interaction.options.getString('command')!;
+ const rolesBlocklist = interaction.options.getBoolean('roles-blocklist') || false;
+ const channelsBlocklist = interaction.options.getBoolean('channels-blocklist') || false;
+ const quietErrors = interaction.options.getBoolean('quiet-errors') || false;
+ const verboseErrors = interaction.options.getBoolean('verbose-errors') || false;
+ const moderator = interaction.user;
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
- let foundCommands = await PrefixCommand.find({ name: command });
- if (!foundCommands || foundCommands.length > 1) {
- foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
- }
- if (!foundCommands || foundCommands.length > 1) {
- await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
- return;
- }
+ let foundCommands = await PrefixCommand.find({ name: command });
+ if (!foundCommands || foundCommands.length > 1) {
+ foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
+ }
+ if (!foundCommands || foundCommands.length > 1) {
+ await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ return;
+ }
- const [foundCommand] = foundCommands;
- if (foundCommand) {
- if (!foundCommand.permissions) {
- foundCommand.permissions = new PrefixCommandPermissions();
- }
- foundCommand.permissions.rolesBlocklist = rolesBlocklist;
- foundCommand.permissions.channelsBlocklist = channelsBlocklist;
- foundCommand.permissions.quietErrors = quietErrors;
- foundCommand.permissions.verboseErrors = verboseErrors;
+ const [foundCommand] = foundCommands;
+ if (foundCommand) {
+ if (!foundCommand.permissions) {
+ foundCommand.permissions = new PrefixCommandPermissions();
+ }
+ foundCommand.permissions.rolesBlocklist = rolesBlocklist;
+ foundCommand.permissions.channelsBlocklist = channelsBlocklist;
+ foundCommand.permissions.quietErrors = quietErrors;
+ foundCommand.permissions.verboseErrors = verboseErrors;
+ try {
+ await foundCommand.save();
+ await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
+ await interaction.followUp({ embeds: [successEmbed(command)], ephemeral: true });
+ if (modLogsChannel) {
try {
- await foundCommand.save();
- await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
- await interaction.followUp({ embeds: [successEmbed(command)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, rolesBlocklist, channelsBlocklist, quietErrors, verboseErrors)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await modLogsChannel.send({
+ embeds: [modLogEmbed(moderator, command, rolesBlocklist, channelsBlocklist, quietErrors, verboseErrors)],
+ });
} catch (error) {
- Logger.error(`Failed to set the permission settings for command ${command}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(command)], ephemeral: true });
+ Logger.error('Failed to post a message to the mod logs channel:', error);
}
- } else {
- await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ }
+ } catch (error) {
+ Logger.error(`Failed to set the permission settings for command ${command}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(command)], ephemeral: true });
}
+ } else {
+ await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/setContent.ts b/src/commands/moderation/prefixCommands/functions/setContent.ts
index 72f7eb4c..bbb65040 100644
--- a/src/commands/moderation/prefixCommands/functions/setContent.ts
+++ b/src/commands/moderation/prefixCommands/functions/setContent.ts
@@ -1,230 +1,267 @@
-import { ActionRowBuilder, ChatInputCommandInteraction, Colors, ModalBuilder, ModalSubmitInteraction, TextInputBuilder, TextInputStyle, User } from 'discord.js';
-import { constantsConfig, getConn, PrefixCommandVersion, PrefixCommand, Logger, makeEmbed, refreshSinglePrefixCommandCache, PrefixCommandContent } from '../../../../lib';
+import {
+ ActionRowBuilder,
+ ChatInputCommandInteraction,
+ Colors,
+ ModalBuilder,
+ ModalSubmitInteraction,
+ TextInputBuilder,
+ TextInputStyle,
+ User,
+} from 'discord.js';
+import {
+ constantsConfig,
+ getConn,
+ PrefixCommandVersion,
+ PrefixCommand,
+ Logger,
+ makeEmbed,
+ refreshSinglePrefixCommandCache,
+ PrefixCommandContent,
+} from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Set Content - No Connection',
- description: 'Could not connect to the database. Unable to set the prefix command content.',
- color: Colors.Red,
+ title: 'Prefix Commands - Set Content - No Connection',
+ description: 'Could not connect to the database. Unable to set the prefix command content.',
+ color: Colors.Red,
});
-const noCommandEmbed = (command: string) => makeEmbed({
+const noCommandEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Set Content - No Command',
description: `Failed to set command content for command ${command} as the command does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const noVersionEmbed = (version: string) => makeEmbed({
+const noVersionEmbed = (version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Set Content - No Version',
description: `Failed to set command content for version ${version} as the version does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (command: string, version: string) => makeEmbed({
+const failedEmbed = (command: string, version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Set Content - Failed',
description: `Failed to set command content for command ${command} and version ${version}.`,
color: Colors.Red,
-});
+ });
-const successEmbed = (command: string, version: string) => makeEmbed({
+const successEmbed = (command: string, version: string) =>
+ makeEmbed({
title: `Prefix command content set for command ${command} and version ${version}.`,
color: Colors.Green,
-});
+ });
-const modLogEmbed = (moderator: User, command: string, version: string, title: string, content: string, image: string, commandId: string, versionId: string) => makeEmbed({
+const modLogEmbed = (
+ moderator: User,
+ command: string,
+ version: string,
+ title: string,
+ content: string,
+ image: string,
+ commandId: string,
+ versionId: string,
+) =>
+ makeEmbed({
title: 'Prefix command content set',
fields: [
- {
- name: 'Command',
- value: command,
- },
- {
- name: 'Version',
- value: version,
- },
- {
- name: 'Title',
- value: title,
- },
- {
- name: 'Content',
- value: content,
- },
- {
- name: 'Image',
- value: image,
- },
- {
- name: 'Moderator',
- value: `${moderator}`,
- },
+ {
+ name: 'Command',
+ value: command,
+ },
+ {
+ name: 'Version',
+ value: version,
+ },
+ {
+ name: 'Title',
+ value: title,
+ },
+ {
+ name: 'Content',
+ value: content,
+ },
+ {
+ name: 'Image',
+ value: image,
+ },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ },
],
footer: { text: `Command ID: ${commandId} - Version ID: ${versionId}` },
color: Colors.Green,
-});
+ });
const noModLogs = makeEmbed({
- title: 'Prefix Commands - Set Content - No Mod Log',
- description: 'I can\'t find the mod logs channel. Please check the channel still exists.',
- color: Colors.Red,
+ title: 'Prefix Commands - Set Content - No Mod Log',
+ description: "I can't find the mod logs channel. Please check the channel still exists.",
+ color: Colors.Red,
});
export async function handleSetPrefixCommandContent(interaction: ChatInputCommandInteraction<'cached'>) {
- const conn = getConn();
- if (!conn) {
- await interaction.reply({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.reply({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const command = interaction.options.getString('command')!;
- const version = interaction.options.getString('version')!;
- const moderator = interaction.user;
+ const command = interaction.options.getString('command')!;
+ const version = interaction.options.getString('version')!;
+ const moderator = interaction.user;
- let foundCommands = await PrefixCommand.find({ name: command });
- if (!foundCommands || foundCommands.length !== 1) {
- foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
- }
- if (!foundCommands || foundCommands.length !== 1) {
- await interaction.reply({ embeds: [noCommandEmbed(command)], ephemeral: true });
- return;
- }
+ let foundCommands = await PrefixCommand.find({ name: command });
+ if (!foundCommands || foundCommands.length !== 1) {
+ foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
+ }
+ if (!foundCommands || foundCommands.length !== 1) {
+ await interaction.reply({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ return;
+ }
- const foundCommand = foundCommands[0];
- const { _id: commandId } = foundCommand;
- let versionId = '';
- let foundVersions = null;
- if (version === 'GENERIC' || version === 'generic') {
- versionId = 'GENERIC';
+ const foundCommand = foundCommands[0];
+ const { _id: commandId } = foundCommand;
+ let versionId = '';
+ let foundVersions = null;
+ if (version === 'GENERIC' || version === 'generic') {
+ versionId = 'GENERIC';
+ } else {
+ foundVersions = await PrefixCommandVersion.find({ name: version });
+ if (foundVersions && foundVersions.length === 1) {
+ [{ _id: versionId }] = foundVersions;
} else {
- foundVersions = await PrefixCommandVersion.find({ name: version });
- if (foundVersions && foundVersions.length === 1) {
- [{ _id: versionId }] = foundVersions;
- } else {
- await interaction.reply({ embeds: [noVersionEmbed(version)], ephemeral: true });
- return;
- }
+ await interaction.reply({ embeds: [noVersionEmbed(version)], ephemeral: true });
+ return;
}
+ }
- const foundContent = foundCommand.contents.find((c) => c.versionId.toString() === versionId.toString());
- const contentModal = new ModalBuilder({
- customId: 'commandContentModal',
- title: `Content for ${command} - ${version}`,
- });
+ const foundContent = foundCommand.contents.find((c) => c.versionId.toString() === versionId.toString());
+ const contentModal = new ModalBuilder({
+ customId: 'commandContentModal',
+ title: `Content for ${command} - ${version}`,
+ });
- const commandContentTitle = new TextInputBuilder()
- .setCustomId('commandContentTitle')
- .setLabel('Title')
- .setPlaceholder('Provide a title for the command.')
- .setStyle(TextInputStyle.Short)
- .setMaxLength(255)
- .setMinLength(0)
- .setRequired(false)
- .setValue(foundContent ? foundContent.title : '');
-
- const commandContentContent = new TextInputBuilder()
- .setCustomId('commandContentContent')
- .setLabel('Content')
- .setPlaceholder('Provide the content for the command.')
- .setStyle(TextInputStyle.Paragraph)
- .setMaxLength(4000)
- .setMinLength(0)
- .setRequired(false)
- .setValue(foundContent && foundContent.content ? foundContent.content : '');
-
- const commandContentImageUrl = new TextInputBuilder()
- .setCustomId('commandContentImageUrl')
- .setLabel('Image URL')
- .setPlaceholder('Provide an optional Image URL for the command.')
- .setStyle(TextInputStyle.Short)
- .setMaxLength(2048)
- .setMinLength(0)
- .setRequired(false)
- .setValue(foundContent && foundContent.image ? foundContent.image : '');
-
- const titleActionRow = new ActionRowBuilder().addComponents(commandContentTitle);
- const contentActionRow = new ActionRowBuilder().addComponents(commandContentContent);
- const imageUrlActionRow = new ActionRowBuilder().addComponents(commandContentImageUrl);
-
- contentModal.addComponents(titleActionRow);
- contentModal.addComponents(contentActionRow);
- contentModal.addComponents(imageUrlActionRow);
-
- await interaction.showModal(contentModal);
-
- const filter = (interaction: ModalSubmitInteraction) => interaction.customId === 'commandContentModal' && interaction.user.id === moderator.id;
-
- let title = '';
- let content = '';
- let image = '';
+ const commandContentTitle = new TextInputBuilder()
+ .setCustomId('commandContentTitle')
+ .setLabel('Title')
+ .setPlaceholder('Provide a title for the command.')
+ .setStyle(TextInputStyle.Short)
+ .setMaxLength(255)
+ .setMinLength(0)
+ .setRequired(false)
+ .setValue(foundContent ? foundContent.title : '');
- try {
- //Await a modal response
- const modalSubmitInteraction = await interaction.awaitModalSubmit({
- filter,
- time: 120000,
- });
+ const commandContentContent = new TextInputBuilder()
+ .setCustomId('commandContentContent')
+ .setLabel('Content')
+ .setPlaceholder('Provide the content for the command.')
+ .setStyle(TextInputStyle.Paragraph)
+ .setMaxLength(4000)
+ .setMinLength(0)
+ .setRequired(false)
+ .setValue(foundContent && foundContent.content ? foundContent.content : '');
- title = modalSubmitInteraction.fields.getTextInputValue('commandContentTitle').trim();
- content = modalSubmitInteraction.fields.getTextInputValue('commandContentContent').trim();
- image = modalSubmitInteraction.fields.getTextInputValue('commandContentImageUrl').trim();
-
- if (!title && !content && !image) {
- await modalSubmitInteraction.reply({
- content: 'You did not provide any content information and the change was not made.',
- ephemeral: true,
- });
- return;
- }
- await modalSubmitInteraction.reply({
- content: 'Processing command content data.',
- ephemeral: true,
- });
- } catch (error) {
- //Handle the error if the user does not respond in time
- Logger.error(error);
- await interaction.followUp({
- content: 'You did not provide the necessary content information in time (2 minutes) and the change was not made.',
- ephemeral: true,
- });
- return;
- }
- //Check if the mod logs channel exists
- let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
- if (!modLogsChannel || !modLogsChannel.isTextBased()) {
- modLogsChannel = null;
- await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
- }
+ const commandContentImageUrl = new TextInputBuilder()
+ .setCustomId('commandContentImageUrl')
+ .setLabel('Image URL')
+ .setPlaceholder('Provide an optional Image URL for the command.')
+ .setStyle(TextInputStyle.Short)
+ .setMaxLength(2048)
+ .setMinLength(0)
+ .setRequired(false)
+ .setValue(foundContent && foundContent.image ? foundContent.image : '');
+
+ const titleActionRow = new ActionRowBuilder().addComponents(commandContentTitle);
+ const contentActionRow = new ActionRowBuilder().addComponents(commandContentContent);
+ const imageUrlActionRow = new ActionRowBuilder().addComponents(commandContentImageUrl);
+
+ contentModal.addComponents(titleActionRow);
+ contentModal.addComponents(contentActionRow);
+ contentModal.addComponents(imageUrlActionRow);
+
+ await interaction.showModal(contentModal);
+
+ const filter = (interaction: ModalSubmitInteraction) =>
+ interaction.customId === 'commandContentModal' && interaction.user.id === moderator.id;
+
+ let title = '';
+ let content = '';
+ let image = '';
- if (foundContent) {
- const foundData = foundCommand.contents.find((c) => c.versionId === foundContent.versionId);
- try {
- await foundData?.deleteOne();
- } catch (error) {
- Logger.error(`Failed to delete existing content for prefix command ${command} and version ${version}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(command, version)], ephemeral: true });
- return;
- }
+ try {
+ //Await a modal response
+ const modalSubmitInteraction = await interaction.awaitModalSubmit({
+ filter,
+ time: 120000,
+ });
+
+ title = modalSubmitInteraction.fields.getTextInputValue('commandContentTitle').trim();
+ content = modalSubmitInteraction.fields.getTextInputValue('commandContentContent').trim();
+ image = modalSubmitInteraction.fields.getTextInputValue('commandContentImageUrl').trim();
+
+ if (!title && !content && !image) {
+ await modalSubmitInteraction.reply({
+ content: 'You did not provide any content information and the change was not made.',
+ ephemeral: true,
+ });
+ return;
}
- const contentData = new PrefixCommandContent({
- versionId,
- title,
- content,
- image,
+ await modalSubmitInteraction.reply({
+ content: 'Processing command content data.',
+ ephemeral: true,
+ });
+ } catch (error) {
+ //Handle the error if the user does not respond in time
+ Logger.error(error);
+ await interaction.followUp({
+ content: 'You did not provide the necessary content information in time (2 minutes) and the change was not made.',
+ ephemeral: true,
});
- foundCommand.contents.push(contentData);
+ return;
+ }
+ //Check if the mod logs channel exists
+ let modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS);
+ if (!modLogsChannel || !modLogsChannel.isTextBased()) {
+ modLogsChannel = null;
+ await interaction.followUp({ embeds: [noModLogs], ephemeral: true });
+ }
+ if (foundContent) {
+ const foundData = foundCommand.contents.find((c) => c.versionId === foundContent.versionId);
try {
- await foundCommand.save();
- await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
- await interaction.followUp({ embeds: [successEmbed(command, version)], ephemeral: true });
- if (modLogsChannel) {
- try {
- await modLogsChannel.send({ embeds: [modLogEmbed(moderator, command, version, title, content, image, commandId, versionId)] });
- } catch (error) {
- Logger.error(`Failed to post a message to the mod logs channel: ${error}`);
- }
- }
+ await foundData?.deleteOne();
} catch (error) {
- Logger.error(`Failed to set prefix command content for command ${command} and version ${version}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(command, version)], ephemeral: true });
+ Logger.error(
+ `Failed to delete existing content for prefix command ${command} and version ${version}${error instanceof Error && `: ${error}`} `,
+ );
+ await interaction.followUp({ embeds: [failedEmbed(command, version)], ephemeral: true });
+ return;
+ }
+ }
+ const contentData = new PrefixCommandContent({
+ versionId,
+ title,
+ content,
+ image,
+ });
+ foundCommand.contents.push(contentData);
+
+ try {
+ await foundCommand.save();
+ await refreshSinglePrefixCommandCache(foundCommand, foundCommand);
+ await interaction.followUp({ embeds: [successEmbed(command, version)], ephemeral: true });
+ if (modLogsChannel) {
+ try {
+ await modLogsChannel.send({
+ embeds: [modLogEmbed(moderator, command, version, title, content, image, commandId, versionId)],
+ });
+ } catch (error) {
+ Logger.error('Failed to post a message to the mod logs channel:', error);
+ }
}
+ } catch (error) {
+ Logger.error(`Failed to set prefix command content for command ${command} and version ${version}`, error);
+ await interaction.followUp({ embeds: [failedEmbed(command, version)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/showChannelDefaultVersion.ts b/src/commands/moderation/prefixCommands/functions/showChannelDefaultVersion.ts
index 03846f87..51fa630b 100644
--- a/src/commands/moderation/prefixCommands/functions/showChannelDefaultVersion.ts
+++ b/src/commands/moderation/prefixCommands/functions/showChannelDefaultVersion.ts
@@ -2,75 +2,89 @@ import { ChatInputCommandInteraction, Colors } from 'discord.js';
import { getConn, PrefixCommandChannelDefaultVersion, PrefixCommandVersion, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Show Default Channel Version - No Connection',
- description: 'Could not connect to the database. Unable to show the channel default version.',
- color: Colors.Red,
+ title: 'Prefix Commands - Show Default Channel Version - No Connection',
+ description: 'Could not connect to the database. Unable to show the channel default version.',
+ color: Colors.Red,
});
-const noVersionEmbed = (channel: string) => makeEmbed({
+const noVersionEmbed = (channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Show Default Channel Version - No Version',
description: `Failed to show default channel version for channel ${channel} as the configured version does not exist.`,
color: Colors.Red,
-});
+ });
-const noChannelDefaultVersionEmbed = (channel: string) => makeEmbed({
+const noChannelDefaultVersionEmbed = (channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Show Default Channel Version - No Default Channel Version',
description: `Failed to show the channel default version for channel ${channel} as there is no default version set.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (channel: string) => makeEmbed({
+const failedEmbed = (channel: string) =>
+ makeEmbed({
title: 'Prefix Commands - Show Default Channel Version - Failed',
description: `Failed to show the channel default version for channel ${channel}.`,
color: Colors.Red,
-});
+ });
-const contentEmbed = (channel: string, version: string, emoji: string, versionId: string) => makeEmbed({
+const contentEmbed = (channel: string, version: string, emoji: string, versionId: string) =>
+ makeEmbed({
title: `Prefix Commands - Show Default Channel Version - ${channel} - ${version}`,
fields: [
- {
- name: 'Channel',
- value: channel,
- },
- {
- name: 'Version',
- value: `${version} - ${emoji}`,
- },
+ {
+ name: 'Channel',
+ value: channel,
+ },
+ {
+ name: 'Version',
+ value: `${version} - ${emoji}`,
+ },
],
footer: { text: `Version ID: ${versionId}` },
color: Colors.Green,
-});
+ });
export async function handleShowPrefixCommandChannelDefaultVersion(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const channel = interaction.options.getChannel('channel')!;
- const { id: channelId, name: channelName } = channel;
- const foundChannelDefaultVersions = await PrefixCommandChannelDefaultVersion.find({ channelId });
- if (!foundChannelDefaultVersions || foundChannelDefaultVersions.length === 0 || foundChannelDefaultVersions.length > 1) {
- await interaction.followUp({ embeds: [noChannelDefaultVersionEmbed(channelName)], ephemeral: true });
- return;
- }
+ const channel = interaction.options.getChannel('channel')!;
+ const { id: channelId, name: channelName } = channel;
+ const foundChannelDefaultVersions = await PrefixCommandChannelDefaultVersion.find({ channelId });
+ if (
+ !foundChannelDefaultVersions ||
+ foundChannelDefaultVersions.length === 0 ||
+ foundChannelDefaultVersions.length > 1
+ ) {
+ await interaction.followUp({ embeds: [noChannelDefaultVersionEmbed(channelName)], ephemeral: true });
+ return;
+ }
- const [foundChannelDefaultVersion] = foundChannelDefaultVersions;
- const { versionId } = foundChannelDefaultVersion;
- const foundVersion = await PrefixCommandVersion.findById(versionId);
- if (!foundVersion) {
- await interaction.followUp({ embeds: [noVersionEmbed(channelName)], ephemeral: true });
- return;
- }
+ const [foundChannelDefaultVersion] = foundChannelDefaultVersions;
+ const { versionId } = foundChannelDefaultVersion;
+ const foundVersion = await PrefixCommandVersion.findById(versionId);
+ if (!foundVersion) {
+ await interaction.followUp({ embeds: [noVersionEmbed(channelName)], ephemeral: true });
+ return;
+ }
- const { name: version, emoji } = foundVersion;
- try {
- await interaction.followUp({ embeds: [contentEmbed(channelName, `${version}`, `${emoji}`, `${versionId}`)], ephemeral: false });
- } catch (error) {
- Logger.error(`Failed to show the channel default version for channel ${channel} and version ${version}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(channelName)], ephemeral: true });
- }
+ const { name: version, emoji } = foundVersion;
+ try {
+ await interaction.followUp({
+ embeds: [contentEmbed(channelName, `${version}`, `${emoji}`, `${versionId}`)],
+ ephemeral: false,
+ });
+ } catch (error) {
+ Logger.error(
+ `Failed to show the channel default version for channel ${channel.toString()} and version ${version}`,
+ error,
+ );
+ await interaction.followUp({ embeds: [failedEmbed(channelName)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/showCommandPermissions.ts b/src/commands/moderation/prefixCommands/functions/showCommandPermissions.ts
index b64bb990..19dd52eb 100644
--- a/src/commands/moderation/prefixCommands/functions/showCommandPermissions.ts
+++ b/src/commands/moderation/prefixCommands/functions/showCommandPermissions.ts
@@ -2,103 +2,127 @@ import { ChatInputCommandInteraction, Colors } from 'discord.js';
import { getConn, PrefixCommand, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Show Command Permissions - No Connection',
- description: 'Could not connect to the database. Unable to show the prefix command permissions.',
- color: Colors.Red,
+ title: 'Prefix Commands - Show Command Permissions - No Connection',
+ description: 'Could not connect to the database. Unable to show the prefix command permissions.',
+ color: Colors.Red,
});
-const noCommandEmbed = (command: string) => makeEmbed({
+const noCommandEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Show Command Permissions - No Command',
description: `Failed to show command permissions for command ${command} as the command does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (command: string) => makeEmbed({
+const failedEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Show Command Permissions - Failed',
description: `Failed to show command permissions for command ${command}.`,
color: Colors.Red,
-});
+ });
-const permissionEmbed = (command: string, roles: string[], rolesBlocklist: boolean, channels: string[], channelsBlocklist: boolean, quietErrors: boolean, verboseErrors: boolean) => makeEmbed({
+const permissionEmbed = (
+ command: string,
+ roles: string[],
+ rolesBlocklist: boolean,
+ channels: string[],
+ channelsBlocklist: boolean,
+ quietErrors: boolean,
+ verboseErrors: boolean,
+) =>
+ makeEmbed({
title: `Prefix Commands - Show Command Permissions - ${command}`,
fields: [
- {
- name: 'Roles',
- value: roles.length > 0 ? roles.join(', ') : 'None',
- },
- {
- name: 'Roles Blocklist',
- value: rolesBlocklist ? 'Enabled' : 'Disabled',
- },
- {
- name: 'Channels',
- value: channels.length > 0 ? channels.join(', ') : 'None',
- },
- {
- name: 'Channels Blocklist',
- value: channelsBlocklist ? 'Enabled' : 'Disabled',
- },
- {
- name: 'Quiet Errors',
- value: quietErrors ? 'Enabled' : 'Disabled',
- },
- {
- name: 'Verbose Errors',
- value: verboseErrors ? 'Enabled' : 'Disabled',
- },
+ {
+ name: 'Roles',
+ value: roles.length > 0 ? roles.join(', ') : 'None',
+ },
+ {
+ name: 'Roles Blocklist',
+ value: rolesBlocklist ? 'Enabled' : 'Disabled',
+ },
+ {
+ name: 'Channels',
+ value: channels.length > 0 ? channels.join(', ') : 'None',
+ },
+ {
+ name: 'Channels Blocklist',
+ value: channelsBlocklist ? 'Enabled' : 'Disabled',
+ },
+ {
+ name: 'Quiet Errors',
+ value: quietErrors ? 'Enabled' : 'Disabled',
+ },
+ {
+ name: 'Verbose Errors',
+ value: verboseErrors ? 'Enabled' : 'Disabled',
+ },
],
color: Colors.Green,
-});
+ });
export async function handleShowPrefixCommandPermissions(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const command = interaction.options.getString('command') || '';
- let foundCommands = await PrefixCommand.find({ name: command });
- if (!foundCommands || foundCommands.length > 1) {
- foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
- }
- if (!foundCommands || foundCommands.length > 1) {
- await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
- return;
- }
+ const command = interaction.options.getString('command') || '';
+ let foundCommands = await PrefixCommand.find({ name: command });
+ if (!foundCommands || foundCommands.length > 1) {
+ foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
+ }
+ if (!foundCommands || foundCommands.length > 1) {
+ await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ return;
+ }
- const [foundCommand] = foundCommands;
- const { permissions } = foundCommand;
- const { roles, rolesBlocklist, channels, channelsBlocklist, quietErrors, verboseErrors } = permissions;
- const roleNames = [];
- const channelNames = [];
- if (roles) {
- for (const role of roles) {
- // eslint-disable-next-line no-await-in-loop
- const discordRole = await interaction.guild.roles.fetch(role);
- if (discordRole) {
- const { name } = discordRole;
- roleNames.push(name);
- }
- }
+ const [foundCommand] = foundCommands;
+ const { permissions } = foundCommand;
+ const { roles, rolesBlocklist, channels, channelsBlocklist, quietErrors, verboseErrors } = permissions;
+ const roleNames = [];
+ const channelNames = [];
+ if (roles) {
+ for (const role of roles) {
+ // eslint-disable-next-line no-await-in-loop
+ const discordRole = await interaction.guild.roles.fetch(role);
+ if (discordRole) {
+ const { name } = discordRole;
+ roleNames.push(name);
+ }
}
- if (channels) {
- for (const channel of channels) {
- // eslint-disable-next-line no-await-in-loop
- const discordChannel = await interaction.guild.channels.fetch(channel);
- if (discordChannel) {
- const { id: channelId } = discordChannel;
- channelNames.push(`<#${channelId}>`);
- }
- }
+ }
+ if (channels) {
+ for (const channel of channels) {
+ // eslint-disable-next-line no-await-in-loop
+ const discordChannel = await interaction.guild.channels.fetch(channel);
+ if (discordChannel) {
+ const { id: channelId } = discordChannel;
+ channelNames.push(`<#${channelId}>`);
+ }
}
+ }
- try {
- await interaction.followUp({ embeds: [permissionEmbed(command, roleNames, rolesBlocklist || false, channelNames, channelsBlocklist || false, quietErrors || false, verboseErrors || false)], ephemeral: false });
- } catch (error) {
- Logger.error(`Failed to show prefix command content for command ${command}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(command)], ephemeral: true });
- }
+ try {
+ await interaction.followUp({
+ embeds: [
+ permissionEmbed(
+ command,
+ roleNames,
+ rolesBlocklist || false,
+ channelNames,
+ channelsBlocklist || false,
+ quietErrors || false,
+ verboseErrors || false,
+ ),
+ ],
+ ephemeral: false,
+ });
+ } catch (error) {
+ Logger.error(`Failed to show prefix command content for command ${command}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(command)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/functions/showContent.ts b/src/commands/moderation/prefixCommands/functions/showContent.ts
index 286d7997..f8ebbd62 100644
--- a/src/commands/moderation/prefixCommands/functions/showContent.ts
+++ b/src/commands/moderation/prefixCommands/functions/showContent.ts
@@ -2,101 +2,129 @@ import { ChatInputCommandInteraction, Colors } from 'discord.js';
import { getConn, PrefixCommandVersion, PrefixCommand, Logger, makeEmbed } from '../../../../lib';
const noConnEmbed = makeEmbed({
- title: 'Prefix Commands - Show Content - No Connection',
- description: 'Could not connect to the database. Unable to show the prefix command content.',
- color: Colors.Red,
+ title: 'Prefix Commands - Show Content - No Connection',
+ description: 'Could not connect to the database. Unable to show the prefix command content.',
+ color: Colors.Red,
});
-const noCommandEmbed = (command: string) => makeEmbed({
+const noCommandEmbed = (command: string) =>
+ makeEmbed({
title: 'Prefix Commands - Show Content - No Command',
description: `Failed to show command content for command ${command} as the command does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const noVersionEmbed = (version: string) => makeEmbed({
+const noVersionEmbed = (version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Show Content - No Version',
description: `Failed to show command content for version ${version} as the version does not exist or there are more than one matching.`,
color: Colors.Red,
-});
+ });
-const noContentEmbed = (command: string, version: string) => makeEmbed({
+const noContentEmbed = (command: string, version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Show Content - No Content',
description: `Failed to show command content for command ${command} and version ${version} as the content does not exist.`,
color: Colors.Red,
-});
+ });
-const failedEmbed = (command: string, version: string) => makeEmbed({
+const failedEmbed = (command: string, version: string) =>
+ makeEmbed({
title: 'Prefix Commands - Show Content - Failed',
description: `Failed to show command content for command ${command} and version ${version}.`,
color: Colors.Red,
-});
+ });
-const contentEmbed = (command: string, version: string, title: string, content: string, image: string, commandId: string, versionId: string, contentId: string) => makeEmbed({
+const contentEmbed = (
+ command: string,
+ version: string,
+ title: string,
+ content: string,
+ image: string,
+ commandId: string,
+ versionId: string,
+ contentId: string,
+) =>
+ makeEmbed({
title: `Prefix Commands - Show Content - ${command} - ${version}`,
fields: [
- {
- name: 'Title',
- value: title,
- },
- {
- name: 'Content',
- value: content,
- },
- {
- name: 'Image',
- value: image,
- },
+ {
+ name: 'Title',
+ value: title,
+ },
+ {
+ name: 'Content',
+ value: content,
+ },
+ {
+ name: 'Image',
+ value: image,
+ },
],
footer: { text: `Command ID: ${commandId} - Version ID: ${versionId} - Content ID: ${contentId}` },
color: Colors.Green,
-});
+ });
export async function handleShowPrefixCommandContent(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- const conn = getConn();
- if (!conn) {
- await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ const conn = getConn();
+ if (!conn) {
+ await interaction.followUp({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const command = interaction.options.getString('command') || '';
- const version = interaction.options.getString('version') || '';
- let foundCommands = await PrefixCommand.find({ name: command });
- if (!foundCommands || foundCommands.length > 1) {
- foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
- }
- if (!foundCommands || foundCommands.length > 1) {
- await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
- return;
- }
+ const command = interaction.options.getString('command') || '';
+ const version = interaction.options.getString('version') || '';
+ let foundCommands = await PrefixCommand.find({ name: command });
+ if (!foundCommands || foundCommands.length > 1) {
+ foundCommands = await PrefixCommand.find({ aliases: { $in: [command] } });
+ }
+ if (!foundCommands || foundCommands.length > 1) {
+ await interaction.followUp({ embeds: [noCommandEmbed(command)], ephemeral: true });
+ return;
+ }
- const [foundCommand] = foundCommands;
- const { id: commandId } = foundCommand;
- let versionId = '';
- if (version === 'GENERIC' || version === 'generic') {
- versionId = 'GENERIC';
+ const [foundCommand] = foundCommands;
+ const { id: commandId } = foundCommand;
+ let versionId = '';
+ if (version === 'GENERIC' || version === 'generic') {
+ versionId = 'GENERIC';
+ } else {
+ const foundVersions = await PrefixCommandVersion.find({ name: version });
+ if (foundVersions && foundVersions.length === 1) {
+ const [foundVersion] = foundVersions;
+ ({ id: versionId } = foundVersion);
} else {
- const foundVersions = await PrefixCommandVersion.find({ name: version });
- if (foundVersions && foundVersions.length === 1) {
- const [foundVersion] = foundVersions;
- ({ id: versionId } = foundVersion);
- } else {
- await interaction.followUp({ embeds: [noVersionEmbed(version)], ephemeral: true });
- return;
- }
+ await interaction.followUp({ embeds: [noVersionEmbed(version)], ephemeral: true });
+ return;
}
+ }
- const foundContent = foundCommand.contents.find((content) => content.versionId === versionId);
- if (!foundContent) {
- await interaction.followUp({ embeds: [noContentEmbed(command, version)], ephemeral: true });
- return;
- }
- const { id: contentId, title, content, image } = foundContent;
- try {
- await interaction.followUp({ embeds: [contentEmbed(command, version, title || '', content || '', image || '', `${commandId}`, `${versionId}`, `${contentId}`)], ephemeral: false });
- } catch (error) {
- Logger.error(`Failed to show prefix command content for command ${command} and version ${version}: ${error}`);
- await interaction.followUp({ embeds: [failedEmbed(command, version)], ephemeral: true });
- }
+ const foundContent = foundCommand.contents.find((content) => content.versionId === versionId);
+ if (!foundContent) {
+ await interaction.followUp({ embeds: [noContentEmbed(command, version)], ephemeral: true });
+ return;
+ }
+ const { id: contentId, title, content, image } = foundContent;
+ try {
+ await interaction.followUp({
+ embeds: [
+ contentEmbed(
+ command,
+ version,
+ title || '',
+ content || '',
+ image || '',
+ `${commandId}`,
+ `${versionId}`,
+ `${contentId}`,
+ ),
+ ],
+ ephemeral: false,
+ });
+ } catch (error) {
+ Logger.error(`Failed to show prefix command content for command ${command} and version ${version}:`, error);
+ await interaction.followUp({ embeds: [failedEmbed(command, version)], ephemeral: true });
+ }
}
diff --git a/src/commands/moderation/prefixCommands/prefixCommandCacheUpdate.ts b/src/commands/moderation/prefixCommands/prefixCommandCacheUpdate.ts
index f4f87233..5e1d2d6e 100644
--- a/src/commands/moderation/prefixCommands/prefixCommandCacheUpdate.ts
+++ b/src/commands/moderation/prefixCommands/prefixCommandCacheUpdate.ts
@@ -1,80 +1,81 @@
import { APIEmbedField, ApplicationCommandType, Colors, EmbedField, TextChannel, User } from 'discord.js';
-import { constantsConfig, slashCommand, slashCommandStructure, makeEmbed, refreshAllPrefixCommandsCache, refreshAllPrefixCommandVersionsCache, refreshAllPrefixCommandCategoriesCache, refreshAllPrefixCommandChannelDefaultVersionsCache } from '../../../lib';
+import {
+ constantsConfig,
+ slashCommand,
+ slashCommandStructure,
+ makeEmbed,
+ refreshAllPrefixCommandsCache,
+ refreshAllPrefixCommandVersionsCache,
+ refreshAllPrefixCommandCategoriesCache,
+ refreshAllPrefixCommandChannelDefaultVersionsCache,
+} from '../../../lib';
const data = slashCommandStructure({
- name: 'prefix-commands-cache-update',
- description: 'Updates the in-memory prefix command cache of the bot.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin, moderator and bot developer roles
- dm_permission: false,
- options: [],
+ name: 'prefix-commands-cache-update',
+ description: 'Updates the in-memory prefix command cache of the bot.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin, moderator and bot developer roles
+ dm_permission: false,
+ options: [],
});
-const cacheUpdateEmbed = (fields: APIEmbedField[], color: number) => makeEmbed({
+const cacheUpdateEmbed = (fields: APIEmbedField[], color: number) =>
+ makeEmbed({
title: 'Prefix Command Cache Update',
fields,
color,
-});
+ });
-const noChannelEmbed = (channelName: string) => makeEmbed({
+const noChannelEmbed = (channelName: string) =>
+ makeEmbed({
title: `Prefix Command Cache Update - No ${channelName} channel`,
description: `The command was successful, but no message to ${channelName} was sent. Please check the channel still exists.`,
color: Colors.Yellow,
-});
+ });
const cacheUpdateEmbedField = (moderator: User, duration: string): EmbedField[] => [
- {
- name: 'Moderator',
- value: `${moderator}`,
- inline: true,
- },
- {
- name: 'Duration',
- value: `${duration}s`,
- inline: true,
- },
+ {
+ name: 'Moderator',
+ value: `${moderator.toString()}`,
+ inline: true,
+ },
+ {
+ name: 'Duration',
+ value: `${duration}s`,
+ inline: true,
+ },
];
export default slashCommand(data, async ({ interaction }) => {
- await interaction.deferReply({ ephemeral: true });
-
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- const start = new Date().getTime();
- try {
- await Promise.all([
- refreshAllPrefixCommandVersionsCache(),
- refreshAllPrefixCommandCategoriesCache(),
- refreshAllPrefixCommandsCache(),
- refreshAllPrefixCommandChannelDefaultVersionsCache(),
- ]);
- } catch (error) {
- await interaction.editReply({ content: `An error occurred while updating the cache: ${error}` });
- return;
- }
-
- const duration = ((new Date().getTime() - start) / 1000).toFixed(2);
+ await interaction.deferReply({ ephemeral: true });
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const start = new Date().getTime();
+ try {
+ await Promise.all([
+ refreshAllPrefixCommandVersionsCache(),
+ refreshAllPrefixCommandCategoriesCache(),
+ refreshAllPrefixCommandsCache(),
+ refreshAllPrefixCommandChannelDefaultVersionsCache(),
+ ]);
+ } catch (error) {
await interaction.editReply({
- embeds: [cacheUpdateEmbed(
- cacheUpdateEmbedField(
- interaction.user,
- duration,
- ),
- Colors.Green,
- )],
+ content: `An error occurred while updating the cache${error instanceof Error && `: ${error}`}`,
});
+ return;
+ }
- try {
- await modLogsChannel.send({
- embeds: [cacheUpdateEmbed(
- cacheUpdateEmbedField(
- interaction.user,
- duration,
- ),
- Colors.Green,
- )],
- });
- } catch (error) {
- await interaction.followUp({ embeds: [noChannelEmbed('mod-log')] });
- }
+ const duration = ((new Date().getTime() - start) / 1000).toFixed(2);
+
+ await interaction.editReply({
+ embeds: [cacheUpdateEmbed(cacheUpdateEmbedField(interaction.user, duration), Colors.Green)],
+ });
+
+ try {
+ await modLogsChannel.send({
+ embeds: [cacheUpdateEmbed(cacheUpdateEmbedField(interaction.user, duration), Colors.Green)],
+ });
+ } catch {
+ await interaction.followUp({ embeds: [noChannelEmbed('mod-log')] });
+ }
});
diff --git a/src/commands/moderation/prefixCommands/prefixCommandPermissions.ts b/src/commands/moderation/prefixCommands/prefixCommandPermissions.ts
index 62d2dd3e..8792fba5 100644
--- a/src/commands/moderation/prefixCommands/prefixCommandPermissions.ts
+++ b/src/commands/moderation/prefixCommands/prefixCommandPermissions.ts
@@ -1,5 +1,12 @@
import { ApplicationCommandOptionChoiceData, ApplicationCommandOptionType, ApplicationCommandType } from 'discord.js';
-import { AutocompleteCallback, constantsConfig, getConn, PrefixCommand, slashCommand, slashCommandStructure } from '../../../lib';
+import {
+ AutocompleteCallback,
+ constantsConfig,
+ getConn,
+ PrefixCommand,
+ slashCommand,
+ slashCommandStructure,
+} from '../../../lib';
import { handleAddPrefixCommandChannelPermission } from './functions/addChannelPermission';
import { handleAddPrefixCommandRolePermission } from './functions/addRolePermission';
import { handleRemovePrefixCommandChannelPermission } from './functions/removeChannelPermission';
@@ -8,235 +15,240 @@ import { handleSetPrefixCommandPermissionSettings } from './functions/setCommand
import { handleShowPrefixCommandPermissions } from './functions/showCommandPermissions';
const data = slashCommandStructure({
- name: 'prefix-command-permissions',
- description: 'Command to manage the permissions of prefix based commands.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
- dm_permission: false,
- options: [
+ name: 'prefix-command-permissions',
+ description: 'Command to manage the permissions of prefix based commands.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
+ dm_permission: false,
+ options: [
+ {
+ name: 'show',
+ description: 'Show the permissions of a prefix command.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
{
- name: 'show',
- description: 'Show the permissions of a prefix command.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- ],
+ name: 'command',
+ description: 'Provide the name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
},
+ ],
+ },
+ {
+ name: 'settings',
+ description: 'Manage prefix command permission settings.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
{
- name: 'settings',
- description: 'Manage prefix command permission settings.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'roles-blocklist',
- description: 'Enable or disable the role blocklist.',
- type: ApplicationCommandOptionType.Boolean,
- required: false,
- },
- {
- name: 'channels-blocklist',
- description: 'Enable or disable the channel blocklist.',
- type: ApplicationCommandOptionType.Boolean,
- required: false,
- },
- {
- name: 'quiet-errors',
- description: 'Enable or disable quiet errors.',
- type: ApplicationCommandOptionType.Boolean,
- required: false,
- },
- {
- name: 'verbose-errors',
- description: 'Enable or disable verbose errors.',
- type: ApplicationCommandOptionType.Boolean,
- required: false,
- },
- ],
+ name: 'command',
+ description: 'Provide the name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
},
{
- name: 'channels',
- description: 'Manage prefix command channel permissions.',
- type: ApplicationCommandOptionType.SubcommandGroup,
- options: [
- {
- name: 'add',
- description: 'Add a channel permission for a prefix command.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'channel',
- description: 'Provide the channel to add or remove from the selected list.',
- type: ApplicationCommandOptionType.Channel,
- required: true,
- },
- ],
- },
- {
- name: 'remove',
- description: 'Remove a channel permission for a prefix command.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'channel',
- description: 'Provide the channel to add or remove from the selected list.',
- type: ApplicationCommandOptionType.Channel,
- required: true,
- },
- ],
- },
- ],
+ name: 'roles-blocklist',
+ description: 'Enable or disable the role blocklist.',
+ type: ApplicationCommandOptionType.Boolean,
+ required: false,
},
{
- name: 'roles',
- description: 'Manage prefix command role permissions.',
- type: ApplicationCommandOptionType.SubcommandGroup,
- options: [
- {
- name: 'add',
- description: 'Add a role permission for a prefix command.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'role',
- description: 'Provide the role to add or remove from the selected list.',
- type: ApplicationCommandOptionType.Role,
- required: true,
- },
- ],
- },
- {
- name: 'remove',
- description: 'Remove a role permission for a prefix command.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'role',
- description: 'Provide the role to add or remove from the selected list.',
- type: ApplicationCommandOptionType.Role,
- required: true,
- },
- ],
- },
- ],
+ name: 'channels-blocklist',
+ description: 'Enable or disable the channel blocklist.',
+ type: ApplicationCommandOptionType.Boolean,
+ required: false,
},
- ],
+ {
+ name: 'quiet-errors',
+ description: 'Enable or disable quiet errors.',
+ type: ApplicationCommandOptionType.Boolean,
+ required: false,
+ },
+ {
+ name: 'verbose-errors',
+ description: 'Enable or disable verbose errors.',
+ type: ApplicationCommandOptionType.Boolean,
+ required: false,
+ },
+ ],
+ },
+ {
+ name: 'channels',
+ description: 'Manage prefix command channel permissions.',
+ type: ApplicationCommandOptionType.SubcommandGroup,
+ options: [
+ {
+ name: 'add',
+ description: 'Add a channel permission for a prefix command.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'command',
+ description: 'Provide the name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'channel',
+ description: 'Provide the channel to add or remove from the selected list.',
+ type: ApplicationCommandOptionType.Channel,
+ required: true,
+ },
+ ],
+ },
+ {
+ name: 'remove',
+ description: 'Remove a channel permission for a prefix command.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'command',
+ description: 'Provide the name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'channel',
+ description: 'Provide the channel to add or remove from the selected list.',
+ type: ApplicationCommandOptionType.Channel,
+ required: true,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ name: 'roles',
+ description: 'Manage prefix command role permissions.',
+ type: ApplicationCommandOptionType.SubcommandGroup,
+ options: [
+ {
+ name: 'add',
+ description: 'Add a role permission for a prefix command.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'command',
+ description: 'Provide the name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'role',
+ description: 'Provide the role to add or remove from the selected list.',
+ type: ApplicationCommandOptionType.Role,
+ required: true,
+ },
+ ],
+ },
+ {
+ name: 'remove',
+ description: 'Remove a role permission for a prefix command.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'command',
+ description: 'Provide the name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'role',
+ description: 'Provide the role to add or remove from the selected list.',
+ type: ApplicationCommandOptionType.Role,
+ required: true,
+ },
+ ],
+ },
+ ],
+ },
+ ],
});
const autocompleteCallback: AutocompleteCallback = async ({ interaction }) => {
- const autoCompleteOption = interaction.options.getFocused(true);
- const { name: optionName, value: searchText } = autoCompleteOption;
- let choices: ApplicationCommandOptionChoiceData[] = [];
+ const autoCompleteOption = interaction.options.getFocused(true);
+ const { name: optionName, value: searchText } = autoCompleteOption;
+ let choices: ApplicationCommandOptionChoiceData[] = [];
- const conn = getConn();
+ const conn = getConn();
- switch (optionName) {
- case 'command':
- if (!conn) {
- return interaction.respond(choices);
- }
- const foundCommands = await PrefixCommand.find({ name: { $regex: searchText, $options: 'i' } })
- .sort({ name: 1 })
- .limit(25);
- for (let i = 0; i < foundCommands.length; i++) {
- const command = foundCommands[i];
- const { name } = command;
- choices.push({ name, value: name });
- }
- break;
- default:
- choices = [];
+ switch (optionName) {
+ case 'command': {
+ if (!conn) {
+ return interaction.respond(choices);
+ }
+ const foundCommands = await PrefixCommand.find({ name: { $regex: searchText, $options: 'i' } })
+ .sort({ name: 1 })
+ .limit(25);
+ for (let i = 0; i < foundCommands.length; i++) {
+ const command = foundCommands[i];
+ const { name } = command;
+ choices.push({ name, value: name });
+ }
+ break;
}
+ default:
+ choices = [];
+ }
- return interaction.respond(choices);
+ return interaction.respond(choices);
};
-export default slashCommand(data, async ({ interaction }) => {
+export default slashCommand(
+ data,
+ async ({ interaction }) => {
const subcommandGroup = interaction.options.getSubcommandGroup();
const subcommandName = interaction.options.getSubcommand();
switch (subcommandName) {
- case 'show':
+ case 'show':
await handleShowPrefixCommandPermissions(interaction);
return;
- case 'settings':
+ case 'settings':
await handleSetPrefixCommandPermissionSettings(interaction);
return;
- default:
+ default:
}
switch (subcommandGroup) {
- case 'channels':
+ case 'channels':
switch (subcommandName) {
- case 'add':
+ case 'add':
await handleAddPrefixCommandChannelPermission(interaction);
break;
- case 'remove':
+ case 'remove':
await handleRemovePrefixCommandChannelPermission(interaction);
break;
- default:
+ default:
await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
}
break;
- case 'roles':
+ case 'roles':
switch (subcommandName) {
- case 'add':
+ case 'add':
await handleAddPrefixCommandRolePermission(interaction);
break;
- case 'remove':
+ case 'remove':
await handleRemovePrefixCommandRolePermission(interaction);
break;
- default:
+ default:
await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
}
break;
- default:
+ default:
await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
}
-}, autocompleteCallback);
+ },
+ autocompleteCallback,
+);
diff --git a/src/commands/moderation/prefixCommands/prefixCommands.ts b/src/commands/moderation/prefixCommands/prefixCommands.ts
index 6662056d..f7c647a5 100644
--- a/src/commands/moderation/prefixCommands/prefixCommands.ts
+++ b/src/commands/moderation/prefixCommands/prefixCommands.ts
@@ -1,5 +1,14 @@
import { ApplicationCommandOptionChoiceData, ApplicationCommandOptionType, ApplicationCommandType } from 'discord.js';
-import { AutocompleteCallback, constantsConfig, getConn, PrefixCommand, PrefixCommandCategory, PrefixCommandVersion, slashCommand, slashCommandStructure } from '../../../lib';
+import {
+ AutocompleteCallback,
+ constantsConfig,
+ getConn,
+ PrefixCommand,
+ PrefixCommandCategory,
+ PrefixCommandVersion,
+ slashCommand,
+ slashCommandStructure,
+} from '../../../lib';
import { handleAddPrefixCommandCategory } from './functions/addCategory';
import { handleModifyPrefixCommandCategory } from './functions/modifyCategory';
import { handleDeletePrefixCommandCategory } from './functions/deleteCategory';
@@ -21,645 +30,652 @@ import { handleDeletePrefixCommandChannelDefaultVersion } from './functions/dele
const colorChoices = [];
for (let i = 0; i < Object.keys(constantsConfig.colors).length; i++) {
- const name = Object.keys(constantsConfig.colors)[i];
- const value = constantsConfig.colors[name];
- colorChoices.push({ name, value });
+ const name = Object.keys(constantsConfig.colors)[i];
+ const value = constantsConfig.colors[name];
+ colorChoices.push({ name, value });
}
const data = slashCommandStructure({
- name: 'prefix-commands',
- description: 'Command to manage prefix based commands.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
- dm_permission: false,
- options: [
+ name: 'prefix-commands',
+ description: 'Command to manage prefix based commands.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
+ dm_permission: false,
+ options: [
+ {
+ name: 'categories',
+ description: 'Manage prefix command categories.',
+ type: ApplicationCommandOptionType.SubcommandGroup,
+ options: [
{
- name: 'categories',
- description: 'Manage prefix command categories.',
- type: ApplicationCommandOptionType.SubcommandGroup,
- options: [
- {
- name: 'add',
- description: 'Add a prefix command category.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'name',
- description: 'Provide a name for the prefix command category.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'emoji',
- description: 'Provide an emoji to identify the prefix command category.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 128,
- },
- ],
- },
- {
- name: 'modify',
- description: 'Modify a prefix command category.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'category',
- description: 'Provide the category name of the prefix command category.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'name',
- description: 'Provide a name for the prefix command category.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 32,
- },
- {
- name: 'emoji',
- description: 'Provide an emoji to identify the prefix command category.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 128,
- },
- ],
- },
- {
- name: 'delete',
- description: 'Delete a prefix command category.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'category',
- description: 'Provide the category name of the prefix command category.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- ],
- },
- {
- name: 'list',
- description: 'Get list of prefix command categories.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'search_text',
- description: 'Provide an optional search term.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 32,
- },
- ],
- },
- ],
+ name: 'add',
+ description: 'Add a prefix command category.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'name',
+ description: 'Provide a name for the prefix command category.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'emoji',
+ description: 'Provide an emoji to identify the prefix command category.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 128,
+ },
+ ],
},
{
- name: 'versions',
- description: 'Manage prefix command versions.',
- type: ApplicationCommandOptionType.SubcommandGroup,
- options: [
- {
- name: 'add',
- description: 'Add a prefix command version.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'name',
- description: 'Provide a name for the prefix command version.',
- type: ApplicationCommandOptionType.String,
- required: true,
- max_length: 32,
- },
- {
- name: 'emoji',
- description: 'Provide an emoji to identify the prefix command version.',
- type: ApplicationCommandOptionType.String,
- required: true,
- max_length: 128,
- },
- {
- name: 'alias',
- description: 'Provide an alias for the prefix command version.',
- type: ApplicationCommandOptionType.String,
- required: true,
- max_length: 32,
- },
- {
- name: 'is_enabled',
- description: 'Indicate wether this version is enabled.',
- type: ApplicationCommandOptionType.Boolean,
- required: false,
- },
- ],
- },
- {
- name: 'modify',
- description: 'Modify a prefix command version.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'version',
- description: 'Provide the name of the prefix command version.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'name',
- description: 'Provide a name for the prefix command version.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 32,
- },
- {
- name: 'emoji',
- description: 'Provide an emoji to identify the prefix command version.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 128,
- },
- {
- name: 'alias',
- description: 'Provide an alias for the prefix command version.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 32,
- },
- {
- name: 'is_enabled',
- description: 'Indicate wether this version is enabled.',
- type: ApplicationCommandOptionType.Boolean,
- required: false,
- },
- ],
- },
- {
- name: 'delete',
- description: 'Delete a prefix command version.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'version',
- description: 'Provide the name of the prefix command version.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'force',
- description: 'Force delete the version even if it is used for command content.',
- type: ApplicationCommandOptionType.Boolean,
- required: false,
- },
- ],
- },
- {
- name: 'list',
- description: 'Get list of prefix command versions.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'search_text',
- description: 'Provide an optional search term.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 32,
- },
- ],
- },
- ],
+ name: 'modify',
+ description: 'Modify a prefix command category.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'category',
+ description: 'Provide the category name of the prefix command category.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'name',
+ description: 'Provide a name for the prefix command category.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 32,
+ },
+ {
+ name: 'emoji',
+ description: 'Provide an emoji to identify the prefix command category.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 128,
+ },
+ ],
},
{
- name: 'commands',
- description: 'Manage prefix commands.',
- type: ApplicationCommandOptionType.SubcommandGroup,
- options: [
- {
- name: 'add',
- description: 'Add a prefix command.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'name',
- description: 'Provide a name for the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- max_length: 32,
- },
- {
- name: 'category',
- description: 'Provide the category for the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'description',
- description: 'Provide a description for the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- max_length: 255,
- },
- {
- name: 'aliases',
- description: 'Provide a comma separated list of aliases for the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 255,
- },
- {
- name: 'is_embed',
- description: 'Indicate wether this prefix command should print as an embed or regular message.',
- type: ApplicationCommandOptionType.Boolean,
- required: false,
- },
- {
- name: 'embed_color',
- description: 'If this command results in an embed, specify the color.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 16,
- choices: colorChoices,
- },
- ],
- },
- {
- name: 'modify',
- description: 'Modify a prefix command.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the command name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 24,
- },
- {
- name: 'name',
- description: 'Provide a name for the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 32,
- },
- {
- name: 'category',
- description: 'Provide the category for the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: false,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'description',
- description: 'Provide a description for the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 255,
- },
- {
- name: 'aliases',
- description: 'Provide a comma separated list of aliases for the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 255,
- },
- {
- name: 'is_embed',
- description: 'Indicate wether this prefix command should print as an embed or regular message.',
- type: ApplicationCommandOptionType.Boolean,
- required: false,
- },
- {
- name: 'embed_color',
- description: 'If this command results in an embed, specify the color.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 16,
- choices: colorChoices,
- },
- ],
- },
- {
- name: 'delete',
- description: 'Delete a prefix command.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the command name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 24,
- },
- ],
- },
- {
- name: 'list',
- description: 'Get list of prefix commands.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'search_text',
- description: 'Provide an optional search term.',
- type: ApplicationCommandOptionType.String,
- required: false,
- max_length: 32,
- },
- ],
- },
- ],
+ name: 'delete',
+ description: 'Delete a prefix command category.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'category',
+ description: 'Provide the category name of the prefix command category.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ ],
},
{
- name: 'content',
- description: 'Manage prefix command content.',
- type: ApplicationCommandOptionType.SubcommandGroup,
- options: [
- {
- name: 'show',
- description: 'Show the details of the content of a command.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'version',
- description: 'Provide the name of the prefix command version. Use GENERIC for the generic content.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- ],
- },
- {
- name: 'set',
- description: 'Set a prefix command\'s content for a specific version.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'version',
- description: 'Provide the name of the prefix command version. Use GENERIC for the generic content.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- ],
- },
- {
- name: 'delete',
- description: 'Delete a prefix command\'s content for a specific version.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'command',
- description: 'Provide the name of the prefix command.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- {
- name: 'version',
- description: 'Provide the name of the prefix command version. Use GENERIC for the generic content.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- ],
- },
- ],
+ name: 'list',
+ description: 'Get list of prefix command categories.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'search_text',
+ description: 'Provide an optional search term.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 32,
+ },
+ ],
},
+ ],
+ },
+ {
+ name: 'versions',
+ description: 'Manage prefix command versions.',
+ type: ApplicationCommandOptionType.SubcommandGroup,
+ options: [
{
- name: 'channel-default-version',
- description: 'Manage prefix command default versions for channels.',
- type: ApplicationCommandOptionType.SubcommandGroup,
- options: [
- {
- name: 'show',
- description: 'Show the default version for a channel.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'channel',
- description: 'Provide the channel to show the default version for.',
- type: ApplicationCommandOptionType.Channel,
- required: true,
- },
- ],
- },
- {
- name: 'set',
- description: 'Set the default version for a channel.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'channel',
- description: 'Provide the channel to set the default version for.',
- type: ApplicationCommandOptionType.Channel,
- required: true,
- },
- {
- name: 'version',
- description: 'Provide the version to set as default.',
- type: ApplicationCommandOptionType.String,
- required: true,
- autocomplete: true,
- max_length: 32,
- },
- ],
- },
- {
- name: 'delete',
- description: 'Delete the default version for a channel.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'channel',
- description: 'Provide the channel to unset the default version for.',
- type: ApplicationCommandOptionType.Channel,
- required: true,
- },
- ],
- },
- ],
+ name: 'add',
+ description: 'Add a prefix command version.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'name',
+ description: 'Provide a name for the prefix command version.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ max_length: 32,
+ },
+ {
+ name: 'emoji',
+ description: 'Provide an emoji to identify the prefix command version.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ max_length: 128,
+ },
+ {
+ name: 'alias',
+ description: 'Provide an alias for the prefix command version.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ max_length: 32,
+ },
+ {
+ name: 'is_enabled',
+ description: 'Indicate wether this version is enabled.',
+ type: ApplicationCommandOptionType.Boolean,
+ required: false,
+ },
+ ],
},
- ],
+ {
+ name: 'modify',
+ description: 'Modify a prefix command version.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'version',
+ description: 'Provide the name of the prefix command version.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'name',
+ description: 'Provide a name for the prefix command version.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 32,
+ },
+ {
+ name: 'emoji',
+ description: 'Provide an emoji to identify the prefix command version.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 128,
+ },
+ {
+ name: 'alias',
+ description: 'Provide an alias for the prefix command version.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 32,
+ },
+ {
+ name: 'is_enabled',
+ description: 'Indicate wether this version is enabled.',
+ type: ApplicationCommandOptionType.Boolean,
+ required: false,
+ },
+ ],
+ },
+ {
+ name: 'delete',
+ description: 'Delete a prefix command version.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'version',
+ description: 'Provide the name of the prefix command version.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'force',
+ description: 'Force delete the version even if it is used for command content.',
+ type: ApplicationCommandOptionType.Boolean,
+ required: false,
+ },
+ ],
+ },
+ {
+ name: 'list',
+ description: 'Get list of prefix command versions.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'search_text',
+ description: 'Provide an optional search term.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 32,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ name: 'commands',
+ description: 'Manage prefix commands.',
+ type: ApplicationCommandOptionType.SubcommandGroup,
+ options: [
+ {
+ name: 'add',
+ description: 'Add a prefix command.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'name',
+ description: 'Provide a name for the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ max_length: 32,
+ },
+ {
+ name: 'category',
+ description: 'Provide the category for the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'description',
+ description: 'Provide a description for the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ max_length: 255,
+ },
+ {
+ name: 'aliases',
+ description: 'Provide a comma separated list of aliases for the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 255,
+ },
+ {
+ name: 'is_embed',
+ description: 'Indicate wether this prefix command should print as an embed or regular message.',
+ type: ApplicationCommandOptionType.Boolean,
+ required: false,
+ },
+ {
+ name: 'embed_color',
+ description: 'If this command results in an embed, specify the color.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 16,
+ choices: colorChoices,
+ },
+ ],
+ },
+ {
+ name: 'modify',
+ description: 'Modify a prefix command.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'command',
+ description: 'Provide the command name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 24,
+ },
+ {
+ name: 'name',
+ description: 'Provide a name for the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 32,
+ },
+ {
+ name: 'category',
+ description: 'Provide the category for the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'description',
+ description: 'Provide a description for the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 255,
+ },
+ {
+ name: 'aliases',
+ description: 'Provide a comma separated list of aliases for the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 255,
+ },
+ {
+ name: 'is_embed',
+ description: 'Indicate wether this prefix command should print as an embed or regular message.',
+ type: ApplicationCommandOptionType.Boolean,
+ required: false,
+ },
+ {
+ name: 'embed_color',
+ description: 'If this command results in an embed, specify the color.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 16,
+ choices: colorChoices,
+ },
+ ],
+ },
+ {
+ name: 'delete',
+ description: 'Delete a prefix command.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'command',
+ description: 'Provide the command name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 24,
+ },
+ ],
+ },
+ {
+ name: 'list',
+ description: 'Get list of prefix commands.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'search_text',
+ description: 'Provide an optional search term.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ max_length: 32,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ name: 'content',
+ description: 'Manage prefix command content.',
+ type: ApplicationCommandOptionType.SubcommandGroup,
+ options: [
+ {
+ name: 'show',
+ description: 'Show the details of the content of a command.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'command',
+ description: 'Provide the name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'version',
+ description: 'Provide the name of the prefix command version. Use GENERIC for the generic content.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ ],
+ },
+ {
+ name: 'set',
+ description: "Set a prefix command's content for a specific version.",
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'command',
+ description: 'Provide the name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'version',
+ description: 'Provide the name of the prefix command version. Use GENERIC for the generic content.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ ],
+ },
+ {
+ name: 'delete',
+ description: "Delete a prefix command's content for a specific version.",
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'command',
+ description: 'Provide the name of the prefix command.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ {
+ name: 'version',
+ description: 'Provide the name of the prefix command version. Use GENERIC for the generic content.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ name: 'channel-default-version',
+ description: 'Manage prefix command default versions for channels.',
+ type: ApplicationCommandOptionType.SubcommandGroup,
+ options: [
+ {
+ name: 'show',
+ description: 'Show the default version for a channel.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'channel',
+ description: 'Provide the channel to show the default version for.',
+ type: ApplicationCommandOptionType.Channel,
+ required: true,
+ },
+ ],
+ },
+ {
+ name: 'set',
+ description: 'Set the default version for a channel.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'channel',
+ description: 'Provide the channel to set the default version for.',
+ type: ApplicationCommandOptionType.Channel,
+ required: true,
+ },
+ {
+ name: 'version',
+ description: 'Provide the version to set as default.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ autocomplete: true,
+ max_length: 32,
+ },
+ ],
+ },
+ {
+ name: 'delete',
+ description: 'Delete the default version for a channel.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'channel',
+ description: 'Provide the channel to unset the default version for.',
+ type: ApplicationCommandOptionType.Channel,
+ required: true,
+ },
+ ],
+ },
+ ],
+ },
+ ],
});
const autocompleteCallback: AutocompleteCallback = async ({ interaction }) => {
- const autoCompleteOption = interaction.options.getFocused(true);
- const { name: optionName, value: searchText } = autoCompleteOption;
- const choices: ApplicationCommandOptionChoiceData[] = [];
+ const autoCompleteOption = interaction.options.getFocused(true);
+ const { name: optionName, value: searchText } = autoCompleteOption;
+ const choices: ApplicationCommandOptionChoiceData[] = [];
- const conn = getConn();
+ const conn = getConn();
- switch (optionName) {
- case 'category':
- if (!conn) {
- return interaction.respond(choices);
- }
- const foundCategories = await PrefixCommandCategory.find({ name: { $regex: searchText, $options: 'i' } })
- .sort({ name: 1 })
- .limit(25);
- for (let i = 0; i < foundCategories.length; i++) {
- const category = foundCategories[i];
- const { name } = category;
- choices.push({ name, value: name });
- }
- break;
- case 'command':
- if (!conn) {
- return interaction.respond(choices);
- }
- const foundCommands = await PrefixCommand.find({ name: { $regex: searchText, $options: 'i' } })
- .sort({ name: 1 })
- .limit(25);
- for (let i = 0; i < foundCommands.length; i++) {
- const command = foundCommands[i];
- const { name } = command;
- choices.push({ name, value: name });
- }
- break;
- case 'version':
- choices.push({ name: 'GENERIC', value: 'GENERIC' });
- if (!conn) {
- return interaction.respond(choices);
- }
- const foundVersions = await PrefixCommandVersion.find({ name: { $regex: searchText, $options: 'i' } })
- .sort({ name: 1 })
- .limit(25);
- for (let i = 0; i < foundVersions.length; i++) {
- const version = foundVersions[i];
- const { name } = version;
- choices.push({ name, value: name });
- }
- break;
- default:
- break;
+ switch (optionName) {
+ case 'category': {
+ if (!conn) {
+ return interaction.respond(choices);
+ }
+ const foundCategories = await PrefixCommandCategory.find({ name: { $regex: searchText, $options: 'i' } })
+ .sort({ name: 1 })
+ .limit(25);
+ for (let i = 0; i < foundCategories.length; i++) {
+ const category = foundCategories[i];
+ const { name } = category;
+ choices.push({ name, value: name });
+ }
+ break;
+ }
+ case 'command': {
+ if (!conn) {
+ return interaction.respond(choices);
+ }
+ const foundCommands = await PrefixCommand.find({ name: { $regex: searchText, $options: 'i' } })
+ .sort({ name: 1 })
+ .limit(25);
+ for (let i = 0; i < foundCommands.length; i++) {
+ const command = foundCommands[i];
+ const { name } = command;
+ choices.push({ name, value: name });
+ }
+ break;
+ }
+ case 'version': {
+ choices.push({ name: 'GENERIC', value: 'GENERIC' });
+ if (!conn) {
+ return interaction.respond(choices);
+ }
+ const foundVersions = await PrefixCommandVersion.find({ name: { $regex: searchText, $options: 'i' } })
+ .sort({ name: 1 })
+ .limit(25);
+ for (let i = 0; i < foundVersions.length; i++) {
+ const version = foundVersions[i];
+ const { name } = version;
+ choices.push({ name, value: name });
+ }
+ break;
}
+ default:
+ break;
+ }
- return interaction.respond(choices);
+ return interaction.respond(choices);
};
-export default slashCommand(data, async ({ interaction }) => {
+export default slashCommand(
+ data,
+ async ({ interaction }) => {
const subcommandGroup = interaction.options.getSubcommandGroup();
const subcommandName = interaction.options.getSubcommand();
switch (subcommandGroup) {
- case 'categories':
+ case 'categories':
switch (subcommandName) {
- case 'add':
+ case 'add':
await handleAddPrefixCommandCategory(interaction);
break;
- case 'modify':
+ case 'modify':
await handleModifyPrefixCommandCategory(interaction);
break;
- case 'delete':
+ case 'delete':
await handleDeletePrefixCommandCategory(interaction);
break;
- case 'list':
+ case 'list':
await handleListPrefixCommandCategories(interaction);
break;
- default:
+ default:
await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
}
break;
- case 'versions':
+ case 'versions':
switch (subcommandName) {
- case 'add':
+ case 'add':
await handleAddPrefixCommandVersion(interaction);
break;
- case 'modify':
+ case 'modify':
await handleModifyPrefixCommandVersion(interaction);
break;
- case 'delete':
+ case 'delete':
await handleDeletePrefixCommandVersion(interaction);
break;
- case 'list':
+ case 'list':
await handleListPrefixCommandVersions(interaction);
break;
- default:
+ default:
await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
}
break;
- case 'commands':
+ case 'commands':
switch (subcommandName) {
- case 'add':
+ case 'add':
await handleAddPrefixCommand(interaction);
break;
- case 'modify':
+ case 'modify':
await handleModifyPrefixCommand(interaction);
break;
- case 'delete':
+ case 'delete':
await handleDeletePrefixCommand(interaction);
break;
- case 'list':
+ case 'list':
await handleListPrefixCommands(interaction);
break;
- default:
+ default:
await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
}
break;
- case 'content':
+ case 'content':
switch (subcommandName) {
- case 'show':
+ case 'show':
await handleShowPrefixCommandContent(interaction);
break;
- case 'set':
+ case 'set':
await handleSetPrefixCommandContent(interaction);
break;
- case 'delete':
+ case 'delete':
await handleDeletePrefixCommandContent(interaction);
break;
- default:
+ default:
await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
}
break;
- case 'channel-default-version':
+ case 'channel-default-version':
switch (subcommandName) {
- case 'show':
+ case 'show':
await handleShowPrefixCommandChannelDefaultVersion(interaction);
break;
- case 'set':
+ case 'set':
await handleSetPrefixCommandChannelDefaultVersion(interaction);
break;
- case 'delete':
+ case 'delete':
await handleDeletePrefixCommandChannelDefaultVersion(interaction);
break;
- default:
+ default:
await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
}
break;
- default:
+ default:
await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
}
-}, autocompleteCallback);
+ },
+ autocompleteCallback,
+);
diff --git a/src/commands/moderation/roleAssignment.ts b/src/commands/moderation/roleAssignment.ts
index 0ad0c832..fe4adab3 100644
--- a/src/commands/moderation/roleAssignment.ts
+++ b/src/commands/moderation/roleAssignment.ts
@@ -1,104 +1,100 @@
-import {
- ActionRowBuilder,
- ApplicationCommandType,
- ButtonBuilder,
- ButtonStyle,
-} from 'discord.js';
+import { ActionRowBuilder, ApplicationCommandType, ButtonBuilder, ButtonStyle } from 'discord.js';
import { constantsConfig, makeEmbed, slashCommand, slashCommandStructure } from '../../lib';
const data = slashCommandStructure({
- name: 'role-assignment',
- description: 'Configures and sends the role assignment embed.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator
- dm_permission: false,
+ name: 'role-assignment',
+ description: 'Configures and sends the role assignment embed.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator
+ dm_permission: false,
});
const interestedInEmbed = makeEmbed({
- title: 'Role Assignment',
- description: 'Please react below to set your role according to your skill set. If you do not have the skills in any of the available roles, please do not react as this will not benefit the development of the addon.',
+ title: 'Role Assignment',
+ description:
+ 'Please react below to set your role according to your skill set. If you do not have the skills in any of the available roles, please do not react as this will not benefit the development of the addon.',
});
const mediaAnnouncementsEmbed = makeEmbed({
- title: 'Media Announcements',
- description: 'Please react to the corresponding buttons to be pinged for the various announcements.',
+ title: 'Media Announcements',
+ description: 'Please react to the corresponding buttons to be pinged for the various announcements.',
});
function splitButtonsIntoRows(buttons: ButtonBuilder[], maxButtonsPerRow: number): ButtonBuilder[][] {
- const rows: ButtonBuilder[][] = [];
- let currentRow: ButtonBuilder[] = [];
+ const rows: ButtonBuilder[][] = [];
+ let currentRow: ButtonBuilder[] = [];
- for (const button of buttons) {
- currentRow.push(button);
+ for (const button of buttons) {
+ currentRow.push(button);
- if (currentRow.length === maxButtonsPerRow) {
- rows.push([...currentRow]);
- currentRow = [];
- }
+ if (currentRow.length === maxButtonsPerRow) {
+ rows.push([...currentRow]);
+ currentRow = [];
}
+ }
- if (currentRow.length > 0) {
- rows.push([...currentRow]);
- }
+ if (currentRow.length > 0) {
+ rows.push([...currentRow]);
+ }
- return rows;
+ return rows;
}
export default slashCommand(data, async ({ interaction }) => {
- const maxButtonsPerRow = 5; // Define the maximum buttons per row
-
- const interestedInButtons: ButtonBuilder[] = [];
- const mediaAnnouncementsButtons: ButtonBuilder[] = [];
-
- const { roleAssignmentIds } = constantsConfig;
- roleAssignmentIds.forEach((group) => {
- group.roles.forEach((role) => {
- const button = new ButtonBuilder()
- .setCustomId(`roleAssignment_${role.id}`)
- .setLabel(role.label)
- .setStyle(ButtonStyle.Primary);
-
- if (group.group === 'interestedIn') {
- interestedInButtons.push(button);
- } else if (group.group === 'mediaAnnouncements') {
- mediaAnnouncementsButtons.push(button);
- }
- });
- });
-
- // Split the buttons into rows
- const interestedInRows = splitButtonsIntoRows(interestedInButtons, maxButtonsPerRow);
- const mediaAnnouncementsRows = splitButtonsIntoRows(mediaAnnouncementsButtons, maxButtonsPerRow);
-
- if (!interaction.channel) {
- await interaction.reply({ content: 'Interaction channel is null.', ephemeral: true });
- return;
- }
-
- // Create a single embed for each group type and add all rows to it
- const interestedInEmbedWithRows = {
- embeds: [interestedInEmbed],
- components: [] as ActionRowBuilder[],
- };
-
- const mediaAnnouncementsEmbedWithRows = {
- embeds: [mediaAnnouncementsEmbed],
- components: [] as ActionRowBuilder[],
- };
-
- interestedInRows.forEach((row) => {
- const actionRow: ActionRowBuilder = new ActionRowBuilder().addComponents(...row);
- interestedInEmbedWithRows.components.push(actionRow);
- });
-
- mediaAnnouncementsRows.forEach((row) => {
- const actionRow: ActionRowBuilder = new ActionRowBuilder().addComponents(...row);
- mediaAnnouncementsEmbedWithRows.components.push(actionRow);
+ const maxButtonsPerRow = 5; // Define the maximum buttons per row
+
+ const interestedInButtons: ButtonBuilder[] = [];
+ const mediaAnnouncementsButtons: ButtonBuilder[] = [];
+
+ const { roleAssignmentIds } = constantsConfig;
+ roleAssignmentIds.forEach((group) => {
+ group.roles.forEach((role) => {
+ const button = new ButtonBuilder()
+ .setCustomId(`roleAssignment_${role.id}`)
+ .setLabel(role.label)
+ .setStyle(ButtonStyle.Primary);
+
+ if (group.group === 'interestedIn') {
+ interestedInButtons.push(button);
+ } else if (group.group === 'mediaAnnouncements') {
+ mediaAnnouncementsButtons.push(button);
+ }
});
-
- // Send the embeds with attached rows
- await interaction.channel.send(interestedInEmbedWithRows);
- await interaction.channel.send(mediaAnnouncementsEmbedWithRows);
-
- await interaction.reply({ content: 'Role assignment embeds sent.', ephemeral: true });
+ });
+
+ // Split the buttons into rows
+ const interestedInRows = splitButtonsIntoRows(interestedInButtons, maxButtonsPerRow);
+ const mediaAnnouncementsRows = splitButtonsIntoRows(mediaAnnouncementsButtons, maxButtonsPerRow);
+
+ if (!interaction.channel) {
+ await interaction.reply({ content: 'Interaction channel is null.', ephemeral: true });
+ return;
+ }
+
+ // Create a single embed for each group type and add all rows to it
+ const interestedInEmbedWithRows = {
+ embeds: [interestedInEmbed],
+ components: [] as ActionRowBuilder[],
+ };
+
+ const mediaAnnouncementsEmbedWithRows = {
+ embeds: [mediaAnnouncementsEmbed],
+ components: [] as ActionRowBuilder[],
+ };
+
+ interestedInRows.forEach((row) => {
+ const actionRow: ActionRowBuilder = new ActionRowBuilder().addComponents(...row);
+ interestedInEmbedWithRows.components.push(actionRow);
+ });
+
+ mediaAnnouncementsRows.forEach((row) => {
+ const actionRow: ActionRowBuilder = new ActionRowBuilder().addComponents(...row);
+ mediaAnnouncementsEmbedWithRows.components.push(actionRow);
+ });
+
+ // Send the embeds with attached rows
+ await interaction.channel.send(interestedInEmbedWithRows);
+ await interaction.channel.send(mediaAnnouncementsEmbedWithRows);
+
+ await interaction.reply({ content: 'Role assignment embeds sent.', ephemeral: true });
});
diff --git a/src/commands/moderation/rules.ts b/src/commands/moderation/rules.ts
index c0c83960..8da14c9a 100644
--- a/src/commands/moderation/rules.ts
+++ b/src/commands/moderation/rules.ts
@@ -2,74 +2,76 @@ import { ApplicationCommandType } from 'discord.js';
import { constantsConfig, slashCommand, slashCommandStructure, makeEmbed, makeLines } from '../../lib';
const data = slashCommandStructure({
- name: 'rules',
- description: 'Lists server rules.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator
- dm_permission: false,
+ name: 'rules',
+ description: 'Lists server rules.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator
+ dm_permission: false,
});
const RULES_EMBED = makeEmbed({
- title: 'FlyByWire Simulations Server Rules',
- description: makeLines([
- 'Below are the rules you must follow to participate in this discord server. Failure to abide by these rules could result in a removal from the server. Mute/ban evasions will result in a permanent ban.',
- '',
- `The <@&${constantsConfig.roles.MODERATION_TEAM}> reserve the right to action at discretion.`,
- ]),
+ title: 'FlyByWire Simulations Server Rules',
+ description: makeLines([
+ 'Below are the rules you must follow to participate in this discord server. Failure to abide by these rules could result in a removal from the server. Mute/ban evasions will result in a permanent ban.',
+ '',
+ `The <@&${constantsConfig.roles.MODERATION_TEAM}> reserve the right to action at discretion.`,
+ ]),
});
const FAQ_EMBED = makeEmbed({
- title: '<:question:759405702044975114> Frequently Asked Questions',
- description: `Check the <#${constantsConfig.channels.FAQ}> for the answers to your questions prior to asking in the channels below, post your question in the appropriate channel.`,
+ title: '<:question:759405702044975114> Frequently Asked Questions',
+ description: `Check the <#${constantsConfig.channels.FAQ}> for the answers to your questions prior to asking in the channels below, post your question in the appropriate channel.`,
});
const POLICIES_EMBED = makeEmbed({
- title: '<:bookmark_tabs:759405704644788256> Discord Policies',
- description: 'Whilst using Discord, you are subject to both the Terms of Service, and its Community Guidelines:',
- fields: [
- {
- name: 'ToS -',
- value: 'https://discordapp.com/terms',
- },
- {
- name: 'Guidelines -',
- value: 'https://discordapp.com/guidelines',
- },
- ],
+ title: '<:bookmark_tabs:759405704644788256> Discord Policies',
+ description: 'Whilst using Discord, you are subject to both the Terms of Service, and its Community Guidelines:',
+ fields: [
+ {
+ name: 'ToS -',
+ value: 'https://discordapp.com/terms',
+ },
+ {
+ name: 'Guidelines -',
+ value: 'https://discordapp.com/guidelines',
+ },
+ ],
});
const DISCUSSION_EMBED = makeEmbed({
- title: '<:speech_balloon:759405706804723742> Appropriate Discussion',
- description: makeLines([
- 'The prime purpose of this server is to discuss flight sim and aviation topics. Respectful and friendly discussions of general topics in the server are welcome; however, we expect everyone to follow Discord policies and good housekeeping.',
- '',
- '- If you have a message, please post it in the appropriate channel',
- '- Send your message once; do not repeat messages',
- '- Do not send malicious or illegal content',
- '- Use of slurs or any form of bigotry is not tolerated',
- '- No inappropriate, NSFW or NSFL content like (but not limited to) nudity, pornography, gore, ...',
- '- No general spam',
- '- Do not send multiple unsolicited DM\'s',
- '- No troll or insensitive messaging, including insensitive inside jokes',
- '- Inappropriate/offensive profile information/picture will not be tolerated',
- '- Certain topics like politics, religion and other sensitive subjects will only be tolerated if a careful and respectful conversation is held',
- `- Self promotion is not permitted except in the case of YouTube/Twitch content etc. which can be promoted in <#${constantsConfig.channels.VIDEOS}>`,
- '- To help with moderation and set a standard the server language is English',
- '',
- 'Moderators and admins will intervene when there is a risk for escalation or when the situation requires to keep the server friendly and tolerant.',
- ]),
+ title: '<:speech_balloon:759405706804723742> Appropriate Discussion',
+ description: makeLines([
+ 'The prime purpose of this server is to discuss flight sim and aviation topics. Respectful and friendly discussions of general topics in the server are welcome; however, we expect everyone to follow Discord policies and good housekeeping.',
+ '',
+ '- If you have a message, please post it in the appropriate channel',
+ '- Send your message once; do not repeat messages',
+ '- Do not send malicious or illegal content',
+ '- Use of slurs or any form of bigotry is not tolerated',
+ '- No inappropriate, NSFW or NSFL content like (but not limited to) nudity, pornography, gore, ...',
+ '- No general spam',
+ "- Do not send multiple unsolicited DM's",
+ '- No troll or insensitive messaging, including insensitive inside jokes',
+ '- Inappropriate/offensive profile information/picture will not be tolerated',
+ '- Certain topics like politics, religion and other sensitive subjects will only be tolerated if a careful and respectful conversation is held',
+ `- Self promotion is not permitted except in the case of YouTube/Twitch content etc. which can be promoted in <#${constantsConfig.channels.VIDEOS}>`,
+ '- To help with moderation and set a standard the server language is English',
+ '',
+ 'Moderators and admins will intervene when there is a risk for escalation or when the situation requires to keep the server friendly and tolerant.',
+ ]),
});
const ROLE_EMBED = makeEmbed({
- title: '<:person_raising_hand:759405708994281493> Role Assignment',
- description: `We encourage people to use their vast experience and knowledge to help us create a highly detailed addon. If you have skills in Documentation, Modelling and/or Programming, please assign your <#${constantsConfig.channels.ROLES}> and get started with the conversation to help us develop the addon.`,
+ title: '<:person_raising_hand:759405708994281493> Role Assignment',
+ description: `We encourage people to use their vast experience and knowledge to help us create a highly detailed addon. If you have skills in Documentation, Modelling and/or Programming, please assign your <#${constantsConfig.channels.ROLES}> and get started with the conversation to help us develop the addon.`,
});
export default slashCommand(data, async ({ interaction }) => {
- if (interaction.channel) {
- await interaction.channel.send({ embeds: [RULES_EMBED, FAQ_EMBED, POLICIES_EMBED, DISCUSSION_EMBED, ROLE_EMBED] });
- } else {
- await interaction.reply({ content: 'This command can only be used in a server.', ephemeral: true });
- }
- await interaction.reply({ content: 'Rules sent.', ephemeral: true });
+ if (interaction.channel) {
+ await interaction.channel.send({
+ embeds: [RULES_EMBED, FAQ_EMBED, POLICIES_EMBED, DISCUSSION_EMBED, ROLE_EMBED],
+ });
+ } else {
+ await interaction.reply({ content: 'This command can only be used in a server.', ephemeral: true });
+ }
+ await interaction.reply({ content: 'Rules sent.', ephemeral: true });
});
diff --git a/src/commands/moderation/slowmode/functions/disable.ts b/src/commands/moderation/slowmode/functions/disable.ts
index 2f5dd384..4e485fe7 100644
--- a/src/commands/moderation/slowmode/functions/disable.ts
+++ b/src/commands/moderation/slowmode/functions/disable.ts
@@ -1,34 +1,50 @@
-import { ChannelType, ChatInputCommandInteraction, Colors } from 'discord.js';
+import { ChannelType, ChatInputCommandInteraction, Colors, EmbedBuilder, EmbedField, TextChannel } from 'discord.js';
import { Logger } from '../../../../lib';
+import { SlowmodeChannel } from '../slowmode';
+import { Agenda } from '@hokify/agenda';
-export async function handleDisableSlowmode(interaction: ChatInputCommandInteraction<'cached'>, slowmodeChannel: any, modLogsChannel: any, scheduler: any, failedEmbed: any, noChannelEmbed: any, successEmbed: any, modLogEmbed: any, slowModeEmbedField: any) {
- try {
- if (slowmodeChannel.type === ChannelType.GuildForum || slowmodeChannel.type === ChannelType.GuildText || slowmodeChannel.type === ChannelType.PrivateThread || slowmodeChannel.type === ChannelType.PublicThread) {
- await slowmodeChannel.setRateLimitPerUser(0, 'Slow mode disabled through bot');
- if (scheduler) {
- await scheduler.cancel({ name: 'autoDisableSlowMode', data: { channelId: slowmodeChannel.id } });
- }
- }
- } catch (error) {
- Logger.error(error);
- await interaction.reply({ embeds: [failedEmbed('Disable', slowmodeChannel.id)] });
- return;
+export async function handleDisableSlowmode(
+ interaction: ChatInputCommandInteraction<'cached'>,
+ slowmodeChannel: SlowmodeChannel,
+ modLogsChannel: TextChannel,
+ scheduler: Agenda | null,
+ failedEmbed: (action: string, channel: string) => EmbedBuilder,
+ noChannelEmbed: (action: string, channel: string) => EmbedBuilder,
+ successEmbed: (action: string, channel: string) => EmbedBuilder,
+ modLogEmbed: (action: string, fields: EmbedField[], color: number) => EmbedBuilder,
+ slowModeEmbedField: (moderator: string, channel: string, duration: number, autoDisable: string) => EmbedField[],
+) {
+ try {
+ if (
+ slowmodeChannel.type === ChannelType.GuildForum ||
+ slowmodeChannel.type === ChannelType.GuildText ||
+ slowmodeChannel.type === ChannelType.PrivateThread ||
+ slowmodeChannel.type === ChannelType.PublicThread
+ ) {
+ await slowmodeChannel.setRateLimitPerUser(0, 'Slow mode disabled through bot');
+ if (scheduler) {
+ await scheduler.cancel({ name: 'autoDisableSlowMode', data: { channelId: slowmodeChannel.id } });
+ }
}
+ } catch (error) {
+ Logger.error(error);
+ await interaction.reply({ embeds: [failedEmbed('Disable', slowmodeChannel.id)] });
+ return;
+ }
- try {
- await modLogsChannel.send({
- embeds: [modLogEmbed('disabled',
- slowModeEmbedField(
- interaction.user.toString(),
- slowmodeChannel.id,
- 0,
- 0,
- ),
- Colors.Green)],
- });
- } catch {
- await interaction.reply({ embeds: [noChannelEmbed('Disable', 'Mod Log')] });
- }
+ try {
+ await modLogsChannel.send({
+ embeds: [
+ modLogEmbed(
+ 'disabled',
+ slowModeEmbedField(interaction.user.toString(), slowmodeChannel.id, 0, '0'),
+ Colors.Green,
+ ),
+ ],
+ });
+ } catch {
+ await interaction.reply({ embeds: [noChannelEmbed('Disable', 'Mod Log')] });
+ }
- await interaction.reply({ embeds: [successEmbed('Disable', slowmodeChannel.id)], ephemeral: true });
+ await interaction.reply({ embeds: [successEmbed('Disable', slowmodeChannel.id)], ephemeral: true });
}
diff --git a/src/commands/moderation/slowmode/functions/set.ts b/src/commands/moderation/slowmode/functions/set.ts
index 857d504b..fa97810a 100644
--- a/src/commands/moderation/slowmode/functions/set.ts
+++ b/src/commands/moderation/slowmode/functions/set.ts
@@ -1,37 +1,60 @@
-import { ChannelType, ChatInputCommandInteraction, Colors } from 'discord.js';
+import { Agenda } from '@hokify/agenda';
+import { ChannelType, ChatInputCommandInteraction, Colors, EmbedBuilder, EmbedField, TextChannel } from 'discord.js';
+import { SlowmodeChannel } from '../slowmode';
-export async function handleSetSlowmode(interaction: ChatInputCommandInteraction<'cached'>, duration: number, slowmodeChannel: any, autoDisable: any, modLogsChannel: any, scheduler: any, failedEmbed: any, noChannelEmbed: any, successEmbed: any, modLogEmbed: any, slowModeEmbedField: any) {
- try {
- if (slowmodeChannel.type === ChannelType.GuildForum || slowmodeChannel.type === ChannelType.GuildText || slowmodeChannel.type === ChannelType.PrivateThread || slowmodeChannel.type === ChannelType.PublicThread) {
- await slowmodeChannel.setRateLimitPerUser(duration / 1000, 'Slow mode enabled through bot');
- if (scheduler) {
- await scheduler.cancel({ name: 'autoDisableSlowMode', data: { channelId: slowmodeChannel.id } });
- if (autoDisable) {
- const executionDate: Date = new Date(Date.now() + autoDisable);
- await scheduler.schedule(executionDate, 'autoDisableSlowMode', { channelId: slowmodeChannel.id });
- }
- }
+export async function handleSetSlowmode(
+ interaction: ChatInputCommandInteraction<'cached'>,
+ duration: number,
+ slowmodeChannel: SlowmodeChannel,
+ autoDisable: number | null,
+ modLogsChannel: TextChannel,
+ scheduler: Agenda | null,
+ failedEmbed: (action: string, channel: string) => EmbedBuilder,
+ noChannelEmbed: (action: string, channel: string) => EmbedBuilder,
+ successEmbed: (action: string, channel: string) => EmbedBuilder,
+ modLogEmbed: (action: string, fields: EmbedField[], color: number) => EmbedBuilder,
+ slowModeEmbedField: (moderator: string, channel: string, duration: number, autoDisable: string) => EmbedField[],
+) {
+ try {
+ if (
+ slowmodeChannel.type === ChannelType.GuildForum ||
+ slowmodeChannel.type === ChannelType.GuildText ||
+ slowmodeChannel.type === ChannelType.PrivateThread ||
+ slowmodeChannel.type === ChannelType.PublicThread
+ ) {
+ await slowmodeChannel.setRateLimitPerUser(duration / 1000, 'Slow mode enabled through bot');
+ if (scheduler) {
+ await scheduler.cancel({ name: 'autoDisableSlowMode', data: { channelId: slowmodeChannel.id } });
+ if (autoDisable) {
+ const executionDate: Date = new Date(Date.now() + autoDisable);
+ await scheduler.schedule(executionDate, 'autoDisableSlowMode', { channelId: slowmodeChannel.id });
}
- } catch {
- await interaction.reply({ embeds: [failedEmbed('set', slowmodeChannel.id)], ephemeral: true });
- return;
+ }
}
+ } catch {
+ await interaction.reply({ embeds: [failedEmbed('set', slowmodeChannel.id)], ephemeral: true });
+ return;
+ }
- try {
- await modLogsChannel.send({
- embeds: [modLogEmbed('Set',
- slowModeEmbedField(
- interaction.user.toString(),
- slowmodeChannel.id,
- duration,
- autoDisable && scheduler ? autoDisable.toString() : 0,
- ),
- Colors.Green)],
- });
- } catch {
- await interaction.reply({ embeds: [noChannelEmbed('set', 'mod logs')], ephemeral: true });
- return;
- }
+ try {
+ await modLogsChannel.send({
+ embeds: [
+ modLogEmbed(
+ 'Set',
+ slowModeEmbedField(
+ interaction.user.toString(),
+ slowmodeChannel.id,
+ duration,
+ autoDisable && scheduler ? autoDisable.toString() : '0',
+ ),
+ Colors.Green,
+ ),
+ ],
+ });
+ } catch {
+ await interaction.reply({ embeds: [noChannelEmbed('set', 'mod logs')], ephemeral: true });
+ return;
+ }
- await interaction.reply({ embeds: [successEmbed('set', slowmodeChannel.id)], ephemeral: true });
+ await interaction.reply({ embeds: [successEmbed('set', slowmodeChannel.id)], ephemeral: true });
}
diff --git a/src/commands/moderation/slowmode/slowmode.ts b/src/commands/moderation/slowmode/slowmode.ts
index f192e5c0..c6dd3254 100644
--- a/src/commands/moderation/slowmode/slowmode.ts
+++ b/src/commands/moderation/slowmode/slowmode.ts
@@ -1,159 +1,222 @@
-import { ApplicationCommandOptionType, ApplicationCommandType, Colors, EmbedField, TextChannel } from 'discord.js';
-import { constantsConfig, slashCommand, slashCommandStructure, makeEmbed, durationInEnglish, getScheduler } from '../../../lib';
-import { handleSetSlowmode } from './functions/set';
+import {
+ ApplicationCommandOptionType,
+ ApplicationCommandType,
+ CategoryChannel,
+ Colors,
+ EmbedField,
+ ForumChannel,
+ MediaChannel,
+ NewsChannel,
+ PrivateThreadChannel,
+ PublicThreadChannel,
+ StageChannel,
+ TextChannel,
+ VoiceChannel,
+} from 'discord.js';
+import {
+ constantsConfig,
+ durationInEnglish,
+ getScheduler,
+ makeEmbed,
+ slashCommand,
+ slashCommandStructure,
+} from '../../../lib';
import { handleDisableSlowmode } from './functions/disable';
+import { handleSetSlowmode } from './functions/set';
const data = slashCommandStructure({
- name: 'slowmode',
- description: 'Command to manage slowmode.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
- dm_permission: false,
- options: [
+ name: 'slowmode',
+ description: 'Command to manage slowmode.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
+ dm_permission: false,
+ options: [
+ {
+ name: 'set',
+ description: 'Set the slowmode for the channel.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'duration',
+ description: 'Please provide a duration.',
+ type: ApplicationCommandOptionType.Number,
+ required: true,
+ choices: [
+ { name: '5 Seconds', value: 5000 },
+ { name: '10 Seconds', value: 10000 },
+ { name: '15 Seconds', value: 15000 },
+ { name: '30 Seconds', value: 30000 },
+ { name: '1 Minute', value: 60000 },
+ { name: '5 minutes', value: 300000 },
+ { name: '10 minutes', value: 600000 },
+ { name: '15 minutes', value: 900000 },
+ { name: '30 minutes', value: 1800000 },
+ { name: '1 hour', value: 3600000 },
+ { name: '3 hours', value: 10800000 },
+ { name: '6 hours', value: 21600000 },
+ ],
+ },
+ {
+ name: 'channel',
+ description: 'Please provide a channel.',
+ type: ApplicationCommandOptionType.Channel,
+ required: false,
+ },
{
- name: 'set',
- description: 'Set the slowmode for the channel.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'duration',
- description: 'Please provide a duration.',
- type: ApplicationCommandOptionType.Number,
- required: true,
- choices: [
- { name: '5 Seconds', value: 5000 },
- { name: '10 Seconds', value: 10000 },
- { name: '15 Seconds', value: 15000 },
- { name: '30 Seconds', value: 30000 },
- { name: '1 Minute', value: 60000 },
- { name: '5 minutes', value: 300000 },
- { name: '10 minutes', value: 600000 },
- { name: '15 minutes', value: 900000 },
- { name: '30 minutes', value: 1800000 },
- { name: '1 hour', value: 3600000 },
- { name: '3 hours', value: 10800000 },
- { name: '6 hours', value: 21600000 },
- ],
- },
- {
- name: 'channel',
- description: 'Please provide a channel.',
- type: ApplicationCommandOptionType.Channel,
- required: false,
- },
- {
- name: 'auto-disable',
- description: 'Please provide a duration.',
- type: ApplicationCommandOptionType.Number,
- required: false,
- choices: [
- { name: '1 Minute', value: 60000 },
- { name: '5 minutes', value: 300000 },
- { name: '10 minutes', value: 600000 },
- { name: '15 minutes', value: 900000 },
- { name: '30 minutes', value: 1800000 },
- { name: '1 hour', value: 3600000 },
- { name: '3 hours', value: 10800000 },
- { name: '6 hours', value: 21600000 },
- { name: '12 hours', value: 43200000 },
- { name: '1 day', value: 86400000 },
- { name: '3 days', value: 259200000 },
- { name: '1 week', value: 604800000 },
- ],
- },
- ],
+ name: 'auto-disable',
+ description: 'Please provide a duration.',
+ type: ApplicationCommandOptionType.Number,
+ required: false,
+ choices: [
+ { name: '1 Minute', value: 60000 },
+ { name: '5 minutes', value: 300000 },
+ { name: '10 minutes', value: 600000 },
+ { name: '15 minutes', value: 900000 },
+ { name: '30 minutes', value: 1800000 },
+ { name: '1 hour', value: 3600000 },
+ { name: '3 hours', value: 10800000 },
+ { name: '6 hours', value: 21600000 },
+ { name: '12 hours', value: 43200000 },
+ { name: '1 day', value: 86400000 },
+ { name: '3 days', value: 259200000 },
+ { name: '1 week', value: 604800000 },
+ ],
},
+ ],
+ },
+ {
+ name: 'disable',
+ description: 'Disable the slowmode for the channel.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
{
- name: 'disable',
- description: 'Disable the slowmode for the channel.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'channel',
- description: 'Please provide a channel.',
- type: ApplicationCommandOptionType.Channel,
- required: false,
- },
- ],
+ name: 'channel',
+ description: 'Please provide a channel.',
+ type: ApplicationCommandOptionType.Channel,
+ required: false,
},
- ],
+ ],
+ },
+ ],
});
+export type SlowmodeChannel =
+ | CategoryChannel
+ | NewsChannel
+ | StageChannel
+ | TextChannel
+ | PrivateThreadChannel
+ | PublicThreadChannel
+ | VoiceChannel
+ | ForumChannel
+ | MediaChannel;
+
const noSchedulerEmbed = makeEmbed({
- title: 'Slow Mode - No scheduler',
- description: 'Could not find an active scheduler. No automatic disable can be scheduled.',
- color: Colors.Red,
+ title: 'Slow Mode - No scheduler',
+ description: 'Could not find an active scheduler. No automatic disable can be scheduled.',
+ color: Colors.Red,
});
-const failedEmbed = (action: string, channel: string) => makeEmbed({
+const failedEmbed = (action: string, channel: string) =>
+ makeEmbed({
title: `Slow Mode - ${action} failed`,
description: `Failed to ${action} the slow mode for channel <@${channel}>.`,
color: Colors.Red,
-});
+ });
-const modLogEmbed = (action: string, fields: any, color: number) => makeEmbed({
+const modLogEmbed = (action: string, fields: EmbedField[], color: number) =>
+ makeEmbed({
title: `Slow Mode - ${action}`,
fields,
color,
-});
+ });
-const slowModeEmbedField = (moderator: string, channel: string, duration: number, autoDisable: string): EmbedField[] => [
- {
- inline: true,
- name: 'Channel',
- value: `<#${channel}>`,
- },
- {
- inline: true,
- name: 'Slow mode limit',
- value: durationInEnglish(duration),
- },
- {
- inline: true,
- name: 'Auto disable timeout',
- value: durationInEnglish(autoDisable),
- },
- {
- inline: true,
- name: 'Moderator',
- value: moderator,
- },
+const slowModeEmbedField = (
+ moderator: string,
+ channel: string,
+ duration: number,
+ autoDisable: string,
+): EmbedField[] => [
+ {
+ inline: true,
+ name: 'Channel',
+ value: `<#${channel}>`,
+ },
+ {
+ inline: true,
+ name: 'Slow mode limit',
+ value: durationInEnglish(duration),
+ },
+ {
+ inline: true,
+ name: 'Auto disable timeout',
+ value: durationInEnglish(Number.parseInt(autoDisable)),
+ },
+ {
+ inline: true,
+ name: 'Moderator',
+ value: moderator,
+ },
];
-const noChannelEmbed = (action:string, channelName: string) => makeEmbed({
+const noChannelEmbed = (action: string, channelName: string) =>
+ makeEmbed({
title: `Slow Mode - ${action} - No ${channelName} channel`,
description: `The command was successful, but no message to ${channelName} was sent. Please check the channel still exists.`,
color: Colors.Yellow,
-});
+ });
-const successEmbed = (action: string, channel: string) => makeEmbed({
+const successEmbed = (action: string, channel: string) =>
+ makeEmbed({
title: `Slow Mode - ${action} successful`,
description: `Slow mode for channel <#${channel}> has been ${action} successfully.`,
color: Colors.Green,
-});
+ });
export default slashCommand(data, async ({ interaction }) => {
- const scheduler = getScheduler();
- if (!scheduler) {
- await interaction.reply({ embeds: [noSchedulerEmbed] });
- }
+ const scheduler = getScheduler();
+ if (!scheduler) {
+ await interaction.reply({ embeds: [noSchedulerEmbed] });
+ }
- const duration = interaction.options.getNumber('duration')!;
- const slowmodeChannel = interaction.options.getChannel('channel')! ?? interaction.channel;
- const autoDisable = interaction.options.getNumber('auto-disable');
- const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ const duration = interaction.options.getNumber('duration')!;
+ const slowmodeChannel = interaction.options.getChannel('channel')! ?? interaction.channel;
+ const autoDisable = interaction.options.getNumber('auto-disable');
+ const modLogsChannel = interaction.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- const subcommandName = interaction.options.getSubcommand();
+ const subcommandName = interaction.options.getSubcommand();
- switch (subcommandName) {
+ switch (subcommandName) {
case 'set':
- await handleSetSlowmode(interaction, duration, slowmodeChannel, autoDisable, modLogsChannel, scheduler, failedEmbed, noChannelEmbed, successEmbed, modLogEmbed, slowModeEmbedField);
- break;
+ await handleSetSlowmode(
+ interaction,
+ duration,
+ slowmodeChannel,
+ autoDisable,
+ modLogsChannel,
+ scheduler,
+ failedEmbed,
+ noChannelEmbed,
+ successEmbed,
+ modLogEmbed,
+ slowModeEmbedField,
+ );
+ break;
case 'disable':
- await handleDisableSlowmode(interaction, slowmodeChannel, modLogsChannel, scheduler, failedEmbed, noChannelEmbed, successEmbed, modLogEmbed, slowModeEmbedField);
- break;
+ await handleDisableSlowmode(
+ interaction,
+ slowmodeChannel,
+ modLogsChannel,
+ scheduler,
+ failedEmbed,
+ noChannelEmbed,
+ successEmbed,
+ modLogEmbed,
+ slowModeEmbedField,
+ );
+ break;
default:
- await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
- }
+ await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
+ }
});
diff --git a/src/commands/moderation/welcome.ts b/src/commands/moderation/welcome.ts
index 2b1f160e..8a276fdc 100644
--- a/src/commands/moderation/welcome.ts
+++ b/src/commands/moderation/welcome.ts
@@ -2,11 +2,11 @@ import { ApplicationCommandType } from 'discord.js';
import { constantsConfig, imageBaseUrl, slashCommand, slashCommandStructure, makeEmbed, makeLines } from '../../lib';
const data = slashCommandStructure({
- name: 'welcome',
- description: 'Displays the welcome message for the server.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator
- dm_permission: false,
+ name: 'welcome',
+ description: 'Displays the welcome message for the server.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator
+ dm_permission: false,
});
const HEADER_IMAGE_URL = `${imageBaseUrl}/moderation/welcome_discord_banner.png`;
@@ -16,112 +16,111 @@ const HELP_IMAGE_URL = `${imageBaseUrl}/moderation/welcome_help_and_support.png`
const IMPORTANT_INFO_IMAGE_URL = `${imageBaseUrl}/moderation/welcome_impt_info.png`;
const WELCOME_EMBED = makeEmbed({
- description: makeLines([
- 'Welcome to the **Official Discord Server** of **FlyByWire Simulations!**',
- '',
- 'The A32NX Project is a community-driven open source project to create a free Airbus A320neo in Microsoft Flight Simulator that is as close to reality as possible. It started out as an enhancement project to the default A320neo and is now proceeding as an independent add-on project aiming to bring the FlyByWire A32NX up to payware-level systems depth and functionality, all for free.',
- '',
- 'We are also developing an A380 from scratch which will be aiming to produce a high fidelity freeware aircraft.',
- '',
- `Feel free to download, test, and share your feedback, or if you are interested in developing, assign your <#${constantsConfig.channels.ROLES}>, and get cracking!`,
- ]),
-
+ description: makeLines([
+ 'Welcome to the **Official Discord Server** of **FlyByWire Simulations!**',
+ '',
+ 'The A32NX Project is a community-driven open source project to create a free Airbus A320neo in Microsoft Flight Simulator that is as close to reality as possible. It started out as an enhancement project to the default A320neo and is now proceeding as an independent add-on project aiming to bring the FlyByWire A32NX up to payware-level systems depth and functionality, all for free.',
+ '',
+ 'We are also developing an A380 from scratch which will be aiming to produce a high fidelity freeware aircraft.',
+ '',
+ `Feel free to download, test, and share your feedback, or if you are interested in developing, assign your <#${constantsConfig.channels.ROLES}>, and get cracking!`,
+ ]),
});
const SOCIAL_EMBED = makeEmbed({
- title: '<:Partnered:921520970123059231> FlyByWireSimulations | Socials',
- description: makeLines([
- '<:FBW:921521552699310141> ',
- '<:Twitter:921521552942571601> ',
- '<:Facebook:921521552984539146> ',
- '<:Youtube:921521552829329488> ',
- '<:Twitch:921521552623804506> ',
- ]),
+ title: '<:Partnered:921520970123059231> FlyByWireSimulations | Socials',
+ description: makeLines([
+ '<:FBW:921521552699310141> ',
+ '<:Twitter:921521552942571601> ',
+ '<:Facebook:921521552984539146> ',
+ '<:Youtube:921521552829329488> ',
+ '<:Twitch:921521552623804506> ',
+ ]),
});
const SUPPORT_EMBED = makeEmbed({
- title: '<:Partnered:921520970123059231> FlyByWireSimulations | Support Us',
- description: makeLines([
- 'You are able to voluntarily support us financially to ensure we are able to cover the costs of servers and developmental resources.',
- '',
- 'https://opencollective.com/flybywire',
- ]),
+ title: '<:Partnered:921520970123059231> FlyByWireSimulations | Support Us',
+ description: makeLines([
+ 'You are able to voluntarily support us financially to ensure we are able to cover the costs of servers and developmental resources.',
+ '',
+ 'https://opencollective.com/flybywire',
+ ]),
});
const IMPORTANT_INFO_EMBED = makeEmbed({
- title: '<:Partnered:921520970123059231> FlyByWireSimulations | Important Info',
- description: 'By being a member of our Discord Server, you agree to the following, and failure to do so can result in removal from the server.',
- fields: [
- {
- name: 'Appropriate Content',
- value: makeLines([
- 'We want to promote a healthy environment in our Discord server. To maintain this, we will not tolerate inappropriate names, profile pictures, messages or emotes that may offend others in the community. Alongside this we do not welcome any form of spam, the distribution or conversation of pirated material, or general disturbances in our channels and voice chat.',
- '',
- 'Moderators and Admins reserve the right to mute or remove any member they see violating the rules without prior notice.',
- '',
- 'Avoiding mutes or bans will result in further action being taken to safeguard the Discord community.',
- ]),
- },
- {
- name: 'Discord Policies',
- value: makeLines([
- 'Please read the Discord TOS and Guidelines listed below!',
- '',
- 'Discord Terms of Service & Guidelines',
- '',
- 'https://discordapp.com/terms',
- '',
- 'https://discordapp.com/guidelines',
- ]),
- },
- ],
+ title: '<:Partnered:921520970123059231> FlyByWireSimulations | Important Info',
+ description:
+ 'By being a member of our Discord Server, you agree to the following, and failure to do so can result in removal from the server.',
+ fields: [
+ {
+ name: 'Appropriate Content',
+ value: makeLines([
+ 'We want to promote a healthy environment in our Discord server. To maintain this, we will not tolerate inappropriate names, profile pictures, messages or emotes that may offend others in the community. Alongside this we do not welcome any form of spam, the distribution or conversation of pirated material, or general disturbances in our channels and voice chat.',
+ '',
+ 'Moderators and Admins reserve the right to mute or remove any member they see violating the rules without prior notice.',
+ '',
+ 'Avoiding mutes or bans will result in further action being taken to safeguard the Discord community.',
+ ]),
+ },
+ {
+ name: 'Discord Policies',
+ value: makeLines([
+ 'Please read the Discord TOS and Guidelines listed below!',
+ '',
+ 'Discord Terms of Service & Guidelines',
+ '',
+ 'https://discordapp.com/terms',
+ '',
+ 'https://discordapp.com/guidelines',
+ ]),
+ },
+ ],
});
const HELP_EMBED = makeEmbed({
- title: '<:Partnered:921520970123059231> FlyByWireSimulations | Help and Support',
- fields: [
- {
- name: 'Documentation',
- value: 'Guides & Support Information: https://docs.flybywiresim.com/',
- },
- {
- name: 'FAQ',
- value: `Always check <#${constantsConfig.channels.FAQ}>, <#${constantsConfig.channels.KNOWN_ISSUES}>, and our documentation site to see if your question has already been answered. If not head over to <#${constantsConfig.channels.A32NX_SUPPORT}> for assistance.`,
- },
- {
- name: 'Flight School',
- value: `We've opened our <#${constantsConfig.channels.FLIGHT_SCHOOL}> channel for any questions you have pertaining to the operation of the A32NX in the simulator.`,
- },
-
- ],
+ title: '<:Partnered:921520970123059231> FlyByWireSimulations | Help and Support',
+ fields: [
+ {
+ name: 'Documentation',
+ value: 'Guides & Support Information: https://docs.flybywiresim.com/',
+ },
+ {
+ name: 'FAQ',
+ value: `Always check <#${constantsConfig.channels.FAQ}>, <#${constantsConfig.channels.KNOWN_ISSUES}>, and our documentation site to see if your question has already been answered. If not head over to <#${constantsConfig.channels.A32NX_SUPPORT}> for assistance.`,
+ },
+ {
+ name: 'Flight School',
+ value: `We've opened our <#${constantsConfig.channels.FLIGHT_SCHOOL}> channel for any questions you have pertaining to the operation of the A32NX in the simulator.`,
+ },
+ ],
});
export default slashCommand(data, async ({ interaction }) => {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- if (interaction.channel) {
- await interaction.channel.send({ files: [HEADER_IMAGE_URL] });
+ if (interaction.channel) {
+ await interaction.channel.send({ files: [HEADER_IMAGE_URL] });
- await interaction.channel.send({ embeds: [WELCOME_EMBED] });
+ await interaction.channel.send({ embeds: [WELCOME_EMBED] });
- await interaction.channel.send({ files: [SOCIAL_IMAGE_URL] });
+ await interaction.channel.send({ files: [SOCIAL_IMAGE_URL] });
- await interaction.channel.send({ embeds: [SOCIAL_EMBED] });
+ await interaction.channel.send({ embeds: [SOCIAL_EMBED] });
- await interaction.channel.send({ files: [SUPPORT_IMAGE_URL] });
+ await interaction.channel.send({ files: [SUPPORT_IMAGE_URL] });
- await interaction.channel.send({ embeds: [SUPPORT_EMBED] });
+ await interaction.channel.send({ embeds: [SUPPORT_EMBED] });
- await interaction.channel.send({ files: [HELP_IMAGE_URL] });
+ await interaction.channel.send({ files: [HELP_IMAGE_URL] });
- await interaction.channel.send({ embeds: [HELP_EMBED] });
+ await interaction.channel.send({ embeds: [HELP_EMBED] });
- await interaction.channel.send({ files: [IMPORTANT_INFO_IMAGE_URL] });
+ await interaction.channel.send({ files: [IMPORTANT_INFO_IMAGE_URL] });
- await interaction.channel.send({ embeds: [IMPORTANT_INFO_EMBED] });
- } else {
- await interaction.followUp({ content: 'This command can only be used in a server.', ephemeral: true });
- }
+ await interaction.channel.send({ embeds: [IMPORTANT_INFO_EMBED] });
+ } else {
+ await interaction.followUp({ content: 'This command can only be used in a server.', ephemeral: true });
+ }
- await interaction.followUp({ content: 'Welcome message sent.', ephemeral: true });
+ await interaction.followUp({ content: 'Welcome message sent.', ephemeral: true });
});
diff --git a/src/commands/moderation/whois.ts b/src/commands/moderation/whois.ts
index 917cba5a..8cede53e 100644
--- a/src/commands/moderation/whois.ts
+++ b/src/commands/moderation/whois.ts
@@ -3,81 +3,87 @@ import moment from 'moment';
import { constantsConfig, slashCommand, slashCommandStructure, makeEmbed } from '../../lib';
const data = slashCommandStructure({
- name: 'whois',
- description: 'Provides information about a user.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
- dm_permission: false,
- options: [{
- name: 'tag_or_id',
- description: 'Provide a user\'s tag or id to get information about them.',
- type: ApplicationCommandOptionType.User,
- required: false,
- }],
+ name: 'whois',
+ description: 'Provides information about a user.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Overrides need to be added for admin and moderator roles
+ dm_permission: false,
+ options: [
+ {
+ name: 'tag_or_id',
+ description: "Provide a user's tag or id to get information about them.",
+ type: ApplicationCommandOptionType.User,
+ required: false,
+ },
+ ],
});
const beautifiedStatus: { [key: string]: string } = {
- ONLINE: 'Online',
- IDLE: 'Idle',
- DND: 'Do Not Disturb',
- OFFLINE: 'Offline',
+ ONLINE: 'Online',
+ IDLE: 'Idle',
+ DND: 'Do Not Disturb',
+ OFFLINE: 'Offline',
};
export default slashCommand(data, async ({ interaction }) => {
- const targetMember = interaction.options.getMember('tag_or_id') ?? interaction.member;
+ const targetMember = interaction.options.getMember('tag_or_id') ?? interaction.member;
- const filteredRoles = targetMember.roles.cache.filter((role) => role.id !== interaction.guild.id);
- const listedRoles = filteredRoles.sort((a, b) => b.position - a.position).map((role) => role.toString());
+ const filteredRoles = targetMember.roles.cache.filter((role) => role.id !== interaction.guild.id);
+ const listedRoles = filteredRoles.sort((a, b) => b.position - a.position).map((role) => role.toString());
- const onlineStatus = beautifiedStatus[targetMember.presence?.status?.toUpperCase() ?? 'OFFLINE'];
+ const onlineStatus = beautifiedStatus[targetMember.presence?.status?.toUpperCase() ?? 'OFFLINE'];
- let status;
- if (targetMember.presence == null) {
- status = 'Offline';
- } else {
- status = onlineStatus;
- }
+ let status;
+ if (targetMember.presence == null) {
+ status = 'Offline';
+ } else {
+ status = onlineStatus;
+ }
- const whoisEmbed = makeEmbed({
- author: {
- name: targetMember.user.username,
- iconURL: targetMember.user.avatarURL()!,
- },
- description: `${targetMember}`,
- thumbnail: { url: targetMember.user.avatarURL()! },
- fields: [
- {
- name: 'Username',
- value: targetMember.user.tag,
- inline: true,
- },
- {
- name: 'Status',
- value: status,
- inline: true,
- },
- {
- name: 'Joined',
- value: moment(targetMember.joinedTimestamp).format('llll'),
- inline: true,
- },
- {
- name: 'Registered',
- value: moment(targetMember.user.createdTimestamp).format('llll'),
- inline: false,
- },
- {
- name: 'Roles',
- value: `\u200B${listedRoles.join(', ')}`,
- },
- {
- name: 'Permissions',
- value: targetMember.permissions.toArray().join(', ').toLowerCase().replace(/_/g, ' ')
- .replace(/(^\w)|(\s+\w)/g, (char) => char.toUpperCase()),
- },
- ],
- footer: { text: `User ID: ${targetMember.id}` },
- });
+ const whoisEmbed = makeEmbed({
+ author: {
+ name: targetMember.user.username,
+ iconURL: targetMember.user.avatarURL()!,
+ },
+ description: `${targetMember.toString()}`,
+ thumbnail: { url: targetMember.user.avatarURL()! },
+ fields: [
+ {
+ name: 'Username',
+ value: targetMember.user.tag,
+ inline: true,
+ },
+ {
+ name: 'Status',
+ value: status,
+ inline: true,
+ },
+ {
+ name: 'Joined',
+ value: moment(targetMember.joinedTimestamp).format('llll'),
+ inline: true,
+ },
+ {
+ name: 'Registered',
+ value: moment(targetMember.user.createdTimestamp).format('llll'),
+ inline: false,
+ },
+ {
+ name: 'Roles',
+ value: `\u200B${listedRoles.join(', ')}`,
+ },
+ {
+ name: 'Permissions',
+ value: targetMember.permissions
+ .toArray()
+ .join(', ')
+ .toLowerCase()
+ .replace(/_/g, ' ')
+ .replace(/(^\w)|(\s+\w)/g, (char) => char.toUpperCase()),
+ },
+ ],
+ footer: { text: `User ID: ${targetMember.id}` },
+ });
- return interaction.reply({ embeds: [whoisEmbed] });
+ return interaction.reply({ embeds: [whoisEmbed] });
});
diff --git a/src/commands/utils/avatar.ts b/src/commands/utils/avatar.ts
index 941e37e4..0cea08c1 100644
--- a/src/commands/utils/avatar.ts
+++ b/src/commands/utils/avatar.ts
@@ -2,24 +2,26 @@ import { ApplicationCommandOptionType, ApplicationCommandType } from 'discord.js
import { slashCommand, slashCommandStructure, makeEmbed } from '../../lib';
const data = slashCommandStructure({
- name: 'avatar',
- description: 'Shows the selected user\'s avatar',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'tag_or_id',
- description: 'Please provide a user tag or ID.',
- type: ApplicationCommandOptionType.User,
- required: false,
- }],
+ name: 'avatar',
+ description: "Shows the selected user's avatar",
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'tag_or_id',
+ description: 'Please provide a user tag or ID.',
+ type: ApplicationCommandOptionType.User,
+ required: false,
+ },
+ ],
});
export default slashCommand(data, async ({ interaction }) => {
- const user = interaction.options.getUser('tag_or_id') || interaction.user;
+ const user = interaction.options.getUser('tag_or_id') || interaction.user;
- const avatarEmbed = makeEmbed({
- title: `${user.tag}'s avatar`,
- image: { url: user.displayAvatarURL({ size: 4096 }) },
- });
+ const avatarEmbed = makeEmbed({
+ title: `${user.tag}'s avatar`,
+ image: { url: user.displayAvatarURL({ size: 4096 }) },
+ });
- return interaction.reply({ embeds: [avatarEmbed] });
+ return interaction.reply({ embeds: [avatarEmbed] });
});
diff --git a/src/commands/utils/birthday/birthday.ts b/src/commands/utils/birthday/birthday.ts
index 71fab53f..ce94edd3 100644
--- a/src/commands/utils/birthday/birthday.ts
+++ b/src/commands/utils/birthday/birthday.ts
@@ -5,96 +5,96 @@ import { handleListBirthday } from './functions/listBirthday';
import { handleRemoveBirthday } from './functions/removeBirthday';
const data = slashCommandStructure({
- name: 'birthday',
- description: 'Command to manage birthdays.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Needs overrides adding for team members and lock to birthday thread
- dm_permission: false,
- options: [
+ name: 'birthday',
+ description: 'Command to manage birthdays.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, //Needs overrides adding for team members and lock to birthday thread
+ dm_permission: false,
+ options: [
+ {
+ name: 'set',
+ description: 'Sets your birthday.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
{
- name: 'set',
- description: 'Sets your birthday.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'day',
- description: 'The day of your birthday.',
- type: ApplicationCommandOptionType.Integer,
- min_value: 1,
- max_value: 31,
- required: true,
- },
- {
- name: 'month',
- description: 'The month of your birthday.',
- type: ApplicationCommandOptionType.Integer,
- required: true,
- choices: [
- { name: 'January', value: 1 },
- { name: 'February', value: 2 },
- { name: 'March', value: 3 },
- { name: 'April', value: 4 },
- { name: 'May', value: 5 },
- { name: 'June', value: 6 },
- { name: 'July', value: 7 },
- { name: 'August', value: 8 },
- { name: 'September', value: 9 },
- { name: 'October', value: 10 },
- { name: 'November', value: 11 },
- { name: 'December', value: 12 },
- ],
- },
- {
- name: 'timezone',
- description: 'Your timezone in relation to UTC. e.g. 2 or -6.',
- type: ApplicationCommandOptionType.Integer,
- max_value: +14,
- min_value: -12,
- required: true,
- },
- ],
+ name: 'day',
+ description: 'The day of your birthday.',
+ type: ApplicationCommandOptionType.Integer,
+ min_value: 1,
+ max_value: 31,
+ required: true,
},
{
- name: 'remove',
- description: 'Removes your birthday.',
- type: ApplicationCommandOptionType.Subcommand,
+ name: 'month',
+ description: 'The month of your birthday.',
+ type: ApplicationCommandOptionType.Integer,
+ required: true,
+ choices: [
+ { name: 'January', value: 1 },
+ { name: 'February', value: 2 },
+ { name: 'March', value: 3 },
+ { name: 'April', value: 4 },
+ { name: 'May', value: 5 },
+ { name: 'June', value: 6 },
+ { name: 'July', value: 7 },
+ { name: 'August', value: 8 },
+ { name: 'September', value: 9 },
+ { name: 'October', value: 10 },
+ { name: 'November', value: 11 },
+ { name: 'December', value: 12 },
+ ],
},
{
- name: 'list',
- description: 'Lists all birthdays.',
- type: ApplicationCommandOptionType.Subcommand,
+ name: 'timezone',
+ description: 'Your timezone in relation to UTC. e.g. 2 or -6.',
+ type: ApplicationCommandOptionType.Integer,
+ max_value: +14,
+ min_value: -12,
+ required: true,
},
- ],
+ ],
+ },
+ {
+ name: 'remove',
+ description: 'Removes your birthday.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ {
+ name: 'list',
+ description: 'Lists all birthdays.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ ],
});
const noConnEmbed = makeEmbed({
- title: 'Birthday - No Connection',
- description: 'Could not connect to the database',
- color: Colors.Red,
+ title: 'Birthday - No Connection',
+ description: 'Could not connect to the database',
+ color: Colors.Red,
});
export default slashCommand(data, async ({ interaction }) => {
- const conn = await getConn();
+ const conn = getConn();
- if (!conn) {
- await interaction.reply({ embeds: [noConnEmbed], ephemeral: true });
- return;
- }
+ if (!conn) {
+ await interaction.reply({ embeds: [noConnEmbed], ephemeral: true });
+ return;
+ }
- const subcommandName = interaction.options.getSubcommand();
+ const subcommandName = interaction.options.getSubcommand();
- switch (subcommandName) {
+ switch (subcommandName) {
case 'set':
- await handleSetBirthday(interaction);
- break;
+ await handleSetBirthday(interaction);
+ break;
case 'remove':
- await handleRemoveBirthday(interaction);
- break;
+ await handleRemoveBirthday(interaction);
+ break;
case 'list':
- await handleListBirthday(interaction);
- break;
+ await handleListBirthday(interaction);
+ break;
default:
- await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
- }
+ await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
+ }
});
diff --git a/src/commands/utils/birthday/functions/listBirthday.ts b/src/commands/utils/birthday/functions/listBirthday.ts
index 82369cad..f5b435f9 100644
--- a/src/commands/utils/birthday/functions/listBirthday.ts
+++ b/src/commands/utils/birthday/functions/listBirthday.ts
@@ -1,56 +1,60 @@
-import { ChatInputCommandInteraction } from 'discord.js';
+import { ChatInputCommandInteraction, EmbedField } from 'discord.js';
import { Birthday, Logger, makeEmbed } from '../../../../lib';
-const birthdayListEmbed = (fields: Array) => makeEmbed({
+const birthdayListEmbed = (fields: EmbedField[]) =>
+ makeEmbed({
title: 'Birthday - Birthday List',
description: fields.length > 0 ? undefined : 'No birthdays set',
fields,
-});
+ });
export async function handleListBirthday(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply();
-
- try {
- const birthdays = await Birthday.find({}).sort({ day: 1 }); // Only day sort required, months are bucketized
- const members = await interaction.guild!.members.fetch();
-
- const monthBuckets: Array> = [
- ['January', []],
- ['February', []],
- ['March', []],
- ['April', []],
- ['May', []],
- ['June', []],
- ['July', []],
- ['August', []],
- ['September', []],
- ['October', []],
- ['November', []],
- ['December', []],
- ];
-
- for (const birthday of birthdays) {
- const member = members.get(birthday.userID!);
-
- if (member) {
- monthBuckets[birthday.utcDatetime!.getUTCMonth()][1].push(`${member.displayName} - ${birthday.day}/${birthday.month} (Z${birthday.timezone! < 0 ? '' : '+'}${birthday.timezone})`);
- }
- }
-
- const fields = [];
-
- for (const monthBucket of monthBuckets) {
- if (monthBucket[1].length > 0) {
- fields.push({
- name: monthBucket[0],
- value: monthBucket[1].join('\n'),
- });
- }
- }
-
- await interaction.editReply({ embeds: [birthdayListEmbed(fields)] });
- } catch (error) {
- Logger.error(error);
- await interaction.followUp({ content: 'An error occurred while processing this command.', ephemeral: true });
+ await interaction.deferReply();
+
+ try {
+ const birthdays = await Birthday.find({}).sort({ day: 1 }); // Only day sort required, months are bucketized
+ const members = await interaction.guild.members.fetch();
+
+ const monthBuckets: Array<[string, string[]]> = [
+ ['January', []],
+ ['February', []],
+ ['March', []],
+ ['April', []],
+ ['May', []],
+ ['June', []],
+ ['July', []],
+ ['August', []],
+ ['September', []],
+ ['October', []],
+ ['November', []],
+ ['December', []],
+ ];
+
+ for (const birthday of birthdays) {
+ const member = members.get(birthday.userID!);
+
+ if (member) {
+ monthBuckets[birthday.utcDatetime!.getUTCMonth()][1].push(
+ `${member.displayName} - ${birthday.day}/${birthday.month} (Z${birthday.timezone! < 0 ? '' : '+'}${birthday.timezone})`,
+ );
+ }
}
+
+ const fields: EmbedField[] = [];
+
+ for (const monthBucket of monthBuckets) {
+ if (monthBucket[1].length > 0) {
+ fields.push({
+ name: monthBucket[0],
+ value: monthBucket[1].join('\n'),
+ inline: false,
+ });
+ }
+ }
+
+ await interaction.editReply({ embeds: [birthdayListEmbed(fields)] });
+ } catch (error) {
+ Logger.error(error);
+ await interaction.followUp({ content: 'An error occurred while processing this command.', ephemeral: true });
+ }
}
diff --git a/src/commands/utils/birthday/functions/removeBirthday.ts b/src/commands/utils/birthday/functions/removeBirthday.ts
index 49c4539e..e021b56e 100644
--- a/src/commands/utils/birthday/functions/removeBirthday.ts
+++ b/src/commands/utils/birthday/functions/removeBirthday.ts
@@ -1,27 +1,29 @@
import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
import { Birthday, makeEmbed } from '../../../../lib';
-const noBirthdayEmbed = (discordUser: User) => makeEmbed({
+const noBirthdayEmbed = (discordUser: User) =>
+ makeEmbed({
title: 'Birthday remove failed',
- description: `${discordUser} doesn't have a birthday set`,
+ description: `${discordUser.toString()} doesn't have a birthday set`,
color: Colors.Red,
-});
+ });
-const birthdayRemovedEmbed = (discordUser: User) => makeEmbed({
+const birthdayRemovedEmbed = (discordUser: User) =>
+ makeEmbed({
title: 'Birthday removed',
- description: `${discordUser}'s birthday has been removed`,
-});
+ description: `${discordUser.toString()}'s birthday has been removed`,
+ });
export async function handleRemoveBirthday(interaction: ChatInputCommandInteraction<'cached'>) {
- const userID = interaction.user.id;
- const discordUser = interaction.user;
+ const userID = interaction.user.id;
+ const discordUser = interaction.user;
- const birthday = await Birthday.findOne({ userID });
+ const birthday = await Birthday.findOne({ userID });
- if (!birthday) {
- await interaction.reply({ embeds: [noBirthdayEmbed(discordUser)] });
- } else {
- await Birthday.deleteOne({ userID });
- await interaction.reply({ embeds: [birthdayRemovedEmbed(discordUser)] });
- }
+ if (!birthday) {
+ await interaction.reply({ embeds: [noBirthdayEmbed(discordUser)] });
+ } else {
+ await Birthday.deleteOne({ userID });
+ await interaction.reply({ embeds: [birthdayRemovedEmbed(discordUser)] });
+ }
}
diff --git a/src/commands/utils/birthday/functions/setBirthday.ts b/src/commands/utils/birthday/functions/setBirthday.ts
index 67714cfb..c5a2615e 100644
--- a/src/commands/utils/birthday/functions/setBirthday.ts
+++ b/src/commands/utils/birthday/functions/setBirthday.ts
@@ -2,84 +2,85 @@ import { ChatInputCommandInteraction, Colors, User } from 'discord.js';
import { Birthday, makeEmbed } from '../../../../lib';
function isDateValid(day: number, month: number) {
- if (month < 1 || month > 12) {
- return false;
+ if (month < 1 || month > 12) {
+ return false;
+ }
+
+ if (day < 1) {
+ return false;
+ }
+
+ if (month === 2) {
+ // Check for February
+ if (day > 29) {
+ return false;
}
-
- if (day < 1) {
- return false;
- }
-
- if (month === 2) {
- // Check for February
- if (day > 29) {
- return false;
- }
- } else if ((month <= 7 && month % 2 === 0) || (month >= 8 && month % 2 === 1)) {
- // Check for months with 30 days
- if (day > 30) {
- return false;
- }
+ } else if ((month <= 7 && month % 2 === 0) || (month >= 8 && month % 2 === 1)) {
+ // Check for months with 30 days
+ if (day > 30) {
+ return false;
}
+ }
- return true;
+ return true;
}
const invalidDateEmbed = makeEmbed({
- title: 'Birthday - Invalid Date',
- description: 'Please provide a valid date.',
- color: Colors.Red,
+ title: 'Birthday - Invalid Date',
+ description: 'Please provide a valid date.',
+ color: Colors.Red,
});
-const birthdaySetEmbed = (discordUser: User, birthdayDay: number, birthdayMonth: number, birthdayTimezone: number) => makeEmbed({
+const birthdaySetEmbed = (discordUser: User, birthdayDay: number, birthdayMonth: number, birthdayTimezone: number) =>
+ makeEmbed({
title: 'Birthday - Birthday Set',
- description: `${discordUser}'s birthday has been set to ${birthdayDay}/${birthdayMonth} and their timezone is UTC${birthdayTimezone < 0 ? '' : '+'}${birthdayTimezone}`,
-});
+ description: `${discordUser.toString()}'s birthday has been set to ${birthdayDay}/${birthdayMonth} and their timezone is UTC${birthdayTimezone < 0 ? '' : '+'}${birthdayTimezone}`,
+ });
export async function handleSetBirthday(interaction: ChatInputCommandInteraction<'cached'>) {
- const selectedDay = interaction.options.getInteger('day')!;
- const selectedMonth = interaction.options.getInteger('month')!;
- const selectedTimezone = interaction.options.getInteger('timezone')!;
-
- if (!isDateValid(selectedDay, selectedMonth)) {
- await interaction.reply({ embeds: [invalidDateEmbed], ephemeral: true });
- return;
- }
-
- const userID = interaction.user.id;
- const discordUser = interaction.user;
-
- // Determine UTC datetime to send birthday message
-
- const currentDate = new Date();
- const utcDatetime = new Date(Date.UTC(currentDate.getUTCFullYear(), selectedMonth - 1, selectedDay));
- utcDatetime.setUTCHours(10 - selectedTimezone);
-
- let birthdayDoc = await Birthday.findOne({ userID });
-
- if (birthdayDoc) {
- birthdayDoc.month = selectedMonth;
- birthdayDoc.day = selectedDay;
- birthdayDoc.utcDatetime = utcDatetime;
- birthdayDoc.timezone = selectedTimezone;
- } else {
- birthdayDoc = new Birthday({
- userID,
- month: selectedMonth,
- day: selectedDay,
- utcDatetime,
- timezone: selectedTimezone,
- });
- }
-
- // If birthday already passed this year then set next year's birthday
-
- if (currentDate > utcDatetime) {
- utcDatetime.setUTCFullYear(utcDatetime.getUTCFullYear() + 1);
- birthdayDoc.utcDatetime = utcDatetime;
- }
-
- await birthdayDoc.save();
-
- await interaction.reply({ embeds: [birthdaySetEmbed(discordUser, selectedDay, selectedMonth, selectedTimezone)] });
+ const selectedDay = interaction.options.getInteger('day')!;
+ const selectedMonth = interaction.options.getInteger('month')!;
+ const selectedTimezone = interaction.options.getInteger('timezone')!;
+
+ if (!isDateValid(selectedDay, selectedMonth)) {
+ await interaction.reply({ embeds: [invalidDateEmbed], ephemeral: true });
+ return;
+ }
+
+ const userID = interaction.user.id;
+ const discordUser = interaction.user;
+
+ // Determine UTC datetime to send birthday message
+
+ const currentDate = new Date();
+ const utcDatetime = new Date(Date.UTC(currentDate.getUTCFullYear(), selectedMonth - 1, selectedDay));
+ utcDatetime.setUTCHours(10 - selectedTimezone);
+
+ let birthdayDoc = await Birthday.findOne({ userID });
+
+ if (birthdayDoc) {
+ birthdayDoc.month = selectedMonth;
+ birthdayDoc.day = selectedDay;
+ birthdayDoc.utcDatetime = utcDatetime;
+ birthdayDoc.timezone = selectedTimezone;
+ } else {
+ birthdayDoc = new Birthday({
+ userID,
+ month: selectedMonth,
+ day: selectedDay,
+ utcDatetime,
+ timezone: selectedTimezone,
+ });
+ }
+
+ // If birthday already passed this year then set next year's birthday
+
+ if (currentDate > utcDatetime) {
+ utcDatetime.setUTCFullYear(utcDatetime.getUTCFullYear() + 1);
+ birthdayDoc.utcDatetime = utcDatetime;
+ }
+
+ await birthdayDoc.save();
+
+ await interaction.reply({ embeds: [birthdaySetEmbed(discordUser, selectedDay, selectedMonth, selectedTimezone)] });
}
diff --git a/src/commands/utils/count.ts b/src/commands/utils/count.ts
index ad6bf7dd..a6b855ee 100644
--- a/src/commands/utils/count.ts
+++ b/src/commands/utils/count.ts
@@ -2,39 +2,39 @@ import { ApplicationCommandOptionType, ApplicationCommandType, TextChannel } fro
import { constantsConfig, slashCommand, slashCommandStructure } from '../../lib';
const data = slashCommandStructure({
- name: 'count',
- description: 'Counts for me.',
- type: ApplicationCommandType.ChatInput,
- default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, // Overrides needed for bot dev team
- options: [
- {
- name: 'number',
- description: 'The number to count as.',
- type: ApplicationCommandOptionType.Integer,
- required: true,
- },
- ],
+ name: 'count',
+ description: 'Counts for me.',
+ type: ApplicationCommandType.ChatInput,
+ default_member_permissions: constantsConfig.commandPermission.MANAGE_SERVER, // Overrides needed for bot dev team
+ options: [
+ {
+ name: 'number',
+ description: 'The number to count as.',
+ type: ApplicationCommandOptionType.Integer,
+ required: true,
+ },
+ ],
});
export default slashCommand(data, async ({ interaction }) => {
-// check if user has the role
- const hasRole = interaction.member.roles.cache.has(constantsConfig.roles.BOT_DEVELOPER);
+ // check if user has the role
+ const hasRole = interaction.member.roles.cache.has(constantsConfig.roles.BOT_DEVELOPER);
- if (!hasRole) {
- await interaction.reply({ content: 'Go count yourself ;)', ephemeral: true });
- return;
- }
+ if (!hasRole) {
+ await interaction.reply({ content: 'Go count yourself ;)', ephemeral: true });
+ return;
+ }
- const countThread = interaction.guild.channels.resolve(constantsConfig.threads.COUNT_THREAD) as TextChannel | null;
+ const countThread = interaction.guild.channels.resolve(constantsConfig.threads.COUNT_THREAD) as TextChannel | null;
- if (!countThread) {
- await interaction.reply({ content: 'Count thread not found.', ephemeral: true });
- return;
- }
+ if (!countThread) {
+ await interaction.reply({ content: 'Count thread not found.', ephemeral: true });
+ return;
+ }
- const countNumber = interaction.options.getInteger('number');
+ const countNumber = interaction.options.getInteger('number');
- await countThread.send(`${interaction.user} says ${countNumber}`);
+ await countThread.send(`${interaction.user.toString()} says ${countNumber}`);
- await interaction.reply({ content: 'Counted!', ephemeral: true });
+ await interaction.reply({ content: 'Counted!', ephemeral: true });
});
diff --git a/src/commands/utils/docSearch.ts b/src/commands/utils/docSearch.ts
index 4a4ee487..6d4238b3 100644
--- a/src/commands/utils/docSearch.ts
+++ b/src/commands/utils/docSearch.ts
@@ -3,56 +3,60 @@ import Filter from 'bad-words';
import { slashCommand, slashCommandStructure, makeEmbed } from '../../lib';
const data = slashCommandStructure({
- name: 'doc-search',
- description: 'Searches the FlyByWire Documentation for a given query.',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'query',
- description: 'The query to search for.',
- type: ApplicationCommandOptionType.String,
- max_length: 100,
- required: true,
- }],
+ name: 'doc-search',
+ description: 'Searches the FlyByWire Documentation for a given query.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'query',
+ description: 'The query to search for.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 100,
+ required: true,
+ },
+ ],
});
const DOCS_BASE_URL = 'https://docs.flybywiresim.com';
export default slashCommand(data, async ({ interaction }) => {
- const query = interaction.options.getString('query')!;
-
- // Separates the query into an array.
- const words = query.split(/\s+/);
-
- // Itterate through the array and check if any of the words are a URL. Then check if any of the words are profanity.
- for (const searchWord of words) {
- try {
- const _ = new URL(searchWord);
- const URLEmbed = makeEmbed({
- title: 'FlyByWire Documentation | Error',
- description: 'Providing URLs to the Documentation search command is not allowed.',
- color: Colors.Red,
- });
- return interaction.reply({ embeds: [URLEmbed] });
- } catch (_) { /**/ }
-
- const filter = new Filter();
- if (filter.isProfane(searchWord)) {
- const profanityEmbed = makeEmbed({
- title: 'FlyByWire Documentation | Error',
- description: 'Providing profanity to the Documentation search command is not allowed.',
- color: Colors.Red,
- });
-
- return interaction.reply({ embeds: [profanityEmbed] });
- }
+ const query = interaction.options.getString('query')!;
+
+ // Separates the query into an array.
+ const words = query.split(/\s+/);
+
+ // Itterate through the array and check if any of the words are a URL. Then check if any of the words are profanity.
+ for (const searchWord of words) {
+ try {
+ const _ = new URL(searchWord);
+ const URLEmbed = makeEmbed({
+ title: 'FlyByWire Documentation | Error',
+ description: 'Providing URLs to the Documentation search command is not allowed.',
+ color: Colors.Red,
+ });
+ return interaction.reply({ embeds: [URLEmbed] });
+ } catch {
+ /**/
}
- // Safety to prevent users from entering unexpected data that might result in strange behavior in a URL.
- const encodedSearchQuery = encodeURIComponent(query);
+ const filter = new Filter();
+ if (filter.isProfane(searchWord)) {
+ const profanityEmbed = makeEmbed({
+ title: 'FlyByWire Documentation | Error',
+ description: 'Providing profanity to the Documentation search command is not allowed.',
+ color: Colors.Red,
+ });
- const queryEmbed = makeEmbed({
- title: 'FlyByWire Documentation Search',
- description: `Search the FlyByWire Documentation for "${query}" [here](${DOCS_BASE_URL}/?q=${encodedSearchQuery}).`,
- });
- return interaction.reply({ embeds: [queryEmbed] });
+ return interaction.reply({ embeds: [profanityEmbed] });
+ }
+ }
+
+ // Safety to prevent users from entering unexpected data that might result in strange behavior in a URL.
+ const encodedSearchQuery = encodeURIComponent(query);
+
+ const queryEmbed = makeEmbed({
+ title: 'FlyByWire Documentation Search',
+ description: `Search the FlyByWire Documentation for "${query}" [here](${DOCS_BASE_URL}/?q=${encodedSearchQuery}).`,
+ });
+ return interaction.reply({ embeds: [queryEmbed] });
});
diff --git a/src/commands/utils/github/functions/githubPullRequest.ts b/src/commands/utils/github/functions/githubPullRequest.ts
index c656d566..f9dd4518 100644
--- a/src/commands/utils/github/functions/githubPullRequest.ts
+++ b/src/commands/utils/github/functions/githubPullRequest.ts
@@ -5,40 +5,48 @@ import { makeEmbed } from '../../../../lib';
const syntaxHelp = '\nSyntax:\nAircraft repo: `/github pr `\nAny FBW repo: `/github pr `';
const noQueryEmbed = makeEmbed({
- title: 'PR Error | Missing Query',
- description: `Invalid command!${syntaxHelp}`,
- color: Colors.Red,
+ title: 'PR Error | Missing Query',
+ description: `Invalid command!${syntaxHelp}`,
+ color: Colors.Red,
});
const invalidEmbed = makeEmbed({
- title: 'PR Error | Invalid',
- description: `Something went wrong! Did you provide the correct repo/PR id?${syntaxHelp}`,
- color: Colors.Red,
+ title: 'PR Error | Invalid',
+ description: `Something went wrong! Did you provide the correct repo/PR id?${syntaxHelp}`,
+ color: Colors.Red,
});
export async function handleGithubPullRequest(interaction: ChatInputCommandInteraction<'cached'>) {
- const prNumber = interaction.options.getString('pr_number');
- const repoName = interaction.options.getString('repo');
-
- if (!prNumber) return interaction.reply({ embeds: [noQueryEmbed] });
-
- const cleanedPrNumber = prNumber.replace('#', '');
-
- if (repoName) {
- try {
- const response = await request('GET /repos/flybywiresim/{repo}/pulls/{pull_number}', {
- repo: repoName,
- pull_number: cleanedPrNumber,
- });
- return interaction.reply(response.data.html_url);
- } catch {
- return interaction.reply({ embeds: [invalidEmbed] });
- }
- } else {
- try {
- const response = await request('GET /repos/flybywiresim/a32nx/pulls/{pull_number}', { pull_number: cleanedPrNumber });
- return interaction.reply(response.data.html_url);
- } catch {
- return interaction.reply({ embeds: [invalidEmbed] });
- }
+ const prNumber = interaction.options.getString('pr_number');
+ const repoName = interaction.options.getString('repo');
+
+ if (!prNumber) return interaction.reply({ embeds: [noQueryEmbed] });
+
+ const cleanedPrNumber = prNumber.replace('#', '');
+
+ if (repoName) {
+ try {
+ const response = await request('GET /repos/flybywiresim/{repo}/pulls/{pull_number}', {
+ repo: repoName,
+ pull_number: cleanedPrNumber,
+ });
+
+ // octokit returns untyped data - nothing we can do about
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
+ return interaction.reply(response.data.html_url);
+ } catch {
+ return interaction.reply({ embeds: [invalidEmbed] });
+ }
+ } else {
+ try {
+ const response = await request('GET /repos/flybywiresim/a32nx/pulls/{pull_number}', {
+ pull_number: cleanedPrNumber,
+ });
+
+ // octokit returns untyped data - nothing we can do about
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
+ return interaction.reply(response.data.html_url);
+ } catch {
+ return interaction.reply({ embeds: [invalidEmbed] });
}
+ }
}
diff --git a/src/commands/utils/github/functions/handleGithubIssue.ts b/src/commands/utils/github/functions/handleGithubIssue.ts
index cb7864a4..bf0c1421 100644
--- a/src/commands/utils/github/functions/handleGithubIssue.ts
+++ b/src/commands/utils/github/functions/handleGithubIssue.ts
@@ -5,40 +5,48 @@ import { makeEmbed } from '../../../../lib';
const syntaxHelp = '\nSyntax:\nAircraft repo: `/github issue `\nAny FBW repo: `/github issue `';
const noQueryEmbed = makeEmbed({
- title: 'Issue Error | Missing Query',
- description: `Invalid command!${syntaxHelp}`,
- color: Colors.Red,
+ title: 'Issue Error | Missing Query',
+ description: `Invalid command!${syntaxHelp}`,
+ color: Colors.Red,
});
const invalidEmbed = makeEmbed({
- title: 'Issue Error | Invalid',
- description: `Something went wrong! Did you provide the correct repo/Issue id?${syntaxHelp}`,
- color: Colors.Red,
+ title: 'Issue Error | Invalid',
+ description: `Something went wrong! Did you provide the correct repo/Issue id?${syntaxHelp}`,
+ color: Colors.Red,
});
export async function handleGithubIssue(interaction: ChatInputCommandInteraction<'cached'>) {
- const issueNumber = interaction.options.getString('issue_number');
- const repoName = interaction.options.getString('repo');
-
- if (!issueNumber) return interaction.reply({ embeds: [noQueryEmbed] });
-
- const cleanedIssueNumber = issueNumber.replace('#', '');
-
- if (repoName) {
- try {
- const response = await request('GET /repos/flybywiresim/{repo}/issues/{issue_number}', {
- repo: repoName,
- issue_number: cleanedIssueNumber,
- });
- return interaction.reply(response.data.html_url);
- } catch {
- return interaction.reply({ embeds: [invalidEmbed] });
- }
- } else {
- try {
- const response = await request('GET /repos/flybywiresim/a32nx/issues/{issue_number}', { issue_number: cleanedIssueNumber });
- return interaction.reply(response.data.html_url);
- } catch {
- return interaction.reply({ embeds: [invalidEmbed] });
- }
+ const issueNumber = interaction.options.getString('issue_number');
+ const repoName = interaction.options.getString('repo');
+
+ if (!issueNumber) return interaction.reply({ embeds: [noQueryEmbed] });
+
+ const cleanedIssueNumber = issueNumber.replace('#', '');
+
+ if (repoName) {
+ try {
+ const response = await request('GET /repos/flybywiresim/{repo}/issues/{issue_number}', {
+ repo: repoName,
+ issue_number: cleanedIssueNumber,
+ });
+
+ // octokit returns untyped data - nothing we can do about
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
+ return interaction.reply(response.data.html_url);
+ } catch {
+ return interaction.reply({ embeds: [invalidEmbed] });
+ }
+ } else {
+ try {
+ const response = await request('GET /repos/flybywiresim/a32nx/issues/{issue_number}', {
+ issue_number: cleanedIssueNumber,
+ });
+
+ // octokit returns untyped data - nothing we can do about
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
+ return interaction.reply(response.data.html_url);
+ } catch {
+ return interaction.reply({ embeds: [invalidEmbed] });
}
+ }
}
diff --git a/src/commands/utils/github/github.ts b/src/commands/utils/github/github.ts
index 3cfec522..f36e44bf 100644
--- a/src/commands/utils/github/github.ts
+++ b/src/commands/utils/github/github.ts
@@ -4,61 +4,63 @@ import { handleGithubPullRequest } from './functions/githubPullRequest';
import { handleGithubIssue } from './functions/handleGithubIssue';
const data = slashCommandStructure({
- name: 'github',
- description: 'Retrieve links for a GitHub pull request or issue.',
- type: ApplicationCommandType.ChatInput,
- options: [
+ name: 'github',
+ description: 'Retrieve links for a GitHub pull request or issue.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'pr',
+ description: 'Retrieves the link of the provided GitHub pull request.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
{
- name: 'pr',
- description: 'Retrieves the link of the provided GitHub pull request.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [{
- name: 'pr_number',
- description: 'Please provide the pull request number.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- {
- name: 'repo',
- description: 'Please provide the repo name.',
- type: ApplicationCommandOptionType.String,
- required: false,
- },
- ],
+ name: 'pr_number',
+ description: 'Please provide the pull request number.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
},
{
- name: 'issue',
- description: 'Retrieves the link of the provided GitHub issue.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [{
- name: 'issue_number',
- description: 'Please provide the issue number.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- {
- name: 'repo',
- description: 'Please provide the repo name.',
- type: ApplicationCommandOptionType.String,
- required: false,
- },
- ],
+ name: 'repo',
+ description: 'Please provide the repo name.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
},
- ],
+ ],
+ },
+ {
+ name: 'issue',
+ description: 'Retrieves the link of the provided GitHub issue.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'issue_number',
+ description: 'Please provide the issue number.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ },
+ {
+ name: 'repo',
+ description: 'Please provide the repo name.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ },
+ ],
+ },
+ ],
});
export default slashCommand(data, async ({ interaction }) => {
- const subcommandName = interaction.options.getSubcommand();
+ const subcommandName = interaction.options.getSubcommand();
- switch (subcommandName) {
+ switch (subcommandName) {
case 'pr':
- await handleGithubPullRequest(interaction);
- break;
+ await handleGithubPullRequest(interaction);
+ break;
case 'issue':
- await handleGithubIssue(interaction);
- break;
+ await handleGithubIssue(interaction);
+ break;
default:
- await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
- }
+ await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
+ }
});
diff --git a/src/commands/utils/help.ts b/src/commands/utils/help.ts
index 7702a60a..4daed07b 100644
--- a/src/commands/utils/help.ts
+++ b/src/commands/utils/help.ts
@@ -4,110 +4,111 @@ import { Logger, makeEmbed, createPaginatedEmbedHandler, slashCommand, slashComm
// May need re wrting to pull commands from index instead of the API
const data = slashCommandStructure({
- name: 'help',
- description: 'Display a list of all commands and subcommands.',
- type: ApplicationCommandType.ChatInput,
+ name: 'help',
+ description: 'Display a list of all commands and subcommands.',
+ type: ApplicationCommandType.ChatInput,
});
export default slashCommand(data, async ({ interaction }: { interaction: CommandInteraction }) => {
- try {
- // Fetch all commands from the API based on the environment
-
- let commands;
-
- if (process.env.NODE_ENV === 'production') {
- commands = await interaction.client.application?.commands.fetch();
- } else {
- commands = await interaction.guild?.commands.fetch();
- }
-
- // Check if the commands were fetched successfully
-
- if (!commands) {
- return interaction.reply({
- content: 'An error occurred while fetching commands.',
- ephemeral: true,
- });
- }
-
- // Convert the iterable of commands into an array
- const commandArray = Array.from(commands.values());
-
- // Sort the commands alphabetically by name
- const sortedCommands = commandArray.sort((a, b) => a.name.localeCompare(b.name));
-
- // Generate an array of embeds for all pages
- const pageLimit = 10;
- const embeds = [];
- for (let page = 0; page * pageLimit < sortedCommands.length; page++) {
- const startIndex = page * pageLimit;
- const endIndex = startIndex + pageLimit;
- const currentCommands = sortedCommands.slice(startIndex, endIndex);
- const totalPages = Math.ceil(sortedCommands.length / pageLimit);
-
- // Build the description with subcommands and subcommand groups
- const description = currentCommands.map((command) => {
- let { description } = command;
-
- // Check if it's a context-specific message command
- const isMessageCommand = command.type === ApplicationCommandType.Message;
-
- // Check if it's a context-specific user command
- const isUserCommand = command.type === ApplicationCommandType.User;
-
- const subcommandList = command.options?.filter(
- (option) => option.type === ApplicationCommandOptionType.Subcommand
- || option.type === ApplicationCommandOptionType.SubcommandGroup,
- );
-
- if (subcommandList && subcommandList.length > 0) {
- const subcommandDescription = subcommandList
- .map((subcommand) => {
- if (subcommand.type === ApplicationCommandOptionType.Subcommand) {
- return subcommand.name;
- }
- if (subcommand.type === ApplicationCommandOptionType.SubcommandGroup) {
- const groupSubcommands = subcommand.options?.filter(
- (sub) => sub.type === ApplicationCommandOptionType.Subcommand,
- );
- if (groupSubcommands && groupSubcommands.length > 0) {
- return `${subcommand.name} [${groupSubcommands
- .map((sub) => sub.name)
- .join(', ')}]`;
- }
- return `${subcommand.name} [None]`;
- }
- return '';
- })
- .join(', '); // Use a comma to separate subcommands
- description += `\n**Subcommands and Groups:** \n${subcommandDescription}`;
- }
+ try {
+ // Fetch all commands from the API based on the environment
- // Append a label for context-specific message and user commands
- if (isMessageCommand) {
- description += '\n(Context Command - Message)';
- } else if (isUserCommand) {
- description += '\n(Context Command - User)';
- }
+ let commands;
+
+ if (process.env.NODE_ENV === 'production') {
+ commands = await interaction.client.application?.commands.fetch();
+ } else {
+ commands = await interaction.guild?.commands.fetch();
+ }
+
+ // Check if the commands were fetched successfully
- return `**${command.name}**: ${description}`;
- }).join('\n\n');
-
- const embed = makeEmbed({
- title: `Bot Commands - Page ${page + 1} of ${totalPages}`,
- description,
- });
- embeds.push(embed);
- }
-
- // Use the pagination function to send the paginated embeds
- return createPaginatedEmbedHandler(interaction, embeds);
- } catch (error) {
- Logger.error(error);
- return interaction.reply({
- content: 'An error occurred while fetching commands.',
- ephemeral: true,
- });
- // Handle errors appropriately
+ if (!commands) {
+ return interaction.reply({
+ content: 'An error occurred while fetching commands.',
+ ephemeral: true,
+ });
}
+
+ // Convert the iterable of commands into an array
+ const commandArray = Array.from(commands.values());
+
+ // Sort the commands alphabetically by name
+ const sortedCommands = commandArray.sort((a, b) => a.name.localeCompare(b.name));
+
+ // Generate an array of embeds for all pages
+ const pageLimit = 10;
+ const embeds = [];
+ for (let page = 0; page * pageLimit < sortedCommands.length; page++) {
+ const startIndex = page * pageLimit;
+ const endIndex = startIndex + pageLimit;
+ const currentCommands = sortedCommands.slice(startIndex, endIndex);
+ const totalPages = Math.ceil(sortedCommands.length / pageLimit);
+
+ // Build the description with subcommands and subcommand groups
+ const description = currentCommands
+ .map((command) => {
+ let { description } = command;
+
+ // Check if it's a context-specific message command
+ const isMessageCommand = command.type === ApplicationCommandType.Message;
+
+ // Check if it's a context-specific user command
+ const isUserCommand = command.type === ApplicationCommandType.User;
+
+ const subcommandList = command.options?.filter(
+ (option) =>
+ option.type === ApplicationCommandOptionType.Subcommand ||
+ option.type === ApplicationCommandOptionType.SubcommandGroup,
+ );
+
+ if (subcommandList && subcommandList.length > 0) {
+ const subcommandDescription = subcommandList
+ .map((subcommand) => {
+ if (subcommand.type === ApplicationCommandOptionType.Subcommand) {
+ return subcommand.name;
+ }
+ if (subcommand.type === ApplicationCommandOptionType.SubcommandGroup) {
+ const groupSubcommands = subcommand.options?.filter(
+ (sub) => sub.type === ApplicationCommandOptionType.Subcommand,
+ );
+ if (groupSubcommands && groupSubcommands.length > 0) {
+ return `${subcommand.name} [${groupSubcommands.map((sub) => sub.name).join(', ')}]`;
+ }
+ return `${subcommand.name} [None]`;
+ }
+ return '';
+ })
+ .join(', '); // Use a comma to separate subcommands
+ description += `\n**Subcommands and Groups:** \n${subcommandDescription}`;
+ }
+
+ // Append a label for context-specific message and user commands
+ if (isMessageCommand) {
+ description += '\n(Context Command - Message)';
+ } else if (isUserCommand) {
+ description += '\n(Context Command - User)';
+ }
+
+ return `**${command.name}**: ${description}`;
+ })
+ .join('\n\n');
+
+ const embed = makeEmbed({
+ title: `Bot Commands - Page ${page + 1} of ${totalPages}`,
+ description,
+ });
+ embeds.push(embed);
+ }
+
+ // Use the pagination function to send the paginated embeds
+ return createPaginatedEmbedHandler(interaction, embeds);
+ } catch (error) {
+ Logger.error(error);
+ return interaction.reply({
+ content: 'An error occurred while fetching commands.',
+ ephemeral: true,
+ });
+ // Handle errors appropriately
+ }
});
diff --git a/src/commands/utils/liveFlights.ts b/src/commands/utils/liveFlights.ts
index cc0e0b96..cf296a09 100644
--- a/src/commands/utils/liveFlights.ts
+++ b/src/commands/utils/liveFlights.ts
@@ -2,33 +2,33 @@ import { ApplicationCommandType, Colors } from 'discord.js';
import { slashCommand, slashCommandStructure, makeEmbed, Logger } from '../../lib';
const data = slashCommandStructure({
- name: 'live-flights',
- description: 'Get the current live flights for FlyByWire Simulations.',
- type: ApplicationCommandType.ChatInput,
+ name: 'live-flights',
+ description: 'Get the current live flights for FlyByWire Simulations.',
+ type: ApplicationCommandType.ChatInput,
});
const FBW_WEB_MAP_URL = 'https://flybywiresim.com/map';
const FBW_API_BASE_URL = 'https://api.flybywiresim.com';
export default slashCommand(data, async ({ interaction }) => {
- try {
- const flights = await fetch(`${FBW_API_BASE_URL}/txcxn/_count`).then((res) => res.json());
- const flightsEmbed = makeEmbed({
- title: 'Live Flights',
- description: `There are currently **${flights}** active flights with TELEX enabled.`,
- footer: { text: 'Note: This includes the A32NX, and other aircraft using FlyByWire systems' },
- url: FBW_WEB_MAP_URL,
- timestamp: new Date().toISOString(),
- });
- return interaction.reply({ embeds: [flightsEmbed] });
- } catch (e) {
- const error = e as Error;
- Logger.error(error);
- const errorEmbed = makeEmbed({
- title: 'Error | Live Flights',
- description: error.message,
- color: Colors.Red,
- });
- return interaction.reply({ embeds: [errorEmbed] });
- }
+ try {
+ const flights = await fetch(`${FBW_API_BASE_URL}/txcxn/_count`).then((res) => res.json());
+ const flightsEmbed = makeEmbed({
+ title: 'Live Flights',
+ description: `There are currently **${flights}** active flights with TELEX enabled.`,
+ footer: { text: 'Note: This includes the A32NX, and other aircraft using FlyByWire systems' },
+ url: FBW_WEB_MAP_URL,
+ timestamp: new Date().toISOString(),
+ });
+ return interaction.reply({ embeds: [flightsEmbed] });
+ } catch (e) {
+ const error = e as Error;
+ Logger.error(error);
+ const errorEmbed = makeEmbed({
+ title: 'Error | Live Flights',
+ description: error.message,
+ color: Colors.Red,
+ });
+ return interaction.reply({ embeds: [errorEmbed] });
+ }
});
diff --git a/src/commands/utils/locate/base-urls.ts b/src/commands/utils/locate/base-urls.ts
index 1d13756a..0600da93 100644
--- a/src/commands/utils/locate/base-urls.ts
+++ b/src/commands/utils/locate/base-urls.ts
@@ -7,16 +7,16 @@ const LOCATE_DOCS_BASE_URL = 'https://docs.flybywiresim.com';
const LOCATE_A32NX_DOCS_BASE_URL = `${LOCATE_DOCS_BASE_URL}/pilots-corner/a32nx-briefing/flight-deck`;
export const LOCATE_DOCS_BASE_URLS = {
- a32nx: {
- flightdeck: 'https://docs.flybywiresim.com/pilots-corner/a32nx-briefing/flight-deck/',
- flypad: 'https://docs.flybywiresim.com/fbw-a32nx/feature-guides/flypados3/',
- rearCb: `${LOCATE_A32NX_DOCS_BASE_URL}/ovhd-aft/circuit/#rear-right-back-panel`,
- overhead: `${LOCATE_A32NX_DOCS_BASE_URL}/ovhd`,
- aftOverhead: `${LOCATE_A32NX_DOCS_BASE_URL}/ovhd-aft`,
- glareshield: `${LOCATE_A32NX_DOCS_BASE_URL}/glareshield`,
- front: `${LOCATE_A32NX_DOCS_BASE_URL}/front`,
- pedestal: `${LOCATE_A32NX_DOCS_BASE_URL}/pedestal`,
- },
+ a32nx: {
+ flightdeck: 'https://docs.flybywiresim.com/pilots-corner/a32nx-briefing/flight-deck/',
+ flypad: 'https://docs.flybywiresim.com/fbw-a32nx/feature-guides/flypados3/',
+ rearCb: `${LOCATE_A32NX_DOCS_BASE_URL}/ovhd-aft/circuit/#rear-right-back-panel`,
+ overhead: `${LOCATE_A32NX_DOCS_BASE_URL}/ovhd`,
+ aftOverhead: `${LOCATE_A32NX_DOCS_BASE_URL}/ovhd-aft`,
+ glareshield: `${LOCATE_A32NX_DOCS_BASE_URL}/glareshield`,
+ front: `${LOCATE_A32NX_DOCS_BASE_URL}/front`,
+ pedestal: `${LOCATE_A32NX_DOCS_BASE_URL}/pedestal`,
+ },
};
// Base URL for all locate-cmd images.
@@ -26,13 +26,13 @@ const LOCATE_IMAGE_BASE_URL = `${imageBaseUrl}/utils/locate-cmd`;
const LOCATE_A32NX_IMAGE_BASE_URL = `${LOCATE_IMAGE_BASE_URL}/a32nx`;
export const LOCATE_IMAGE_BASE_URLS = {
- a32nx: {
- flypad: `${LOCATE_A32NX_IMAGE_BASE_URL}`,
- rearCb: `${LOCATE_A32NX_IMAGE_BASE_URL}`,
- overhead: `${LOCATE_A32NX_IMAGE_BASE_URL}/overhead`,
- aftOverhead: `${LOCATE_A32NX_IMAGE_BASE_URL}/aft-overhead`,
- front: `${LOCATE_A32NX_IMAGE_BASE_URL}/front`,
- glareshield: `${LOCATE_A32NX_IMAGE_BASE_URL}/glareshield`,
- pedestal: `${LOCATE_A32NX_IMAGE_BASE_URL}/pedestal`,
- },
+ a32nx: {
+ flypad: `${LOCATE_A32NX_IMAGE_BASE_URL}`,
+ rearCb: `${LOCATE_A32NX_IMAGE_BASE_URL}`,
+ overhead: `${LOCATE_A32NX_IMAGE_BASE_URL}/overhead`,
+ aftOverhead: `${LOCATE_A32NX_IMAGE_BASE_URL}/aft-overhead`,
+ front: `${LOCATE_A32NX_IMAGE_BASE_URL}/front`,
+ glareshield: `${LOCATE_A32NX_IMAGE_BASE_URL}/glareshield`,
+ pedestal: `${LOCATE_A32NX_IMAGE_BASE_URL}/pedestal`,
+ },
};
diff --git a/src/commands/utils/locate/functions/filterSearchResults.ts b/src/commands/utils/locate/functions/filterSearchResults.ts
index c0779d4d..29957185 100644
--- a/src/commands/utils/locate/functions/filterSearchResults.ts
+++ b/src/commands/utils/locate/functions/filterSearchResults.ts
@@ -2,26 +2,28 @@ import { ApplicationCommandOptionChoiceData } from 'discord.js';
import { Panel } from '../panels/panel';
export const filterSearchResults = (query: string, source: Map) => {
- // Get any target that includes the query string.
- const possibleTargets = Array.from(source.keys()).filter((current) => current.toLowerCase().includes(query.toLowerCase()));
+ // Get any target that includes the query string.
+ const possibleTargets = Array.from(source.keys()).filter((current) =>
+ current.toLowerCase().includes(query.toLowerCase()),
+ );
- // Sort possible targets based on the length of the match. -> More equal characters between query and target = higher ranking
- possibleTargets.sort((a, b) => a.indexOf(query) - b.indexOf(query));
+ // Sort possible targets based on the length of the match. -> More equal characters between query and target = higher ranking
+ possibleTargets.sort((a, b) => a.indexOf(query) - b.indexOf(query));
- // Remove all targets that are not preceded by a hyphen, or where .substring(0) !== query.
- const filteredTargets = possibleTargets.filter((current) => {
- const indexOfQuery = current.indexOf(query);
+ // Remove all targets that are not preceded by a hyphen, or where .substring(0) !== query.
+ const filteredTargets = possibleTargets.filter((current) => {
+ const indexOfQuery = current.indexOf(query);
- if (indexOfQuery === 0) return true;
+ if (indexOfQuery === 0) return true;
- return current.charAt(indexOfQuery - 1) === '-';
- });
+ return current.charAt(indexOfQuery - 1) === '-';
+ });
- // Limit the number of returned targets to 25. (Discord limitation)
- const choices: ApplicationCommandOptionChoiceData[] = [];
- for (let i = 0; i < filteredTargets.length && i < 25; i++) {
- choices.push({ name: filteredTargets[i], value: filteredTargets[i] });
- }
+ // Limit the number of returned targets to 25. (Discord limitation)
+ const choices: ApplicationCommandOptionChoiceData[] = [];
+ for (let i = 0; i < filteredTargets.length && i < 25; i++) {
+ choices.push({ name: filteredTargets[i], value: filteredTargets[i] });
+ }
- return choices;
+ return choices;
};
diff --git a/src/commands/utils/locate/functions/handleCommand.ts b/src/commands/utils/locate/functions/handleCommand.ts
index adebbe6d..5b091cec 100644
--- a/src/commands/utils/locate/functions/handleCommand.ts
+++ b/src/commands/utils/locate/functions/handleCommand.ts
@@ -4,42 +4,43 @@ import { makeEmbed, makeLines } from '../../../../lib';
import { cleanTargetQuery } from './cleanTargetQuery';
const emptyTargetEmbed = makeEmbed({
- title: 'Locate - Empty target',
- description: 'Please provide a switch, system or panel that you want to locate.',
- color: Colors.Red,
+ title: 'Locate - Empty target',
+ description: 'Please provide a switch, system or panel that you want to locate.',
+ color: Colors.Red,
});
const invalidTargetEmbed = makeEmbed({
- title: 'Locate - Invalid target',
- description: 'The target you provided is invalid. Please type your search query and choose one from the list.',
- color: Colors.Red,
+ title: 'Locate - Invalid target',
+ description: 'The target you provided is invalid. Please type your search query and choose one from the list.',
+ color: Colors.Red,
});
-const locateEmbed = (panel: Panel) => makeEmbed({
+const locateEmbed = (panel: Panel) =>
+ makeEmbed({
title: panel.title,
url: panel.docsUrl,
description: makeLines([
- `Learn more about the ${panel.name} and the flight deck:`,
- `* [${panel.name} Documentation](${panel.docsUrl})`,
- `* [Flight Deck Overview](${panel.flightDeckUrl})`,
+ `Learn more about the ${panel.name} and the flight deck:`,
+ `* [${panel.name} Documentation](${panel.docsUrl})`,
+ `* [Flight Deck Overview](${panel.flightDeckUrl})`,
]),
fields: panel.description ? [panel.description] : [],
image: { url: panel.imageUrl },
footer: { text: 'Tip: Click the image to view in full size' },
-});
+ });
export async function handleCommand(interaction: ChatInputCommandInteraction<'cached'>, panelMap: Map) {
- const target = interaction.options.getString('target');
+ const target = interaction.options.getString('target');
- if (!target) return interaction.editReply({ embeds: [emptyTargetEmbed] });
+ if (!target) return interaction.editReply({ embeds: [emptyTargetEmbed] });
- // Replace whitespace characters with a hyphen.
- const cleanTarget = cleanTargetQuery(target);
+ // Replace whitespace characters with a hyphen.
+ const cleanTarget = cleanTargetQuery(target);
- if (!Array.from(panelMap.keys()).includes(cleanTarget)) {
- return interaction.editReply({ embeds: [invalidTargetEmbed] });
- }
- const panel = panelMap.get(cleanTarget)!;
+ if (!Array.from(panelMap.keys()).includes(cleanTarget)) {
+ return interaction.editReply({ embeds: [invalidTargetEmbed] });
+ }
+ const panel = panelMap.get(cleanTarget)!;
- return interaction.editReply({ embeds: [locateEmbed(panel)] });
+ return interaction.editReply({ embeds: [locateEmbed(panel)] });
}
diff --git a/src/commands/utils/locate/locate.ts b/src/commands/utils/locate/locate.ts
index 13dd0f6e..6fa996cd 100644
--- a/src/commands/utils/locate/locate.ts
+++ b/src/commands/utils/locate/locate.ts
@@ -8,9 +8,9 @@ import { cleanTargetQuery } from './functions/cleanTargetQuery';
const a32nxPanelMap: Map = new Map();
for (const panel of a32nxPanels) {
- for (const identifier of panel.identifiers) {
- a32nxPanelMap.set(identifier, panel);
- }
+ for (const identifier of panel.identifiers) {
+ a32nxPanelMap.set(identifier, panel);
+ }
}
/* const a380xPanelMap: Map = new Map();
@@ -21,25 +21,25 @@ for (const panel of a380xPanel) {
} */
const data = slashCommandStructure({
- name: 'locate',
- description: 'Locate any switch or panel on the flight decks of our aircraft.',
- type: ApplicationCommandType.ChatInput,
- options: [
+ name: 'locate',
+ description: 'Locate any switch or panel on the flight decks of our aircraft.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'a32nx',
+ description: 'Locate any switch or panel on the A32NX flight deck.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
{
- name: 'a32nx',
- description: 'Locate any switch or panel on the A32NX flight deck.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'target',
- description: 'Specify the component to locate.',
- type: ApplicationCommandOptionType.String,
- autocomplete: true,
- required: true,
- },
- ],
+ name: 'target',
+ description: 'Specify the component to locate.',
+ type: ApplicationCommandOptionType.String,
+ autocomplete: true,
+ required: true,
},
- /* {
+ ],
+ },
+ /* {
name: 'a380x',
description: 'Locate any switch or panel on the A380X flight deck.',
type: ApplicationCommandOptionType.Subcommand,
@@ -53,49 +53,53 @@ const data = slashCommandStructure({
},
],
}, */
- ],
+ ],
});
const autocompleteCallback: AutocompleteCallback = ({ interaction }) => {
- const subcommand = interaction.options.getSubcommand();
- const target = interaction.options.getString('target')!;
+ const subcommand = interaction.options.getSubcommand();
+ const target = interaction.options.getString('target')!;
- // If target is empty, trigger 'no values match your query' UI state in discord client.
- if (target.length < 1) return interaction.respond([]);
+ // If target is empty, trigger 'no values match your query' UI state in discord client.
+ if (target.length < 1) return interaction.respond([]);
- // Replace whitespace characters with a hyphen.
- const cleanTarget = cleanTargetQuery(target);
+ // Replace whitespace characters with a hyphen.
+ const cleanTarget = cleanTargetQuery(target);
- let choices: ApplicationCommandOptionChoiceData[];
- switch (subcommand) {
+ let choices: ApplicationCommandOptionChoiceData[];
+ switch (subcommand) {
case 'a32nx':
- choices = filterSearchResults(cleanTarget, a32nxPanelMap);
- break;
+ choices = filterSearchResults(cleanTarget, a32nxPanelMap);
+ break;
/* case 'a380x':
choices = filterSearchResults(cleanTarget, a380xPanelMap);
break;
*/
default:
- return interaction.respond([]);
- }
+ return interaction.respond([]);
+ }
- return interaction.respond(choices);
+ return interaction.respond(choices);
};
-export default slashCommand(data, async ({ interaction }) => {
+export default slashCommand(
+ data,
+ async ({ interaction }) => {
await interaction.deferReply();
const subcommand = interaction.options.getSubcommand();
switch (subcommand) {
- case 'a32nx':
+ case 'a32nx':
await handleCommand(interaction, a32nxPanelMap);
break;
- /* case 'a380x':
+ /* case 'a380x':
await handleCommand(interaction, a380xPanelMap);
break;
*/
- default:
+ default:
await interaction.editReply({ content: 'Unknown subcommand' });
}
-}, autocompleteCallback);
+ },
+ autocompleteCallback,
+);
diff --git a/src/commands/utils/locate/panels/a32nx/a32nx-panels.ts b/src/commands/utils/locate/panels/a32nx/a32nx-panels.ts
index 51272118..30cedccf 100644
--- a/src/commands/utils/locate/panels/a32nx/a32nx-panels.ts
+++ b/src/commands/utils/locate/panels/a32nx/a32nx-panels.ts
@@ -1,86 +1,150 @@
import { Panel } from '../panel';
import { flyPad } from './flyPad';
-import { accuPressPanel, autobrakeAndGearPanel, clockPanel, dcdu, ewd, instrumentLightingPanel, isis, nd, pfd, sd } from './front-panel';
+import {
+ accuPressPanel,
+ autobrakeAndGearPanel,
+ clockPanel,
+ dcdu,
+ ewd,
+ instrumentLightingPanel,
+ isis,
+ nd,
+ pfd,
+ sd,
+} from './front-panel';
import { efisPanel, fcuPanel, lightKnobsPanel, warningPanel } from './glareshield';
-import { antiIcePanel, adirsPanel, apuPanel, callsPanel, cvrPanel, emerElecPwrPanel, evacPanel, extLtPanel, fltCtlPanel, gpwsPanel, intLtPanel, oxyPanel, paVideoPanel, signsPanel, wiperPanel, cabinPressPanel, airCondPanel, elecPanel, fuelPanel, hydPanel, firePanel, engManStartPanel, ventilationPanel, cargoSmokePanel, cargoVentPanel, thirdACP, readingLightsJumpSeats, cockpitDoorIndicatorPanel, eltPanel, pedestalLightPanel, emerCbPanel, fmsLoadPanel, maintenancePanel } from './overhead';
-import { aidsDfdrPanel, atcTcasPanel, captPedestalLightingPanel, cockpitDoorPanel, console, ecamControlPanel, engPanel, flaps, gravityGearExtensionPanel, mcdu, parkBrkPanel, printer, rmpAcpPanel, rudderTrim, speedBrake, switchingPanel, thrLvrPitchTrim, wxPanel } from './pedestal';
+import {
+ antiIcePanel,
+ adirsPanel,
+ apuPanel,
+ callsPanel,
+ cvrPanel,
+ emerElecPwrPanel,
+ evacPanel,
+ extLtPanel,
+ fltCtlPanel,
+ gpwsPanel,
+ intLtPanel,
+ oxyPanel,
+ paVideoPanel,
+ signsPanel,
+ wiperPanel,
+ cabinPressPanel,
+ airCondPanel,
+ elecPanel,
+ fuelPanel,
+ hydPanel,
+ firePanel,
+ engManStartPanel,
+ ventilationPanel,
+ cargoSmokePanel,
+ cargoVentPanel,
+ thirdACP,
+ readingLightsJumpSeats,
+ cockpitDoorIndicatorPanel,
+ eltPanel,
+ pedestalLightPanel,
+ emerCbPanel,
+ fmsLoadPanel,
+ maintenancePanel,
+} from './overhead';
+import {
+ aidsDfdrPanel,
+ atcTcasPanel,
+ captPedestalLightingPanel,
+ cockpitDoorPanel,
+ console,
+ ecamControlPanel,
+ engPanel,
+ flaps,
+ gravityGearExtensionPanel,
+ mcdu,
+ parkBrkPanel,
+ printer,
+ rmpAcpPanel,
+ rudderTrim,
+ speedBrake,
+ switchingPanel,
+ thrLvrPitchTrim,
+ wxPanel,
+} from './pedestal';
import { rearBackCbPanel } from './rear-cb-panel';
export const a32nxPanels: Panel[] = [
- // OVERHEAD
- wiperPanel,
- callsPanel,
- oxyPanel,
- cvrPanel,
- gpwsPanel,
- emerElecPwrPanel,
- evacPanel,
- fltCtlPanel,
- adirsPanel,
- paVideoPanel,
- extLtPanel,
- apuPanel,
- signsPanel,
- intLtPanel,
- antiIcePanel,
- cabinPressPanel,
- airCondPanel,
- elecPanel,
- fuelPanel,
- hydPanel,
- firePanel,
- engManStartPanel,
- ventilationPanel,
- cargoSmokePanel,
- cargoVentPanel,
- thirdACP,
- readingLightsJumpSeats,
- cockpitDoorIndicatorPanel,
- eltPanel,
- pedestalLightPanel,
- emerCbPanel,
- rearBackCbPanel,
- fmsLoadPanel,
- maintenancePanel,
+ // OVERHEAD
+ wiperPanel,
+ callsPanel,
+ oxyPanel,
+ cvrPanel,
+ gpwsPanel,
+ emerElecPwrPanel,
+ evacPanel,
+ fltCtlPanel,
+ adirsPanel,
+ paVideoPanel,
+ extLtPanel,
+ apuPanel,
+ signsPanel,
+ intLtPanel,
+ antiIcePanel,
+ cabinPressPanel,
+ airCondPanel,
+ elecPanel,
+ fuelPanel,
+ hydPanel,
+ firePanel,
+ engManStartPanel,
+ ventilationPanel,
+ cargoSmokePanel,
+ cargoVentPanel,
+ thirdACP,
+ readingLightsJumpSeats,
+ cockpitDoorIndicatorPanel,
+ eltPanel,
+ pedestalLightPanel,
+ emerCbPanel,
+ rearBackCbPanel,
+ fmsLoadPanel,
+ maintenancePanel,
- // GLARESHIELD
- warningPanel,
- efisPanel,
- fcuPanel,
- lightKnobsPanel,
+ // GLARESHIELD
+ warningPanel,
+ efisPanel,
+ fcuPanel,
+ lightKnobsPanel,
- // FRONT PANEL
- instrumentLightingPanel,
- pfd,
- nd,
- isis,
- dcdu,
- ewd,
- sd,
- autobrakeAndGearPanel,
- clockPanel,
- accuPressPanel,
+ // FRONT PANEL
+ instrumentLightingPanel,
+ pfd,
+ nd,
+ isis,
+ dcdu,
+ ewd,
+ sd,
+ autobrakeAndGearPanel,
+ clockPanel,
+ accuPressPanel,
- // PEDESTAL
- console,
- mcdu,
- rmpAcpPanel,
- captPedestalLightingPanel,
- wxPanel,
- speedBrake,
- cockpitDoorPanel,
- switchingPanel,
- ecamControlPanel,
- thrLvrPitchTrim,
- engPanel,
- rudderTrim,
- parkBrkPanel,
- gravityGearExtensionPanel,
- aidsDfdrPanel,
- atcTcasPanel,
- flaps,
- printer,
+ // PEDESTAL
+ console,
+ mcdu,
+ rmpAcpPanel,
+ captPedestalLightingPanel,
+ wxPanel,
+ speedBrake,
+ cockpitDoorPanel,
+ switchingPanel,
+ ecamControlPanel,
+ thrLvrPitchTrim,
+ engPanel,
+ rudderTrim,
+ parkBrkPanel,
+ gravityGearExtensionPanel,
+ aidsDfdrPanel,
+ atcTcasPanel,
+ flaps,
+ printer,
- // flyPad
- flyPad,
+ // flyPad
+ flyPad,
];
diff --git a/src/commands/utils/locate/panels/a32nx/flyPad.ts b/src/commands/utils/locate/panels/a32nx/flyPad.ts
index 36e4dc0a..3b290808 100644
--- a/src/commands/utils/locate/panels/a32nx/flyPad.ts
+++ b/src/commands/utils/locate/panels/a32nx/flyPad.ts
@@ -2,14 +2,10 @@ import { LOCATE_DOCS_BASE_URLS, LOCATE_IMAGE_BASE_URLS } from '../../base-urls';
import { Panel } from '../panel';
export const flyPad: Panel = {
- name: 'flyPad',
- title: 'FlyByWire A32NX | flyPad (EFB)',
- docsUrl: LOCATE_DOCS_BASE_URLS.a32nx.flypad,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${LOCATE_IMAGE_BASE_URLS.a32nx.flypad}/efb_downscaled.gif`,
- identifiers: [
- 'flypad',
- 'efb',
- 'electronic-flight-bag',
- ],
+ name: 'flyPad',
+ title: 'FlyByWire A32NX | flyPad (EFB)',
+ docsUrl: LOCATE_DOCS_BASE_URLS.a32nx.flypad,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${LOCATE_IMAGE_BASE_URLS.a32nx.flypad}/efb_downscaled.gif`,
+ identifiers: ['flypad', 'efb', 'electronic-flight-bag'],
};
diff --git a/src/commands/utils/locate/panels/a32nx/front-panel.ts b/src/commands/utils/locate/panels/a32nx/front-panel.ts
index 6a75d57b..aa0a2ab7 100644
--- a/src/commands/utils/locate/panels/a32nx/front-panel.ts
+++ b/src/commands/utils/locate/panels/a32nx/front-panel.ts
@@ -5,160 +5,133 @@ const FRONT_DOCS_BASE_URL = LOCATE_DOCS_BASE_URLS.a32nx.front;
const FRONT_IMAGE_BASE_URL = LOCATE_IMAGE_BASE_URLS.a32nx.front;
export const instrumentLightingPanel: Panel = {
- name: 'Instrument Lighting Control Panel',
- title: 'FlyByWire A32NX | Instrument Lighting Control Panel',
- docsUrl: `${FRONT_DOCS_BASE_URL}/ilcp/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${FRONT_IMAGE_BASE_URL}/instrument_lighting.png`,
- identifiers: [
- 'instrument-brightness',
- 'instrument-lighting-panel',
- 'gpws-gs-button',
- 'pfd-brightness-knob',
- 'pfd-nd-xfr-button',
- 'nd-brightness-knob',
- 'loudspeaker-knob',
- 'console-floor-light-switch',
- ],
+ name: 'Instrument Lighting Control Panel',
+ title: 'FlyByWire A32NX | Instrument Lighting Control Panel',
+ docsUrl: `${FRONT_DOCS_BASE_URL}/ilcp/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${FRONT_IMAGE_BASE_URL}/instrument_lighting.png`,
+ identifiers: [
+ 'instrument-brightness',
+ 'instrument-lighting-panel',
+ 'gpws-gs-button',
+ 'pfd-brightness-knob',
+ 'pfd-nd-xfr-button',
+ 'nd-brightness-knob',
+ 'loudspeaker-knob',
+ 'console-floor-light-switch',
+ ],
};
export const pfd: Panel = {
- name: 'PFD',
- title: 'FlyByWire A32NX | Primary Flight Display (PFD)',
- docsUrl: `${FRONT_DOCS_BASE_URL}/pfd`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${FRONT_IMAGE_BASE_URL}/pfd.png`,
- identifiers: [
- 'pfd',
- 'primary-flight-display',
- 'fma',
- 'flight-mode-annunciator',
- 'speed-tape',
- 'artificial-horizon',
- 'compass-scale',
- 'v-dev-scales',
- 'loc-scale',
- 'gs-scale',
- 'altitude-tape',
- 'vs-indicator',
- 'vertical-speed-indicator',
- ],
+ name: 'PFD',
+ title: 'FlyByWire A32NX | Primary Flight Display (PFD)',
+ docsUrl: `${FRONT_DOCS_BASE_URL}/pfd`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${FRONT_IMAGE_BASE_URL}/pfd.png`,
+ identifiers: [
+ 'pfd',
+ 'primary-flight-display',
+ 'fma',
+ 'flight-mode-annunciator',
+ 'speed-tape',
+ 'artificial-horizon',
+ 'compass-scale',
+ 'v-dev-scales',
+ 'loc-scale',
+ 'gs-scale',
+ 'altitude-tape',
+ 'vs-indicator',
+ 'vertical-speed-indicator',
+ ],
};
export const nd: Panel = {
- name: 'ND',
- title: 'FlyByWire A32NX | Navigation Display (ND)',
- docsUrl: `${FRONT_DOCS_BASE_URL}/nd`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${FRONT_IMAGE_BASE_URL}/nd.png`,
- identifiers: [
- 'nd',
- 'navigation-display',
- 'weather-radar',
- 'terrain-map',
- 'terr-on-nd-switch',
- ],
+ name: 'ND',
+ title: 'FlyByWire A32NX | Navigation Display (ND)',
+ docsUrl: `${FRONT_DOCS_BASE_URL}/nd`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${FRONT_IMAGE_BASE_URL}/nd.png`,
+ identifiers: ['nd', 'navigation-display', 'weather-radar', 'terrain-map', 'terr-on-nd-switch'],
};
export const isis: Panel = {
- name: 'ISIS',
- title: 'FlyByWire A32NX | Integrated Standby Instrument System (ISIS)',
- docsUrl: `${FRONT_DOCS_BASE_URL}/isis`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${FRONT_IMAGE_BASE_URL}/isis.png`,
- identifiers: [
- 'isis',
- 'integrated-standby-instrument-system',
- 'backup-pfd',
- ],
+ name: 'ISIS',
+ title: 'FlyByWire A32NX | Integrated Standby Instrument System (ISIS)',
+ docsUrl: `${FRONT_DOCS_BASE_URL}/isis`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${FRONT_IMAGE_BASE_URL}/isis.png`,
+ identifiers: ['isis', 'integrated-standby-instrument-system', 'backup-pfd'],
};
export const dcdu: Panel = {
- name: 'DCDU',
- title: 'FlyByWire A32NX | Datalink Ctl and Display Unit (DCDU)',
- docsUrl: `${FRONT_DOCS_BASE_URL}/dcdu`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${FRONT_IMAGE_BASE_URL}/dcdu.png`,
- identifiers: [
- 'dcdu',
- 'datalink-ctl-and-display-unit',
- 'cpdlc',
- ],
+ name: 'DCDU',
+ title: 'FlyByWire A32NX | Datalink Ctl and Display Unit (DCDU)',
+ docsUrl: `${FRONT_DOCS_BASE_URL}/dcdu`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${FRONT_IMAGE_BASE_URL}/dcdu.png`,
+ identifiers: ['dcdu', 'datalink-ctl-and-display-unit', 'cpdlc'],
};
export const ewd: Panel = {
- name: 'E/WD',
- title: 'FlyByWire A32NX | Engine and Warning Display (E/WD) (Upper ECAM)',
- docsUrl: `${FRONT_DOCS_BASE_URL}/upper-ecam`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${FRONT_IMAGE_BASE_URL}/ewd.png`,
- identifiers: [
- 'ecam-upper',
- 'upper-ecam',
- 'ewd',
- 'engine-and-warning-display',
- 'n1-display',
- ],
+ name: 'E/WD',
+ title: 'FlyByWire A32NX | Engine and Warning Display (E/WD) (Upper ECAM)',
+ docsUrl: `${FRONT_DOCS_BASE_URL}/upper-ecam`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${FRONT_IMAGE_BASE_URL}/ewd.png`,
+ identifiers: ['ecam-upper', 'upper-ecam', 'ewd', 'engine-and-warning-display', 'n1-display'],
};
export const sd: Panel = {
- name: 'SD',
- title: 'FlyByWire A32NX | System Display (SD) (Lower ECAM)',
- docsUrl: `${FRONT_DOCS_BASE_URL}/lower-ecam`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${FRONT_IMAGE_BASE_URL}/sd.png`,
- identifiers: [
- 'sd',
- 'system-display',
- 'lower-ecam',
- 'ecam-lower',
- 'tat-display',
- 'sat-display',
- 'isa-display',
- 'gw-display',
- 'gross-weight-display',
- ],
+ name: 'SD',
+ title: 'FlyByWire A32NX | System Display (SD) (Lower ECAM)',
+ docsUrl: `${FRONT_DOCS_BASE_URL}/lower-ecam`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${FRONT_IMAGE_BASE_URL}/sd.png`,
+ identifiers: [
+ 'sd',
+ 'system-display',
+ 'lower-ecam',
+ 'ecam-lower',
+ 'tat-display',
+ 'sat-display',
+ 'isa-display',
+ 'gw-display',
+ 'gross-weight-display',
+ ],
};
export const autobrakeAndGearPanel: Panel = {
- name: 'Autobrake and Gear Indicator',
- title: 'FlyByWire A32NX | Autobrake and Gear Indications',
- docsUrl: `${FRONT_DOCS_BASE_URL}/autobrake-gear`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${FRONT_IMAGE_BASE_URL}/autobrake_gear.png`,
- identifiers: [
- 'gear',
- 'ldg-gear-indicator',
- 'brk-fan-switch',
- 'brake-fan-switch',
- 'autobrake-switch',
- 'anti-skid-nosewheel-steering-switch',
- 'lg-lever',
- 'landing-gear-lever',
- ],
+ name: 'Autobrake and Gear Indicator',
+ title: 'FlyByWire A32NX | Autobrake and Gear Indications',
+ docsUrl: `${FRONT_DOCS_BASE_URL}/autobrake-gear`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${FRONT_IMAGE_BASE_URL}/autobrake_gear.png`,
+ identifiers: [
+ 'gear',
+ 'ldg-gear-indicator',
+ 'brk-fan-switch',
+ 'brake-fan-switch',
+ 'autobrake-switch',
+ 'anti-skid-nosewheel-steering-switch',
+ 'lg-lever',
+ 'landing-gear-lever',
+ ],
};
export const clockPanel: Panel = {
- name: 'Clock Panel',
- title: 'FlyByWire A32NX | Clock',
- docsUrl: `${FRONT_DOCS_BASE_URL}/clock`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${FRONT_IMAGE_BASE_URL}/clock.png`,
- identifiers: [
- 'clock',
- 'date',
- ],
+ name: 'Clock Panel',
+ title: 'FlyByWire A32NX | Clock',
+ docsUrl: `${FRONT_DOCS_BASE_URL}/clock`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${FRONT_IMAGE_BASE_URL}/clock.png`,
+ identifiers: ['clock', 'date'],
};
export const accuPressPanel: Panel = {
- name: 'Accumulator Pressure Indicator',
- title: 'FlyByWire A32NX | Accumulator Pressure Indicator',
- docsUrl: `${FRONT_DOCS_BASE_URL}/accu`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${FRONT_IMAGE_BASE_URL}/accu_press.png`,
- identifiers: [
- 'accu-press',
- 'accumulator-pressure-indicator',
- 'brake-pressure-indicator',
- ],
+ name: 'Accumulator Pressure Indicator',
+ title: 'FlyByWire A32NX | Accumulator Pressure Indicator',
+ docsUrl: `${FRONT_DOCS_BASE_URL}/accu`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${FRONT_IMAGE_BASE_URL}/accu_press.png`,
+ identifiers: ['accu-press', 'accumulator-pressure-indicator', 'brake-pressure-indicator'],
};
diff --git a/src/commands/utils/locate/panels/a32nx/glareshield.ts b/src/commands/utils/locate/panels/a32nx/glareshield.ts
index c7f999a5..e03cf34a 100644
--- a/src/commands/utils/locate/panels/a32nx/glareshield.ts
+++ b/src/commands/utils/locate/panels/a32nx/glareshield.ts
@@ -5,97 +5,93 @@ const GLARESHIELD_DOCS_BASE_URL = LOCATE_DOCS_BASE_URLS.a32nx.glareshield;
const GLARESHIELD_IMAGE_BASE_URL = LOCATE_IMAGE_BASE_URLS.a32nx.glareshield;
export const warningPanel: Panel = {
- name: 'Warning Panel',
- title: 'FlyByWire A32NX | Warning Panel',
- docsUrl: `${GLARESHIELD_DOCS_BASE_URL}/warning/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${GLARESHIELD_IMAGE_BASE_URL}/warning.png`,
- identifiers: [
- 'warning',
- 'warning-panel',
- 'atc-msg-button',
- 'autoland-warning-light',
- 'master-caution',
- 'master-warning',
- 'chrono',
- 'chrono-button',
- 'sidestick-priority-indicator',
- ],
+ name: 'Warning Panel',
+ title: 'FlyByWire A32NX | Warning Panel',
+ docsUrl: `${GLARESHIELD_DOCS_BASE_URL}/warning/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${GLARESHIELD_IMAGE_BASE_URL}/warning.png`,
+ identifiers: [
+ 'warning',
+ 'warning-panel',
+ 'atc-msg-button',
+ 'autoland-warning-light',
+ 'master-caution',
+ 'master-warning',
+ 'chrono',
+ 'chrono-button',
+ 'sidestick-priority-indicator',
+ ],
};
export const efisPanel: Panel = {
- name: 'EFIS',
- title: 'FlyByWire A32NX | EFIS Panel',
- docsUrl: `${GLARESHIELD_DOCS_BASE_URL}/efis_control/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${GLARESHIELD_IMAGE_BASE_URL}/efis.png`,
- identifiers: [
- 'efis',
- 'efis-panel',
- 'qnh',
- 'fd',
- 'flight-director-switch',
- 'ls',
- 'ls-switch',
- 'cstr',
- 'constraint-switch',
- 'wpt',
- 'waypoint-switch',
- 'vor-d',
- 'vor-dme-switch',
- 'ndb',
- 'ndb-switch',
- 'vor',
- 'adf',
- 'arpt',
- 'airport-switch',
- 'rose-mode',
- 'arc-mode',
- 'plan-mode',
- 'nd-range',
- 'adf-switch',
- 'vor-switch',
- ],
+ name: 'EFIS',
+ title: 'FlyByWire A32NX | EFIS Panel',
+ docsUrl: `${GLARESHIELD_DOCS_BASE_URL}/efis_control/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${GLARESHIELD_IMAGE_BASE_URL}/efis.png`,
+ identifiers: [
+ 'efis',
+ 'efis-panel',
+ 'qnh',
+ 'fd',
+ 'flight-director-switch',
+ 'ls',
+ 'ls-switch',
+ 'cstr',
+ 'constraint-switch',
+ 'wpt',
+ 'waypoint-switch',
+ 'vor-d',
+ 'vor-dme-switch',
+ 'ndb',
+ 'ndb-switch',
+ 'vor',
+ 'adf',
+ 'arpt',
+ 'airport-switch',
+ 'rose-mode',
+ 'arc-mode',
+ 'plan-mode',
+ 'nd-range',
+ 'adf-switch',
+ 'vor-switch',
+ ],
};
export const fcuPanel: Panel = {
- name: 'FCU',
- title: 'FlyByWire A32NX | Flight Control Unit (FCU)',
- docsUrl: `${GLARESHIELD_DOCS_BASE_URL}/fcu/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${GLARESHIELD_IMAGE_BASE_URL}/fcu.png`,
- identifiers: [
- 'fcu',
- 'flight-control-unit',
- 'ap',
- 'autopilot',
- 'spd-mach-button',
- 'spd-mach-knob',
- 'hdg-trk-knob',
- 'loc-switch',
- 'hdg-vs',
- 'trk-fpa',
- 'hdg-vs-trk-fpa-button',
- 'ap-1-switch',
- 'ap-2-switch',
- 'alt-knob',
- 'exped-switch',
- 'metric-alt-button',
- 'vs-knob',
- 'vertical-speed-knob',
- 'fpa-knob',
- ],
+ name: 'FCU',
+ title: 'FlyByWire A32NX | Flight Control Unit (FCU)',
+ docsUrl: `${GLARESHIELD_DOCS_BASE_URL}/fcu/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${GLARESHIELD_IMAGE_BASE_URL}/fcu.png`,
+ identifiers: [
+ 'fcu',
+ 'flight-control-unit',
+ 'ap',
+ 'autopilot',
+ 'spd-mach-button',
+ 'spd-mach-knob',
+ 'hdg-trk-knob',
+ 'loc-switch',
+ 'hdg-vs',
+ 'trk-fpa',
+ 'hdg-vs-trk-fpa-button',
+ 'ap-1-switch',
+ 'ap-2-switch',
+ 'alt-knob',
+ 'exped-switch',
+ 'metric-alt-button',
+ 'vs-knob',
+ 'vertical-speed-knob',
+ 'fpa-knob',
+ ],
};
export const lightKnobsPanel: Panel = {
- name: 'Lighting Knobs Panel',
- title: 'FlyByWire A32NX | Light Knobs Panel',
- docsUrl: `${GLARESHIELD_DOCS_BASE_URL}/light-knobs/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${GLARESHIELD_IMAGE_BASE_URL}/light_knobs.png`,
- identifiers: [
- 'table-light-knob',
- 'integral-glareshield-lighting-knob',
- 'fcu-brightness-knob',
- ],
+ name: 'Lighting Knobs Panel',
+ title: 'FlyByWire A32NX | Light Knobs Panel',
+ docsUrl: `${GLARESHIELD_DOCS_BASE_URL}/light-knobs/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${GLARESHIELD_IMAGE_BASE_URL}/light_knobs.png`,
+ identifiers: ['table-light-knob', 'integral-glareshield-lighting-knob', 'fcu-brightness-knob'],
};
diff --git a/src/commands/utils/locate/panels/a32nx/overhead.ts b/src/commands/utils/locate/panels/a32nx/overhead.ts
index 01c7423d..16da59e4 100644
--- a/src/commands/utils/locate/panels/a32nx/overhead.ts
+++ b/src/commands/utils/locate/panels/a32nx/overhead.ts
@@ -9,554 +9,457 @@ const OVHD_IMAGE_BASE_URL = LOCATE_IMAGE_BASE_URLS.a32nx.overhead;
const AFT_OVHD_IMAGE_BASE_URL = LOCATE_IMAGE_BASE_URLS.a32nx.aftOverhead;
export const wiperPanel: Panel = {
- name: 'Wiper Panel',
- title: 'FlyByWire A32NX | Wiper Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/wipers/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/wiper.png`,
- identifiers: [
- 'wiper-panel',
- 'wiper',
- 'wipers',
- 'rain',
- 'rain-repellent',
- 'repellent',
- 'rplnt',
- 'wiper-selector',
- 'rain-rplnt-button',
- ],
+ name: 'Wiper Panel',
+ title: 'FlyByWire A32NX | Wiper Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/wipers/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/wiper.png`,
+ identifiers: [
+ 'wiper-panel',
+ 'wiper',
+ 'wipers',
+ 'rain',
+ 'rain-repellent',
+ 'repellent',
+ 'rplnt',
+ 'wiper-selector',
+ 'rain-rplnt-button',
+ ],
};
export const callsPanel: Panel = {
- name: 'Calls Panel',
- title: 'FlyByWire A32NX | Calls Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/calls/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/calls.png`,
- identifiers: [
- 'calls-panel',
- 'call',
- 'calls',
- ],
+ name: 'Calls Panel',
+ title: 'FlyByWire A32NX | Calls Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/calls/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/calls.png`,
+ identifiers: ['calls-panel', 'call', 'calls'],
};
export const oxyPanel: Panel = {
- name: 'Oxygen Panel',
- title: 'FlyByWire A32NX | Oxygen Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/oxygen/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/oxygen.png`,
- identifiers: [
- 'oxy',
- 'oxygen-panel',
- 'oxygen',
- 'mask-man-on-switch',
- 'crew-supply-switch',
- ],
+ name: 'Oxygen Panel',
+ title: 'FlyByWire A32NX | Oxygen Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/oxygen/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/oxygen.png`,
+ identifiers: ['oxy', 'oxygen-panel', 'oxygen', 'mask-man-on-switch', 'crew-supply-switch'],
};
export const cvrPanel: Panel = {
- name: 'RCDR Panel',
- title: 'FlyByWire A32NX | Voice Recorder Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/voice-recorder/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/rcdr.png`,
- identifiers: [
- 'voice-recorder-panel',
- 'cvr',
- 'fdr',
- 'cockpit-voice-recorder',
- 'flight-data-recorder',
- 'gnd-ctl-switch',
- 'cvr-erase-button',
- 'cvr-test-button',
- ],
+ name: 'RCDR Panel',
+ title: 'FlyByWire A32NX | Voice Recorder Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/voice-recorder/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/rcdr.png`,
+ identifiers: [
+ 'voice-recorder-panel',
+ 'cvr',
+ 'fdr',
+ 'cockpit-voice-recorder',
+ 'flight-data-recorder',
+ 'gnd-ctl-switch',
+ 'cvr-erase-button',
+ 'cvr-test-button',
+ ],
};
export const gpwsPanel: Panel = {
- name: 'GPWS Panel',
- title: 'FlyByWire A32NX | GPWS Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/gpws/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/gpws.png`,
- identifiers: [
- 'gpws-panel',
- 'gpws',
- 'egpws',
- 'terr-switch',
- 'sys-switch',
- 'gs-mode-switch',
- 'flap-mode-switch',
- 'ldg-flap-3-switch',
- ],
+ name: 'GPWS Panel',
+ title: 'FlyByWire A32NX | GPWS Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/gpws/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/gpws.png`,
+ identifiers: [
+ 'gpws-panel',
+ 'gpws',
+ 'egpws',
+ 'terr-switch',
+ 'sys-switch',
+ 'gs-mode-switch',
+ 'flap-mode-switch',
+ 'ldg-flap-3-switch',
+ ],
};
export const emerElecPwrPanel: Panel = {
- name: 'EMER ELEC PWR Panel',
- title: 'FlyByWire A32NX | Emergency Electric Power Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/emergency-electric/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/emer_elec_pwr.png`,
- identifiers: [
- 'emergency-electrical-panel',
- 'emer-elec-panel',
- 'emer-elec',
- 'emer-elec-pwr',
- 'emer-gen-test-switch',
- 'gen-1-line-switch',
- 'man-on-switch',
- ],
+ name: 'EMER ELEC PWR Panel',
+ title: 'FlyByWire A32NX | Emergency Electric Power Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/emergency-electric/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/emer_elec_pwr.png`,
+ identifiers: [
+ 'emergency-electrical-panel',
+ 'emer-elec-panel',
+ 'emer-elec',
+ 'emer-elec-pwr',
+ 'emer-gen-test-switch',
+ 'gen-1-line-switch',
+ 'man-on-switch',
+ ],
};
export const evacPanel: Panel = {
- name: 'EVAC Panel',
- title: 'FlyByWire A32NX | Evacuation Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/evacuation/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/evac.png`,
- identifiers: [
- 'evac-panel',
- 'evac',
- 'evacuation',
- 'command-switch',
- 'horn-shut-off-button',
- 'capt-purs-switch',
- ],
+ name: 'EVAC Panel',
+ title: 'FlyByWire A32NX | Evacuation Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/evacuation/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/evac.png`,
+ identifiers: ['evac-panel', 'evac', 'evacuation', 'command-switch', 'horn-shut-off-button', 'capt-purs-switch'],
};
export const fltCtlPanel: Panel = {
- name: 'FLT CLT Panel',
- title: 'FlyByWire A32NX | Flight Control Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/flight-control-computer/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/flt_ctl.png`,
- identifiers: [
- 'flight-controls',
- 'flight-control-panel',
- 'flt-ctl',
- 'elac',
- 'sec',
- 'fac',
- ],
+ name: 'FLT CLT Panel',
+ title: 'FlyByWire A32NX | Flight Control Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/flight-control-computer/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/flt_ctl.png`,
+ identifiers: ['flight-controls', 'flight-control-panel', 'flt-ctl', 'elac', 'sec', 'fac'],
};
export const adirsPanel: Panel = {
- name: 'ADIRS Panel',
- title: 'FlyByWire A32NX | ADIRS Panel',
- description: {
- name: 'Aligning the ADIRSs',
- value: makeLines([
- 'On the overhead panel you will see the three switches under \'ADIRS\'. Turn these three to the \'NAV\' position. It takes several minutes for the ADIRUs to align.',
- 'You can check how long you have to wait by looking at the align time on your Upper Ecam.',
- ]),
- inline: false,
- },
- docsUrl: `${OVHD_DOCS_BASE_URL}/adirs/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/adirs.png`,
- identifiers: [
- 'adirs-panel',
- 'adirs',
- 'adiru',
- 'irs',
- 'adr',
- 'ir-selector',
- ],
+ name: 'ADIRS Panel',
+ title: 'FlyByWire A32NX | ADIRS Panel',
+ description: {
+ name: 'Aligning the ADIRSs',
+ value: makeLines([
+ "On the overhead panel you will see the three switches under 'ADIRS'. Turn these three to the 'NAV' position. It takes several minutes for the ADIRUs to align.",
+ 'You can check how long you have to wait by looking at the align time on your Upper Ecam.',
+ ]),
+ inline: false,
+ },
+ docsUrl: `${OVHD_DOCS_BASE_URL}/adirs/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/adirs.png`,
+ identifiers: ['adirs-panel', 'adirs', 'adiru', 'irs', 'adr', 'ir-selector'],
};
export const paVideoPanel: Panel = {
- name: 'PA and Cockpit Video Panel',
- title: 'FlyByWire A32NX | PA and Cockpit Video Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/pa-cockpit-video/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/pa_video.png`,
- identifiers: [
- 'pa-panel',
- 'video',
- 'cockpit-video-panel',
- 'cockpit-door-video',
- 'cockpit-door-video-switch',
- ],
+ name: 'PA and Cockpit Video Panel',
+ title: 'FlyByWire A32NX | PA and Cockpit Video Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/pa-cockpit-video/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/pa_video.png`,
+ identifiers: ['pa-panel', 'video', 'cockpit-video-panel', 'cockpit-door-video', 'cockpit-door-video-switch'],
};
export const extLtPanel: Panel = {
- name: 'EXT LT Panel',
- title: 'FlyByWire A32NX | Exterior Lighting Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/ext-lt/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/ext_lt.png`,
- identifiers: [
- 'ext-lt-panel',
- 'ext-lt',
- 'exterior-lights',
- 'strobe-switch',
- 'beacon-switch',
- 'wing-switch',
- 'nav-logo-switch',
- 'rwy-turn-off-switch',
- 'land-switch',
- 'taxi-switch',
- 'strobes',
- 'wing-lights',
- 'runway-turnoff-lights',
- 'landing-lights',
- 'taxi-lights',
- 'logo-lights',
- ],
+ name: 'EXT LT Panel',
+ title: 'FlyByWire A32NX | Exterior Lighting Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/ext-lt/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/ext_lt.png`,
+ identifiers: [
+ 'ext-lt-panel',
+ 'ext-lt',
+ 'exterior-lights',
+ 'strobe-switch',
+ 'beacon-switch',
+ 'wing-switch',
+ 'nav-logo-switch',
+ 'rwy-turn-off-switch',
+ 'land-switch',
+ 'taxi-switch',
+ 'strobes',
+ 'wing-lights',
+ 'runway-turnoff-lights',
+ 'landing-lights',
+ 'taxi-lights',
+ 'logo-lights',
+ ],
};
export const apuPanel: Panel = {
- name: 'APU Panel',
- title: 'FlyByWire A32NX | APU Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/apu/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/apu.png`,
- identifiers: [
- 'apu-panel',
- 'apu',
- 'auxiliary-power-unit',
- 'apu-master-switch',
- 'apu-start-button',
- ],
+ name: 'APU Panel',
+ title: 'FlyByWire A32NX | APU Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/apu/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/apu.png`,
+ identifiers: ['apu-panel', 'apu', 'auxiliary-power-unit', 'apu-master-switch', 'apu-start-button'],
};
export const signsPanel: Panel = {
- name: 'Signs Panel',
- title: 'FlyByWire A32NX | Signs Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/signs/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/signs.png`,
- identifiers: [
- 'signs-panel',
- 'signs',
- 'seat-belts',
- 'no-smoking',
- 'no-portable-devices',
- 'emergency-exit-lights',
- 'emer-exit-lights',
- ],
+ name: 'Signs Panel',
+ title: 'FlyByWire A32NX | Signs Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/signs/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/signs.png`,
+ identifiers: [
+ 'signs-panel',
+ 'signs',
+ 'seat-belts',
+ 'no-smoking',
+ 'no-portable-devices',
+ 'emergency-exit-lights',
+ 'emer-exit-lights',
+ ],
};
export const intLtPanel: Panel = {
- name: 'INT LT Panel',
- title: 'FlyByWire A32NX | Internal Lights Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/int-lt/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/int_lt.png`,
- identifiers: [
- 'int-lt',
- 'int-lt-panel',
- 'dome-light',
- 'overhead-integrated-light',
- 'ovhd-integ-lt-knob',
- 'ice-ind-stby-compass-switch',
- 'dome-switch',
- 'annunciator-lights',
- 'ann-lt-switch',
- ],
+ name: 'INT LT Panel',
+ title: 'FlyByWire A32NX | Internal Lights Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/int-lt/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/int_lt.png`,
+ identifiers: [
+ 'int-lt',
+ 'int-lt-panel',
+ 'dome-light',
+ 'overhead-integrated-light',
+ 'ovhd-integ-lt-knob',
+ 'ice-ind-stby-compass-switch',
+ 'dome-switch',
+ 'annunciator-lights',
+ 'ann-lt-switch',
+ ],
};
export const antiIcePanel: Panel = {
- name: 'Anti Ice Panel',
- title: 'FlyByWire A32NX | Anti Ice Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/anti-ice/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/anti_ice.png`,
- identifiers: [
- 'icing',
- 'anti-ice-panel',
- 'anti-ice',
- 'window-heat',
- 'probe-heat',
- 'wing-anti-ice-switch',
- 'engine-anti-ice-switch',
- 'probe-window-heat-switch',
- ],
+ name: 'Anti Ice Panel',
+ title: 'FlyByWire A32NX | Anti Ice Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/anti-ice/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/anti_ice.png`,
+ identifiers: [
+ 'icing',
+ 'anti-ice-panel',
+ 'anti-ice',
+ 'window-heat',
+ 'probe-heat',
+ 'wing-anti-ice-switch',
+ 'engine-anti-ice-switch',
+ 'probe-window-heat-switch',
+ ],
};
export const cabinPressPanel: Panel = {
- name: 'CABIN PRESS Panel',
- title: 'FlyByWire A32NX | Cabin Pressurization Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/cab-press/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/cabin_press.png`,
- identifiers: [
- 'cabin-press',
- 'cabin-press-panel',
- 'pressurization',
- 'cabin-pressure',
- 'pressure',
- 'landing-elevation',
- 'man-vs-ctl-switch',
- 'cabin-press-mode-sel-switch',
- 'ldg-elev-knob',
- 'ditching-switch',
- ],
+ name: 'CABIN PRESS Panel',
+ title: 'FlyByWire A32NX | Cabin Pressurization Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/cab-press/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/cabin_press.png`,
+ identifiers: [
+ 'cabin-press',
+ 'cabin-press-panel',
+ 'pressurization',
+ 'cabin-pressure',
+ 'pressure',
+ 'landing-elevation',
+ 'man-vs-ctl-switch',
+ 'cabin-press-mode-sel-switch',
+ 'ldg-elev-knob',
+ 'ditching-switch',
+ ],
};
export const airCondPanel: Panel = {
- name: 'AIR COND Panel',
- title: 'FlyByWire A32NX | Air Condition Control Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/ac/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/air_cond.png`,
- identifiers: [
- 'air-cond',
- 'air-cond-panel',
- 'ac-panel',
- 'air-cond-panel',
- 'packs',
- 'bleed',
- 'bleed-air',
- 'pack-flow-selector',
- 'pack-switch',
- 'pack-flow-switch',
- 'eng-bleed-switch',
- 'engine-bleed-switch',
- 'ram-air-switch',
- 'apu-bleed',
- 'x-bleed-selector',
- 'cross-bleed-selector',
- 'hot-air-switch',
- 'cabin-temp-selector',
- ],
+ name: 'AIR COND Panel',
+ title: 'FlyByWire A32NX | Air Condition Control Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/ac/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/air_cond.png`,
+ identifiers: [
+ 'air-cond',
+ 'air-cond-panel',
+ 'ac-panel',
+ 'air-cond-panel',
+ 'packs',
+ 'bleed',
+ 'bleed-air',
+ 'pack-flow-selector',
+ 'pack-switch',
+ 'pack-flow-switch',
+ 'eng-bleed-switch',
+ 'engine-bleed-switch',
+ 'ram-air-switch',
+ 'apu-bleed',
+ 'x-bleed-selector',
+ 'cross-bleed-selector',
+ 'hot-air-switch',
+ 'cabin-temp-selector',
+ ],
};
export const elecPanel: Panel = {
- name: 'ELEC Panel',
- title: 'FlyByWire A32NX | Electrical System Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/elec/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/elec.png`,
- identifiers: [
- 'elec',
- 'elec-panel',
- 'electrical-panel',
- 'generators',
- 'ac-bus',
- 'dc-bus',
- 'batteries',
- 'external-power',
- 'commercial-pwr-switch',
- 'galy-cab-pwr-switch',
- 'idg-switch',
- 'eng-gen-switch',
- 'engine-generator-switch',
- 'apu-gen-switch',
- 'bus-tie-switch',
- 'ext-pwr-switch',
- 'ac-ess-feed-switch',
- 'battery-switch',
- 'bat-switch',
- ],
+ name: 'ELEC Panel',
+ title: 'FlyByWire A32NX | Electrical System Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/elec/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/elec.png`,
+ identifiers: [
+ 'elec',
+ 'elec-panel',
+ 'electrical-panel',
+ 'generators',
+ 'ac-bus',
+ 'dc-bus',
+ 'batteries',
+ 'external-power',
+ 'commercial-pwr-switch',
+ 'galy-cab-pwr-switch',
+ 'idg-switch',
+ 'eng-gen-switch',
+ 'engine-generator-switch',
+ 'apu-gen-switch',
+ 'bus-tie-switch',
+ 'ext-pwr-switch',
+ 'ac-ess-feed-switch',
+ 'battery-switch',
+ 'bat-switch',
+ ],
};
export const fuelPanel: Panel = {
- name: 'FUEL Panel',
- title: 'FlyByWire A32NX | Fuel Control Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/fuel/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/fuel.png`,
- identifiers: [
- 'fuel',
- 'fuel-panel',
- 'fuel-pumps',
- 'x-feed',
- 'cross-feed',
- 'wing-tanks',
- 'center-tanks',
- ],
+ name: 'FUEL Panel',
+ title: 'FlyByWire A32NX | Fuel Control Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/fuel/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/fuel.png`,
+ identifiers: ['fuel', 'fuel-panel', 'fuel-pumps', 'x-feed', 'cross-feed', 'wing-tanks', 'center-tanks'],
};
export const hydPanel: Panel = {
- name: 'HYD Panel',
- title: 'FlyByWire A32NX | Hydraulics Control Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/hyd/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/hyd.png`,
- identifiers: [
- 'hyd',
- 'hydraulics-panel',
- 'green-system',
- 'blue-system',
- 'yellow-system',
- 'rat',
- 'ptu',
- 'eng-hyd-pump-switch',
- 'engine-hydraulics-pump-switch',
- 'elec-hyd-pump',
- 'rat-man-on-switch',
- ],
+ name: 'HYD Panel',
+ title: 'FlyByWire A32NX | Hydraulics Control Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/hyd/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/hyd.png`,
+ identifiers: [
+ 'hyd',
+ 'hydraulics-panel',
+ 'green-system',
+ 'blue-system',
+ 'yellow-system',
+ 'rat',
+ 'ptu',
+ 'eng-hyd-pump-switch',
+ 'engine-hydraulics-pump-switch',
+ 'elec-hyd-pump',
+ 'rat-man-on-switch',
+ ],
};
export const firePanel: Panel = {
- name: 'FIRE Panel',
- title: 'FlyByWire A32NX | Fire Control Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/fire/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/fire.png`,
- identifiers: [
- 'engine-fire-panel',
- 'fire',
- 'smoke',
- 'fire-agent',
- 'disch',
- ],
+ name: 'FIRE Panel',
+ title: 'FlyByWire A32NX | Fire Control Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/fire/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/fire.png`,
+ identifiers: ['engine-fire-panel', 'fire', 'smoke', 'fire-agent', 'disch'],
};
export const engManStartPanel: Panel = {
- name: 'ENG MAN START Panel',
- title: 'FlyByWire A32NX | Engine Manual Start Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/eng-man/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/eng_n1.png`,
- identifiers: [
- 'eng-n1',
- 'manual-engine-start',
- 'eng-man-start-switch',
- ],
+ name: 'ENG MAN START Panel',
+ title: 'FlyByWire A32NX | Engine Manual Start Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/eng-man/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/eng_n1.png`,
+ identifiers: ['eng-n1', 'manual-engine-start', 'eng-man-start-switch'],
};
export const ventilationPanel: Panel = {
- name: 'Ventilation Panel',
- title: 'FlyByWire A32NX | Ventilation Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/vent/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/ventilation.png`,
- identifiers: [
- 'vent',
- 'ventilation-panel',
- 'cabin-fans',
- 'blower-switch',
- 'extract-ventilation-switch',
- ],
+ name: 'Ventilation Panel',
+ title: 'FlyByWire A32NX | Ventilation Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/vent/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/ventilation.png`,
+ identifiers: ['vent', 'ventilation-panel', 'cabin-fans', 'blower-switch', 'extract-ventilation-switch'],
};
export const cargoSmokePanel: Panel = {
- name: 'CARGO SMOKE Panel',
- title: 'FlyByWire A32NX | Cargo Smoke Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/cargo-smoke/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/cargo_smoke.png`,
- identifiers: [
- 'cargo-fire',
- 'cargo-smoke-panel',
- ],
+ name: 'CARGO SMOKE Panel',
+ title: 'FlyByWire A32NX | Cargo Smoke Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/cargo-smoke/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/cargo_smoke.png`,
+ identifiers: ['cargo-fire', 'cargo-smoke-panel'],
};
export const cargoVentPanel: Panel = {
- name: 'CARGO VENT Panel',
- title: 'FlyByWire A32NX | Cargo Vent Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/cargo-vent/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/cargo_vent.png`,
- identifiers: [
- 'cargo-vent-panel',
- 'cargo-ventilation',
- 'aft-isol-valve-switch',
- ],
+ name: 'CARGO VENT Panel',
+ title: 'FlyByWire A32NX | Cargo Vent Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/cargo-vent/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/cargo_vent.png`,
+ identifiers: ['cargo-vent-panel', 'cargo-ventilation', 'aft-isol-valve-switch'],
};
export const thirdACP: Panel = {
- name: '3rd ACP',
- title: 'FlyByWire A32NX | 3rd Audio Control Panel',
- docsUrl: `${OVHD_DOCS_BASE_URL}/3rd-acp/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${OVHD_IMAGE_BASE_URL}/acp_3.png`,
- identifiers: [
- 'acp3',
- '3rd-acp',
- '3rd-audio-control-panel',
- ],
+ name: '3rd ACP',
+ title: 'FlyByWire A32NX | 3rd Audio Control Panel',
+ docsUrl: `${OVHD_DOCS_BASE_URL}/3rd-acp/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${OVHD_IMAGE_BASE_URL}/acp_3.png`,
+ identifiers: ['acp3', '3rd-acp', '3rd-audio-control-panel'],
};
export const readingLightsJumpSeats: Panel = {
- name: 'Jump Seats Reading Light Panel',
- title: 'FlyByWire A32NX | Reading Lights Jump Seats',
- docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/reading-light/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/jump_seat_reading_lt.png`,
- identifiers: [
- 'reading-lights-jump-seat',
- 'jump-seat-reading-lights',
- ],
+ name: 'Jump Seats Reading Light Panel',
+ title: 'FlyByWire A32NX | Reading Lights Jump Seats',
+ docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/reading-light/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/jump_seat_reading_lt.png`,
+ identifiers: ['reading-lights-jump-seat', 'jump-seat-reading-lights'],
};
export const cockpitDoorIndicatorPanel: Panel = {
- name: 'CKPT DOOR CONT Panel',
- title: 'FlyByWire A32NX | Cockpit Door Panel',
- docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/cockpit-door/#description`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/ckpt_door_cont.png`,
- identifiers: [
- 'cockpit-door-cont',
- 'cockpit-door-indicator-panel',
- ],
+ name: 'CKPT DOOR CONT Panel',
+ title: 'FlyByWire A32NX | Cockpit Door Panel',
+ docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/cockpit-door/#description`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/ckpt_door_cont.png`,
+ identifiers: ['cockpit-door-cont', 'cockpit-door-indicator-panel'],
};
export const eltPanel: Panel = {
- name: 'ELT Panel',
- title: 'FlyByWire A32NX | ELT Panel',
- docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/elt/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/elt.png`,
- identifiers: [
- 'elt',
- 'elt-panel',
- 'emergency-locator-transmitter',
- ],
+ name: 'ELT Panel',
+ title: 'FlyByWire A32NX | ELT Panel',
+ docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/elt/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/elt.png`,
+ identifiers: ['elt', 'elt-panel', 'emergency-locator-transmitter'],
};
export const pedestalLightPanel: Panel = {
- name: 'Pedestal Light Panel',
- title: 'FlyByWire A32NX | Pedestal Light and Audio 3 Switch',
- docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/pedestal-light/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/pedestal_light.png`,
- identifiers: [
- 'pedestal-light-panel',
- 'acp3-switching-selector',
- 'audio-control-panel-3-switching-selector',
- ],
+ name: 'Pedestal Light Panel',
+ title: 'FlyByWire A32NX | Pedestal Light and Audio 3 Switch',
+ docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/pedestal-light/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/pedestal_light.png`,
+ identifiers: ['pedestal-light-panel', 'acp3-switching-selector', 'audio-control-panel-3-switching-selector'],
};
export const emerCbPanel: Panel = {
- name: 'EMER CB Panel',
- title: 'FlyByWire A32NX | Emergency Circuit Breaker Panel',
- docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/circuit/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/emer_cb.png`,
- identifiers: [
- 'emer-cb',
- 'emergency-circuit-breaker-panel',
- ],
+ name: 'EMER CB Panel',
+ title: 'FlyByWire A32NX | Emergency Circuit Breaker Panel',
+ docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/circuit/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/emer_cb.png`,
+ identifiers: ['emer-cb', 'emergency-circuit-breaker-panel'],
};
export const fmsLoadPanel: Panel = {
- name: 'FMS LOAD Panel',
- title: 'FlyByWire A32NX | FMS Load Panel',
- docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/fms-load/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/fms_load.png`,
- identifiers: [
- 'fms-load-panel',
- ],
+ name: 'FMS LOAD Panel',
+ title: 'FlyByWire A32NX | FMS Load Panel',
+ docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/fms-load/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/fms_load.png`,
+ identifiers: ['fms-load-panel'],
};
export const maintenancePanel: Panel = {
- name: 'Maintenance Panel',
- title: 'FlyByWire A32NX | Maintenance Panel',
- docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/maintenance/`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/maintenance.png`,
- identifiers: [
- 'maintenance',
- 'maintenance-panel',
- 'fadec-ground-power-switch',
- 'blue-pump-override-switch',
- 'hyd-leak-measurement-valves-switch',
- 'oxygen-tmr-reset-switch',
- 'svge-int-ovrd-switch',
- 'avionics-comp-lt-switch',
- ],
+ name: 'Maintenance Panel',
+ title: 'FlyByWire A32NX | Maintenance Panel',
+ docsUrl: `${AFT_OVHD_DOCS_BASE_URL}/maintenance/`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${AFT_OVHD_IMAGE_BASE_URL}/maintenance.png`,
+ identifiers: [
+ 'maintenance',
+ 'maintenance-panel',
+ 'fadec-ground-power-switch',
+ 'blue-pump-override-switch',
+ 'hyd-leak-measurement-valves-switch',
+ 'oxygen-tmr-reset-switch',
+ 'svge-int-ovrd-switch',
+ 'avionics-comp-lt-switch',
+ ],
};
diff --git a/src/commands/utils/locate/panels/a32nx/pedestal.ts b/src/commands/utils/locate/panels/a32nx/pedestal.ts
index d3beb6e3..de74478f 100644
--- a/src/commands/utils/locate/panels/a32nx/pedestal.ts
+++ b/src/commands/utils/locate/panels/a32nx/pedestal.ts
@@ -5,258 +5,199 @@ const PEDESTAL_DOCS_BASE_URL = LOCATE_DOCS_BASE_URLS.a32nx.pedestal;
const PEDESTAL_IMAGE_BASE_URL = LOCATE_IMAGE_BASE_URLS.a32nx.pedestal;
export const console: Panel = {
- name: 'Console',
- title: 'FlyByWire A32NX | Console',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/console`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/console.png`,
- identifiers: [
- 'console',
- 'sidestick',
- 'side-stick',
- 'ap-disc-button',
- 'autopilot-disconnect-button',
- 'tiller',
- 'pedal-disconnect-button',
- ],
+ name: 'Console',
+ title: 'FlyByWire A32NX | Console',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/console`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/console.png`,
+ identifiers: [
+ 'console',
+ 'sidestick',
+ 'side-stick',
+ 'ap-disc-button',
+ 'autopilot-disconnect-button',
+ 'tiller',
+ 'pedal-disconnect-button',
+ ],
};
export const mcdu: Panel = {
- name: 'MCDU',
- title: 'FlyByWire A32NX | Multipurpose Control & Display Unit (MCDU)',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/mcdu`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/mcdu.png`,
- identifiers: [
- 'fms',
- 'cdu',
- 'mcdu',
- 'fmgc',
- ],
+ name: 'MCDU',
+ title: 'FlyByWire A32NX | Multipurpose Control & Display Unit (MCDU)',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/mcdu`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/mcdu.png`,
+ identifiers: ['fms', 'cdu', 'mcdu', 'fmgc'],
};
export const rmpAcpPanel: Panel = {
- name: 'RMP/ACP Panel',
- title: 'FlyByWire A32NX | Radio Management and Audio Control Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/rmp`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/rmp_acp.png`,
- identifiers: [
- 'rmp',
- 'radio-management-panel',
- 'acp',
- 'audio-control-panel',
- 'atc-panel',
- ],
+ name: 'RMP/ACP Panel',
+ title: 'FlyByWire A32NX | Radio Management and Audio Control Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/rmp`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/rmp_acp.png`,
+ identifiers: ['rmp', 'radio-management-panel', 'acp', 'audio-control-panel', 'atc-panel'],
};
export const captPedestalLightingPanel: Panel = {
- name: 'Pedestal Lighting Panel',
- title: 'FlyByWire A32NX | Pedestal Lighting Panel (Captain Side)',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/lighting-capt`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/capt_pedestal_lt.png`,
- identifiers: [
- 'captain-pedestal-lighting-panel',
- ],
+ name: 'Pedestal Lighting Panel',
+ title: 'FlyByWire A32NX | Pedestal Lighting Panel (Captain Side)',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/lighting-capt`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/capt_pedestal_lt.png`,
+ identifiers: ['captain-pedestal-lighting-panel'],
};
export const wxPanel: Panel = {
- name: 'WX Radar',
- title: 'Weather Radar Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/radar`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/wx_radar.png`,
- identifiers: [
- 'wx',
- 'weather-radar',
- 'wx-radar',
- 'pws',
- 'predictive-windshear-systems',
- ],
+ name: 'WX Radar',
+ title: 'Weather Radar Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/radar`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/wx_radar.png`,
+ identifiers: ['wx', 'weather-radar', 'wx-radar', 'pws', 'predictive-windshear-systems'],
};
export const speedBrake: Panel = {
- name: 'Speed Brake',
- title: 'FlyByWire A32NX | Speed Brake',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/speedbrake`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/spd_brk.png`,
- identifiers: [
- 'speed-brake',
- 'spd-brk',
- 'spoilers',
- 'gnd-sprls',
- ],
+ name: 'Speed Brake',
+ title: 'FlyByWire A32NX | Speed Brake',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/speedbrake`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/spd_brk.png`,
+ identifiers: ['speed-brake', 'spd-brk', 'spoilers', 'gnd-sprls'],
};
export const cockpitDoorPanel: Panel = {
- name: 'Cockpit Door Panel',
- title: 'FlyByWire A32NX | Cockpit Door Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/cockpit-door`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/cockpit_door.png`,
- identifiers: [
- 'cockpit-door',
- 'cockpit-door-panel',
- 'cockpit-door-switch',
- 'cockpit-door-video-button',
- ],
+ name: 'Cockpit Door Panel',
+ title: 'FlyByWire A32NX | Cockpit Door Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/cockpit-door`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/cockpit_door.png`,
+ identifiers: ['cockpit-door', 'cockpit-door-panel', 'cockpit-door-switch', 'cockpit-door-video-button'],
};
export const switchingPanel: Panel = {
- name: 'Switching Panel',
- title: 'FlyByWire A32NX | Switching Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/switching`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/switching.png`,
- identifiers: [
- 'switching',
- 'switching-panel',
- 'att-hdg-selector',
- 'air-data-selector',
- 'eis-dmc-selector',
- 'ecam-nd-xfr-selector',
- ],
+ name: 'Switching Panel',
+ title: 'FlyByWire A32NX | Switching Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/switching`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/switching.png`,
+ identifiers: [
+ 'switching',
+ 'switching-panel',
+ 'att-hdg-selector',
+ 'air-data-selector',
+ 'eis-dmc-selector',
+ 'ecam-nd-xfr-selector',
+ ],
};
export const ecamControlPanel: Panel = {
- name: 'ECAM Control Panel',
- title: 'FlyByWire A32NX | ECAM Control Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/ecam-control`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/ecam_ctl.png`,
- identifiers: [
- 'ecam-control',
- 'upper-ecam-display-brightness',
- 'lower-ecam-display-brightness',
- 'ecam-to-config',
- 'to-config',
- 'emer-canc',
- 'ecam-clr',
- 'ecam-rcl',
- ],
+ name: 'ECAM Control Panel',
+ title: 'FlyByWire A32NX | ECAM Control Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/ecam-control`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/ecam_ctl.png`,
+ identifiers: [
+ 'ecam-control',
+ 'upper-ecam-display-brightness',
+ 'lower-ecam-display-brightness',
+ 'ecam-to-config',
+ 'to-config',
+ 'emer-canc',
+ 'ecam-clr',
+ 'ecam-rcl',
+ ],
};
export const thrLvrPitchTrim: Panel = {
- name: 'THR LVR/Pitch Trim Column',
- title: 'FlyByWire A32NX | Thrust Lever and Pitch Trim Column',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/thrust-pitch-trim`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/thr_lvrs_pitch_trim.png`,
- identifiers: [
- 'thr-lvr',
- 'thrust-levers',
- 'athr-disc-button',
- 'autothrust-disconnect-button',
- 'pitch-trim-wheels',
- 'idle-detent',
- 'cb-detent',
- 'clb-detent',
- 'flx-mct-detent',
- 'toga-detent',
- 'reversers',
- ],
+ name: 'THR LVR/Pitch Trim Column',
+ title: 'FlyByWire A32NX | Thrust Lever and Pitch Trim Column',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/thrust-pitch-trim`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/thr_lvrs_pitch_trim.png`,
+ identifiers: [
+ 'thr-lvr',
+ 'thrust-levers',
+ 'athr-disc-button',
+ 'autothrust-disconnect-button',
+ 'pitch-trim-wheels',
+ 'idle-detent',
+ 'cb-detent',
+ 'clb-detent',
+ 'flx-mct-detent',
+ 'toga-detent',
+ 'reversers',
+ ],
};
export const engPanel: Panel = {
- name: 'ENG Panel',
- title: 'FlyByWire A32NX | Engine Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/engine`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/eng.png`,
- identifiers: [
- 'engine-panel',
- 'engine-master',
- 'engine-master-switches',
- 'eng-mode-selector',
- 'engine-mode-selector',
- ],
+ name: 'ENG Panel',
+ title: 'FlyByWire A32NX | Engine Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/engine`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/eng.png`,
+ identifiers: ['engine-panel', 'engine-master', 'engine-master-switches', 'eng-mode-selector', 'engine-mode-selector'],
};
export const rudderTrim: Panel = {
- name: 'Rudder Trim Panel',
- title: 'FlyByWire A32NX | Rudder Trim Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/rudder-trim`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/rudder_trim.png`,
- identifiers: [
- 'rudder-trim',
- ],
+ name: 'Rudder Trim Panel',
+ title: 'FlyByWire A32NX | Rudder Trim Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/rudder-trim`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/rudder_trim.png`,
+ identifiers: ['rudder-trim'],
};
export const parkBrkPanel: Panel = {
- name: 'Parking Brake Panel',
- title: 'FlyByWire A32NX | Parking Brake Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/parking-brake`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/park_brk.png`,
- identifiers: [
- 'parking-brake',
- 'park-brk',
- ],
+ name: 'Parking Brake Panel',
+ title: 'FlyByWire A32NX | Parking Brake Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/parking-brake`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/park_brk.png`,
+ identifiers: ['parking-brake', 'park-brk'],
};
export const gravityGearExtensionPanel: Panel = {
- name: 'Gravity Gear Extension Panel',
- title: 'FlyByWire A32NX | Emergency Gravity Gear Extension Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/gravity-gear-ext`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/gravity_gear_extn.png`,
- identifiers: [
- 'gravity-gear-extension',
- ],
+ name: 'Gravity Gear Extension Panel',
+ title: 'FlyByWire A32NX | Emergency Gravity Gear Extension Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/gravity-gear-ext`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/gravity_gear_extn.png`,
+ identifiers: ['gravity-gear-extension'],
};
export const aidsDfdrPanel: Panel = {
- name: 'AIDS/DFDR Panel',
- title: 'FlyByWire A32NX | AIDS, DFDR Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/lighting-aids-dfdr`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/aids_dfdr.png`,
- identifiers: [
- 'aids',
- 'dfdr',
- 'ped-flood-lt-knob',
- 'pedestal-flood-light-knob',
- 'aids-button',
- 'dfdr-button',
- ],
+ name: 'AIDS/DFDR Panel',
+ title: 'FlyByWire A32NX | AIDS, DFDR Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/lighting-aids-dfdr`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/aids_dfdr.png`,
+ identifiers: ['aids', 'dfdr', 'ped-flood-lt-knob', 'pedestal-flood-light-knob', 'aids-button', 'dfdr-button'],
};
export const atcTcasPanel: Panel = {
- name: 'ATC/TCAS Panel',
- title: 'FlyByWire A32NX | ATC TCAS Panel',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/atc-tcas`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/atc_tcas.png`,
- identifiers: [
- 'xpdr',
- 'atc-tcas-panel',
- 'transponder',
- 'tcas',
- 'alt-rptg-switch',
- ],
+ name: 'ATC/TCAS Panel',
+ title: 'FlyByWire A32NX | ATC TCAS Panel',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/atc-tcas`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/atc_tcas.png`,
+ identifiers: ['xpdr', 'atc-tcas-panel', 'transponder', 'tcas', 'alt-rptg-switch'],
};
export const flaps: Panel = {
- name: 'Flaps',
- title: 'FlyByWire A32NX | Flaps',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/flaps`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/flaps.png`,
- identifiers: [
- 'flaps',
- ],
+ name: 'Flaps',
+ title: 'FlyByWire A32NX | Flaps',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/flaps`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/flaps.png`,
+ identifiers: ['flaps'],
};
export const printer: Panel = {
- name: 'Printer',
- title: 'FlyByWire A32NX | Printer',
- docsUrl: `${PEDESTAL_DOCS_BASE_URL}/printer`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/printer.png`,
- identifiers: [
- 'printer',
- ],
+ name: 'Printer',
+ title: 'FlyByWire A32NX | Printer',
+ docsUrl: `${PEDESTAL_DOCS_BASE_URL}/printer`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${PEDESTAL_IMAGE_BASE_URL}/printer.png`,
+ identifiers: ['printer'],
};
diff --git a/src/commands/utils/locate/panels/a32nx/rear-cb-panel.ts b/src/commands/utils/locate/panels/a32nx/rear-cb-panel.ts
index 87f6037f..34e55773 100644
--- a/src/commands/utils/locate/panels/a32nx/rear-cb-panel.ts
+++ b/src/commands/utils/locate/panels/a32nx/rear-cb-panel.ts
@@ -2,13 +2,10 @@ import { LOCATE_DOCS_BASE_URLS, LOCATE_IMAGE_BASE_URLS } from '../../base-urls';
import { Panel } from '../panel';
export const rearBackCbPanel: Panel = {
- name: 'Rear CB Panel',
- title: 'FlyByWire A32NX | Rear Back Circuit Breaker Panel',
- docsUrl: `${LOCATE_DOCS_BASE_URLS.a32nx.aftOverhead}/circuit/#rear-right-back-panel`,
- flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
- imageUrl: `${LOCATE_IMAGE_BASE_URLS.a32nx.rearCb}/rear_right_back.jpg`,
- identifiers: [
- 'rear-back-circuit-breaker-panel',
- 'secondary-circuit-breaker-panel',
- ],
+ name: 'Rear CB Panel',
+ title: 'FlyByWire A32NX | Rear Back Circuit Breaker Panel',
+ docsUrl: `${LOCATE_DOCS_BASE_URLS.a32nx.aftOverhead}/circuit/#rear-right-back-panel`,
+ flightDeckUrl: LOCATE_DOCS_BASE_URLS.a32nx.flightdeck,
+ imageUrl: `${LOCATE_IMAGE_BASE_URLS.a32nx.rearCb}/rear_right_back.jpg`,
+ identifiers: ['rear-back-circuit-breaker-panel', 'secondary-circuit-breaker-panel'],
};
diff --git a/src/commands/utils/locate/panels/panel.ts b/src/commands/utils/locate/panels/panel.ts
index c618f5ca..296ddf9e 100644
--- a/src/commands/utils/locate/panels/panel.ts
+++ b/src/commands/utils/locate/panels/panel.ts
@@ -1,38 +1,38 @@
import { EmbedField } from 'discord.js';
export interface Panel {
- /**
- * The name of the Panel. This should be usable in sentences.
- */
- name: string;
+ /**
+ * The name of the Panel. This should be usable in sentences.
+ */
+ name: string;
- /**
- * The title of the Panel. -> Used as the embed title.
- */
- title: string;
+ /**
+ * The title of the Panel. -> Used as the embed title.
+ */
+ title: string;
- /**
- * Optional description for a panel such as instructions on aligning the ADIRSs.
- */
- description?: EmbedField;
+ /**
+ * Optional description for a panel such as instructions on aligning the ADIRSs.
+ */
+ description?: EmbedField;
- /**
- * The URL to the relevant documentation.
- */
- docsUrl: string;
+ /**
+ * The URL to the relevant documentation.
+ */
+ docsUrl: string;
- /**
- * The URL to documentation of the flight deck this panel belongs to.
- */
- flightDeckUrl: string;
+ /**
+ * The URL to documentation of the flight deck this panel belongs to.
+ */
+ flightDeckUrl: string;
- /**
- * The URL to the image that shows the location of this panel.
- */
- imageUrl: string;
+ /**
+ * The URL to the image that shows the location of this panel.
+ */
+ imageUrl: string;
- /**
- * The search queries that lead to this panel.
- */
- identifiers: string[];
+ /**
+ * The search queries that lead to this panel.
+ */
+ identifiers: string[];
}
diff --git a/src/commands/utils/memberCount.ts b/src/commands/utils/memberCount.ts
index 46423ea7..5bf4fa7b 100644
--- a/src/commands/utils/memberCount.ts
+++ b/src/commands/utils/memberCount.ts
@@ -2,16 +2,16 @@ import { ApplicationCommandType } from 'discord.js';
import { slashCommand, slashCommandStructure, makeEmbed } from '../../lib';
const data = slashCommandStructure({
- name: 'member-count',
- description: 'Lists the current member count for the server.',
- type: ApplicationCommandType.ChatInput,
+ name: 'member-count',
+ description: 'Lists the current member count for the server.',
+ type: ApplicationCommandType.ChatInput,
});
export default slashCommand(data, async ({ interaction }) => {
- const memberCountEmbed = makeEmbed({
- title: 'Member Count',
- description: `There are currently **${interaction.guild?.memberCount}** members in the server.`,
- });
+ const memberCountEmbed = makeEmbed({
+ title: 'Member Count',
+ description: `There are currently **${interaction.guild?.memberCount}** members in the server.`,
+ });
- return interaction.reply({ embeds: [memberCountEmbed] });
+ return interaction.reply({ embeds: [memberCountEmbed] });
});
diff --git a/src/commands/utils/metar.ts b/src/commands/utils/metar.ts
index dd688e48..c9f5e03f 100644
--- a/src/commands/utils/metar.ts
+++ b/src/commands/utils/metar.ts
@@ -3,84 +3,88 @@ import fetch from 'node-fetch';
import { constantsConfig, slashCommand, slashCommandStructure, makeEmbed, makeLines, Logger } from '../../lib';
const data = slashCommandStructure({
- name: 'metar',
- description: 'Provides the METAR report of the requested airport',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'icao',
- description: 'Provide an airport ICAO code.',
- type: ApplicationCommandOptionType.String,
- max_length: 4,
- min_length: 4,
- required: true,
- }],
+ name: 'metar',
+ description: 'Provides the METAR report of the requested airport',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'icao',
+ description: 'Provide an airport ICAO code.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 4,
+ min_length: 4,
+ required: true,
+ },
+ ],
});
export default slashCommand(data, async ({ interaction }) => {
- await interaction.deferReply();
+ await interaction.deferReply();
- const icao = interaction.options.getString('icao')!;
+ const icao = interaction.options.getString('icao')!;
- const metarToken = process.env.METAR_TOKEN;
+ const metarToken = process.env.METAR_TOKEN;
- if (!metarToken) {
- const noTokenEmbed = makeEmbed({
- title: 'Error | METAR',
- description: 'Metar token not found.',
- color: Colors.Red,
- });
- return interaction.editReply({ embeds: [noTokenEmbed] });
- }
-
- try {
- const metarReport: any = await fetch(`https://avwx.rest/api/metar/${icao}`, {
- method: 'GET',
- headers: { Authorization: metarToken },
- })
- .then((res) => res.json());
+ if (!metarToken) {
+ const noTokenEmbed = makeEmbed({
+ title: 'Error | METAR',
+ description: 'Metar token not found.',
+ color: Colors.Red,
+ });
+ return interaction.editReply({ embeds: [noTokenEmbed] });
+ }
- if (metarReport.error) {
- const invalidEmbed = makeEmbed({
- title: `Metar Error | ${icao.toUpperCase()}`,
- description: metarReport.error,
- color: Colors.Red,
- });
- return interaction.editReply({ embeds: [invalidEmbed] });
- }
- const metarEmbed = makeEmbed({
- title: `METAR Report | ${metarReport.station}`,
- description: makeLines([
- '**Raw Report**',
- metarReport.raw,
- '',
- '**Basic Report:**',
- `**Time Observed:** ${metarReport.time.dt}`,
- `**Station:** ${metarReport.station}`,
- `**Wind:** ${metarReport.wind_direction.repr}${metarReport.wind_direction.repr === 'VRB' ? '' : constantsConfig.units.DEGREES} at ${metarReport.wind_speed.repr} ${metarReport.units.wind_speed}`,
- `**Visibility:** ${metarReport.visibility.repr} ${Number.isNaN(+metarReport.visibility.repr) ? '' : metarReport.units.visibility}`,
- `**Temperature:** ${metarReport.temperature.repr} ${constantsConfig.units.CELSIUS}`,
- `**Dew Point:** ${metarReport.dewpoint.repr} ${constantsConfig.units.CELSIUS}`,
- `**Altimeter:** ${metarReport.altimeter.value.toString()} ${metarReport.units.altimeter}`,
- `**Flight Rules:** ${metarReport.flight_rules}`,
- ]),
- fields: [
- {
- name: 'Unsure of how to read the raw report?',
- value: 'Please refer to our guide [here.](https://docs.flybywiresim.com/pilots-corner/airliner-flying-guide/weather/)',
- inline: false,
- },
- ],
- footer: { text: 'This METAR report may not accurately reflect the weather in the simulator. However, it will always be similar to the current conditions present in the sim.' },
- });
+ try {
+ const metarReport: any = await fetch(`https://avwx.rest/api/metar/${icao}`, {
+ method: 'GET',
+ headers: { Authorization: metarToken },
+ }).then((res) => res.json());
- return interaction.editReply({ embeds: [metarEmbed] });
- } catch (e) {
- Logger.error('metar:', e);
- const fetchErrorEmbed = makeEmbed({
- title: 'Metar Error | Fetch Error',
- description: 'There was an error fetching the METAR report. Please try again later.',
- color: Colors.Red,
- });
- return interaction.editReply({ embeds: [fetchErrorEmbed] });
+ if (metarReport.error) {
+ const invalidEmbed = makeEmbed({
+ title: `Metar Error | ${icao.toUpperCase()}`,
+ description: metarReport.error,
+ color: Colors.Red,
+ });
+ return interaction.editReply({ embeds: [invalidEmbed] });
}
+ const metarEmbed = makeEmbed({
+ title: `METAR Report | ${metarReport.station}`,
+ description: makeLines([
+ '**Raw Report**',
+ metarReport.raw,
+ '',
+ '**Basic Report:**',
+ `**Time Observed:** ${metarReport.time.dt}`,
+ `**Station:** ${metarReport.station}`,
+ `**Wind:** ${metarReport.wind_direction.repr}${metarReport.wind_direction.repr === 'VRB' ? '' : constantsConfig.units.DEGREES} at ${metarReport.wind_speed.repr} ${metarReport.units.wind_speed}`,
+ `**Visibility:** ${metarReport.visibility.repr} ${Number.isNaN(+metarReport.visibility.repr) ? '' : metarReport.units.visibility}`,
+ `**Temperature:** ${metarReport.temperature.repr} ${constantsConfig.units.CELSIUS}`,
+ `**Dew Point:** ${metarReport.dewpoint.repr} ${constantsConfig.units.CELSIUS}`,
+ `**Altimeter:** ${metarReport.altimeter.value.toString()} ${metarReport.units.altimeter}`,
+ `**Flight Rules:** ${metarReport.flight_rules}`,
+ ]),
+ fields: [
+ {
+ name: 'Unsure of how to read the raw report?',
+ value:
+ 'Please refer to our guide [here.](https://docs.flybywiresim.com/pilots-corner/airliner-flying-guide/weather/)',
+ inline: false,
+ },
+ ],
+ footer: {
+ text: 'This METAR report may not accurately reflect the weather in the simulator. However, it will always be similar to the current conditions present in the sim.',
+ },
+ });
+
+ return interaction.editReply({ embeds: [metarEmbed] });
+ } catch (e) {
+ Logger.error('metar:', e);
+ const fetchErrorEmbed = makeEmbed({
+ title: 'Metar Error | Fetch Error',
+ description: 'There was an error fetching the METAR report. Please try again later.',
+ color: Colors.Red,
+ });
+ return interaction.editReply({ embeds: [fetchErrorEmbed] });
+ }
});
diff --git a/src/commands/utils/ping.ts b/src/commands/utils/ping.ts
index 5d29b95b..e5af6fda 100644
--- a/src/commands/utils/ping.ts
+++ b/src/commands/utils/ping.ts
@@ -2,22 +2,24 @@ import { ApplicationCommandOptionType, ApplicationCommandType } from 'discord.js
import { slashCommand, slashCommandStructure, makeEmbed } from '../../lib';
const data = slashCommandStructure({
- name: 'ping',
- description: 'Ping the bot for a response.',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'message',
- description: 'Provide some text to send back.',
- type: ApplicationCommandOptionType.String,
- max_length: 100,
- required: false,
- }],
+ name: 'ping',
+ description: 'Ping the bot for a response.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'message',
+ description: 'Provide some text to send back.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 100,
+ required: false,
+ },
+ ],
});
export default slashCommand(data, async ({ interaction }) => {
- const msg = interaction.options.getString('message') ?? 'Pong 🏓';
+ const msg = interaction.options.getString('message') ?? 'Pong 🏓';
- const pongEmbed = makeEmbed({ description: msg });
+ const pongEmbed = makeEmbed({ description: msg });
- return interaction.reply({ embeds: [pongEmbed] });
+ return interaction.reply({ embeds: [pongEmbed] });
});
diff --git a/src/commands/utils/prefixHelp.ts b/src/commands/utils/prefixHelp.ts
index 76968c5a..3c4d169c 100644
--- a/src/commands/utils/prefixHelp.ts
+++ b/src/commands/utils/prefixHelp.ts
@@ -1,78 +1,96 @@
import { ApplicationCommandOptionChoiceData, ApplicationCommandOptionType, ApplicationCommandType } from 'discord.js';
-import { makeEmbed, createPaginatedEmbedHandler, slashCommand, slashCommandStructure, getInMemoryCache, MemoryCachePrefix, AutocompleteCallback, makeLines, Logger, PrefixCommand, PrefixCommandVersion, PrefixCommandCategory, IPrefixCommand } from '../../lib';
+import {
+ makeEmbed,
+ createPaginatedEmbedHandler,
+ slashCommand,
+ slashCommandStructure,
+ getInMemoryCache,
+ MemoryCachePrefix,
+ AutocompleteCallback,
+ makeLines,
+ Logger,
+ PrefixCommand,
+ PrefixCommandVersion,
+ PrefixCommandCategory,
+ IPrefixCommand,
+} from '../../lib';
const data = slashCommandStructure({
- name: 'prefix-help',
- description: 'Display a list of all the prefix commands matching an optional search.',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'category',
- description: 'The category to show the prefix commands for.',
- type: ApplicationCommandOptionType.String,
- max_length: 32,
- autocomplete: true,
- required: true,
+ name: 'prefix-help',
+ description: 'Display a list of all the prefix commands matching an optional search.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'category',
+ description: 'The category to show the prefix commands for.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 32,
+ autocomplete: true,
+ required: true,
},
{
- name: 'search',
- description: 'The search term to filter the prefix commands by.',
- type: ApplicationCommandOptionType.String,
- max_length: 32,
- autocomplete: true,
- required: false,
- }],
+ name: 'search',
+ description: 'The search term to filter the prefix commands by.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 32,
+ autocomplete: true,
+ required: false,
+ },
+ ],
});
const autocompleteCallback: AutocompleteCallback = async ({ interaction }) => {
- const autoCompleteOption = interaction.options.getFocused(true);
- const { name: optionName, value: searchText } = autoCompleteOption;
- const choices: ApplicationCommandOptionChoiceData[] = [];
+ const autoCompleteOption = interaction.options.getFocused(true);
+ const { name: optionName, value: searchText } = autoCompleteOption;
+ const choices: ApplicationCommandOptionChoiceData[] = [];
- const inMemoryCache = getInMemoryCache();
+ const inMemoryCache = getInMemoryCache();
- switch (optionName) {
+ switch (optionName) {
case 'category':
- if (inMemoryCache) {
- const foundCategories = await inMemoryCache.store.keys();
- for (const key of foundCategories) {
- if (key.startsWith(MemoryCachePrefix.CATEGORY) && key.includes(searchText.toLowerCase())) {
- // eslint-disable-next-line no-await-in-loop
- const categoryCached = await inMemoryCache.get(key);
- if (categoryCached) {
- const category = PrefixCommandCategory.hydrate(categoryCached);
- const { name } = category;
- choices.push({ name, value: name });
- if (choices.length >= 25) {
- break;
- }
- }
- }
+ if (inMemoryCache) {
+ const foundCategories = await inMemoryCache.store.keys();
+ for (const key of foundCategories) {
+ if (key.startsWith(MemoryCachePrefix.CATEGORY) && key.includes(searchText.toLowerCase())) {
+ // eslint-disable-next-line no-await-in-loop
+ const categoryCached = await inMemoryCache.get(key);
+ if (categoryCached) {
+ const category = PrefixCommandCategory.hydrate(categoryCached);
+ const { name } = category;
+ choices.push({ name, value: name });
+ if (choices.length >= 25) {
+ break;
+ }
}
+ }
}
- break;
+ }
+ break;
case 'search':
- if (inMemoryCache) {
- const foundCommands = await inMemoryCache.store.keys();
- for (const key of foundCommands) {
- if (key.startsWith(MemoryCachePrefix.COMMAND) && key.includes(searchText.toLowerCase())) {
- // Explicitly does not use the cache to hydrate the command to also capture aliases, resulting in commands
- const commandName = key.split(':')[1];
- choices.push({ name: commandName, value: commandName });
- if (choices.length >= 25) {
- break;
- }
- }
+ if (inMemoryCache) {
+ const foundCommands = await inMemoryCache.store.keys();
+ for (const key of foundCommands) {
+ if (key.startsWith(MemoryCachePrefix.COMMAND) && key.includes(searchText.toLowerCase())) {
+ // Explicitly does not use the cache to hydrate the command to also capture aliases, resulting in commands
+ const commandName = key.split(':')[1];
+ choices.push({ name: commandName, value: commandName });
+ if (choices.length >= 25) {
+ break;
}
+ }
}
- break;
+ }
+ break;
default:
- break;
- }
+ break;
+ }
- return interaction.respond(choices);
+ return interaction.respond(choices);
};
-export default slashCommand(data, async ({ interaction }) => {
+export default slashCommand(
+ data,
+ async ({ interaction }) => {
await interaction.deferReply({ ephemeral: true });
const categoryName = interaction.options.getString('category')!;
@@ -80,36 +98,36 @@ export default slashCommand(data, async ({ interaction }) => {
const inMemoryCache = getInMemoryCache();
if (!inMemoryCache) {
- return interaction.reply({
- content: 'An error occurred while fetching commands.',
- ephemeral: true,
- });
+ return interaction.reply({
+ content: 'An error occurred while fetching commands.',
+ ephemeral: true,
+ });
}
const categoryCached = await inMemoryCache.get(`${MemoryCachePrefix.CATEGORY}:${categoryName.toLowerCase()}`);
if (!categoryCached) {
- return interaction.reply({
- content: 'Invalid category, please select an existing category.',
- ephemeral: true,
- });
+ return interaction.reply({
+ content: 'Invalid category, please select an existing category.',
+ ephemeral: true,
+ });
}
const category = PrefixCommandCategory.hydrate(categoryCached);
const commands: { [key: string]: IPrefixCommand } = {};
const keys = await inMemoryCache.store.keys();
for (const key of keys) {
- if (key.startsWith(MemoryCachePrefix.COMMAND) && key.includes(search.toLowerCase())) {
- // eslint-disable-next-line no-await-in-loop
- const commandCached = await inMemoryCache.get(key);
- if (commandCached) {
- const command = PrefixCommand.hydrate(commandCached);
- const { name, categoryId: commandCategoryId } = command;
- const { _id: categoryId } = category;
- if (commandCategoryId.toString() === categoryId.toString() && !(name in commands)) {
- commands[name] = command;
- }
- }
+ if (key.startsWith(MemoryCachePrefix.COMMAND) && key.includes(search.toLowerCase())) {
+ // eslint-disable-next-line no-await-in-loop
+ const commandCached = await inMemoryCache.get(key);
+ if (commandCached) {
+ const command = PrefixCommand.hydrate(commandCached);
+ const { name, categoryId: commandCategoryId } = command;
+ const { _id: categoryId } = category;
+ if (commandCategoryId.toString() === categoryId.toString() && !(name in commands)) {
+ commands[name] = command;
+ }
}
+ }
}
const sortedCommands = Object.values(commands).sort((a, b) => a.name.localeCompare(b.name));
@@ -117,44 +135,46 @@ export default slashCommand(data, async ({ interaction }) => {
const pageLimit = 10;
const embeds = [];
for (let page = 0; page * pageLimit < sortedCommands.length; page++) {
- const startIndex = page * pageLimit;
- const endIndex = startIndex + pageLimit;
- const currentCommands = sortedCommands.slice(startIndex, endIndex);
- const totalPages = Math.ceil(sortedCommands.length / pageLimit);
-
- const descriptionLines: string[] = [];
- for (const command of currentCommands) {
- const { name, aliases, description, contents } = command;
- const versionEmojis = [];
- for (const content of contents) {
- const { versionId } = content;
- if (versionId !== 'GENERIC') {
- Logger.debug(`Fetching version ${versionId} for command ${name}`);
- // eslint-disable-next-line no-await-in-loop
- const versionCached = await inMemoryCache.get(`${MemoryCachePrefix.VERSION}:${versionId}`);
- if (versionCached) {
- const version = PrefixCommandVersion.hydrate(versionCached);
- const { emoji } = version;
- Logger.debug(`Found version ${versionId} for command ${name} with emoji ${emoji}`);
- versionEmojis.push(emoji);
- }
- }
+ const startIndex = page * pageLimit;
+ const endIndex = startIndex + pageLimit;
+ const currentCommands = sortedCommands.slice(startIndex, endIndex);
+ const totalPages = Math.ceil(sortedCommands.length / pageLimit);
+
+ const descriptionLines: string[] = [];
+ for (const command of currentCommands) {
+ const { name, aliases, description, contents } = command;
+ const versionEmojis = [];
+ for (const content of contents) {
+ const { versionId } = content;
+ if (versionId !== 'GENERIC') {
+ Logger.debug(`Fetching version ${versionId} for command ${name}`);
+ // eslint-disable-next-line no-await-in-loop
+ const versionCached = await inMemoryCache.get(`${MemoryCachePrefix.VERSION}:${versionId}`);
+ if (versionCached) {
+ const version = PrefixCommandVersion.hydrate(versionCached);
+ const { emoji } = version;
+ Logger.debug(`Found version ${versionId} for command ${name} with emoji ${emoji}`);
+ versionEmojis.push(emoji);
}
- const sortedVersionEmojis = versionEmojis.sort((a, b) => a.localeCompare(b));
- descriptionLines.push(`**${name}** ${sortedVersionEmojis.join(', ')}`);
- descriptionLines.push(description);
- if (aliases.length > 0) descriptionLines.push(`Aliases: ${aliases.join(', ')}`);
- descriptionLines.push('');
+ }
}
-
- const { name: categoryName, emoji: categoryEmoji } = category;
- const embed = makeEmbed({
- title: `${categoryEmoji || ''}${categoryName} Commands (${page + 1}/${totalPages})`,
- description: makeLines(descriptionLines),
- });
-
- embeds.push(embed);
+ const sortedVersionEmojis = versionEmojis.sort((a, b) => a.localeCompare(b));
+ descriptionLines.push(`**${name}** ${sortedVersionEmojis.join(', ')}`);
+ descriptionLines.push(description);
+ if (aliases.length > 0) descriptionLines.push(`Aliases: ${aliases.join(', ')}`);
+ descriptionLines.push('');
+ }
+
+ const { name: categoryName, emoji: categoryEmoji } = category;
+ const embed = makeEmbed({
+ title: `${categoryEmoji || ''}${categoryName} Commands (${page + 1}/${totalPages})`,
+ description: makeLines(descriptionLines),
+ });
+
+ embeds.push(embed);
}
return createPaginatedEmbedHandler(interaction, embeds);
-}, autocompleteCallback);
+ },
+ autocompleteCallback,
+);
diff --git a/src/commands/utils/reportedIssues.ts b/src/commands/utils/reportedIssues.ts
index c00677e7..ca54aea8 100644
--- a/src/commands/utils/reportedIssues.ts
+++ b/src/commands/utils/reportedIssues.ts
@@ -3,115 +3,140 @@ import { JSDOM } from 'jsdom';
import { Logger, makeEmbed, slashCommand, slashCommandStructure } from '../../lib';
const data = slashCommandStructure({
- name: 'reported-issues',
- description: 'Provides a link to the reported issues page within docs.',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'query',
- description: 'Provide a query to search for.',
- type: ApplicationCommandOptionType.String,
- max_length: 100,
- required: true,
- }],
+ name: 'reported-issues',
+ description: 'Provides a link to the reported issues page within docs.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'query',
+ description: 'Provide a query to search for.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 100,
+ required: true,
+ },
+ ],
});
const FBW_DOCS_REPORTED_ISSUES_URL = 'https://docs.flybywiresim.com/fbw-a32nx/support/reported-issues/';
-const FBW_DOCS_AUTOPILOT_ISSUES_URL = 'https://docs.flybywiresim.com/fbw-a32nx/feature-guides/autopilot-fbw/#typical-issues-and-how-to-solve-them';
+const FBW_DOCS_AUTOPILOT_ISSUES_URL =
+ 'https://docs.flybywiresim.com/fbw-a32nx/feature-guides/autopilot-fbw/#typical-issues-and-how-to-solve-them';
const FBW_DOCS_SIMBRIDGE_ISSUES_URL = 'https://docs.flybywiresim.com/simbridge/troubleshooting/';
const genericReportedIssuesEmbed = makeEmbed({
- title: 'FlyByWire A32NX | Reported Issues',
- description: `I couldn't find a match foy your query. Please see [this link](${FBW_DOCS_REPORTED_ISSUES_URL}) for a current list of reported issues.`,
+ title: 'FlyByWire A32NX | Reported Issues',
+ description: `I couldn't find a match foy your query. Please see [this link](${FBW_DOCS_REPORTED_ISSUES_URL}) for a current list of reported issues.`,
});
-const issueInSubsectionEmbed = (fields: EmbedField[]) => makeEmbed({
+const issueInSubsectionEmbed = (fields: EmbedField[]) =>
+ makeEmbed({
title: 'FlyByWire A32NX | Reported Issues',
- description: 'Your issue is in our reported issues list. Please try the possible solutions in the following link(s) and report back if they didn\'t help. Include all the steps you tried.',
+ description:
+ "Your issue is in our reported issues list. Please try the possible solutions in the following link(s) and report back if they didn't help. Include all the steps you tried.",
fields,
-});
+ });
const subsectionLinkEmbedField = (id: string, title: string): EmbedField[] => [
- {
- inline: false,
- name: `${title}`,
- value: `[Link to reported issues section](${FBW_DOCS_REPORTED_ISSUES_URL}#${id})`,
- },
+ {
+ inline: false,
+ name: `${title}`,
+ value: `[Link to reported issues section](${FBW_DOCS_REPORTED_ISSUES_URL}#${id})`,
+ },
];
const autopilotEmbed = makeEmbed({
- title: 'FlyByWire A32NX | Reported Issues',
- description: `Please see [this link](${FBW_DOCS_AUTOPILOT_ISSUES_URL}) for typical issues with the custom autopilot and how to solve them.`,
+ title: 'FlyByWire A32NX | Reported Issues',
+ description: `Please see [this link](${FBW_DOCS_AUTOPILOT_ISSUES_URL}) for typical issues with the custom autopilot and how to solve them.`,
});
const simbridgeEmbed = makeEmbed({
- title: 'FlyByWire A32NX | Reported Issues',
- description: `Please see [this link](${FBW_DOCS_SIMBRIDGE_ISSUES_URL}) for typical issues with simbridge and how to solve them.`,
+ title: 'FlyByWire A32NX | Reported Issues',
+ description: `Please see [this link](${FBW_DOCS_SIMBRIDGE_ISSUES_URL}) for typical issues with simbridge and how to solve them.`,
});
const generalTroubleshootingEmbed = makeEmbed({
- title: 'FlyByWire A32NX | Reported Issues',
- description: 'Please try the general troubleshooting steps from our reported issues page and report back if they didn\'t help. Include all the steps you tried.',
- fields: [{
- inline: false,
- name: 'General Troubleshooting Steps',
- value: `[Link to reported issues section](${FBW_DOCS_REPORTED_ISSUES_URL}#general-troubleshooting-steps)`,
- }],
+ title: 'FlyByWire A32NX | Reported Issues',
+ description:
+ "Please try the general troubleshooting steps from our reported issues page and report back if they didn't help. Include all the steps you tried.",
+ fields: [
+ {
+ inline: false,
+ name: 'General Troubleshooting Steps',
+ value: `[Link to reported issues section](${FBW_DOCS_REPORTED_ISSUES_URL}#general-troubleshooting-steps)`,
+ },
+ ],
});
const tooManyResultsEmbed = makeEmbed({
- title: 'FlyByWire A32NX | Error',
- description: 'The search term returned too many results',
- color: Colors.Red,
+ title: 'FlyByWire A32NX | Error',
+ description: 'The search term returned too many results',
+ color: Colors.Red,
});
export default slashCommand(data, async ({ interaction }) => {
- const query = interaction.options.getString('query')!;
-
- const lowercaseQuery = query.toLowerCase();
-
- const words = lowercaseQuery.split(/\s+/);
-
- if (words.length === 1) {
- if (lowercaseQuery === 'autopilot') {
- return interaction.reply({ embeds: [autopilotEmbed] });
- }
- if (lowercaseQuery === 'simbridge') {
- return interaction.reply({ embeds: [simbridgeEmbed] });
- }
- if (lowercaseQuery === 'troubleshooting') {
- return interaction.reply({ embeds: [generalTroubleshootingEmbed] });
- }
+ const query = interaction.options.getString('query')!;
+
+ const lowercaseQuery = query.toLowerCase();
+
+ const words = lowercaseQuery.split(/\s+/);
+
+ if (words.length === 1) {
+ if (lowercaseQuery === 'autopilot') {
+ return interaction.reply({ embeds: [autopilotEmbed] });
+ }
+ if (lowercaseQuery === 'simbridge') {
+ return interaction.reply({ embeds: [simbridgeEmbed] });
+ }
+ if (lowercaseQuery === 'troubleshooting') {
+ return interaction.reply({ embeds: [generalTroubleshootingEmbed] });
+ }
+ }
+
+ interface ReportedIssue {
+ id: string;
+ title: string | null;
+ }
+
+ try {
+ const reportedIssues: ReportedIssue[] = [];
+ const dom = await JSDOM.fromURL(`${FBW_DOCS_REPORTED_ISSUES_URL}`);
+ const { document } = dom.window;
+ const h3Elements = document.querySelectorAll('h3');
+ h3Elements.forEach((element) => {
+ const { id } = element;
+ if (words.every((searchWord) => id.includes(searchWord))) {
+ reportedIssues.push({ id, title: element.textContent });
+ }
+ });
+
+ if (reportedIssues.length === 0 || reportedIssues.length > 4) {
+ if (reportedIssues.length > 4) {
+ return interaction.reply({ embeds: [tooManyResultsEmbed] });
+ }
+ return interaction.reply({ embeds: [genericReportedIssuesEmbed] });
}
- try {
- const reportedIssues: any = [];
- const dom = await JSDOM.fromURL(`${FBW_DOCS_REPORTED_ISSUES_URL}`);
- const { document } = dom.window;
- const h3Elements = document.querySelectorAll('h3');
- h3Elements.forEach((element) => {
- const { id } = element;
- if (words.every((searchWord) => id.includes(searchWord))) {
- reportedIssues.push({ id, title: element.textContent });
- }
- });
-
- if (reportedIssues.length === 0 || reportedIssues.length > 4) {
- if (reportedIssues.length > 4) {
- return interaction.reply({ embeds: [tooManyResultsEmbed] });
- }
- return interaction.reply({ embeds: [genericReportedIssuesEmbed] });
- }
-
- const fields = reportedIssues.map((sectionElement: any) => subsectionLinkEmbedField(sectionElement.id, sectionElement.title)).flat();
- return interaction.reply({ embeds: [issueInSubsectionEmbed(fields)] });
- } catch (error: any) {
- Logger.error(error);
- Logger.error(error.stack);
- const errorEmbed = makeEmbed({
- title: 'Error | Reported Issues',
- description: error.message,
- color: Colors.Red,
- });
- return interaction.reply({ embeds: [errorEmbed] });
+ const fields = reportedIssues
+ .map((sectionElement) => subsectionLinkEmbedField(sectionElement.id, sectionElement.title ?? ''))
+ .flat();
+ return interaction.reply({ embeds: [issueInSubsectionEmbed(fields)] });
+ } catch (error) {
+ Logger.error(error);
+ if (error instanceof Error) {
+ Logger.error(error.stack);
+
+ const errorEmbed = makeEmbed({
+ title: 'Error | Reported Issues',
+ description: error.message,
+ color: Colors.Red,
+ });
+ return interaction.reply({ embeds: [errorEmbed] });
}
+
+ const errorEmbed = makeEmbed({
+ title: 'Error | Reported Issues',
+ description: 'An unknown error occurred.',
+ color: Colors.Red,
+ });
+ return interaction.reply({ embeds: [errorEmbed] });
+ }
});
diff --git a/src/commands/utils/roleInfo.ts b/src/commands/utils/roleInfo.ts
index 8ba7233f..06eb201e 100644
--- a/src/commands/utils/roleInfo.ts
+++ b/src/commands/utils/roleInfo.ts
@@ -2,29 +2,31 @@ import { ApplicationCommandOptionType, ApplicationCommandType } from 'discord.js
import { slashCommand, slashCommandStructure, makeEmbed } from '../../lib';
const data = slashCommandStructure({
- name: 'role-info',
- description: 'Lists the given role\'s amount of members.',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'role',
- description: 'Provide the role to get info about.',
- type: ApplicationCommandOptionType.Role,
- required: true,
- }],
+ name: 'role-info',
+ description: "Lists the given role's amount of members.",
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'role',
+ description: 'Provide the role to get info about.',
+ type: ApplicationCommandOptionType.Role,
+ required: true,
+ },
+ ],
});
export default slashCommand(data, async ({ interaction }) => {
- const role = interaction.options.getRole('role');
+ const role = interaction.options.getRole('role');
- if (!role) return interaction.reply({ content: 'Invalid role!', ephemeral: true });
+ if (!role) return interaction.reply({ content: 'Invalid role!', ephemeral: true });
- const roleMembers = role.members.map((member) => member.user.tag);
- const roleMemberCount = roleMembers.length;
+ const roleMembers = role.members.map((member) => member.user.tag);
+ const roleMemberCount = roleMembers.length;
- const roleInfoEmbed = makeEmbed({
- title: `Role Info | ${role.name}`,
- description: `Members: ${roleMemberCount}`,
- });
+ const roleInfoEmbed = makeEmbed({
+ title: `Role Info | ${role.name}`,
+ description: `Members: ${roleMemberCount}`,
+ });
- return interaction.reply({ embeds: [roleInfoEmbed] });
+ return interaction.reply({ embeds: [roleInfoEmbed] });
});
diff --git a/src/commands/utils/searchFaq.ts b/src/commands/utils/searchFaq.ts
index 465a07c2..dd20b719 100644
--- a/src/commands/utils/searchFaq.ts
+++ b/src/commands/utils/searchFaq.ts
@@ -2,62 +2,63 @@ import { ApplicationCommandOptionType, ApplicationCommandType } from 'discord.js
import { constantsConfig, slashCommand, slashCommandStructure, makeEmbed, FAQ, Logger } from '../../lib';
const data = slashCommandStructure({
- name: 'faq-search',
- description: 'Searches the FAQs.',
- type: ApplicationCommandType.ChatInput,
- options: [
- {
- name: 'search_term',
- description: 'The faq title to search for.',
- type: ApplicationCommandOptionType.String,
- max_length: 100,
- required: true,
- },
- ],
+ name: 'faq-search',
+ description: 'Searches the FAQs.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'search_term',
+ description: 'The faq title to search for.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 100,
+ required: true,
+ },
+ ],
});
-const noFaqsFoundEmbed = (searchTerm: string) => makeEmbed({
+const noFaqsFoundEmbed = (searchTerm: string) =>
+ makeEmbed({
title: `No FAQs found - ${searchTerm}`,
description: 'No FAQs found matching your search term. Please try again or see the links below.',
fields: [
- {
- name: '**FAQ Channel**',
- value: `<#${constantsConfig.channels.FAQ}>`,
- },
- {
- name: '**Docs FAQ**',
- value: 'https://docs.flybywiresim.com/fbw-a32nx/faq/',
- },
+ {
+ name: '**FAQ Channel**',
+ value: `<#${constantsConfig.channels.FAQ}>`,
+ },
+ {
+ name: '**Docs FAQ**',
+ value: 'https://docs.flybywiresim.com/fbw-a32nx/faq/',
+ },
],
-});
+ });
export default slashCommand(data, async ({ interaction }) => {
- const searchTerm = interaction.options.getString('search_term') ?? '';
+ const searchTerm = interaction.options.getString('search_term') ?? '';
- await interaction.deferReply();
+ await interaction.deferReply();
- try {
- // Fetch FAQs from the database based on the search term
- const faq = await FAQ.findOne({ faqTitle: { $regex: new RegExp(searchTerm, 'i') } });
+ try {
+ // Fetch FAQs from the database based on the search term
+ const faq = await FAQ.findOne({ faqTitle: { $regex: new RegExp(searchTerm, 'i') } });
- if (!faq) {
- await interaction.followUp({ embeds: [noFaqsFoundEmbed(searchTerm)] });
- } else {
- const faqEmbed = makeEmbed({
- title: 'Frequently Asked Question',
- description: `Search results for **${searchTerm}**`,
- fields: [
- {
- name: `**${faq.faqTitle}**`,
- value: `${faq.faqAnswer}`,
- },
- ],
- });
+ if (!faq) {
+ await interaction.followUp({ embeds: [noFaqsFoundEmbed(searchTerm)] });
+ } else {
+ const faqEmbed = makeEmbed({
+ title: 'Frequently Asked Question',
+ description: `Search results for **${searchTerm}**`,
+ fields: [
+ {
+ name: `**${faq.faqTitle}**`,
+ value: `${faq.faqAnswer}`,
+ },
+ ],
+ });
- await interaction.followUp({ embeds: [faqEmbed] });
- }
- } catch (error) {
- Logger.error('Error fetching FAQ:', error);
- await interaction.followUp({ content: 'An error occurred while fetching the FAQ.', ephemeral: true });
+ await interaction.followUp({ embeds: [faqEmbed] });
}
+ } catch (error) {
+ Logger.error('Error fetching FAQ:', error);
+ await interaction.followUp({ content: 'An error occurred while fetching the FAQ.', ephemeral: true });
+ }
});
diff --git a/src/commands/utils/simbriefData.ts b/src/commands/utils/simbriefData.ts
index b7d818a1..fe124566 100644
--- a/src/commands/utils/simbriefData.ts
+++ b/src/commands/utils/simbriefData.ts
@@ -3,91 +3,97 @@ import moment from 'moment';
import { slashCommand, makeEmbed, makeLines, slashCommandStructure } from '../../lib';
const data = slashCommandStructure({
- name: 'simbrief-data',
- description: 'Gets the simbrief data for the given flight number/pilotID.',
- type: ApplicationCommandType.ChatInput,
- options: [
+ name: 'simbrief-data',
+ description: 'Gets the simbrief data for the given flight number/pilotID.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'retrieve',
+ description: 'Shows data for your last filed flight plan.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
{
- name: 'retrieve',
- description: 'Shows data for your last filed flight plan.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [{
- name: 'pilot_id',
- description: 'Please provide your pilot ID.',
- type: ApplicationCommandOptionType.String,
- max_length: 100,
- required: true,
- }],
+ name: 'pilot_id',
+ description: 'Please provide your pilot ID.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 100,
+ required: true,
},
- {
- name: 'support-request',
- description: 'Shows information on how to provide SimBrief data.',
- type: ApplicationCommandOptionType.Subcommand,
- },
- ],
+ ],
+ },
+ {
+ name: 'support-request',
+ description: 'Shows information on how to provide SimBrief data.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ ],
});
const FBW_AIRFRAME_ID = '337364_1631550522735';
const simbriefdatarequestEmbed = makeEmbed({
- title: 'FlyByWire Support | SimBrief Data Request',
- description: makeLines([
- 'To evaluate your problem we kindly ask you to enter the following bot command into a new message.',
- '```/simbrief-data retrieve```',
- 'Enter your `pilotId` with your simbrief pilotId or userName (as set in the EFB settings). The Bot will read your last generated flight plan and display some details about it including the route.',
- '',
- '**Privacy notice**: If you share your pilotId or username it is possible to read your pilot name from the API the bot uses. This pilot name is by default your real name, but you can change it in the flight edit screen or your user profile in SimBrief. No data is stored by FlyByWire when using the command.',
- ]),
+ title: 'FlyByWire Support | SimBrief Data Request',
+ description: makeLines([
+ 'To evaluate your problem we kindly ask you to enter the following bot command into a new message.',
+ '```/simbrief-data retrieve```',
+ 'Enter your `pilotId` with your simbrief pilotId or userName (as set in the EFB settings). The Bot will read your last generated flight plan and display some details about it including the route.',
+ '',
+ '**Privacy notice**: If you share your pilotId or username it is possible to read your pilot name from the API the bot uses. This pilot name is by default your real name, but you can change it in the flight edit screen or your user profile in SimBrief. No data is stored by FlyByWire when using the command.',
+ ]),
});
-const errorEmbed = (errorMessage: any) => makeEmbed({
+const errorEmbed = (errorMessage: any) =>
+ makeEmbed({
title: 'SimBrief Error',
description: makeLines(['SimBrief data could not be read.', errorMessage]),
color: Colors.Red,
-});
+ });
-const simbriefIdMismatchEmbed = (enteredId: any, flightplanId: any) => makeEmbed({
+const simbriefIdMismatchEmbed = (enteredId: any, flightplanId: any) =>
+ makeEmbed({
title: 'SimBrief Data',
description: makeLines([
- `Entered pilotId ${enteredId} and returned pilotId ${flightplanId} don't match. The pilotId might be used as username by someone else.`,
+ `Entered pilotId ${enteredId} and returned pilotId ${flightplanId} don't match. The pilotId might be used as username by someone else.`,
]),
-});
+ });
-const simbriefEmbed = (flightplan: any) => makeEmbed({
+const simbriefEmbed = (flightplan: any) =>
+ makeEmbed({
title: 'SimBrief Data',
description: makeLines([
- `**Generated at**: ${moment(flightplan.params.time_generated * 1000).format('DD.MM.YYYY, HH:mm:ss')}`,
- `**AirFrame**: ${flightplan.aircraft.name} ${flightplan.aircraft.internal_id} ${(flightplan.aircraft.internal_id === FBW_AIRFRAME_ID) ? '(provided by FBW)' : ''}`,
- `**AIRAC Cycle**: ${flightplan.params.airac}`,
- `**Origin**: ${flightplan.origin.icao_code} ${flightplan.origin.plan_rwy}`,
- `**Destination**: ${flightplan.destination.icao_code} ${flightplan.destination.plan_rwy}`,
- `**Route**: ${flightplan.general.route}`,
+ `**Generated at**: ${moment(flightplan.params.time_generated * 1000).format('DD.MM.YYYY, HH:mm:ss')}`,
+ `**AirFrame**: ${flightplan.aircraft.name} ${flightplan.aircraft.internal_id} ${flightplan.aircraft.internal_id === FBW_AIRFRAME_ID ? '(provided by FBW)' : ''}`,
+ `**AIRAC Cycle**: ${flightplan.params.airac}`,
+ `**Origin**: ${flightplan.origin.icao_code} ${flightplan.origin.plan_rwy}`,
+ `**Destination**: ${flightplan.destination.icao_code} ${flightplan.destination.plan_rwy}`,
+ `**Route**: ${flightplan.general.route}`,
]),
-
-});
+ });
export default slashCommand(data, async ({ interaction }) => {
- if (interaction.options.getSubcommand() === 'support-request') {
- return interaction.reply({ embeds: [simbriefdatarequestEmbed] });
- }
+ if (interaction.options.getSubcommand() === 'support-request') {
+ return interaction.reply({ embeds: [simbriefdatarequestEmbed] });
+ }
- if (interaction.options.getSubcommand() === 'retrieve') {
- const simbriefId = interaction.options.getString('pilot_id');
- if (!simbriefId) return interaction.reply({ content: 'Invalid pilot ID!', ephemeral: true });
+ if (interaction.options.getSubcommand() === 'retrieve') {
+ const simbriefId = interaction.options.getString('pilot_id');
+ if (!simbriefId) return interaction.reply({ content: 'Invalid pilot ID!', ephemeral: true });
- const flightplan = await fetch(`https://www.simbrief.com/api/xml.fetcher.php?json=1&userid=${simbriefId}&username=${simbriefId}`).then((res) => res.json());
+ const flightplan = await fetch(
+ `https://www.simbrief.com/api/xml.fetcher.php?json=1&userid=${simbriefId}&username=${simbriefId}`,
+ ).then((res) => res.json());
- if (flightplan.fetch.status !== 'Success') {
- interaction.reply({ embeds: [errorEmbed(flightplan.fetch.status)], ephemeral: true });
- return Promise.resolve();
- }
-
- if (!simbriefId.match(/\D/) && simbriefId !== flightplan.params.user_id) {
- interaction.reply({ embeds: [simbriefIdMismatchEmbed(simbriefId, flightplan.params.user_id)] });
- }
- interaction.reply({ embeds: [simbriefEmbed(flightplan)] });
+ if (flightplan.fetch.status !== 'Success') {
+ interaction.reply({ embeds: [errorEmbed(flightplan.fetch.status)], ephemeral: true });
+ return Promise.resolve();
+ }
- return Promise.resolve();
+ if (!simbriefId.match(/\D/) && simbriefId !== flightplan.params.user_id) {
+ interaction.reply({ embeds: [simbriefIdMismatchEmbed(simbriefId, flightplan.params.user_id)] });
}
+ interaction.reply({ embeds: [simbriefEmbed(flightplan)] });
+
return Promise.resolve();
+ }
+ return Promise.resolve();
});
diff --git a/src/commands/utils/station.ts b/src/commands/utils/station.ts
index 8cde14a2..44fb247d 100644
--- a/src/commands/utils/station.ts
+++ b/src/commands/utils/station.ts
@@ -3,91 +3,96 @@ import fetch from 'node-fetch';
import { slashCommand, slashCommandStructure, makeEmbed, Logger, makeLines } from '../../lib';
const data = slashCommandStructure({
- name: 'station',
- description: 'Provides station information.',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'icao',
- description: 'Provide an airport ICAO code.',
- type: ApplicationCommandOptionType.String,
- max_length: 4,
- min_length: 4,
- required: true,
- }],
+ name: 'station',
+ description: 'Provides station information.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'icao',
+ description: 'Provide an airport ICAO code.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 4,
+ min_length: 4,
+ required: true,
+ },
+ ],
});
const noQueryEmbed = makeEmbed({
- title: 'Station Error | Missing Query',
- description: 'You must provide an airport ICAO code.',
- color: Colors.Red,
+ title: 'Station Error | Missing Query',
+ description: 'You must provide an airport ICAO code.',
+ color: Colors.Red,
});
export default slashCommand(data, async ({ interaction }) => {
- await interaction.deferReply();
+ await interaction.deferReply();
- const stationToken = process.env.STATION_TOKEN;
+ const stationToken = process.env.STATION_TOKEN;
- if (!stationToken) {
- const noTokenEmbed = makeEmbed({
- title: 'Error | Station',
- description: 'Station token not found.',
- color: Colors.Red,
- });
- return interaction.editReply({ embeds: [noTokenEmbed] });
- }
+ if (!stationToken) {
+ const noTokenEmbed = makeEmbed({
+ title: 'Error | Station',
+ description: 'Station token not found.',
+ color: Colors.Red,
+ });
+ return interaction.editReply({ embeds: [noTokenEmbed] });
+ }
- const icao = interaction.options.getString('icao');
+ const icao = interaction.options.getString('icao');
- if (!icao) return interaction.editReply({ embeds: [noQueryEmbed] });
+ if (!icao) return interaction.editReply({ embeds: [noQueryEmbed] });
- try {
- const stationReport: any = await fetch(`https://avwx.rest/api/station/${icao}`, {
- method: 'GET',
- headers: { Authorization: stationToken },
- }).then((res) => res.json());
+ try {
+ const stationReport: any = await fetch(`https://avwx.rest/api/station/${icao}`, {
+ method: 'GET',
+ headers: { Authorization: stationToken },
+ }).then((res) => res.json());
- if (stationReport.error) {
- const invalidEmbed = makeEmbed({
- title: `Station Error | ${icao.toUpperCase()}`,
- description: stationReport.error,
- color: Colors.Red,
- });
- return interaction.editReply({ embeds: [invalidEmbed] });
- }
+ if (stationReport.error) {
+ const invalidEmbed = makeEmbed({
+ title: `Station Error | ${icao.toUpperCase()}`,
+ description: stationReport.error,
+ color: Colors.Red,
+ });
+ return interaction.editReply({ embeds: [invalidEmbed] });
+ }
- const runwayIdents = stationReport.runways.map((runways: any) => `**${runways.ident1}/${runways.ident2}:** `
- + `${runways.length_ft} ft x ${runways.width_ft} ft / `
- + `${Math.round(runways.length_ft * 0.3048)} m x ${Math.round(runways.width_ft * 0.3048)} m`);
+ const runwayIdents = stationReport.runways.map(
+ (runways: any) =>
+ `**${runways.ident1}/${runways.ident2}:** ` +
+ `${runways.length_ft} ft x ${runways.width_ft} ft / ` +
+ `${Math.round(runways.length_ft * 0.3048)} m x ${Math.round(runways.width_ft * 0.3048)} m`,
+ );
- const stationEmbed = makeEmbed({
- title: `Station Info | ${stationReport.icao}`,
- description: makeLines([
- '**Station Information:**',
- `**Name:** ${stationReport.name}`,
- `**Country:** ${stationReport.country}`,
- `**City:** ${stationReport.city}`,
- `**Latitude:** ${stationReport.latitude}°`,
- `**Longitude:** ${stationReport.longitude}°`,
- `**Elevation:** ${stationReport.elevation_m} m/${stationReport.elevation_ft} ft`,
- '',
- '**Runways (Ident1/Ident2: Length x Width):**',
- `${runwayIdents.toString().replace(/,/g, '\n')}`,
- '',
- `**Type:** ${stationReport.type.replace(/_/g, ' ')}`,
- `**Website:** ${stationReport.website}`,
- `**Wiki:** ${stationReport.wiki}`,
- ]),
- footer: { text: 'Due to limitations of the API, not all links may be up to date at all times.' },
- });
+ const stationEmbed = makeEmbed({
+ title: `Station Info | ${stationReport.icao}`,
+ description: makeLines([
+ '**Station Information:**',
+ `**Name:** ${stationReport.name}`,
+ `**Country:** ${stationReport.country}`,
+ `**City:** ${stationReport.city}`,
+ `**Latitude:** ${stationReport.latitude}°`,
+ `**Longitude:** ${stationReport.longitude}°`,
+ `**Elevation:** ${stationReport.elevation_m} m/${stationReport.elevation_ft} ft`,
+ '',
+ '**Runways (Ident1/Ident2: Length x Width):**',
+ `${runwayIdents.toString().replace(/,/g, '\n')}`,
+ '',
+ `**Type:** ${stationReport.type.replace(/_/g, ' ')}`,
+ `**Website:** ${stationReport.website}`,
+ `**Wiki:** ${stationReport.wiki}`,
+ ]),
+ footer: { text: 'Due to limitations of the API, not all links may be up to date at all times.' },
+ });
- return interaction.editReply({ embeds: [stationEmbed] });
- } catch (error) {
- Logger.error('station:', error);
- const fetchErrorEmbed = makeEmbed({
- title: 'Station Error | Fetch Error',
- description: 'There was an error fetching the station report. Please try again later.',
- color: Colors.Red,
- });
- return interaction.editReply({ embeds: [fetchErrorEmbed] });
- }
+ return interaction.editReply({ embeds: [stationEmbed] });
+ } catch (error) {
+ Logger.error('station:', error);
+ const fetchErrorEmbed = makeEmbed({
+ title: 'Station Error | Fetch Error',
+ description: 'There was an error fetching the station report. Please try again later.',
+ color: Colors.Red,
+ });
+ return interaction.editReply({ embeds: [fetchErrorEmbed] });
+ }
});
diff --git a/src/commands/utils/taf.ts b/src/commands/utils/taf.ts
index dba64551..799cc3a1 100644
--- a/src/commands/utils/taf.ts
+++ b/src/commands/utils/taf.ts
@@ -3,100 +3,105 @@ import fetch from 'node-fetch';
import { constantsConfig, slashCommand, slashCommandStructure, makeEmbed, makeLines, Logger } from '../../lib';
const data = slashCommandStructure({
- name: 'taf',
- description: 'Provides the TAF report of the requested airport.',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'icao',
- description: 'Provide an airport ICAO code.',
- type: ApplicationCommandOptionType.String,
- max_length: 4,
- min_length: 4,
- required: true,
- }],
+ name: 'taf',
+ description: 'Provides the TAF report of the requested airport.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'icao',
+ description: 'Provide an airport ICAO code.',
+ type: ApplicationCommandOptionType.String,
+ max_length: 4,
+ min_length: 4,
+ required: true,
+ },
+ ],
});
const noQueryEmbed = makeEmbed({
- title: 'TAF Error | Missing Query',
- description: 'You must provide an airport ICAO code.',
- color: Colors.Red,
+ title: 'TAF Error | Missing Query',
+ description: 'You must provide an airport ICAO code.',
+ color: Colors.Red,
});
export default slashCommand(data, async ({ interaction }) => {
- await interaction.deferReply();
+ await interaction.deferReply();
- const tafToken = process.env.TAF_TOKEN;
+ const tafToken = process.env.TAF_TOKEN;
- if (!tafToken) {
- const noTokenEmbed = makeEmbed({
- title: 'Error | Station',
- description: 'Station token not found.',
- color: Colors.Red,
- });
- return interaction.editReply({ embeds: [noTokenEmbed] });
- }
+ if (!tafToken) {
+ const noTokenEmbed = makeEmbed({
+ title: 'Error | Station',
+ description: 'Station token not found.',
+ color: Colors.Red,
+ });
+ return interaction.editReply({ embeds: [noTokenEmbed] });
+ }
- const icao = interaction.options.getString('icao');
+ const icao = interaction.options.getString('icao');
- if (!icao) {
- return interaction.editReply({ embeds: [noQueryEmbed] });
- }
+ if (!icao) {
+ return interaction.editReply({ embeds: [noQueryEmbed] });
+ }
- try {
- const tafReport: any = await fetch(`https://avwx.rest/api/taf/${icao}`, {
- method: 'GET',
- headers: { Authorization: tafToken },
- }).then((res) => res.json());
+ try {
+ const tafReport: any = await fetch(`https://avwx.rest/api/taf/${icao}`, {
+ method: 'GET',
+ headers: { Authorization: tafToken },
+ }).then((res) => res.json());
- if (tafReport.error) {
- const invalidEmbed = makeEmbed({
- title: `TAF Error | ${icao.toUpperCase()}`,
- description: tafReport.error,
- color: Colors.Red,
- });
- return interaction.editReply({ embeds: [invalidEmbed] });
- }
- const getClouds = (clouds: any) => {
- const retClouds = [];
- for (const cloud of clouds) {
- retClouds.push(cloud.repr);
- }
- return retClouds.join(', ');
- };
- const tafEmbed = makeEmbed({
- title: `TAF Report | ${tafReport.station}`,
- description: makeLines([
- '**Raw Report**',
- tafReport.raw,
+ if (tafReport.error) {
+ const invalidEmbed = makeEmbed({
+ title: `TAF Error | ${icao.toUpperCase()}`,
+ description: tafReport.error,
+ color: Colors.Red,
+ });
+ return interaction.editReply({ embeds: [invalidEmbed] });
+ }
+ const getClouds = (clouds: any) => {
+ const retClouds = [];
+ for (const cloud of clouds) {
+ retClouds.push(cloud.repr);
+ }
+ return retClouds.join(', ');
+ };
+ const tafEmbed = makeEmbed({
+ title: `TAF Report | ${tafReport.station}`,
+ description: makeLines([
+ '**Raw Report**',
+ tafReport.raw,
- '',
- '**Basic Report:**',
- `**Time Forecasted:** ${tafReport.time.dt}`,
- `**Forecast Start Time:** ${tafReport.start_time.dt}`,
- `**Forecast End Time:** ${tafReport.end_time.dt}`,
- `**Visibility:** ${tafReport.forecast[0].visibility.repr} ${Number.isNaN(+tafReport.forecast[0].visibility.repr) ? '' : tafReport.units.visibility}`,
- `**Wind:** ${tafReport.forecast[0].wind_direction.repr}${tafReport.forecast[0].wind_direction.repr === 'VRB' ? '' : constantsConfig.units.DEGREES} at ${tafReport.forecast[0].wind_speed.repr} ${tafReport.units.wind_speed}`,
- `**Clouds:** ${getClouds(tafReport.forecast[0].clouds)}`,
- `**Flight Rules:** ${tafReport.forecast[0].flight_rules}`,
- ]),
- fields: [
- {
- name: 'Unsure of how to read the raw report?',
- value: 'Please refer to our guide [here.](https://docs.flybywiresim.com/pilots-corner/airliner-flying-guide/weather/#taf-example-decoded)',
- inline: false,
- },
- ],
- footer: { text: 'This TAF report is only a forecast, and may not accurately reflect weather in the simulator.' },
- });
+ '',
+ '**Basic Report:**',
+ `**Time Forecasted:** ${tafReport.time.dt}`,
+ `**Forecast Start Time:** ${tafReport.start_time.dt}`,
+ `**Forecast End Time:** ${tafReport.end_time.dt}`,
+ `**Visibility:** ${tafReport.forecast[0].visibility.repr} ${Number.isNaN(+tafReport.forecast[0].visibility.repr) ? '' : tafReport.units.visibility}`,
+ `**Wind:** ${tafReport.forecast[0].wind_direction.repr}${tafReport.forecast[0].wind_direction.repr === 'VRB' ? '' : constantsConfig.units.DEGREES} at ${tafReport.forecast[0].wind_speed.repr} ${tafReport.units.wind_speed}`,
+ `**Clouds:** ${getClouds(tafReport.forecast[0].clouds)}`,
+ `**Flight Rules:** ${tafReport.forecast[0].flight_rules}`,
+ ]),
+ fields: [
+ {
+ name: 'Unsure of how to read the raw report?',
+ value:
+ 'Please refer to our guide [here.](https://docs.flybywiresim.com/pilots-corner/airliner-flying-guide/weather/#taf-example-decoded)',
+ inline: false,
+ },
+ ],
+ footer: {
+ text: 'This TAF report is only a forecast, and may not accurately reflect weather in the simulator.',
+ },
+ });
- return interaction.editReply({ embeds: [tafEmbed] });
- } catch (error) {
- Logger.error('taf:', error);
- const fetchErrorEmbed = makeEmbed({
- title: 'TAF Error | Fetch Error',
- description: 'There was an error fetching the TAF report. Please try again later.',
- color: Colors.Red,
- });
- return interaction.editReply({ embeds: [fetchErrorEmbed] });
- }
+ return interaction.editReply({ embeds: [tafEmbed] });
+ } catch (error) {
+ Logger.error('taf:', error);
+ const fetchErrorEmbed = makeEmbed({
+ title: 'TAF Error | Fetch Error',
+ description: 'There was an error fetching the TAF report. Please try again later.',
+ color: Colors.Red,
+ });
+ return interaction.editReply({ embeds: [fetchErrorEmbed] });
+ }
});
diff --git a/src/commands/utils/vatsim/functions/vatsimControllers.ts b/src/commands/utils/vatsim/functions/vatsimControllers.ts
index 08e5cd2b..35b9067c 100644
--- a/src/commands/utils/vatsim/functions/vatsimControllers.ts
+++ b/src/commands/utils/vatsim/functions/vatsimControllers.ts
@@ -1,86 +1,115 @@
+/* eslint-disable */
+// Safer to be done separately due to complexity.
+
import { ChatInputCommandInteraction, EmbedField } from 'discord.js';
import { makeEmbed } from '../../../../lib';
-/* eslint-disable camelcase */
-
-const listEmbed = (type: string, fields: EmbedField[], totalCount: number, shownCount: number, callsign: string) => makeEmbed({
+const listEmbed = (type: string, fields: EmbedField[], totalCount: number, shownCount: number, callsign: string) =>
+ makeEmbed({
title: `VATSIM Data - ${callsign} - ${totalCount} ${type} online`,
description: `A list of ${shownCount} online ${type} matching ${callsign}.`,
fields,
-});
+ });
-const controllersListEmbedFields = (callsign: string, frequency: string, logon: string, rating: string, atis: string, atisCode: string): EmbedField[] => {
- const fields = [
- {
- name: 'Callsign',
- value: `${callsign}`,
- inline: false,
- },
- {
- name: 'Frequency',
- value: `${frequency}`,
- inline: true,
- },
- {
- name: 'Logon Date & Time',
- value: `${logon}`,
- inline: true,
- },
- {
- name: 'Rating',
- value: `${rating}`,
- inline: true,
- },
- ];
- if (atis !== null) {
- let atisTitle = 'Info';
- if (atisCode) {
- atisTitle = `ATIS - Code: ${atisCode}`;
- } else if (atisCode !== undefined) {
- atisTitle = 'ATIS';
- }
- fields.push({
- name: atisTitle,
- value: atis,
- inline: false,
- });
+const controllersListEmbedFields = (
+ callsign: string,
+ frequency: string,
+ logon: string,
+ rating: string,
+ atis: string,
+ atisCode: string,
+): EmbedField[] => {
+ const fields = [
+ {
+ name: 'Callsign',
+ value: `${callsign}`,
+ inline: false,
+ },
+ {
+ name: 'Frequency',
+ value: `${frequency}`,
+ inline: true,
+ },
+ {
+ name: 'Logon Date & Time',
+ value: `${logon}`,
+ inline: true,
+ },
+ {
+ name: 'Rating',
+ value: `${rating}`,
+ inline: true,
+ },
+ ];
+ if (atis !== null) {
+ let atisTitle = 'Info';
+ if (atisCode) {
+ atisTitle = `ATIS - Code: ${atisCode}`;
+ } else if (atisCode !== undefined) {
+ atisTitle = 'ATIS';
}
+ fields.push({
+ name: atisTitle,
+ value: atis,
+ inline: false,
+ });
+ }
- return fields;
+ return fields;
};
-const handleLocaleDateTimeString = (date: Date) => date.toLocaleDateString('en-US', {
+const handleLocaleDateTimeString = (date: Date) =>
+ date.toLocaleDateString('en-US', {
hour: 'numeric',
minute: 'numeric',
weekday: 'short',
month: 'short',
day: 'numeric',
-});
+ });
-export async function handleVatsimControllers(interaction: ChatInputCommandInteraction<'cached'>, vatsimData: any, callsignSearch: any) {
- const vatsimAllControllers = vatsimData.controllers ? vatsimData.controllers.filter((controller: { facility: number; }) => controller.facility > 0) : null;
+export async function handleVatsimControllers(
+ interaction: ChatInputCommandInteraction<'cached'>,
+ vatsimData: any,
+ callsignSearch: any,
+) {
+ const vatsimAllControllers = vatsimData.controllers
+ ? vatsimData.controllers.filter((controller: { facility: number }) => controller.facility > 0)
+ : null;
- const vatsimControllerRatings = vatsimData.ratings ? vatsimData.ratings : null;
- const vatsimControllers = vatsimAllControllers ? vatsimAllControllers.filter((controller: { callsign: string | string[]; }) => controller.callsign.includes(callsignSearch)) : null;
- const vatsimAtis = vatsimData.atis ? vatsimData.atis.filter((atis: { callsign: string | string[]; }) => atis.callsign.includes(callsignSearch)) : null;
+ const vatsimControllerRatings = vatsimData.ratings ? vatsimData.ratings : null;
+ const vatsimControllers = vatsimAllControllers
+ ? vatsimAllControllers.filter((controller: { callsign: string | string[] }) =>
+ controller.callsign.includes(callsignSearch),
+ )
+ : null;
+ const vatsimAtis = vatsimData.atis
+ ? vatsimData.atis.filter((atis: { callsign: string | string[] }) => atis.callsign.includes(callsignSearch))
+ : null;
- const { keys }: ObjectConstructor = Object;
+ const { keys }: ObjectConstructor = Object;
- const fields: EmbedField[] = [...vatsimControllers.sort((a: { facility: number; }, b: { facility: number; }) => b.facility - a.facility), ...vatsimAtis]
- .map((vatsimController) => {
- const { callsign, frequency, logon_time, atis_code, text_atis, rating } = vatsimController;
- const logonTime = new Date(logon_time);
- const logonTimeString = handleLocaleDateTimeString(logonTime);
- const ratingDetail = vatsimControllerRatings.filter((ratingInfo: { id: any; }) => ratingInfo.id === rating);
- const { short, long } = ratingDetail[0];
- const ratingText = `${short} - ${long}`;
- const atisText = text_atis ? text_atis.join('\n') : null;
+ const fields: EmbedField[] = [
+ ...vatsimControllers.sort((a: { facility: number }, b: { facility: number }) => b.facility - a.facility),
+ ...vatsimAtis,
+ ]
+ .map((vatsimController) => {
+ const { callsign, frequency, logon_time, atis_code, text_atis, rating } = vatsimController;
+ const logonTime = new Date(logon_time);
+ const logonTimeString = handleLocaleDateTimeString(logonTime);
+ const ratingDetail = vatsimControllerRatings.filter((ratingInfo: { id: any }) => ratingInfo.id === rating);
+ const { short, long } = ratingDetail[0];
+ const ratingText = `${short} - ${long}`;
+ const atisText = text_atis ? text_atis.join('\n') : null;
- return controllersListEmbedFields(callsign, frequency, logonTimeString, ratingText, atisText, atis_code);
- }).slice(0, 5).flat();
+ return controllersListEmbedFields(callsign, frequency, logonTimeString, ratingText, atisText, atis_code);
+ })
+ .slice(0, 5)
+ .flat();
- const totalCount = keys(vatsimControllers).length + keys(vatsimAtis).length;
- const shownCount = totalCount < 5 ? totalCount : 5;
+ const totalCount = keys(vatsimControllers).length + keys(vatsimAtis).length;
+ const shownCount = totalCount < 5 ? totalCount : 5;
- return interaction.reply({ embeds: [listEmbed('Controllers & ATIS', fields, totalCount, shownCount, callsignSearch)] });
+ return interaction.reply({
+ embeds: [listEmbed('Controllers & ATIS', fields, totalCount, shownCount, callsignSearch)],
+ });
}
diff --git a/src/commands/utils/vatsim/functions/vatsimEvents.ts b/src/commands/utils/vatsim/functions/vatsimEvents.ts
index 468c8f83..a63e4cbd 100644
--- a/src/commands/utils/vatsim/functions/vatsimEvents.ts
+++ b/src/commands/utils/vatsim/functions/vatsimEvents.ts
@@ -1,83 +1,90 @@
+/* eslint-disable */
+// Safer to be done separately due to complexity.
+
import { ChatInputCommandInteraction, Colors, EmbedField } from 'discord.js';
import { Logger, makeEmbed } from '../../../../lib';
const BASE_VATSIM_URL = 'https://my.vatsim.net';
-const handleLocaleTimeString = (date: Date) => date.toLocaleTimeString('en-US', {
+const handleLocaleTimeString = (date: Date) =>
+ date.toLocaleTimeString('en-US', {
hour: 'numeric',
minute: 'numeric',
-});
+ });
-const handleLocaleDateString = (date: Date) => date.toLocaleDateString('en-US', {
+const handleLocaleDateString = (date: Date) =>
+ date.toLocaleDateString('en-US', {
weekday: 'short',
month: 'short',
day: 'numeric',
-});
+ });
export async function handleVatsimEvents(interaction: ChatInputCommandInteraction<'cached'>) {
- await interaction.deferReply();
+ await interaction.deferReply();
- try {
- const eventsList = await fetch(`${BASE_VATSIM_URL}/api/v1/events/all`)
- .then((res) => res.json())
- .then((res) => res.data)
- .then((res) => res.filter((event: { type: string; }) => event.type === 'Event'))
- .then((res) => res.slice(0, 5));
+ try {
+ const eventsList = await fetch(`${BASE_VATSIM_URL}/api/v1/events/all`)
+ .then((res) => res.json())
+ .then((res) => res.data)
+ .then((res) => res.filter((event: { type: string }) => event.type === 'Event'))
+ .then((res) => res.slice(0, 5));
- const fields: EmbedField[] = eventsList.map((event: any) => {
- // eslint-disable-next-line camelcase
- const { name, organisers, end_time, start_time, link } = event;
- const { division } = organisers[0];
- const startDate = new Date(start_time);
- const endDate = new Date(end_time);
- const startTime = handleLocaleTimeString(startDate);
- const endTime = handleLocaleTimeString(endDate);
- const startDateString = handleLocaleDateString(startDate);
- const endDateString = handleLocaleDateString(endDate);
+ const fields: EmbedField[] = eventsList
+ .map((event: any) => {
+ const { name, organisers, end_time, start_time, link } = event;
+ const { division } = organisers[0];
+ const startDate = new Date(start_time);
+ const endDate = new Date(end_time);
+ const startTime = handleLocaleTimeString(startDate);
+ const endTime = handleLocaleTimeString(endDate);
+ const startDateString = handleLocaleDateString(startDate);
+ const endDateString = handleLocaleDateString(endDate);
- return [
- {
- name: 'Name',
- value: name,
- inline: false,
- },
- {
- name: 'Start Time/Date',
- value: `${startTime}/${startDateString}`,
- inline: true,
- },
- {
- name: 'End Time/Date',
- value: `${endTime}/${endDateString}`,
- inline: true,
- },
- {
- name: 'Division',
- value: `${division}`,
- inline: true,
- },
- {
- name: 'Link',
- value: `${link}`,
- inline: false,
- },
- ];
- }).flat();
+ return [
+ {
+ name: 'Name',
+ value: name,
+ inline: false,
+ },
+ {
+ name: 'Start Time/Date',
+ value: `${startTime}/${startDateString}`,
+ inline: true,
+ },
+ {
+ name: 'End Time/Date',
+ value: `${endTime}/${endDateString}`,
+ inline: true,
+ },
+ {
+ name: 'Division',
+ value: `${division}`,
+ inline: true,
+ },
+ {
+ name: 'Link',
+ value: `${link}`,
+ inline: false,
+ },
+ ];
+ })
+ .flat();
- const eventsEmbed = makeEmbed({
- title: 'VATSIM Events',
- description: 'A list of upcoming events on the VATSIM network. Find the full list [here.](https://my.vatsim.net/events)',
- fields,
- });
+ const eventsEmbed = makeEmbed({
+ title: 'VATSIM Events',
+ description:
+ 'A list of upcoming events on the VATSIM network. Find the full list [here.](https://my.vatsim.net/events)',
+ fields,
+ });
- return interaction.editReply({ embeds: [eventsEmbed] });
- } catch (error: any) {
- Logger.error(error);
- const errorEmbed = makeEmbed({
- title: 'Events Error',
- description: error.message,
- color: Colors.Red,
- });
- return interaction.editReply({ embeds: [errorEmbed] });
- }
+ return interaction.editReply({ embeds: [eventsEmbed] });
+ } catch (error: any) {
+ Logger.error(error);
+ const errorEmbed = makeEmbed({
+ title: 'Events Error',
+ description: error.message,
+ color: Colors.Red,
+ });
+ return interaction.editReply({ embeds: [errorEmbed] });
+ }
}
diff --git a/src/commands/utils/vatsim/functions/vatsimObservers.ts b/src/commands/utils/vatsim/functions/vatsimObservers.ts
index 48fd6ed1..102fa2e8 100644
--- a/src/commands/utils/vatsim/functions/vatsimObservers.ts
+++ b/src/commands/utils/vatsim/functions/vatsimObservers.ts
@@ -1,74 +1,90 @@
+/* eslint-disable */
+// Safer to be done separately due to complexity.
+
import { ChatInputCommandInteraction, EmbedField } from 'discord.js';
import { makeEmbed } from '../../../../lib';
-/* eslint-disable camelcase */
-
-const listEmbed = (type: string, fields: EmbedField[], totalCount: number, shownCount: number, callsign: string) => makeEmbed({
+const listEmbed = (type: string, fields: EmbedField[], totalCount: number, shownCount: number, callsign: string) =>
+ makeEmbed({
title: `VATSIM Data - ${callsign} - ${totalCount} ${type} online`,
description: `A list of ${shownCount} online ${type} matching ${callsign}.`,
fields,
-});
+ });
const observersListEmbedFields = (callsign: string, logon: string, rating: string, atis: string): EmbedField[] => {
- const fields = [
- {
- name: 'Callsign',
- value: `${callsign}`,
- inline: false,
- },
- {
- name: 'Logon Date & Time',
- value: `${logon}`,
- inline: true,
- },
- {
- name: 'Rating',
- value: `${rating}`,
- inline: true,
- },
- ];
- if (atis !== null) {
- const atisTitle = 'Info';
- fields.push({
- name: atisTitle,
- value: atis,
- inline: false,
- });
- }
+ const fields = [
+ {
+ name: 'Callsign',
+ value: `${callsign}`,
+ inline: false,
+ },
+ {
+ name: 'Logon Date & Time',
+ value: `${logon}`,
+ inline: true,
+ },
+ {
+ name: 'Rating',
+ value: `${rating}`,
+ inline: true,
+ },
+ ];
+ if (atis !== null) {
+ const atisTitle = 'Info';
+ fields.push({
+ name: atisTitle,
+ value: atis,
+ inline: false,
+ });
+ }
- return fields;
+ return fields;
};
-const handleLocaleDateTimeString = (date: Date) => date.toLocaleDateString('en-US', {
+const handleLocaleDateTimeString = (date: Date) =>
+ date.toLocaleDateString('en-US', {
hour: 'numeric',
minute: 'numeric',
weekday: 'short',
month: 'short',
day: 'numeric',
-});
+ });
-export async function handleVatsimObservers(interaction: ChatInputCommandInteraction<'cached'>, vatsimData: any, callsignSearch: any) {
- const vatsimAllObservers = vatsimData.controllers ? vatsimData.controllers.filter((controller: { facility: number; }) => controller.facility <= 0) : null;
+export async function handleVatsimObservers(
+ interaction: ChatInputCommandInteraction<'cached'>,
+ vatsimData: any,
+ callsignSearch: any,
+) {
+ const vatsimAllObservers = vatsimData.controllers
+ ? vatsimData.controllers.filter((controller: { facility: number }) => controller.facility <= 0)
+ : null;
- const vatsimControllerRatings = vatsimData.ratings ? vatsimData.ratings : null;
- const vatsimObservers = vatsimAllObservers ? vatsimAllObservers.filter((observer: { callsign: string | any[]; }) => observer.callsign.includes(callsignSearch)) : null;
+ const vatsimControllerRatings = vatsimData.ratings ? vatsimData.ratings : null;
+ const vatsimObservers = vatsimAllObservers
+ ? vatsimAllObservers.filter((observer: { callsign: string | any[] }) => observer.callsign.includes(callsignSearch))
+ : null;
- const { keys }: ObjectConstructor = Object;
+ const { keys }: ObjectConstructor = Object;
- const fields: EmbedField[] = [...vatsimObservers.sort((a: { rating: number; }, b: { rating: number; }) => b.rating - a.rating)].map((vatsimObserver) => {
- const { callsign, logon_time, text_atis, rating } = vatsimObserver;
- const logonTime = new Date(logon_time);
- const logonTimeString = handleLocaleDateTimeString(logonTime);
- const ratingDetail = vatsimControllerRatings.filter((ratingInfo: { id: any; }) => ratingInfo.id === rating);
- const { short, long } = ratingDetail[0];
- const ratingText = `${short} - ${long}`;
- const atisText = text_atis ? text_atis.join('\n') : null;
+ const fields: EmbedField[] = [
+ ...vatsimObservers.sort((a: { rating: number }, b: { rating: number }) => b.rating - a.rating),
+ ]
+ .map((vatsimObserver) => {
+ const { callsign, logon_time, text_atis, rating } = vatsimObserver;
+ const logonTime = new Date(logon_time);
+ const logonTimeString = handleLocaleDateTimeString(logonTime);
+ const ratingDetail = vatsimControllerRatings.filter((ratingInfo: { id: any }) => ratingInfo.id === rating);
+ const { short, long } = ratingDetail[0];
+ const ratingText = `${short} - ${long}`;
+ const atisText = text_atis ? text_atis.join('\n') : null;
- return observersListEmbedFields(callsign, logonTimeString, ratingText, atisText);
- }).slice(0, 5).flat();
+ return observersListEmbedFields(callsign, logonTimeString, ratingText, atisText);
+ })
+ .slice(0, 5)
+ .flat();
- const totalCount = keys(vatsimObservers).length;
- const shownCount = totalCount < 5 ? totalCount : 5;
+ const totalCount = keys(vatsimObservers).length;
+ const shownCount = totalCount < 5 ? totalCount : 5;
- return interaction.reply({ embeds: [listEmbed('Observers', fields, totalCount, shownCount, callsignSearch)] });
+ return interaction.reply({ embeds: [listEmbed('Observers', fields, totalCount, shownCount, callsignSearch)] });
}
diff --git a/src/commands/utils/vatsim/functions/vatsimPilots.ts b/src/commands/utils/vatsim/functions/vatsimPilots.ts
index e73c6300..f8157839 100644
--- a/src/commands/utils/vatsim/functions/vatsimPilots.ts
+++ b/src/commands/utils/vatsim/functions/vatsimPilots.ts
@@ -1,63 +1,76 @@
+/* eslint-disable */
+// Safer to be done separately due to complexity.
+
import { ChatInputCommandInteraction, EmbedField } from 'discord.js';
import { makeEmbed } from '../../../../lib';
-/* eslint-disable camelcase */
-
-const listEmbed = (type: string, fields: EmbedField[], totalCount: number, shownCount: number, callsign: string) => makeEmbed({
+const listEmbed = (type: string, fields: EmbedField[], totalCount: number, shownCount: number, callsign: string) =>
+ makeEmbed({
title: `VATSIM Data - ${callsign} - ${totalCount} ${type} online`,
description: `A list of ${shownCount} online ${type} matching ${callsign}.`,
fields,
-});
+ });
const pilotsListEmbedFields = (callsign: string, rating: string, flightPlan: any) => {
- const fields = [
- {
- name: 'Callsign',
- value: callsign,
- inline: false,
- },
- {
- name: 'Rating',
- value: rating,
- inline: true,
- },
- ];
-
- if (flightPlan !== null) {
- const { aircraft_short, departure, arrival } = flightPlan;
- fields.push(
- {
- name: 'Route',
- value: `${departure} - ${arrival}`,
- inline: true,
- },
- {
- name: 'Aircraft',
- value: `${aircraft_short}`,
- inline: true,
- },
- );
- }
-
- return fields;
+ const fields = [
+ {
+ name: 'Callsign',
+ value: callsign,
+ inline: false,
+ },
+ {
+ name: 'Rating',
+ value: rating,
+ inline: true,
+ },
+ ];
+
+ if (flightPlan !== null) {
+ const { aircraft_short, departure, arrival } = flightPlan;
+ fields.push(
+ {
+ name: 'Route',
+ value: `${departure} - ${arrival}`,
+ inline: true,
+ },
+ {
+ name: 'Aircraft',
+ value: `${aircraft_short}`,
+ inline: true,
+ },
+ );
+ }
+
+ return fields;
};
-export async function handleVatsimPilots(interaction: ChatInputCommandInteraction<'cached'>, vatsimData: any, callsignSearch: any) {
- const vatsimPilotRatings = vatsimData.pilot_ratings ? vatsimData.pilot_ratings : null;
- const vatsimPilots = vatsimData.pilots ? vatsimData.pilots.filter((pilot: { callsign: (string | null)[]; }) => pilot.callsign.includes(callsignSearch)) : null;
+export async function handleVatsimPilots(
+ interaction: ChatInputCommandInteraction<'cached'>,
+ vatsimData: any,
+ callsignSearch: any,
+) {
+ const vatsimPilotRatings = vatsimData.pilot_ratings ? vatsimData.pilot_ratings : null;
+ const vatsimPilots = vatsimData.pilots
+ ? vatsimData.pilots.filter((pilot: { callsign: (string | null)[] }) => pilot.callsign.includes(callsignSearch))
+ : null;
- const { keys }: ObjectConstructor = Object;
+ const { keys }: ObjectConstructor = Object;
- const fields: EmbedField[] = [...vatsimPilots.sort((a: { pilot_rating: number; }, b: { pilot_rating: number; }) => b.pilot_rating - a.pilot_rating)].map((vatsimPilot) => {
- const { callsign, pilot_rating, flight_plan } = vatsimPilot;
- const ratingDetail = vatsimPilotRatings.filter((ratingInfo: { id: number; }) => ratingInfo.id === pilot_rating);
- const { short_name, long_name } = ratingDetail[0];
- const ratingText = `${short_name} - ${long_name}`;
+ const fields: EmbedField[] = [
+ ...vatsimPilots.sort((a: { pilot_rating: number }, b: { pilot_rating: number }) => b.pilot_rating - a.pilot_rating),
+ ]
+ .map((vatsimPilot) => {
+ const { callsign, pilot_rating, flight_plan } = vatsimPilot;
+ const ratingDetail = vatsimPilotRatings.filter((ratingInfo: { id: number }) => ratingInfo.id === pilot_rating);
+ const { short_name, long_name } = ratingDetail[0];
+ const ratingText = `${short_name} - ${long_name}`;
- return pilotsListEmbedFields(callsign, ratingText, flight_plan);
- }).slice(0, 5).flat();
+ return pilotsListEmbedFields(callsign, ratingText, flight_plan);
+ })
+ .slice(0, 5)
+ .flat();
- const totalCount = keys(vatsimPilots).length;
- const shownCount = totalCount < 5 ? totalCount : 5;
+ const totalCount = keys(vatsimPilots).length;
+ const shownCount = totalCount < 5 ? totalCount : 5;
- return interaction.reply({ embeds: [listEmbed('Pilots', fields, totalCount, shownCount, callsignSearch)] });
+ return interaction.reply({ embeds: [listEmbed('Pilots', fields, totalCount, shownCount, callsignSearch)] });
}
diff --git a/src/commands/utils/vatsim/functions/vatsimStats.ts b/src/commands/utils/vatsim/functions/vatsimStats.ts
index a37c7c82..1e7e78a9 100644
--- a/src/commands/utils/vatsim/functions/vatsimStats.ts
+++ b/src/commands/utils/vatsim/functions/vatsimStats.ts
@@ -1,54 +1,84 @@
+/* eslint-disable */
+// Safer to be done separately due to complexity.
+
import { ChatInputCommandInteraction } from 'discord.js';
import { makeEmbed } from '../../../../lib';
-const statsEmbed = (pilots: string, controllers: string, atis: string, observers: string, callsign: any) => makeEmbed({
+const statsEmbed = (pilots: string, controllers: string, atis: string, observers: string, callsign: any) =>
+ makeEmbed({
title: callsign ? `VATSIM Data | Statistics for callsign ${callsign}` : 'VATSIM Data | Statistics',
- description: callsign ? `An overview of the current active Pilots, Controllers, ATIS and Observers matching ${callsign}.` : 'An overview of the current active Pilots, Controllers, ATIS and Observers.',
+ description: callsign
+ ? `An overview of the current active Pilots, Controllers, ATIS and Observers matching ${callsign}.`
+ : 'An overview of the current active Pilots, Controllers, ATIS and Observers.',
fields: [
- {
- name: 'Pilots',
- value: pilots,
- inline: true,
- },
- {
- name: 'Controllers',
- value: controllers,
- inline: true,
- },
- {
- name: 'ATIS',
- value: atis,
- inline: true,
- },
- {
- name: 'Observers',
- value: observers,
- inline: true,
- },
+ {
+ name: 'Pilots',
+ value: pilots,
+ inline: true,
+ },
+ {
+ name: 'Controllers',
+ value: controllers,
+ inline: true,
+ },
+ {
+ name: 'ATIS',
+ value: atis,
+ inline: true,
+ },
+ {
+ name: 'Observers',
+ value: observers,
+ inline: true,
+ },
],
-});
+ });
-export async function handleVatsimStats(interaction: ChatInputCommandInteraction<'cached'>, vatsimData: any, callsignSearch: any) {
- const vatsimAllControllers = vatsimData.controllers ? vatsimData.controllers.filter((controller: { facility: number; }) => controller.facility > 0) : null;
- const vatsimAllObservers = vatsimData.controllers ? vatsimData.controllers.filter((controller: { facility: number; }) => controller.facility <= 0) : null;
+export async function handleVatsimStats(
+ interaction: ChatInputCommandInteraction<'cached'>,
+ vatsimData: any,
+ callsignSearch: any,
+) {
+ const vatsimAllControllers = vatsimData.controllers
+ ? vatsimData.controllers.filter((controller: { facility: number }) => controller.facility > 0)
+ : null;
+ const vatsimAllObservers = vatsimData.controllers
+ ? vatsimData.controllers.filter((controller: { facility: number }) => controller.facility <= 0)
+ : null;
- if (!callsignSearch) {
- const vatsimPilotCount = vatsimData.pilots ? vatsimData.pilots.length : 0;
- const vatsimControllerCount = vatsimAllControllers ? vatsimAllControllers.length : 0;
- const vatsimAtisCount = vatsimData.atis ? vatsimData.atis.length : 0;
- const vatsimObserverCount = vatsimAllObservers ? vatsimAllObservers.length : 0;
+ if (!callsignSearch) {
+ const vatsimPilotCount = vatsimData.pilots ? vatsimData.pilots.length : 0;
+ const vatsimControllerCount = vatsimAllControllers ? vatsimAllControllers.length : 0;
+ const vatsimAtisCount = vatsimData.atis ? vatsimData.atis.length : 0;
+ const vatsimObserverCount = vatsimAllObservers ? vatsimAllObservers.length : 0;
- return interaction.reply({ embeds: [statsEmbed(vatsimPilotCount, vatsimControllerCount, vatsimAtisCount, vatsimObserverCount, null)] });
- }
- const vatsimPilots = vatsimData.pilots ? vatsimData.pilots.filter((pilot: { callsign: string | string[]; }) => pilot.callsign.includes(callsignSearch)) : null;
- const vatsimControllers = vatsimAllControllers ? vatsimAllControllers.filter((controller: { callsign: string | string[]; }) => controller.callsign.includes(callsignSearch)) : null;
- const vatsimAtis = vatsimData.atis ? vatsimData.atis.filter((atis: { callsign: string | string[]; }) => atis.callsign.includes(callsignSearch)) : null;
- const vatsimObservers = vatsimAllObservers ? vatsimAllObservers.filter((observer: { callsign: string | string[]; }) => observer.callsign.includes(callsignSearch)) : null;
+ return interaction.reply({
+ embeds: [statsEmbed(vatsimPilotCount, vatsimControllerCount, vatsimAtisCount, vatsimObserverCount, null)],
+ });
+ }
+ const vatsimPilots = vatsimData.pilots
+ ? vatsimData.pilots.filter((pilot: { callsign: string | string[] }) => pilot.callsign.includes(callsignSearch))
+ : null;
+ const vatsimControllers = vatsimAllControllers
+ ? vatsimAllControllers.filter((controller: { callsign: string | string[] }) =>
+ controller.callsign.includes(callsignSearch),
+ )
+ : null;
+ const vatsimAtis = vatsimData.atis
+ ? vatsimData.atis.filter((atis: { callsign: string | string[] }) => atis.callsign.includes(callsignSearch))
+ : null;
+ const vatsimObservers = vatsimAllObservers
+ ? vatsimAllObservers.filter((observer: { callsign: string | string[] }) =>
+ observer.callsign.includes(callsignSearch),
+ )
+ : null;
- const vatsimPilotCount = vatsimPilots ? vatsimPilots.length : 0;
- const vatsimControllerCount = vatsimControllers ? vatsimControllers.length : 0;
- const vatsimAtisCount = vatsimAtis ? vatsimAtis.length : 0;
- const vatsimObserverCount = vatsimObservers ? vatsimObservers.length : 0;
+ const vatsimPilotCount = vatsimPilots ? vatsimPilots.length : 0;
+ const vatsimControllerCount = vatsimControllers ? vatsimControllers.length : 0;
+ const vatsimAtisCount = vatsimAtis ? vatsimAtis.length : 0;
+ const vatsimObserverCount = vatsimObservers ? vatsimObservers.length : 0;
- return interaction.reply({ embeds: [statsEmbed(vatsimPilotCount, vatsimControllerCount, vatsimAtisCount, vatsimObserverCount, callsignSearch)] });
+ return interaction.reply({
+ embeds: [statsEmbed(vatsimPilotCount, vatsimControllerCount, vatsimAtisCount, vatsimObserverCount, callsignSearch)],
+ });
}
diff --git a/src/commands/utils/vatsim/vatsim.ts b/src/commands/utils/vatsim/vatsim.ts
index c1511937..a5fc98ff 100644
--- a/src/commands/utils/vatsim/vatsim.ts
+++ b/src/commands/utils/vatsim/vatsim.ts
@@ -1,3 +1,6 @@
+/* eslint-disable */
+// Safer to be done separately due to complexity.
+
import { ApplicationCommandOptionType, ApplicationCommandType, Colors } from 'discord.js';
import { makeEmbed, slashCommand, slashCommandStructure } from '../../../lib';
import { handleVatsimStats } from './functions/vatsimStats';
@@ -7,140 +10,143 @@ import { handleVatsimObservers } from './functions/vatsimObservers';
import { handleVatsimEvents } from './functions/vatsimEvents';
const data = slashCommandStructure({
- name: 'vatsim',
- description: 'Displays information about Vatsim.',
- type: ApplicationCommandType.ChatInput,
- options: [
+ name: 'vatsim',
+ description: 'Displays information about Vatsim.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'data',
+ description: 'Vatsim data.',
+ type: ApplicationCommandOptionType.SubcommandGroup,
+ options: [
+ {
+ name: 'stats',
+ description: 'Displays Vatsim stats.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'callsign',
+ description: 'Please provide a callsign to retrieve specific data.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ },
+ ],
+ },
+ {
+ name: 'controllers',
+ description: 'Displays Vatsim controllers and ATIS.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'callsign',
+ description: 'Please provide a callsign.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ },
+ ],
+ },
{
- name: 'data',
- description: 'Vatsim data.',
- type: ApplicationCommandOptionType.SubcommandGroup,
- options: [
- {
- name: 'stats',
- description: 'Displays Vatsim stats.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'callsign',
- description: 'Please provide a callsign to retrieve specific data.',
- type: ApplicationCommandOptionType.String,
- required: false,
- },
- ],
- },
- {
- name: 'controllers',
- description: 'Displays Vatsim controllers and ATIS.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'callsign',
- description: 'Please provide a callsign.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- ],
- },
- {
- name: 'pilots',
- description: 'Displays Vatsim pilots.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'callsign',
- description: 'Please provide a callsign.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- ],
- },
- {
- name: 'observers',
- description: 'Displays Vatsim observers.',
- type: ApplicationCommandOptionType.Subcommand,
- options: [
- {
- name: 'callsign',
- description: 'Please provide a callsign.',
- type: ApplicationCommandOptionType.String,
- required: true,
- },
- ],
- },
- ],
+ name: 'pilots',
+ description: 'Displays Vatsim pilots.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'callsign',
+ description: 'Please provide a callsign.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ },
+ ],
},
{
- name: 'events',
- description: 'Displays Vatsim events.',
- type: ApplicationCommandOptionType.Subcommand,
+ name: 'observers',
+ description: 'Displays Vatsim observers.',
+ type: ApplicationCommandOptionType.Subcommand,
+ options: [
+ {
+ name: 'callsign',
+ description: 'Please provide a callsign.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ },
+ ],
},
- ],
+ ],
+ },
+ {
+ name: 'events',
+ description: 'Displays Vatsim events.',
+ type: ApplicationCommandOptionType.Subcommand,
+ },
+ ],
});
-const fetchErrorEmbed = (error: any) => makeEmbed({
+const fetchErrorEmbed = (error: any) =>
+ makeEmbed({
title: 'VATSIM Data - Fetching data failure',
description: `Could not fetch the VATSIM data from the VATSIM API service: ${error}`,
color: Colors.Red,
-});
+ });
export default slashCommand(data, async ({ interaction }) => {
- // Fetch VATSIM data
-
- let vatsimData;
- try {
- vatsimData = await fetch('https://data.vatsim.net/v3/vatsim-data.json').then((response) => {
- if (response.ok) {
- return response.json();
- }
- throw new Error(response.statusText);
- });
- } catch (error) {
- await interaction.reply({ embeds: [fetchErrorEmbed(error)], ephemeral: true });
- return;
- }
+ // Fetch VATSIM data
- // Grap the callsign from the interaction
+ let vatsimData;
+ try {
+ vatsimData = await fetch('https://data.vatsim.net/v3/vatsim-data.json').then((response) => {
+ if (response.ok) {
+ return response.json();
+ }
+ throw new Error(response.statusText);
+ });
+ } catch (error) {
+ await interaction.reply({ embeds: [fetchErrorEmbed(error)], ephemeral: true });
+ return;
+ }
- let callsign = interaction.options.getString('callsign');
- let callsignSearch;
+ // Grap the callsign from the interaction
- if (callsign) {
- callsign = callsign.toUpperCase();
+ let callsign = interaction.options.getString('callsign');
+ let callsignSearch;
- const regexCheck = /^["']?(?[\w-]+)?["']?\s*$/;
- const regexMatches = callsign.match(regexCheck);
+ if (callsign) {
+ callsign = callsign.toUpperCase();
- if (!regexMatches || !regexMatches.groups || !regexMatches.groups.callsignSearch) {
- // eslint-disable-next-line consistent-return
- return interaction.reply({ content: 'You need to provide a valid callsign or part of a callsign to search for', ephemeral: true });
- }
+ const regexCheck = /^["']?(?[\w-]+)?["']?\s*$/;
+ const regexMatches = callsign.match(regexCheck);
- callsignSearch = regexMatches.groups.callsignSearch;
+ if (!regexMatches || !regexMatches.groups || !regexMatches.groups.callsignSearch) {
+ return interaction.reply({
+ content: 'You need to provide a valid callsign or part of a callsign to search for',
+ ephemeral: true,
+ });
}
- // Handle the subcommands
+ callsignSearch = regexMatches.groups.callsignSearch;
+ }
- const subcommandName = interaction.options.getSubcommand();
+ // Handle the subcommands
- switch (subcommandName) {
+ const subcommandName = interaction.options.getSubcommand();
+
+ switch (subcommandName) {
case 'stats':
- await handleVatsimStats(interaction, vatsimData, callsignSearch);
- break;
+ await handleVatsimStats(interaction, vatsimData, callsignSearch);
+ break;
case 'controllers':
- await handleVatsimControllers(interaction, vatsimData, callsignSearch);
- break;
+ await handleVatsimControllers(interaction, vatsimData, callsignSearch);
+ break;
case 'pilots':
- await handleVatsimPilots(interaction, vatsimData, callsignSearch);
- break;
+ await handleVatsimPilots(interaction, vatsimData, callsignSearch);
+ break;
case 'observers':
- await handleVatsimObservers(interaction, vatsimData, callsignSearch);
- break;
+ await handleVatsimObservers(interaction, vatsimData, callsignSearch);
+ break;
case 'events':
- await handleVatsimEvents(interaction);
- break;
+ await handleVatsimEvents(interaction);
+ break;
default:
- await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
- }
+ await interaction.reply({ content: 'Unknown subcommand', ephemeral: true });
+ }
});
diff --git a/src/commands/utils/wolframAlpha.ts b/src/commands/utils/wolframAlpha.ts
index 71ed2744..5ea57376 100644
--- a/src/commands/utils/wolframAlpha.ts
+++ b/src/commands/utils/wolframAlpha.ts
@@ -1,120 +1,153 @@
import { ApplicationCommandOptionType, ApplicationCommandType, Colors } from 'discord.js';
import { slashCommand, slashCommandStructure, makeEmbed, makeLines, Logger } from '../../lib';
+import { Response } from 'node-fetch';
const data = slashCommandStructure({
- name: 'wolframalpha',
- description: 'Queries the Wolfram Alpha API.',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'query',
- description: 'Please provide a query. For example: `.wa How much is 1 + 1?`.',
- type: ApplicationCommandOptionType.String,
- required: true,
- }],
+ name: 'wolframalpha',
+ description: 'Queries the Wolfram Alpha API.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'query',
+ description: 'Please provide a query. For example: `.wa How much is 1 + 1?`.',
+ type: ApplicationCommandOptionType.String,
+ required: true,
+ },
+ ],
});
const noQueryEmbed = makeEmbed({
- title: 'Wolfram Alpha Error | Missing Query',
- description: 'Please provide a query. For example: `.wa How much is 1 + 1?`',
- color: Colors.Red,
+ title: 'Wolfram Alpha Error | Missing Query',
+ description: 'Please provide a query. For example: `.wa How much is 1 + 1?`',
+ color: Colors.Red,
});
const WOLFRAMALPHA_API_URL = 'https://api.wolframalpha.com/v2/query?';
const WOLFRAMALPHA_QUERY_URL = 'https://www.wolframalpha.com/input/?';
export default slashCommand(data, async ({ interaction }) => {
- await interaction.deferReply();
+ await interaction.deferReply();
- const wolframAlphaToken = process.env.WOLFRAMALPHA_TOKEN;
+ const wolframAlphaToken = process.env.WOLFRAMALPHA_TOKEN;
- if (!wolframAlphaToken) {
- const noTokenEmbed = makeEmbed({
- title: 'Error | Wolfram Alpha',
- description: 'Wolfram Alpha token not found.',
- color: Colors.Red,
- });
- return interaction.followUp({ embeds: [noTokenEmbed], ephemeral: true });
- }
+ if (!wolframAlphaToken) {
+ const noTokenEmbed = makeEmbed({
+ title: 'Error | Wolfram Alpha',
+ description: 'Wolfram Alpha token not found.',
+ color: Colors.Red,
+ });
+ return interaction.followUp({ embeds: [noTokenEmbed], ephemeral: true });
+ }
- const query = interaction.options.getString('query');
+ const query = interaction.options.getString('query');
- if (!query) return interaction.followUp({ embeds: [noQueryEmbed], ephemeral: true });
+ if (!query) return interaction.followUp({ embeds: [noQueryEmbed], ephemeral: true });
- const params = {
- appid: wolframAlphaToken,
- input: query,
- format: 'plaintext',
- output: 'JSON',
- };
+ const params = {
+ appid: wolframAlphaToken,
+ input: query,
+ format: 'plaintext',
+ output: 'JSON',
+ };
- const searchParams = new URLSearchParams(params);
+ const searchParams = new URLSearchParams(params);
- try {
- const response = await fetch(`${WOLFRAMALPHA_API_URL}${searchParams.toString()}`)
- .then((res) => res.json());
+ try {
+ const response = (await fetch(`${WOLFRAMALPHA_API_URL}${searchParams.toString()}`).then((res) =>
+ res.json(),
+ )) as WolframAlphaResponse;
- if (response.error) {
- const errorEmbed = makeEmbed({
- title: 'Wolfram Alpha Error',
- description: response.error,
- color: Colors.Red,
- });
- return interaction.followUp({ embeds: [errorEmbed], ephemeral: true });
- }
+ if (response.error) {
+ const errorEmbed = makeEmbed({
+ title: 'Wolfram Alpha Error',
+ description: response.error.toString(),
+ color: Colors.Red,
+ });
+ return interaction.followUp({ embeds: [errorEmbed], ephemeral: true });
+ }
- if (response.queryresult.success === true) {
- const podTexts: string[] = [];
- response.queryresult.pods.forEach((pod: any) => {
- if (pod.id !== 'Input' && pod.primary === true) {
- const results: string[] = [];
- pod.subpods.forEach((subpod: any) => {
- results.push(subpod.plaintext);
- });
- if (results.length > 0) {
- podTexts.push(`**${pod.title}:** \n${results.join('\n')}`);
- }
- }
- });
- if (podTexts.length > 0) {
- const result = podTexts.join('\n\n');
- const queryParams = new URLSearchParams({ i: query });
-
- const waEmbed = makeEmbed({
- description: makeLines([
- `**Query:** ${query}`,
- '',
- result,
- '',
- `[Web Result](${WOLFRAMALPHA_QUERY_URL}${queryParams.toString()})`,
- ]),
- });
-
- return interaction.followUp({ embeds: [waEmbed] });
- }
- const noResultsEmbed = makeEmbed({
- title: 'Wolfram Alpha Error | No Results',
- description: makeLines([
- 'No results were found for your query.',
- ]),
- color: Colors.Red,
- });
- return interaction.followUp({ embeds: [noResultsEmbed], ephemeral: true });
+ if (response.queryresult.success === true) {
+ const podTexts: string[] = [];
+ response.queryresult.pods.forEach((pod: Pod) => {
+ if (pod.id !== 'Input' && pod.primary === true) {
+ const results: string[] = [];
+ pod.subpods.forEach((subpod: SubPod) => {
+ results.push(subpod.plaintext);
+ });
+ if (results.length > 0) {
+ podTexts.push(`**${pod.title}:** \n${results.join('\n')}`);
+ }
}
- const obscureQueryEmbed = makeEmbed({
- title: 'Wolfram Alpha Error | Could not understand query',
- description: makeLines([
- 'Wolfram Alpha could not understand your query.',
- ]),
- color: Colors.Red,
- });
- return interaction.followUp({ embeds: [obscureQueryEmbed], ephemeral: true });
- } catch (e) {
- Logger.error('wolframalpha:', e);
- const fetchErrorEmbed = makeEmbed({
- title: 'Wolfram Alpha | Fetch Error',
- description: 'There was an error fetching your request. Please try again later.',
- color: Colors.Red,
+ });
+ if (podTexts.length > 0) {
+ const result = podTexts.join('\n\n');
+ const queryParams = new URLSearchParams({ i: query });
+
+ const waEmbed = makeEmbed({
+ description: makeLines([
+ `**Query:** ${query}`,
+ '',
+ result,
+ '',
+ `[Web Result](${WOLFRAMALPHA_QUERY_URL}${queryParams.toString()})`,
+ ]),
});
- return interaction.followUp({ embeds: [fetchErrorEmbed], ephemeral: true });
+
+ return interaction.followUp({ embeds: [waEmbed] });
+ }
+ const noResultsEmbed = makeEmbed({
+ title: 'Wolfram Alpha Error | No Results',
+ description: makeLines(['No results were found for your query.']),
+ color: Colors.Red,
+ });
+ return interaction.followUp({ embeds: [noResultsEmbed], ephemeral: true });
}
+ const obscureQueryEmbed = makeEmbed({
+ title: 'Wolfram Alpha Error | Could not understand query',
+ description: makeLines(['Wolfram Alpha could not understand your query.']),
+ color: Colors.Red,
+ });
+ return interaction.followUp({ embeds: [obscureQueryEmbed], ephemeral: true });
+ } catch (e) {
+ Logger.error('wolframalpha:', e);
+ const fetchErrorEmbed = makeEmbed({
+ title: 'Wolfram Alpha | Fetch Error',
+ description: 'There was an error fetching your request. Please try again later.',
+ color: Colors.Red,
+ });
+ return interaction.followUp({ embeds: [fetchErrorEmbed], ephemeral: true });
+ }
});
+
+/**
+ * This is a very hacky approach to satisfy TS-ESLint. However, there are no type packages or API wrappers that are somewhat up-to-date.
+ * Therefore, I would recommend using our own types.
+ * Note, that the types below are not complete and only cover our current needs.
+ * Changes to the JSON data returned by the API may break this code, whether or not proper typing is used.
+ * Therefore, this approach is probably better than simply disabling ESLint for this file.
+ * See WolframAlpha API docs: https://products.wolframalpha.com/api/documentation
+ */
+
+interface WolframAlphaResponse extends Response {
+ queryresult: QueryResult;
+ error?: string;
+}
+
+interface QueryResult {
+ success: boolean;
+ error: boolean;
+ pods: Pod[];
+}
+
+interface Pod {
+ title: string;
+ id: string;
+ primary: boolean;
+ subpods: SubPod[];
+}
+
+interface SubPod {
+ title: string;
+ plaintext: string;
+ primary: boolean;
+}
diff --git a/src/commands/utils/zulu.ts b/src/commands/utils/zulu.ts
index 74575a05..ed827c23 100644
--- a/src/commands/utils/zulu.ts
+++ b/src/commands/utils/zulu.ts
@@ -3,41 +3,40 @@ import moment from 'moment';
import { slashCommand, slashCommandStructure, makeEmbed, makeLines } from '../../lib';
const data = slashCommandStructure({
- name: 'zulu',
- description: 'Get the current time at a given UTC-offset timezone.',
- type: ApplicationCommandType.ChatInput,
- options: [{
- name: 'offset',
- description: 'Please provide a timezone within UTC-12 and UTC+14.',
- type: ApplicationCommandOptionType.String,
- required: false,
- }],
+ name: 'zulu',
+ description: 'Get the current time at a given UTC-offset timezone.',
+ type: ApplicationCommandType.ChatInput,
+ options: [
+ {
+ name: 'offset',
+ description: 'Please provide a timezone within UTC-12 and UTC+14.',
+ type: ApplicationCommandOptionType.String,
+ required: false,
+ },
+ ],
});
const dateFormat = 'HH:mm (LT)';
export default slashCommand(data, async ({ interaction }) => {
- let utcOffset = interaction.options.getString('offset') ?? '0';
+ let utcOffset = interaction.options.getString('offset') ?? '0';
- utcOffset = utcOffset.replace(/^[+-]+/, (match) => match[0]);
- const numericOffset = parseInt(utcOffset);
- const sign = utcOffset.startsWith('-') ? '-' : '+';
+ utcOffset = utcOffset.replace(/^[+-]+/, (match) => match[0]);
+ const numericOffset = parseInt(utcOffset);
+ const sign = utcOffset.startsWith('-') ? '-' : '+';
- if (Number.isNaN(numericOffset)
- || numericOffset < -12
- || numericOffset > 14) {
- const invalidEmbed = makeEmbed({
- title: 'Zulu Error | Invalid Offset',
- description: makeLines([
- 'Please provide a timezone within UTC-12 and UTC+14.',
- 'For example: `/zulu -5`.',
- ]),
- color: Colors.Red,
- });
- return interaction.reply({ embeds: [invalidEmbed], ephemeral: true });
- }
+ if (Number.isNaN(numericOffset) || numericOffset < -12 || numericOffset > 14) {
+ const invalidEmbed = makeEmbed({
+ title: 'Zulu Error | Invalid Offset',
+ description: makeLines(['Please provide a timezone within UTC-12 and UTC+14.', 'For example: `/zulu -5`.']),
+ color: Colors.Red,
+ });
+ return interaction.reply({ embeds: [invalidEmbed], ephemeral: true });
+ }
- const formattedOffset = `${sign}${Math.abs(numericOffset)}`;
+ const formattedOffset = `${sign}${Math.abs(numericOffset)}`;
- return interaction.reply({ content: `It is ${moment().utc().add(utcOffset, 'hours').format(dateFormat)} in that timezone (UTC${formattedOffset}).` });
+ return interaction.reply({
+ content: `It is ${moment().utc().add(utcOffset, 'hours').format(dateFormat)} in that timezone (UTC${formattedOffset}).`,
+ });
});
diff --git a/src/events/autocompleteHandler.ts b/src/events/autocompleteHandler.ts
index 8790d095..b1a5e295 100644
--- a/src/events/autocompleteHandler.ts
+++ b/src/events/autocompleteHandler.ts
@@ -4,38 +4,35 @@ import commandArray from '../commands';
const commandMap = new Map();
for (const cmd of commandArray) {
- commandMap.set(cmd.meta.name, cmd);
+ commandMap.set(cmd.meta.name, cmd);
}
export default event(Events.InteractionCreate, async ({ log, client }, interaction) => {
- if (!interaction.isAutocomplete()) {
- return;
- }
-
- if (!interaction.inCachedGuild()) {
- return;
- }
+ if (!interaction.isAutocomplete()) {
+ return;
+ }
- try {
- const { commandName } = interaction as {
- commandName: any;
- options: any;
- };
+ if (!interaction.inCachedGuild()) {
+ return;
+ }
- const command = commandMap.get(commandName);
+ try {
+ const { commandName } = interaction;
- if (!command) {
- log(`Could not resolve the command with name "${commandName}"`);
- return;
- }
+ const command = commandMap.get(commandName);
- if (!command.autocompleteCallback) {
- log(`Command has no autocomplete, ignoring. Command: ${command.meta.name}`);
- return;
- }
+ if (!command) {
+ log(`Could not resolve the command with name "${commandName}"`);
+ return;
+ }
- await command.autocompleteCallback({ client, log, interaction });
- } catch (error) {
- log('[Autocomplete Error]', error);
+ if (!command.autocompleteCallback) {
+ log(`Command has no autocomplete, ignoring. Command: ${command.meta.name}`);
+ return;
}
+
+ await command.autocompleteCallback({ client, log, interaction });
+ } catch (error) {
+ log('[Autocomplete Error]', error);
+ }
});
diff --git a/src/events/buttonHandlers/buttonHandler.ts b/src/events/buttonHandlers/buttonHandler.ts
index c2cdac81..7607b4d6 100644
--- a/src/events/buttonHandlers/buttonHandler.ts
+++ b/src/events/buttonHandlers/buttonHandler.ts
@@ -1,33 +1,40 @@
+import { ButtonComponent } from 'discord.js';
import { event, Events } from '../../lib';
import { handleRoleAssignment } from './functions/handleRoleAssignment';
export default event(Events.InteractionCreate, async ({ log }, interaction) => {
- if (!interaction.isButton()) return;
+ if (!interaction.isButton()) return;
- log('Button Handler: Button pressed');
+ log('Button Handler: Button pressed');
- const { customId, component, user } = interaction;
+ const component = interaction.component as ButtonComponent;
+ const { customId, user } = interaction;
- const buttonLabel = component?.label;
+ const buttonLabel = component.label;
- try {
- const [prefix, ...params] = interaction.customId.split('_');
+ try {
+ const [prefix, ...params] = interaction.customId.split('_');
- switch (prefix) {
- case 'roleAssignment':
- const [roleID] = params;
- await handleRoleAssignment(interaction, roleID);
- log(`Button Handler: Role assignment button pressed by ${user.tag} (${user.id}). roleID: ${roleID}`);
- break;
- default:
- if (buttonLabel) {
- log(`Button Handler: Custom ID not matched. Skipping...\nCustom ID: ${customId}, Label: ${buttonLabel}, User: ${user.tag}, User ID: ${user.id}`);
- } else {
- log(`Button Handler: Custom ID not matched. Skipping...\nCustom ID: ${customId}, Label: null, User: ${user.tag}, User ID: ${user.id}`);
- }
- return;
+ switch (prefix) {
+ case 'roleAssignment': {
+ const [roleID] = params;
+ await handleRoleAssignment(interaction, roleID);
+ log(`Button Handler: Role assignment button pressed by ${user.tag} (${user.id}). roleID: ${roleID}`);
+ break;
+ }
+ default:
+ if (buttonLabel) {
+ log(
+ `Button Handler: Custom ID not matched. Skipping...\nCustom ID: ${customId}, Label: ${buttonLabel}, User: ${user.tag}, User ID: ${user.id}`,
+ );
+ } else {
+ log(
+ `Button Handler: Custom ID not matched. Skipping...\nCustom ID: ${customId}, Label: null, User: ${user.tag}, User ID: ${user.id}`,
+ );
}
- } catch (error) {
- log('Button Handler: Error handling button press', error);
+ return;
}
+ } catch (error) {
+ log('Button Handler: Error handling button press', error);
+ }
});
diff --git a/src/events/buttonHandlers/functions/handleRoleAssignment.ts b/src/events/buttonHandlers/functions/handleRoleAssignment.ts
index 53233829..25570602 100644
--- a/src/events/buttonHandlers/functions/handleRoleAssignment.ts
+++ b/src/events/buttonHandlers/functions/handleRoleAssignment.ts
@@ -2,40 +2,43 @@ import { ButtonInteraction, GuildMember } from 'discord.js';
import { constantsConfig, Logger } from '../../../lib';
export async function handleRoleAssignment(interaction: ButtonInteraction, roleID: string) {
- await interaction.deferReply({ ephemeral: true });
+ await interaction.deferReply({ ephemeral: true });
- try {
- // Find the role object based on the customId
- let role = null;
- for (const group of constantsConfig.roleAssignmentIds) {
- role = group.roles.find((r) => r.id === roleID);
- if (role) break; // Stop searching if the role is found in any group
- }
+ try {
+ // Find the role object based on the customId
+ let role = null;
+ for (const group of constantsConfig.roleAssignmentIds) {
+ role = group.roles.find((r) => r.id === roleID);
+ if (role) break; // Stop searching if the role is found in any group
+ }
- if (!role) {
- Logger.error('Role Assignment: Role not found');
- interaction.editReply({ content: 'I couldn\'t find that role' });
- return;
- }
+ if (!role) {
+ Logger.error('Role Assignment: Role not found');
+ await interaction.editReply({ content: "I couldn't find that role" });
+ return;
+ }
- if (!interaction.member) {
- Logger.error('Role Assignment: Interaction member is null');
- return;
- }
+ if (!interaction.member) {
+ Logger.error('Role Assignment: Interaction member is null');
+ return;
+ }
- const member = interaction.member as GuildMember;
+ const member = interaction.member as GuildMember;
- const hasRole = member.roles.cache.has(role.id);
+ const hasRole = member.roles.cache.has(role.id);
- if (hasRole) {
- await member.roles.remove(role.id);
- await interaction.editReply(`The role <@&${role.id}> has been removed.`);
- } else {
- await member.roles.add(role.id);
- await interaction.editReply(`The role <@&${role.id}> has been added.`);
- }
- } catch (error) {
- Logger.error(error);
- await interaction.editReply({ content: 'Something went wrong, this role may no longer exist. Please try again. The error message has been logged.' });
+ if (hasRole) {
+ await member.roles.remove(role.id);
+ await interaction.editReply(`The role <@&${role.id}> has been removed.`);
+ } else {
+ await member.roles.add(role.id);
+ await interaction.editReply(`The role <@&${role.id}> has been added.`);
}
+ } catch (error) {
+ Logger.error(error);
+ await interaction.editReply({
+ content:
+ 'Something went wrong, this role may no longer exist. Please try again. The error message has been logged.',
+ });
+ }
}
diff --git a/src/events/contextInteractionHandler.ts b/src/events/contextInteractionHandler.ts
index d8afd555..a4c9de3c 100644
--- a/src/events/contextInteractionHandler.ts
+++ b/src/events/contextInteractionHandler.ts
@@ -1,47 +1,43 @@
import { Color, ContextMenuCommand, event, Events, makeEmbed, Reply } from '../lib';
import contextArray from '../commands/context';
-const contextMap = new Map(
- contextArray.map((c) => [c.meta.name, c]),
-);
+const contextMap = new Map(contextArray.map((c) => [c.meta.name, c]));
export default event(Events.InteractionCreate, async ({ log, client }, interaction) => {
- if (!interaction.isContextMenuCommand()) {
- return;
+ if (!interaction.isContextMenuCommand()) {
+ return;
+ }
+
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply(Reply('This bot can only be used in a server!', Color.Error));
+ return;
+ }
+
+ try {
+ const contextName = interaction.commandName;
+ const context = contextMap.get(contextName);
+
+ if (!context) {
+ log(`Could not resolve the context with name "${contextName}"`);
+ return;
}
- if (!interaction.inCachedGuild()) {
- await interaction.reply(
- Reply('This bot can only be used in a server!', Color.Error),
- );
- return;
- }
-
- try {
- const contextName = interaction.commandName;
- const context = contextMap.get(contextName);
-
- if (!context) {
- log(`Could not resolve the context with name "${contextName}"`);
- return;
- }
-
- log(`[Context Command]: ${contextName} was executed by ${interaction.user.tag}`);
+ log(`[Context Command]: ${contextName} was executed by ${interaction.user.tag}`);
- await context.callback({ client, log, interaction });
- } catch (error) {
- const errorEmbed = makeEmbed({
- title: 'An error occurred while executing this context command.',
- description: `${error}`,
- color: Color.Error,
- });
+ await context.callback({ client, log, interaction });
+ } catch (error) {
+ const errorEmbed = makeEmbed({
+ title: 'An error occurred while executing this context command.',
+ description: String(error),
+ color: Color.Error,
+ });
- log('[Context Error]', error);
+ log('[Context Error]', error);
- await interaction.followUp({ embeds: [errorEmbed] });
+ await interaction.followUp({ embeds: [errorEmbed] });
- if (interaction.deferred || interaction.replied) {
- log('Interaction was already replied to or deferred, ignoring');
- }
+ if (interaction.deferred || interaction.replied) {
+ log('Interaction was already replied to or deferred, ignoring');
}
+ }
});
diff --git a/src/events/index.ts b/src/events/index.ts
index 684f5870..af732465 100644
--- a/src/events/index.ts
+++ b/src/events/index.ts
@@ -12,14 +12,14 @@ import autocompleteHandler from './autocompleteHandler';
import buttonHandler from './buttonHandlers/buttonHandler';
export default [
- ready,
- scamLogs,
- detectBan,
- slashCommandHandler,
- contextInteractionHandler,
- messageDelete,
- messageUpdate,
- messageCreateHandler,
- autocompleteHandler,
- buttonHandler,
+ ready,
+ scamLogs,
+ detectBan,
+ slashCommandHandler,
+ contextInteractionHandler,
+ messageDelete,
+ messageUpdate,
+ messageCreateHandler,
+ autocompleteHandler,
+ buttonHandler,
] as Event[];
diff --git a/src/events/logging/detectBan.ts b/src/events/logging/detectBan.ts
index d9ae940a..0019c7ce 100644
--- a/src/events/logging/detectBan.ts
+++ b/src/events/logging/detectBan.ts
@@ -1,6 +1,6 @@
//This detects non bot bans and sends a message to the mod logs channel
-import { AuditLogEvent, bold, Colors, GuildBan, TextChannel, User } from 'discord.js';
+import { AuditLogEvent, bold, Colors, TextChannel, User } from 'discord.js';
import moment from 'moment/moment';
import mongoose from 'mongoose';
import { constantsConfig, event, Events, Infraction, Logger, makeEmbed, makeLines } from '../../lib';
@@ -8,191 +8,197 @@ import { constantsConfig, event, Events, Infraction, Logger, makeEmbed, makeLine
const MAX_RETRIES = 5;
const SLEEP_TIMER = 0.5 * 1000;
-const noLogEmbed = (user: User, guildName: string) => makeEmbed({
+const noLogEmbed = (user: User, guildName: string) =>
+ makeEmbed({
color: Colors.Red,
author: {
- name: `[BANNED] ${user.tag}`,
- iconURL: user.displayAvatarURL(),
+ name: `[BANNED] ${user.tag}`,
+ iconURL: user.displayAvatarURL(),
},
description: makeLines([
- `${user.tag} was banned from ${guildName} but no audit log could be found.`,
- '',
- bold('NOTE - This was a non bot ban.'),
- '',
- `Please remember to send the user the reason they were banned and the ban appeal form - ${process.env.BAN_APPEAL_URL}`,
+ `${user.tag} was banned from ${guildName} but no audit log could be found.`,
+ '',
+ bold('NOTE - This was a non bot ban.'),
+ '',
+ `Please remember to send the user the reason they were banned and the ban appeal form - ${process.env.BAN_APPEAL_URL}`,
]),
footer: { text: `User ID: ${user.id}` },
-});
+ });
-const modLogEmbed = (user: User, executor: User, reason: string, formattedDate: string) => makeEmbed({
+const modLogEmbed = (user: User, executor: User, reason: string, formattedDate: string) =>
+ makeEmbed({
color: Colors.Red,
author: {
- name: `[BANNED] ${user.tag}`,
- iconURL: user.displayAvatarURL(),
+ name: `[BANNED] ${user.tag}`,
+ iconURL: user.displayAvatarURL(),
},
description: makeLines([
- bold('NOTE - This was a non bot ban.'),
- '',
- `Please remember to send the user the reason they were banned and the ban appeal form - ${process.env.BAN_APPEAL_URL}`,
+ bold('NOTE - This was a non bot ban.'),
+ '',
+ `Please remember to send the user the reason they were banned and the ban appeal form - ${process.env.BAN_APPEAL_URL}`,
]),
fields: [
- {
- name: 'User',
- value: `${user}`,
- },
- {
- name: 'Moderator',
- value: `${executor}`,
- },
- {
- name: 'Reason',
- value: reason || 'No reason provided',
- },
- {
- name: 'Days of messages deleted',
- value: 'Unavailable with a non bot ban',
- },
- {
- name: 'Date',
- value: formattedDate,
- },
+ {
+ name: 'User',
+ value: `${user.toString()}`,
+ },
+ {
+ name: 'Moderator',
+ value: `${executor.toString()}`,
+ },
+ {
+ name: 'Reason',
+ value: reason || 'No reason provided',
+ },
+ {
+ name: 'Days of messages deleted',
+ value: 'Unavailable with a non bot ban',
+ },
+ {
+ name: 'Date',
+ value: formattedDate,
+ },
],
footer: { text: `User ID: ${user.id}` },
-});
+ });
-const userBannedIncompleteEmbed = (user: User, formattedDate: string) => makeEmbed({
+const userBannedIncompleteEmbed = (user: User, formattedDate: string) =>
+ makeEmbed({
color: Colors.Red,
author: {
- name: `[BANNED] ${user.tag}`,
- iconURL: user.displayAvatarURL(),
+ name: `[BANNED] ${user.tag}`,
+ iconURL: user.displayAvatarURL(),
},
description: makeLines([
- bold('NOTE - This was a non bot ban.'),
- '',
- `Please remember to send the user the reason they were banned and the ban appeal form - ${process.env.BAN_APPEAL_URL}`,
+ bold('NOTE - This was a non bot ban.'),
+ '',
+ `Please remember to send the user the reason they were banned and the ban appeal form - ${process.env.BAN_APPEAL_URL}`,
]),
fields: [
- {
- name: 'Member',
- value: user.tag,
- },
- {
- name: 'Moderator',
- value: 'Unavailable - Audit log incomplete',
- },
- {
- name: 'Reason',
- value: 'Unavailable - Audit log incomplete',
- },
- {
- name: 'Days of messages deleted',
- value: 'Unavailable with a non bot ban',
- },
- {
- name: 'Date',
- value: formattedDate,
- },
+ {
+ name: 'Member',
+ value: user.tag,
+ },
+ {
+ name: 'Moderator',
+ value: 'Unavailable - Audit log incomplete',
+ },
+ {
+ name: 'Reason',
+ value: 'Unavailable - Audit log incomplete',
+ },
+ {
+ name: 'Days of messages deleted',
+ value: 'Unavailable with a non bot ban',
+ },
+ {
+ name: 'Date',
+ value: formattedDate,
+ },
],
footer: { text: `User ID: ${user.id}` },
-});
+ });
const logFailed = makeEmbed({
- title: 'Non Bot Ban - Failed to log',
- description: 'Failed to log the ban to the database, audit log could have been unavailable.',
- color: Colors.Red,
+ title: 'Non Bot Ban - Failed to log',
+ description: 'Failed to log the ban to the database, audit log could have been unavailable.',
+ color: Colors.Red,
});
export default event(Events.GuildBanAdd, async (_, msg) => {
- Logger.debug('Starting Ban Handler');
-
- const guildBanAdd = msg as GuildBan;
-
- if (guildBanAdd.guild === null) {
- // DMs
- return;
+ Logger.debug('Starting Ban Handler');
+
+ const guildBanAdd = msg;
+
+ if (guildBanAdd.guild === null) {
+ // DMs
+ return;
+ }
+
+ const modLogsChannel = guildBanAdd.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel | null;
+ if (!modLogsChannel) {
+ // Exit as can't post
+ return;
+ }
+
+ const currentDate = new Date();
+ const formattedDate: string = moment(currentDate).utcOffset(0).format();
+
+ let executor;
+ let reason;
+ let target;
+ let retryCount = MAX_RETRIES;
+
+ // No performance impact by await.
+ /* eslint-disable no-await-in-loop */
+ do {
+ Logger.debug(`Ban Handler - Finding Audit Log entry retries left: ${retryCount}`);
+ if (retryCount < MAX_RETRIES) {
+ await new Promise((f) => setTimeout(f, SLEEP_TIMER));
}
- const modLogsChannel = await guildBanAdd.guild.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel | null;
- if (!modLogsChannel) {
- // Exit as can't post
- return;
+ const fetchedLogs = await guildBanAdd.guild.fetchAuditLogs({
+ limit: 1,
+ type: AuditLogEvent.MemberBanAdd,
+ });
+ const banLog = fetchedLogs.entries.first();
+ if (banLog) {
+ ({ executor, reason, target } = banLog);
}
- const currentDate = new Date();
- const formattedDate: string = moment(currentDate)
- .utcOffset(0)
- .format();
-
- let executor;
- let reason;
- let target;
- let retryCount = MAX_RETRIES;
- do {
- Logger.debug(`Ban Handler - Finding Audit Log entry retries left: ${retryCount}`);
- if (retryCount < MAX_RETRIES) {
- // eslint-disable-next-line no-await-in-loop
- await new Promise((f) => setTimeout(f, SLEEP_TIMER));
- }
- // eslint-disable-next-line no-await-in-loop
- const fetchedLogs = await guildBanAdd.guild.fetchAuditLogs({
- limit: 1,
- type: AuditLogEvent.MemberBanAdd,
- });
- const banLog = fetchedLogs.entries.first();
- if (banLog) {
- ({ executor, reason, target } = banLog);
- }
-
- retryCount--;
+ retryCount--;
+ } while ((!target || target.id !== guildBanAdd.user.id) && retryCount > 0);
+ /* eslint-enable no-await-in-loop */
+
+ if (!target) {
+ await modLogsChannel.send({ embeds: [noLogEmbed(guildBanAdd.user, guildBanAdd.guild.name)] });
+ return;
+ }
+ if (target.id !== guildBanAdd.user.id) {
+ await modLogsChannel.send({ embeds: [userBannedIncompleteEmbed(guildBanAdd.user, formattedDate)] });
+ return;
+ }
+ if (executor && !constantsConfig.modLogExclude.includes(executor.id)) {
+ await modLogsChannel.send({
+ content: executor.toString(),
+ embeds: [modLogEmbed(guildBanAdd.user, executor, reason as string, formattedDate)],
+ });
+
+ //Log to the DB
+ Logger.info('Starting Infraction process');
+
+ const newInfraction = {
+ infractionType: 'Ban',
+ moderatorID: executor ? executor.id : 'Unavailable',
+ reason: `This was a non bot ban: ${reason as string}`,
+ date: currentDate,
+ infractionID: new mongoose.Types.ObjectId(),
+ };
+
+ let userData = await Infraction.findOne({ userID: target.id });
+
+ Logger.info(userData);
+
+ if (!userData) {
+ userData = new Infraction({
+ userID: target.id,
+ infractions: [newInfraction],
+ });
+ Logger.info(userData);
+ Logger.info('New user data created');
+ } else {
+ userData.infractions.push(newInfraction);
+ Logger.info('User data updated');
}
- while ((!target || target.id !== guildBanAdd.user.id) && retryCount > 0);
- if (!target) {
- await modLogsChannel.send({ embeds: [noLogEmbed(guildBanAdd.user, guildBanAdd.guild.name)] });
- return;
- }
- if (target.id !== guildBanAdd.user.id) {
- await modLogsChannel.send({ embeds: [userBannedIncompleteEmbed(guildBanAdd.user, formattedDate)] });
- return;
- }
- if (executor && !constantsConfig.modLogExclude.includes(executor.id)) {
- await modLogsChannel.send({ content: executor.toString(), embeds: [modLogEmbed(guildBanAdd.user, executor, reason as string, formattedDate)] });
-
- //Log to the DB
- Logger.info('Starting Infraction process');
-
- const newInfraction = {
- infractionType: 'Ban',
- moderatorID: executor ? executor.id : 'Unavailable',
- reason: `This was a non bot ban: ${reason as string}`,
- date: currentDate,
- infractionID: new mongoose.Types.ObjectId(),
- };
-
- let userData = await Infraction.findOne({ userID: target.id });
-
- Logger.info(userData);
-
- if (!userData) {
- userData = new Infraction({
- userID: target.id,
- infractions: [newInfraction],
- });
- Logger.info(userData);
- Logger.info('New user data created');
- } else {
- userData.infractions.push(newInfraction);
- Logger.info('User data updated');
- }
-
- try {
- await userData.save();
- Logger.info('Infraction process complete');
- } catch (error) {
- await modLogsChannel.send({ embeds: [logFailed] });
- Logger.error(error);
- }
+ try {
+ await userData.save();
+ Logger.info('Infraction process complete');
+ } catch (error) {
+ await modLogsChannel.send({ embeds: [logFailed] });
+ Logger.error(error);
}
+ }
- Logger.debug('Ban Handler - Finished');
+ Logger.debug('Ban Handler - Finished');
});
diff --git a/src/events/logging/messageDelete.ts b/src/events/logging/messageDelete.ts
index 74215e10..3915a6b5 100644
--- a/src/events/logging/messageDelete.ts
+++ b/src/events/logging/messageDelete.ts
@@ -5,110 +5,111 @@ import { constantsConfig, event, Events, imageBaseUrl, Logger, makeEmbed } from
const CONTENT_NOT_AVAIL = 'Unable to find content or embeds.';
export default event(Events.MessageDelete, async (_, msg) => {
- try {
- if (msg.guild === null || msg.author === null) {
- // DMs
- return;
- }
+ try {
+ if (msg.guild === null || msg.author === null) {
+ // DMs
+ return;
+ }
- if (msg.content === null || msg.content.trim() === '') {
- // Old Message or empty content
- return;
- }
+ if (msg.content === null || msg.content.trim() === '') {
+ // Old Message or empty content
+ return;
+ }
- const fetchedLogs = await msg.guild.fetchAuditLogs({
- limit: 1,
- type: AuditLogEvent.MessageDelete,
- });
- const deletionLog = fetchedLogs.entries.first();
- const currentDate = new Date();
- const formattedDate: string = moment(currentDate)
- .utcOffset(0)
- .format('DD, MM, YYYY, HH:mm:ss');
- const userLogsChannel = msg.guild.channels.resolve(constantsConfig.channels.USER_LOGS) as TextChannel | null;
- const messageEmbeds = msg.embeds.length > 0 ? msg.embeds : [];
- const messageComponents = [];
- if (msg.content) {
- messageComponents.push(msg.content);
- }
- if (msg.attachments) {
- msg.attachments.forEach((attachment) => {
- if (attachment.url || attachment.proxyURL) {
- messageComponents.push(attachment.url ? attachment.url : attachment.proxyURL);
- }
- });
+ const fetchedLogs = await msg.guild.fetchAuditLogs({
+ limit: 1,
+ type: AuditLogEvent.MessageDelete,
+ });
+ const deletionLog = fetchedLogs.entries.first();
+ const currentDate = new Date();
+ const formattedDate: string = moment(currentDate).utcOffset(0).format('DD, MM, YYYY, HH:mm:ss');
+ const userLogsChannel = msg.guild.channels.resolve(constantsConfig.channels.USER_LOGS) as TextChannel | null;
+ const messageEmbeds = msg.embeds.length > 0 ? msg.embeds : [];
+ const messageComponents = [];
+ if (msg.content) {
+ messageComponents.push(msg.content);
+ }
+ if (msg.attachments) {
+ msg.attachments.forEach((attachment) => {
+ if (attachment.url || attachment.proxyURL) {
+ messageComponents.push(attachment.url ? attachment.url : attachment.proxyURL);
}
- for (const messageEmbed of messageEmbeds) {
- const { image, fields } = messageEmbed;
- if (image) {
- messageComponents.push(`<${image.url}>`);
- }
- for (const field of fields) {
- const { name, value } = field;
- if (name && value) {
- messageComponents.push(`${name}: ${value}`);
- }
- }
+ });
+ }
+ for (const messageEmbed of messageEmbeds) {
+ const { image, fields } = messageEmbed;
+ if (image) {
+ messageComponents.push(`<${image.url}>`);
+ }
+ for (const field of fields) {
+ const { name, value } = field;
+ if (name && value) {
+ messageComponents.push(`${name}: ${value}`);
}
+ }
+ }
- const MAX_MESSAGE_LENGTH = 1024;
+ const MAX_MESSAGE_LENGTH = 1024;
- let messageContent = messageComponents.join('\n');
+ let messageContent = messageComponents.join('\n');
- let deletedMessageFieldTitle = 'Deleted Message';
+ let deletedMessageFieldTitle = 'Deleted Message';
- if (messageContent.length > MAX_MESSAGE_LENGTH) {
- messageContent = `${messageComponents.join('\n').slice(0, MAX_MESSAGE_LENGTH - 3)}...`;
- deletedMessageFieldTitle = 'Deleted Message (truncated)';
- }
+ if (messageContent.length > MAX_MESSAGE_LENGTH) {
+ messageContent = `${messageComponents.join('\n').slice(0, MAX_MESSAGE_LENGTH - 3)}...`;
+ deletedMessageFieldTitle = 'Deleted Message (truncated)';
+ }
- const messageReference = msg.reference ? await msg.fetchReference() : null;
- const messageDeleteEmbed = makeEmbed({
- color: Colors.Red,
- thumbnail: { url: `${imageBaseUrl}/moderation/message_deleted.png` },
- author: {
- name: msg.author.tag,
- iconURL: msg.author.displayAvatarURL(),
- },
- fields: [
- {
- name: 'Date',
- value: formattedDate,
- inline: true,
- },
- {
- name: 'Author',
- value: `${msg.author}`,
- inline: true,
- },
- {
- name: 'Channel',
- value: `${msg.channel}`,
- inline: true,
- },
- {
- name: 'Reply to',
- value: messageReference ? `${messageReference.url}` : 'None',
- inline: true,
- },
- {
- name: 'Deleted by',
- value: (deletionLog && deletionLog.target.id === msg.author.id) ? `${deletionLog.executor}` : 'No audit log was found, message was either deleted by author, or a bot',
- inline: false,
- },
- {
- name: deletedMessageFieldTitle,
- value: messageContent ? `${messageContent}` : CONTENT_NOT_AVAIL,
- inline: false,
- },
- ],
- footer: { text: `User ID: ${msg.author.id}` },
- });
+ const messageReference = msg.reference ? await msg.fetchReference() : null;
+ const messageDeleteEmbed = makeEmbed({
+ color: Colors.Red,
+ thumbnail: { url: `${imageBaseUrl}/moderation/message_deleted.png` },
+ author: {
+ name: msg.author.tag,
+ iconURL: msg.author.displayAvatarURL(),
+ },
+ fields: [
+ {
+ name: 'Date',
+ value: formattedDate,
+ inline: true,
+ },
+ {
+ name: 'Author',
+ value: `${msg.author.toString()}`,
+ inline: true,
+ },
+ {
+ name: 'Channel',
+ value: `${msg.channel.toString()}`,
+ inline: true,
+ },
+ {
+ name: 'Reply to',
+ value: messageReference ? `${messageReference.url}` : 'None',
+ inline: true,
+ },
+ {
+ name: 'Deleted by',
+ value:
+ deletionLog && deletionLog.target.id === msg.author.id
+ ? `${deletionLog.executor ? deletionLog.executor.toString() : 'Could not find executor.'}`
+ : 'No audit log was found, message was either deleted by author, or a bot',
+ inline: false,
+ },
+ {
+ name: deletedMessageFieldTitle,
+ value: messageContent ? `${messageContent}` : CONTENT_NOT_AVAIL,
+ inline: false,
+ },
+ ],
+ footer: { text: `User ID: ${msg.author.id}` },
+ });
- if (userLogsChannel && !constantsConfig.userLogExclude.includes(msg.author!.id)) {
- await userLogsChannel.send({ embeds: [messageDeleteEmbed] });
- }
- } catch (error) {
- Logger.error(error);
+ if (userLogsChannel && !constantsConfig.userLogExclude.includes(msg.author.id)) {
+ await userLogsChannel.send({ embeds: [messageDeleteEmbed] });
}
+ } catch (error) {
+ Logger.error(error);
+ }
});
diff --git a/src/events/logging/messageUpdate.ts b/src/events/logging/messageUpdate.ts
index 11d509a5..9252bd13 100644
--- a/src/events/logging/messageUpdate.ts
+++ b/src/events/logging/messageUpdate.ts
@@ -1,64 +1,72 @@
import { Colors, TextChannel } from 'discord.js';
import { constantsConfig, event, Events, imageBaseUrl, Logger, makeEmbed } from '../../lib';
-const FEATURE_NOT_AVAIL = '(can\'t show embeds or images)';
+const FEATURE_NOT_AVAIL = "(can't show embeds or images)";
export default event(Events.MessageUpdate, async (_, oldMessage, newMessage) => {
- try {
- if (oldMessage.guild === null || oldMessage.author === null || newMessage.author === null) {
- // DMs
- return;
- }
+ try {
+ if (oldMessage.guild === null || oldMessage.author === null || newMessage.author === null) {
+ // DMs
+ return;
+ }
- if (oldMessage.content === null) {
- // Old Message
- return;
- }
+ if (oldMessage.content === null) {
+ // Old Message
+ return;
+ }
- if (newMessage.content === null) {
- // Message was deleted
- return;
- }
+ if (newMessage.content === null) {
+ // Message was deleted
+ return;
+ }
- const userLogsChannel = oldMessage.guild.channels.resolve(constantsConfig.channels.USER_LOGS) as TextChannel | null;
+ const userLogsChannel = oldMessage.guild.channels.resolve(constantsConfig.channels.USER_LOGS) as TextChannel | null;
- const MAX_MESSAGE_LENGTH = 1024;
+ const MAX_MESSAGE_LENGTH = 1024;
- let oldMessageContent = oldMessage.content;
- let newMessageContent = newMessage.content;
+ let oldMessageContent = oldMessage.content;
+ let newMessageContent = newMessage.content;
- let originalMessageFieldTitle = 'Original Message';
- let editedMessageFieldTitle = 'Edited Message';
+ let originalMessageFieldTitle = 'Original Message';
+ let editedMessageFieldTitle = 'Edited Message';
- if (oldMessageContent.length > MAX_MESSAGE_LENGTH) {
- oldMessageContent = `${oldMessageContent.slice(0, MAX_MESSAGE_LENGTH - 9)}...`;
- originalMessageFieldTitle = 'Original Message (truncated)';
- }
+ if (oldMessageContent.length > MAX_MESSAGE_LENGTH) {
+ oldMessageContent = `${oldMessageContent.slice(0, MAX_MESSAGE_LENGTH - 9)}...`;
+ originalMessageFieldTitle = 'Original Message (truncated)';
+ }
- if (newMessageContent.length > MAX_MESSAGE_LENGTH) {
- newMessageContent = `${newMessageContent.slice(0, MAX_MESSAGE_LENGTH - 9)}...`;
- editedMessageFieldTitle = 'Edited Message (truncated)';
- }
+ if (newMessageContent.length > MAX_MESSAGE_LENGTH) {
+ newMessageContent = `${newMessageContent.slice(0, MAX_MESSAGE_LENGTH - 9)}...`;
+ editedMessageFieldTitle = 'Edited Message (truncated)';
+ }
- if (userLogsChannel && !constantsConfig.userLogExclude.includes(oldMessage.author!.id)) {
- const messageUpdateEmbed = makeEmbed({
- color: Colors.Orange,
- thumbnail: { url: `${imageBaseUrl}/moderation/message_edited.png` },
- author: {
- name: oldMessage.author.tag,
- iconURL: oldMessage.author.displayAvatarURL(),
- },
- fields: [
- { name: 'Author', value: `${oldMessage.author}`, inline: true },
- { name: 'Channel', value: `${oldMessage.channel}`, inline: true },
- { name: originalMessageFieldTitle, value: oldMessageContent ? `\`\`\`${oldMessageContent}\`\`\`` : FEATURE_NOT_AVAIL, inline: false },
- { name: editedMessageFieldTitle, value: newMessageContent ? `\`\`\`${newMessageContent}\`\`\`` : FEATURE_NOT_AVAIL, inline: false },
- ],
- footer: { text: `User ID: ${oldMessage.author.id}` },
- });
- await userLogsChannel.send({ embeds: [messageUpdateEmbed] });
- }
- } catch (error) {
- Logger.error(error);
+ if (userLogsChannel && !constantsConfig.userLogExclude.includes(oldMessage.author.id)) {
+ const messageUpdateEmbed = makeEmbed({
+ color: Colors.Orange,
+ thumbnail: { url: `${imageBaseUrl}/moderation/message_edited.png` },
+ author: {
+ name: oldMessage.author.tag,
+ iconURL: oldMessage.author.displayAvatarURL(),
+ },
+ fields: [
+ { name: 'Author', value: `${oldMessage.author.toString()}`, inline: true },
+ { name: 'Channel', value: `${oldMessage.channel.toString()}`, inline: true },
+ {
+ name: originalMessageFieldTitle,
+ value: oldMessageContent ? `\`\`\`${oldMessageContent}\`\`\`` : FEATURE_NOT_AVAIL,
+ inline: false,
+ },
+ {
+ name: editedMessageFieldTitle,
+ value: newMessageContent ? `\`\`\`${newMessageContent}\`\`\`` : FEATURE_NOT_AVAIL,
+ inline: false,
+ },
+ ],
+ footer: { text: `User ID: ${oldMessage.author.id}` },
+ });
+ await userLogsChannel.send({ embeds: [messageUpdateEmbed] });
}
+ } catch (error) {
+ Logger.error(error);
+ }
});
diff --git a/src/events/logging/scamLogs.ts b/src/events/logging/scamLogs.ts
index 1b2cb265..658bdb38 100644
--- a/src/events/logging/scamLogs.ts
+++ b/src/events/logging/scamLogs.ts
@@ -1,200 +1,212 @@
import { codeBlock, Colors, DMChannel, TextChannel } from 'discord.js';
import mongoose from 'mongoose';
-import { constantsConfig, makeEmbed, makeLines, event, Events, getConn, Infraction, Logger, imageBaseUrl } from '../../lib';
+import {
+ constantsConfig,
+ makeEmbed,
+ makeLines,
+ event,
+ Events,
+ getConn,
+ Infraction,
+ Logger,
+ imageBaseUrl,
+} from '../../lib';
const excludedRoles = [
- constantsConfig.roles.ADMIN_TEAM,
- constantsConfig.roles.MODERATION_TEAM,
- constantsConfig.roles.DEVELOPMENT_TEAM,
- constantsConfig.roles.MEDIA_TEAM,
- constantsConfig.roles.COMMUNITY_SUPPORT,
- constantsConfig.roles.FBW_EMERITUS,
+ constantsConfig.roles.ADMIN_TEAM,
+ constantsConfig.roles.MODERATION_TEAM,
+ constantsConfig.roles.DEVELOPMENT_TEAM,
+ constantsConfig.roles.MEDIA_TEAM,
+ constantsConfig.roles.COMMUNITY_SUPPORT,
+ constantsConfig.roles.FBW_EMERITUS,
];
const noConnEmbed = makeEmbed({
- title: 'Scam Logs - No Connection',
- description: 'Could not connect to the database.',
- color: Colors.Red,
+ title: 'Scam Logs - No Connection',
+ description: 'Could not connect to the database.',
+ color: Colors.Red,
});
const logFailed = makeEmbed({
- title: 'Scam Logs - Failed to log',
- description: 'Failed to log the Scam Log entry to the database.',
- color: Colors.Red,
+ title: 'Scam Logs - Failed to log',
+ description: 'Failed to log the Scam Log entry to the database.',
+ color: Colors.Red,
});
const deleteFailed = makeEmbed({
- title: 'Scam Logs - Failed to delete',
- description: 'Failed to delete the message.',
- color: Colors.Red,
+ title: 'Scam Logs - Failed to delete',
+ description: 'Failed to delete the message.',
+ color: Colors.Red,
});
export default event(Events.MessageCreate, async ({ log }, msg) => {
- if (msg.guild === null) {
- // DM's
- return;
+ if (msg.guild === null) {
+ // DM's
+ return;
+ }
+
+ const scamReportLogs = msg.guild.channels.resolve(constantsConfig.channels.SCAM_REPORT_LOGS) as TextChannel | null;
+ if (scamReportLogs && msg.content.toLowerCase().includes('@everyone') && !msg.author.bot) {
+ const conn = getConn();
+ if (!conn && scamReportLogs) {
+ await scamReportLogs.send({ embeds: [noConnEmbed] });
+ return;
}
- const scamReportLogs = msg.guild.channels.resolve(constantsConfig.channels.SCAM_REPORT_LOGS) as TextChannel | null;
- if (scamReportLogs && msg.content.toLowerCase().includes('@everyone') && !msg.author.bot) {
- const conn = getConn();
- if (!conn && scamReportLogs) {
- await scamReportLogs.send({ embeds: [noConnEmbed] });
- return;
- }
-
- const MAX_MESSAGE_LENGTH = 1024;
-
- let messageContent = msg.content.toString();
-
- let messageContentFieldTitle = 'Message Content:';
-
- if (messageContent.length > MAX_MESSAGE_LENGTH) {
- messageContent = `${msg.content.slice(0, MAX_MESSAGE_LENGTH - 11)}...`;
- messageContentFieldTitle = 'Message Content (truncated):';
- }
-
- if (!(msg.channel instanceof DMChannel)) {
- let hasRole = false;
- try {
- excludedRoles.forEach((roleList) => {
- // @ts-ignore
- if (msg.member.roles.cache.some((role) => role.id === roleList)) {
- hasRole = true;
- }
- });
- } catch (e) {
- log(e);
- }
- // Has role, message can stay, log sent
- if (hasRole) {
- const allowedEmbed = makeEmbed({
- title: 'Potential Scam Alert',
- thumbnail: { url: `${imageBaseUrl}/moderation/approved.png` },
- description: 'An allowed role has used @everyone',
- author: {
- name: msg.author.tag,
- iconURL: msg.author.displayAvatarURL(),
- },
- fields: [
- {
- name: 'User:',
- value: `${msg.author}`,
- },
- {
- name: 'Channel:',
- value: `${msg.channel}`,
- },
- {
- name: messageContentFieldTitle,
- value: codeBlock(messageContent),
- },
- ],
- });
-
- await scamReportLogs.send({ embeds: [allowedEmbed] });
- return;
- }
- // Doesn't have role, message deleted, log sent, user timed out
- try {
- await msg.delete();
- } catch (e) {
- log(e);
- await scamReportLogs.send({ embeds: [deleteFailed] });
- }
-
- const notAllowedEmbed = makeEmbed({
- title: 'Potential Scam Alert',
- thumbnail: { url: `${imageBaseUrl}/moderation/scam.png` },
- author: {
- name: msg.author.tag,
- iconURL: msg.author.displayAvatarURL(),
- },
- fields: [
- {
- name: 'User:',
- value: `${msg.author}`,
- },
- {
- name: 'Channel:',
- value: `${msg.channel}`,
- },
- {
- name: messageContentFieldTitle,
- value: codeBlock(messageContent),
- },
- ],
- });
- // Time out
- try {
- // @ts-ignore
- await msg.member.timeout(60 * 60 * 24 * 7 * 1000, 'Scam log');
- } catch (e) {
- log(e);
- const errorEmbed = makeEmbed({
- title: 'Error timing out user',
- description: makeLines([
- `An error occurred while timing out ${msg.author}`,
- `${codeBlock(`Error : ${e}`)}`,
- ]),
- color: Colors.Red,
- });
- await scamReportLogs.send({ embeds: [errorEmbed] });
- }
- // Try and send a DM
- try {
- await msg.author.send('We have detected use of @everyone in one of our text channels. This function is in place to prevent discord scams and has resulted in an automatic timeout and notification of our moderation team. If this was done in error, our moderation team will reverse the timeout, however please refrain from using the @everyone ping in future.');
- } catch (e) {
- log(e);
-
- const noDMEmbed = makeEmbed({
- author: {
- name: msg.author.tag,
- iconURL: msg.author.displayAvatarURL(),
- },
- description: `DM was not sent to ${msg.author.id}.`,
- });
-
- await scamReportLogs.send({ embeds: [noDMEmbed] });
- }
-
- await scamReportLogs.send({ embeds: [notAllowedEmbed] });
-
- // Add infraction to database
-
- Logger.info('Starting Infraction process');
-
- const newInfraction = {
- infractionType: 'ScamLog',
- moderatorID: msg.client.user.id,
- reason: `Message content: ${msg.content.toString()}`,
- date: new Date(),
- infractionID: new mongoose.Types.ObjectId(),
- };
-
- let userData = await Infraction.findOne({ UserID: msg.author.id });
-
- log(userData);
-
- if (!userData) {
- userData = new Infraction({
- userID: msg.author.id,
- infractions: [newInfraction],
- });
- Logger.info(userData);
- Logger.info('New user data created');
- } else {
- userData.infractions.push(newInfraction);
- Logger.info('User data updated');
- }
-
- try {
- await userData.save();
- Logger.info('Infraction process complete');
- } catch (error) {
- await scamReportLogs.send({ embeds: [logFailed] });
- Logger.error(error);
- }
- }
+ const MAX_MESSAGE_LENGTH = 1024;
+
+ let messageContent = msg.content.toString();
+
+ let messageContentFieldTitle = 'Message Content:';
+
+ if (messageContent.length > MAX_MESSAGE_LENGTH) {
+ messageContent = `${msg.content.slice(0, MAX_MESSAGE_LENGTH - 11)}...`;
+ messageContentFieldTitle = 'Message Content (truncated):';
+ }
+
+ if (!(msg.channel instanceof DMChannel)) {
+ let hasRole = false;
+ try {
+ excludedRoles.forEach((roleList) => {
+ // FIXME: assert msg.member type
+ if (msg.member!.roles.cache.some((role) => role.id === roleList)) {
+ hasRole = true;
+ }
+ });
+ } catch (e) {
+ log(e);
+ }
+ // Has role, message can stay, log sent
+ if (hasRole) {
+ const allowedEmbed = makeEmbed({
+ title: 'Potential Scam Alert',
+ thumbnail: { url: `${imageBaseUrl}/moderation/approved.png` },
+ description: 'An allowed role has used @everyone',
+ author: {
+ name: msg.author.tag,
+ iconURL: msg.author.displayAvatarURL(),
+ },
+ fields: [
+ {
+ name: 'User:',
+ value: `${msg.author.toString()}`,
+ },
+ {
+ name: 'Channel:',
+ value: `${msg.channel.toString()}`,
+ },
+ {
+ name: messageContentFieldTitle,
+ value: codeBlock(messageContent),
+ },
+ ],
+ });
+
+ await scamReportLogs.send({ embeds: [allowedEmbed] });
+ return;
+ }
+ // Doesn't have role, message deleted, log sent, user timed out
+ try {
+ await msg.delete();
+ } catch (e) {
+ log(e);
+ await scamReportLogs.send({ embeds: [deleteFailed] });
+ }
+
+ const notAllowedEmbed = makeEmbed({
+ title: 'Potential Scam Alert',
+ thumbnail: { url: `${imageBaseUrl}/moderation/scam.png` },
+ author: {
+ name: msg.author.tag,
+ iconURL: msg.author.displayAvatarURL(),
+ },
+ fields: [
+ {
+ name: 'User:',
+ value: `${msg.author.toString()}`,
+ },
+ {
+ name: 'Channel:',
+ value: `${msg.channel.toString()}`,
+ },
+ {
+ name: messageContentFieldTitle,
+ value: codeBlock(messageContent),
+ },
+ ],
+ });
+ // Time out
+ try {
+ // FIXME: assert msg.member type
+ await msg.member!.timeout(60 * 60 * 24 * 7 * 1000, 'Scam log');
+ } catch (e) {
+ log(e);
+ const errorEmbed = makeEmbed({
+ title: 'Error timing out user',
+ description: makeLines([
+ `An error occurred while timing out ${msg.author.toString()}`,
+ `${codeBlock(`Error : ${String(e)}`)}`,
+ ]),
+ color: Colors.Red,
+ });
+ await scamReportLogs.send({ embeds: [errorEmbed] });
+ }
+ // Try and send a DM
+ try {
+ await msg.author.send(
+ 'We have detected use of @everyone in one of our text channels. This function is in place to prevent discord scams and has resulted in an automatic timeout and notification of our moderation team. If this was done in error, our moderation team will reverse the timeout, however please refrain from using the @everyone ping in future.',
+ );
+ } catch (e) {
+ log(e);
+
+ const noDMEmbed = makeEmbed({
+ author: {
+ name: msg.author.tag,
+ iconURL: msg.author.displayAvatarURL(),
+ },
+ description: `DM was not sent to ${msg.author.id}.`,
+ });
+
+ await scamReportLogs.send({ embeds: [noDMEmbed] });
+ }
+
+ await scamReportLogs.send({ embeds: [notAllowedEmbed] });
+
+ // Add infraction to database
+
+ Logger.info('Starting Infraction process');
+
+ const newInfraction = {
+ infractionType: 'ScamLog',
+ moderatorID: msg.client.user.id,
+ reason: `Message content: ${msg.content.toString()}`,
+ date: new Date(),
+ infractionID: new mongoose.Types.ObjectId(),
+ };
+
+ let userData = await Infraction.findOne({ UserID: msg.author.id });
+
+ log(userData);
+
+ if (!userData) {
+ userData = new Infraction({
+ userID: msg.author.id,
+ infractions: [newInfraction],
+ });
+ Logger.info(userData);
+ Logger.info('New user data created');
+ } else {
+ userData.infractions.push(newInfraction);
+ Logger.info('User data updated');
+ }
+
+ try {
+ await userData.save();
+ Logger.info('Infraction process complete');
+ } catch (error) {
+ await scamReportLogs.send({ embeds: [logFailed] });
+ Logger.error(error);
+ }
}
+ }
});
diff --git a/src/events/messageCreateHandler.ts b/src/events/messageCreateHandler.ts
index 78a2f0db..7a582518 100644
--- a/src/events/messageCreateHandler.ts
+++ b/src/events/messageCreateHandler.ts
@@ -1,298 +1,440 @@
-import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, EmbedBuilder, Interaction, Message } from 'discord.js';
-import { event, getInMemoryCache, MemoryCachePrefix, Logger, Events, constantsConfig, makeEmbed, makeLines, PrefixCommand, PrefixCommandPermissions, PrefixCommandVersion } from '../lib';
+import {
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonInteraction,
+ ButtonStyle,
+ ComponentType,
+ EmbedBuilder,
+ Message,
+} from 'discord.js';
+import {
+ event,
+ getInMemoryCache,
+ MemoryCachePrefix,
+ Logger,
+ Events,
+ constantsConfig,
+ makeEmbed,
+ makeLines,
+ PrefixCommand,
+ PrefixCommandPermissions,
+ PrefixCommandVersion,
+} from '../lib';
-const commandEmbed = (title: string, description: string, color: string, imageUrl: string = '') => makeEmbed({
+const commandEmbed = (title: string, description: string, color: string, imageUrl: string = '') =>
+ makeEmbed({
title,
description,
color: Number(color),
...(imageUrl && { image: { url: imageUrl } }),
-});
+ });
-async function replyWithEmbed(msg: Message, embed: EmbedBuilder, buttonRow?: ActionRowBuilder) : Promise> {
- return msg.fetchReference()
- .then((res) => {
- embed = EmbedBuilder.from(embed.data);
- embed.setFooter({ text: `Executed by ${msg.author.tag} - ${msg.author.id}` });
- return res.reply({
- embeds: [embed],
- components: buttonRow ? [buttonRow] : [],
- });
- })
- .catch(() => msg.reply({
- embeds: [embed],
- components: buttonRow ? [buttonRow] : [],
- }));
+async function replyWithEmbed(
+ msg: Message,
+ embed: EmbedBuilder,
+ buttonRow?: ActionRowBuilder,
+): Promise> {
+ return msg
+ .fetchReference()
+ .then((res) => {
+ embed = EmbedBuilder.from(embed.data);
+ embed.setFooter({ text: `Executed by ${msg.author.tag} - ${msg.author.id}` });
+ return res.reply({
+ embeds: [embed],
+ components: buttonRow ? [buttonRow] : [],
+ });
+ })
+ .catch(() =>
+ msg.reply({
+ embeds: [embed],
+ components: buttonRow ? [buttonRow] : [],
+ }),
+ );
}
-async function replyWithMsg(msg: Message, text: string, buttonRow?:ActionRowBuilder) : Promise> {
- return msg.fetchReference()
- .then((res) => res.reply({
- content: `${text}\n\n\`Executed by ${msg.author.tag} - ${msg.author.id}\``,
- components: buttonRow ? [buttonRow] : [],
- }))
- .catch(() => msg.reply({
- content: text,
- components: buttonRow ? [buttonRow] : [],
- }));
+async function replyWithMsg(
+ msg: Message,
+ text: string,
+ buttonRow?: ActionRowBuilder,
+): Promise> {
+ return msg
+ .fetchReference()
+ .then((res) =>
+ res.reply({
+ content: `${text}\n\n\`Executed by ${msg.author.tag} - ${msg.author.id}\``,
+ components: buttonRow ? [buttonRow] : [],
+ }),
+ )
+ .catch(() =>
+ msg.reply({
+ content: text,
+ components: buttonRow ? [buttonRow] : [],
+ }),
+ );
}
-async function sendReply(message: Message, commandTitle: string, commandContent: string, isEmbed: boolean, embedColor: string, commandImage: string, versionButtonRow?: ActionRowBuilder) : Promise> {
- try {
- let actualCommandContent = commandContent;
- if (!commandTitle && !commandContent && !commandImage) {
- actualCommandContent = 'No content available.';
- }
- if (isEmbed) {
- return replyWithEmbed(message, commandEmbed(commandTitle, actualCommandContent, embedColor, commandImage), versionButtonRow);
- }
- const content: string[] = [];
- if (commandTitle) {
- content.push(`**${commandTitle}**`);
- }
- content.push(actualCommandContent);
- return replyWithMsg(message, makeLines(content), versionButtonRow);
- } catch (error) {
- Logger.error(error);
- return message.reply('An error occurred while processing the command.');
+async function sendReply(
+ message: Message,
+ commandTitle: string,
+ commandContent: string,
+ isEmbed: boolean,
+ embedColor: string,
+ commandImage: string,
+ versionButtonRow?: ActionRowBuilder,
+): Promise> {
+ try {
+ let actualCommandContent = commandContent;
+ if (!commandTitle && !commandContent && !commandImage) {
+ actualCommandContent = 'No content available.';
+ }
+ if (isEmbed) {
+ return replyWithEmbed(
+ message,
+ commandEmbed(commandTitle, actualCommandContent, embedColor, commandImage),
+ versionButtonRow,
+ );
+ }
+ const content: string[] = [];
+ if (commandTitle) {
+ content.push(`**${commandTitle}**`);
}
+ content.push(actualCommandContent);
+ return replyWithMsg(message, makeLines(content), versionButtonRow);
+ } catch (error) {
+ Logger.error(error);
+ return message.reply('An error occurred while processing the command.');
+ }
}
-async function expireChoiceReply(message: Message, commandTitle: string, commandContent: string, isEmbed: boolean, embedColor: string, commandImage: string) : Promise> {
- try {
- let actualCommandContent = commandContent;
- if (!commandTitle && !commandContent && !commandImage) {
- actualCommandContent = 'No content available.';
- }
- if (isEmbed) {
- const commandEmbedData = commandEmbed(commandTitle, actualCommandContent, embedColor, commandImage);
- const { footer } = message.embeds[0];
- const newFooter = footer?.text ? `${footer.text} - The choice has expired.` : 'The choice has expired.';
- commandEmbedData.setFooter({ text: newFooter });
- return message.edit({ embeds: [commandEmbedData], components: [] });
- }
+async function expireChoiceReply(
+ message: Message,
+ commandTitle: string,
+ commandContent: string,
+ isEmbed: boolean,
+ embedColor: string,
+ commandImage: string,
+): Promise> {
+ try {
+ let actualCommandContent = commandContent;
+ if (!commandTitle && !commandContent && !commandImage) {
+ actualCommandContent = 'No content available.';
+ }
+ if (isEmbed) {
+ const commandEmbedData = commandEmbed(commandTitle, actualCommandContent, embedColor, commandImage);
+ const { footer } = message.embeds[0];
+ const newFooter = footer?.text ? `${footer.text} - The choice has expired.` : 'The choice has expired.';
+ commandEmbedData.setFooter({ text: newFooter });
+ return message.edit({ embeds: [commandEmbedData], components: [] });
+ }
- const content: string[] = [];
- if (commandTitle) {
- content.push(`**${commandTitle}**`);
- }
- content.push(actualCommandContent);
- content.push('\n`The choice has expired.`');
- return message.edit({
- content: makeLines(content),
- components: [],
- });
- } catch (error) {
- Logger.error(error);
- return message.reply('An error occurred while updating the message.');
+ const content: string[] = [];
+ if (commandTitle) {
+ content.push(`**${commandTitle}**`);
}
+ content.push(actualCommandContent);
+ content.push('\n`The choice has expired.`');
+ return message.edit({
+ content: makeLines(content),
+ components: [],
+ });
+ } catch (error) {
+ Logger.error(error);
+ return message.reply('An error occurred while updating the message.');
+ }
}
async function sendPermError(message: Message, errorText: string) {
- if (constantsConfig.prefixCommandPermissionDelay > 0) {
- errorText += `\n\nThis message & the original command message will be deleted in ${constantsConfig.prefixCommandPermissionDelay / 1000} seconds.`;
- }
- const permReply = await sendReply(message, 'Permission Error', errorText, true, constantsConfig.colors.FBW_RED, '');
- if (constantsConfig.prefixCommandPermissionDelay > 0) {
- setTimeout(() => {
- try {
- permReply.delete();
- message.delete();
- } catch (error) {
- Logger.error(`Error while deleting permission error message for command: ${error}`);
- }
- }, constantsConfig.prefixCommandPermissionDelay);
- }
+ if (constantsConfig.prefixCommandPermissionDelay > 0) {
+ errorText += `\n\nThis message & the original command message will be deleted in ${constantsConfig.prefixCommandPermissionDelay / 1000} seconds.`;
+ }
+ const permReply = await sendReply(message, 'Permission Error', errorText, true, constantsConfig.colors.FBW_RED, '');
+ if (constantsConfig.prefixCommandPermissionDelay > 0) {
+ setTimeout(() => {
+ try {
+ void permReply.delete();
+ void message.delete();
+ } catch (error) {
+ Logger.error('Error while deleting permission error message for command:', error);
+ }
+ }, constantsConfig.prefixCommandPermissionDelay);
+ }
}
export default event(Events.MessageCreate, async (_, message) => {
- const { id: messageId, author, channel, content } = message;
- const { id: authorId, bot } = author;
+ const { id: messageId, author, channel, content } = message;
+ const { id: authorId, bot } = author;
- if (bot || channel.isDMBased()) return;
- const { id: channelId, guild } = channel;
- const { id: guildId } = guild;
- Logger.debug(`Processing message ${messageId} from user ${authorId} in channel ${channelId} of server ${guildId}.`);
+ if (bot || channel.isDMBased()) return;
+ const { id: channelId, guild } = channel;
+ const { id: guildId } = guild;
+ Logger.debug(`Processing message ${messageId} from user ${authorId} in channel ${channelId} of server ${guildId}.`);
- const inMemoryCache = getInMemoryCache();
- if (inMemoryCache && content.startsWith(constantsConfig.prefixCommandPrefix)) {
- const commandTextMatch = content.match(`^\\${constantsConfig.prefixCommandPrefix}([\\w\\d-_]+)[^\\w\\d-_]*([\\w\\d-_]+)?`);
- if (commandTextMatch) {
- let [commandText] = commandTextMatch.slice(1);
- const commandVersionExplicitGeneric = (commandText.toLowerCase() === 'generic');
+ const inMemoryCache = getInMemoryCache();
+ // Return if either the memory-cache is null or the message doesn't start with the defined prefix-command prefix.
+ if (!inMemoryCache || !content.startsWith(constantsConfig.prefixCommandPrefix)) {
+ return;
+ }
- // Step 1: Check if the command is actually a version alias
- const commandCachedVersion = await inMemoryCache.get(`${MemoryCachePrefix.VERSION}:${commandText.toLowerCase()}`);
- let commandVersionId: string;
- let commandVersionName: string;
- let commandVersionEnabled: boolean;
- if (commandCachedVersion) {
- const commandVersion = PrefixCommandVersion.hydrate(commandCachedVersion);
- ({ id: commandVersionId, name: commandVersionName, enabled: commandVersionEnabled } = commandVersion);
- } else {
- commandVersionId = 'GENERIC';
- commandVersionName = 'GENERIC';
- commandVersionEnabled = true;
- }
+ const commandTextMatch = content.match(
+ `^\\${constantsConfig.prefixCommandPrefix}([\\w\\d-_]+)[^\\w\\d-_]*([\\w\\d-_]+)?`,
+ );
+ // Return if the message doesn't match the regex.
+ if (!commandTextMatch) {
+ Logger.debug('no match');
+ return;
+ }
- // Step 2: Check if there's a default version for the channel if commandVersionName is GENERIC
- let channelDefaultVersionUsed = false;
- if (commandVersionName === 'GENERIC' && !commandVersionExplicitGeneric) {
- const channelDefaultVersionCached = await inMemoryCache.get(`${MemoryCachePrefix.CHANNEL_DEFAULT_VERSION}:${channelId}`);
- if (channelDefaultVersionCached) {
- const channelDefaultVersion = PrefixCommandVersion.hydrate(channelDefaultVersionCached);
- ({ id: commandVersionId, name: commandVersionName, enabled: commandVersionEnabled } = channelDefaultVersion);
- channelDefaultVersionUsed = true;
- }
- }
+ let [commandText] = commandTextMatch.slice(1);
+ const commandVersionExplicitGeneric = commandText.toLowerCase() === 'generic';
- // Drop execution if the version is disabled and we aren't using the default version for a channel
- if (!commandVersionEnabled && !channelDefaultVersionUsed) {
- if ((commandCachedVersion || commandVersionExplicitGeneric) && commandTextMatch[2]) {
- [commandText] = commandTextMatch.slice(2);
- }
- Logger.debug(`Prefix Command - Version "${commandVersionName}" is disabled - Not executing command "${commandText}"`);
- return;
- }
- // If the version is disabled and we are using the default version for a channel, switch to the generic version
- if (!commandVersionEnabled && channelDefaultVersionUsed) {
- commandVersionId = 'GENERIC';
- commandVersionName = 'GENERIC';
- commandVersionEnabled = true;
- }
+ // Step 1: Check if the command is actually a version alias
+ const commandCachedVersion = await inMemoryCache.get(`${MemoryCachePrefix.VERSION}:${commandText.toLowerCase()}`);
+ let commandVersionId: string;
+ let commandVersionName: string;
+ let commandVersionEnabled: boolean;
+ if (commandCachedVersion) {
+ const commandVersion = PrefixCommandVersion.hydrate(commandCachedVersion);
+ ({ id: commandVersionId, name: commandVersionName, enabled: commandVersionEnabled } = commandVersion);
+ } else {
+ commandVersionId = 'GENERIC';
+ commandVersionName = 'GENERIC';
+ commandVersionEnabled = true;
+ }
- // Step 2.5: If the first command was actually a version alias, take the actual command as CommandText
- if ((commandCachedVersion || commandVersionExplicitGeneric) && commandTextMatch[2]) {
- [commandText] = commandTextMatch.slice(2);
- }
+ // Step 2: Check if there's a default version for the channel if commandVersionName is GENERIC
+ let channelDefaultVersionUsed = false;
+ if (commandVersionName === 'GENERIC' && !commandVersionExplicitGeneric) {
+ const channelDefaultVersionCached = await inMemoryCache.get(
+ `${MemoryCachePrefix.CHANNEL_DEFAULT_VERSION}:${channelId}`,
+ );
+ if (channelDefaultVersionCached) {
+ const channelDefaultVersion = PrefixCommandVersion.hydrate(channelDefaultVersionCached);
+ ({ id: commandVersionId, name: commandVersionName, enabled: commandVersionEnabled } = channelDefaultVersion);
+ channelDefaultVersionUsed = true;
+ }
+ }
- // Step 3: Check if the command exists itself and process it
- const cachedCommandDetails = await inMemoryCache.get(`${MemoryCachePrefix.COMMAND}:${commandText.toLowerCase()}`);
- if (cachedCommandDetails) {
- const commandDetails = PrefixCommand.hydrate(cachedCommandDetails);
- const { name, contents, isEmbed, embedColor, permissions } = commandDetails;
- const { roles: permRoles, rolesBlocklist, channels: permChannels, channelsBlocklist, quietErrors, verboseErrors } = permissions ?? new PrefixCommandPermissions();
- const authorMember = await guild.members.fetch(authorId);
+ // Drop execution if the version is disabled and we aren't using the default version for a channel
+ if (!commandVersionEnabled && !channelDefaultVersionUsed) {
+ if ((commandCachedVersion || commandVersionExplicitGeneric) && commandTextMatch[2]) {
+ [commandText] = commandTextMatch.slice(2);
+ }
+ Logger.debug(
+ `Prefix Command - Version "${commandVersionName}" is disabled - Not executing command "${commandText}"`,
+ );
+ return;
+ }
+ // If the version is disabled and we are using the default version for a channel, switch to the generic version
+ if (!commandVersionEnabled && channelDefaultVersionUsed) {
+ commandVersionId = 'GENERIC';
+ commandVersionName = 'GENERIC';
+ commandVersionEnabled = true;
+ }
- // Check permissions
- const hasAnyRole = permRoles && permRoles.some((role) => authorMember.roles.cache.has(role));
- const isInChannel = permChannels && permChannels.includes(channelId);
- const meetsRoleRequirements = !permRoles || permRoles.length === 0
- || (hasAnyRole && !rolesBlocklist)
- || (!hasAnyRole && rolesBlocklist);
- const meetsChannelRequirements = !permChannels || permChannels.length === 0
- || (isInChannel && !channelsBlocklist)
- || (!isInChannel && channelsBlocklist);
+ // Step 2.5: If the first command was actually a version alias, take the actual command as CommandText
+ if ((commandCachedVersion || commandVersionExplicitGeneric) && commandTextMatch[2]) {
+ [commandText] = commandTextMatch.slice(2);
+ }
- if (!meetsRoleRequirements) {
- Logger.debug(`Prefix Command - User does not meet role requirements for command "${name}" based on user command "${commandText}"`);
- if (quietErrors) return;
- let errorText = '';
- if (verboseErrors && !rolesBlocklist) {
- errorText = `You do not have the required role to execute this command. Required roles: ${permRoles.map((role) => guild.roles.cache.get(role)?.name).join(', ')}.`;
- } else if (verboseErrors && rolesBlocklist) {
- errorText = `You have a blocklisted role for this command. Blocklisted roles: ${permRoles.map((role) => guild.roles.cache.get(role)?.name).join(', ')}.`;
- } else if (!verboseErrors && !rolesBlocklist) {
- errorText = 'You do not have the required role to execute this command.';
- } else {
- errorText = 'You have a blocklisted role for this command.';
- }
- await sendPermError(message, errorText);
- return;
- }
+ // Step 3: Check if the command exists itself and process it, otherwise return.
+ const cachedCommandDetails = await inMemoryCache.get(`${MemoryCachePrefix.COMMAND}:${commandText.toLowerCase()}`);
+ if (!cachedCommandDetails) {
+ Logger.debug('No command details found. Returning...');
+ return;
+ }
- if (!meetsChannelRequirements) {
- Logger.debug(`Prefix Command - Message does not meet channel requirements for command "${name}" based on user command "${commandText}"`);
- if (quietErrors) return;
- let errorText = '';
- if (verboseErrors && !channelsBlocklist) {
- errorText = `This command is not available in this channel. Required channels: ${permChannels.map((channel) => guild.channels.cache.get(channel)?.toString()).join(', ')}.`;
- } else if (verboseErrors && channelsBlocklist) {
- errorText = `This command is blocklisted in this channel. Blocklisted channels: ${permChannels.map((channel) => guild.channels.cache.get(channel)?.toString()).join(', ')}.`;
- } else if (!verboseErrors && !channelsBlocklist) {
- errorText = 'This command is not available in this channel.';
- } else {
- errorText = 'This command is blocklisted in this channel.';
- }
- await sendPermError(message, errorText);
- return;
- }
+ const commandDetails = PrefixCommand.hydrate(cachedCommandDetails);
+ const { name, contents, isEmbed, embedColor, permissions } = commandDetails;
+ const {
+ roles: permRoles,
+ rolesBlocklist,
+ channels: permChannels,
+ channelsBlocklist,
+ quietErrors,
+ verboseErrors,
+ } = permissions ?? new PrefixCommandPermissions();
+ const authorMember = await guild.members.fetch(authorId);
- let commandContentData = contents.find(({ versionId }) => versionId === commandVersionId);
- let enableButtons = true;
- // If the version is not found, try to find the generic version
- if (!commandContentData) {
- commandContentData = contents.find(({ versionId }) => versionId === 'GENERIC');
- commandVersionName = 'GENERIC';
- enableButtons = false;
- }
- // If the generic version is not found, drop execution
- if (!commandContentData) {
- Logger.debug(`Prefix Command - Version "${commandVersionName}" not found for command "${name}" based on user command "${commandText}"`);
- return;
- }
- const { title: commandTitle, content: commandContent, image: commandImage } = commandContentData;
- // If generic requested and multiple versions, show the selection
- // Note that this only applies if GENERIC is the version explicitly requested
- // Otherwise, the options are not shown
- if (enableButtons && commandVersionName === 'GENERIC' && contents.length > 1) {
- Logger.debug(`Prefix Command - Multiple versions found for command "${name}" based on user command "${commandText}", showing version selection`);
- const versionSelectionButtonData: { [key: string]: ButtonBuilder } = {};
- for (const { versionId: versionIdForButton } of contents) {
- // eslint-disable-next-line no-await-in-loop
- const versionCached = await inMemoryCache.get(`${MemoryCachePrefix.VERSION}:${versionIdForButton}`);
- if (versionCached) {
- const version = PrefixCommandVersion.hydrate(versionCached);
- const { emoji, enabled } = version;
- if (enabled) {
- versionSelectionButtonData[emoji] = new ButtonBuilder()
- .setCustomId(`${versionIdForButton}`)
- .setEmoji(emoji)
- .setStyle(ButtonStyle.Primary);
- }
- }
- }
- const versionSelectionButtons: ButtonBuilder[] = Object.keys(versionSelectionButtonData)
- .sort()
- .map((key: string) => versionSelectionButtonData[key]);
- const versionSelectButtonRow = new ActionRowBuilder().addComponents(versionSelectionButtons);
+ // Check permissions
+ const hasAnyRole = permRoles && permRoles.some((role) => authorMember.roles.cache.has(role));
+ const isInChannel = permChannels && permChannels.includes(channelId);
+ const meetsRoleRequirements =
+ !permRoles || permRoles.length === 0 || (hasAnyRole && !rolesBlocklist) || (!hasAnyRole && rolesBlocklist);
+ const meetsChannelRequirements =
+ !permChannels ||
+ permChannels.length === 0 ||
+ (isInChannel && !channelsBlocklist) ||
+ (!isInChannel && channelsBlocklist);
- if (versionSelectButtonRow.components.length < 1) {
- Logger.debug(`Prefix Command - No enabled versions found for command "${name}" based on user command "${commandText}"`);
- Logger.debug(`Prefix Command - Executing version "${commandVersionName}" for command "${name}" based on user command "${commandText}"`);
- await sendReply(message, commandTitle, commandContent || '', isEmbed || false, embedColor || constantsConfig.colors.FBW_CYAN, commandImage || '');
- return;
- }
- const buttonMessage = await sendReply(message, commandTitle, commandContent || '', isEmbed || false, embedColor || constantsConfig.colors.FBW_CYAN, commandImage || '', versionSelectButtonRow);
+ if (!meetsRoleRequirements) {
+ Logger.debug(
+ `Prefix Command - User does not meet role requirements for command "${name}" based on user command "${commandText}"`,
+ );
+ if (quietErrors) return;
+ let errorText = '';
+ if (verboseErrors && !rolesBlocklist) {
+ errorText = `You do not have the required role to execute this command. Required roles: ${permRoles.map((role) => guild.roles.cache.get(role)?.name).join(', ')}.`;
+ } else if (verboseErrors && rolesBlocklist) {
+ errorText = `You have a blocklisted role for this command. Blocklisted roles: ${permRoles.map((role) => guild.roles.cache.get(role)?.name).join(', ')}.`;
+ } else if (!verboseErrors && !rolesBlocklist) {
+ errorText = 'You do not have the required role to execute this command.';
+ } else {
+ errorText = 'You have a blocklisted role for this command.';
+ }
+ await sendPermError(message, errorText);
+ return;
+ }
- const filter = (interaction: Interaction) => interaction.user.id === authorId;
- const collector = buttonMessage.createMessageComponentCollector({ filter, time: 60_000 });
- let buttonClicked = false;
- collector.on('collect', async (collectedInteraction: ButtonInteraction) => {
- buttonClicked = true;
- await collectedInteraction.deferUpdate();
- Logger.debug(`Prefix Command - User selected button "${collectedInteraction.customId}" for command "${name}" based on user command "${commandText}"`);
- await buttonMessage.delete();
- const { customId: selectedVersionId } = collectedInteraction;
- const commandContentData = contents.find(({ versionId }) => versionId === selectedVersionId);
- if (!commandContentData) {
- Logger.debug(`Prefix Command - Version ID "${selectedVersionId}" not found for command "${name}" based on user command "${commandText}"`);
- return;
- }
- const { title: commandTitle, content: commandContent, image: commandImage } = commandContentData;
- await sendReply(message, commandTitle, commandContent || '', isEmbed || false, embedColor || constantsConfig.colors.FBW_CYAN, commandImage || '');
- });
+ if (!meetsChannelRequirements) {
+ Logger.debug(
+ `Prefix Command - Message does not meet channel requirements for command "${name}" based on user command "${commandText}"`,
+ );
+ if (quietErrors) return;
+ let errorText = '';
+ if (verboseErrors && !channelsBlocklist) {
+ errorText = `This command is not available in this channel. Required channels: ${permChannels.map((channel) => guild.channels.cache.get(channel)?.toString()).join(', ')}.`;
+ } else if (verboseErrors && channelsBlocklist) {
+ errorText = `This command is blocklisted in this channel. Blocklisted channels: ${permChannels.map((channel) => guild.channels.cache.get(channel)?.toString()).join(', ')}.`;
+ } else if (!verboseErrors && !channelsBlocklist) {
+ errorText = 'This command is not available in this channel.';
+ } else {
+ errorText = 'This command is blocklisted in this channel.';
+ }
+ await sendPermError(message, errorText);
+ return;
+ }
- collector.on('end', async (_: ButtonInteraction, reason: string) => {
- if (!buttonClicked && reason === 'time') {
- Logger.debug(`Prefix Command - User did not select a version for command "${name}" based on user command "${commandText}"`);
- await expireChoiceReply(buttonMessage, commandTitle, commandContent || '', isEmbed || false, embedColor || constantsConfig.colors.FBW_CYAN, commandImage || '');
- }
- });
- } else {
- Logger.debug(`Prefix Command - Executing version "${commandVersionName}" for command "${name}" based on user command "${commandText}"`);
- await sendReply(message, commandTitle, commandContent || '', isEmbed || false, embedColor || constantsConfig.colors.FBW_CYAN, commandImage || '');
- }
- }
+ let commandContentData = contents.find(({ versionId }) => versionId === commandVersionId);
+ let enableButtons = true;
+ // If the version is not found, try to find the generic version
+ if (!commandContentData) {
+ commandContentData = contents.find(({ versionId }) => versionId === 'GENERIC');
+ commandVersionName = 'GENERIC';
+ enableButtons = false;
+ }
+ // If the generic version is not found, drop execution
+ if (!commandContentData) {
+ Logger.debug(
+ `Prefix Command - Version "${commandVersionName}" not found for command "${name}" based on user command "${commandText}"`,
+ );
+ return;
+ }
+ const { title: commandTitle, content: commandContent, image: commandImage } = commandContentData;
+ // If generic requested and multiple versions, show the selection
+ // Note that this only applies if GENERIC is the version explicitly requested
+ // Otherwise, the options are not shown
+ if (enableButtons && commandVersionName === 'GENERIC' && contents.length > 1) {
+ Logger.debug(
+ `Prefix Command - Multiple versions found for command "${name}" based on user command "${commandText}", showing version selection`,
+ );
+ const versionSelectionButtonData: { [key: string]: ButtonBuilder } = {};
+ for (const { versionId: versionIdForButton } of contents) {
+ // eslint-disable-next-line no-await-in-loop
+ const versionCached = await inMemoryCache.get(`${MemoryCachePrefix.VERSION}:${versionIdForButton}`);
+ if (versionCached) {
+ const version = PrefixCommandVersion.hydrate(versionCached);
+ const { emoji, enabled } = version;
+ if (enabled) {
+ versionSelectionButtonData[emoji] = new ButtonBuilder()
+ .setCustomId(`${versionIdForButton}`)
+ .setEmoji(emoji)
+ .setStyle(ButtonStyle.Primary);
}
+ }
+ }
+ const versionSelectionButtons: ButtonBuilder[] = Object.keys(versionSelectionButtonData)
+ .sort()
+ .map((key: string) => versionSelectionButtonData[key]);
+ const versionSelectButtonRow = new ActionRowBuilder().addComponents(versionSelectionButtons);
+
+ if (versionSelectButtonRow.components.length < 1) {
+ Logger.debug(
+ `Prefix Command - No enabled versions found for command "${name}" based on user command "${commandText}"`,
+ );
+ Logger.debug(
+ `Prefix Command - Executing version "${commandVersionName}" for command "${name}" based on user command "${commandText}"`,
+ );
+ await sendReply(
+ message,
+ commandTitle,
+ commandContent || '',
+ isEmbed || false,
+ embedColor || constantsConfig.colors.FBW_CYAN,
+ commandImage || '',
+ );
+ return;
+ }
+
+ const buttonMessage = await sendReply(
+ message,
+ commandTitle,
+ commandContent || '',
+ isEmbed || false,
+ embedColor || constantsConfig.colors.FBW_CYAN,
+ commandImage || '',
+ versionSelectButtonRow,
+ );
+
+ const filter = (interaction: ButtonInteraction) => {
+ return interaction.user.id === authorId;
+ };
+
+ try {
+ const buttonInteraction = await buttonMessage.awaitMessageComponent({
+ filter,
+ time: 60_000,
+ componentType: ComponentType.Button,
+ });
+
+ void buttonInteraction.deferUpdate();
+
+ Logger.debug(
+ `Prefix Command - User selected button "${buttonInteraction.customId}" for command "${name}" based on user command "${commandText}"`,
+ );
+ void buttonMessage.delete();
+ const { customId: selectedVersionId } = buttonInteraction;
+ const commandContentData = contents.find(({ versionId }) => versionId === selectedVersionId);
+ if (!commandContentData) {
+ Logger.debug(
+ `Prefix Command - Version ID "${selectedVersionId}" not found for command "${name}" based on user command "${commandText}"`,
+ );
+ return;
+ }
+ const { title: commandTitle, content: commandContent, image: commandImage } = commandContentData;
+ await sendReply(
+ message,
+ commandTitle,
+ commandContent || '',
+ isEmbed || false,
+ embedColor || constantsConfig.colors.FBW_CYAN,
+ commandImage || '',
+ );
+ return;
+ } catch {
+ Logger.debug(
+ `Prefix Command - User did not select a version for command "${name}" based on user command "${commandText}"`,
+ );
+ await expireChoiceReply(
+ buttonMessage,
+ commandTitle,
+ commandContent || '',
+ isEmbed || false,
+ embedColor || constantsConfig.colors.FBW_CYAN,
+ commandImage || '',
+ );
+ return;
}
+ } else {
+ Logger.debug(
+ `Prefix Command - Executing version "${commandVersionName}" for command "${name}" based on user command "${commandText}"`,
+ );
+ await sendReply(
+ message,
+ commandTitle,
+ commandContent || '',
+ isEmbed || false,
+ embedColor || constantsConfig.colors.FBW_CYAN,
+ commandImage || '',
+ );
+ }
});
diff --git a/src/events/ready.ts b/src/events/ready.ts
index 2572190f..c6de1e87 100644
--- a/src/events/ready.ts
+++ b/src/events/ready.ts
@@ -1,234 +1,244 @@
import { ActivityType, TextChannel } from 'discord.js';
import moment from 'moment';
+import commandArray from '../commands';
+import contextArray from '../commands/context';
import {
- constantsConfig,
- event,
- Events,
- connect,
- setupScheduler,
- Logger,
- imageBaseUrl,
- getScheduler,
- setupInMemoryCache,
- loadAllPrefixCommandsToCache,
- loadAllPrefixCommandVersionsToCache,
- loadAllPrefixCommandCategoriesToCache,
- loadAllPrefixCommandChannelDefaultVersionsToCache,
+ Events,
+ Logger,
+ connect,
+ constantsConfig,
+ event,
+ getScheduler,
+ imageBaseUrl,
+ loadAllPrefixCommandCategoriesToCache,
+ loadAllPrefixCommandChannelDefaultVersionsToCache,
+ loadAllPrefixCommandVersionsToCache,
+ loadAllPrefixCommandsToCache,
+ setupInMemoryCache,
+ setupScheduler,
} from '../lib';
import { deployCommands } from '../scripts/deployCommands';
-import commandArray from '../commands';
-import contextArray from '../commands/context';
export default event(Events.ClientReady, async ({ log }, client) => {
- log(`Logged in as ${client.user.username}!`);
-
- // Set username, activity, status and avatar
- if (process.env.NODE_ENV === 'production') {
- log('Production environment detected, setting username, activity, status and avatar.');
-
- try {
- client.user?.setUsername('FlyByWire Simulations Utilities');
- client.user?.setActivity('the A380X', { type: ActivityType.Watching });
- client.user?.setStatus('online');
- client.user?.setAvatar(`${imageBaseUrl}/fbw_tail.png`);
- } catch (error) {
- log('Failed to set username, activity, status and avatar:', error);
- }
+ log(`Logged in as ${client.user.username}!`);
+
+ // Set username, activity, status and avatar
+ if (process.env.NODE_ENV === 'production') {
+ log('Production environment detected, setting username, activity, status and avatar.');
+
+ try {
+ await client.user?.setUsername('FlyByWire Simulations Utilities');
+ client.user?.setActivity('the A380X', { type: ActivityType.Watching });
+ client.user?.setStatus('online');
+ await client.user?.setAvatar(`${imageBaseUrl}/fbw_tail.png`);
+ } catch (error) {
+ log('Failed to set username, activity, status and avatar:', error);
}
-
- // Deploy commands and contexts
- if (process.env.DEPLOY === 'true') {
- log('DEPLOY variable set to true, deploying commands and contexts.');
- try {
- await deployCommands(commandArray, contextArray)
- .then(async (user) => {
- const bot = `<@${user.id}>`;
-
- const response = process.env.NODE_ENV === 'production'
- ? `Deployed ${commandArray.length} commands and ${contextArray.length} contexts globally as ${bot}!`
- : `Deployed ${commandArray.length} commands and ${contextArray.length} contexts to \`<@${constantsConfig.guildId}>\` as ${bot}!`;
-
- log(response);
- });
- } catch (error) {
- log('Failed to deploy commands:', error);
- }
+ }
+
+ // Deploy commands and contexts
+ if (process.env.DEPLOY === 'true') {
+ log('DEPLOY variable set to true, deploying commands and contexts.');
+ try {
+ await deployCommands(commandArray, contextArray).then((user) => {
+ const bot = `<@${user.id}>`;
+
+ const response =
+ process.env.NODE_ENV === 'production'
+ ? `Deployed ${commandArray.length} commands and ${contextArray.length} contexts globally as ${bot}!`
+ : `Deployed ${commandArray.length} commands and ${contextArray.length} contexts to \`<@${constantsConfig.guildId}>\` as ${bot}!`;
+
+ log(response);
+ });
+ } catch (error) {
+ log('Failed to deploy commands:', error);
}
-
- // Setup cache manager
- let inMemoryCacheSetup = false;
- let inMemoryCacheError: Error | undefined;
- await setupInMemoryCache()
- .then(() => {
- inMemoryCacheSetup = true;
- })
- .catch((error) => {
- inMemoryCacheError = error;
- Logger.error(error);
+ }
+
+ // Setup cache manager
+ let inMemoryCacheSetup = false;
+ let inMemoryCacheError: Error | undefined;
+ await setupInMemoryCache()
+ .then(() => {
+ inMemoryCacheSetup = true;
+ })
+ .catch((error) => {
+ inMemoryCacheError = error instanceof Error ? error : undefined;
+ Logger.error(error);
+ });
+
+ // Connect to MongoDB and set up scheduler
+ let dbConnected = false;
+ let dbError: Error | undefined;
+ let schedulerConnected = false;
+ let schedulerError: Error | undefined;
+
+ if (process.env.MONGODB_URL) {
+ await connect(process.env.MONGODB_URL)
+ .then(() => {
+ dbConnected = true;
+ })
+ .catch((error) => {
+ dbError = error instanceof Error ? error : undefined;
+ Logger.error(error);
+ });
+ await setupScheduler('fbwBotScheduler', process.env.MONGODB_URL)
+ .then(() => {
+ schedulerConnected = true;
+ })
+ .catch((error) => {
+ schedulerError = error instanceof Error ? error : undefined;
+ Logger.error(error);
+ });
+ }
+
+ // Set heartbeat handler
+ if (schedulerConnected && process.env.HEARTBEAT_URL && process.env.HEARTBEAT_INTERVAL) {
+ const scheduler = getScheduler();
+ if (scheduler) {
+ const heartbeatJobList = await scheduler.jobs({ name: 'sendHeartbeat' });
+ if (heartbeatJobList.length === 0) {
+ await scheduler.every(`${process.env.HEARTBEAT_INTERVAL} seconds`, 'sendHeartbeat', {
+ interval: process.env.HEARTBEAT_INTERVAL,
});
-
- // Connect to MongoDB and set up scheduler
- let dbConnected = false;
- let dbError: Error | undefined;
- let schedulerConnected = false;
- let schedulerError: Error | undefined;
-
- if (process.env.MONGODB_URL) {
- await connect(process.env.MONGODB_URL)
- .then(() => {
- dbConnected = true;
- })
- .catch((error) => {
- dbError = error;
- Logger.error(error);
- });
- await setupScheduler('fbwBotScheduler', process.env.MONGODB_URL)
- .then(() => {
- schedulerConnected = true;
- })
- .catch((error) => {
- schedulerError = error;
- Logger.error(error);
- });
- }
-
- // Set heartbeat handler
- if (schedulerConnected && process.env.HEARTBEAT_URL && process.env.HEARTBEAT_INTERVAL) {
- const scheduler = getScheduler();
- if (scheduler) {
- const heartbeatJobList = await scheduler.jobs({ name: 'sendHeartbeat' });
- if (heartbeatJobList.length === 0) {
- scheduler.every(`${process.env.HEARTBEAT_INTERVAL} seconds`, 'sendHeartbeat', { interval: process.env.HEARTBEAT_INTERVAL });
- Logger.info(`Heartbeat job scheduled with interval ${process.env.HEARTBEAT_INTERVAL}`);
- } else {
- const heartbeatJob = heartbeatJobList[0];
- const { interval } = heartbeatJob.attrs.data as { interval: string };
- if (interval !== process.env.HEARTBEAT_INTERVAL) {
- await scheduler.cancel({ name: 'sendHeartbeat' });
- scheduler.every(`${process.env.HEARTBEAT_INTERVAL} seconds`, 'sendHeartbeat', { interval: process.env.HEARTBEAT_INTERVAL });
- Logger.info(`Heartbeat job rescheduled with new interval ${process.env.HEARTBEAT_INTERVAL}`);
- } else {
- Logger.info('Heartbeat job already scheduled');
- }
- }
+ Logger.info(`Heartbeat job scheduled with interval ${process.env.HEARTBEAT_INTERVAL}`);
+ } else {
+ const heartbeatJob = heartbeatJobList[0];
+ const { interval } = heartbeatJob.attrs.data as { interval: string };
+ if (interval !== process.env.HEARTBEAT_INTERVAL) {
+ await scheduler.cancel({ name: 'sendHeartbeat' });
+ await scheduler.every(`${process.env.HEARTBEAT_INTERVAL} seconds`, 'sendHeartbeat', {
+ interval: process.env.HEARTBEAT_INTERVAL,
+ });
+ Logger.info(`Heartbeat job rescheduled with new interval ${process.env.HEARTBEAT_INTERVAL}`);
+ } else {
+ Logger.info('Heartbeat job already scheduled');
}
+ }
}
-
- // Set birthday handler
- if (schedulerConnected && process.env.BIRTHDAY_INTERVAL) {
- const scheduler = getScheduler();
- if (scheduler) {
- const birthdayJobList = await scheduler.jobs({ name: 'postBirthdays' });
- if (birthdayJobList.length === 0) {
- scheduler.every(`${process.env.BIRTHDAY_INTERVAL} seconds`, 'postBirthdays', { interval: process.env.BIRTHDAY_INTERVAL });
- Logger.info(`Birthday job scheduled with interval ${process.env.BIRTHDAY_INTERVAL}`);
- } else {
- const birthdayJob = birthdayJobList[0];
- const { interval } = birthdayJob.attrs.data as { interval: string };
- if (interval !== process.env.BIRTHDAY_INTERVAL) {
- await scheduler.cancel({ name: 'postBirthdays' });
- scheduler.every(`${process.env.BIRTHDAY_INTERVAL} seconds`, 'postBirthdays', { interval: process.env.BIRTHDAY_INTERVAL });
- Logger.info(`Birthday job rescheduled with new interval ${process.env.BIRTHDAY_INTERVAL}`);
- } else {
- Logger.info('Birthday job already scheduled');
- }
- }
+ }
+
+ // Set birthday handler
+ if (schedulerConnected && process.env.BIRTHDAY_INTERVAL) {
+ const scheduler = getScheduler();
+ if (scheduler) {
+ const birthdayJobList = await scheduler.jobs({ name: 'postBirthdays' });
+ if (birthdayJobList.length === 0) {
+ await scheduler.every(`${process.env.BIRTHDAY_INTERVAL} seconds`, 'postBirthdays', {
+ interval: process.env.BIRTHDAY_INTERVAL,
+ });
+ Logger.info(`Birthday job scheduled with interval ${process.env.BIRTHDAY_INTERVAL}`);
+ } else {
+ const birthdayJob = birthdayJobList[0];
+ const { interval } = birthdayJob.attrs.data as { interval: string };
+ if (interval !== process.env.BIRTHDAY_INTERVAL) {
+ await scheduler.cancel({ name: 'postBirthdays' });
+ await scheduler.every(`${process.env.BIRTHDAY_INTERVAL} seconds`, 'postBirthdays', {
+ interval: process.env.BIRTHDAY_INTERVAL,
+ });
+ Logger.info(`Birthday job rescheduled with new interval ${process.env.BIRTHDAY_INTERVAL}`);
+ } else {
+ Logger.info('Birthday job already scheduled');
}
+ }
}
-
- const cacheRefreshInterval = process.env.CACHE_REFRESH_INTERVAL ? Number(process.env.CACHE_REFRESH_INTERVAL) : 1800;
- // Set in memory cache refresh handler
- if (schedulerConnected && cacheRefreshInterval) {
- const scheduler = getScheduler();
- if (scheduler) {
- const cacheJobList = await scheduler.jobs({ name: 'refreshInMemoryCache' });
- if (cacheJobList.length === 0) {
- scheduler.every(`${cacheRefreshInterval} seconds`, 'refreshInMemoryCache', { interval: cacheRefreshInterval });
- Logger.info(`Cache refresh job scheduled with interval ${cacheRefreshInterval}`);
- } else {
- const cacheJob = cacheJobList[0];
- const { interval } = cacheJob.attrs.data as { interval: number };
- if (interval !== cacheRefreshInterval) {
- await scheduler.cancel({ name: 'refreshInMemoryCache' });
- scheduler.every(`${cacheRefreshInterval} seconds`, 'refreshInMemoryCache', { interval: cacheRefreshInterval });
- Logger.info(`Cache refresh job rescheduled with new interval ${cacheRefreshInterval}`);
- } else {
- Logger.info('Cache refresh job already scheduled');
- }
- }
+ }
+
+ const cacheRefreshInterval = process.env.CACHE_REFRESH_INTERVAL ? Number(process.env.CACHE_REFRESH_INTERVAL) : 1800;
+ // Set in memory cache refresh handler
+ if (schedulerConnected && cacheRefreshInterval) {
+ const scheduler = getScheduler();
+ if (scheduler) {
+ const cacheJobList = await scheduler.jobs({ name: 'refreshInMemoryCache' });
+ if (cacheJobList.length === 0) {
+ await scheduler.every(`${cacheRefreshInterval} seconds`, 'refreshInMemoryCache', {
+ interval: cacheRefreshInterval,
+ });
+ Logger.info(`Cache refresh job scheduled with interval ${cacheRefreshInterval}`);
+ } else {
+ const cacheJob = cacheJobList[0];
+ const { interval } = cacheJob.attrs.data as { interval: number };
+ if (interval !== cacheRefreshInterval) {
+ await scheduler.cancel({ name: 'refreshInMemoryCache' });
+ await scheduler.every(`${cacheRefreshInterval} seconds`, 'refreshInMemoryCache', {
+ interval: cacheRefreshInterval,
+ });
+ Logger.info(`Cache refresh job rescheduled with new interval ${cacheRefreshInterval}`);
+ } else {
+ Logger.info('Cache refresh job already scheduled');
}
+ }
}
-
- // Loading in-memory cache with prefix commands
- if (inMemoryCacheSetup && dbConnected) {
- await loadAllPrefixCommandsToCache()
- .then(() => {
- Logger.info('Loaded prefix commands to cache.');
- })
- .catch((error) => {
- Logger.error(`Failed to load prefix commands to cache: ${error}`);
- });
- }
-
- // Loading in-memory cache with prefix command versions
- if (inMemoryCacheSetup && dbConnected) {
- await loadAllPrefixCommandVersionsToCache()
- .then(() => {
- Logger.info('Loaded prefix command versions to cache.');
- })
- .catch((error) => {
- Logger.error(`Failed to load prefix command versions to cache: ${error}`);
- });
+ }
+
+ // Loading in-memory cache with prefix commands
+ if (inMemoryCacheSetup && dbConnected) {
+ loadAllPrefixCommandsToCache()
+ .then(() => {
+ Logger.info('Loaded prefix commands to cache.');
+ })
+ .catch((error) => {
+ Logger.error(`Failed to load prefix commands to cache: ${error}`);
+ });
+ }
+
+ // Loading in-memory cache with prefix command versions
+ if (inMemoryCacheSetup && dbConnected) {
+ await loadAllPrefixCommandVersionsToCache()
+ .then(() => {
+ Logger.info('Loaded prefix command versions to cache.');
+ })
+ .catch((error) => {
+ Logger.error(`Failed to load prefix command versions to cache: ${error}`);
+ });
+ }
+
+ // Loading in-memory cache with prefix command categories
+ if (inMemoryCacheSetup && dbConnected) {
+ await loadAllPrefixCommandCategoriesToCache()
+ .then(() => {
+ Logger.info('Loaded prefix command categories to cache.');
+ })
+ .catch((error) => {
+ Logger.error(`Failed to load prefix command categories to cache: ${error}`);
+ });
+ }
+
+ // Loading in-memory cache with prefix command channel default versions
+ if (inMemoryCacheSetup && dbConnected) {
+ await loadAllPrefixCommandChannelDefaultVersionsToCache()
+ .then(() => {
+ Logger.info('Loaded prefix command channel default versions to cache.');
+ })
+ .catch((error) => {
+ Logger.error(`Failed to load prefix command channel default versions to cache: ${error}`);
+ });
+ }
+
+ // Send bot status message to bot-dev channel
+ const botDevChannel = client.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
+ if (botDevChannel) {
+ const currentDate = new Date();
+ const formattedDate = moment(currentDate).utcOffset(0).format();
+
+ // Include the database connection and scheduler status in the mod logs message.
+ let logMessage = `<@&${constantsConfig.roles.BOT_DEVELOPER}>\n[${formattedDate}] - ${client.user?.username} has connected! - DB State: ${dbConnected ? 'Connected' : 'Disconnected'}`;
+ if (!dbConnected && dbError) {
+ logMessage += ` - DB Error: ${dbError.message}`;
}
- // Loading in-memory cache with prefix command categories
- if (inMemoryCacheSetup && dbConnected) {
- await loadAllPrefixCommandCategoriesToCache()
- .then(() => {
- Logger.info('Loaded prefix command categories to cache.');
- })
- .catch((error) => {
- Logger.error(`Failed to load prefix command categories to cache: ${error}`);
- });
+ logMessage += ` - Scheduler State: ${schedulerConnected ? 'Connected' : 'Disconnected'}`;
+ if (!schedulerConnected && schedulerError) {
+ logMessage += ` - Scheduler Error: ${schedulerError.message}`;
}
- // Loading in-memory cache with prefix command channel default versions
- if (inMemoryCacheSetup && dbConnected) {
- await loadAllPrefixCommandChannelDefaultVersionsToCache()
- .then(() => {
- Logger.info('Loaded prefix command channel default versions to cache.');
- })
- .catch((error) => {
- Logger.error(`Failed to load prefix command channel default versions to cache: ${error}`);
- });
+ logMessage += ` - Cache State: ${inMemoryCacheSetup ? 'Setup' : 'Not Setup'}`;
+ if (!inMemoryCacheSetup && inMemoryCacheError) {
+ logMessage += ` - Cache Error: ${inMemoryCacheError.message}`;
}
- // Send bot status message to bot-dev channel
- const botDevChannel = client.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel;
- if (botDevChannel) {
- const currentDate = new Date();
- const formattedDate = moment(currentDate)
- .utcOffset(0)
- .format();
-
- // Include the database connection and scheduler status in the mod logs message.
- let logMessage = `<@&${constantsConfig.roles.BOT_DEVELOPER}>\n[${formattedDate}] - ${client.user?.username} has connected! - DB State: ${dbConnected ? 'Connected' : 'Disconnected'}`;
- if (!dbConnected && dbError) {
- logMessage += ` - DB Error: ${dbError.message}`;
- }
-
- logMessage += ` - Scheduler State: ${schedulerConnected ? 'Connected' : 'Disconnected'}`;
- if (!schedulerConnected && schedulerError) {
- logMessage += ` - Scheduler Error: ${schedulerError.message}`;
- }
-
- logMessage += ` - Cache State: ${inMemoryCacheSetup ? 'Setup' : 'Not Setup'}`;
- if (!inMemoryCacheSetup && inMemoryCacheError) {
- logMessage += ` - Cache Error: ${inMemoryCacheError.message}`;
- }
-
- await botDevChannel.send({ content: logMessage });
- } else {
- log('Unable to find bot-dev channel. Cannot send bot status message.');
- }
+ await botDevChannel.send({ content: logMessage });
+ } else {
+ log('Unable to find bot-dev channel. Cannot send bot status message.');
+ }
});
diff --git a/src/events/slashCommandHandler.ts b/src/events/slashCommandHandler.ts
index 0d6edaf0..83312df6 100644
--- a/src/events/slashCommandHandler.ts
+++ b/src/events/slashCommandHandler.ts
@@ -1,75 +1,84 @@
-import { Color, SlashCommand, event, Events, Reply, makeEmbed } from '../lib';
+import { ApplicationCommandOptionType, CommandInteractionOption, CommandInteractionOptionResolver } from 'discord.js';
import commandArray from '../commands';
-
-/* eslint-disable no-underscore-dangle */
+import { Color, Events, Reply, SlashCommand, event, makeEmbed } from '../lib';
const commandMap = new Map();
for (const cmd of commandArray) {
- commandMap.set(cmd.meta.name, cmd);
+ commandMap.set(cmd.meta.name, cmd);
}
export default event(Events.InteractionCreate, async ({ log, client }, interaction) => {
- if (!interaction.isChatInputCommand()) {
- return;
- }
-
- if (!interaction.inCachedGuild()) {
- await interaction.reply(
- Reply('This bot can only be used in a server!', Color.Error),
- );
- return;
+ if (!interaction.isChatInputCommand()) {
+ return;
+ }
+
+ if (!interaction.inCachedGuild()) {
+ await interaction.reply(Reply('This bot can only be used in a server!', Color.Error));
+ return;
+ }
+
+ try {
+ /**
+ * @deprecated This is a hacky workaround to use private members of the [CommandInteractionOptionResolver](https://discord.js.org/docs/packages/discord.js/14.15.2/CommandInteractionOptionResolver:Class) class.
+ *
+ * As minor version updates may break this, we should instead use the public properties to achieve this functionality.
+ */
+ type ChatInputCommandInteractionWithPrivateFields = Omit<
+ CommandInteractionOptionResolver<'cached'>,
+ 'getMessage' | 'getFocused'
+ > & {
+ _group: string | null;
+ _hoistedOptions: CommandInteractionOption[];
+ _subcommand: string | null;
+ };
+
+ const { commandName } = interaction;
+ const options = interaction.options as ChatInputCommandInteractionWithPrivateFields;
+
+ const command = commandMap.get(commandName);
+
+ if (!command) {
+ log(`Could not resolve the command with name "${commandName}"`);
+ return;
}
- try {
- const { commandName, options } = interaction as{
- commandName: any;
- options: any;
- };
-
- const command = commandMap.get(commandName);
-
- if (!command) {
- log(`Could not resolve the command with name "${commandName}"`);
- return;
- }
-
- let logMessage = `[Command]: ${commandName}`;
-
- if (options) {
- if (options._group) {
- logMessage += `, Subcommand Group: ${options._group}`;
- }
- if (options._subcommand) {
- logMessage += `, Subcommand: ${options._subcommand}`;
- }
- if (options._hoistedOptions) {
- for (const subcommandOption of options._hoistedOptions) {
- if (subcommandOption.type === 1) {
- logMessage += `, ${subcommandOption.name}`;
- }
- }
- }
+ let logMessage = `[Command]: ${commandName}`;
+
+ if (options) {
+ if (options._group) {
+ logMessage += `, Subcommand Group: ${options._group}`;
+ }
+ if (options._subcommand) {
+ logMessage += `, Subcommand: ${options._subcommand}`;
+ }
+ if (options._hoistedOptions) {
+ for (const subcommandOption of options._hoistedOptions) {
+ if (subcommandOption.type === ApplicationCommandOptionType.Subcommand) {
+ logMessage += `, ${subcommandOption.name}`;
+ }
}
+ }
+ }
- logMessage += ` was executed by ${interaction.user.tag}`;
+ logMessage += ` was executed by ${interaction.user.tag}`;
- log(logMessage);
+ log(logMessage);
- await command.callback({ client, log, interaction });
- } catch (error) {
- const errorEmbed = makeEmbed({
- title: 'An error occurred while executing this command.',
- description: `${error}`,
- color: Color.Error,
- });
+ await command.callback({ client, log, interaction });
+ } catch (error) {
+ const errorEmbed = makeEmbed({
+ title: 'An error occurred while executing this command.',
+ description: String(error),
+ color: Color.Error,
+ });
- log('[Command Error]', error);
+ log('[Command Error]', error);
- await interaction.followUp({ embeds: [errorEmbed] });
+ await interaction.followUp({ embeds: [errorEmbed] });
- if (interaction.deferred || interaction.replied) {
- log('Interaction was already replied to or deferred, ignoring');
- }
+ if (interaction.deferred || interaction.replied) {
+ log('Interaction was already replied to or deferred, ignoring');
}
+ }
});
diff --git a/src/index.ts b/src/index.ts
index 68418da1..0b7c9e22 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,3 +1,3 @@
import 'dotenv/config';
-import('./client');
+void import('./client');
diff --git a/src/lib/autocomplete.ts b/src/lib/autocomplete.ts
index 0ce99d84..f4d56015 100644
--- a/src/lib/autocomplete.ts
+++ b/src/lib/autocomplete.ts
@@ -3,9 +3,9 @@ import { LogMethods } from './index';
/// Props that will be passed through the autocomplete callback.
export interface AutocompleteProps {
- interaction: AutocompleteInteraction<'cached'>;
- client: Client;
- log: LogMethods;
+ interaction: AutocompleteInteraction<'cached'>;
+ client: Client;
+ log: LogMethods;
}
export type AutocompleteCallback = (props: AutocompleteProps) => Awaitable;
diff --git a/src/lib/cache/cacheManager.ts b/src/lib/cache/cacheManager.ts
index 84e67e91..676c025e 100644
--- a/src/lib/cache/cacheManager.ts
+++ b/src/lib/cache/cacheManager.ts
@@ -1,5 +1,16 @@
import { Cache, caching } from 'cache-manager';
-import { getConn, IPrefixCommand, IPrefixCommandCategory, IPrefixCommandChannelDefaultVersion, IPrefixCommandVersion, Logger, PrefixCommand, PrefixCommandCategory, PrefixCommandChannelDefaultVersion, PrefixCommandVersion } from '../index';
+import {
+ getConn,
+ IPrefixCommand,
+ IPrefixCommandCategory,
+ IPrefixCommandChannelDefaultVersion,
+ IPrefixCommandVersion,
+ Logger,
+ PrefixCommand,
+ PrefixCommandCategory,
+ PrefixCommandChannelDefaultVersion,
+ PrefixCommandVersion,
+} from '../index';
let inMemoryCache: Cache;
const cacheSize = 10000;
@@ -11,10 +22,10 @@ const cacheTTL = cacheRefreshInterval * 2 * 1000;
*/
export enum MemoryCachePrefix {
- COMMAND = 'PF_COMMAND',
- VERSION = 'PF_VERSION',
- CATEGORY = 'PF_CATEGORY',
- CHANNEL_DEFAULT_VERSION = 'PF_CHANNEL_VERSION',
+ COMMAND = 'PF_COMMAND',
+ VERSION = 'PF_VERSION',
+ CATEGORY = 'PF_CATEGORY',
+ CHANNEL_DEFAULT_VERSION = 'PF_CHANNEL_VERSION',
}
/**
@@ -22,26 +33,23 @@ export enum MemoryCachePrefix {
*/
export async function setupInMemoryCache(callback = Logger.error) {
- try {
- inMemoryCache = await caching(
- 'memory',
- {
- ttl: cacheTTL,
- max: cacheSize,
- },
- );
- Logger.info('In memory cache set up');
- } catch (err) {
- callback(err);
- }
+ try {
+ inMemoryCache = await caching('memory', {
+ ttl: cacheTTL,
+ max: cacheSize,
+ });
+ Logger.info('In memory cache set up');
+ } catch (err) {
+ callback(err);
+ }
}
export function getInMemoryCache(callback = Logger.error) {
- if (!inMemoryCache) {
- callback(new Error('No in memory cache available.'));
- return null;
- }
- return inMemoryCache;
+ if (!inMemoryCache) {
+ callback(new Error('No in memory cache available.'));
+ return null;
+ }
+ return inMemoryCache;
}
/**
@@ -49,71 +57,75 @@ export function getInMemoryCache(callback = Logger.error) {
*/
export async function clearSinglePrefixCommandCache(command: IPrefixCommand) {
- const inMemoryCache = getInMemoryCache();
- if (!inMemoryCache) return;
+ const inMemoryCache = getInMemoryCache();
+ if (!inMemoryCache) return;
- const { name, aliases } = command;
- Logger.debug(`Clearing cache for command or alias "${name}"`);
- await Promise.all(aliases.map((alias) => inMemoryCache.del(`${MemoryCachePrefix.COMMAND}:${alias.toLowerCase()}`)));
- await inMemoryCache.del(`${MemoryCachePrefix.COMMAND}:${name.toLowerCase()}`);
+ const { name, aliases } = command;
+ Logger.debug(`Clearing cache for command or alias "${name}"`);
+ await Promise.all(aliases.map((alias) => inMemoryCache.del(`${MemoryCachePrefix.COMMAND}:${alias.toLowerCase()}`)));
+ await inMemoryCache.del(`${MemoryCachePrefix.COMMAND}:${name.toLowerCase()}`);
}
export async function loadSinglePrefixCommandToCache(command: IPrefixCommand) {
- const inMemoryCache = getInMemoryCache();
- if (!inMemoryCache) return;
-
- const { name, aliases } = command;
- Logger.debug(`Loading command ${name} to cache`);
- await inMemoryCache.set(`${MemoryCachePrefix.COMMAND}:${name.toLowerCase()}`, command.toObject());
- await Promise.all(aliases.map((alias) => inMemoryCache.set(`${MemoryCachePrefix.COMMAND}:${alias.toLowerCase()}`, command.toObject())));
+ const inMemoryCache = getInMemoryCache();
+ if (!inMemoryCache) return;
+
+ const { name, aliases } = command;
+ Logger.debug(`Loading command ${name} to cache`);
+ await inMemoryCache.set(`${MemoryCachePrefix.COMMAND}:${name.toLowerCase()}`, command.toObject());
+ await Promise.all(
+ aliases.map((alias) =>
+ inMemoryCache.set(`${MemoryCachePrefix.COMMAND}:${alias.toLowerCase()}`, command.toObject()),
+ ),
+ );
}
export async function loadAllPrefixCommandsToCache() {
- const conn = getConn();
- const inMemoryCache = getInMemoryCache();
- if (!conn || !inMemoryCache) return;
+ const conn = getConn();
+ const inMemoryCache = getInMemoryCache();
+ if (!conn || !inMemoryCache) return;
- const prefixCommands = await PrefixCommand.find();
- await Promise.all(prefixCommands.map((command) => loadSinglePrefixCommandToCache(command)));
+ const prefixCommands = await PrefixCommand.find();
+ await Promise.all(prefixCommands.map((command) => loadSinglePrefixCommandToCache(command)));
}
export async function refreshSinglePrefixCommandCache(oldCommand: IPrefixCommand, newCommand: IPrefixCommand) {
- await clearSinglePrefixCommandCache(oldCommand);
- await loadSinglePrefixCommandToCache(newCommand);
+ await clearSinglePrefixCommandCache(oldCommand);
+ await loadSinglePrefixCommandToCache(newCommand);
}
export async function refreshAllPrefixCommandsCache() {
- const conn = getConn();
- const inMemoryCache = getInMemoryCache();
- if (!conn || !inMemoryCache) return;
-
- // Step 1: Get all commands from the database
- const prefixCommands = await PrefixCommand.find();
- // Step 2: Get all commands from the cache
- const cacheKeys = await inMemoryCache.store.keys();
- // Step 3: Loop over cached commands
- for (const key of cacheKeys) {
- if (key.startsWith(`${MemoryCachePrefix.COMMAND}:`)) {
- const checkCommand = key.split(':')[1];
- // Step 3.a: Check if cached command exists in the database list
- let found = false;
- for (const dbCommand of prefixCommands) {
- const { name: dbCommandName, aliases: dbCommandAliases } = dbCommand;
- if (dbCommandName.toLowerCase() === checkCommand.toLowerCase() || dbCommandAliases.includes(checkCommand)) {
- found = true;
- break;
- }
- }
- // Step 3.b: If not found, remove from cache
- if (!found) {
- Logger.debug(`Removing command or alias ${checkCommand} from cache`);
- // eslint-disable-next-line no-await-in-loop
- await inMemoryCache.del(key);
- }
+ const conn = getConn();
+ const inMemoryCache = getInMemoryCache();
+ if (!conn || !inMemoryCache) return;
+
+ // Step 1: Get all commands from the database
+ const prefixCommands = await PrefixCommand.find();
+ // Step 2: Get all commands from the cache
+ const cacheKeys = await inMemoryCache.store.keys();
+ // Step 3: Loop over cached commands
+ for (const key of cacheKeys) {
+ if (key.startsWith(`${MemoryCachePrefix.COMMAND}:`)) {
+ const checkCommand = key.split(':')[1];
+ // Step 3.a: Check if cached command exists in the database list
+ let found = false;
+ for (const dbCommand of prefixCommands) {
+ const { name: dbCommandName, aliases: dbCommandAliases } = dbCommand;
+ if (dbCommandName.toLowerCase() === checkCommand.toLowerCase() || dbCommandAliases.includes(checkCommand)) {
+ found = true;
+ break;
}
+ }
+ // Step 3.b: If not found, remove from cache
+ if (!found) {
+ Logger.debug(`Removing command or alias ${checkCommand} from cache`);
+ // eslint-disable-next-line no-await-in-loop
+ await inMemoryCache.del(key);
+ }
}
- // Step 4: Loop over database commands and update cache
- await Promise.all(prefixCommands.map((dbCommand) => loadSinglePrefixCommandToCache(dbCommand)));
+ }
+ // Step 4: Loop over database commands and update cache
+ await Promise.all(prefixCommands.map((dbCommand) => loadSinglePrefixCommandToCache(dbCommand)));
}
/**
@@ -121,71 +133,77 @@ export async function refreshAllPrefixCommandsCache() {
*/
export async function clearSinglePrefixCommandVersionCache(version: IPrefixCommandVersion) {
- const inMemoryCache = getInMemoryCache();
- if (!inMemoryCache) return;
+ const inMemoryCache = getInMemoryCache();
+ if (!inMemoryCache) return;
- const { alias, _id: versionId } = version;
- Logger.debug(`Clearing cache for command version alias "${alias}"`);
- await inMemoryCache.del(`${MemoryCachePrefix.VERSION}:${alias.toLowerCase()}`);
- await inMemoryCache.del(`${MemoryCachePrefix.VERSION}:${versionId}`);
+ const { alias, _id: versionId } = version;
+ Logger.debug(`Clearing cache for command version alias "${alias}"`);
+ await inMemoryCache.del(`${MemoryCachePrefix.VERSION}:${alias.toLowerCase()}`);
+ await inMemoryCache.del(`${MemoryCachePrefix.VERSION}:${versionId}`);
}
export async function loadSinglePrefixCommandVersionToCache(version: IPrefixCommandVersion) {
- const inMemoryCache = getInMemoryCache();
- if (!inMemoryCache) return;
+ const inMemoryCache = getInMemoryCache();
+ if (!inMemoryCache) return;
- const { alias, _id: versionId } = version;
- Logger.debug(`Loading version with alias ${alias} to cache`);
- await inMemoryCache.set(`${MemoryCachePrefix.VERSION}:${alias.toLowerCase()}`, version.toObject());
- await inMemoryCache.set(`${MemoryCachePrefix.VERSION}:${versionId}`, version.toObject());
+ const { alias, _id: versionId } = version;
+ Logger.debug(`Loading version with alias ${alias} to cache`);
+ await inMemoryCache.set(`${MemoryCachePrefix.VERSION}:${alias.toLowerCase()}`, version.toObject());
+ await inMemoryCache.set(`${MemoryCachePrefix.VERSION}:${versionId}`, version.toObject());
}
export async function loadAllPrefixCommandVersionsToCache() {
- const conn = getConn();
- const inMemoryCache = getInMemoryCache();
- if (!conn || !inMemoryCache) return;
+ const conn = getConn();
+ const inMemoryCache = getInMemoryCache();
+ if (!conn || !inMemoryCache) return;
- const prefixCommandVersions = await PrefixCommandVersion.find();
- await Promise.all(prefixCommandVersions.map((version) => loadSinglePrefixCommandVersionToCache(version)));
+ const prefixCommandVersions = await PrefixCommandVersion.find();
+ await Promise.all(prefixCommandVersions.map((version) => loadSinglePrefixCommandVersionToCache(version)));
}
-export async function refreshSinglePrefixCommandVersionCache(oldVersion: IPrefixCommandVersion, newVersion: IPrefixCommandVersion) {
- await clearSinglePrefixCommandVersionCache(oldVersion);
- await loadSinglePrefixCommandVersionToCache(newVersion);
+export async function refreshSinglePrefixCommandVersionCache(
+ oldVersion: IPrefixCommandVersion,
+ newVersion: IPrefixCommandVersion,
+) {
+ await clearSinglePrefixCommandVersionCache(oldVersion);
+ await loadSinglePrefixCommandVersionToCache(newVersion);
}
export async function refreshAllPrefixCommandVersionsCache() {
- const conn = getConn();
- const inMemoryCache = getInMemoryCache();
- if (!conn || !inMemoryCache) return;
-
- // Step 1: Get all versions from the database
- const prefixCommandVersions = await PrefixCommandVersion.find();
- // Step 2: Get all versions from the cache
- const cacheKeys = await inMemoryCache.store.keys();
- // Step 3: Loop over cached versions
- for (const key of cacheKeys) {
- if (key.startsWith(`${MemoryCachePrefix.VERSION}:`)) {
- const checkVersion = key.split(':')[1];
- // Step 3.a: Check if cached version exists in the database list
- let found = false;
- for (const dbVersion of prefixCommandVersions) {
- const { _id: dbVersionId, alias } = dbVersion;
- if (dbVersionId.toString().toLowerCase() === checkVersion.toLowerCase() || alias.toLowerCase() === checkVersion.toLowerCase()) {
- found = true;
- break;
- }
- }
- // Step 3.b: If not found, remove from cache
- if (!found) {
- Logger.debug(`Removing version with id ${checkVersion} from cache`);
- // eslint-disable-next-line no-await-in-loop
- await inMemoryCache.del(key);
- }
+ const conn = getConn();
+ const inMemoryCache = getInMemoryCache();
+ if (!conn || !inMemoryCache) return;
+
+ // Step 1: Get all versions from the database
+ const prefixCommandVersions = await PrefixCommandVersion.find();
+ // Step 2: Get all versions from the cache
+ const cacheKeys = await inMemoryCache.store.keys();
+ // Step 3: Loop over cached versions
+ for (const key of cacheKeys) {
+ if (key.startsWith(`${MemoryCachePrefix.VERSION}:`)) {
+ const checkVersion = key.split(':')[1];
+ // Step 3.a: Check if cached version exists in the database list
+ let found = false;
+ for (const dbVersion of prefixCommandVersions) {
+ const { _id: dbVersionId, alias } = dbVersion;
+ if (
+ dbVersionId.toString().toLowerCase() === checkVersion.toLowerCase() ||
+ alias.toLowerCase() === checkVersion.toLowerCase()
+ ) {
+ found = true;
+ break;
}
+ }
+ // Step 3.b: If not found, remove from cache
+ if (!found) {
+ Logger.debug(`Removing version with id ${checkVersion} from cache`);
+ // eslint-disable-next-line no-await-in-loop
+ await inMemoryCache.del(key);
+ }
}
- // Step 4: Loop over database versions and update cache
- await Promise.all(prefixCommandVersions.map((dbVersion) => loadSinglePrefixCommandVersionToCache(dbVersion)));
+ }
+ // Step 4: Loop over database versions and update cache
+ await Promise.all(prefixCommandVersions.map((dbVersion) => loadSinglePrefixCommandVersionToCache(dbVersion)));
}
/**
@@ -193,135 +211,150 @@ export async function refreshAllPrefixCommandVersionsCache() {
*/
export async function clearSinglePrefixCommandCategoryCache(category: IPrefixCommandCategory) {
- const inMemoryCache = getInMemoryCache();
- if (!inMemoryCache) return;
+ const inMemoryCache = getInMemoryCache();
+ if (!inMemoryCache) return;
- const { name } = category;
- Logger.debug(`Clearing cache for command category "${name}"`);
- await inMemoryCache.del(`${MemoryCachePrefix.CATEGORY}:${name.toLowerCase()}`);
+ const { name } = category;
+ Logger.debug(`Clearing cache for command category "${name}"`);
+ await inMemoryCache.del(`${MemoryCachePrefix.CATEGORY}:${name.toLowerCase()}`);
}
export async function loadSinglePrefixCommandCategoryToCache(category: IPrefixCommandCategory) {
- const inMemoryCache = getInMemoryCache();
- if (!inMemoryCache) return;
+ const inMemoryCache = getInMemoryCache();
+ if (!inMemoryCache) return;
- const { name } = category;
- Logger.debug(`Loading category ${name} to cache`);
- await inMemoryCache.set(`${MemoryCachePrefix.CATEGORY}:${name.toLowerCase()}`, category.toObject());
+ const { name } = category;
+ Logger.debug(`Loading category ${name} to cache`);
+ await inMemoryCache.set(`${MemoryCachePrefix.CATEGORY}:${name.toLowerCase()}`, category.toObject());
}
export async function loadAllPrefixCommandCategoriesToCache() {
- const conn = getConn();
- const inMemoryCache = getInMemoryCache();
- if (!conn || !inMemoryCache) return;
+ const conn = getConn();
+ const inMemoryCache = getInMemoryCache();
+ if (!conn || !inMemoryCache) return;
- const prefixCommandCategories = await PrefixCommandCategory.find();
- await Promise.all(prefixCommandCategories.map((category) => loadSinglePrefixCommandCategoryToCache(category)));
+ const prefixCommandCategories = await PrefixCommandCategory.find();
+ await Promise.all(prefixCommandCategories.map((category) => loadSinglePrefixCommandCategoryToCache(category)));
}
-export async function refreshSinglePrefixCommandCategoryCache(oldCategory: IPrefixCommandCategory, newCategory: IPrefixCommandCategory) {
- await clearSinglePrefixCommandCategoryCache(oldCategory);
- await loadSinglePrefixCommandCategoryToCache(newCategory);
+export async function refreshSinglePrefixCommandCategoryCache(
+ oldCategory: IPrefixCommandCategory,
+ newCategory: IPrefixCommandCategory,
+) {
+ await clearSinglePrefixCommandCategoryCache(oldCategory);
+ await loadSinglePrefixCommandCategoryToCache(newCategory);
}
export async function refreshAllPrefixCommandCategoriesCache() {
- const conn = getConn();
- const inMemoryCache = getInMemoryCache();
- if (!conn || !inMemoryCache) return;
-
- // Step 1: Get all catagories from the database
- const prefixCommandCategories = await PrefixCommandCategory.find();
- // Step 2: Get all categories from the cache
- const cacheKeys = await inMemoryCache.store.keys();
- // Step 3: Loop over cached categories
- for (const key of cacheKeys) {
- if (key.startsWith(`${MemoryCachePrefix.CATEGORY}:`)) {
- const categoryName = key.split(':')[1];
- // Step 3.a: Check if cached category exists in the database list
- let found = false;
- for (const dbCategory of prefixCommandCategories) {
- const { name: dbCategoryName } = dbCategory;
- if (dbCategoryName.toLowerCase() === categoryName.toLowerCase()) {
- found = true;
- break;
- }
- }
- // Step 3.b: If not found, remove from cache
- if (!found) {
- Logger.debug(`Removing category ${categoryName} from cache`);
- // eslint-disable-next-line no-await-in-loop
- await inMemoryCache.del(key);
- }
+ const conn = getConn();
+ const inMemoryCache = getInMemoryCache();
+ if (!conn || !inMemoryCache) return;
+
+ // Step 1: Get all catagories from the database
+ const prefixCommandCategories = await PrefixCommandCategory.find();
+ // Step 2: Get all categories from the cache
+ const cacheKeys = await inMemoryCache.store.keys();
+ // Step 3: Loop over cached categories
+ for (const key of cacheKeys) {
+ if (key.startsWith(`${MemoryCachePrefix.CATEGORY}:`)) {
+ const categoryName = key.split(':')[1];
+ // Step 3.a: Check if cached category exists in the database list
+ let found = false;
+ for (const dbCategory of prefixCommandCategories) {
+ const { name: dbCategoryName } = dbCategory;
+ if (dbCategoryName.toLowerCase() === categoryName.toLowerCase()) {
+ found = true;
+ break;
}
+ }
+ // Step 3.b: If not found, remove from cache
+ if (!found) {
+ Logger.debug(`Removing category ${categoryName} from cache`);
+ // eslint-disable-next-line no-await-in-loop
+ await inMemoryCache.del(key);
+ }
}
- // Step 4: Loop over database categories and update cache
- await Promise.all(prefixCommandCategories.map((dbCategory) => loadSinglePrefixCommandCategoryToCache(dbCategory)));
+ }
+ // Step 4: Loop over database categories and update cache
+ await Promise.all(prefixCommandCategories.map((dbCategory) => loadSinglePrefixCommandCategoryToCache(dbCategory)));
}
/**
* Prefix Command Channel Default Version Cache Management Functions
*/
-export async function clearSinglePrefixCommandChannelDefaultVersionCache(channelDefaultVersion: IPrefixCommandChannelDefaultVersion) {
- const inMemoryCache = getInMemoryCache();
- if (!inMemoryCache) return;
+export async function clearSinglePrefixCommandChannelDefaultVersionCache(
+ channelDefaultVersion: IPrefixCommandChannelDefaultVersion,
+) {
+ const inMemoryCache = getInMemoryCache();
+ if (!inMemoryCache) return;
- const { channelId } = channelDefaultVersion;
- Logger.debug(`Clearing cache for channel default version for channel "${channelId}"`);
- await inMemoryCache.del(`${MemoryCachePrefix.CHANNEL_DEFAULT_VERSION}:${channelId}`);
+ const { channelId } = channelDefaultVersion;
+ Logger.debug(`Clearing cache for channel default version for channel "${channelId}"`);
+ await inMemoryCache.del(`${MemoryCachePrefix.CHANNEL_DEFAULT_VERSION}:${channelId}`);
}
-export async function loadSinglePrefixCommandChannelDefaultVersionToCache(channelDefaultVersion: IPrefixCommandChannelDefaultVersion) {
- const inMemoryCache = getInMemoryCache();
- if (!inMemoryCache) return;
-
- const { channelId, versionId } = channelDefaultVersion;
- const version = await PrefixCommandVersion.findById(versionId);
- if (version) {
- Logger.debug(`Loading default version for channel ${channelId} to cache`);
- await inMemoryCache.set(`${MemoryCachePrefix.CHANNEL_DEFAULT_VERSION}:${channelId}`, version.toObject());
- }
+export async function loadSinglePrefixCommandChannelDefaultVersionToCache(
+ channelDefaultVersion: IPrefixCommandChannelDefaultVersion,
+) {
+ const inMemoryCache = getInMemoryCache();
+ if (!inMemoryCache) return;
+
+ const { channelId, versionId } = channelDefaultVersion;
+ const version = await PrefixCommandVersion.findById(versionId);
+ if (version) {
+ Logger.debug(`Loading default version for channel ${channelId} to cache`);
+ await inMemoryCache.set(`${MemoryCachePrefix.CHANNEL_DEFAULT_VERSION}:${channelId}`, version.toObject());
+ }
}
export async function loadAllPrefixCommandChannelDefaultVersionsToCache() {
- const conn = getConn();
- const inMemoryCache = getInMemoryCache();
- if (!conn || !inMemoryCache) return;
-
- const PrefixCommandChannelDefaultVersions = await PrefixCommandChannelDefaultVersion.find();
- await Promise.all(PrefixCommandChannelDefaultVersions.map((channelDefaultVersion) => loadSinglePrefixCommandChannelDefaultVersionToCache(channelDefaultVersion)));
+ const conn = getConn();
+ const inMemoryCache = getInMemoryCache();
+ if (!conn || !inMemoryCache) return;
+
+ const PrefixCommandChannelDefaultVersions = await PrefixCommandChannelDefaultVersion.find();
+ await Promise.all(
+ PrefixCommandChannelDefaultVersions.map((channelDefaultVersion) =>
+ loadSinglePrefixCommandChannelDefaultVersionToCache(channelDefaultVersion),
+ ),
+ );
}
export async function refreshAllPrefixCommandChannelDefaultVersionsCache() {
- const conn = getConn();
- const inMemoryCache = getInMemoryCache();
- if (!conn || !inMemoryCache) return;
-
- // Step 1: Get all channel default versions from the database
- const prefixCommandChannelDefaultVersions = await PrefixCommandChannelDefaultVersion.find();
- // Step 2: Get all channel default versions from the cache
- const cacheKeys = await inMemoryCache.store.keys();
- // Step 3: Loop over cached channel default versions
- for (const key of cacheKeys) {
- if (key.startsWith(`${MemoryCachePrefix.CHANNEL_DEFAULT_VERSION}:`)) {
- const channelId = key.split(':')[1];
- // Step 3.a: Check if cached channel default version exists in the database list
- let found = false;
- for (const dbChannelDefaultVersion of prefixCommandChannelDefaultVersions) {
- const { channelId: dbChannelId } = dbChannelDefaultVersion;
- if (dbChannelId.toString().toLowerCase() === channelId.toLowerCase()) {
- found = true;
- break;
- }
- }
- // Step 3.b: If not found, remove from cache
- if (!found) {
- Logger.debug(`Removing channel default version for channel ${channelId} from cache`);
- // eslint-disable-next-line no-await-in-loop
- await inMemoryCache.del(key);
- }
+ const conn = getConn();
+ const inMemoryCache = getInMemoryCache();
+ if (!conn || !inMemoryCache) return;
+
+ // Step 1: Get all channel default versions from the database
+ const prefixCommandChannelDefaultVersions = await PrefixCommandChannelDefaultVersion.find();
+ // Step 2: Get all channel default versions from the cache
+ const cacheKeys = await inMemoryCache.store.keys();
+ // Step 3: Loop over cached channel default versions
+ for (const key of cacheKeys) {
+ if (key.startsWith(`${MemoryCachePrefix.CHANNEL_DEFAULT_VERSION}:`)) {
+ const channelId = key.split(':')[1];
+ // Step 3.a: Check if cached channel default version exists in the database list
+ let found = false;
+ for (const dbChannelDefaultVersion of prefixCommandChannelDefaultVersions) {
+ const { channelId: dbChannelId } = dbChannelDefaultVersion;
+ if (dbChannelId.toString().toLowerCase() === channelId.toLowerCase()) {
+ found = true;
+ break;
}
+ }
+ // Step 3.b: If not found, remove from cache
+ if (!found) {
+ Logger.debug(`Removing channel default version for channel ${channelId} from cache`);
+ // eslint-disable-next-line no-await-in-loop
+ await inMemoryCache.del(key);
+ }
}
- // Step 4: Loop over database channel default versions and update cache
- await Promise.all(prefixCommandChannelDefaultVersions.map((dbChannelDefaultVersion) => loadSinglePrefixCommandChannelDefaultVersionToCache(dbChannelDefaultVersion)));
+ }
+ // Step 4: Loop over database channel default versions and update cache
+ await Promise.all(
+ prefixCommandChannelDefaultVersions.map((dbChannelDefaultVersion) =>
+ loadSinglePrefixCommandChannelDefaultVersionToCache(dbChannelDefaultVersion),
+ ),
+ );
}
diff --git a/src/lib/config.ts b/src/lib/config.ts
index cf36dae1..f73727f5 100644
--- a/src/lib/config.ts
+++ b/src/lib/config.ts
@@ -8,8 +8,8 @@ const imageBaseUrl = originalBaseUrl.endsWith('/') ? originalBaseUrl.slice(0, -1
export { imageBaseUrl };
interface roleAssignmentId {
- group: string,
- roles: { id: string, label: string}[]
+ group: string;
+ roles: { id: string; label: string }[];
}
// Config constants that are directly used in code should be mandatory,
@@ -18,105 +18,105 @@ interface roleAssignmentId {
// Constants that are only part of role groups or role assignment IDs are
// not mandatory, as they can be dynamic.
interface Config {
- aircraftTypeList: {
- [x: string]: string,
- },
- channels: {
- A32NX_SUPPORT: string,
- FAQ: string,
- FLIGHT_SCHOOL: string,
- KNOWN_ISSUES: string,
- MOD_ALERTS: string,
- MOD_LOGS: string,
- ROLES: string,
- SCAM_REPORT_LOGS: string,
- TEAM: string,
- USER_LOGS: string,
- VIDEOS: string,
- [x: string]: string,
- },
- colors: {
- FBW_CYAN: string,
- [x: string]: string,
- },
- commandPermission: {
- MANAGE_SERVER: string,
- [x: string]: string,
- },
- guildId: string,
- modLogExclude: string[],
- roleAssignmentIds: roleAssignmentId[],
- roleGroups: {
- [x: string]: string[],
- },
- prefixCommandPrefix: string,
- prefixCommandPermissionDelay: number,
- roles: {
- ADMIN_TEAM: string,
- BOT_DEVELOPER: string,
- COMMUNITY_SUPPORT: string,
- DEVELOPMENT_TEAM: string,
- FBW_EMERITUS: string,
- MEDIA_TEAM: string,
- MODERATION_TEAM: string,
- [x: string]: string,
- },
- threads: {
- BIRTHDAY_THREAD: string,
- COUNT_THREAD: string,
- [x: string]: string,
- },
- units: {
- CELSIUS: string,
- DEGREES: string,
- [x: string]: string,
- },
- userLogExclude: string[],
+ aircraftTypeList: {
+ [x: string]: string;
+ };
+ channels: {
+ A32NX_SUPPORT: string;
+ FAQ: string;
+ FLIGHT_SCHOOL: string;
+ KNOWN_ISSUES: string;
+ MOD_ALERTS: string;
+ MOD_LOGS: string;
+ ROLES: string;
+ SCAM_REPORT_LOGS: string;
+ TEAM: string;
+ USER_LOGS: string;
+ VIDEOS: string;
+ [x: string]: string;
+ };
+ colors: {
+ FBW_CYAN: string;
+ [x: string]: string;
+ };
+ commandPermission: {
+ MANAGE_SERVER: string;
+ [x: string]: string;
+ };
+ guildId: string;
+ modLogExclude: string[];
+ roleAssignmentIds: roleAssignmentId[];
+ roleGroups: {
+ [x: string]: string[];
+ };
+ prefixCommandPrefix: string;
+ prefixCommandPermissionDelay: number;
+ roles: {
+ ADMIN_TEAM: string;
+ BOT_DEVELOPER: string;
+ COMMUNITY_SUPPORT: string;
+ DEVELOPMENT_TEAM: string;
+ FBW_EMERITUS: string;
+ MEDIA_TEAM: string;
+ MODERATION_TEAM: string;
+ [x: string]: string;
+ };
+ threads: {
+ BIRTHDAY_THREAD: string;
+ COUNT_THREAD: string;
+ [x: string]: string;
+ };
+ units: {
+ CELSIUS: string;
+ DEGREES: string;
+ [x: string]: string;
+ };
+ userLogExclude: string[];
}
let parsedConfig: Config;
try {
- parsedConfig = (botConfig as unknown as Config);
- if (!parsedConfig.commandPermission.MANAGE_SERVER) {
- // Making sure this is always set, even if an empty string is given
- parsedConfig.commandPermission.MANAGE_SERVER = '32';
- }
- const { roles, roleGroups, roleAssignmentIds } = parsedConfig;
- // Parsing Role groups
- const newRoleGroups: { [x: string]: string[] } = {};
- for (const group in roleGroups) {
- if (Object.prototype.hasOwnProperty.call(roleGroups, group)) {
- const groupRoles = roleGroups[group];
- const groupRoleIds = [];
- for (let index = 0; index < groupRoles.length; index++) {
- const groupRole = groupRoles[index];
- if (groupRole in roles) {
- groupRoleIds.push(roles[groupRole]);
- }
- }
- newRoleGroups[group] = groupRoleIds;
+ parsedConfig = botConfig as unknown as Config;
+ if (!parsedConfig.commandPermission.MANAGE_SERVER) {
+ // Making sure this is always set, even if an empty string is given
+ parsedConfig.commandPermission.MANAGE_SERVER = '32';
+ }
+ const { roles, roleGroups, roleAssignmentIds } = parsedConfig;
+ // Parsing Role groups
+ const newRoleGroups: { [x: string]: string[] } = {};
+ for (const group in roleGroups) {
+ if (Object.prototype.hasOwnProperty.call(roleGroups, group)) {
+ const groupRoles = roleGroups[group];
+ const groupRoleIds = [];
+ for (let index = 0; index < groupRoles.length; index++) {
+ const groupRole = groupRoles[index];
+ if (groupRole in roles) {
+ groupRoleIds.push(roles[groupRole]);
}
+ }
+ newRoleGroups[group] = groupRoleIds;
}
- parsedConfig.roleGroups = newRoleGroups;
- // Parsing Role assignment IDs
- const newRoleAssignmentIds: roleAssignmentId[] = [];
- for (let i = 0; i < roleAssignmentIds.length; i++) {
- const roleAssignmentId = roleAssignmentIds[i];
- const { group, roles: roleAssignmentIdRoles } = roleAssignmentId;
- const newRoleAssignmentIdRoles = [];
- for (let j = 0; j < roleAssignmentIdRoles.length; j++) {
- const roleAssignmentIdRole = roleAssignmentIdRoles[j];
- const { id, label } = roleAssignmentIdRole;
- if (id in roles) {
- newRoleAssignmentIdRoles.push({ id: roles[id], label });
- }
- }
- newRoleAssignmentIds.push({ group, roles: newRoleAssignmentIdRoles });
+ }
+ parsedConfig.roleGroups = newRoleGroups;
+ // Parsing Role assignment IDs
+ const newRoleAssignmentIds: roleAssignmentId[] = [];
+ for (let i = 0; i < roleAssignmentIds.length; i++) {
+ const roleAssignmentId = roleAssignmentIds[i];
+ const { group, roles: roleAssignmentIdRoles } = roleAssignmentId;
+ const newRoleAssignmentIdRoles = [];
+ for (let j = 0; j < roleAssignmentIdRoles.length; j++) {
+ const roleAssignmentIdRole = roleAssignmentIdRoles[j];
+ const { id, label } = roleAssignmentIdRole;
+ if (id in roles) {
+ newRoleAssignmentIdRoles.push({ id: roles[id], label });
+ }
}
- parsedConfig.roleAssignmentIds = newRoleAssignmentIds;
+ newRoleAssignmentIds.push({ group, roles: newRoleAssignmentIdRoles });
+ }
+ parsedConfig.roleAssignmentIds = newRoleAssignmentIds;
} catch (e) {
- Logger.error(`Failed to load config: ${e}`);
- exit(1);
+ Logger.error(`Failed to load config: ${JSON.stringify(e)}`);
+ exit(1);
}
const constantsConfig = parsedConfig;
diff --git a/src/lib/contextMenuCommand.ts b/src/lib/contextMenuCommand.ts
index 33051c80..f3bf413b 100644
--- a/src/lib/contextMenuCommand.ts
+++ b/src/lib/contextMenuCommand.ts
@@ -1,32 +1,34 @@
import {
- Awaitable,
- Client,
- ContextMenuCommandBuilder,
- RESTPostAPIApplicationCommandsJSONBody, ContextMenuCommandInteraction,
+ Awaitable,
+ Client,
+ ContextMenuCommandBuilder,
+ RESTPostAPIApplicationCommandsJSONBody,
+ ContextMenuCommandInteraction,
} from 'discord.js';
import { LogMethods } from './index';
export interface ContextMenuCommandProps {
- interaction: ContextMenuCommandInteraction<'cached'>;
- client: Client;
- log: LogMethods;
+ interaction: ContextMenuCommandInteraction<'cached'>;
+ client: Client;
+ log: LogMethods;
}
export type ContextMenuCommandCallback = (props: ContextMenuCommandProps) => Awaitable;
-export type ContextMenuCommandStructure =
- | ContextMenuCommandBuilder
- | RESTPostAPIApplicationCommandsJSONBody
+export type ContextMenuCommandStructure = ContextMenuCommandBuilder | RESTPostAPIApplicationCommandsJSONBody;
export interface ContextMenuCommand {
- meta: ContextMenuCommandStructure;
- callback: ContextMenuCommandCallback;
+ meta: ContextMenuCommandStructure;
+ callback: ContextMenuCommandCallback;
}
export function contextMenuCommandStructure(data: RESTPostAPIApplicationCommandsJSONBody): ContextMenuCommandStructure {
- return data;
+ return data;
}
-export function contextMenuCommand(meta: ContextMenuCommandStructure, callback: ContextMenuCommandCallback): ContextMenuCommand {
- return { meta, callback };
+export function contextMenuCommand(
+ meta: ContextMenuCommandStructure,
+ callback: ContextMenuCommandCallback,
+): ContextMenuCommand {
+ return { meta, callback };
}
diff --git a/src/lib/db.ts b/src/lib/db.ts
index 4f985bcd..ee8b35c5 100644
--- a/src/lib/db.ts
+++ b/src/lib/db.ts
@@ -4,35 +4,35 @@ import { Logger } from './index';
let connection: mongoose.Connection;
export async function connect(url: string, callback = Logger.error) {
- try {
- await mongoose.connect(url);
- connection = mongoose.connection;
+ try {
+ await mongoose.connect(url);
+ connection = mongoose.connection;
- Logger.info('Connected to database');
- } catch (err) {
- callback(err);
- }
+ Logger.info('Connected to database');
+ } catch (err) {
+ callback(err);
+ }
- mongoose.connection.on('error', (err) => {
- callback(err);
- });
+ mongoose.connection.on('error', (err) => {
+ callback(err);
+ });
}
export function getConn(callback = Logger.error) {
- if (!connection || connection.readyState !== mongoose.ConnectionStates.connected) {
- callback(new Error('Not connected to database'));
- } else {
- return connection;
- }
+ if (!connection || connection.readyState !== mongoose.ConnectionStates.connected) {
+ callback(new Error('Not connected to database'));
+ } else {
+ return connection;
+ }
- return null;
+ return null;
}
export async function closeMongooseConnection() {
- try {
- await mongoose.disconnect();
- Logger.info('Mongoose connection closed.');
- } catch (error) {
- Logger.error('Error closing Mongoose connection:', error);
- }
+ try {
+ await mongoose.disconnect();
+ Logger.info('Mongoose connection closed.');
+ } catch (error) {
+ Logger.error('Error closing Mongoose connection:', error);
+ }
}
diff --git a/src/lib/durationInEnglish.ts b/src/lib/durationInEnglish.ts
index 1b15515a..204c7ac5 100644
--- a/src/lib/durationInEnglish.ts
+++ b/src/lib/durationInEnglish.ts
@@ -1,15 +1,17 @@
-export function durationInEnglish(milliseconds: any) {
- const seconds = milliseconds / 1000;
+export function durationInEnglish(milliseconds: number) {
+ const seconds = milliseconds / 1000;
- if (seconds < 60) {
- return `${Math.floor(seconds)} second${Math.floor(seconds) === 1 ? '' : 's'}`;
- } if (seconds < 3600) {
- const minutes = seconds / 60;
- return `${Math.floor(minutes)} minute${Math.floor(minutes) === 1 ? '' : 's'}`;
- } if (seconds < 86400) {
- const hours = seconds / 3600;
- return `${Math.floor(hours)} hour${Math.floor(hours) === 1 ? '' : 's'}`;
- }
- const days = seconds / 86400;
- return `${Math.floor(days)} day${Math.floor(days) === 1 ? '' : 's'}`;
+ if (seconds < 60) {
+ return `${Math.floor(seconds)} second${Math.floor(seconds) === 1 ? '' : 's'}`;
+ }
+ if (seconds < 3600) {
+ const minutes = seconds / 60;
+ return `${Math.floor(minutes)} minute${Math.floor(minutes) === 1 ? '' : 's'}`;
+ }
+ if (seconds < 86400) {
+ const hours = seconds / 3600;
+ return `${Math.floor(hours)} hour${Math.floor(hours) === 1 ? '' : 's'}`;
+ }
+ const days = seconds / 86400;
+ return `${Math.floor(days)} day${Math.floor(days) === 1 ? '' : 's'}`;
}
diff --git a/src/lib/embed.ts b/src/lib/embed.ts
index 5d3f3155..f158a18a 100644
--- a/src/lib/embed.ts
+++ b/src/lib/embed.ts
@@ -4,23 +4,23 @@ import { constantsConfig } from './index';
type ListTypes = 'bullet' | 'ordered';
export function makeEmbed(embed: EmbedData): EmbedBuilder {
- return new EmbedBuilder({
- color: Number(constantsConfig.colors.FBW_CYAN),
- ...embed,
- });
+ return new EmbedBuilder({
+ color: Number(constantsConfig.colors.FBW_CYAN),
+ ...embed,
+ });
}
export function makeLines(lines: string[]): string {
- return lines.join('\n');
+ return lines.join('\n');
}
export const makeList = (lines: string[], type?: ListTypes): string => {
- switch (type) {
+ switch (type) {
case 'bullet':
- return lines.map((line) => `• ${line}`).join('\n');
+ return lines.map((line) => `• ${line}`).join('\n');
case 'ordered':
- return lines.map((line, index) => `${index + 1}. ${line}`).join('\n');
+ return lines.map((line, index) => `${index + 1}. ${line}`).join('\n');
default:
- return lines.map((line) => `- ${line}`).join('\n');
- }
+ return lines.map((line) => `- ${line}`).join('\n');
+ }
};
diff --git a/src/lib/events.ts b/src/lib/events.ts
index cc3e23a4..0b16a43d 100644
--- a/src/lib/events.ts
+++ b/src/lib/events.ts
@@ -7,35 +7,31 @@ export type LogMethods = (...args: unknown[]) => void;
export type EventKeys = keyof ClientEvents;
export interface EventProps {
- client: Client;
- log: LogMethods;
+ client: Client;
+ log: LogMethods;
}
-export type EventCallback = (
- props: EventProps,
- ...args: ClientEvents[T]
-) => Awaitable;
+export type EventCallback = (props: EventProps, ...args: ClientEvents[T]) => Awaitable;
export interface Event {
- key: T;
- callback: EventCallback;
+ key: T;
+ callback: EventCallback;
}
export function event(key: T, callback: EventCallback): Event {
- return { key, callback };
+ return { key, callback };
}
export function registerEvents(client: Client, events: Event[]): void {
- for (const { key, callback } of events) {
- client.on(key, (...args) => {
- // eslint-disable-next-line no-console
- const log = console.log.bind(Logger, `[Event: ${key}]`);
-
- try {
- callback({ client, log }, ...args);
- } catch (e) {
- log('[Uncaught Error]', e);
- }
- });
- }
+ for (const { key, callback } of events) {
+ client.on(key, (...args) => {
+ const log = console.log.bind(Logger, `[Event: ${key}]`);
+
+ try {
+ callback({ client, log }, ...args);
+ } catch (e) {
+ log('[Uncaught Error]', e);
+ }
+ });
+ }
}
diff --git a/src/lib/genericEmbedPagination.ts b/src/lib/genericEmbedPagination.ts
index e1024331..033c2756 100644
--- a/src/lib/genericEmbedPagination.ts
+++ b/src/lib/genericEmbedPagination.ts
@@ -1,61 +1,86 @@
-import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, CommandInteraction, ComponentType, EmbedBuilder, Interaction, InteractionResponse, Message } from 'discord.js';
+import {
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonInteraction,
+ ButtonStyle,
+ CommandInteraction,
+ ComponentType,
+ EmbedBuilder,
+ Interaction,
+ InteractionResponse,
+ Message,
+} from 'discord.js';
-export async function createPaginatedEmbedHandler(initialInteraction: CommandInteraction, embeds: EmbedBuilder[]): Promise {
- let currentPage = 0;
+export async function createPaginatedEmbedHandler(
+ initialInteraction: CommandInteraction,
+ embeds: EmbedBuilder[],
+): Promise {
+ let currentPage = 0;
- const nextButton = new ButtonBuilder()
- .setCustomId('pagination_nextPage')
- .setLabel('Next')
- .setStyle(ButtonStyle.Primary);
+ const nextButton = new ButtonBuilder()
+ .setCustomId('pagination_nextPage')
+ .setLabel('Next')
+ .setStyle(ButtonStyle.Primary);
- const prevButton = new ButtonBuilder()
- .setCustomId('pagination_prevPage')
- .setLabel('Previous')
- .setStyle(ButtonStyle.Primary);
+ const prevButton = new ButtonBuilder()
+ .setCustomId('pagination_prevPage')
+ .setLabel('Previous')
+ .setStyle(ButtonStyle.Primary);
- setButtonDisabledStates();
+ setButtonDisabledStates();
- const buttonRow = new ActionRowBuilder().addComponents(prevButton, nextButton);
+ const buttonRow = new ActionRowBuilder().addComponents(prevButton, nextButton);
- let message: Message | InteractionResponse;
- if (initialInteraction.deferred || initialInteraction.replied) {
- message = await initialInteraction.editReply({ embeds: [embeds[currentPage]], components: [buttonRow] });
- } else {
- message = await initialInteraction.reply({ embeds: [embeds[currentPage]], components: [buttonRow] });
- }
+ let message: Message | InteractionResponse;
+ if (initialInteraction.deferred || initialInteraction.replied) {
+ message = await initialInteraction.editReply({ embeds: [embeds[currentPage]], components: [buttonRow] });
+ } else {
+ message = await initialInteraction.reply({ embeds: [embeds[currentPage]], components: [buttonRow] });
+ }
- const filter = (buttonInteraction: Interaction) => initialInteraction.user.id === buttonInteraction.user.id;
- const collector = message.createMessageComponentCollector({ filter, componentType: ComponentType.Button, time: 120_000 });
+ const filter = (buttonInteraction: Interaction) => initialInteraction.user.id === buttonInteraction.user.id;
+ const collector = message.createMessageComponentCollector({
+ filter,
+ componentType: ComponentType.Button,
+ time: 120_000,
+ });
- collector.on('collect', async (collectedInteraction: ButtonInteraction) => {
- await collectedInteraction.deferUpdate();
+ collector.on('collect', (collectedInteraction: ButtonInteraction) => {
+ void collectedInteraction.deferUpdate();
- if (collectedInteraction.customId === 'pagination_nextPage') {
- currentPage++;
- } else if (collectedInteraction.customId === 'pagination_prevPage') {
- currentPage--;
- }
+ if (collectedInteraction.customId === 'pagination_nextPage') {
+ currentPage++;
+ } else if (collectedInteraction.customId === 'pagination_prevPage') {
+ currentPage--;
+ }
- setButtonDisabledStates();
+ setButtonDisabledStates();
- updateEmbed();
- });
+ void updateEmbed();
+ });
- collector.on('end', async () => {
- handleEmbedExpire();
- });
+ collector.on('end', () => {
+ void handleEmbedExpire();
+ });
- function updateEmbed() {
- initialInteraction.editReply({ embeds: [embeds[currentPage]], components: [buttonRow] });
- }
+ async function updateEmbed() {
+ await initialInteraction.editReply({ embeds: [embeds[currentPage]], components: [buttonRow] });
+ }
- function handleEmbedExpire() {
- const embed = embeds[currentPage];
- initialInteraction.editReply({ embeds: [embed.setFooter({ text: `${embed.data.footer ? `${embed.data.footer.text} - ` : ''}This embed has expired.` })], components: [] });
- }
+ async function handleEmbedExpire() {
+ const embed = embeds[currentPage];
+ await initialInteraction.editReply({
+ embeds: [
+ embed.setFooter({
+ text: `${embed.data.footer ? `${embed.data.footer.text} - ` : ''}This embed has expired.`,
+ }),
+ ],
+ components: [],
+ });
+ }
- function setButtonDisabledStates() {
- prevButton.setDisabled(currentPage <= 0);
- nextButton.setDisabled(currentPage >= embeds.length - 1);
- }
+ function setButtonDisabledStates() {
+ prevButton.setDisabled(currentPage <= 0);
+ nextButton.setDisabled(currentPage >= embeds.length - 1);
+ }
}
diff --git a/src/lib/infractionEmbedPagination.ts b/src/lib/infractionEmbedPagination.ts
index a5150526..49f26e28 100644
--- a/src/lib/infractionEmbedPagination.ts
+++ b/src/lib/infractionEmbedPagination.ts
@@ -1,90 +1,125 @@
-import { ActionRowBuilder, ButtonBuilder, ButtonStyle, Interaction, CommandInteraction, ButtonInteraction, EmbedBuilder } from 'discord.js';
-
-export async function createPaginatedInfractionEmbedHandler(initialInteraction: CommandInteraction, user:string, embeds: EmbedBuilder[], infractionsLengths: { warnsLength: string; timeoutsLength: string; scamLogsLength: string; bansLength: string; unbansLength: string; notesLength: string; }): Promise {
- let currentPage = 0;
-
- const aboutButton = new ButtonBuilder()
- .setCustomId('infractions_about')
- .setLabel('About')
- .setStyle(ButtonStyle.Success);
-
- const warnButton = new ButtonBuilder()
- .setCustomId('infractions_warns')
- .setLabel(`Warns (${infractionsLengths.warnsLength})`)
- .setStyle(ButtonStyle.Primary);
-
- const timeoutButton = new ButtonBuilder()
- .setCustomId('infractions_timeouts')
- .setLabel(`Timeouts (${infractionsLengths.timeoutsLength})`)
- .setStyle(ButtonStyle.Primary);
-
- const scamLogButton = new ButtonBuilder()
- .setCustomId('infractions_scamlog')
- .setLabel(`Scam Logs (${infractionsLengths.scamLogsLength})`)
- .setStyle(ButtonStyle.Primary);
-
- const banButton = new ButtonBuilder()
- .setCustomId('infractions_bans')
- .setLabel(`Bans (${infractionsLengths.bansLength})`)
- .setStyle(ButtonStyle.Primary);
-
- const unbanButton = new ButtonBuilder()
- .setCustomId('infractions_unbans')
- .setLabel(`Unbans (${infractionsLengths.unbansLength})`)
- .setStyle(ButtonStyle.Primary);
-
- const noteButton = new ButtonBuilder()
- .setCustomId('infractions_notes')
- .setLabel(`Notes (${infractionsLengths.notesLength})`)
- .setStyle(ButtonStyle.Primary);
-
- const buttonRow1 = new ActionRowBuilder().addComponents(aboutButton, warnButton, timeoutButton);
- const buttonRow2 = new ActionRowBuilder().addComponents(scamLogButton, banButton, unbanButton, noteButton);
- const message = await initialInteraction.followUp({ embeds: [embeds[currentPage]], components: [buttonRow1, buttonRow2] });
-
- const filter = (interaction: Interaction) => interaction.user.id === user;
- const collector = message.createMessageComponentCollector({ filter, time: 120_000 });
-
- collector.on('collect', async (collectedInteraction: ButtonInteraction) => {
- await collectedInteraction.deferUpdate();
-
- if (collectedInteraction.customId === 'infractions_about') {
- currentPage = 0;
- } else if (collectedInteraction.customId === 'infractions_warns') {
- currentPage = 1;
- } else if (collectedInteraction.customId === 'infractions_timeouts') {
- currentPage = 2;
- } else if (collectedInteraction.customId === 'infractions_scamlog') {
- currentPage = 3;
- } else if (collectedInteraction.customId === 'infractions_bans') {
- currentPage = 4;
- } else if (collectedInteraction.customId === 'infractions_unbans') {
- currentPage = 5;
- } else if (collectedInteraction.customId === 'infractions_notes') {
- currentPage = 6;
- }
-
- updateEmbed();
- });
-
- collector.on('end', async () => {
- handleEmbedExpire();
- });
-
- function updateEmbed() {
- aboutButton.setStyle(currentPage === 0 ? ButtonStyle.Success : ButtonStyle.Primary);
- warnButton.setStyle(currentPage === 1 ? ButtonStyle.Success : ButtonStyle.Primary);
- timeoutButton.setStyle(currentPage === 2 ? ButtonStyle.Success : ButtonStyle.Primary);
- scamLogButton.setStyle(currentPage === 3 ? ButtonStyle.Success : ButtonStyle.Primary);
- banButton.setStyle(currentPage === 4 ? ButtonStyle.Success : ButtonStyle.Primary);
- unbanButton.setStyle(currentPage === 5 ? ButtonStyle.Success : ButtonStyle.Primary);
- noteButton.setStyle(currentPage === 6 ? ButtonStyle.Success : ButtonStyle.Primary);
-
- initialInteraction.editReply({ embeds: [embeds[currentPage]], components: [buttonRow1, buttonRow2] });
+import {
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ Interaction,
+ CommandInteraction,
+ ButtonInteraction,
+ EmbedBuilder,
+} from 'discord.js';
+
+export async function createPaginatedInfractionEmbedHandler(
+ initialInteraction: CommandInteraction,
+ user: string,
+ embeds: EmbedBuilder[],
+ infractionsLengths: {
+ warnsLength: string;
+ timeoutsLength: string;
+ scamLogsLength: string;
+ bansLength: string;
+ unbansLength: string;
+ notesLength: string;
+ },
+): Promise {
+ let currentPage = 0;
+
+ const aboutButton = new ButtonBuilder()
+ .setCustomId('infractions_about')
+ .setLabel('About')
+ .setStyle(ButtonStyle.Success);
+
+ const warnButton = new ButtonBuilder()
+ .setCustomId('infractions_warns')
+ .setLabel(`Warns (${infractionsLengths.warnsLength})`)
+ .setStyle(ButtonStyle.Primary);
+
+ const timeoutButton = new ButtonBuilder()
+ .setCustomId('infractions_timeouts')
+ .setLabel(`Timeouts (${infractionsLengths.timeoutsLength})`)
+ .setStyle(ButtonStyle.Primary);
+
+ const scamLogButton = new ButtonBuilder()
+ .setCustomId('infractions_scamlog')
+ .setLabel(`Scam Logs (${infractionsLengths.scamLogsLength})`)
+ .setStyle(ButtonStyle.Primary);
+
+ const banButton = new ButtonBuilder()
+ .setCustomId('infractions_bans')
+ .setLabel(`Bans (${infractionsLengths.bansLength})`)
+ .setStyle(ButtonStyle.Primary);
+
+ const unbanButton = new ButtonBuilder()
+ .setCustomId('infractions_unbans')
+ .setLabel(`Unbans (${infractionsLengths.unbansLength})`)
+ .setStyle(ButtonStyle.Primary);
+
+ const noteButton = new ButtonBuilder()
+ .setCustomId('infractions_notes')
+ .setLabel(`Notes (${infractionsLengths.notesLength})`)
+ .setStyle(ButtonStyle.Primary);
+
+ const buttonRow1 = new ActionRowBuilder().addComponents(aboutButton, warnButton, timeoutButton);
+ const buttonRow2 = new ActionRowBuilder().addComponents(
+ scamLogButton,
+ banButton,
+ unbanButton,
+ noteButton,
+ );
+ const message = await initialInteraction.followUp({
+ embeds: [embeds[currentPage]],
+ components: [buttonRow1, buttonRow2],
+ });
+
+ const filter = (interaction: Interaction) => interaction.user.id === user;
+ const collector = message.createMessageComponentCollector({ filter, time: 120_000 });
+
+ collector.on('collect', (collectedInteraction: ButtonInteraction) => {
+ void collectedInteraction.deferUpdate();
+
+ if (collectedInteraction.customId === 'infractions_about') {
+ currentPage = 0;
+ } else if (collectedInteraction.customId === 'infractions_warns') {
+ currentPage = 1;
+ } else if (collectedInteraction.customId === 'infractions_timeouts') {
+ currentPage = 2;
+ } else if (collectedInteraction.customId === 'infractions_scamlog') {
+ currentPage = 3;
+ } else if (collectedInteraction.customId === 'infractions_bans') {
+ currentPage = 4;
+ } else if (collectedInteraction.customId === 'infractions_unbans') {
+ currentPage = 5;
+ } else if (collectedInteraction.customId === 'infractions_notes') {
+ currentPage = 6;
}
- function handleEmbedExpire() {
- const embed = embeds[currentPage];
- initialInteraction.editReply({ embeds: [embed.setFooter({ text: `${embed.data.footer ? `${embed.data.footer.text} - ` : ''}This embed has expired.` })], components: [] });
- }
+ void updateEmbed();
+ });
+
+ collector.on('end', () => {
+ void handleEmbedExpire();
+ });
+
+ async function updateEmbed() {
+ aboutButton.setStyle(currentPage === 0 ? ButtonStyle.Success : ButtonStyle.Primary);
+ warnButton.setStyle(currentPage === 1 ? ButtonStyle.Success : ButtonStyle.Primary);
+ timeoutButton.setStyle(currentPage === 2 ? ButtonStyle.Success : ButtonStyle.Primary);
+ scamLogButton.setStyle(currentPage === 3 ? ButtonStyle.Success : ButtonStyle.Primary);
+ banButton.setStyle(currentPage === 4 ? ButtonStyle.Success : ButtonStyle.Primary);
+ unbanButton.setStyle(currentPage === 5 ? ButtonStyle.Success : ButtonStyle.Primary);
+ noteButton.setStyle(currentPage === 6 ? ButtonStyle.Success : ButtonStyle.Primary);
+
+ await initialInteraction.editReply({ embeds: [embeds[currentPage]], components: [buttonRow1, buttonRow2] });
+ }
+
+ async function handleEmbedExpire() {
+ const embed = embeds[currentPage];
+ await initialInteraction.editReply({
+ embeds: [
+ embed.setFooter({
+ text: `${embed.data.footer ? `${embed.data.footer.text} - ` : ''}This embed has expired.`,
+ }),
+ ],
+ components: [],
+ });
+ }
}
diff --git a/src/lib/logger.ts b/src/lib/logger.ts
index d2f2e6f4..2c238a5d 100644
--- a/src/lib/logger.ts
+++ b/src/lib/logger.ts
@@ -1,25 +1,23 @@
import winston from 'winston';
const level = () => {
- if (process.env.DEBUG_MODE === 'true') {
- return 'debug';
- }
+ if (process.env.DEBUG_MODE === 'true') {
+ return 'debug';
+ }
- const env = process.env.NODE_ENV || 'development';
- const isDevelopment = env === 'development';
- return isDevelopment ? 'debug' : 'info';
+ const env = process.env.NODE_ENV || 'development';
+ const isDevelopment = env === 'development';
+ return isDevelopment ? 'debug' : 'info';
};
const format = () => {
- const env = process.env.NODE_ENV || 'development';
- const isDevelopment = env === 'development';
- return isDevelopment ? winston.format.simple() : winston.format.json();
+ const env = process.env.NODE_ENV || 'development';
+ const isDevelopment = env === 'development';
+ return isDevelopment ? winston.format.simple() : winston.format.json();
};
export const Logger = winston.createLogger({
- level: level(),
- format: format(),
- transports: [
- new winston.transports.Console(),
- ],
+ level: level(),
+ format: format(),
+ transports: [new winston.transports.Console()],
});
diff --git a/src/lib/replies.ts b/src/lib/replies.ts
index 472fcf34..7ff9efde 100644
--- a/src/lib/replies.ts
+++ b/src/lib/replies.ts
@@ -4,22 +4,24 @@
import { InteractionReplyOptions, InteractionEditReplyOptions } from 'discord.js';
export enum Color {
- Error = 0xf54242,
- Success = 0x42f551,
- Info = 0x4296f5,
+ Error = 0xf54242,
+ Success = 0x42f551,
+ Info = 0x4296f5,
}
export const EditReply = (msg: string, color: Color = Color.Info): InteractionEditReplyOptions => ({
- content: undefined,
- embeds: [{
- description: msg,
- color,
- }],
- components: [],
- files: [],
+ content: undefined,
+ embeds: [
+ {
+ description: msg,
+ color,
+ },
+ ],
+ components: [],
+ files: [],
});
export const Reply = (msg: string, color: Color = Color.Info): InteractionReplyOptions => ({
- ephemeral: true,
- ...EditReply(msg, color) as InteractionReplyOptions,
+ ephemeral: true,
+ ...(EditReply(msg, color) as InteractionReplyOptions),
});
diff --git a/src/lib/scheduler.ts b/src/lib/scheduler.ts
index ddc1f6a8..79376c26 100644
--- a/src/lib/scheduler.ts
+++ b/src/lib/scheduler.ts
@@ -4,35 +4,35 @@ import { Logger, autoDisableSlowMode, sendHeartbeat, postBirthdays, refreshInMem
let scheduler: Agenda;
export async function setupScheduler(name: string, url: string, callback = Logger.error) {
- try {
- scheduler = new Agenda({
- name,
- processEvery: '30 seconds',
- defaultLockLifetime: 30000, // In milliseconds, this makes sure that if the bot restarts with locked jobs, they get released quickly and tried again.
- db: {
- address: url,
- collection: `${name}Jobs`,
- },
- });
- await scheduler.start();
- scheduler.define('autoDisableSlowMode', autoDisableSlowMode);
- scheduler.define('sendHeartbeat', sendHeartbeat);
- scheduler.define('postBirthdays', postBirthdays);
- scheduler.define('refreshInMemoryCache', refreshInMemoryCache);
- Logger.info('Scheduler set up');
- } catch (err) {
- callback(err);
- }
-
- scheduler.on('error', (err) => {
- callback(err);
+ try {
+ scheduler = new Agenda({
+ name,
+ processEvery: '30 seconds',
+ defaultLockLifetime: 30000, // In milliseconds, this makes sure that if the bot restarts with locked jobs, they get released quickly and tried again.
+ db: {
+ address: url,
+ collection: `${name}Jobs`,
+ },
});
+ await scheduler.start();
+ scheduler.define('autoDisableSlowMode', autoDisableSlowMode);
+ scheduler.define('sendHeartbeat', sendHeartbeat);
+ scheduler.define('postBirthdays', postBirthdays);
+ scheduler.define('refreshInMemoryCache', refreshInMemoryCache);
+ Logger.info('Scheduler set up');
+ } catch (err) {
+ callback(err);
+ }
+
+ scheduler.on('error', (err) => {
+ callback(err);
+ });
}
export function getScheduler(callback = Logger.error) {
- if (!scheduler) {
- callback(new Error('No scheduler available. Check database connection.'));
- return null;
- }
- return scheduler;
+ if (!scheduler) {
+ callback(new Error('No scheduler available. Check database connection.'));
+ return null;
+ }
+ return scheduler;
}
diff --git a/src/lib/schedulerJobs/autoDisableSlowMode.ts b/src/lib/schedulerJobs/autoDisableSlowMode.ts
index 1684d5e2..620b5bdd 100644
--- a/src/lib/schedulerJobs/autoDisableSlowMode.ts
+++ b/src/lib/schedulerJobs/autoDisableSlowMode.ts
@@ -1,81 +1,98 @@
import { Job } from '@hokify/agenda';
-import { ChannelType, TextChannel, Colors } from 'discord.js';
+import { ChannelType, TextChannel, Colors, EmbedField } from 'discord.js';
import { client } from '../../client';
import { constantsConfig, makeEmbed, Logger, getScheduler } from '../index';
-const failedEmbed = (action: string, channel: string) => makeEmbed({
+const failedEmbed = (action: string, channel: string) =>
+ makeEmbed({
title: `Slow Message - ${action} failed`,
description: `Failed to ${action} the slow mode for channel <#${channel}>.`,
color: Colors.Red,
-});
+ });
-const modLogEmbed = (action: string, fields: any, color: number) => makeEmbed({
+const modLogEmbed = (action: string, fields: EmbedField[], color: number) =>
+ makeEmbed({
title: `Slow Mode - ${action}`,
fields,
color,
-});
+ });
export async function autoDisableSlowMode(job: Job) {
- const scheduler = getScheduler();
- if (!scheduler) {
- Logger.error('Failed to get scheduler instance');
- return;
- }
- // Needed because of https://github.com/agenda/agenda/issues/401
- // eslint-disable-next-line no-underscore-dangle
- const matchingJobs = await scheduler.jobs({ _id: job.attrs._id });
- if (matchingJobs.length !== 1) {
- Logger.debug('Job has been deleted already, skipping execution.');
- return;
- }
- const { channelId } = job.attrs.data as { channelId: string };
- const modLogsChannel = client.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel | null;
- const slowmodeChannel = client.channels.resolve(channelId);
- if (!slowmodeChannel || [ChannelType.GuildText, ChannelType.GuildForum, ChannelType.PublicThread, ChannelType.PrivateThread].indexOf(slowmodeChannel.type) === -1) {
- Logger.error('Slow mode - Auto disable - Unable to disable for non-existing channel');
- if (modLogsChannel) {
- await modLogsChannel.send({ embeds: [failedEmbed('Auto disable', channelId)] });
- }
- return;
- }
- try {
- if (slowmodeChannel.type === ChannelType.GuildForum || slowmodeChannel.type === ChannelType.GuildText || slowmodeChannel.type === ChannelType.PrivateThread || slowmodeChannel.type === ChannelType.PublicThread) {
- await slowmodeChannel.setRateLimitPerUser(0, 'Slow mode disabled through bot');
- }
- await job.remove();
- } catch (err) {
- Logger.error(`Failed to auto disable slow mode for channel <#${channelId}>: ${err}`);
- return;
+ const scheduler = getScheduler();
+ if (!scheduler) {
+ Logger.error('Failed to get scheduler instance');
+ return;
+ }
+ // Needed because of https://github.com/agenda/agenda/issues/401
+
+ const matchingJobs = await scheduler.jobs({ _id: job.attrs._id });
+ if (matchingJobs.length !== 1) {
+ Logger.debug('Job has been deleted already, skipping execution.');
+ return;
+ }
+ const { channelId } = job.attrs.data as { channelId: string };
+ const modLogsChannel = client.channels.resolve(constantsConfig.channels.MOD_LOGS) as TextChannel | null;
+ const slowmodeChannel = client.channels.resolve(channelId);
+ if (
+ !slowmodeChannel ||
+ [ChannelType.GuildText, ChannelType.GuildForum, ChannelType.PublicThread, ChannelType.PrivateThread].indexOf(
+ slowmodeChannel.type,
+ ) === -1
+ ) {
+ Logger.error('Slow mode - Auto disable - Unable to disable for non-existing channel');
+ if (modLogsChannel) {
+ await modLogsChannel.send({ embeds: [failedEmbed('Auto disable', channelId)] });
}
+ return;
+ }
- try {
- // @ts-ignore
- await modLogsChannel.send({
- embeds: [modLogEmbed('Auto Disable', [
- {
- inline: true,
- name: 'Channel',
- value: `<#${channelId}>`,
- },
- {
- inline: true,
- name: 'Slow mode limit',
- value: 'Disabled',
- },
- {
- inline: true,
- name: 'Auto disable timeout',
- value: 'None',
- },
- {
- inline: true,
- name: 'Moderator',
- value: 'FBW Bot',
- },
- ],
- Colors.Green)],
- });
- } catch (err) {
- Logger.warn(`Failed to send Mod Log for auto disable of slow mode for channel <#${channelId}>: ${err}`);
+ try {
+ if (
+ slowmodeChannel.type === ChannelType.GuildForum ||
+ slowmodeChannel.type === ChannelType.GuildText ||
+ slowmodeChannel.type === ChannelType.PrivateThread ||
+ slowmodeChannel.type === ChannelType.PublicThread
+ ) {
+ await slowmodeChannel.setRateLimitPerUser(0, 'Slow mode disabled through bot');
}
+ await job.remove();
+ } catch (err) {
+ Logger.error(`Failed to auto disable slow mode for channel <#${channelId}>: ${JSON.stringify(err)}`);
+ return;
+ }
+
+ try {
+ await modLogsChannel!.send({
+ embeds: [
+ modLogEmbed(
+ 'Auto Disable',
+ [
+ {
+ inline: true,
+ name: 'Channel',
+ value: `<#${channelId}>`,
+ },
+ {
+ inline: true,
+ name: 'Slow mode limit',
+ value: 'Disabled',
+ },
+ {
+ inline: true,
+ name: 'Auto disable timeout',
+ value: 'None',
+ },
+ {
+ inline: true,
+ name: 'Moderator',
+ value: 'FBW Bot',
+ },
+ ],
+ Colors.Green,
+ ),
+ ],
+ });
+ } catch (err) {
+ Logger.warn(`Failed to send Mod Log for auto disable of slow mode for channel <#${channelId}>:`, err);
+ }
}
diff --git a/src/lib/schedulerJobs/postBirthdays.ts b/src/lib/schedulerJobs/postBirthdays.ts
index 6b11f669..933b0f5f 100644
--- a/src/lib/schedulerJobs/postBirthdays.ts
+++ b/src/lib/schedulerJobs/postBirthdays.ts
@@ -1,128 +1,129 @@
import { Job } from '@hokify/agenda';
-import { Colors, Guild, TextChannel, ThreadChannel } from 'discord.js';
+import { Colors, TextChannel } from 'discord.js';
import { Logger, getScheduler, constantsConfig, getConn, Birthday, makeEmbed, imageBaseUrl } from '../index';
import { client } from '../../client';
const gifs: string[] = [
- `${imageBaseUrl}/birthday/bubbles.gif`,
- `${imageBaseUrl}/birthday/carrey.gif`,
- `${imageBaseUrl}/birthday/cat.gif`,
- `${imageBaseUrl}/birthday/cat_2.gif`,
- `${imageBaseUrl}/birthday/cat_3.gif`,
- `${imageBaseUrl}/birthday/dance.gif`,
- `${imageBaseUrl}/birthday/dog.gif`,
- `${imageBaseUrl}/birthday/dog_2.gif`,
- `${imageBaseUrl}/birthday/dwight.gif`,
- `${imageBaseUrl}/birthday/elf.gif`,
- `${imageBaseUrl}/birthday/snoop.gif`,
- `${imageBaseUrl}/birthday/yoda.gif`,
+ `${imageBaseUrl}/birthday/bubbles.gif`,
+ `${imageBaseUrl}/birthday/carrey.gif`,
+ `${imageBaseUrl}/birthday/cat.gif`,
+ `${imageBaseUrl}/birthday/cat_2.gif`,
+ `${imageBaseUrl}/birthday/cat_3.gif`,
+ `${imageBaseUrl}/birthday/dance.gif`,
+ `${imageBaseUrl}/birthday/dog.gif`,
+ `${imageBaseUrl}/birthday/dog_2.gif`,
+ `${imageBaseUrl}/birthday/dwight.gif`,
+ `${imageBaseUrl}/birthday/elf.gif`,
+ `${imageBaseUrl}/birthday/snoop.gif`,
+ `${imageBaseUrl}/birthday/yoda.gif`,
];
export async function postBirthdays(job: Job) {
- const scheduler = getScheduler();
- if (!scheduler) {
- Logger.error('Failed to get scheduler instance');
- return;
+ const scheduler = getScheduler();
+ if (!scheduler) {
+ Logger.error('Failed to get scheduler instance');
+ return;
+ }
+
+ const matchingJobs = await scheduler.jobs({ _id: job.attrs._id });
+ if (matchingJobs.length !== 1) {
+ Logger.debug('Job has been deleted already, skipping execution.');
+ return;
+ }
+
+ const guild = client.guilds.resolve(constantsConfig.guildId);
+ if (!guild) {
+ Logger.error('BirthdayHandler - Guild not found.');
+ return;
+ }
+
+ const channel = guild.channels.resolve(constantsConfig.channels.TEAM) as TextChannel | null;
+ if (!channel) {
+ Logger.error('BirthdayHandler - Channel not found.');
+ return;
+ }
+
+ // Get all threads (archived included)
+
+ await channel.threads.fetch({ archived: {} });
+ const thread = channel.threads.cache.find((t) => t.id === constantsConfig.threads.BIRTHDAY_THREAD);
+ if (!thread) {
+ Logger.error('Birthday handler - Thread not found');
+ return;
+ }
+
+ // Unarchive thread if needed
+
+ if (thread.archived) {
+ await thread.setArchived(false);
+ }
+
+ // Get DB Connection
+
+ const conn = getConn();
+ if (!conn) {
+ Logger.error('BirthdayHandler - DB Connection not found, skipping processing.');
+ return;
+ }
+
+ // Get current date
+ const currentDate = new Date();
+
+ // Get all birthdays for today
+ const birthdays = await Birthday.find({ utcDatetime: { $lt: currentDate } });
+
+ // If there are no birthdays, return
+ if (!birthdays.length) {
+ Logger.info('BirthdayHandler - No birthdays found.');
+ return;
+ }
+ Logger.info(`BirthdayHandler - Processing ${birthdays.length} birthdays.`);
+
+ // Send birthday messages
+ const birthdayPromises = birthdays.map(async (birthday) => {
+ let user;
+ try {
+ user = await guild.members.fetch(birthday.userID!);
+ } catch (error) {
+ Logger.error(`BirthdayHandler - Failed to fetch user: ${JSON.stringify(error)}`);
}
- // eslint-disable-next-line no-underscore-dangle
- const matchingJobs = await scheduler.jobs({ _id: job.attrs._id });
- if (matchingJobs.length !== 1) {
- Logger.debug('Job has been deleted already, skipping execution.');
- return;
+ if (!user) {
+ return;
}
- const guild = client.guilds.resolve(constantsConfig.guildId) as Guild | null;
- if (!guild) {
- Logger.error('BirthdayHandler - Guild not found.');
- return;
+ const gif = gifs[Math.floor(Math.random() * gifs.length)];
+
+ // Happy birthday!
+ const birthdayEmbed = makeEmbed({
+ title: 'Happy Birthday!',
+ description: `${user.displayName}'s birthday is today!`,
+ color: Colors.Green,
+ image: { url: gif },
+ });
+
+ // Update birthday to next year
+ const nextBirthdayDatetime = new Date(
+ Date.UTC(currentDate.getUTCFullYear() + 1, birthday.month! - 1, birthday.day!),
+ );
+ nextBirthdayDatetime.setUTCHours(10 - birthday.timezone!);
+ birthday.utcDatetime = nextBirthdayDatetime;
+ try {
+ await birthday.save();
+ } catch (error) {
+ Logger.error(`Birthday handler - Failed to save the new birthday trigger: ${JSON.stringify(error)}`);
}
- const channel = guild.channels.resolve(constantsConfig.channels.TEAM) as TextChannel | null;
- if (!channel) {
- Logger.error('BirthdayHandler - Channel not found.');
- return;
+ // Send the birthday message
+ try {
+ await thread.send({
+ content: user.toString(),
+ embeds: [birthdayEmbed],
+ });
+ } catch (error) {
+ Logger.error(`BirthdayHandler - Failed to send birthday message: ${JSON.stringify(error)}`);
}
+ });
- // Get all threads (archived included)
-
- await channel.threads.fetch({ archived: {} });
- const thread = channel.threads.cache.find((t) => t.id === constantsConfig.threads.BIRTHDAY_THREAD) as ThreadChannel | null;
- if (!thread) {
- Logger.error('Birthday handler - Thread not found');
- return;
- }
-
- // Unarchive thread if needed
-
- if (thread.archived) {
- await thread.setArchived(false);
- }
-
- // Get DB Connection
-
- const conn = getConn();
- if (!conn) {
- Logger.error('BirthdayHandler - DB Connection not found, skipping processing.');
- return;
- }
-
- // Get current date
- const currentDate = new Date();
-
- // Get all birthdays for today
- const birthdays = await Birthday.find({ utcDatetime: { $lt: currentDate } });
-
- // If there are no birthdays, return
- if (!birthdays.length) {
- Logger.info('BirthdayHandler - No birthdays found.');
- return;
- }
- Logger.info(`BirthdayHandler - Processing ${birthdays.length} birthdays.`);
-
- // Send birthday messages
-
- for (const birthday of birthdays) {
- let user;
- try {
- // eslint-disable-next-line no-await-in-loop
- user = await guild.members.fetch(birthday.userID!);
- } catch (error) {
- Logger.error('BirthdayHandler - Failed to fetch user', error);
- }
-
- if (!user) {
- continue;
- }
-
- const gif = gifs[Math.floor(Math.random() * gifs.length)];
-
- // Happy birthday!
- const birthdayEmbed = makeEmbed({
- title: 'Happy Birthday!',
- description: `${user.displayName}'s birthday is today!`,
- color: Colors.Green,
- image: { url: gif },
- });
-
- // Update birthday to next year
- const nextBirthdayDatetime = new Date(Date.UTC(currentDate.getUTCFullYear() + 1, birthday.month! - 1, birthday.day!));
- nextBirthdayDatetime.setUTCHours(10 - birthday.timezone!);
- birthday.utcDatetime = nextBirthdayDatetime;
- try {
- birthday.save();
- } catch (e) {
- Logger.error(`Birthday handler - Failed to save the new birthday trigger: ${e}`);
- }
-
- // Send the birthday message
- try {
- thread.send({
- content: user.toString(),
- embeds: [birthdayEmbed],
- });
- } catch (error) {
- Logger.error('BirthdayHandler - Failed to send birthday message', error);
- }
- }
+ await Promise.all(birthdayPromises);
}
diff --git a/src/lib/schedulerJobs/refreshInMemoryCache.ts b/src/lib/schedulerJobs/refreshInMemoryCache.ts
index 3c4462f4..3e2285ce 100644
--- a/src/lib/schedulerJobs/refreshInMemoryCache.ts
+++ b/src/lib/schedulerJobs/refreshInMemoryCache.ts
@@ -1,38 +1,45 @@
import { Job } from '@hokify/agenda';
-import { Logger, getInMemoryCache, getScheduler, refreshAllPrefixCommandCategoriesCache, refreshAllPrefixCommandChannelDefaultVersionsCache, refreshAllPrefixCommandVersionsCache, refreshAllPrefixCommandsCache } from '../index';
+import {
+ Logger,
+ getInMemoryCache,
+ getScheduler,
+ refreshAllPrefixCommandCategoriesCache,
+ refreshAllPrefixCommandChannelDefaultVersionsCache,
+ refreshAllPrefixCommandVersionsCache,
+ refreshAllPrefixCommandsCache,
+} from '../index';
export async function refreshInMemoryCache(job: Job) {
- const scheduler = getScheduler();
- if (!scheduler) {
- Logger.error('Failed to get scheduler instance');
- return;
- }
+ const scheduler = getScheduler();
+ if (!scheduler) {
+ Logger.error('Failed to get scheduler instance');
+ return;
+ }
- const inMemoryCache = getInMemoryCache();
- if (!inMemoryCache) {
- Logger.error('Failed to get in-memory cache instance');
- return;
- }
+ const inMemoryCache = getInMemoryCache();
+ if (!inMemoryCache) {
+ Logger.error('Failed to get in-memory cache instance');
+ return;
+ }
- // Needed because of https://github.com/agenda/agenda/issues/401
- // eslint-disable-next-line no-underscore-dangle
- const matchingJobs = await scheduler.jobs({ _id: job.attrs._id });
- if (matchingJobs.length !== 1) {
- Logger.debug('Job has been deleted already, skipping execution.');
- return;
- }
+ // Needed because of https://github.com/agenda/agenda/issues/401
+ const matchingJobs = await scheduler.jobs({ _id: job.attrs._id });
+ if (matchingJobs.length !== 1) {
+ Logger.debug('Job has been deleted already, skipping execution.');
+ return;
+ }
- const start = new Date().getTime();
- try {
- await Promise.all([
- refreshAllPrefixCommandVersionsCache(),
- refreshAllPrefixCommandCategoriesCache(),
- refreshAllPrefixCommandsCache(),
- refreshAllPrefixCommandChannelDefaultVersionsCache(),
- ]);
- } catch (error) {
- Logger.error('Failed to refresh the in memory cache:', error);
- }
- const duration = ((new Date().getTime() - start) / 1000).toFixed(2);
- Logger.info(`In memory cache refreshed successfully, duration: ${duration}s`);
+ const start = new Date().getTime();
+ try {
+ await Promise.all([
+ refreshAllPrefixCommandVersionsCache(),
+ refreshAllPrefixCommandCategoriesCache(),
+ refreshAllPrefixCommandsCache(),
+ refreshAllPrefixCommandChannelDefaultVersionsCache(),
+ ]);
+ } catch (error) {
+ Logger.error('Failed to refresh the in memory cache:', error);
+ }
+ const duration = ((new Date().getTime() - start) / 1000).toFixed(2);
+ Logger.info(`In memory cache refreshed successfully, duration: ${duration}s`);
}
diff --git a/src/lib/schedulerJobs/sendHeartbeat.ts b/src/lib/schedulerJobs/sendHeartbeat.ts
index 8aa36286..32c36f1c 100644
--- a/src/lib/schedulerJobs/sendHeartbeat.ts
+++ b/src/lib/schedulerJobs/sendHeartbeat.ts
@@ -2,32 +2,32 @@ import { Job } from '@hokify/agenda';
import { Logger, getScheduler } from '../index';
export async function sendHeartbeat(job: Job) {
- const scheduler = getScheduler();
- if (!scheduler) {
- Logger.error('Failed to get scheduler instance');
- return;
- }
+ const scheduler = getScheduler();
+ if (!scheduler) {
+ Logger.error('Failed to get scheduler instance');
+ return;
+ }
- // Needed because of https://github.com/agenda/agenda/issues/401
- // eslint-disable-next-line no-underscore-dangle
- const matchingJobs = await scheduler.jobs({ _id: job.attrs._id });
- if (matchingJobs.length !== 1) {
- Logger.debug('Job has been deleted already, skipping execution.');
- return;
- }
+ // Needed because of https://github.com/agenda/agenda/issues/401
- const heartbeatUrl = process.env.HEARTBEAT_URL;
- if (!heartbeatUrl) {
- Logger.error('HEARTBEAT_URL environment variable not set');
- return;
- }
- try {
- const heartBeatResult = await fetch(`${heartbeatUrl}`);
- if (heartBeatResult.status !== 200) {
- Logger.error('Failed to send heartbeat:', heartBeatResult.statusText);
- }
- } catch (error) {
- Logger.error('Failed to send heartbeat:', error);
+ const matchingJobs = await scheduler.jobs({ _id: job.attrs._id });
+ if (matchingJobs.length !== 1) {
+ Logger.debug('Job has been deleted already, skipping execution.');
+ return;
+ }
+
+ const heartbeatUrl = process.env.HEARTBEAT_URL;
+ if (!heartbeatUrl) {
+ Logger.error('HEARTBEAT_URL environment variable not set');
+ return;
+ }
+ try {
+ const heartBeatResult = await fetch(`${heartbeatUrl}`);
+ if (heartBeatResult.status !== 200) {
+ Logger.error('Failed to send heartbeat:', heartBeatResult.statusText);
}
- Logger.info('Heartbeat sent successfully');
+ } catch (error) {
+ Logger.error('Failed to send heartbeat:', error);
+ }
+ Logger.info('Heartbeat sent successfully');
}
diff --git a/src/lib/schemas/birthdaySchema.ts b/src/lib/schemas/birthdaySchema.ts
index c9cddb78..122e466b 100644
--- a/src/lib/schemas/birthdaySchema.ts
+++ b/src/lib/schemas/birthdaySchema.ts
@@ -1,11 +1,11 @@
import mongoose, { Schema } from 'mongoose';
const birthdaySchema = new Schema({
- userID: String,
- month: Number,
- day: Number,
- utcDatetime: Date,
- timezone: Number,
+ userID: String,
+ month: Number,
+ day: Number,
+ utcDatetime: Date,
+ timezone: Number,
});
export const Birthday = mongoose.model('Birthday', birthdaySchema);
diff --git a/src/lib/schemas/faqSchema.ts b/src/lib/schemas/faqSchema.ts
index f96c47cb..6269e71b 100644
--- a/src/lib/schemas/faqSchema.ts
+++ b/src/lib/schemas/faqSchema.ts
@@ -1,10 +1,10 @@
import mongoose, { Schema } from 'mongoose';
const faqSchema = new Schema({
- faqTitle: String,
- faqAnswer: String,
- moderatorID: String,
- dateSet: Date,
+ faqTitle: String,
+ faqAnswer: String,
+ moderatorID: String,
+ dateSet: Date,
});
export const FAQ = mongoose.model('FAQ', faqSchema);
diff --git a/src/lib/schemas/infractionSchema.ts b/src/lib/schemas/infractionSchema.ts
index ab3f6767..22114336 100644
--- a/src/lib/schemas/infractionSchema.ts
+++ b/src/lib/schemas/infractionSchema.ts
@@ -1,20 +1,20 @@
import mongoose, { Schema } from 'mongoose';
const infractionSchema = new Schema({
- userID: String,
- infractions: [
- {
- // All infractions must contain the below fields
- infractionType: String, // Ban, Kick, Timeout, ScamLog, Note, etc.
- moderatorID: String,
- reason: String,
- date: Date,
- infractionID: mongoose.Schema.Types.ObjectId,
- // Additional fields specific to each infraction type
- duration: String, // Used for timeouts
- _id: false,
- },
- ],
+ userID: String,
+ infractions: [
+ {
+ // All infractions must contain the below fields
+ infractionType: String, // Ban, Kick, Timeout, ScamLog, Note, etc.
+ moderatorID: String,
+ reason: String,
+ date: Date,
+ infractionID: mongoose.Schema.Types.ObjectId,
+ // Additional fields specific to each infraction type
+ duration: String, // Used for timeouts
+ _id: false,
+ },
+ ],
});
export const Infraction = mongoose.model('Infraction', infractionSchema);
diff --git a/src/lib/schemas/prefixCommandSchemas.ts b/src/lib/schemas/prefixCommandSchemas.ts
index c4dee8b5..3ccf06c6 100644
--- a/src/lib/schemas/prefixCommandSchemas.ts
+++ b/src/lib/schemas/prefixCommandSchemas.ts
@@ -1,136 +1,145 @@
import mongoose, { Schema, Document } from 'mongoose';
export interface IPrefixCommandCategory extends Document {
- categoryId: mongoose.Schema.Types.ObjectId;
- name: string;
- emoji: string;
+ categoryId: mongoose.Schema.Types.ObjectId;
+ name: string;
+ emoji: string;
}
const prefixCommandCategorySchema = new Schema({
- categoryId: mongoose.Schema.Types.ObjectId,
- name: {
- type: String,
- required: true,
- unique: true,
- },
- emoji: String,
+ categoryId: mongoose.Schema.Types.ObjectId,
+ name: {
+ type: String,
+ required: true,
+ unique: true,
+ },
+ emoji: String,
});
export interface IPrefixCommandVersion extends Document {
- versionId: mongoose.Schema.Types.ObjectId;
- name: string;
- emoji: string;
- alias: string;
- enabled: boolean;
+ versionId: mongoose.Schema.Types.ObjectId;
+ name: string;
+ emoji: string;
+ alias: string;
+ enabled: boolean;
}
const prefixCommandVersionSchema = new Schema({
- versionId: mongoose.Schema.Types.ObjectId,
- name: {
- type: String,
- required: true,
- unique: true,
- },
- emoji: {
- type: String,
- required: true,
- unique: true,
- },
- alias: {
- type: String,
- required: true,
- unique: true,
- },
- enabled: Boolean,
+ versionId: mongoose.Schema.Types.ObjectId,
+ name: {
+ type: String,
+ required: true,
+ unique: true,
+ },
+ emoji: {
+ type: String,
+ required: true,
+ unique: true,
+ },
+ alias: {
+ type: String,
+ required: true,
+ unique: true,
+ },
+ enabled: Boolean,
});
export interface IPrefixCommandChannelDefaultVersion extends Document {
- channelId: string;
- versionId: string;
+ channelId: string;
+ versionId: string;
}
const prefixCommandChannelDefaultVersionSchema = new Schema({
- channelId: {
- type: String,
- required: true,
- unique: true,
- },
- versionId: {
- type: String,
- required: true,
- },
+ channelId: {
+ type: String,
+ required: true,
+ unique: true,
+ },
+ versionId: {
+ type: String,
+ required: true,
+ },
});
-export interface IPrefixCommandContent extends Document{
- versionId: string;
- title: string;
- content?: string;
- image?: string;
+export interface IPrefixCommandContent extends Document {
+ versionId: string;
+ title: string;
+ content?: string;
+ image?: string;
}
-const prefixCommandContentSchema = new Schema({
+const prefixCommandContentSchema = new Schema(
+ {
versionId: {
- type: String,
- required: true,
+ type: String,
+ required: true,
},
title: String,
content: String,
image: String,
-}, { autoCreate: false });
+ },
+ { autoCreate: false },
+);
export interface IPrefixCommandPermissions extends Document {
- roles?: string[],
- rolesBlocklist?: boolean,
- channels?: string[],
- channelsBlocklist?: boolean,
- quietErrors?: boolean,
- verboseErrors?: boolean,
+ roles?: string[];
+ rolesBlocklist?: boolean;
+ channels?: string[];
+ channelsBlocklist?: boolean;
+ quietErrors?: boolean;
+ verboseErrors?: boolean;
}
-const prefixCommandPermissionsSchema = new Schema({
+const prefixCommandPermissionsSchema = new Schema(
+ {
roles: [String],
rolesBlocklist: Boolean,
channels: [String],
channelsBlocklist: Boolean,
quietErrors: Boolean,
verboseErrors: Boolean,
-}, { autoCreate: false });
+ },
+ { autoCreate: false },
+);
export interface IPrefixCommand extends Document {
- commandId: mongoose.Schema.Types.ObjectId;
- categoryId: mongoose.Schema.Types.ObjectId;
- name: string;
- description: string;
- aliases: string[];
- isEmbed: boolean;
- embedColor?: string;
- contents: IPrefixCommandContent[];
- permissions: IPrefixCommandPermissions;
+ commandId: mongoose.Schema.Types.ObjectId;
+ categoryId: mongoose.Schema.Types.ObjectId;
+ name: string;
+ description: string;
+ aliases: string[];
+ isEmbed: boolean;
+ embedColor?: string;
+ contents: IPrefixCommandContent[];
+ permissions: IPrefixCommandPermissions;
}
const prefixCommandSchema = new Schema({
- commandId: mongoose.Schema.Types.ObjectId,
- categoryId: {
- type: mongoose.Schema.Types.ObjectId,
- ref: 'PrefixCommandCategory',
- required: true,
- },
- name: {
- type: String,
- required: true,
- unique: true,
- },
- description: String,
- aliases: [{ type: String }],
- isEmbed: Boolean,
- embedColor: String,
- contents: [prefixCommandContentSchema],
- permissions: prefixCommandPermissionsSchema,
+ commandId: mongoose.Schema.Types.ObjectId,
+ categoryId: {
+ type: mongoose.Schema.Types.ObjectId,
+ ref: 'PrefixCommandCategory',
+ required: true,
+ },
+ name: {
+ type: String,
+ required: true,
+ unique: true,
+ },
+ description: String,
+ aliases: [{ type: String }],
+ isEmbed: Boolean,
+ embedColor: String,
+ contents: [prefixCommandContentSchema],
+ permissions: prefixCommandPermissionsSchema,
});
export const PrefixCommandCategory = mongoose.model('PrefixCommandCategory', prefixCommandCategorySchema);
export const PrefixCommandVersion = mongoose.model('PrefixCommandVersion', prefixCommandVersionSchema);
export const PrefixCommandContent = mongoose.model('PrefixCommandContent', prefixCommandContentSchema);
export const PrefixCommandPermissions = mongoose.model('PrefixCommandPermissions', prefixCommandPermissionsSchema);
-export const PrefixCommandChannelDefaultVersion = mongoose.model('PrefixCommandChannelDefaultVersion', prefixCommandChannelDefaultVersionSchema);
+export const PrefixCommandChannelDefaultVersion = mongoose.model(
+ 'PrefixCommandChannelDefaultVersion',
+ prefixCommandChannelDefaultVersionSchema,
+);
export const PrefixCommand = mongoose.model('PrefixCommand', prefixCommandSchema);
diff --git a/src/lib/slashCommand.ts b/src/lib/slashCommand.ts
index 9184c8f3..19fd8c24 100644
--- a/src/lib/slashCommand.ts
+++ b/src/lib/slashCommand.ts
@@ -1,34 +1,47 @@
-import type { Awaitable, Client, ChatInputCommandInteraction, SlashCommandBuilder, SlashCommandSubcommandsOnlyBuilder, RESTPostAPIApplicationCommandsJSONBody } from 'discord.js';
+import type {
+ Awaitable,
+ Client,
+ ChatInputCommandInteraction,
+ SlashCommandBuilder,
+ SlashCommandSubcommandsOnlyBuilder,
+ RESTPostAPIApplicationCommandsJSONBody,
+} from 'discord.js';
import { LogMethods, AutocompleteCallback } from './index';
/// Props that will be passed through the command callback.
export interface SlashCommandProps {
- interaction: ChatInputCommandInteraction<'cached'>,
- client: Client,
- log: LogMethods,
+ interaction: ChatInputCommandInteraction<'cached'>;
+ client: Client;
+ log: LogMethods;
}
export type SlashCommandCallback = (props: SlashCommandProps) => Awaitable;
/// Command structure for slash commands
export type SlashCommandStructure =
- | SlashCommandBuilder & { category?: string }
- | SlashCommandSubcommandsOnlyBuilder & { category?: string }
- | Omit & { category?: string }
- | RESTPostAPIApplicationCommandsJSONBody & { category?: string };
+ | (SlashCommandBuilder & { category?: string })
+ | (SlashCommandSubcommandsOnlyBuilder & { category?: string })
+ | (Omit & { category?: string })
+ | (RESTPostAPIApplicationCommandsJSONBody & { category?: string });
/// Internal structure that represents a command and its callback.
export interface SlashCommand {
- meta: SlashCommandStructure,
- callback: SlashCommandCallback,
- autocompleteCallback?: AutocompleteCallback,
+ meta: SlashCommandStructure;
+ callback: SlashCommandCallback;
+ autocompleteCallback?: AutocompleteCallback;
}
/// Function to provide data for slash commands
-export function slashCommandStructure(data: RESTPostAPIApplicationCommandsJSONBody & { category?: string }): SlashCommandStructure {
- return data;
+export function slashCommandStructure(
+ data: RESTPostAPIApplicationCommandsJSONBody & { category?: string },
+): SlashCommandStructure {
+ return data;
}
/// Creates command structure
-export function slashCommand(meta: SlashCommandStructure, callback: SlashCommandCallback, autocompleteCallback?: AutocompleteCallback): SlashCommand {
- return { meta, callback, autocompleteCallback };
+export function slashCommand(
+ meta: SlashCommandStructure,
+ callback: SlashCommandCallback,
+ autocompleteCallback?: AutocompleteCallback,
+): SlashCommand {
+ return { meta, callback, autocompleteCallback };
}
diff --git a/src/scripts/deployCommands.ts b/src/scripts/deployCommands.ts
index d350c027..200dbb78 100644
--- a/src/scripts/deployCommands.ts
+++ b/src/scripts/deployCommands.ts
@@ -1,28 +1,26 @@
import { REST, Routes, APIUser } from 'discord.js';
-import { constantsConfig } from '../lib';
+import { ContextMenuCommand, SlashCommand, constantsConfig } from '../lib';
if (!constantsConfig.guildId) {
- throw new Error('guildId configuratoin constant is not defined.');
+ throw new Error('guildId configuratoin constant is not defined.');
}
if (!process.env.BOT_SECRET) {
- throw new Error('BOT_SECRET environment variable is not defined.');
+ throw new Error('BOT_SECRET environment variable is not defined.');
}
const rest = new REST({ version: '10' }).setToken(process.env.BOT_SECRET);
-export async function deployCommands(commandArray: any[], contextArray: any[]) {
- const body = [
- ...commandArray.map((cmd) => cmd.meta),
- ...contextArray.map((ctx) => ctx.meta),
- ];
- const currentUser = await rest.get(Routes.user()) as APIUser;
+export async function deployCommands(commandArray: SlashCommand[], contextArray: ContextMenuCommand[]) {
+ const body = [...commandArray.map((cmd) => cmd.meta), ...contextArray.map((ctx) => ctx.meta)];
+ const currentUser = (await rest.get(Routes.user())) as APIUser;
- const endpoint = process.env.NODE_ENV === 'production'
- ? Routes.applicationCommands(currentUser.id)
- : Routes.applicationGuildCommands(currentUser.id, constantsConfig.guildId);
+ const endpoint =
+ process.env.NODE_ENV === 'production'
+ ? Routes.applicationCommands(currentUser.id)
+ : Routes.applicationGuildCommands(currentUser.id, constantsConfig.guildId);
- await rest.put(endpoint, { body });
+ await rest.put(endpoint, { body });
- return currentUser;
+ return currentUser;
}
diff --git a/tsconfig.json b/tsconfig.json
index bb22582a..516305ab 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,17 +1,17 @@
{
"compilerOptions": {
- "target": "ES2020", // Target ES2020 or later
- "module": "CommonJS", // Use CommonJS modules
- "outDir": "./build", // Output directory for compiled files
- "rootDir": "./src", // Source directory
- "strict": true, // Enable strict type checking
- "esModuleInterop": true, // Enable import/export interoperability
+ "target": "ES2020", // Target ES2020 or later
+ "module": "CommonJS", // Use CommonJS modules
+ "outDir": "./build", // Output directory for compiled files
+ "rootDir": "./src", // Source directory
+ "strict": true, // Enable strict type checking
+ "esModuleInterop": true, // Enable import/export interoperability
"forceConsistentCasingInFileNames": true, // Enforce consistent file naming
- "resolveJsonModule": true, // Allow importing JSON files as modules
- "lib": ["ES2020", "DOM"], // Include necessary TypeScript typings
- "types": ["node", "discord.js"], // Include typings for Node.js and discord.js
- "baseUrl": ".", // Base URL for module resolution
+ "resolveJsonModule": true, // Allow importing JSON files as modules
+ "lib": ["ES2020", "DOM"], // Include necessary TypeScript typings
+ "types": ["node", "discord.js"], // Include typings for Node.js and discord.js
+ "baseUrl": "." // Base URL for module resolution
},
- "include": ["src/**/*.ts"], // Include TypeScript source files
+ "include": ["src/**/*.ts"], // Include TypeScript source files
"exclude": ["node_modules", "dist"] // Exclude files from compilation
}