diff --git a/.env b/.env
index 6bc8826..6806c45 100644
--- a/.env
+++ b/.env
@@ -16,6 +16,7 @@ BOT_SOUNDCLOUD_CLIENT_ID=undefined
BOT_SOUNDCLOUD_TOKEN=undefined
BOT_YANDEXMUSIC_TOKEN=undefined
+BOT_YANDEXMUSIC_UID=undefined
MONGO_URI=undefined
MONGO_DATABASE_NAME=undefined
diff --git a/.eslintrc.json b/.eslintrc.json
index a64efde..52940fa 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,10 +1,7 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
- "plugins": [
- "@typescript-eslint",
- "prettier"
- ],
+ "plugins": ["@typescript-eslint", "prettier"],
"env": {
"commonjs": true,
"es2021": true,
@@ -22,6 +19,6 @@
"rules": {
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/no-non-null-assertion": 0,
- "prettier/prettier": 2
+ "prettier/prettier": ["error", { "endOfLine": "auto" }]
}
}
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000..b6599f3
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,61 @@
+name: Bug Report
+description: Bug report for anything
+labels: ["bug"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Please also ensure you have searched for any existing reports of this issue before you begin - if one exists, please leave a thumbs-up and/or a comment on that one, rather than knowingly filing a duplicate report, as duplicates just slow things down.
+
+ Note that most fields are required to be filled-in before you can submit this report, as it is all essential information which we will require in order to confirm and fix your issue.
+
+ - type: dropdown
+ id: user-type
+ attributes:
+ label: Who are you? User (who just use bot from discord)/developer/admin (who download all bot stuff to host)?
+ description: If you are on an older version, update and confirm your issue stil exists!
+ multiple: true
+ options:
+ - User
+ - Developer
+ - Admin
+ validations:
+ required: true
+
+ - type: textarea
+ id: description
+ attributes:
+ label: Description
+ description: Write a concise yet detailed description of the issue!)
+ validations:
+ required: true
+
+ - type: textarea
+ id: steps
+ attributes:
+ label: Steps To Reproduce
+ description: Add detailed, ordered steps for someone else to recreate the issue into the gaps below (add as many steps into the middle as you require)
+ value: |
+ 1. Use command
+ 2.
+ 3.
+ 4. See the issue
+ validations:
+ required: true
+
+ - type: dropdown
+ id: repro-rate
+ attributes:
+ label: How reliably can you recreate this issue using your steps above?
+ options:
+ - Always
+ - Most Times
+ - Only Sometimes
+ - Rarely
+ - Only Ever Happened Once
+ validations:
+ required: true
+
+ - type: markdown
+ attributes:
+ value: Thanks for taking the time to fill out this bug report!
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..ddbc450
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,6 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Frequently Asked Questions
+ url: https://github.com/AlexInCube/AICoTest/wiki/Frequently-Asked-Questions
+ about: AICoTest Frequently Asked Questions
+
diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml
new file mode 100644
index 0000000..cacec3a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature-request.yml
@@ -0,0 +1,35 @@
+name: Feature Request
+description: Suggest an improvement for AICoTest!
+labels: ["feature"]
+body:
+ - type: textarea
+ id: problem
+ attributes:
+ label: Is your feature request related to a problem?
+ description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+ validations:
+ required: true
+
+ - type: textarea
+ id: solution
+ attributes:
+ label: Describe the solution you'd like
+ description: A clear and concise description of what you want to happen.
+ validations:
+ required: true
+
+ - type: textarea
+ id: alternatives
+ attributes:
+ label: Describe alternatives you've considered
+ description: A clear and concise description of any alternative solutions or features you've considered.
+ validations:
+ required: false
+
+ - type: textarea
+ id: additional
+ attributes:
+ label: Additional context
+ description: Add any other context or screenshots about the feature request here.
+ validations:
+ required: false
diff --git a/.github/workflows/wiki.yaml b/.github/workflows/wiki.yaml
new file mode 100644
index 0000000..54d2d7f
--- /dev/null
+++ b/.github/workflows/wiki.yaml
@@ -0,0 +1,15 @@
+name: Wiki
+on:
+ push:
+ branches: ['master']
+ paths:
+ - wiki/**
+ - .github/workflows/wiki.yml
+permissions:
+ contents: write
+jobs:
+ wiki:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: Andrew-Chen-Wang/github-wiki-action@v4
diff --git a/.prettierrc b/.prettierrc
index 83289e0..262579f 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -2,5 +2,6 @@
"semi": true,
"trailingComma": "none",
"singleQuote": true,
- "printWidth": 100
+ "printWidth": 100,
+ "endOfLine": "auto"
}
diff --git a/Dockerfile b/Dockerfile
index da0fa68..0fc98ea 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,8 +12,17 @@ RUN pnpm run build
RUN pnpm prune --prod
FROM base as prod
+
+RUN addgroup --system --gid 1001 nodejs
+RUN adduser --system --uid 1001 aicbot
+
WORKDIR /bot
COPY --from=build /botbuild/build ./build
COPY --from=build /botbuild/node_modules ./node_modules
COPY --from=build /botbuild/package.json .
+
+RUN chown -R aicbot:nodejs /bot
+
+USER aicbot
+
CMD ["npm", "run", "production"]
diff --git a/README.md b/README.md
index 9a349e5..fd7255b 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
AICTest
@@ -7,72 +7,7 @@ Cool audiobot for Discord created by @Ale
## 🌟 Features
- Command /alcotest which shows your alcohol count in blood
-- Audioplayer based on [Distube](https://github.com/skick1234/DisTube) with buttons ![image](https://i.imgur.com/zqQ6ViY.png)
+- Audioplayer based on [Distube](https://github.com/skick1234/DisTube) with buttons ![play-audioplayer](/wiki/images/commands/play-audioplayer.png)
- Support YouTube, Spotify, Soundcloud, any HTTP-stream and Discord Attachments (/playfile support MP3/WAV/OGG)
- Support Slash and Text commands (with customizable prefix per server using /setprefix)
- Localization (English and Russian are currently supported)
-
-## 🎛️ Requirements
-- Node.js 20 or higher
-- MongoDB 6.0 or higher
-- ffmpeg latest
-
-## How to run bot?
-### ⚙️ Configure .env
-You can use Docker image or install things from "Requirements" and source code locally.
-But in both cases, you need to configure .env file.
-
-- Create .env.production
-- Fill all fields in .env.production. If the field is marked as (Optional), you can skip it.
-- (Required) To get Discord Token, follow this [guide](https://discordjs.guide/preparations/setting-up-a-bot-application.html#creating-your-bot). After following the guide, you need to enable privileged intents in [Discord Developer Portal.](https://github.com/AlexInCube/AlCoTest/assets/25522245/fdbcdcf1-9501-47f0-93bf-7e76806f623f)
-- (Optional) To get Spotify Secret and ID, follow this [guide](https://stevesie.com/docs/pages/spotify-client-id-secret-developer-api)
-- (Optional) To get Yandex Music token, follow this [guide](https://github.com/MarshalX/yandex-music-api/discussions/513)
-```
-BOT_VERBOSE_LOGGING= (Optional) The bot will give more information about what it is doing to the console, useful for debugging. By default is: false
-
-BOT_COMMAND_PREFIX= (Required) Used only for text commands, for example: //
-BOT_LANGUAGE= (Optional) Supported values: en ru. By default is: en
-
-MONGO_URI= (Required) If you run bot locally, use mongodb://localhost:27017. If you run in Docker, use mongodb://mongo:27017
-MONGO_DATABASE_NAME= (Required) Database name in MongoDB, for example: aicbot
-
-BOT_DISCORD_TOKEN= (Required)
-BOT_DISCORD_CLIENT_ID= (Required)
-BOT_DISCORD_OVERPOWERED_ID= (Required) This need to retrieve reports in direct message
-
-BOT_SPOTIFY_CLIENT_SECRET= (Optional)
-BOT_SPOTIFY_CLIENT_ID= (Optional)
-
-BOT_YANDEXMUSIC_TOKEN= (Optional)
-```
-
-### 🍪 Youtube Cookie
-Also, it is preferable to provide cookies for YouTube.
-This will allow you to play 18+ videos and bypass YouTube rate limiting error (429 Error).
-I highly recommend that you create a new Google account from which you get the cookie.
-You cannot watch videos in your browser from this account,
-otherwise your cookie will be reset, and you will need to retrieve it again.
-
-- Install an extension for extracting cookie, [EditThisCookie](https://www.editthiscookie.com/blog/2014/03/install-editthiscookie/)
-- Go to [YouTube](https://www.youtube.com/)
-- Log in to your account. (You should use a new account for this purpose)
-- Click on the extension icon and click "Export" button.
-- Create file yt-cookies.json and paste cookie in this file
-
-### 🖥️ Run locally
-- Install things from "Requirements" section
-- Follow the "Configure .env" section and put .env.production in folder with repository.
-- Follow the "YouTube Cookie" section and put yt-cookies.json in the folder with repository.
-- Run commands below
-
-```npm
-npm install
-npm run build
-npm run production
-```
-
-### 🐋 Run in Docker
-- Copy docker-compose.yml, Dockerfile in empty folder
-- Follow the "Configure .env" section and put .env.production in folder with Dockerfile etc.
-- Follow the "YouTube Cookie" section and put yt-cookies.json in the folder with Dockerfile etc.
-- Run command ```docker-compose up --detach --force-recreate``` in folder with files
diff --git a/binding.gyp b/binding.gyp
new file mode 100644
index 0000000..9ed99b8
--- /dev/null
+++ b/binding.gyp
@@ -0,0 +1,17 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'bindings',
+ 'sources': [ 'bindings.node' ],
+ 'cflags!': [ '-fno-exceptions' ],
+ 'cflags_cc!': [ '-fno-exceptions' ],
+ 'conditions': [
+ ['OS=="mac"', {
+ 'xcode_settings': {
+ 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES'
+ }
+ }]
+ ]
+ }
+ ]
+}
diff --git a/docker-compose.yml b/docker-compose.yml
index fb02ffe..a2c8839 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -11,7 +11,7 @@ services:
volumes:
- ./data:/data/db
ports:
- - '27018:27017'
+ - '27017:27017'
aicbot:
container_name: aicbot
image: alexincube/aicotest:latest
diff --git a/icons/audioplayer/player/play.png b/icons/audioplayer/player/play.png
new file mode 100644
index 0000000..a18dd6e
Binary files /dev/null and b/icons/audioplayer/player/play.png differ
diff --git a/icons/audioplayer/services/apple-music.png b/icons/audioplayer/services/apple-music.png
new file mode 100644
index 0000000..1adfdb3
Binary files /dev/null and b/icons/audioplayer/services/apple-music.png differ
diff --git a/icons/audioplayer/services/attach-file.png b/icons/audioplayer/services/attach-file.png
new file mode 100644
index 0000000..ef806ee
Binary files /dev/null and b/icons/audioplayer/services/attach-file.png differ
diff --git a/icons/audioplayer/services/audio-waves.png b/icons/audioplayer/services/audio-waves.png
new file mode 100644
index 0000000..749525d
Binary files /dev/null and b/icons/audioplayer/services/audio-waves.png differ
diff --git a/icons/audioplayer/services/soundcloud.png b/icons/audioplayer/services/soundcloud.png
new file mode 100644
index 0000000..f0243e1
Binary files /dev/null and b/icons/audioplayer/services/soundcloud.png differ
diff --git a/icons/audioplayer/services/spotify.png b/icons/audioplayer/services/spotify.png
new file mode 100644
index 0000000..932dd00
Binary files /dev/null and b/icons/audioplayer/services/spotify.png differ
diff --git a/icons/audioplayer/services/yandex-music.png b/icons/audioplayer/services/yandex-music.png
new file mode 100644
index 0000000..ce681bd
Binary files /dev/null and b/icons/audioplayer/services/yandex-music.png differ
diff --git a/icons/audioplayer/services/youtube.png b/icons/audioplayer/services/youtube.png
new file mode 100644
index 0000000..cf640c6
Binary files /dev/null and b/icons/audioplayer/services/youtube.png differ
diff --git a/icons/error.png b/icons/error.png
new file mode 100644
index 0000000..f3f43b9
Binary files /dev/null and b/icons/error.png differ
diff --git a/src/logo.png b/icons/logo.png
similarity index 100%
rename from src/logo.png
rename to icons/logo.png
diff --git a/icons/warning.png b/icons/warning.png
new file mode 100644
index 0000000..98fc5f3
Binary files /dev/null and b/icons/warning.png differ
diff --git a/package.json b/package.json
index 014826d..3b7cc37 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "aicbot",
- "version": "2.5.0",
+ "version": "3.0.1",
"description": "Discord Bot for playing music",
"main": "build/main.js",
"scripts": {
@@ -13,29 +13,34 @@
"author": "AlexInCube",
"license": "ISC",
"dependencies": {
- "@discordjs/opus": "^0.9.0",
"@discordjs/rest": "^1.7.1",
"@discordjs/voice": "^0.16.1",
- "@distube/soundcloud": "^1.3.5",
- "@distube/spotify": "^1.6.1",
- "@distube/yt-dlp": "^1.1.3",
- "@distube/ytdl-core": "^4.13.3",
+ "@distube/direct-link": "^1.0.1",
+ "@distube/file": "^1.0.1",
+ "@distube/soundcloud": "^2.0.2",
+ "@distube/spotify": "^2.0.2",
+ "@distube/youtube": "^1.0.2",
+ "@distube/yt-dlp": "^2.0.1",
+ "@distube/ytdl-core": "^4.13.4",
+ "@distube/ytsr": "^2.0.4",
"cross-env": "7.0.3",
- "discord.js": "14.14.1",
- "distube": "^4.2.2",
- "distube-yandex-music-plugin": "^0.2.1",
+ "discord.js": "^14.15.3",
+ "distube": "^5.0.2",
+ "distube-apple-music": "^0.1.0",
+ "distube-yandex-music-plugin": "^1.0.4",
"dotenv": "^16.4.5",
"i18next": "^22.5.1",
"i18next-fs-backend": "^2.3.1",
- "mongoose": "^7.6.12",
+ "mongoose": "^7.7.0",
"node-os-utils": "^1.3.7",
+ "opusscript": "^0.1.1",
"prism-media": "^1.3.5",
"sodium-native": "^4.1.1",
"uuid": "^9.0.1",
"zod": "^3.23.8"
},
"devDependencies": {
- "@types/node": "^20.12.12",
+ "@types/node": "^20.14.10",
"@types/node-os-utils": "^1.3.4",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^5.62.0",
@@ -43,7 +48,7 @@
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
- "prettier": "^3.2.5",
- "typescript": "^5.4.5"
+ "prettier": "^3.3.2",
+ "typescript": "^5.5.3"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d300e86..ba2b7a2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,488 +1,310 @@
-lockfileVersion: '6.0'
+lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
-dependencies:
- '@discordjs/opus':
- specifier: ^0.9.0
- version: 0.9.0
- '@discordjs/rest':
- specifier: ^1.7.1
- version: 1.7.1
- '@discordjs/voice':
- specifier: ^0.16.1
- version: 0.16.1(@discordjs/opus@0.9.0)
- '@distube/soundcloud':
- specifier: ^1.3.5
- version: 1.3.5(distube@4.2.2)
- '@distube/spotify':
- specifier: ^1.6.1
- version: 1.6.1(distube@4.2.2)
- '@distube/yt-dlp':
- specifier: ^1.1.3
- version: 1.1.3(distube@4.2.2)
- '@distube/ytdl-core':
- specifier: ^4.13.3
- version: 4.13.3
- cross-env:
- specifier: 7.0.3
- version: 7.0.3
- discord.js:
- specifier: 14.14.1
- version: 14.14.1
- distube:
- specifier: ^4.2.2
- version: 4.2.2(@discordjs/voice@0.16.1)(discord.js@14.14.1)
- distube-yandex-music-plugin:
- specifier: ^0.2.1
- version: 0.2.1(distube@4.2.2)
- dotenv:
- specifier: ^16.4.5
- version: 16.4.5
- i18next:
- specifier: ^22.5.1
- version: 22.5.1
- i18next-fs-backend:
- specifier: ^2.3.1
- version: 2.3.1
- mongoose:
- specifier: ^7.6.12
- version: 7.6.12
- node-os-utils:
- specifier: ^1.3.7
- version: 1.3.7
- prism-media:
- specifier: ^1.3.5
- version: 1.3.5(@discordjs/opus@0.9.0)
- sodium-native:
- specifier: ^4.1.1
- version: 4.1.1
- uuid:
- specifier: ^9.0.1
- version: 9.0.1
- zod:
- specifier: ^3.23.8
- version: 3.23.8
-
-devDependencies:
- '@types/node':
- specifier: ^20.12.12
- version: 20.12.12
- '@types/node-os-utils':
- specifier: ^1.3.4
- version: 1.3.4
- '@types/uuid':
- specifier: ^9.0.8
- version: 9.0.8
- '@typescript-eslint/eslint-plugin':
- specifier: ^5.62.0
- version: 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/parser':
- specifier: ^5.62.0
- version: 5.62.0(eslint@8.57.0)(typescript@5.4.5)
- eslint:
- specifier: ^8.57.0
- version: 8.57.0
- eslint-config-prettier:
- specifier: ^9.1.0
- version: 9.1.0(eslint@8.57.0)
- eslint-plugin-prettier:
- specifier: ^5.1.3
- version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5)
- prettier:
- specifier: ^3.2.5
- version: 3.2.5
- typescript:
- specifier: ^5.4.5
- version: 5.4.5
+importers:
+
+ .:
+ dependencies:
+ '@discordjs/rest':
+ specifier: ^1.7.1
+ version: 1.7.1
+ '@discordjs/voice':
+ specifier: ^0.16.1
+ version: 0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1)
+ '@distube/direct-link':
+ specifier: ^1.0.1
+ version: 1.0.1(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))
+ '@distube/file':
+ specifier: ^1.0.1
+ version: 1.0.1(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))
+ '@distube/soundcloud':
+ specifier: ^2.0.2
+ version: 2.0.2(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))
+ '@distube/spotify':
+ specifier: ^2.0.2
+ version: 2.0.2(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))
+ '@distube/youtube':
+ specifier: ^1.0.2
+ version: 1.0.2(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))
+ '@distube/yt-dlp':
+ specifier: ^2.0.1
+ version: 2.0.1(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))
+ '@distube/ytdl-core':
+ specifier: ^4.13.4
+ version: 4.13.4
+ '@distube/ytsr':
+ specifier: ^2.0.4
+ version: 2.0.4
+ cross-env:
+ specifier: 7.0.3
+ version: 7.0.3
+ discord.js:
+ specifier: ^14.15.3
+ version: 14.15.3
+ distube:
+ specifier: ^5.0.2
+ version: 5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)
+ distube-apple-music:
+ specifier: ^0.1.0
+ version: 0.1.0(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))
+ distube-yandex-music-plugin:
+ specifier: ^1.0.4
+ version: 1.0.4(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))
+ dotenv:
+ specifier: ^16.4.5
+ version: 16.4.5
+ i18next:
+ specifier: ^22.5.1
+ version: 22.5.1
+ i18next-fs-backend:
+ specifier: ^2.3.1
+ version: 2.3.1
+ mongoose:
+ specifier: ^7.7.0
+ version: 7.7.0
+ node-os-utils:
+ specifier: ^1.3.7
+ version: 1.3.7
+ opusscript:
+ specifier: ^0.1.1
+ version: 0.1.1
+ prism-media:
+ specifier: ^1.3.5
+ version: 1.3.5(@discordjs/opus@0.9.0)(opusscript@0.1.1)
+ sodium-native:
+ specifier: ^4.1.1
+ version: 4.1.1
+ uuid:
+ specifier: ^9.0.1
+ version: 9.0.1
+ zod:
+ specifier: ^3.23.8
+ version: 3.23.8
+ devDependencies:
+ '@types/node':
+ specifier: ^20.14.10
+ version: 20.14.10
+ '@types/node-os-utils':
+ specifier: ^1.3.4
+ version: 1.3.4
+ '@types/uuid':
+ specifier: ^9.0.8
+ version: 9.0.8
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^5.62.0
+ version: 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)
+ '@typescript-eslint/parser':
+ specifier: ^5.62.0
+ version: 5.62.0(eslint@8.57.0)(typescript@5.5.3)
+ eslint:
+ specifier: ^8.57.0
+ version: 8.57.0
+ eslint-config-prettier:
+ specifier: ^9.1.0
+ version: 9.1.0(eslint@8.57.0)
+ eslint-plugin-prettier:
+ specifier: ^5.1.3
+ version: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2)
+ prettier:
+ specifier: ^3.3.2
+ version: 3.3.2
+ typescript:
+ specifier: ^5.5.3
+ version: 5.5.3
packages:
- /@babel/runtime@7.24.6:
- resolution: {integrity: sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==}
+ '@babel/runtime@7.24.7':
+ resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==}
engines: {node: '>=6.9.0'}
- dependencies:
- regenerator-runtime: 0.14.1
- dev: false
- /@discordjs/builders@1.8.1:
- resolution: {integrity: sha512-GkF+HM01FHy+NSoTaUPR8z44otfQgJ1AIsRxclYGUZDyUbdZEFyD/5QVv2Y1Flx6M+B0bQLzg2M9CJv5lGTqpA==}
+ '@discordjs/builders@1.8.2':
+ resolution: {integrity: sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g==}
engines: {node: '>=16.11.0'}
- 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
- dev: false
- /@discordjs/collection@1.5.3:
+ '@discordjs/collection@1.5.3':
resolution: {integrity: sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==}
engines: {node: '>=16.11.0'}
- dev: false
- /@discordjs/collection@2.1.0:
+ '@discordjs/collection@2.1.0':
resolution: {integrity: sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==}
engines: {node: '>=18'}
- dev: false
-
- /@discordjs/formatters@0.3.3:
- resolution: {integrity: sha512-wTcI1Q5cps1eSGhl6+6AzzZkBBlVrBdc9IUhJbijRgVjCNIIIZPgqnUj3ntFODsHrdbGU8BEG9XmDQmgEEYn3w==}
- engines: {node: '>=16.11.0'}
- dependencies:
- discord-api-types: 0.37.61
- dev: false
- /@discordjs/formatters@0.4.0:
+ '@discordjs/formatters@0.4.0':
resolution: {integrity: sha512-fJ06TLC1NiruF35470q3Nr1bi95BdvKFAF+T5bNfZJ4bNdqZ3VZ+Ttg6SThqTxm6qumSG3choxLBHMC69WXNXQ==}
engines: {node: '>=16.11.0'}
- dependencies:
- discord-api-types: 0.37.83
- dev: false
- /@discordjs/node-pre-gyp@0.4.5:
+ '@discordjs/node-pre-gyp@0.4.5':
resolution: {integrity: sha512-YJOVVZ545x24mHzANfYoy0BJX5PDyeZlpiJjDkUBM/V/Ao7TFX9lcUvCN4nr0tbr5ubeaXxtEBILUrHtTphVeQ==}
hasBin: true
- dependencies:
- detect-libc: 2.0.3
- https-proxy-agent: 5.0.1
- make-dir: 3.1.0
- node-fetch: 2.7.0
- nopt: 5.0.0
- npmlog: 5.0.1
- rimraf: 3.0.2
- semver: 7.6.2
- tar: 6.2.1
- transitivePeerDependencies:
- - encoding
- - supports-color
- dev: false
- /@discordjs/opus@0.9.0:
+ '@discordjs/opus@0.9.0':
resolution: {integrity: sha512-NEE76A96FtQ5YuoAVlOlB3ryMPrkXbUCTQICHGKb8ShtjXyubGicjRMouHtP1RpuDdm16cDa+oI3aAMo1zQRUQ==}
engines: {node: '>=12.0.0'}
- requiresBuild: true
- dependencies:
- '@discordjs/node-pre-gyp': 0.4.5
- node-addon-api: 5.1.0
- transitivePeerDependencies:
- - encoding
- - supports-color
- dev: false
- /@discordjs/rest@1.7.1:
+ '@discordjs/rest@1.7.1':
resolution: {integrity: sha512-Ofa9UqT0U45G/eX86cURQnX7gzOJLG2oC28VhIk/G6IliYgQF7jFByBJEykPSHE4MxPhqCleYvmsrtfKh1nYmQ==}
engines: {node: '>=16.9.0'}
- dependencies:
- '@discordjs/collection': 1.5.3
- '@discordjs/util': 0.3.1
- '@sapphire/async-queue': 1.5.2
- '@sapphire/snowflake': 3.5.3
- discord-api-types: 0.37.85
- file-type: 18.7.0
- tslib: 2.6.2
- undici: 5.28.4
- dev: false
- /@discordjs/rest@2.3.0:
+ '@discordjs/rest@2.3.0':
resolution: {integrity: sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==}
engines: {node: '>=16.11.0'}
- dependencies:
- '@discordjs/collection': 2.1.0
- '@discordjs/util': 1.1.0
- '@sapphire/async-queue': 1.5.2
- '@sapphire/snowflake': 3.5.3
- '@vladfrangu/async_event_emitter': 2.2.4
- discord-api-types: 0.37.83
- magic-bytes.js: 1.10.0
- tslib: 2.6.2
- undici: 6.13.0
- dev: false
- /@discordjs/util@0.3.1:
+ '@discordjs/util@0.3.1':
resolution: {integrity: sha512-HxXKYKg7vohx2/OupUN/4Sd02Ev3PBJ5q0gtjdcvXb0ErCva8jNHWfe/v5sU3UKjIB/uxOhc+TDOnhqffj9pRA==}
engines: {node: '>=16.9.0'}
- dev: false
- /@discordjs/util@1.1.0:
+ '@discordjs/util@1.1.0':
resolution: {integrity: sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==}
engines: {node: '>=16.11.0'}
- dev: false
- /@discordjs/voice@0.16.1(@discordjs/opus@0.9.0):
+ '@discordjs/voice@0.16.1':
resolution: {integrity: sha512-uiWiW0Ta6K473yf8zs13RfKuPqm/xU4m4dAidMkIdwqgy1CztbbZBtPLfDkVSKzpW7s6m072C+uQcs4LwF3FhA==}
engines: {node: '>=16.11.0'}
- dependencies:
- '@types/ws': 8.5.10
- discord-api-types: 0.37.61
- prism-media: 1.3.5(@discordjs/opus@0.9.0)
- tslib: 2.6.2
- ws: 8.17.0
- transitivePeerDependencies:
- - '@discordjs/opus'
- - bufferutil
- - ffmpeg-static
- - node-opus
- - opusscript
- - utf-8-validate
- dev: false
- /@discordjs/ws@1.1.0:
- resolution: {integrity: sha512-O97DIeSvfNTn5wz5vaER6ciyUsr7nOqSEtsLoMhhIgeFkhnxLRqSr00/Fpq2/ppLgjDGLbQCDzIK7ilGoB/M7A==}
+ '@discordjs/ws@1.1.1':
+ resolution: {integrity: sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==}
engines: {node: '>=16.11.0'}
- dependencies:
- '@discordjs/collection': 2.1.0
- '@discordjs/rest': 2.3.0
- '@discordjs/util': 1.1.0
- '@sapphire/async-queue': 1.5.2
- '@types/ws': 8.5.10
- '@vladfrangu/async_event_emitter': 2.2.4
- discord-api-types: 0.37.83
- tslib: 2.6.2
- ws: 8.17.0
- transitivePeerDependencies:
- - bufferutil
- - utf-8-validate
- dev: false
- /@distube/soundcloud@1.3.5(distube@4.2.2):
- resolution: {integrity: sha512-d/Va+DrBCpwFB7aAEwofAbQ8OWmJViHJtl/OsIfHsNBhh/A5Agp1I0P2Go8dJTQtOhNhKUxgR7Pa1jOxP7m9Xw==}
+ '@distube/direct-link@1.0.1':
+ resolution: {integrity: sha512-NbUzRj1mVOkpmcUrjQ1KjfYDQEeS8uRWGPcgunNmRGdI+BQ5BG+pcHK1r6wMVwzaIdQrpg3X6Sh/T7uG3bdImg==}
peerDependencies:
- distube: 3||4
- dependencies:
- distube: 4.2.2(@discordjs/voice@0.16.1)(discord.js@14.14.1)
- soundcloud.ts: 0.5.3
- dev: false
+ distube: '5'
- /@distube/spotify@1.6.1(distube@4.2.2):
- resolution: {integrity: sha512-nuBftbp05y+pMFcJBlaewauz1LXqrjv5PluIFtlaq50cNx4smton1l3rZxFoqbYQJaFx1cfnbVxwqCUBNEkpIQ==}
+ '@distube/file@1.0.1':
+ resolution: {integrity: sha512-XdWxh4zNI1hdNBf7tAnCL07Mytl63xxVhtF3M3jrh/aklqY9MXlI+bqogmuCa2j8bqTE3XJ/TBwgIhNoyy//JA==}
peerDependencies:
- distube: ^3.3.1||4
- dependencies:
- distube: 4.2.2(@discordjs/voice@0.16.1)(discord.js@14.14.1)
- spotify-uri: 4.1.0
- spotify-url-info: 3.2.15
- spotify-web-api-node: 5.0.2
- undici: 6.18.1
- transitivePeerDependencies:
- - supports-color
- dev: false
+ distube: '5'
- /@distube/yt-dlp@1.1.3(distube@4.2.2):
- resolution: {integrity: sha512-kInFaIgNK7bhUJwY5o/ejBpwHdtLEH9l/GPBl9G7ddMKFYx7/MA5vKZ2F3oZQVMq9pzphPMRpSGi4UBT9L6O2g==}
- engines: {node: '>=12.0.0'}
- requiresBuild: true
+ '@distube/soundcloud@2.0.2':
+ resolution: {integrity: sha512-+SgxJ9jRA0SxInWj23rsvi12nzJ7tNpo42A5SRgeoHVvDp7XgBgTEDg2vvVfnj1WaVIptulZsD7gHDAudURODA==}
peerDependencies:
- distube: 3.x||4.x
- dependencies:
- dargs: 7.0.0
- distube: 4.2.2(@discordjs/voice@0.16.1)(discord.js@14.14.1)
- execa: 5.1.1
- mkdirp: 1.0.4
- undici: 5.28.4
- dev: false
+ distube: '5'
- /@distube/ytdl-core@4.13.3:
- resolution: {integrity: sha512-WHVzp0NyUkmdxRkfU8tN7eRquL7bnia2U/EDNWVupCptRo7EToTdBKHwJrDFqvavbXsdqLG/kR1r+1LaPglrFQ==}
- engines: {node: '>=12'}
- dependencies:
- http-cookie-agent: 5.0.4(tough-cookie@4.1.4)(undici@5.28.4)
- m3u8stream: 0.8.6
- miniget: 4.2.3
- sax: 1.3.0
- tough-cookie: 4.1.4
- undici: 5.28.4
- transitivePeerDependencies:
- - deasync
- - supports-color
- dev: false
+ '@distube/spotify@2.0.2':
+ resolution: {integrity: sha512-rIncX05PhedMZuZyhgz7dt9y/nxir9KPmxUo6sBxfITQcztkXlG3r0EhKivp9+BRCQlEBO/GitRTHVwhRKtmLg==}
+ peerDependencies:
+ distube: '5'
+
+ '@distube/youtube@1.0.2':
+ resolution: {integrity: sha512-vNOE7kGhg3pC87iqT3Q4eu+yTae8Nr3J1XDR67YMH9HAg1RsPjwM7TvfabZoGxIUiPl4ua/PG6s8Nfxf2U9cxQ==}
+ peerDependencies:
+ distube: '5'
- /@distube/ytpl@1.2.1:
+ '@distube/yt-dlp@2.0.1':
+ resolution: {integrity: sha512-9c16lRU6jbyal38UUr5E36+2lp36s0DaJySOtFjuAPgaJkp2xvKvyd+s4rFZSqVQGJO5GOhBiH+HD115SKfKAw==}
+ peerDependencies:
+ distube: '5'
+
+ '@distube/ytdl-core@4.13.4':
+ resolution: {integrity: sha512-AMuKFWN8MHq+gtlhMq2O4jMm7KNtFbXpFMxK6NgDsyMxZT+obH+wVCu/2sj+ZBn6HOnGofvrmb6kAx0P59+lFw==}
+ engines: {node: '>=16'}
+
+ '@distube/ytpl@1.2.1':
resolution: {integrity: sha512-cp9nDYyGTZ2DNHURQXS76ptKWijLMspoxJEj03i++9tJf0LFGTWkskL3sLwcY4qQPLXjlH9FAXwwpjVttdXvZQ==}
engines: {node: '>=8'}
- dependencies:
- undici: 5.28.4
- dev: false
- /@distube/ytsr@2.0.0:
- resolution: {integrity: sha512-N9z8IMbBCQ/gNnJmBgc0TBOU7tdl2nYDOnT6adN1utzIlrKWa2Ux+3UdAPV38f/qRrWohcmyMHPbSbex80ap3A==}
- engines: {node: '>=18.0'}
- dependencies:
- undici: 6.0.1
- dev: false
+ '@distube/ytsr@2.0.4':
+ resolution: {integrity: sha512-OiSWgARQ9LTj+dXt3jmMFzUH4l86VVCD4dVC4hEHNXdqp+DyU4QEzc+W6YY6//kWkvzTaUxOo7JUY7lBzwIF0A==}
+ engines: {node: '>=14.0'}
- /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0):
+ '@eslint-community/eslint-utils@4.4.0':
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
- dependencies:
- eslint: 8.57.0
- eslint-visitor-keys: 3.4.3
- dev: true
- /@eslint-community/regexpp@4.10.0:
- resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==}
+ '@eslint-community/regexpp@4.11.0':
+ resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
- dev: true
- /@eslint/eslintrc@2.1.4:
+ '@eslint/eslintrc@2.1.4':
resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dependencies:
- ajv: 6.12.6
- debug: 4.3.4
- espree: 9.6.1
- globals: 13.24.0
- ignore: 5.3.1
- import-fresh: 3.3.0
- js-yaml: 4.1.0
- minimatch: 3.1.2
- strip-json-comments: 3.1.1
- transitivePeerDependencies:
- - supports-color
- dev: true
- /@eslint/js@8.57.0:
+ '@eslint/js@8.57.0':
resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dev: true
- /@fastify/busboy@2.1.1:
+ '@fastify/busboy@2.1.1':
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
engines: {node: '>=14'}
- dev: false
- /@humanwhocodes/config-array@0.11.14:
+ '@humanwhocodes/config-array@0.11.14':
resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
engines: {node: '>=10.10.0'}
- dependencies:
- '@humanwhocodes/object-schema': 2.0.3
- debug: 4.3.4
- minimatch: 3.1.2
- transitivePeerDependencies:
- - supports-color
- dev: true
+ deprecated: Use @eslint/config-array instead
- /@humanwhocodes/module-importer@1.0.1:
+ '@humanwhocodes/module-importer@1.0.1':
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
engines: {node: '>=12.22'}
- dev: true
- /@humanwhocodes/object-schema@2.0.3:
+ '@humanwhocodes/object-schema@2.0.3':
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
- dev: true
+ deprecated: Use @eslint/object-schema instead
- /@mongodb-js/saslprep@1.1.7:
+ '@mongodb-js/saslprep@1.1.7':
resolution: {integrity: sha512-dCHW/oEX0KJ4NjDULBo3JiOaK5+6axtpBbS+ao2ZInoAL9/YRQLhXzSNAFz7hP4nzLkIqsfYAK/PDE3+XHny0Q==}
- requiresBuild: true
- dependencies:
- sparse-bitfield: 3.0.3
- dev: false
- optional: true
- /@nodelib/fs.scandir@2.1.5:
+ '@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
- dependencies:
- '@nodelib/fs.stat': 2.0.5
- run-parallel: 1.2.0
- dev: true
- /@nodelib/fs.stat@2.0.5:
+ '@nodelib/fs.stat@2.0.5':
resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
engines: {node: '>= 8'}
- dev: true
- /@nodelib/fs.walk@1.2.8:
+ '@nodelib/fs.walk@1.2.8':
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
- dependencies:
- '@nodelib/fs.scandir': 2.1.5
- fastq: 1.17.1
- dev: true
- /@pkgr/core@0.1.1:
+ '@pkgr/core@0.1.1':
resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- dev: true
- /@sapphire/async-queue@1.5.2:
+ '@sapphire/async-queue@1.5.2':
resolution: {integrity: sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
- dev: false
- /@sapphire/shapeshift@3.9.7:
+ '@sapphire/shapeshift@3.9.7':
resolution: {integrity: sha512-4It2mxPSr4OGn4HSQWGmhFMsNFGfFVhWeRPCRwbH972Ek2pzfGRZtb0pJ4Ze6oIzcyh2jw7nUDa6qGlWofgd9g==}
engines: {node: '>=v16'}
- dependencies:
- fast-deep-equal: 3.1.3
- lodash: 4.17.21
- dev: false
-
- /@sapphire/snowflake@3.5.1:
- resolution: {integrity: sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==}
- engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
- dev: false
- /@sapphire/snowflake@3.5.3:
+ '@sapphire/snowflake@3.5.3':
resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
- dev: false
- /@tokenizer/token@0.3.0:
+ '@tokenizer/token@0.3.0':
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
- dev: false
- /@types/json-schema@7.0.15:
+ '@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
- dev: true
- /@types/node-os-utils@1.3.4:
+ '@types/node-os-utils@1.3.4':
resolution: {integrity: sha512-BCUYrbdoO4FUbx6MB9atLNFnkxdliFaxdiTJMIPPiecXIApc5zf4NIqV5G1jWv/ReZvtYyHLs40RkBjHX+vykA==}
- dev: true
- /@types/node@20.12.12:
- resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==}
- dependencies:
- undici-types: 5.26.5
+ '@types/node@20.14.10':
+ resolution: {integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==}
- /@types/semver@7.5.8:
+ '@types/semver@7.5.8':
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
- dev: true
- /@types/uuid@9.0.8:
+ '@types/uuid@9.0.8':
resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==}
- dev: true
- /@types/webidl-conversions@7.0.3:
+ '@types/webidl-conversions@7.0.3':
resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==}
- dev: false
- /@types/whatwg-url@8.2.2:
+ '@types/whatwg-url@8.2.2':
resolution: {integrity: sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==}
- dependencies:
- '@types/node': 20.12.12
- '@types/webidl-conversions': 7.0.3
- dev: false
- /@types/ws@8.5.10:
+ '@types/ws@8.5.10':
resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
- dependencies:
- '@types/node': 20.12.12
- dev: false
-
- /@types/ws@8.5.9:
- resolution: {integrity: sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==}
- dependencies:
- '@types/node': 20.12.12
- dev: false
- /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.57.0)(typescript@5.4.5):
+ '@typescript-eslint/eslint-plugin@5.62.0':
resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -492,25 +314,8 @@ packages:
peerDependenciesMeta:
typescript:
optional: true
- dependencies:
- '@eslint-community/regexpp': 4.10.0
- '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/scope-manager': 5.62.0
- '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
- debug: 4.3.4
- eslint: 8.57.0
- graphemer: 1.4.0
- ignore: 5.3.1
- natural-compare-lite: 1.4.0
- semver: 7.6.2
- tsutils: 3.21.0(typescript@5.4.5)
- typescript: 5.4.5
- transitivePeerDependencies:
- - supports-color
- dev: true
- /@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5):
+ '@typescript-eslint/parser@5.62.0':
resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -519,26 +324,12 @@ packages:
peerDependenciesMeta:
typescript:
optional: true
- dependencies:
- '@typescript-eslint/scope-manager': 5.62.0
- '@typescript-eslint/types': 5.62.0
- '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5)
- debug: 4.3.4
- eslint: 8.57.0
- typescript: 5.4.5
- transitivePeerDependencies:
- - supports-color
- dev: true
- /@typescript-eslint/scope-manager@5.62.0:
+ '@typescript-eslint/scope-manager@5.62.0':
resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dependencies:
- '@typescript-eslint/types': 5.62.0
- '@typescript-eslint/visitor-keys': 5.62.0
- dev: true
- /@typescript-eslint/type-utils@5.62.0(eslint@8.57.0)(typescript@5.4.5):
+ '@typescript-eslint/type-utils@5.62.0':
resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -547,23 +338,12 @@ packages:
peerDependenciesMeta:
typescript:
optional: true
- dependencies:
- '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5)
- '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5)
- debug: 4.3.4
- eslint: 8.57.0
- tsutils: 3.21.0(typescript@5.4.5)
- typescript: 5.4.5
- transitivePeerDependencies:
- - supports-color
- dev: true
- /@typescript-eslint/types@5.62.0:
+ '@typescript-eslint/types@5.62.0':
resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dev: true
- /@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.5):
+ '@typescript-eslint/typescript-estree@5.62.0':
resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -571,418 +351,269 @@ packages:
peerDependenciesMeta:
typescript:
optional: true
- dependencies:
- '@typescript-eslint/types': 5.62.0
- '@typescript-eslint/visitor-keys': 5.62.0
- debug: 4.3.4
- globby: 11.1.0
- is-glob: 4.0.3
- semver: 7.6.2
- tsutils: 3.21.0(typescript@5.4.5)
- typescript: 5.4.5
- transitivePeerDependencies:
- - supports-color
- dev: true
- /@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.4.5):
+ '@typescript-eslint/utils@5.62.0':
resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
- dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
- '@types/json-schema': 7.0.15
- '@types/semver': 7.5.8
- '@typescript-eslint/scope-manager': 5.62.0
- '@typescript-eslint/types': 5.62.0
- '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5)
- eslint: 8.57.0
- eslint-scope: 5.1.1
- semver: 7.6.2
- transitivePeerDependencies:
- - supports-color
- - typescript
- dev: true
- /@typescript-eslint/visitor-keys@5.62.0:
+ '@typescript-eslint/visitor-keys@5.62.0':
resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dependencies:
- '@typescript-eslint/types': 5.62.0
- eslint-visitor-keys: 3.4.3
- dev: true
- /@ungap/structured-clone@1.2.0:
+ '@ungap/structured-clone@1.2.0':
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
- dev: true
- /@vladfrangu/async_event_emitter@2.2.4:
- resolution: {integrity: sha512-ButUPz9E9cXMLgvAW8aLAKKJJsPu1dY1/l/E8xzLFuysowXygs6GBcyunK9rnGC4zTsnIc2mQo71rGw9U+Ykug==}
+ '@vladfrangu/async_event_emitter@2.4.1':
+ resolution: {integrity: sha512-cedU1DrzO4oliUigSAOqSgts6wEfGGSbpO1hYxvKbz8sr7a0meyP3GxnL6hIUtBK0nMG6zHfIYWcqOIb+MRI7w==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
- dev: false
- /abbrev@1.1.1:
+ abbrev@1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
- dev: false
- /acorn-jsx@5.3.2(acorn@8.11.3):
+ acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
- dependencies:
- acorn: 8.11.3
- dev: true
- /acorn@8.11.3:
- resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
+ acorn@8.12.1:
+ resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
engines: {node: '>=0.4.0'}
hasBin: true
- dev: true
- /agent-base@6.0.2:
+ agent-base@6.0.2:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'}
- dependencies:
- debug: 4.3.4
- transitivePeerDependencies:
- - supports-color
- dev: false
- /agent-base@7.1.1:
+ agent-base@7.1.1:
resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==}
engines: {node: '>= 14'}
- dependencies:
- debug: 4.3.4
- transitivePeerDependencies:
- - supports-color
- dev: false
- /ajv@6.12.6:
+ ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
- dependencies:
- fast-deep-equal: 3.1.3
- fast-json-stable-stringify: 2.1.0
- json-schema-traverse: 0.4.1
- uri-js: 4.4.1
- dev: true
- /ansi-regex@5.0.1:
+ ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
- /ansi-styles@4.3.0:
+ ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
- dependencies:
- color-convert: 2.0.1
- dev: true
- /aproba@2.0.0:
+ aproba@2.0.0:
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
- dev: false
- /are-we-there-yet@2.0.0:
+ are-we-there-yet@2.0.0:
resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
engines: {node: '>=10'}
deprecated: This package is no longer supported.
- dependencies:
- delegates: 1.0.0
- readable-stream: 3.6.2
- dev: false
- /argparse@2.0.1:
+ argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
- dev: true
- /array-union@2.1.0:
+ array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
- dev: true
- /asynckit@0.4.0:
+ asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
- dev: false
- /axios@1.7.2:
+ axios@1.7.2:
resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==}
- dependencies:
- follow-redirects: 1.15.6
- form-data: 4.0.0
- proxy-from-env: 1.1.0
- transitivePeerDependencies:
- - debug
- dev: false
- /balanced-match@1.0.2:
+ balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
- /brace-expansion@1.1.11:
+ boolbase@1.0.0:
+ resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+
+ brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
- dependencies:
- balanced-match: 1.0.2
- concat-map: 0.0.1
- /braces@3.0.3:
+ braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
- dependencies:
- fill-range: 7.1.1
- dev: true
- /bson@5.5.1:
+ bson@5.5.1:
resolution: {integrity: sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==}
engines: {node: '>=14.20.1'}
- dev: false
- /call-bind@1.0.7:
+ call-bind@1.0.7:
resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
engines: {node: '>= 0.4'}
- dependencies:
- es-define-property: 1.0.0
- es-errors: 1.3.0
- function-bind: 1.1.2
- get-intrinsic: 1.2.4
- set-function-length: 1.2.2
- dev: false
- /callsites@3.1.0:
+ callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
- dev: true
- /chalk@4.1.2:
+ chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
- dependencies:
- ansi-styles: 4.3.0
- supports-color: 7.2.0
- dev: true
- /chownr@2.0.0:
+ chownr@2.0.0:
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
engines: {node: '>=10'}
- dev: false
- /color-convert@2.0.1:
+ color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
- dependencies:
- color-name: 1.1.4
- dev: true
- /color-name@1.1.4:
+ color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
- dev: true
- /color-support@1.1.3:
+ color-support@1.1.3:
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
hasBin: true
- dev: false
- /combined-stream@1.0.8:
+ combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
- dependencies:
- delayed-stream: 1.0.0
- dev: false
- /component-emitter@1.3.1:
+ component-emitter@1.3.1:
resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==}
- dev: false
- /concat-map@0.0.1:
+ concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
- /console-control-strings@1.1.0:
+ console-control-strings@1.1.0:
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
- dev: false
- /cookiejar@2.1.4:
+ cookiejar@2.1.4:
resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==}
- dev: false
- /cross-env@7.0.3:
+ cross-env@7.0.3:
resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==}
engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
hasBin: true
- dependencies:
- cross-spawn: 7.0.3
- dev: false
- /cross-spawn@7.0.3:
+ cross-spawn@7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'}
- dependencies:
- path-key: 3.1.1
- shebang-command: 2.0.0
- which: 2.0.2
- /crypto@1.0.1:
- resolution: {integrity: sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==}
- deprecated: This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in.
- dev: false
+ css-select@5.1.0:
+ resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
+
+ css-what@6.1.0:
+ resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
+ engines: {node: '>= 6'}
- /dargs@7.0.0:
+ dargs@7.0.0:
resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==}
engines: {node: '>=8'}
- dev: false
- /debug@4.3.4:
- resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ data-uri-to-buffer@4.0.1:
+ resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
+ engines: {node: '>= 12'}
+
+ debug@4.3.5:
+ resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
- dependencies:
- ms: 2.1.2
- /deep-is@0.1.4:
+ deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
- dev: true
- /define-data-property@1.1.4:
+ define-data-property@1.1.4:
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
engines: {node: '>= 0.4'}
- dependencies:
- es-define-property: 1.0.0
- es-errors: 1.3.0
- gopd: 1.0.1
- dev: false
- /delayed-stream@1.0.0:
+ delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
- dev: false
- /delegates@1.0.0:
+ delegates@1.0.0:
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
- dev: false
- /detect-libc@2.0.3:
+ detect-libc@2.0.3:
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
engines: {node: '>=8'}
- dev: false
- /dir-glob@3.0.1:
+ dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
- dependencies:
- path-type: 4.0.0
- dev: true
- /discord-api-types@0.37.61:
+ discord-api-types@0.37.61:
resolution: {integrity: sha512-o/dXNFfhBpYHpQFdT6FWzeO7pKc838QeeZ9d91CfVAtpr5XLK4B/zYxQbYgPdoMiTDvJfzcsLW5naXgmHGDNXw==}
- dev: false
- /discord-api-types@0.37.83:
+ discord-api-types@0.37.83:
resolution: {integrity: sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==}
- dev: false
- /discord-api-types@0.37.85:
- resolution: {integrity: sha512-T75aB9JEw9X0rlMChEMHbr9JlXMqdmdKiZVjBeKs91cJo28IuAIldj+VZoC+I+Q9gCaRjHlwRkcksy2XZY6c3A==}
- dev: false
+ discord-api-types@0.37.92:
+ resolution: {integrity: sha512-7xnedbQRLRef/O+4jKPyIFwl6YqoyihOG3OSneiRmVJMBk30ph2YuZGcHjeX1Kk/a3yQWeyCKe4RZJB3iECcxg==}
- /discord.js@14.14.1:
- resolution: {integrity: sha512-/hUVzkIerxKHyRKopJy5xejp4MYKDPTszAnpYxzVVv4qJYf+Tkt+jnT2N29PIPschicaEEpXwF2ARrTYHYwQ5w==}
+ discord.js@14.15.3:
+ resolution: {integrity: sha512-/UJDQO10VuU6wQPglA4kz2bw2ngeeSbogiIPx/TsnctfzV/tNf+q+i1HlgtX1OGpeOBpJH9erZQNO5oRM2uAtQ==}
engines: {node: '>=16.11.0'}
- dependencies:
- '@discordjs/builders': 1.8.1
- '@discordjs/collection': 1.5.3
- '@discordjs/formatters': 0.3.3
- '@discordjs/rest': 2.3.0
- '@discordjs/util': 1.1.0
- '@discordjs/ws': 1.1.0
- '@sapphire/snowflake': 3.5.1
- '@types/ws': 8.5.9
- discord-api-types: 0.37.61
- fast-deep-equal: 3.1.3
- lodash.snakecase: 4.1.1
- tslib: 2.6.2
- undici: 5.27.2
- ws: 8.14.2
- transitivePeerDependencies:
- - bufferutil
- - utf-8-validate
- dev: false
- /distube-yandex-music-plugin@0.2.1(distube@4.2.2):
- resolution: {integrity: sha512-irCjn3t3JctfxLR86Mi9twcvDs8hTouYArpFR2nV/SkW59z1SA/0XUfqAJ0pBBW/aSADR06RqJi/WMH4MIWVPw==}
+ distube-apple-music@0.1.0:
+ resolution: {integrity: sha512-f+YMXZ5+9RX7HTvtp0V51A987RwiniiCyDzwy0ZFVFgWQq0EPqziYEmZ5D1RSZ6c5s6+YCc9vIC8KPulezdhIw==}
peerDependencies:
- distube: ^3.3.1||4
- dependencies:
- axios: 1.7.2
- distube: 4.2.2(@discordjs/voice@0.16.1)(discord.js@14.14.1)
- yandex-music-client: 0.4.3
- transitivePeerDependencies:
- - debug
- dev: false
+ distube: '5'
- /distube@4.2.2(@discordjs/voice@0.16.1)(discord.js@14.14.1):
- resolution: {integrity: sha512-DBfyScFM66RFGWzPlf+mXy4uU4wfF33qyCr+ojDjHsVYy7m7CJo3e9tkpz/PhIo8OdU/gb4TDiUHc8Pj0r5B/Q==}
+ distube-yandex-music-plugin@1.0.4:
+ resolution: {integrity: sha512-A3VnMHqyoKxsp/2S1ZSuYpSOQboY2H2kr4zwIY7OYoVBAy4ZDbzKC2IWB47F49n+bz6kgi4tnps5WI+8wg2DRg==}
+ peerDependencies:
+ distube: '5'
+
+ distube@5.0.2:
+ resolution: {integrity: sha512-VR+js/RS+sbxQIGaewh1jZtQDeSE1x05V6CFDb7/KATXSln+nUemIh/RTqKPuPeFJhcPcYGdZWPvEliDU/RS/g==}
engines: {node: '>=18.17'}
peerDependencies:
'@discordjs/voice': '*'
discord.js: '14'
- dependencies:
- '@discordjs/voice': 0.16.1(@discordjs/opus@0.9.0)
- '@distube/ytdl-core': 4.13.3
- '@distube/ytpl': 1.2.1
- '@distube/ytsr': 2.0.0
- discord.js: 14.14.1
- tiny-typed-emitter: 2.1.0
- tough-cookie: 4.1.4
- tslib: 2.6.2
- undici: 6.18.1
- transitivePeerDependencies:
- - deasync
- - supports-color
- dev: false
- /doctrine@3.0.0:
+ doctrine@3.0.0:
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
engines: {node: '>=6.0.0'}
- dependencies:
- esutils: 2.0.3
- dev: true
- /dotenv@16.4.5:
+ dom-serializer@2.0.0:
+ resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
+
+ domelementtype@2.3.0:
+ resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+
+ domhandler@5.0.3:
+ resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
+ engines: {node: '>= 4'}
+
+ domutils@3.1.0:
+ resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==}
+
+ dotenv@16.4.5:
resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
engines: {node: '>=12'}
- dev: false
- /emoji-regex@8.0.0:
+ emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
- dev: false
- /es-define-property@1.0.0:
+ entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+
+ es-define-property@1.0.0:
resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
engines: {node: '>= 0.4'}
- dependencies:
- get-intrinsic: 1.2.4
- dev: false
- /es-errors@1.3.0:
+ es-errors@1.3.0:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
- dev: false
- /escape-string-regexp@4.0.0:
+ escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
- dev: true
- /eslint-config-prettier@9.1.0(eslint@8.57.0):
+ eslint-config-prettier@9.1.0:
resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
- dependencies:
- eslint: 8.57.0
- dev: true
- /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5):
+ eslint-plugin-prettier@5.1.3:
resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
@@ -995,216 +626,98 @@ packages:
optional: true
eslint-config-prettier:
optional: true
- dependencies:
- eslint: 8.57.0
- eslint-config-prettier: 9.1.0(eslint@8.57.0)
- prettier: 3.2.5
- prettier-linter-helpers: 1.0.0
- synckit: 0.8.8
- dev: true
- /eslint-scope@5.1.1:
+ eslint-scope@5.1.1:
resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
engines: {node: '>=8.0.0'}
- dependencies:
- esrecurse: 4.3.0
- estraverse: 4.3.0
- dev: true
- /eslint-scope@7.2.2:
+ eslint-scope@7.2.2:
resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dependencies:
- esrecurse: 4.3.0
- estraverse: 5.3.0
- dev: true
- /eslint-visitor-keys@3.4.3:
+ eslint-visitor-keys@3.4.3:
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dev: true
- /eslint@8.57.0:
+ eslint@8.57.0:
resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
- dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
- '@eslint-community/regexpp': 4.10.0
- '@eslint/eslintrc': 2.1.4
- '@eslint/js': 8.57.0
- '@humanwhocodes/config-array': 0.11.14
- '@humanwhocodes/module-importer': 1.0.1
- '@nodelib/fs.walk': 1.2.8
- '@ungap/structured-clone': 1.2.0
- ajv: 6.12.6
- chalk: 4.1.2
- cross-spawn: 7.0.3
- debug: 4.3.4
- doctrine: 3.0.0
- escape-string-regexp: 4.0.0
- eslint-scope: 7.2.2
- eslint-visitor-keys: 3.4.3
- espree: 9.6.1
- esquery: 1.5.0
- esutils: 2.0.3
- fast-deep-equal: 3.1.3
- file-entry-cache: 6.0.1
- find-up: 5.0.0
- glob-parent: 6.0.2
- globals: 13.24.0
- graphemer: 1.4.0
- ignore: 5.3.1
- imurmurhash: 0.1.4
- is-glob: 4.0.3
- is-path-inside: 3.0.3
- js-yaml: 4.1.0
- json-stable-stringify-without-jsonify: 1.0.1
- levn: 0.4.1
- lodash.merge: 4.6.2
- minimatch: 3.1.2
- natural-compare: 1.4.0
- optionator: 0.9.4
- strip-ansi: 6.0.1
- text-table: 0.2.0
- transitivePeerDependencies:
- - supports-color
- dev: true
- /espree@9.6.1:
+ espree@9.6.1:
resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dependencies:
- acorn: 8.11.3
- acorn-jsx: 5.3.2(acorn@8.11.3)
- eslint-visitor-keys: 3.4.3
- dev: true
- /esquery@1.5.0:
+ esquery@1.5.0:
resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
engines: {node: '>=0.10'}
- dependencies:
- estraverse: 5.3.0
- dev: true
- /esrecurse@4.3.0:
+ esrecurse@4.3.0:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
engines: {node: '>=4.0'}
- dependencies:
- estraverse: 5.3.0
- dev: true
- /estraverse@4.3.0:
+ estraverse@4.3.0:
resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
engines: {node: '>=4.0'}
- dev: true
- /estraverse@5.3.0:
+ estraverse@5.3.0:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
engines: {node: '>=4.0'}
- dev: true
- /esutils@2.0.3:
+ esutils@2.0.3:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
- dev: true
-
- /execa@5.1.1:
- resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
- engines: {node: '>=10'}
- dependencies:
- cross-spawn: 7.0.3
- get-stream: 6.0.1
- human-signals: 2.1.0
- is-stream: 2.0.1
- merge-stream: 2.0.0
- npm-run-path: 4.0.1
- onetime: 5.1.2
- signal-exit: 3.0.7
- strip-final-newline: 2.0.0
- dev: false
- /fast-deep-equal@3.1.3:
+ fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
- /fast-diff@1.3.0:
+ fast-diff@1.3.0:
resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
- dev: true
- /fast-glob@3.3.2:
+ fast-glob@3.3.2:
resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
engines: {node: '>=8.6.0'}
- dependencies:
- '@nodelib/fs.stat': 2.0.5
- '@nodelib/fs.walk': 1.2.8
- glob-parent: 5.1.2
- merge2: 1.4.1
- micromatch: 4.0.7
- dev: true
- /fast-json-stable-stringify@2.1.0:
+ fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
- dev: true
- /fast-levenshtein@2.0.6:
+ fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
- dev: true
- /fast-safe-stringify@2.1.1:
+ fast-safe-stringify@2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
- dev: false
- /fastq@1.17.1:
+ fastq@1.17.1:
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
- dependencies:
- reusify: 1.0.4
- dev: true
- /file-entry-cache@6.0.1:
+ fetch-blob@3.2.0:
+ resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
+ engines: {node: ^12.20 || >= 14.13}
+
+ file-entry-cache@6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
- dependencies:
- flat-cache: 3.2.0
- dev: true
- /file-type@18.7.0:
+ file-type@18.7.0:
resolution: {integrity: sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw==}
engines: {node: '>=14.16'}
- dependencies:
- readable-web-to-node-stream: 3.0.2
- strtok3: 7.0.0
- token-types: 5.0.1
- dev: false
- /fill-range@7.1.1:
+ fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
- dependencies:
- to-regex-range: 5.0.1
- dev: true
- /find-up@5.0.0:
+ find-up@5.0.0:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
- dependencies:
- locate-path: 6.0.0
- path-exists: 4.0.0
- dev: true
- /flat-cache@3.2.0:
+ flat-cache@3.2.0:
resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
engines: {node: ^10.12.0 || >=12.0.0}
- dependencies:
- flatted: 3.3.1
- keyv: 4.5.4
- rimraf: 3.0.2
- dev: true
- /flatted@3.3.1:
+ flatted@3.3.1:
resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
- dev: true
- /follow-redirects@1.15.6:
+ follow-redirects@1.15.6:
resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
engines: {node: '>=4.0'}
peerDependencies:
@@ -1212,462 +725,276 @@ packages:
peerDependenciesMeta:
debug:
optional: true
- dev: false
- /form-data@3.0.1:
+ form-data@3.0.1:
resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==}
engines: {node: '>= 6'}
- dependencies:
- asynckit: 0.4.0
- combined-stream: 1.0.8
- mime-types: 2.1.35
- dev: false
- /form-data@4.0.0:
+ form-data@4.0.0:
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
engines: {node: '>= 6'}
- dependencies:
- asynckit: 0.4.0
- combined-stream: 1.0.8
- mime-types: 2.1.35
- dev: false
- /formidable@1.2.6:
+ formdata-polyfill@4.0.10:
+ resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
+ engines: {node: '>=12.20.0'}
+
+ formidable@1.2.6:
resolution: {integrity: sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==}
deprecated: 'Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau'
- dev: false
- /fs-minipass@2.1.0:
+ fs-minipass@2.1.0:
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
engines: {node: '>= 8'}
- dependencies:
- minipass: 3.3.6
- dev: false
- /fs.realpath@1.0.0:
+ fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
- /function-bind@1.1.2:
+ function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
- dev: false
- /gauge@3.0.2:
+ gauge@3.0.2:
resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
engines: {node: '>=10'}
deprecated: This package is no longer supported.
- dependencies:
- aproba: 2.0.0
- color-support: 1.1.3
- console-control-strings: 1.1.0
- has-unicode: 2.0.1
- object-assign: 4.1.1
- signal-exit: 3.0.7
- string-width: 4.2.3
- strip-ansi: 6.0.1
- wide-align: 1.1.5
- dev: false
- /get-intrinsic@1.2.4:
+ get-intrinsic@1.2.4:
resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
engines: {node: '>= 0.4'}
- dependencies:
- es-errors: 1.3.0
- function-bind: 1.1.2
- has-proto: 1.0.3
- has-symbols: 1.0.3
- hasown: 2.0.2
- dev: false
- /get-stream@6.0.1:
- resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
- engines: {node: '>=10'}
- dev: false
-
- /glob-parent@5.1.2:
+ glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
- dependencies:
- is-glob: 4.0.3
- dev: true
- /glob-parent@6.0.2:
+ glob-parent@6.0.2:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
- dependencies:
- is-glob: 4.0.3
- dev: true
- /glob@7.2.3:
+ glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
deprecated: Glob versions prior to v9 are no longer supported
- dependencies:
- fs.realpath: 1.0.0
- inflight: 1.0.6
- inherits: 2.0.4
- minimatch: 3.1.2
- once: 1.4.0
- path-is-absolute: 1.0.1
- /globals@13.24.0:
+ globals@13.24.0:
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
engines: {node: '>=8'}
- dependencies:
- type-fest: 0.20.2
- dev: true
- /globby@11.1.0:
+ globby@11.1.0:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
- dependencies:
- array-union: 2.1.0
- dir-glob: 3.0.1
- fast-glob: 3.3.2
- ignore: 5.3.1
- merge2: 1.4.1
- slash: 3.0.0
- dev: true
- /gopd@1.0.1:
+ gopd@1.0.1:
resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
- dependencies:
- get-intrinsic: 1.2.4
- dev: false
- /graphemer@1.4.0:
+ graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
- dev: true
- /has-flag@4.0.0:
+ has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
- dev: true
- /has-property-descriptors@1.0.2:
+ has-property-descriptors@1.0.2:
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
- dependencies:
- es-define-property: 1.0.0
- dev: false
- /has-proto@1.0.3:
+ has-proto@1.0.3:
resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
engines: {node: '>= 0.4'}
- dev: false
- /has-symbols@1.0.3:
+ has-symbols@1.0.3:
resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
engines: {node: '>= 0.4'}
- dev: false
- /has-unicode@2.0.1:
+ has-unicode@2.0.1:
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
- dev: false
- /hasown@2.0.2:
+ hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
- dependencies:
- function-bind: 1.1.2
- dev: false
- /himalaya@1.1.0:
+ he@1.2.0:
+ resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
+ hasBin: true
+
+ himalaya@1.1.0:
resolution: {integrity: sha512-LLase1dHCRMel68/HZTFft0N0wti0epHr3nNY7ynpLbyZpmrKMQ8YIpiOV77TM97cNpC8Wb2n6f66IRggwdWPw==}
- dev: false
- /http-cookie-agent@5.0.4(tough-cookie@4.1.4)(undici@5.28.4):
- resolution: {integrity: sha512-OtvikW69RvfyP6Lsequ0fN5R49S+8QcS9zwd58k6VSr6r57T8G29BkPdyrBcSwLq6ExLs9V+rBlfxu7gDstJag==}
- engines: {node: '>=14.18.0 <15.0.0 || >=16.0.0'}
+ http-cookie-agent@6.0.5:
+ resolution: {integrity: sha512-sfZ8fDgDP3B1YB+teqSnAK1aPgBu8reUUGxSsndP2XnYN6cM29EURXWXZqQQiaRdor3B4QjpkUNfv21syaO4DA==}
+ engines: {node: '>=18.0.0'}
peerDependencies:
- deasync: ^0.1.26
tough-cookie: ^4.0.0
- undici: ^5.11.0
+ undici: ^5.11.0 || ^6.0.0
peerDependenciesMeta:
- deasync:
- optional: true
undici:
optional: true
- dependencies:
- agent-base: 7.1.1
- tough-cookie: 4.1.4
- undici: 5.28.4
- transitivePeerDependencies:
- - supports-color
- dev: false
- /https-proxy-agent@5.0.1:
+ https-proxy-agent@5.0.1:
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
engines: {node: '>= 6'}
- dependencies:
- agent-base: 6.0.2
- debug: 4.3.4
- transitivePeerDependencies:
- - supports-color
- dev: false
-
- /human-signals@2.1.0:
- resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
- engines: {node: '>=10.17.0'}
- dev: false
- /i18next-fs-backend@2.3.1:
+ i18next-fs-backend@2.3.1:
resolution: {integrity: sha512-tvfXskmG/9o+TJ5Fxu54sSO5OkY6d+uMn+K6JiUGLJrwxAVfer+8V3nU8jq3ts9Pe5lXJv4b1N7foIjJ8Iy2Gg==}
- dev: false
- /i18next@22.5.1:
+ i18next@22.5.1:
resolution: {integrity: sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==}
- dependencies:
- '@babel/runtime': 7.24.6
- dev: false
- /ieee754@1.2.1:
+ ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
- dev: false
- /ignore@5.3.1:
+ ignore@5.3.1:
resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
engines: {node: '>= 4'}
- dev: true
- /import-fresh@3.3.0:
+ import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'}
- dependencies:
- parent-module: 1.0.1
- resolve-from: 4.0.0
- dev: true
- /imurmurhash@0.1.4:
+ imurmurhash@0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
- dev: true
- /inflight@1.0.6:
+ inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
- dependencies:
- once: 1.4.0
- wrappy: 1.0.2
- /inherits@2.0.4:
+ inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
- /ip-address@9.0.5:
+ ip-address@9.0.5:
resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==}
engines: {node: '>= 12'}
- dependencies:
- jsbn: 1.1.0
- sprintf-js: 1.1.3
- dev: false
- /is-extglob@2.1.1:
+ is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
- dev: true
- /is-fullwidth-code-point@3.0.0:
+ is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
- dev: false
- /is-glob@4.0.3:
+ is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
- dependencies:
- is-extglob: 2.1.1
- dev: true
- /is-number@7.0.0:
+ is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
- dev: true
- /is-path-inside@3.0.3:
+ is-path-inside@3.0.3:
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
engines: {node: '>=8'}
- dev: true
-
- /is-stream@2.0.1:
- resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
- engines: {node: '>=8'}
- dev: false
- /isexe@2.0.0:
+ isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
- /js-yaml@4.1.0:
+ isomorphic-unfetch@4.0.2:
+ resolution: {integrity: sha512-1Yd+CF/7al18/N2BDbsLBcp6RO3tucSW+jcLq24dqdX5MNbCNTw1z4BsGsp4zNmjr/Izm2cs/cEqZPp4kvWSCA==}
+
+ js-yaml@4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
- dependencies:
- argparse: 2.0.1
- dev: true
- /jsbn@1.1.0:
+ jsbn@1.1.0:
resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==}
- dev: false
- /json-buffer@3.0.1:
+ json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
- dev: true
- /json-schema-traverse@0.4.1:
+ json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
- dev: true
- /json-stable-stringify-without-jsonify@1.0.1:
+ json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
- dev: true
- /kareem@2.5.1:
+ kareem@2.5.1:
resolution: {integrity: sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==}
engines: {node: '>=12.0.0'}
- dev: false
- /keyv@4.5.4:
+ keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
- dependencies:
- json-buffer: 3.0.1
- dev: true
- /levn@0.4.1:
+ levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
- dependencies:
- prelude-ls: 1.2.1
- type-check: 0.4.0
- dev: true
- /locate-path@6.0.0:
+ locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
- dependencies:
- p-locate: 5.0.0
- dev: true
- /lodash.merge@4.6.2:
+ lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
- dev: true
- /lodash.snakecase@4.1.1:
+ lodash.snakecase@4.1.1:
resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==}
- dev: false
- /lodash@4.17.21:
+ lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
- dev: false
- /m3u8stream@0.8.6:
+ m3u8stream@0.8.6:
resolution: {integrity: sha512-LZj8kIVf9KCphiHmH7sbFQTVe4tOemb202fWwvJwR9W5ENW/1hxJN6ksAWGhQgSBSa3jyWhnjKU1Fw1GaOdbyA==}
engines: {node: '>=12'}
- dependencies:
- miniget: 4.2.3
- sax: 1.3.0
- dev: false
- /magic-bytes.js@1.10.0:
+ magic-bytes.js@1.10.0:
resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==}
- dev: false
- /make-dir@3.1.0:
+ make-dir@3.1.0:
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
engines: {node: '>=8'}
- dependencies:
- semver: 6.3.1
- dev: false
- /memory-pager@1.5.0:
+ memory-pager@1.5.0:
resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==}
- requiresBuild: true
- dev: false
- optional: true
-
- /merge-stream@2.0.0:
- resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
- dev: false
- /merge2@1.4.1:
+ merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
- dev: true
- /methods@1.1.2:
+ methods@1.1.2:
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
engines: {node: '>= 0.6'}
- dev: false
- /micromatch@4.0.7:
+ micromatch@4.0.7:
resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==}
engines: {node: '>=8.6'}
- dependencies:
- braces: 3.0.3
- picomatch: 2.3.1
- dev: true
- /mime-db@1.52.0:
+ mime-db@1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
- dev: false
- /mime-types@2.1.35:
+ mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
- dependencies:
- mime-db: 1.52.0
- dev: false
- /mime@2.6.0:
+ mime@2.6.0:
resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
engines: {node: '>=4.0.0'}
hasBin: true
- dev: false
-
- /mimic-fn@2.1.0:
- resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
- engines: {node: '>=6'}
- dev: false
- /miniget@4.2.3:
+ miniget@4.2.3:
resolution: {integrity: sha512-SjbDPDICJ1zT+ZvQwK0hUcRY4wxlhhNpHL9nJOB2MEAXRGagTljsO8MEDzQMTFf0Q8g4QNi8P9lEm/g7e+qgzA==}
engines: {node: '>=12'}
- dev: false
- /minimatch@3.1.2:
+ minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
- dependencies:
- brace-expansion: 1.1.11
- /minipass@3.3.6:
+ minipass@3.3.6:
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
engines: {node: '>=8'}
- dependencies:
- yallist: 4.0.0
- dev: false
- /minipass@5.0.0:
+ minipass@5.0.0:
resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
engines: {node: '>=8'}
- dev: false
- /minizlib@2.1.2:
+ minizlib@2.1.2:
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
engines: {node: '>= 8'}
- dependencies:
- minipass: 3.3.6
- yallist: 4.0.0
- dev: false
- /mkdirp@1.0.4:
+ mkdirp@1.0.4:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
engines: {node: '>=10'}
hasBin: true
- dev: false
- /mongodb-connection-string-url@2.6.0:
+ mongodb-connection-string-url@2.6.0:
resolution: {integrity: sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==}
- dependencies:
- '@types/whatwg-url': 8.2.2
- whatwg-url: 11.0.0
- dev: false
- /mongodb@5.9.2:
+ mongodb@5.9.2:
resolution: {integrity: sha512-H60HecKO4Bc+7dhOv4sJlgvenK4fQNqqUIlXxZYQNbfEWSALGAwGoyJd/0Qwk4TttFXUOHJ2ZJQe/52ScaUwtQ==}
engines: {node: '>=14.20.1'}
peerDependencies:
@@ -1687,68 +1014,39 @@ packages:
optional: true
snappy:
optional: true
- dependencies:
- bson: 5.5.1
- mongodb-connection-string-url: 2.6.0
- socks: 2.8.3
- optionalDependencies:
- '@mongodb-js/saslprep': 1.1.7
- dev: false
- /mongoose@7.6.12:
- resolution: {integrity: sha512-bjnOELGT2wWV3qjPZC4hol+O/QP4i7LrWenrtaN76A0X69T+Y19lmAhp74kLTNY13Djp1Agz1hoOq3bthmGLTg==}
+ mongoose@7.7.0:
+ resolution: {integrity: sha512-+HcoN/hmkB5IjAqWYA2ZAQeExGD8FNMe6L/eTYB04gqp9S2ZEngVivGkdtGrA4BYRf0suH+3rMNFW2JPOqC4Mg==}
engines: {node: '>=14.20.1'}
- dependencies:
- bson: 5.5.1
- kareem: 2.5.1
- mongodb: 5.9.2
- mpath: 0.9.0
- mquery: 5.0.0
- ms: 2.1.3
- sift: 16.0.1
- transitivePeerDependencies:
- - '@aws-sdk/credential-providers'
- - '@mongodb-js/zstd'
- - kerberos
- - mongodb-client-encryption
- - snappy
- - supports-color
- dev: false
- /mpath@0.9.0:
+ mpath@0.9.0:
resolution: {integrity: sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==}
engines: {node: '>=4.0.0'}
- dev: false
- /mquery@5.0.0:
+ mquery@5.0.0:
resolution: {integrity: sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==}
engines: {node: '>=14.0.0'}
- dependencies:
- debug: 4.3.4
- transitivePeerDependencies:
- - supports-color
- dev: false
- /ms@2.1.2:
+ ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
- /ms@2.1.3:
+ ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
- dev: false
- /natural-compare-lite@1.4.0:
+ natural-compare-lite@1.4.0:
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
- dev: true
- /natural-compare@1.4.0:
+ natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
- dev: true
- /node-addon-api@5.1.0:
+ node-addon-api@5.1.0:
resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==}
- dev: false
- /node-fetch@2.7.0:
+ node-domexception@1.0.0:
+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+ engines: {node: '>=10.5.0'}
+
+ node-fetch@2.7.0:
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
engines: {node: 4.x || >=6.0.0}
peerDependencies:
@@ -1756,145 +1054,101 @@ packages:
peerDependenciesMeta:
encoding:
optional: true
- dependencies:
- whatwg-url: 5.0.0
- dev: false
- /node-gyp-build@4.8.1:
+ node-fetch@3.3.2:
+ resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ node-gyp-build@4.8.1:
resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==}
hasBin: true
- dev: false
- /node-os-utils@1.3.7:
+ node-html-parser@6.1.13:
+ resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==}
+
+ node-os-utils@1.3.7:
resolution: {integrity: sha512-fvnX9tZbR7WfCG5BAy3yO/nCLyjVWD6MghEq0z5FDfN+ZXpLWNITBdbifxQkQ25ebr16G0N7eRWJisOcMEHG3Q==}
- dev: false
- /nopt@5.0.0:
+ nopt@5.0.0:
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
engines: {node: '>=6'}
hasBin: true
- dependencies:
- abbrev: 1.1.1
- dev: false
- /npm-run-path@4.0.1:
- resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
- engines: {node: '>=8'}
- dependencies:
- path-key: 3.1.1
- dev: false
-
- /npmlog@5.0.1:
+ npmlog@5.0.1:
resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
deprecated: This package is no longer supported.
- dependencies:
- are-we-there-yet: 2.0.0
- console-control-strings: 1.1.0
- gauge: 3.0.2
- set-blocking: 2.0.0
- dev: false
- /object-assign@4.1.1:
+ nth-check@2.1.1:
+ resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
+
+ object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
- dev: false
- /object-inspect@1.13.1:
- resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
- dev: false
+ object-inspect@1.13.2:
+ resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==}
+ engines: {node: '>= 0.4'}
- /once@1.4.0:
+ once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
- dependencies:
- wrappy: 1.0.2
-
- /onetime@5.1.2:
- resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
- engines: {node: '>=6'}
- dependencies:
- mimic-fn: 2.1.0
- dev: false
- /optionator@0.9.4:
+ optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
- dependencies:
- deep-is: 0.1.4
- fast-levenshtein: 2.0.6
- levn: 0.4.1
- prelude-ls: 1.2.1
- type-check: 0.4.0
- word-wrap: 1.2.5
- dev: true
- /p-limit@3.1.0:
+ opusscript@0.1.1:
+ resolution: {integrity: sha512-mL0fZZOUnXdZ78woRXp18lApwpp0lF5tozJOD1Wut0dgrA9WuQTgSels/CSmFleaAZrJi/nci5KOVtbuxeWoQA==}
+
+ p-limit@3.1.0:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
- dependencies:
- yocto-queue: 0.1.0
- dev: true
- /p-locate@5.0.0:
+ p-locate@5.0.0:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
- dependencies:
- p-limit: 3.1.0
- dev: true
- /parent-module@1.0.1:
+ parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
- dependencies:
- callsites: 3.1.0
- dev: true
- /path-exists@4.0.0:
+ path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
- dev: true
- /path-is-absolute@1.0.1:
+ path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
- /path-key@3.1.1:
+ path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
- /path-type@4.0.0:
+ path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
- dev: true
- /peek-readable@5.0.0:
- resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==}
+ peek-readable@5.1.1:
+ resolution: {integrity: sha512-4hEOSH7KeEaZpMDF/xfm1W9fS5rT7Ett3BkXWHqAEzRLLwLaHkwOL+GvvpIEh9UrvX9BDhzfkvteslgraoH69w==}
engines: {node: '>=14.16'}
- dev: false
- /picomatch@2.3.1:
+ picomatch@2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
- dev: true
- /prelude-ls@1.2.1:
+ prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
- dev: true
- /prettier-linter-helpers@1.0.0:
+ prettier-linter-helpers@1.0.0:
resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
engines: {node: '>=6.0.0'}
- dependencies:
- fast-diff: 1.3.0
- dev: true
- /prettier@3.2.5:
- resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==}
+ prettier@3.3.2:
+ resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==}
engines: {node: '>=14'}
hasBin: true
- dev: true
- /prism-media@1.3.5(@discordjs/opus@0.9.0):
+ prism-media@1.3.5:
resolution: {integrity: sha512-IQdl0Q01m4LrkN1EGIE9lphov5Hy7WWlH6ulf5QdGePLlPas9p2mhgddTEHrlaXYjjFToM1/rWuwF37VF4taaA==}
peerDependencies:
'@discordjs/opus': '>=0.8.0 <1.0.0'
@@ -1910,487 +1164,294 @@ packages:
optional: true
opusscript:
optional: true
- dependencies:
- '@discordjs/opus': 0.9.0
- dev: false
- /proxy-from-env@1.1.0:
+ proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
- dev: false
- /psl@1.9.0:
+ psl@1.9.0:
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
- dev: false
- /punycode@2.3.1:
+ punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
- /qs@6.12.1:
- resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==}
+ qs@6.12.2:
+ resolution: {integrity: sha512-x+NLUpx9SYrcwXtX7ob1gnkSems4i/mGZX5SlYxwIau6RrUSODO89TR/XDGGpn5RPWSYIB+aSfuSlV5+CmbTBg==}
engines: {node: '>=0.6'}
- dependencies:
- side-channel: 1.0.6
- dev: false
- /querystringify@2.2.0:
+ querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
- dev: false
- /queue-microtask@1.2.3:
+ queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
- dev: true
- /readable-stream@3.6.2:
+ readable-stream@3.6.2:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
- dependencies:
- inherits: 2.0.4
- string_decoder: 1.3.0
- util-deprecate: 1.0.2
- dev: false
- /readable-web-to-node-stream@3.0.2:
+ readable-web-to-node-stream@3.0.2:
resolution: {integrity: sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==}
engines: {node: '>=8'}
- dependencies:
- readable-stream: 3.6.2
- dev: false
- /regenerator-runtime@0.14.1:
+ regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
- dev: false
- /requires-port@1.0.0:
+ requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
- dev: false
- /resolve-from@4.0.0:
+ resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
- dev: true
- /reusify@1.0.4:
+ reusify@1.0.4:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
- dev: true
- /rimraf@3.0.2:
+ rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
- dependencies:
- glob: 7.2.3
- /run-parallel@1.2.0:
+ run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
- dependencies:
- queue-microtask: 1.2.3
- dev: true
- /safe-buffer@5.2.1:
+ safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
- dev: false
- /sax@1.3.0:
- resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==}
- dev: false
+ sax@1.4.1:
+ resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
- /semver@6.3.1:
+ semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
- dev: false
- /semver@7.6.2:
+ semver@7.6.2:
resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==}
engines: {node: '>=10'}
hasBin: true
- /set-blocking@2.0.0:
+ set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
- dev: false
- /set-function-length@1.2.2:
+ set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
- dependencies:
- define-data-property: 1.1.4
- es-errors: 1.3.0
- function-bind: 1.1.2
- get-intrinsic: 1.2.4
- gopd: 1.0.1
- has-property-descriptors: 1.0.2
- dev: false
- /shebang-command@2.0.0:
+ shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'}
- dependencies:
- shebang-regex: 3.0.0
- /shebang-regex@3.0.0:
+ shebang-regex@3.0.0:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
- /side-channel@1.0.6:
+ side-channel@1.0.6:
resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
engines: {node: '>= 0.4'}
- dependencies:
- call-bind: 1.0.7
- es-errors: 1.3.0
- get-intrinsic: 1.2.4
- object-inspect: 1.13.1
- dev: false
- /sift@16.0.1:
+ sift@16.0.1:
resolution: {integrity: sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==}
- dev: false
- /signal-exit@3.0.7:
+ signal-exit@3.0.7:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
- dev: false
- /slash@3.0.0:
+ slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
- dev: true
- /smart-buffer@4.2.0:
+ smart-buffer@4.2.0:
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
- dev: false
- /socks@2.8.3:
+ socks@2.8.3:
resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==}
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
- dependencies:
- ip-address: 9.0.5
- smart-buffer: 4.2.0
- dev: false
- /sodium-native@4.1.1:
+ sodium-native@4.1.1:
resolution: {integrity: sha512-LXkAfRd4FHtkQS4X6g+nRcVaN7mWVNepV06phIsC6+IZFvGh1voW5TNQiQp2twVaMf05gZqQjuS+uWLM6gHhNQ==}
- requiresBuild: true
- dependencies:
- node-gyp-build: 4.8.1
- dev: false
- /soundcloud.ts@0.5.3:
+ soundcloud.ts@0.5.3:
resolution: {integrity: sha512-ZMH6gG5e7WqJrIYXTv14MNArPhx3WzfrL1Ij/2qBDW8mVbNJc8lxOQOc4kLvrfvDl5TkCdZa7zXOiwD6ESXq+g==}
- dependencies:
- undici: 6.18.1
- dev: false
- /sparse-bitfield@3.0.3:
+ sparse-bitfield@3.0.3:
resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==}
- requiresBuild: true
- dependencies:
- memory-pager: 1.5.0
- dev: false
- optional: true
- /spotify-uri@4.1.0:
+ spotify-uri@4.1.0:
resolution: {integrity: sha512-SFpBt8pQqO7DOFBsdUjv3GxGZAKYP7UqcTflfE7h3YL1lynl/6Motq7NERoJJR8eF9kXQRSpcdMmV5ou84rbng==}
engines: {node: '>= 16'}
- dev: false
- /spotify-url-info@3.2.15:
- resolution: {integrity: sha512-NlolD2mqZjvt91hq0XVy3db55FCL2li1XBivkf/i+zUW1K9RP9nIOK5Bpg82DmBf96sjl4TYRI3zPOS94LPulQ==}
+ spotify-url-info@3.2.16:
+ resolution: {integrity: sha512-szXt1PLt8lqhaXsTNYH7zPd+EBj6Ha0xtqitqicCijGX6x/jYvn6wgGaK2F1OQfJzx8lxDNfZbtarn4DxzaZ2Q==}
engines: {node: '>= 12'}
- dependencies:
- himalaya: 1.1.0
- spotify-uri: 4.1.0
- dev: false
- /spotify-web-api-node@5.0.2:
+ spotify-web-api-node@5.0.2:
resolution: {integrity: sha512-r82dRWU9PMimHvHEzL0DwEJrzFk+SMCVfq249SLt3I7EFez7R+jeoKQd+M1//QcnjqlXPs2am4DFsGk8/GCsrA==}
- dependencies:
- superagent: 6.1.0
- transitivePeerDependencies:
- - supports-color
- dev: false
- /sprintf-js@1.1.3:
+ sprintf-js@1.1.3:
resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
- dev: false
- /string-width@4.2.3:
+ string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
- dependencies:
- emoji-regex: 8.0.0
- is-fullwidth-code-point: 3.0.0
- strip-ansi: 6.0.1
- dev: false
- /string_decoder@1.3.0:
+ string_decoder@1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
- dependencies:
- safe-buffer: 5.2.1
- dev: false
- /strip-ansi@6.0.1:
+ strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
- dependencies:
- ansi-regex: 5.0.1
-
- /strip-final-newline@2.0.0:
- resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
- engines: {node: '>=6'}
- dev: false
- /strip-json-comments@3.1.1:
+ strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
- dev: true
- /strtok3@7.0.0:
- resolution: {integrity: sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==}
+ strtok3@7.1.0:
+ resolution: {integrity: sha512-19dQEwG6Jd+VabjPRyBhymIF069vZiqWSZa2jJBoKJTsqGKnTxowGoQaLnz+yLARfDI041IUQekyPUMWElOgsQ==}
engines: {node: '>=14.16'}
- dependencies:
- '@tokenizer/token': 0.3.0
- peek-readable: 5.0.0
- dev: false
- /superagent@6.1.0:
+ superagent@6.1.0:
resolution: {integrity: sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==}
engines: {node: '>= 7.0.0'}
deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net
- dependencies:
- component-emitter: 1.3.1
- cookiejar: 2.1.4
- debug: 4.3.4
- fast-safe-stringify: 2.1.1
- form-data: 3.0.1
- formidable: 1.2.6
- methods: 1.1.2
- mime: 2.6.0
- qs: 6.12.1
- readable-stream: 3.6.2
- semver: 7.6.2
- transitivePeerDependencies:
- - supports-color
- dev: false
- /supports-color@7.2.0:
+ supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
- dependencies:
- has-flag: 4.0.0
- dev: true
- /synckit@0.8.8:
+ synckit@0.8.8:
resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==}
engines: {node: ^14.18.0 || >=16.0.0}
- dependencies:
- '@pkgr/core': 0.1.1
- tslib: 2.6.2
- dev: true
- /tar@6.2.1:
+ tar@6.2.1:
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'}
- dependencies:
- chownr: 2.0.0
- fs-minipass: 2.1.0
- minipass: 5.0.0
- minizlib: 2.1.2
- mkdirp: 1.0.4
- yallist: 4.0.0
- dev: false
- /text-table@0.2.0:
+ text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
- dev: true
- /tiny-typed-emitter@2.1.0:
+ tiny-typed-emitter@2.1.0:
resolution: {integrity: sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==}
- dev: false
- /to-regex-range@5.0.1:
+ to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
- dependencies:
- is-number: 7.0.0
- dev: true
- /token-types@5.0.1:
+ token-types@5.0.1:
resolution: {integrity: sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==}
engines: {node: '>=14.16'}
- dependencies:
- '@tokenizer/token': 0.3.0
- ieee754: 1.2.1
- dev: false
- /tough-cookie@4.1.4:
+ tough-cookie@4.1.4:
resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==}
engines: {node: '>=6'}
- dependencies:
- psl: 1.9.0
- punycode: 2.3.1
- universalify: 0.2.0
- url-parse: 1.5.10
- dev: false
- /tr46@0.0.3:
+ tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
- dev: false
- /tr46@3.0.0:
+ tr46@3.0.0:
resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==}
engines: {node: '>=12'}
- dependencies:
- punycode: 2.3.1
- dev: false
- /ts-mixer@6.0.4:
+ ts-mixer@6.0.4:
resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==}
- dev: false
- /tslib@1.14.1:
+ tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
- dev: true
- /tslib@2.6.2:
+ tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
- /tsutils@3.21.0(typescript@5.4.5):
+ tslib@2.6.3:
+ resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
+
+ tsutils@3.21.0:
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
engines: {node: '>= 6'}
peerDependencies:
typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
- dependencies:
- tslib: 1.14.1
- typescript: 5.4.5
- dev: true
- /type-check@0.4.0:
+ type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
- dependencies:
- prelude-ls: 1.2.1
- dev: true
- /type-fest@0.20.2:
+ type-fest@0.20.2:
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
engines: {node: '>=10'}
- dev: true
- /typescript@5.4.5:
- resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
+ typescript@5.5.3:
+ resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==}
engines: {node: '>=14.17'}
hasBin: true
- dev: true
- /undici-types@5.26.5:
+ undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
- /undici@5.27.2:
- resolution: {integrity: sha512-iS857PdOEy/y3wlM3yRp+6SNQQ6xU0mmZcwRSriqk+et/cwWAtwmIGf6WkoDN2EK/AMdCO/dfXzIwi+rFMrjjQ==}
- engines: {node: '>=14.0'}
- dependencies:
- '@fastify/busboy': 2.1.1
- dev: false
-
- /undici@5.28.4:
+ undici@5.28.4:
resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
engines: {node: '>=14.0'}
- dependencies:
- '@fastify/busboy': 2.1.1
- dev: false
-
- /undici@6.0.1:
- resolution: {integrity: sha512-eZFYQLeS9BiXpsU0cuFhCwfeda2MnC48EVmmOz/eCjsTgmyTdaHdVsPSC/kwC2GtW2e0uH0HIPbadf3/bRWSxw==}
- engines: {node: '>=18.0'}
- dependencies:
- '@fastify/busboy': 2.1.1
- dev: false
- /undici@6.13.0:
+ undici@6.13.0:
resolution: {integrity: sha512-Q2rtqmZWrbP8nePMq7mOJIN98M0fYvSgV89vwl/BQRT4mDOeY2GXZngfGpcBBhtky3woM7G24wZV3Q304Bv6cw==}
engines: {node: '>=18.0'}
- dev: false
- /undici@6.18.1:
- resolution: {integrity: sha512-/0BWqR8rJNRysS5lqVmfc7eeOErcOP4tZpATVjJOojjHZ71gSYVAtFhEmadcIjwMIUehh5NFyKGsXCnXIajtbA==}
+ undici@6.19.2:
+ resolution: {integrity: sha512-JfjKqIauur3Q6biAtHJ564e3bWa8VvT+7cSiOJHFbX4Erv6CLGDpg8z+Fmg/1OI/47RA+GI2QZaF48SSaLvyBA==}
engines: {node: '>=18.17'}
- dev: false
- /universalify@0.2.0:
+ unfetch@5.0.0:
+ resolution: {integrity: sha512-3xM2c89siXg0nHvlmYsQ2zkLASvVMBisZm5lF3gFDqfF2xonNStDJyMpvaOBe0a1Edxmqrf2E0HBdmy9QyZaeg==}
+
+ universalify@0.2.0:
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
engines: {node: '>= 4.0.0'}
- dev: false
- /uri-js@4.4.1:
+ uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
- dependencies:
- punycode: 2.3.1
- dev: true
- /url-parse@1.5.10:
+ url-parse@1.5.10:
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
- dependencies:
- querystringify: 2.2.0
- requires-port: 1.0.0
- dev: false
- /util-deprecate@1.0.2:
+ util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
- dev: false
- /uuid@9.0.1:
+ uuid@9.0.1:
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
hasBin: true
- dev: false
- /webidl-conversions@3.0.1:
+ web-streams-polyfill@3.3.3:
+ resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
+ engines: {node: '>= 8'}
+
+ webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
- dev: false
- /webidl-conversions@7.0.0:
+ webidl-conversions@7.0.0:
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
engines: {node: '>=12'}
- dev: false
- /whatwg-url@11.0.0:
+ whatwg-url@11.0.0:
resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==}
engines: {node: '>=12'}
- dependencies:
- tr46: 3.0.0
- webidl-conversions: 7.0.0
- dev: false
- /whatwg-url@5.0.0:
+ whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
- dependencies:
- tr46: 0.0.3
- webidl-conversions: 3.0.1
- dev: false
- /which@2.0.2:
+ which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
hasBin: true
- dependencies:
- isexe: 2.0.0
- /wide-align@1.1.5:
+ wide-align@1.1.5:
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
- dependencies:
- string-width: 4.2.3
- dev: false
- /word-wrap@1.2.5:
+ word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
- dev: true
- /wrappy@1.0.2:
+ wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
- /ws@8.14.2:
- resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==}
+ ws@8.18.0:
+ resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
@@ -2400,37 +1461,1458 @@ packages:
optional: true
utf-8-validate:
optional: true
- dev: false
- /ws@8.17.0:
- resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==}
- engines: {node: '>=10.0.0'}
- peerDependencies:
- bufferutil: ^4.0.1
- utf-8-validate: '>=5.0.2'
- peerDependenciesMeta:
- bufferutil:
- optional: true
- utf-8-validate:
- optional: true
- dev: false
+ xml2js@0.6.2:
+ resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==}
+ engines: {node: '>=4.0.0'}
+
+ xmlbuilder@11.0.1:
+ resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==}
+ engines: {node: '>=4.0'}
- /yallist@4.0.0:
+ yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
- dev: false
- /yandex-music-client@0.4.3:
- resolution: {integrity: sha512-bsWMXxTozWEgtRtEja/qkeVPmF5rTU5HPsXgNrg9uoTOkjU6SfmoaaKL9kwBBtU/55wxnKvpHlKozPLsfGIMvQ==}
- dependencies:
- crypto: 1.0.1
- form-data: 4.0.0
- dev: false
+ ym-api-meowed@1.3.4:
+ resolution: {integrity: sha512-vHnfdGLgmOj8ST6fXmpKsK/YDO1JxdHJFcRuqrtEJeLFv727vtX2AVUjF46qNpjhVARD/GHqMDL3HE9ixjLdJg==}
- /yocto-queue@0.1.0:
+ yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
- dev: true
- /zod@3.23.8:
+ zod@3.23.8:
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
- dev: false
+
+snapshots:
+
+ '@babel/runtime@7.24.7':
+ dependencies:
+ regenerator-runtime: 0.14.1
+
+ '@discordjs/builders@1.8.2':
+ dependencies:
+ '@discordjs/formatters': 0.4.0
+ '@discordjs/util': 1.1.0
+ '@sapphire/shapeshift': 3.9.7
+ discord-api-types: 0.37.83
+ fast-deep-equal: 3.1.3
+ ts-mixer: 6.0.4
+ tslib: 2.6.2
+
+ '@discordjs/collection@1.5.3': {}
+
+ '@discordjs/collection@2.1.0': {}
+
+ '@discordjs/formatters@0.4.0':
+ dependencies:
+ discord-api-types: 0.37.83
+
+ '@discordjs/node-pre-gyp@0.4.5':
+ dependencies:
+ detect-libc: 2.0.3
+ https-proxy-agent: 5.0.1
+ make-dir: 3.1.0
+ node-fetch: 2.7.0
+ nopt: 5.0.0
+ npmlog: 5.0.1
+ rimraf: 3.0.2
+ semver: 7.6.2
+ tar: 6.2.1
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ '@discordjs/opus@0.9.0':
+ dependencies:
+ '@discordjs/node-pre-gyp': 0.4.5
+ node-addon-api: 5.1.0
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ '@discordjs/rest@1.7.1':
+ dependencies:
+ '@discordjs/collection': 1.5.3
+ '@discordjs/util': 0.3.1
+ '@sapphire/async-queue': 1.5.2
+ '@sapphire/snowflake': 3.5.3
+ discord-api-types: 0.37.92
+ file-type: 18.7.0
+ tslib: 2.6.3
+ undici: 5.28.4
+
+ '@discordjs/rest@2.3.0':
+ dependencies:
+ '@discordjs/collection': 2.1.0
+ '@discordjs/util': 1.1.0
+ '@sapphire/async-queue': 1.5.2
+ '@sapphire/snowflake': 3.5.3
+ '@vladfrangu/async_event_emitter': 2.4.1
+ discord-api-types: 0.37.83
+ magic-bytes.js: 1.10.0
+ tslib: 2.6.2
+ undici: 6.13.0
+
+ '@discordjs/util@0.3.1': {}
+
+ '@discordjs/util@1.1.0': {}
+
+ '@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1)':
+ dependencies:
+ '@types/ws': 8.5.10
+ discord-api-types: 0.37.61
+ prism-media: 1.3.5(@discordjs/opus@0.9.0)(opusscript@0.1.1)
+ tslib: 2.6.3
+ ws: 8.18.0
+ transitivePeerDependencies:
+ - '@discordjs/opus'
+ - bufferutil
+ - ffmpeg-static
+ - node-opus
+ - opusscript
+ - utf-8-validate
+
+ '@discordjs/ws@1.1.1':
+ dependencies:
+ '@discordjs/collection': 2.1.0
+ '@discordjs/rest': 2.3.0
+ '@discordjs/util': 1.1.0
+ '@sapphire/async-queue': 1.5.2
+ '@types/ws': 8.5.10
+ '@vladfrangu/async_event_emitter': 2.4.1
+ discord-api-types: 0.37.83
+ tslib: 2.6.2
+ ws: 8.18.0
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
+ '@distube/direct-link@1.0.1(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))':
+ dependencies:
+ distube: 5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)
+ undici: 6.19.2
+
+ '@distube/file@1.0.1(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))':
+ dependencies:
+ distube: 5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)
+
+ '@distube/soundcloud@2.0.2(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))':
+ dependencies:
+ distube: 5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)
+ soundcloud.ts: 0.5.3
+
+ '@distube/spotify@2.0.2(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))':
+ dependencies:
+ distube: 5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)
+ spotify-uri: 4.1.0
+ spotify-url-info: 3.2.16
+ spotify-web-api-node: 5.0.2
+ undici: 6.19.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@distube/youtube@1.0.2(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))':
+ dependencies:
+ '@distube/ytdl-core': 4.13.4
+ '@distube/ytpl': 1.2.1
+ '@distube/ytsr': 2.0.4
+ distube: 5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@distube/yt-dlp@2.0.1(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3))':
+ dependencies:
+ dargs: 7.0.0
+ distube: 5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)
+ undici: 6.19.2
+
+ '@distube/ytdl-core@4.13.4':
+ dependencies:
+ http-cookie-agent: 6.0.5(tough-cookie@4.1.4)(undici@6.19.2)
+ m3u8stream: 0.8.6
+ miniget: 4.2.3
+ sax: 1.4.1
+ tough-cookie: 4.1.4
+ undici: 6.19.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@distube/ytpl@1.2.1':
+ dependencies:
+ undici: 5.28.4
+
+ '@distube/ytsr@2.0.4':
+ dependencies:
+ undici: 6.19.2
+
+ '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)':
+ dependencies:
+ eslint: 8.57.0
+ eslint-visitor-keys: 3.4.3
+
+ '@eslint-community/regexpp@4.11.0': {}
+
+ '@eslint/eslintrc@2.1.4':
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.3.5
+ espree: 9.6.1
+ globals: 13.24.0
+ ignore: 5.3.1
+ import-fresh: 3.3.0
+ js-yaml: 4.1.0
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/js@8.57.0': {}
+
+ '@fastify/busboy@2.1.1': {}
+
+ '@humanwhocodes/config-array@0.11.14':
+ dependencies:
+ '@humanwhocodes/object-schema': 2.0.3
+ debug: 4.3.5
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@humanwhocodes/module-importer@1.0.1': {}
+
+ '@humanwhocodes/object-schema@2.0.3': {}
+
+ '@mongodb-js/saslprep@1.1.7':
+ dependencies:
+ sparse-bitfield: 3.0.3
+ optional: true
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.17.1
+
+ '@pkgr/core@0.1.1': {}
+
+ '@sapphire/async-queue@1.5.2': {}
+
+ '@sapphire/shapeshift@3.9.7':
+ dependencies:
+ fast-deep-equal: 3.1.3
+ lodash: 4.17.21
+
+ '@sapphire/snowflake@3.5.3': {}
+
+ '@tokenizer/token@0.3.0': {}
+
+ '@types/json-schema@7.0.15': {}
+
+ '@types/node-os-utils@1.3.4': {}
+
+ '@types/node@20.14.10':
+ dependencies:
+ undici-types: 5.26.5
+
+ '@types/semver@7.5.8': {}
+
+ '@types/uuid@9.0.8': {}
+
+ '@types/webidl-conversions@7.0.3': {}
+
+ '@types/whatwg-url@8.2.2':
+ dependencies:
+ '@types/node': 20.14.10
+ '@types/webidl-conversions': 7.0.3
+
+ '@types/ws@8.5.10':
+ dependencies:
+ '@types/node': 20.14.10
+
+ '@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)':
+ dependencies:
+ '@eslint-community/regexpp': 4.11.0
+ '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.5.3)
+ '@typescript-eslint/scope-manager': 5.62.0
+ '@typescript-eslint/type-utils': 5.62.0(eslint@8.57.0)(typescript@5.5.3)
+ '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.3)
+ debug: 4.3.5
+ eslint: 8.57.0
+ graphemer: 1.4.0
+ ignore: 5.3.1
+ natural-compare-lite: 1.4.0
+ semver: 7.6.2
+ tsutils: 3.21.0(typescript@5.5.3)
+ optionalDependencies:
+ typescript: 5.5.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.5.3)':
+ dependencies:
+ '@typescript-eslint/scope-manager': 5.62.0
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.3)
+ debug: 4.3.5
+ eslint: 8.57.0
+ optionalDependencies:
+ typescript: 5.5.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/scope-manager@5.62.0':
+ dependencies:
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/visitor-keys': 5.62.0
+
+ '@typescript-eslint/type-utils@5.62.0(eslint@8.57.0)(typescript@5.5.3)':
+ dependencies:
+ '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.3)
+ '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.5.3)
+ debug: 4.3.5
+ eslint: 8.57.0
+ tsutils: 3.21.0(typescript@5.5.3)
+ optionalDependencies:
+ typescript: 5.5.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/types@5.62.0': {}
+
+ '@typescript-eslint/typescript-estree@5.62.0(typescript@5.5.3)':
+ dependencies:
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/visitor-keys': 5.62.0
+ debug: 4.3.5
+ globby: 11.1.0
+ is-glob: 4.0.3
+ semver: 7.6.2
+ tsutils: 3.21.0(typescript@5.5.3)
+ optionalDependencies:
+ typescript: 5.5.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@5.62.0(eslint@8.57.0)(typescript@5.5.3)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
+ '@types/json-schema': 7.0.15
+ '@types/semver': 7.5.8
+ '@typescript-eslint/scope-manager': 5.62.0
+ '@typescript-eslint/types': 5.62.0
+ '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.3)
+ eslint: 8.57.0
+ eslint-scope: 5.1.1
+ semver: 7.6.2
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
+ '@typescript-eslint/visitor-keys@5.62.0':
+ dependencies:
+ '@typescript-eslint/types': 5.62.0
+ eslint-visitor-keys: 3.4.3
+
+ '@ungap/structured-clone@1.2.0': {}
+
+ '@vladfrangu/async_event_emitter@2.4.1': {}
+
+ abbrev@1.1.1:
+ optional: true
+
+ acorn-jsx@5.3.2(acorn@8.12.1):
+ dependencies:
+ acorn: 8.12.1
+
+ acorn@8.12.1: {}
+
+ agent-base@6.0.2:
+ dependencies:
+ debug: 4.3.5
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ agent-base@7.1.1:
+ dependencies:
+ debug: 4.3.5
+ transitivePeerDependencies:
+ - supports-color
+
+ ajv@6.12.6:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+
+ ansi-regex@5.0.1: {}
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ aproba@2.0.0:
+ optional: true
+
+ are-we-there-yet@2.0.0:
+ dependencies:
+ delegates: 1.0.0
+ readable-stream: 3.6.2
+ optional: true
+
+ argparse@2.0.1: {}
+
+ array-union@2.1.0: {}
+
+ asynckit@0.4.0: {}
+
+ axios@1.7.2:
+ dependencies:
+ follow-redirects: 1.15.6
+ form-data: 4.0.0
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+
+ balanced-match@1.0.2: {}
+
+ boolbase@1.0.0: {}
+
+ brace-expansion@1.1.11:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ bson@5.5.1: {}
+
+ call-bind@1.0.7:
+ dependencies:
+ es-define-property: 1.0.0
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.4
+ set-function-length: 1.2.2
+
+ callsites@3.1.0: {}
+
+ chalk@4.1.2:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
+ chownr@2.0.0:
+ optional: true
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.4: {}
+
+ color-support@1.1.3:
+ optional: true
+
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
+ component-emitter@1.3.1: {}
+
+ concat-map@0.0.1: {}
+
+ console-control-strings@1.1.0:
+ optional: true
+
+ cookiejar@2.1.4: {}
+
+ cross-env@7.0.3:
+ dependencies:
+ cross-spawn: 7.0.3
+
+ cross-spawn@7.0.3:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ css-select@5.1.0:
+ dependencies:
+ boolbase: 1.0.0
+ css-what: 6.1.0
+ domhandler: 5.0.3
+ domutils: 3.1.0
+ nth-check: 2.1.1
+
+ css-what@6.1.0: {}
+
+ dargs@7.0.0: {}
+
+ data-uri-to-buffer@4.0.1: {}
+
+ debug@4.3.5:
+ dependencies:
+ ms: 2.1.2
+
+ deep-is@0.1.4: {}
+
+ define-data-property@1.1.4:
+ dependencies:
+ es-define-property: 1.0.0
+ es-errors: 1.3.0
+ gopd: 1.0.1
+
+ delayed-stream@1.0.0: {}
+
+ delegates@1.0.0:
+ optional: true
+
+ detect-libc@2.0.3:
+ optional: true
+
+ dir-glob@3.0.1:
+ dependencies:
+ path-type: 4.0.0
+
+ discord-api-types@0.37.61: {}
+
+ discord-api-types@0.37.83: {}
+
+ discord-api-types@0.37.92: {}
+
+ discord.js@14.15.3:
+ dependencies:
+ '@discordjs/builders': 1.8.2
+ '@discordjs/collection': 1.5.3
+ '@discordjs/formatters': 0.4.0
+ '@discordjs/rest': 2.3.0
+ '@discordjs/util': 1.1.0
+ '@discordjs/ws': 1.1.1
+ '@sapphire/snowflake': 3.5.3
+ discord-api-types: 0.37.83
+ fast-deep-equal: 3.1.3
+ lodash.snakecase: 4.1.1
+ tslib: 2.6.2
+ undici: 6.13.0
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
+ distube-apple-music@0.1.0(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)):
+ dependencies:
+ distube: 5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)
+ isomorphic-unfetch: 4.0.2
+ node-html-parser: 6.1.13
+
+ distube-yandex-music-plugin@1.0.4(distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)):
+ dependencies:
+ distube: 5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3)
+ ym-api-meowed: 1.3.4
+ transitivePeerDependencies:
+ - debug
+
+ distube@5.0.2(@discordjs/voice@0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1))(discord.js@14.15.3):
+ dependencies:
+ '@discordjs/voice': 0.16.1(@discordjs/opus@0.9.0)(opusscript@0.1.1)
+ discord.js: 14.15.3
+ tiny-typed-emitter: 2.1.0
+ undici: 6.19.2
+
+ doctrine@3.0.0:
+ dependencies:
+ esutils: 2.0.3
+
+ dom-serializer@2.0.0:
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ entities: 4.5.0
+
+ domelementtype@2.3.0: {}
+
+ domhandler@5.0.3:
+ dependencies:
+ domelementtype: 2.3.0
+
+ domutils@3.1.0:
+ dependencies:
+ dom-serializer: 2.0.0
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+
+ dotenv@16.4.5: {}
+
+ emoji-regex@8.0.0:
+ optional: true
+
+ entities@4.5.0: {}
+
+ es-define-property@1.0.0:
+ dependencies:
+ get-intrinsic: 1.2.4
+
+ es-errors@1.3.0: {}
+
+ escape-string-regexp@4.0.0: {}
+
+ eslint-config-prettier@9.1.0(eslint@8.57.0):
+ dependencies:
+ eslint: 8.57.0
+
+ eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2):
+ dependencies:
+ eslint: 8.57.0
+ prettier: 3.3.2
+ prettier-linter-helpers: 1.0.0
+ synckit: 0.8.8
+ optionalDependencies:
+ eslint-config-prettier: 9.1.0(eslint@8.57.0)
+
+ eslint-scope@5.1.1:
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 4.3.0
+
+ eslint-scope@7.2.2:
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+
+ eslint-visitor-keys@3.4.3: {}
+
+ eslint@8.57.0:
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
+ '@eslint-community/regexpp': 4.11.0
+ '@eslint/eslintrc': 2.1.4
+ '@eslint/js': 8.57.0
+ '@humanwhocodes/config-array': 0.11.14
+ '@humanwhocodes/module-importer': 1.0.1
+ '@nodelib/fs.walk': 1.2.8
+ '@ungap/structured-clone': 1.2.0
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.3
+ debug: 4.3.5
+ doctrine: 3.0.0
+ escape-string-regexp: 4.0.0
+ eslint-scope: 7.2.2
+ eslint-visitor-keys: 3.4.3
+ espree: 9.6.1
+ esquery: 1.5.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 6.0.1
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ globals: 13.24.0
+ graphemer: 1.4.0
+ ignore: 5.3.1
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ is-path-inside: 3.0.3
+ js-yaml: 4.1.0
+ json-stable-stringify-without-jsonify: 1.0.1
+ levn: 0.4.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.4
+ strip-ansi: 6.0.1
+ text-table: 0.2.0
+ transitivePeerDependencies:
+ - supports-color
+
+ espree@9.6.1:
+ dependencies:
+ acorn: 8.12.1
+ acorn-jsx: 5.3.2(acorn@8.12.1)
+ eslint-visitor-keys: 3.4.3
+
+ esquery@1.5.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ esrecurse@4.3.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ estraverse@4.3.0: {}
+
+ estraverse@5.3.0: {}
+
+ esutils@2.0.3: {}
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-diff@1.3.0: {}
+
+ fast-glob@3.3.2:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.7
+
+ fast-json-stable-stringify@2.1.0: {}
+
+ fast-levenshtein@2.0.6: {}
+
+ fast-safe-stringify@2.1.1: {}
+
+ fastq@1.17.1:
+ dependencies:
+ reusify: 1.0.4
+
+ fetch-blob@3.2.0:
+ dependencies:
+ node-domexception: 1.0.0
+ web-streams-polyfill: 3.3.3
+
+ file-entry-cache@6.0.1:
+ dependencies:
+ flat-cache: 3.2.0
+
+ file-type@18.7.0:
+ dependencies:
+ readable-web-to-node-stream: 3.0.2
+ strtok3: 7.1.0
+ token-types: 5.0.1
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ find-up@5.0.0:
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+
+ flat-cache@3.2.0:
+ dependencies:
+ flatted: 3.3.1
+ keyv: 4.5.4
+ rimraf: 3.0.2
+
+ flatted@3.3.1: {}
+
+ follow-redirects@1.15.6: {}
+
+ form-data@3.0.1:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ mime-types: 2.1.35
+
+ form-data@4.0.0:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ mime-types: 2.1.35
+
+ formdata-polyfill@4.0.10:
+ dependencies:
+ fetch-blob: 3.2.0
+
+ formidable@1.2.6: {}
+
+ fs-minipass@2.1.0:
+ dependencies:
+ minipass: 3.3.6
+ optional: true
+
+ fs.realpath@1.0.0: {}
+
+ function-bind@1.1.2: {}
+
+ gauge@3.0.2:
+ dependencies:
+ aproba: 2.0.0
+ color-support: 1.1.3
+ console-control-strings: 1.1.0
+ has-unicode: 2.0.1
+ object-assign: 4.1.1
+ signal-exit: 3.0.7
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wide-align: 1.1.5
+ optional: true
+
+ get-intrinsic@1.2.4:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ has-proto: 1.0.3
+ has-symbols: 1.0.3
+ hasown: 2.0.2
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob-parent@6.0.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob@7.2.3:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+
+ globals@13.24.0:
+ dependencies:
+ type-fest: 0.20.2
+
+ globby@11.1.0:
+ dependencies:
+ array-union: 2.1.0
+ dir-glob: 3.0.1
+ fast-glob: 3.3.2
+ ignore: 5.3.1
+ merge2: 1.4.1
+ slash: 3.0.0
+
+ gopd@1.0.1:
+ dependencies:
+ get-intrinsic: 1.2.4
+
+ graphemer@1.4.0: {}
+
+ has-flag@4.0.0: {}
+
+ has-property-descriptors@1.0.2:
+ dependencies:
+ es-define-property: 1.0.0
+
+ has-proto@1.0.3: {}
+
+ has-symbols@1.0.3: {}
+
+ has-unicode@2.0.1:
+ optional: true
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ he@1.2.0: {}
+
+ himalaya@1.1.0: {}
+
+ http-cookie-agent@6.0.5(tough-cookie@4.1.4)(undici@6.19.2):
+ dependencies:
+ agent-base: 7.1.1
+ tough-cookie: 4.1.4
+ optionalDependencies:
+ undici: 6.19.2
+ transitivePeerDependencies:
+ - supports-color
+
+ https-proxy-agent@5.0.1:
+ dependencies:
+ agent-base: 6.0.2
+ debug: 4.3.5
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ i18next-fs-backend@2.3.1: {}
+
+ i18next@22.5.1:
+ dependencies:
+ '@babel/runtime': 7.24.7
+
+ ieee754@1.2.1: {}
+
+ ignore@5.3.1: {}
+
+ import-fresh@3.3.0:
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+
+ imurmurhash@0.1.4: {}
+
+ inflight@1.0.6:
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+
+ inherits@2.0.4: {}
+
+ ip-address@9.0.5:
+ dependencies:
+ jsbn: 1.1.0
+ sprintf-js: 1.1.3
+
+ is-extglob@2.1.1: {}
+
+ is-fullwidth-code-point@3.0.0:
+ optional: true
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-number@7.0.0: {}
+
+ is-path-inside@3.0.3: {}
+
+ isexe@2.0.0: {}
+
+ isomorphic-unfetch@4.0.2:
+ dependencies:
+ node-fetch: 3.3.2
+ unfetch: 5.0.0
+
+ js-yaml@4.1.0:
+ dependencies:
+ argparse: 2.0.1
+
+ jsbn@1.1.0: {}
+
+ json-buffer@3.0.1: {}
+
+ json-schema-traverse@0.4.1: {}
+
+ json-stable-stringify-without-jsonify@1.0.1: {}
+
+ kareem@2.5.1: {}
+
+ keyv@4.5.4:
+ dependencies:
+ json-buffer: 3.0.1
+
+ levn@0.4.1:
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+
+ locate-path@6.0.0:
+ dependencies:
+ p-locate: 5.0.0
+
+ lodash.merge@4.6.2: {}
+
+ lodash.snakecase@4.1.1: {}
+
+ lodash@4.17.21: {}
+
+ m3u8stream@0.8.6:
+ dependencies:
+ miniget: 4.2.3
+ sax: 1.4.1
+
+ magic-bytes.js@1.10.0: {}
+
+ make-dir@3.1.0:
+ dependencies:
+ semver: 6.3.1
+ optional: true
+
+ memory-pager@1.5.0:
+ optional: true
+
+ merge2@1.4.1: {}
+
+ methods@1.1.2: {}
+
+ micromatch@4.0.7:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ mime@2.6.0: {}
+
+ miniget@4.2.3: {}
+
+ minimatch@3.1.2:
+ dependencies:
+ brace-expansion: 1.1.11
+
+ minipass@3.3.6:
+ dependencies:
+ yallist: 4.0.0
+ optional: true
+
+ minipass@5.0.0:
+ optional: true
+
+ minizlib@2.1.2:
+ dependencies:
+ minipass: 3.3.6
+ yallist: 4.0.0
+ optional: true
+
+ mkdirp@1.0.4:
+ optional: true
+
+ mongodb-connection-string-url@2.6.0:
+ dependencies:
+ '@types/whatwg-url': 8.2.2
+ whatwg-url: 11.0.0
+
+ mongodb@5.9.2:
+ dependencies:
+ bson: 5.5.1
+ mongodb-connection-string-url: 2.6.0
+ socks: 2.8.3
+ optionalDependencies:
+ '@mongodb-js/saslprep': 1.1.7
+
+ mongoose@7.7.0:
+ dependencies:
+ bson: 5.5.1
+ kareem: 2.5.1
+ mongodb: 5.9.2
+ mpath: 0.9.0
+ mquery: 5.0.0
+ ms: 2.1.3
+ sift: 16.0.1
+ transitivePeerDependencies:
+ - '@aws-sdk/credential-providers'
+ - '@mongodb-js/zstd'
+ - kerberos
+ - mongodb-client-encryption
+ - snappy
+ - supports-color
+
+ mpath@0.9.0: {}
+
+ mquery@5.0.0:
+ dependencies:
+ debug: 4.3.5
+ transitivePeerDependencies:
+ - supports-color
+
+ ms@2.1.2: {}
+
+ ms@2.1.3: {}
+
+ natural-compare-lite@1.4.0: {}
+
+ natural-compare@1.4.0: {}
+
+ node-addon-api@5.1.0:
+ optional: true
+
+ node-domexception@1.0.0: {}
+
+ node-fetch@2.7.0:
+ dependencies:
+ whatwg-url: 5.0.0
+ optional: true
+
+ node-fetch@3.3.2:
+ dependencies:
+ data-uri-to-buffer: 4.0.1
+ fetch-blob: 3.2.0
+ formdata-polyfill: 4.0.10
+
+ node-gyp-build@4.8.1: {}
+
+ node-html-parser@6.1.13:
+ dependencies:
+ css-select: 5.1.0
+ he: 1.2.0
+
+ node-os-utils@1.3.7: {}
+
+ nopt@5.0.0:
+ dependencies:
+ abbrev: 1.1.1
+ optional: true
+
+ npmlog@5.0.1:
+ dependencies:
+ are-we-there-yet: 2.0.0
+ console-control-strings: 1.1.0
+ gauge: 3.0.2
+ set-blocking: 2.0.0
+ optional: true
+
+ nth-check@2.1.1:
+ dependencies:
+ boolbase: 1.0.0
+
+ object-assign@4.1.1:
+ optional: true
+
+ object-inspect@1.13.2: {}
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ optionator@0.9.4:
+ dependencies:
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ word-wrap: 1.2.5
+
+ opusscript@0.1.1: {}
+
+ p-limit@3.1.0:
+ dependencies:
+ yocto-queue: 0.1.0
+
+ p-locate@5.0.0:
+ dependencies:
+ p-limit: 3.1.0
+
+ parent-module@1.0.1:
+ dependencies:
+ callsites: 3.1.0
+
+ path-exists@4.0.0: {}
+
+ path-is-absolute@1.0.1: {}
+
+ path-key@3.1.1: {}
+
+ path-type@4.0.0: {}
+
+ peek-readable@5.1.1: {}
+
+ picomatch@2.3.1: {}
+
+ prelude-ls@1.2.1: {}
+
+ prettier-linter-helpers@1.0.0:
+ dependencies:
+ fast-diff: 1.3.0
+
+ prettier@3.3.2: {}
+
+ prism-media@1.3.5(@discordjs/opus@0.9.0)(opusscript@0.1.1):
+ optionalDependencies:
+ '@discordjs/opus': 0.9.0
+ opusscript: 0.1.1
+
+ proxy-from-env@1.1.0: {}
+
+ psl@1.9.0: {}
+
+ punycode@2.3.1: {}
+
+ qs@6.12.2:
+ dependencies:
+ side-channel: 1.0.6
+
+ querystringify@2.2.0: {}
+
+ queue-microtask@1.2.3: {}
+
+ readable-stream@3.6.2:
+ dependencies:
+ inherits: 2.0.4
+ string_decoder: 1.3.0
+ util-deprecate: 1.0.2
+
+ readable-web-to-node-stream@3.0.2:
+ dependencies:
+ readable-stream: 3.6.2
+
+ regenerator-runtime@0.14.1: {}
+
+ requires-port@1.0.0: {}
+
+ resolve-from@4.0.0: {}
+
+ reusify@1.0.4: {}
+
+ rimraf@3.0.2:
+ dependencies:
+ glob: 7.2.3
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ safe-buffer@5.2.1: {}
+
+ sax@1.4.1: {}
+
+ semver@6.3.1:
+ optional: true
+
+ semver@7.6.2: {}
+
+ set-blocking@2.0.0:
+ optional: true
+
+ set-function-length@1.2.2:
+ dependencies:
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.4
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.2
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ side-channel@1.0.6:
+ dependencies:
+ call-bind: 1.0.7
+ es-errors: 1.3.0
+ get-intrinsic: 1.2.4
+ object-inspect: 1.13.2
+
+ sift@16.0.1: {}
+
+ signal-exit@3.0.7:
+ optional: true
+
+ slash@3.0.0: {}
+
+ smart-buffer@4.2.0: {}
+
+ socks@2.8.3:
+ dependencies:
+ ip-address: 9.0.5
+ smart-buffer: 4.2.0
+
+ sodium-native@4.1.1:
+ dependencies:
+ node-gyp-build: 4.8.1
+
+ soundcloud.ts@0.5.3:
+ dependencies:
+ undici: 6.19.2
+
+ sparse-bitfield@3.0.3:
+ dependencies:
+ memory-pager: 1.5.0
+ optional: true
+
+ spotify-uri@4.1.0: {}
+
+ spotify-url-info@3.2.16:
+ dependencies:
+ himalaya: 1.1.0
+ spotify-uri: 4.1.0
+
+ spotify-web-api-node@5.0.2:
+ dependencies:
+ superagent: 6.1.0
+ transitivePeerDependencies:
+ - supports-color
+
+ sprintf-js@1.1.3: {}
+
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+ optional: true
+
+ string_decoder@1.3.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
+ strip-json-comments@3.1.1: {}
+
+ strtok3@7.1.0:
+ dependencies:
+ '@tokenizer/token': 0.3.0
+ peek-readable: 5.1.1
+
+ superagent@6.1.0:
+ dependencies:
+ component-emitter: 1.3.1
+ cookiejar: 2.1.4
+ debug: 4.3.5
+ fast-safe-stringify: 2.1.1
+ form-data: 3.0.1
+ formidable: 1.2.6
+ methods: 1.1.2
+ mime: 2.6.0
+ qs: 6.12.2
+ readable-stream: 3.6.2
+ semver: 7.6.2
+ transitivePeerDependencies:
+ - supports-color
+
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
+ synckit@0.8.8:
+ dependencies:
+ '@pkgr/core': 0.1.1
+ tslib: 2.6.3
+
+ tar@6.2.1:
+ dependencies:
+ chownr: 2.0.0
+ fs-minipass: 2.1.0
+ minipass: 5.0.0
+ minizlib: 2.1.2
+ mkdirp: 1.0.4
+ yallist: 4.0.0
+ optional: true
+
+ text-table@0.2.0: {}
+
+ tiny-typed-emitter@2.1.0: {}
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ token-types@5.0.1:
+ dependencies:
+ '@tokenizer/token': 0.3.0
+ ieee754: 1.2.1
+
+ tough-cookie@4.1.4:
+ dependencies:
+ psl: 1.9.0
+ punycode: 2.3.1
+ universalify: 0.2.0
+ url-parse: 1.5.10
+
+ tr46@0.0.3:
+ optional: true
+
+ tr46@3.0.0:
+ dependencies:
+ punycode: 2.3.1
+
+ ts-mixer@6.0.4: {}
+
+ tslib@1.14.1: {}
+
+ tslib@2.6.2: {}
+
+ tslib@2.6.3: {}
+
+ tsutils@3.21.0(typescript@5.5.3):
+ dependencies:
+ tslib: 1.14.1
+ typescript: 5.5.3
+
+ type-check@0.4.0:
+ dependencies:
+ prelude-ls: 1.2.1
+
+ type-fest@0.20.2: {}
+
+ typescript@5.5.3: {}
+
+ undici-types@5.26.5: {}
+
+ undici@5.28.4:
+ dependencies:
+ '@fastify/busboy': 2.1.1
+
+ undici@6.13.0: {}
+
+ undici@6.19.2: {}
+
+ unfetch@5.0.0: {}
+
+ universalify@0.2.0: {}
+
+ uri-js@4.4.1:
+ dependencies:
+ punycode: 2.3.1
+
+ url-parse@1.5.10:
+ dependencies:
+ querystringify: 2.2.0
+ requires-port: 1.0.0
+
+ util-deprecate@1.0.2: {}
+
+ uuid@9.0.1: {}
+
+ web-streams-polyfill@3.3.3: {}
+
+ webidl-conversions@3.0.1:
+ optional: true
+
+ webidl-conversions@7.0.0: {}
+
+ whatwg-url@11.0.0:
+ dependencies:
+ tr46: 3.0.0
+ webidl-conversions: 7.0.0
+
+ whatwg-url@5.0.0:
+ dependencies:
+ tr46: 0.0.3
+ webidl-conversions: 3.0.1
+ optional: true
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ wide-align@1.1.5:
+ dependencies:
+ string-width: 4.2.3
+ optional: true
+
+ word-wrap@1.2.5: {}
+
+ wrappy@1.0.2: {}
+
+ ws@8.18.0: {}
+
+ xml2js@0.6.2:
+ dependencies:
+ sax: 1.4.1
+ xmlbuilder: 11.0.1
+
+ xmlbuilder@11.0.1: {}
+
+ yallist@4.0.0:
+ optional: true
+
+ ym-api-meowed@1.3.4:
+ dependencies:
+ axios: 1.7.2
+ xml2js: 0.6.2
+ transitivePeerDependencies:
+ - debug
+
+ yocto-queue@0.1.0: {}
+
+ zod@3.23.8: {}
diff --git a/src/EnvironmentVariables.ts b/src/EnvironmentVariables.ts
index 8b08893..3ebdc9f 100644
--- a/src/EnvironmentVariables.ts
+++ b/src/EnvironmentVariables.ts
@@ -40,7 +40,8 @@ const envVariables = z.object({
BOT_SPOTIFY_CLIENT_SECRET: z.string().optional(),
BOT_SPOTIFY_CLIENT_ID: z.string().optional(),
- BOT_YANDEXMUSIC_TOKEN: z.string().optional()
+ BOT_YANDEXMUSIC_TOKEN: z.string().optional(),
+ BOT_YANDEXMUSIC_UID: z.coerce.number().optional()
});
export const ENV = envVariables.parse(process.env);
@@ -54,7 +55,7 @@ try {
loggerSend('Cookie file is loaded', loggerPrefixEnv);
} catch (e) {
loggerError(
- 'Cookie file is not provided or cookie is wrong. Please, follow this instructions https://distube.js.org/#/docs/DisTube/main/general/cookie',
+ 'Cookie file is not provided or cookie is wrong. Please, follow instructions in README.md',
loggerPrefixEnv
);
}
diff --git a/src/Types.ts b/src/Types.ts
index 090c23b..48f97c1 100644
--- a/src/Types.ts
+++ b/src/Types.ts
@@ -1,11 +1,9 @@
-import { Client, Collection } from 'discord.js';
+import { Client, ClientEvents, Collection } from 'discord.js';
import { ICommand, ICommandGroup } from './CommandTypes.js';
-import { AudioPlayerCore } from './commands/audio/audioPlayer/AudioPlayerCore.js';
-import { DisTube } from 'distube';
+import { AudioPlayerCore } from './audioplayer/AudioPlayerCore.js';
declare module 'discord.js' {
export interface Client {
- distube: DisTube;
commands: Collection;
commandsGroups: Collection;
audioPlayer: AudioPlayerCore;
@@ -13,7 +11,7 @@ declare module 'discord.js' {
}
export interface BotEvent {
- name: string;
+ name: keyof ClientEvents;
once?: boolean | false;
execute: (client: Client, ...args: any) => void;
}
diff --git a/src/commands/audio/audioPlayer/AudioPlayerCore.ts b/src/audioplayer/AudioPlayerCore.ts
similarity index 54%
rename from src/commands/audio/audioPlayer/AudioPlayerCore.ts
rename to src/audioplayer/AudioPlayerCore.ts
index 3a86acd..b16a8db 100644
--- a/src/commands/audio/audioPlayer/AudioPlayerCore.ts
+++ b/src/audioplayer/AudioPlayerCore.ts
@@ -1,3 +1,15 @@
+import { DisTube, PlayOptions, Queue, RepeatMode, Song, Events as DistubeEvents } from 'distube';
+import { AudioPlayersManager } from './AudioPlayersManager.js';
+import { pagination } from '../utilities/pagination/pagination.js';
+import { ButtonStyles, ButtonTypes } from '../utilities/pagination/paginationTypes.js';
+import { clamp } from '../utilities/clamp.js';
+import { generateErrorEmbed } from '../utilities/generateErrorEmbed.js';
+import i18next from 'i18next';
+import { loggerError, loggerSend } from '../utilities/logger.js';
+import { ENV } from '../EnvironmentVariables.js';
+import { LoadPlugins } from './LoadPlugins.js';
+import { generateAddedPlaylistMessage } from './util/generateAddedPlaylistMessage.js';
+import { generateAddedSongMessage } from './util/generateAddedSongMessage.js';
import {
Client,
CommandInteraction,
@@ -8,91 +20,12 @@ import {
TextChannel,
VoiceBasedChannel
} from 'discord.js';
-import {
- CustomPlugin,
- DisTube,
- ExtractorPlugin,
- Playlist,
- PlayOptions,
- Queue,
- RepeatMode,
- SearchResult,
- Song
-} from 'distube';
-import { AudioPlayersManager } from './AudioPlayersManager.js';
-import { SpotifyPlugin } from '@distube/spotify';
-import { YtDlpPlugin } from '@distube/yt-dlp';
-import { SoundCloudPlugin } from '@distube/soundcloud';
-import { pagination } from '../../../utilities/pagination/pagination.js';
-import { ButtonStyles, ButtonTypes } from '../../../utilities/pagination/paginationTypes.js';
-import { clamp } from '../../../utilities/clamp.js';
-import { generateErrorEmbed } from '../../../utilities/generateErrorEmbed.js';
import { joinVoiceChannel } from '@discordjs/voice';
-import i18next from 'i18next';
-
-import { YandexMusicPlugin } from 'distube-yandex-music-plugin';
-import { loggerError, loggerWarn } from '../../../utilities/logger.js';
-import { BOT_YOUTUBE_COOKIE, ENV } from '../../../EnvironmentVariables.js';
-
-const loggerPrefixAudioplayer = `Audioplayer`;
-
-function LoadPlugins(): Array {
- const plugins: Array = [];
-
- if (!BOT_YOUTUBE_COOKIE) {
- loggerWarn(
- 'BOT_YOUTUBE_COOKIE is not provided, 18+ videos from Youtube is not available',
- loggerPrefixAudioplayer
- );
- }
-
- if (ENV.BOT_SPOTIFY_CLIENT_ID && ENV.BOT_SPOTIFY_CLIENT_SECRET) {
- plugins.push(
- new SpotifyPlugin({
- parallel: true,
- emitEventsAfterFetching: true,
- api: {
- clientId: ENV.BOT_SPOTIFY_CLIENT_ID,
- clientSecret: ENV.BOT_SPOTIFY_CLIENT_SECRET
- }
- })
- );
- } else {
- loggerWarn(
- 'Spotify plugin is disabled, because BOT_SPOTIFY_CLIENT_ID and BOT_SPOTIFY_CLIENT_SECRET are wrong or not provided',
- loggerPrefixAudioplayer
- );
- }
-
- if (ENV.BOT_YANDEXMUSIC_TOKEN) {
- plugins.push(
- new YandexMusicPlugin({
- oauthToken: ENV.BOT_YANDEXMUSIC_TOKEN
- })
- );
- } else {
- loggerWarn(
- 'Yandex Music plugin is disabled, because BOT_YANDEXMUSIC_TOKEN are wrong or not provided',
- loggerPrefixAudioplayer
- );
- }
+import { generateWarningEmbed } from '../utilities/generateWarningEmbed.js';
- plugins.push(new SoundCloudPlugin());
- if (!ENV.BOT_SOUNDCLOUD_CLIENT_ID || !ENV.BOT_SOUNDCLOUD_TOKEN) {
- loggerWarn(
- 'Some Soundcloud features is disabled, because BOT_SOUNDCLOUD_CLIENT_ID or BOT_SOUNDCLOUD_TOKEN are wrong or not provided',
- loggerPrefixAudioplayer
- );
- }
-
- plugins.push(
- new YtDlpPlugin({
- update: true
- })
- );
+export const queueSongsLimit = 500;
- return plugins;
-}
+export const loggerPrefixAudioplayer = `Audioplayer`;
export class AudioPlayerCore {
client: Client;
@@ -103,64 +36,90 @@ export class AudioPlayerCore {
this.client.audioPlayer = this;
this.playersManager = new AudioPlayersManager(this.client);
this.distube = new DisTube(this.client, {
- leaveOnEmpty: true,
- emptyCooldown: ENV.NODE_ENV === 'production' ? 120 : 5,
- leaveOnFinish: false,
- leaveOnStop: true,
- youtubeCookie: BOT_YOUTUBE_COOKIE ?? undefined,
nsfw: true,
emitAddListWhenCreatingQueue: true,
emitAddSongWhenCreatingQueue: true,
savePreviousSongs: true,
+ joinNewVoiceChannel: true,
plugins: LoadPlugins()
});
- this.client.distube = this.distube;
-
this.setupEvents();
}
async play(
voiceChannel: VoiceBasedChannel,
textChannel: TextChannel,
- song: string | Song | SearchResult,
+ song: string | Song,
options?: PlayOptions
) {
- await this.distube.voices.join(voiceChannel);
-
- joinVoiceChannel({
- channelId: voiceChannel.id,
- guildId: voiceChannel.guildId,
- adapterCreator: voiceChannel.guild.voiceAdapterCreator
- });
-
try {
+ // I am need manual connect user to a voice channel, because when I am using only Distube "play"
+ // method, getVoiceConnection in @discordjs/voice is not working
+ joinVoiceChannel({
+ channelId: voiceChannel.id,
+ guildId: voiceChannel.guildId,
+ adapterCreator: voiceChannel.guild.voiceAdapterCreator
+ });
+
await this.distube.play(voiceChannel, song, options);
} catch (e) {
if (ENV.BOT_VERBOSE_LOGGING) loggerError(e);
- await textChannel.send({ embeds: [generateErrorEmbed(i18next.t('audioplayer:play_error'))] });
+ await textChannel.send({
+ embeds: [generateErrorEmbed(e.message, i18next.t('audioplayer:play_error') as string)]
+ });
}
}
async stop(guild: Guild) {
- if (this.distube.getQueue(guild)) {
- await this.distube.stop(guild);
+ const queue = this.distube.getQueue(guild);
+
+ if (queue) {
+ await queue.stop();
+ queue.voice.leave();
} else {
- await this.distube.voices.leave(guild);
+ this.distube.voices.leave(guild);
}
+
await this.playersManager.remove(guild.id);
}
async pause(guild: Guild) {
+ const queue = this.distube.getQueue(guild);
+ if (!queue) return;
+ const player = this.playersManager.get(queue.id);
+ if (!player) return;
+ if (!queue.paused) {
+ this.distube.pause(guild);
+ await player.setState('pause');
+ }
+
+ await player.update();
+ }
+
+ async resume(guild: Guild) {
+ const queue = this.distube.getQueue(guild);
+ if (!queue) return;
+ const player = this.playersManager.get(queue.id);
+ if (!player) return;
+ if (queue.paused) {
+ this.distube.resume(guild);
+ await player.setState('playing');
+ }
+
+ await player.update();
+ }
+
+ async pauseResume(guild: Guild) {
const queue = this.distube.getQueue(guild);
if (!queue) return;
const player = this.playersManager.get(queue.id);
if (!player) return;
if (queue.paused) {
- await this.distube.resume(guild);
+ this.distube.resume(guild);
await player.setState('playing');
} else {
- await this.distube.pause(guild);
+ this.distube.pause(guild);
await player.setState('pause');
}
@@ -175,15 +134,15 @@ export class AudioPlayerCore {
switch (queue.repeatMode) {
case RepeatMode.DISABLED:
- await queue.setRepeatMode(RepeatMode.SONG);
+ queue.setRepeatMode(RepeatMode.SONG);
player.embedBuilder.setLoopMode('song');
break;
case RepeatMode.SONG:
- await queue.setRepeatMode(RepeatMode.QUEUE);
+ queue.setRepeatMode(RepeatMode.QUEUE);
player.embedBuilder.setLoopMode('queue');
break;
case RepeatMode.QUEUE:
- await queue.setRepeatMode(RepeatMode.DISABLED);
+ queue.setRepeatMode(RepeatMode.DISABLED);
player.embedBuilder.setLoopMode('disabled');
break;
}
@@ -195,7 +154,7 @@ export class AudioPlayerCore {
try {
const queue = this.distube.getQueue(guild);
if (queue) {
- await this.distube.skip(guild);
+ await this.distube.skip(guild.id);
return queue.songs[0];
}
} catch (e) {
@@ -251,13 +210,14 @@ export class AudioPlayerCore {
const player = this.playersManager.get(queue.id);
if (!player) return false;
if (time < 0) time = 0;
- await this.distube.seek(guild, time);
+ this.distube.seek(guild, time);
await player.setState('playing');
return true;
} catch (e) {
return false;
}
}
+
async showQueue(interaction: Interaction) {
if (!interaction.guild) return;
const queue = this.distube.getQueue(interaction.guild);
@@ -280,13 +240,18 @@ export class AudioPlayerCore {
`${i + 1}. ` + `[${song.name}](${song.url})` + ` - \`${song.formattedDuration}\`\n`;
}
- return new EmbedBuilder()
+ const page = new EmbedBuilder()
.setAuthor({ name: `${i18next.t('audioplayer:show_queue_songs_in_queue')}: ` })
.setTitle(queue.songs[0].name!)
- .setURL(queue.songs[0].url)
.setDescription(
`**${i18next.t('audioplayer:show_queue_title')}: **\n${queueList}`.slice(0, 4096)
);
+
+ if (queue.songs[0].url) {
+ page.setURL(queue.songs[0].url);
+ }
+
+ return page;
}
const arrayEmbeds: Array = [];
@@ -330,12 +295,18 @@ export class AudioPlayerCore {
}
private setupEvents() {
+ if (ENV.BOT_VERBOSE_LOGGING) {
+ this.distube
+ .on(DistubeEvents.DEBUG, (message) => {
+ loggerSend(message, loggerPrefixAudioplayer);
+ })
+ .on(DistubeEvents.FFMPEG_DEBUG, (message) => {
+ loggerSend(message, loggerPrefixAudioplayer);
+ });
+ }
+
this.distube
- .on('empty', async (queue) => {
- await queue.textChannel?.send(i18next.t('audioplayer:event_empty') as string);
- await this.playersManager.remove(queue.id);
- })
- .on('initQueue', async (queue) => {
+ .on(DistubeEvents.INIT_QUEUE, async (queue) => {
await this.playersManager.add(queue.id, queue.textChannel as TextChannel, queue);
const player = this.playersManager.get(queue.id);
@@ -343,16 +314,16 @@ export class AudioPlayerCore {
await player.init();
}
})
- .on('playSong', async (queue) => {
+ .on(DistubeEvents.PLAY_SONG, async (queue) => {
const player = this.playersManager.get(queue.id);
if (player) {
await player.setState('playing');
}
})
- .on('disconnect', async (queue) => {
+ .on(DistubeEvents.DISCONNECT, async (queue) => {
await this.playersManager.remove(queue.id);
})
- .on('addSong', async (queue, song) => {
+ .on(DistubeEvents.ADD_SONG, async (queue, song) => {
if (queue.textChannel) {
await queue.textChannel.send({ embeds: [generateAddedSongMessage(song)] });
}
@@ -362,9 +333,21 @@ export class AudioPlayerCore {
await player.update();
}
})
- .on('addList', async (queue, playlist) => {
- if (queue.textChannel) {
- await queue.textChannel.send({ embeds: [generateAddedPlaylistMessage(playlist)] });
+ .on(DistubeEvents.ADD_LIST, async (queue, playlist) => {
+ if (!queue.textChannel) return;
+
+ await queue.textChannel.send({ embeds: [generateAddedPlaylistMessage(playlist)] });
+ if (queue.songs.length >= queueSongsLimit) {
+ await queue.textChannel.send({
+ embeds: [
+ generateWarningEmbed(
+ i18next.t('audioplayer:event_add_list_limit', {
+ queueLimit: queueSongsLimit
+ }) as string
+ )
+ ]
+ });
+ queue.songs.length = queueSongsLimit;
}
const player = this.playersManager.get(queue.id);
@@ -372,13 +355,13 @@ export class AudioPlayerCore {
await player.update();
}
})
- .on('finishSong', async (queue) => {
+ .on(DistubeEvents.FINISH_SONG, async (queue) => {
if (!this.playersManager.has(queue.id)) return;
if (queue._next || queue._prev || queue.stopped || queue.songs.length > 1) return;
- this.playersManager.get(queue.id)?.setState('waiting');
+ await this.playersManager.get(queue.id)?.setState('waiting');
})
- .on('error', async (channel, error) => {
- channel?.send({
+ .on(DistubeEvents.ERROR, async (error, queue) => {
+ queue.textChannel?.send({
embeds: [
generateErrorEmbed(`${error.name} + \n\n + ${error.message} \n\n + ${error.stack}`)
]
@@ -386,53 +369,3 @@ export class AudioPlayerCore {
});
}
}
-
-function generateAddedSongMessage(song: Song) {
- return new EmbedBuilder()
- .setTitle(song.name ?? i18next.t('audioplayer:player_embed_unknown'))
- .setURL(song.url ?? null)
- .setAuthor({ name: `🎵${i18next.t('audioplayer:event_add_song')}🎵` })
- .setThumbnail(song.thumbnail ?? null)
- .addFields(
- {
- name: `${i18next.t('audioplayer:player_embed_requester')}`,
- value: `${song.member!.user.toString()}`,
- inline: true
- },
- {
- name: `${i18next.t('audioplayer:event_add_song_length')}`,
- value: `\`${song.formattedDuration}\``,
- inline: true
- },
- {
- name: `${i18next.t('audioplayer:event_add_song_author')}`,
- value: `\`${song.uploader.name ?? i18next.t('audioplayer:player_embed_unknown')}\``,
- inline: true
- }
- );
-}
-
-function generateAddedPlaylistMessage(playlist: Playlist) {
- return new EmbedBuilder()
- .setTitle(playlist.name ?? i18next.t('audioplayer:player_embed_unknown'))
- .setURL(playlist.url ?? null)
- .setAuthor({ name: `🎵${i18next.t('audioplayer:event_add_list')}🎵` })
- .setThumbnail(playlist.thumbnail ?? null)
- .addFields(
- {
- name: `${i18next.t('audioplayer:player_embed_requester')}`,
- value: `${playlist.member!.user.toString()}`,
- inline: true
- },
- {
- name: `${i18next.t('audioplayer:event_add_list_songs_count')}`,
- value: `\`${playlist.songs.length}\``,
- inline: true
- },
- {
- name: `${i18next.t('audioplayer:event_add_song_length')}`,
- value: `\`${playlist.formattedDuration}\``,
- inline: true
- }
- );
-}
diff --git a/src/audioplayer/AudioPlayerTypes.ts b/src/audioplayer/AudioPlayerTypes.ts
new file mode 100644
index 0000000..55581f3
--- /dev/null
+++ b/src/audioplayer/AudioPlayerTypes.ts
@@ -0,0 +1,23 @@
+export type AudioPlayerState = 'playing' | 'pause' | 'waiting' | 'loading' | 'destroying';
+export type AudioPlayerLoopMode = 'disabled' | 'song' | 'queue';
+
+export enum AudioPlayerIcons {
+ stop = '<:stopwhite:1014551716043173989>',
+ play = '<:play:1257590184455835698>',
+ pause = '<:pausewhite:1014551696174764133>',
+ toogleLoopMode = '<:repeatmodewhite:1014551751858331731>',
+ previous = '<:previousbutton:1092107334542696512>',
+ skip = '<:skipbutton:1092107438234275900>',
+ shuffle = '<:shufflebutton:1092107651384614912>',
+ list = '<:songlistwhite:1014551771705782405>'
+}
+
+export enum AudioSourceIcons {
+ other = '<:audiowaves:1257591924693536829>',
+ attachment = '<:attachfile:1257591906658156576>',
+ youtube = '<:youtube:1257591994750992435>',
+ applemusic = '<:applemusic:1257591803260174467>',
+ yandexmusic = '<:yandexmusic:1257591977105555506>',
+ spotify = '<:spotify:1257591960726933576>',
+ soundcloud = '<:soundcloud:1257591943010193500>'
+}
diff --git a/src/commands/audio/audioPlayer/AudioPlayersManager.ts b/src/audioplayer/AudioPlayersManager.ts
similarity index 87%
rename from src/commands/audio/audioPlayer/AudioPlayersManager.ts
rename to src/audioplayer/AudioPlayersManager.ts
index eea762c..b92d9f0 100644
--- a/src/commands/audio/audioPlayer/AudioPlayersManager.ts
+++ b/src/audioplayer/AudioPlayersManager.ts
@@ -1,4 +1,4 @@
-import { Client, Collection, TextChannel } from 'discord.js';
+import { Client, Collection, GuildTextBasedChannel } from 'discord.js';
import { Queue } from 'distube';
import { MessagePlayer } from './MessagePlayer.js';
@@ -10,10 +10,10 @@ export class AudioPlayersManager {
}
async add(
guildId: string,
- textChannel: TextChannel,
+ textChannel: GuildTextBasedChannel,
queue: Queue
): Promise {
- if (await this.client.guilds.cache.get(guildId)) {
+ if (this.client.guilds.cache.get(guildId)) {
if (!this.collection.has(guildId)) {
this.collection.set(guildId, new MessagePlayer(this.client, textChannel, queue));
}
diff --git a/src/audioplayer/LoadPlugins.ts b/src/audioplayer/LoadPlugins.ts
new file mode 100644
index 0000000..14ec0cb
--- /dev/null
+++ b/src/audioplayer/LoadPlugins.ts
@@ -0,0 +1,93 @@
+import { ExtractorPlugin, InfoExtractorPlugin, PlayableExtractorPlugin } from 'distube';
+import { BOT_YOUTUBE_COOKIE, ENV } from '../EnvironmentVariables.js';
+import { loggerSend, loggerWarn } from '../utilities/logger.js';
+import { SpotifyPlugin } from '@distube/spotify';
+import { SoundCloudPlugin } from '@distube/soundcloud';
+import { YtDlpPlugin } from '@distube/yt-dlp';
+import { loggerPrefixAudioplayer } from './AudioPlayerCore.js';
+import { YouTubePlugin } from '@distube/youtube';
+import { DirectLinkPlugin } from '@distube/direct-link';
+import { FilePlugin } from '@distube/file';
+import { AppleMusicPlugin } from 'distube-apple-music';
+import { YandexMusicPlugin } from 'distube-yandex-music-plugin';
+
+export type DistubePlugin = ExtractorPlugin | InfoExtractorPlugin | PlayableExtractorPlugin;
+
+export function LoadPlugins(): Array {
+ const plugins: Array = [];
+
+ if (!BOT_YOUTUBE_COOKIE) {
+ loggerWarn(
+ 'BOT_YOUTUBE_COOKIE is not provided, 18+ videos from Youtube is not available',
+ loggerPrefixAudioplayer
+ );
+ }
+
+ plugins.push(
+ new YouTubePlugin({
+ cookies: BOT_YOUTUBE_COOKIE
+ })
+ );
+
+ if (!ENV.BOT_SPOTIFY_CLIENT_ID || !ENV.BOT_SPOTIFY_CLIENT_SECRET) {
+ loggerWarn(
+ 'Spotify plugin can work worse, because BOT_SPOTIFY_CLIENT_ID and BOT_SPOTIFY_CLIENT_SECRET are wrong or not provided',
+ loggerPrefixAudioplayer
+ );
+ }
+
+ plugins.push(
+ new SpotifyPlugin({
+ api: {
+ clientId: ENV.BOT_SPOTIFY_CLIENT_ID,
+ clientSecret: ENV.BOT_SPOTIFY_CLIENT_SECRET
+ }
+ })
+ );
+
+ if (ENV.BOT_YANDEXMUSIC_TOKEN && ENV.BOT_YANDEXMUSIC_UID) {
+ plugins.push(
+ new YandexMusicPlugin({
+ oauthToken: ENV.BOT_YANDEXMUSIC_TOKEN,
+ uid: ENV.BOT_YANDEXMUSIC_UID
+ })
+ );
+ } else {
+ loggerWarn(
+ 'Yandex Music plugin is disabled, because BOT_YANDEXMUSIC_TOKEN and BOT_YANDEXMUSIC_UID are wrong or not provided',
+ loggerPrefixAudioplayer
+ );
+ }
+
+ if (!ENV.BOT_SOUNDCLOUD_CLIENT_ID || !ENV.BOT_SOUNDCLOUD_TOKEN) {
+ loggerWarn(
+ 'Some Soundcloud features is disabled, because BOT_SOUNDCLOUD_CLIENT_ID or BOT_SOUNDCLOUD_TOKEN are wrong or not provided',
+ loggerPrefixAudioplayer
+ );
+ }
+
+ plugins.push(
+ new SoundCloudPlugin({
+ clientId: ENV.BOT_SOUNDCLOUD_CLIENT_ID,
+ oauthToken: ENV.BOT_SOUNDCLOUD_TOKEN
+ })
+ );
+
+ plugins.push(new AppleMusicPlugin());
+ plugins.push(new DirectLinkPlugin());
+ plugins.push(new FilePlugin());
+ plugins.push(
+ new YtDlpPlugin({
+ update: true
+ })
+ );
+
+ loggerSend(
+ `Loaded plugins: ${plugins.map((plugin: DistubePlugin) => {
+ return ' ' + plugin.constructor.name;
+ })}`,
+ loggerPrefixAudioplayer
+ );
+
+ return plugins;
+}
diff --git a/src/commands/audio/audioPlayer/MessagePlayer.ts b/src/audioplayer/MessagePlayer.ts
similarity index 77%
rename from src/commands/audio/audioPlayer/MessagePlayer.ts
rename to src/audioplayer/MessagePlayer.ts
index 89480af..b898fa4 100644
--- a/src/commands/audio/audioPlayer/MessagePlayer.ts
+++ b/src/audioplayer/MessagePlayer.ts
@@ -1,17 +1,18 @@
-import { Client, Message, TextChannel } from 'discord.js';
+import { Client, GuildTextBasedChannel, Message } from 'discord.js';
import { MessagePlayerEmbedBuilder } from './MessagePlayerEmbedBuilder.js';
import { Queue, Song } from 'distube';
import { MessagePlayerButtonsHandler } from './MessagePlayerButtonsHandler.js';
import { AudioPlayerState } from './AudioPlayerTypes.js';
-import { checkBotInVoice } from '../../../utilities/checkBotInVoice.js';
+import { checkBotInVoice } from '../utilities/checkBotInVoice.js';
import i18next from 'i18next';
-import { ENV } from '../../../EnvironmentVariables.js';
-import { loggerError } from '../../../utilities/logger.js';
+import { ENV } from '../EnvironmentVariables.js';
+import { loggerError } from '../utilities/logger.js';
+import { generateSimpleEmbed } from '../utilities/generateSimpleEmbed.js';
export class MessagePlayer {
private readonly client: Client;
// TextChannel where player was created
- readonly textChannel: TextChannel;
+ readonly textChannel: GuildTextBasedChannel;
// Player state
private state: AudioPlayerState = 'loading';
// Player embed interface
@@ -24,34 +25,63 @@ export class MessagePlayer {
// Variable for "recreationPlayer"
lastDeletedMessage: Message | undefined;
// Delay for player recreation
- private updateTime = 3500;
+ private updateTime = 3500; // in ms
// Timer for "recreationPlayer"
private recreationTimer: NodeJS.Timeout | undefined;
// Time for "waiting" state
- private finishTime = 20000;
+ private finishTime = 20000; // in ms
// Timer object for "waiting" state
private finishTimer: NodeJS.Timeout | undefined;
- constructor(client: Client, txtChannel: TextChannel, queue: Queue) {
+
+ // If no one in voice channel, start afk timer
+ private afkTime = 20000; // in ms
+ private afkTimer: NodeJS.Timeout | undefined;
+
+ constructor(client: Client, txtChannel: GuildTextBasedChannel, queue: Queue) {
this.client = client;
this.textChannel = txtChannel;
this.queue = queue;
this.buttonsHandler = new MessagePlayerButtonsHandler(this.client, this.textChannel);
}
+ async startAfkTimer() {
+ try {
+ this.afkTimer = setTimeout(async () => {
+ await this.client.audioPlayer.stop(this.textChannel.guild);
+ await this.textChannel.send({
+ embeds: [generateSimpleEmbed(i18next.t('audioplayer:event_empty') as string)]
+ });
+ await this.stopAfkTimer();
+ await this.stopFinishTimer();
+ }, this.afkTime);
+ } catch (e) {
+ if (ENV.BOT_VERBOSE_LOGGING) loggerError(e);
+ }
+ }
+
+ async stopAfkTimer() {
+ if (this.afkTimer) {
+ clearTimeout(this.afkTimer);
+ }
+ }
+
// If a player is in "waiting" state, they start finish timer.
// It can be canceled by switching state to any other state
async startFinishTimer() {
try {
- if (await checkBotInVoice(this.textChannel.guild)) {
+ if (checkBotInVoice(this.textChannel.guild)) {
await this.stopFinishTimer();
this.finishTimer = setTimeout(async () => {
- const queue = this.client.audioPlayer.distube.getQueue(this.textChannel.guild);
+ const queue = this.client.audioPlayer.distube.getQueue(this.textChannel.guild.id);
// loggerSend('try to stop player on cooldown')
if (queue) return;
- if (await checkBotInVoice(this.textChannel.guild)) {
+ if (checkBotInVoice(this.textChannel.guild)) {
await this.client.audioPlayer.stop(this.textChannel.guild);
- await this.textChannel.send(i18next.t('audioplayer:event_finish_time') as string);
+ await this.textChannel.send({
+ embeds: [generateSimpleEmbed(i18next.t('audioplayer:event_finish_time') as string)]
+ });
await this.stopFinishTimer();
+ await this.stopAfkTimer();
}
}, this.finishTime);
}
@@ -68,7 +98,7 @@ export class MessagePlayer {
// Update embed interface to represent the current state of player, BUT THIS NOT PUSHES UPDATED EMBED TO MESSAGE
private updateEmbedState() {
const queue: Queue | undefined = this.client.audioPlayer.distube.getQueue(
- this.textChannel.guild
+ this.textChannel.guild.id
);
if (queue) {
this.queue = queue;
@@ -78,15 +108,16 @@ export class MessagePlayer {
const currentSong: Song = this.queue.songs[0];
if (currentSong) {
this.embedBuilder.setSongDuration(currentSong.duration, currentSong.isLive);
+ this.embedBuilder.setSongSource(currentSong);
this.embedBuilder.setSongTitle(
currentSong.name ?? i18next.t('audioplayer:player_embed_unknown'),
- currentSong.url
+ currentSong.url!
);
this.embedBuilder.setThumbnailURL(currentSong.thumbnail ?? null);
this.embedBuilder.setUploader(currentSong.uploader.name);
if (currentSong.user) {
- this.embedBuilder.setRequester(currentSong.user);
+ this.embedBuilder.setRequester(currentSong.user!);
}
}
this.embedBuilder.setNextSong(this.queue.songs[1]?.name);
@@ -99,22 +130,11 @@ export class MessagePlayer {
private async updateMessageState() {
if (!this.messageWithPlayer) return;
try {
- switch (this.state) {
- case 'playing':
- case 'pause':
- await this.messageWithPlayer.edit({
- embeds: [this.embedBuilder],
- components: this.buttonsHandler.getComponents()
- });
- break;
- case 'waiting':
- case 'loading':
- await this.messageWithPlayer.edit({
- embeds: [this.embedBuilder],
- components: this.buttonsHandler.getComponentsOnlyStop()
- });
- break;
- }
+ this.buttonsHandler.setComponentsState(this.state);
+ await this.messageWithPlayer.edit({
+ embeds: [this.embedBuilder],
+ components: this.buttonsHandler.getComponents()
+ });
} catch (e) {
if (ENV.BOT_VERBOSE_LOGGING) loggerError(e);
}
@@ -198,12 +218,12 @@ export class MessagePlayer {
try {
await this.messageWithPlayer?.delete();
} catch (e) {
- if (ENV.BOT_VERBOSE_LOGGING) loggerError(e);
+ //if (ENV.BOT_VERBOSE_LOGGING) loggerError(e);
}
}, 5000);
}
} catch (e) {
- if (ENV.BOT_VERBOSE_LOGGING) loggerError(e);
+ //if (ENV.BOT_VERBOSE_LOGGING) loggerError(e);
}
}
@@ -212,17 +232,15 @@ export class MessagePlayer {
this.state = state;
// When Distube is waiting the song, they remove their Queue object.
// So when we try to play a new song, we need to receive a new Queue
- const queue = this.client.audioPlayer.distube.getQueue(this.textChannel.guild);
+ const queue = this.client.audioPlayer.distube.getQueue(this.textChannel.guild.id);
if (queue) {
this.queue = queue;
}
if (state === 'waiting') {
await this.startFinishTimer();
- } else {
- if (this.finishTimer && queue) {
- clearTimeout(this.finishTimer);
- }
+ } else if (queue) {
+ await this.stopFinishTimer();
}
await this.update();
diff --git a/src/audioplayer/MessagePlayerButtonsHandler.ts b/src/audioplayer/MessagePlayerButtonsHandler.ts
new file mode 100644
index 0000000..3e17bae
--- /dev/null
+++ b/src/audioplayer/MessagePlayerButtonsHandler.ts
@@ -0,0 +1,243 @@
+import {
+ ActionRowBuilder,
+ ButtonBuilder,
+ ButtonStyle,
+ InteractionCollector,
+ ComponentType,
+ Client,
+ GuildMember,
+ ButtonInteraction,
+ Guild,
+ GuildTextBasedChannel
+} from 'discord.js';
+import { checkMemberInVoiceWithBot } from '../utilities/checkMemberInVoiceWithBot.js';
+import { generateErrorEmbed } from '../utilities/generateErrorEmbed.js';
+import { loggerError } from '../utilities/logger.js';
+import { generateSkipEmbed, generateSkipEmbedFailure } from '../commands/audio/skip.command.js';
+import {
+ generateEmbedAudioPlayerShuffle,
+ generateEmbedAudioPlayerShuffleFailure
+} from '../commands/audio/shuffle.command.js';
+import { AudioPlayerIcons, AudioPlayerState } from './AudioPlayerTypes.js';
+import { generateEmbedAudioPlayerStop } from '../commands/audio/stop.command.js';
+import {
+ generateEmbedAudioPlayerPrevious,
+ generateEmbedAudioPlayerPreviousFailure
+} from '../commands/audio/previous.command.js';
+
+enum ButtonIDs {
+ stopMusic = 'stopMusic',
+ pauseMusic = 'pauseMusic',
+ toggleLoopMode = 'toggleLoopMode',
+ previousSong = 'previousSong',
+ skipSong = 'skipSong',
+ //downloadSong = 'downloadSong',
+ shuffle = 'shuffle',
+ showQueue = 'showQueue'
+}
+
+const rowPrimary = new ActionRowBuilder().addComponents(
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.stopMusic)
+ .setStyle(ButtonStyle.Danger)
+ .setEmoji(AudioPlayerIcons.stop),
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.pauseMusic)
+ .setStyle(ButtonStyle.Primary)
+ .setEmoji(AudioPlayerIcons.pause),
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.toggleLoopMode)
+ .setStyle(ButtonStyle.Primary)
+ .setEmoji(AudioPlayerIcons.toogleLoopMode),
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.previousSong)
+ .setStyle(ButtonStyle.Primary)
+ .setEmoji(AudioPlayerIcons.previous),
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.skipSong)
+ .setStyle(ButtonStyle.Primary)
+ .setEmoji(AudioPlayerIcons.skip)
+);
+
+const rowPrimaryPaused = new ActionRowBuilder().addComponents(
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.stopMusic)
+ .setStyle(ButtonStyle.Danger)
+ .setEmoji(AudioPlayerIcons.stop),
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.pauseMusic)
+ .setStyle(ButtonStyle.Success)
+ .setEmoji(AudioPlayerIcons.play),
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.toggleLoopMode)
+ .setStyle(ButtonStyle.Primary)
+ .setEmoji(AudioPlayerIcons.toogleLoopMode),
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.previousSong)
+ .setStyle(ButtonStyle.Primary)
+ .setEmoji(AudioPlayerIcons.previous),
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.skipSong)
+ .setStyle(ButtonStyle.Primary)
+ .setEmoji(AudioPlayerIcons.skip)
+);
+
+const rowSecondary = new ActionRowBuilder().addComponents(
+ //new ButtonBuilder().setCustomId(ButtonIDs.downloadSong).setStyle(ButtonStyle.Success).setEmoji('<:downloadwhite:1014553027614617650>'),
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.shuffle)
+ .setStyle(ButtonStyle.Primary)
+ .setEmoji(AudioPlayerIcons.shuffle),
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.showQueue)
+ .setStyle(ButtonStyle.Secondary)
+ .setEmoji(AudioPlayerIcons.list)
+);
+
+const rowWithOnlyStop = new ActionRowBuilder().addComponents(
+ new ButtonBuilder()
+ .setCustomId(ButtonIDs.stopMusic)
+ .setStyle(ButtonStyle.Danger)
+ .setEmoji(AudioPlayerIcons.stop)
+);
+
+export class MessagePlayerButtonsHandler {
+ private collector: InteractionCollector;
+ private client: Client;
+ private components: Array>;
+
+ constructor(client: Client, textChannel: GuildTextBasedChannel) {
+ this.components = [rowPrimary, rowSecondary];
+ this.client = client;
+
+ this.collector = textChannel.createMessageComponentCollector({
+ componentType: ComponentType.Button
+ });
+
+ this.collector.on('collect', async (ButtonInteraction: ButtonInteraction) => {
+ try {
+ const checkObj = await checkMemberInVoiceWithBot(ButtonInteraction.member as GuildMember);
+ if (!checkObj.channelTheSame) {
+ await ButtonInteraction.reply({
+ embeds: [generateErrorEmbed(checkObj.errorMessage)],
+ ephemeral: true
+ });
+ return;
+ }
+
+ switch (ButtonInteraction.customId) {
+ case ButtonIDs.stopMusic: {
+ const guild = ButtonInteraction.guild as Guild;
+
+ const player = this.client.audioPlayer.playersManager.get(guild.id);
+
+ if (player) {
+ await player.textChannel.send({
+ embeds: [generateEmbedAudioPlayerStop(ButtonInteraction.member as GuildMember)]
+ });
+ }
+
+ await this.client.audioPlayer.stop(guild);
+
+ await ButtonInteraction.deferUpdate();
+ break;
+ }
+ case ButtonIDs.pauseMusic:
+ await this.client.audioPlayer.pauseResume(ButtonInteraction.guild as Guild);
+ await ButtonInteraction.deferUpdate();
+ break;
+
+ case ButtonIDs.previousSong: {
+ const song = await this.client.audioPlayer.previous(ButtonInteraction.guild as Guild);
+ if (song) {
+ await ButtonInteraction.reply({
+ embeds: [
+ generateEmbedAudioPlayerPrevious(ButtonInteraction.member as GuildMember, song)
+ ]
+ });
+ } else {
+ await ButtonInteraction.reply({
+ embeds: [generateEmbedAudioPlayerPreviousFailure()],
+ ephemeral: true
+ });
+ }
+ break;
+ }
+
+ case ButtonIDs.skipSong: {
+ const song = await this.client.audioPlayer.skip(ButtonInteraction.guild as Guild);
+
+ if (song) {
+ await ButtonInteraction.reply({
+ embeds: [generateSkipEmbed(song, ButtonInteraction.member as GuildMember)]
+ });
+ } else {
+ await ButtonInteraction.reply({
+ embeds: [generateSkipEmbedFailure()],
+ ephemeral: true
+ });
+ }
+ break;
+ }
+
+ case ButtonIDs.toggleLoopMode:
+ await this.client.audioPlayer.changeLoopMode(ButtonInteraction.guild as Guild);
+ await ButtonInteraction.deferUpdate();
+ break;
+
+ // case ButtonIDs.downloadSong: {
+ // const song = this.client.audioplayer.distube.getQueue(ButtonInteraction.guild as Guild)?.songs[0]
+ //
+ // if (!song) {
+ // await ButtonInteraction.reply({embeds: [generateErrorEmbed(i18next.t("audioplayer:download_song_error"))]})
+ // break
+ // }
+ // await ButtonInteraction.reply({ephemeral: true, embeds: [generateDownloadSongEmbed(song.streamURL ?? song.url)]})
+ // break
+ // }
+
+ case ButtonIDs.showQueue:
+ await this.client.audioPlayer.showQueue(ButtonInteraction);
+ break;
+
+ case ButtonIDs.shuffle: {
+ if (await this.client.audioPlayer.shuffle(ButtonInteraction.guild as Guild)) {
+ await ButtonInteraction.reply({
+ embeds: [generateEmbedAudioPlayerShuffle(ButtonInteraction.member as GuildMember)]
+ });
+ } else {
+ await ButtonInteraction.reply({ embeds: [generateEmbedAudioPlayerShuffleFailure()] });
+ }
+ break;
+ }
+ }
+ } catch (e) {
+ loggerError(e);
+ }
+ });
+ }
+
+ setComponentsState(state: AudioPlayerState) {
+ switch (state) {
+ case 'playing':
+ this.components = [rowPrimary, rowSecondary];
+ break;
+ case 'pause':
+ this.components = [rowPrimaryPaused, rowSecondary];
+ break;
+ case 'loading':
+ case 'waiting':
+ case 'destroying':
+ default:
+ this.components = [rowWithOnlyStop];
+ }
+ }
+
+ getComponents(): Array> {
+ return this.components;
+ }
+
+ destroy() {
+ this.collector.stop();
+ }
+}
diff --git a/src/commands/audio/audioPlayer/MessagePlayerEmbedBuilder.ts b/src/audioplayer/MessagePlayerEmbedBuilder.ts
similarity index 89%
rename from src/commands/audio/audioPlayer/MessagePlayerEmbedBuilder.ts
rename to src/audioplayer/MessagePlayerEmbedBuilder.ts
index c9ee04c..04a02ae 100644
--- a/src/commands/audio/audioPlayer/MessagePlayerEmbedBuilder.ts
+++ b/src/audioplayer/MessagePlayerEmbedBuilder.ts
@@ -1,8 +1,10 @@
import { EmbedBuilder, User } from 'discord.js';
-import { AudioPlayerLoopMode, AudioPlayerState } from './AudioPlayerTypes.js';
-import { getNoun } from '../../../utilities/getNoun.js';
-import { formatSecondsToTime } from '../../../utilities/formatSecondsToTime.js';
+import { AudioPlayerLoopMode, AudioPlayerState, AudioSourceIcons } from './AudioPlayerTypes.js';
+import { getNoun } from '../utilities/getNoun.js';
+import { formatSecondsToTime } from '../utilities/formatSecondsToTime.js';
import i18next from 'i18next';
+import { Playlist, Song } from 'distube';
+import { getIconFromSource } from './util/getIconFromSource.js';
export class MessagePlayerEmbedBuilder extends EmbedBuilder {
private playerState: AudioPlayerState = 'loading';
@@ -16,11 +18,13 @@ export class MessagePlayerEmbedBuilder extends EmbedBuilder {
private titleUrl: string | null = null;
private thumbnailURL: string | null = null;
private formattedDuration = '00:00';
+ private sourceIcon: AudioSourceIcons;
constructor() {
super();
this.setPlayerState('loading');
this.setNextSong(undefined);
+ this.sourceIcon = AudioSourceIcons.other;
}
update() {
@@ -35,7 +39,7 @@ export class MessagePlayerEmbedBuilder extends EmbedBuilder {
});
}
this.setThumbnail(this.thumbnailURL);
- this.setTitle(this.title);
+ this.setTitle(this.sourceIcon + " " + this.title);
this.setURL(this.titleUrl);
this.addFields({
name: i18next.t('audioplayer:player_embed_author'),
@@ -75,6 +79,10 @@ export class MessagePlayerEmbedBuilder extends EmbedBuilder {
return this;
}
+ setSongSource(playable: Song | Playlist) {
+ this.sourceIcon = getIconFromSource(playable.source);
+ }
+
setSongTitle(name: string, url: string) {
this.title = name;
this.titleUrl = url;
diff --git a/src/audioplayer/eventsHandlers/AudioPlayerEventChannelDelete.ts b/src/audioplayer/eventsHandlers/AudioPlayerEventChannelDelete.ts
new file mode 100644
index 0000000..a7af156
--- /dev/null
+++ b/src/audioplayer/eventsHandlers/AudioPlayerEventChannelDelete.ts
@@ -0,0 +1,8 @@
+import { Client, TextChannel } from 'discord.js';
+
+export async function AudioPlayerEventChannelDelete(client: Client, channel: TextChannel) {
+ const player = client.audioPlayer.playersManager.get(channel.guild.id);
+ if (player?.textChannel.id === channel.id) {
+ await client.audioPlayer.stop(channel.guild);
+ }
+}
diff --git a/src/events/messageHandlers/playerMessageHandler.ts b/src/audioplayer/eventsHandlers/AudioPlayerEventMessageCreate.ts
similarity index 84%
rename from src/events/messageHandlers/playerMessageHandler.ts
rename to src/audioplayer/eventsHandlers/AudioPlayerEventMessageCreate.ts
index 6b09dfe..27f3d13 100644
--- a/src/events/messageHandlers/playerMessageHandler.ts
+++ b/src/audioplayer/eventsHandlers/AudioPlayerEventMessageCreate.ts
@@ -2,7 +2,7 @@ import { TextChannel } from 'discord.js';
import { ENV } from '../../EnvironmentVariables.js';
import { loggerError } from '../../utilities/logger.js';
-export async function playerMessageHandler(textChannel: TextChannel) {
+export async function AudioPlayerEventMessageCreate(textChannel: TextChannel) {
try {
const player = textChannel.client.audioPlayer.playersManager.get(textChannel.guild.id);
if (player) {
diff --git a/src/audioplayer/eventsHandlers/AudioPlayerEventMessageDeleted.ts b/src/audioplayer/eventsHandlers/AudioPlayerEventMessageDeleted.ts
new file mode 100644
index 0000000..ecbf243
--- /dev/null
+++ b/src/audioplayer/eventsHandlers/AudioPlayerEventMessageDeleted.ts
@@ -0,0 +1,19 @@
+import { Client, Message, TextChannel } from 'discord.js';
+import { ENV } from '../../EnvironmentVariables.js';
+import { loggerError } from '../../utilities/logger.js';
+
+export async function AudioPlayerEventMessageDeleted(client: Client, message: Message){
+ if (!message.guild) return;
+
+ const textChannel = message.channel as TextChannel;
+ const player = client.audioPlayer.playersManager.get(textChannel.guild.id);
+ if (player) {
+ if (player.textChannel.id !== textChannel.id) return;
+ if (player.lastDeletedMessage?.id === message.id) return; // If player deleted message them self, then don`t "trigger" event
+ try {
+ await player.recreatePlayer();
+ } catch (e) {
+ if (ENV.BOT_VERBOSE_LOGGING) loggerError(e);
+ }
+ }
+}
diff --git a/src/audioplayer/eventsHandlers/AudioPlayerEventVoiceChannelUpdate.ts b/src/audioplayer/eventsHandlers/AudioPlayerEventVoiceChannelUpdate.ts
new file mode 100644
index 0000000..b44c628
--- /dev/null
+++ b/src/audioplayer/eventsHandlers/AudioPlayerEventVoiceChannelUpdate.ts
@@ -0,0 +1,19 @@
+import { Client, VoiceState } from 'discord.js';
+import { isVoiceChannelEmpty } from 'distube';
+
+export async function AudioPlayerEventVoiceChannelUpdate(
+ client: Client,
+ oldState: VoiceState,
+ newState: VoiceState
+) {
+ const messagePlayer = client.audioPlayer.playersManager.get(oldState.guild.id);
+ if (!messagePlayer) return;
+
+ if (isVoiceChannelEmpty(oldState)) {
+ await messagePlayer.startAfkTimer();
+ await client.audioPlayer.pause(oldState.guild);
+ } else if (!isVoiceChannelEmpty(newState) && messagePlayer.getState() === 'pause') {
+ await messagePlayer.stopAfkTimer();
+ await client.audioPlayer.resume(oldState.guild);
+ }
+}
diff --git a/src/commands/audio/util/AudioCommandWrappers.ts b/src/audioplayer/util/AudioCommandWrappers.ts
similarity index 94%
rename from src/commands/audio/util/AudioCommandWrappers.ts
rename to src/audioplayer/util/AudioCommandWrappers.ts
index fddd686..c7b9633 100644
--- a/src/commands/audio/util/AudioCommandWrappers.ts
+++ b/src/audioplayer/util/AudioCommandWrappers.ts
@@ -1,4 +1,4 @@
-import { generateErrorEmbed } from '../../../utilities/generateErrorEmbed.js';
+import { generateErrorEmbed } from '../../utilities/generateErrorEmbed.js';
import { ChatInputCommandInteraction, Message } from 'discord.js';
import i18next from 'i18next';
diff --git a/src/commands/audio/util/downloadSong.ts b/src/audioplayer/util/downloadSong.ts
similarity index 67%
rename from src/commands/audio/util/downloadSong.ts
rename to src/audioplayer/util/downloadSong.ts
index 8b25a44..3f40636 100644
--- a/src/commands/audio/util/downloadSong.ts
+++ b/src/audioplayer/util/downloadSong.ts
@@ -4,11 +4,13 @@ import fs, { createReadStream, ReadStream } from 'fs';
import { pipeline } from 'stream/promises';
import { v4 as uuidv4 } from 'uuid';
import { unlink } from 'fs/promises';
-import { isURL } from 'distube';
+import { isURL, Playlist, Song } from 'distube';
import i18next from 'i18next';
-fs.rmSync('./downloads', { recursive: true, force: true });
-fs.mkdirSync('./downloads');
+const downloadFolderPath = process.cwd() + '/downloads';
+
+fs.rmSync(downloadFolderPath, { recursive: true, force: true });
+fs.mkdirSync(downloadFolderPath);
class DownloadSongError extends Error {
constructor(message: DownloadSongMessage) {
@@ -17,34 +19,37 @@ class DownloadSongError extends Error {
}
}
-type DownloadSongMessage = 'is_not_url' | 'not_found' | 'song_is_too_large' | 'failed_loading';
-const maxDownloadSize = 10000000; //bytes
+type DownloadSongMessage =
+ | 'is_not_url'
+ | 'not_found'
+ | 'song_is_too_large'
+ | 'failed_loading'
+ | 'this_is_playlist';
+
+const maxDownloadSize = 2.5e7; //bytes
+const maxDownloadSizeMB = maxDownloadSize / 1000000;
export async function downloadSong(
client: Client,
request: string
): Promise {
- let streamUrl = '';
+ let streamUrl: string | undefined = '';
if (!isURL(request)) {
throw new DownloadSongError('is_not_url');
}
- for (const plugin of client.audioPlayer.distube.customPlugins) {
- if (await plugin.validate(request)) {
- streamUrl = await plugin.getStreamURL(request);
- break;
- }
+ const song: Song | Playlist = await client.audioPlayer.distube.handler.resolve(request);
+ if (song instanceof Playlist) {
+ throw new DownloadSongError('this_is_playlist');
}
- for (const plugin of client.audioPlayer.distube.extractorPlugins) {
- if (await plugin.validate(request)) {
- streamUrl = await plugin.getStreamURL(request);
- break;
- }
- }
+ await client.audioPlayer.distube.handler.attachStreamInfo(song);
+
+ // @ts-expect-error Url property exists, I know it
+ streamUrl = song.stream.playFromSource ? song.stream.url : song.stream.song?.stream.url;
- if (streamUrl === '') {
+ if (streamUrl === '' || streamUrl === undefined) {
throw new DownloadSongError('not_found');
}
@@ -68,6 +73,7 @@ async function convertWebmToMp3(webmStream: ReadableStream) {
const file = fs.createWriteStream(file_name);
const duplex = prism.FFmpeg.from(webmStream);
+ // @ts-expect-error Duplex can be provided to pipeline function
await pipeline(duplex, file);
return createReadStream(file_name);
}
@@ -88,7 +94,7 @@ export async function deleteMP3file(fileName: string) {
export function DownloadSongErrorGetLocale(errorMessage: DownloadSongMessage) {
if (errorMessage === 'song_is_too_large') {
return i18next.t(`commands:download_song_error_${errorMessage}`, {
- maxDownloadSize: maxDownloadSize / 1000000
+ maxDownloadSize: maxDownloadSizeMB
});
}
return i18next.t(`commands:download_song_error_${errorMessage}`);
diff --git a/src/audioplayer/util/generateAddedPlaylistMessage.ts b/src/audioplayer/util/generateAddedPlaylistMessage.ts
new file mode 100644
index 0000000..e7cf060
--- /dev/null
+++ b/src/audioplayer/util/generateAddedPlaylistMessage.ts
@@ -0,0 +1,31 @@
+import { Playlist } from 'distube';
+import { EmbedBuilder } from 'discord.js';
+import i18next from 'i18next';
+import { getIconFromSource } from './getIconFromSource.js';
+
+export function generateAddedPlaylistMessage(playlist: Playlist) {
+ const serviceIcon = getIconFromSource(playlist.source);
+
+ return new EmbedBuilder()
+ .setTitle(`${serviceIcon} ${playlist.name}` ?? i18next.t('audioplayer:player_embed_unknown'))
+ .setURL(playlist.url ?? null)
+ .setAuthor({ name: `${i18next.t('audioplayer:event_add_list')}` })
+ .setThumbnail(playlist.thumbnail ?? null)
+ .addFields(
+ {
+ name: `${i18next.t('audioplayer:player_embed_requester')}`,
+ value: `${playlist.member!.user.toString()}`,
+ inline: true
+ },
+ {
+ name: `${i18next.t('audioplayer:event_add_list_songs_count')}`,
+ value: `\`${playlist.songs.length}\``,
+ inline: true
+ },
+ {
+ name: `${i18next.t('audioplayer:event_add_song_length')}`,
+ value: `\`${playlist.formattedDuration}\``,
+ inline: true
+ }
+ );
+}
diff --git a/src/audioplayer/util/generateAddedSongMessage.ts b/src/audioplayer/util/generateAddedSongMessage.ts
new file mode 100644
index 0000000..ff9d23e
--- /dev/null
+++ b/src/audioplayer/util/generateAddedSongMessage.ts
@@ -0,0 +1,31 @@
+import { Song } from 'distube';
+import { EmbedBuilder } from 'discord.js';
+import i18next from 'i18next';
+import { getIconFromSource } from './getIconFromSource.js';
+
+export function generateAddedSongMessage(song: Song) {
+ const serviceIcon = getIconFromSource(song.source);
+
+ return new EmbedBuilder()
+ .setTitle(`${serviceIcon} ${song.name}` ?? i18next.t('audioplayer:player_embed_unknown'))
+ .setURL(song.url ?? null)
+ .setAuthor({ name: `${i18next.t('audioplayer:event_add_song')}` })
+ .setThumbnail(song.thumbnail ?? null)
+ .addFields(
+ {
+ name: `${i18next.t('audioplayer:player_embed_requester')}`,
+ value: `${song.member!.user.toString()}`,
+ inline: true
+ },
+ {
+ name: `${i18next.t('audioplayer:event_add_song_length')}`,
+ value: `\`${song.formattedDuration}\``,
+ inline: true
+ },
+ {
+ name: `${i18next.t('audioplayer:event_add_song_author')}`,
+ value: `\`${song.uploader.name ?? i18next.t('audioplayer:player_embed_unknown')}\``,
+ inline: true
+ }
+ );
+}
diff --git a/src/audioplayer/util/getIconFromSource.ts b/src/audioplayer/util/getIconFromSource.ts
new file mode 100644
index 0000000..584a765
--- /dev/null
+++ b/src/audioplayer/util/getIconFromSource.ts
@@ -0,0 +1,20 @@
+import { AudioSourceIcons } from '../AudioPlayerTypes.js';
+
+export function getIconFromSource(source: string): AudioSourceIcons {
+ switch (source) {
+ case 'applemusic':
+ return AudioSourceIcons.applemusic;
+ case 'spotify':
+ return AudioSourceIcons.spotify;
+ case 'youtube':
+ return AudioSourceIcons.youtube;
+ case 'file':
+ return AudioSourceIcons.attachment;
+ case 'soundcloud':
+ return AudioSourceIcons.soundcloud;
+ case 'yandexmusic':
+ return AudioSourceIcons.yandexmusic;
+ default:
+ return AudioSourceIcons.other;
+ }
+}
diff --git a/src/commands/audio/util/isAudioFile.ts b/src/audioplayer/util/isAudioFile.ts
similarity index 100%
rename from src/commands/audio/util/isAudioFile.ts
rename to src/audioplayer/util/isAudioFile.ts
diff --git a/src/commands/admin/setPrefix.command.ts b/src/commands/admin/setPrefix.command.ts
index 3016f1f..4578798 100644
--- a/src/commands/admin/setPrefix.command.ts
+++ b/src/commands/admin/setPrefix.command.ts
@@ -9,7 +9,7 @@ export default function (): ICommand {
text_data: {
name: 'setprefix',
description: i18next.t('commands:set_prefix_desc'),
- arguments: [new CommandArgument('символ', true)],
+ arguments: [new CommandArgument('newprefix', true)],
execute: async (message: Message, args: string[]): Promise => {
const prefix: string = args[0];
if (!prefix) return;
@@ -50,7 +50,7 @@ export default function (): ICommand {
async function changePrefixTo(guild: Guild, prefix: string): Promise {
if (prefix === '/' || prefix === '@' || prefix === '#')
return i18next.t('commands:set_prefix_restrict_prefixes', { prefixes: '/ @ #' }) as string;
- if (prefix.length > 1) return i18next.t('commands:set_prefix_length_error') as string;
+ if (prefix.length > 2) return i18next.t('commands:set_prefix_length_error') as string;
await setGuildOption(guild, 'prefix', prefix);
return i18next.t('commands:set_prefix_success_change', { prefix: prefix }) as string;
}
diff --git a/src/commands/audio/audioPlayer/AudioPlayerTypes.ts b/src/commands/audio/audioPlayer/AudioPlayerTypes.ts
deleted file mode 100644
index 53e09ea..0000000
--- a/src/commands/audio/audioPlayer/AudioPlayerTypes.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export type AudioPlayerState = 'playing' | 'pause' | 'waiting' | 'loading' | 'destroying';
-export type AudioPlayerLoopMode = 'disabled' | 'song' | 'queue';
diff --git a/src/commands/audio/audioPlayer/MessagePlayerButtonsHandler.ts b/src/commands/audio/audioPlayer/MessagePlayerButtonsHandler.ts
deleted file mode 100644
index 8a8c515..0000000
--- a/src/commands/audio/audioPlayer/MessagePlayerButtonsHandler.ts
+++ /dev/null
@@ -1,198 +0,0 @@
-import {
- ActionRowBuilder,
- ButtonBuilder,
- ButtonStyle,
- InteractionCollector,
- TextChannel,
- ComponentType,
- Client,
- GuildMember,
- ButtonInteraction,
- Guild
-} from 'discord.js';
-import { checkMemberInVoiceWithBot } from '../../../utilities/checkMemberInVoiceWithBot.js';
-import { generateErrorEmbed } from '../../../utilities/generateErrorEmbed.js';
-import { loggerError } from '../../../utilities/logger.js';
-import { generateSkipMessage, generateSkipMessageFailure } from '../skip.command.js';
-import { generateMessageAudioPlayerStop } from '../stop.command.js';
-import {
- generateMessageAudioPlayerPrevious,
- generateMessageAudioPlayerPreviousFailure
-} from '../previous.command.js';
-import {
- generateMessageAudioPlayerShuffle,
- generateMessageAudioPlayerShuffleFailure
-} from '../shuffle.command.js';
-
-enum ButtonIDs {
- stopMusic = 'stopMusic',
- pauseMusic = 'pauseMusic',
- toggleLoopMode = 'toggleLoopMode',
- previousSong = 'previousSong',
- skipSong = 'skipSong',
- downloadSong = 'downloadSong',
- shuffle = 'shuffle',
- showQueue = 'showQueue'
-}
-export class MessagePlayerButtonsHandler {
- rowPrimary = new ActionRowBuilder();
- rowSecondary = new ActionRowBuilder();
- rowWithOnlyStop = new ActionRowBuilder();
- collector: InteractionCollector;
- client: Client;
- constructor(client: Client, textChannel: TextChannel) {
- this.client = client;
-
- this.rowPrimary.addComponents(
- new ButtonBuilder()
- .setCustomId(ButtonIDs.stopMusic)
- .setStyle(ButtonStyle.Danger)
- .setEmoji('<:stopwhite:1014551716043173989>'),
- new ButtonBuilder()
- .setCustomId(ButtonIDs.pauseMusic)
- .setStyle(ButtonStyle.Primary)
- .setEmoji('<:pausewhite:1014551696174764133>'),
- new ButtonBuilder()
- .setCustomId(ButtonIDs.toggleLoopMode)
- .setStyle(ButtonStyle.Primary)
- .setEmoji('<:repeatmodewhite:1014551751858331731>'),
- new ButtonBuilder()
- .setCustomId(ButtonIDs.previousSong)
- .setStyle(ButtonStyle.Primary)
- .setEmoji('<:previousbutton:1092107334542696512>'),
- new ButtonBuilder()
- .setCustomId(ButtonIDs.skipSong)
- .setStyle(ButtonStyle.Primary)
- .setEmoji('<:skipbutton:1092107438234275900>')
- );
-
- this.rowSecondary.addComponents(
- //new ButtonBuilder().setCustomId(ButtonIDs.downloadSong).setStyle(ButtonStyle.Success).setEmoji('<:downloadwhite:1014553027614617650>'),
- new ButtonBuilder()
- .setCustomId(ButtonIDs.shuffle)
- .setStyle(ButtonStyle.Primary)
- .setEmoji('<:shufflebutton:1092107651384614912>'),
- new ButtonBuilder()
- .setCustomId(ButtonIDs.showQueue)
- .setStyle(ButtonStyle.Secondary)
- .setEmoji('<:songlistwhite:1014551771705782405>')
- );
-
- this.rowWithOnlyStop.addComponents(
- new ButtonBuilder()
- .setCustomId(ButtonIDs.stopMusic)
- .setStyle(ButtonStyle.Danger)
- .setEmoji('<:stopwhite:1014551716043173989>')
- );
-
- this.collector = textChannel.createMessageComponentCollector({
- componentType: ComponentType.Button
- });
-
- this.collector.on('collect', async (ButtonInteraction: ButtonInteraction) => {
- try {
- const checkObj = await checkMemberInVoiceWithBot(ButtonInteraction.member as GuildMember);
- if (!checkObj.channelTheSame) {
- await ButtonInteraction.reply({
- embeds: [generateErrorEmbed(checkObj.errorMessage)],
- ephemeral: true
- });
- return;
- }
-
- switch (ButtonInteraction.customId) {
- case ButtonIDs.stopMusic:
- await this.client.audioPlayer.stop(ButtonInteraction.guild as Guild);
- await ButtonInteraction.reply({
- content: generateMessageAudioPlayerStop(ButtonInteraction.member as GuildMember)
- });
- break;
-
- case ButtonIDs.pauseMusic:
- await this.client.audioPlayer.pause(ButtonInteraction.guild as Guild);
- await ButtonInteraction.deferUpdate();
- break;
-
- case ButtonIDs.previousSong: {
- const song = await this.client.audioPlayer.previous(ButtonInteraction.guild as Guild);
- if (song) {
- await ButtonInteraction.reply({
- content: generateMessageAudioPlayerPrevious(
- ButtonInteraction.member as GuildMember,
- song
- )
- });
- } else {
- await ButtonInteraction.reply({
- content: generateMessageAudioPlayerPreviousFailure(),
- ephemeral: true
- });
- }
- break;
- }
-
- case ButtonIDs.skipSong: {
- const song = await this.client.audioPlayer.skip(ButtonInteraction.guild as Guild);
-
- if (song) {
- await ButtonInteraction.reply({
- content: generateSkipMessage(song, ButtonInteraction.member as GuildMember)
- });
- } else {
- await ButtonInteraction.reply({
- content: generateSkipMessageFailure(),
- ephemeral: true
- });
- }
- break;
- }
-
- case ButtonIDs.toggleLoopMode:
- await this.client.audioPlayer.changeLoopMode(ButtonInteraction.guild as Guild);
- await ButtonInteraction.deferUpdate();
- break;
-
- // case ButtonIDs.downloadSong: {
- // const song = this.client.audioPlayer.distube.getQueue(ButtonInteraction.guild as Guild)?.songs[0]
- //
- // if (!song) {
- // await ButtonInteraction.reply({embeds: [generateErrorEmbed(i18next.t("audioplayer:download_song_error"))]})
- // break
- // }
- // await ButtonInteraction.reply({ephemeral: true, embeds: [generateDownloadSongEmbed(song.streamURL ?? song.url)]})
- // break
- // }
-
- case ButtonIDs.showQueue:
- await this.client.audioPlayer.showQueue(ButtonInteraction);
- break;
-
- case ButtonIDs.shuffle: {
- if (await this.client.audioPlayer.shuffle(ButtonInteraction.guild as Guild)) {
- await ButtonInteraction.reply({
- content: generateMessageAudioPlayerShuffle(ButtonInteraction.member as GuildMember)
- });
- } else {
- await ButtonInteraction.reply(generateMessageAudioPlayerShuffleFailure());
- }
- break;
- }
- }
- } catch (e) {
- loggerError(e);
- }
- });
- }
-
- getComponents(): Array> {
- return [this.rowPrimary, this.rowSecondary];
- }
-
- getComponentsOnlyStop(): Array> {
- return [this.rowWithOnlyStop];
- }
-
- destroy() {
- this.collector.stop();
- }
-}
diff --git a/src/commands/audio/audiodebug.command.ts b/src/commands/audio/audiodebug.command.ts
index 178938a..fcaa8be 100644
--- a/src/commands/audio/audiodebug.command.ts
+++ b/src/commands/audio/audiodebug.command.ts
@@ -1,6 +1,7 @@
import { ICommand } from '../../CommandTypes.js';
import { PermissionsBitField } from 'discord.js';
import { GroupAudio } from './AudioTypes.js';
+import { isOverpoweredUser } from '../../utilities/isOverpoweredUser.js';
export default function (): ICommand {
return {
@@ -8,6 +9,8 @@ export default function (): ICommand {
name: 'audiodebug',
description: 'Debug info about audioplayers',
execute: async (message) => {
+ if (!isOverpoweredUser(message.author.id)) return;
+
await message.reply({
content: message.client.audioPlayer.playersManager.debug(),
allowedMentions: { users: [] }
diff --git a/src/commands/audio/download.command.ts b/src/commands/audio/download.command.ts
index 79da861..d6720e8 100644
--- a/src/commands/audio/download.command.ts
+++ b/src/commands/audio/download.command.ts
@@ -6,7 +6,7 @@ import {
deleteMP3file,
DownloadSongErrorGetLocale,
getSongFileAttachment
-} from './util/downloadSong.js';
+} from '../../audioplayer/util/downloadSong.js';
import i18next from 'i18next';
import { generateErrorEmbed } from '../../utilities/generateErrorEmbed.js';
import { ReadStream } from 'fs';
diff --git a/src/commands/audio/jump.command.ts b/src/commands/audio/jump.command.ts
index d3db5d9..d4e341b 100644
--- a/src/commands/audio/jump.command.ts
+++ b/src/commands/audio/jump.command.ts
@@ -1,13 +1,14 @@
import { CommandArgument, ICommand } from '../../CommandTypes.js';
-import { GuildMember, PermissionsBitField, SlashCommandBuilder } from 'discord.js';
+import { EmbedBuilder, GuildMember, PermissionsBitField, SlashCommandBuilder } from 'discord.js';
import { GroupAudio } from './AudioTypes.js';
import {
AudioCommandWrapperInteraction,
AudioCommandWrapperText
-} from './util/AudioCommandWrappers.js';
+} from '../../audioplayer/util/AudioCommandWrappers.js';
import { generateErrorEmbed } from '../../utilities/generateErrorEmbed.js';
import { Song } from 'distube';
import i18next from 'i18next';
+import { generateSimpleEmbed } from '../../utilities/generateSimpleEmbed.js';
export default function (): ICommand {
return {
@@ -32,9 +33,9 @@ export default function (): ICommand {
await AudioCommandWrapperText(message, async () => {
const song = await message.client.audioPlayer.jump(message.guild!, pos!);
if (song) {
- await message.reply(generateMessageAudioPlayerJump(message.member!, song));
+ await message.reply({ embeds: [generateEmbedAudioPlayerJump(message.member!, song)] });
} else {
- await message.reply(generateMessageAudioPlayerJumpFailure());
+ await message.reply({ embeds: [generateEmbedAudioPlayerJumpFailure()] });
}
});
}
@@ -59,11 +60,11 @@ export default function (): ICommand {
await AudioCommandWrapperInteraction(interaction, async () => {
const song = await interaction.client.audioPlayer.jump(interaction.guild!, pos!);
if (song) {
- await interaction.reply(
- generateMessageAudioPlayerJump(interaction.member as GuildMember, song)
- );
+ await interaction.reply({
+ embeds: [generateEmbedAudioPlayerJump(interaction.member as GuildMember, song)]
+ });
} else {
- await interaction.reply(generateMessageAudioPlayerJumpFailure());
+ await interaction.reply({ embeds: [generateEmbedAudioPlayerJumpFailure()] });
}
});
}
@@ -78,10 +79,12 @@ export default function (): ICommand {
};
}
-function generateMessageAudioPlayerJump(member: GuildMember, song: Song) {
- return `:fast_forward: ${member} ${i18next.t('commands:jump_success')} ${song.name} :fast_forward:`;
+function generateEmbedAudioPlayerJump(member: GuildMember, song: Song): EmbedBuilder {
+ return generateSimpleEmbed(
+ `:fast_forward: ${member} ${i18next.t('commands:jump_success')} ${song.name} :fast_forward:`
+ );
}
-function generateMessageAudioPlayerJumpFailure() {
- return i18next.t('commands:jump_failure');
+function generateEmbedAudioPlayerJumpFailure(): EmbedBuilder {
+ return generateSimpleEmbed(i18next.t('commands:jump_failure'));
}
diff --git a/src/commands/audio/play.command.ts b/src/commands/audio/play.command.ts
index a143911..9629c7e 100644
--- a/src/commands/audio/play.command.ts
+++ b/src/commands/audio/play.command.ts
@@ -1,18 +1,24 @@
import { CommandArgument, ICommand } from '../../CommandTypes.js';
import {
+ ApplicationCommandOptionChoiceData,
AutocompleteInteraction,
+ Client,
+ Guild,
GuildMember,
Message,
PermissionsBitField,
SlashCommandBuilder,
TextChannel,
+ VoiceBasedChannel,
VoiceChannel
} from 'discord.js';
import { GroupAudio } from './AudioTypes.js';
-import { isValidURL } from '../../utilities/isValidURL.js';
-import { SearchResultType, SearchResultVideo } from 'distube';
import { truncateString } from '../../utilities/truncateString.js';
import i18next from 'i18next';
+import { SearchResultType } from '@distube/youtube';
+import ytsr from '@distube/ytsr';
+import { queueSongsLimit } from '../../audioplayer/AudioPlayerCore.js';
+import { generateWarningEmbed } from '../../utilities/generateWarningEmbed.js';
export const services = 'Youtube, Spotify, Soundcloud, Yandex Music, HTTP-stream';
export default function (): ICommand {
@@ -27,13 +33,28 @@ export default function (): ICommand {
const songQuery = args.join(' ');
const member = message.member as GuildMember;
+ const channel = message.channel as TextChannel;
+
+ if (queueSongsIsFull(message.client, message.guild as Guild)) {
+ await message.reply({
+ embeds: [
+ generateWarningEmbed(
+ i18next.t('commands:play_error_songs_limit', {
+ queueLimit: queueSongsLimit
+ }) as string
+ )
+ ]
+ });
+ return;
+ }
+
await message.client.audioPlayer.play(
- member.voice.channel as VoiceChannel,
- message.channel as TextChannel,
+ member.voice.channel as VoiceBasedChannel,
+ channel,
songQuery,
{
- member: message.member as GuildMember,
- textChannel: message.channel as TextChannel
+ member: member,
+ textChannel: channel
}
);
@@ -55,12 +76,27 @@ export default function (): ICommand {
execute: async (interaction) => {
const songQuery = interaction.options.getString('request');
+ if (queueSongsIsFull(interaction.client, interaction.guild as Guild)) {
+ await interaction.reply({
+ embeds: [
+ generateWarningEmbed(
+ i18next.t('commands:play_error_songs_limit', {
+ queueLimit: queueSongsLimit
+ }) as string
+ )
+ ],
+ ephemeral: true
+ });
+ return;
+ }
+
await interaction.reply({
content: i18next.t('general:thinking') as string
});
await interaction.deleteReply();
const member = interaction.member as GuildMember;
+
if (songQuery) {
await interaction.client.audioPlayer.play(
member.voice.channel as VoiceChannel,
@@ -90,29 +126,39 @@ export default function (): ICommand {
};
}
+const liveText = i18next.t('commands:play_stream');
+
export async function songSearchAutocomplete(interaction: AutocompleteInteraction) {
const focusedValue = interaction.options.getFocused(false);
- if (focusedValue && !isValidURL(focusedValue)) {
- const choices = await interaction.client.audioPlayer.distube.search(focusedValue, {
+ if (focusedValue) {
+ const choices = await ytsr(focusedValue, {
+ safeSearch: true,
limit: 10,
- type: SearchResultType.VIDEO,
- safeSearch: false
+ type: SearchResultType.VIDEO
});
- const finalResult = choices.map((choice: SearchResultVideo) => {
- const duration = choice.isLive ? i18next.t('commands:play_stream') : choice.formattedDuration;
- let choiceString = `${duration} | ${truncateString(choice.uploader.name ?? '', 20)} | `;
- choiceString += truncateString(choice.name, 100 - choiceString.length);
+ const finalResult = choices.items.map((video: ytsr.Video) => {
+ const duration = video.isLive ? liveText : video.duration;
+ let choiceString = `${duration} | ${truncateString(video.author?.name ?? ' ', 20)} | `;
+ choiceString += truncateString(video.name, 100 - choiceString.length);
return {
name: choiceString,
- value: choice.url
+ value: video.url
};
});
- await interaction.respond(finalResult);
+ await interaction.respond(finalResult as Array);
return;
}
await interaction.respond([]);
}
+
+function queueSongsIsFull(client: Client, guild: Guild): boolean {
+ const queue = client.audioPlayer.distube.getQueue(guild);
+
+ if (!queue) return false;
+
+ return queue.songs.length >= queueSongsLimit;
+}
diff --git a/src/commands/audio/playfile.command.ts b/src/commands/audio/playfile.command.ts
index d15bf51..5327293 100644
--- a/src/commands/audio/playfile.command.ts
+++ b/src/commands/audio/playfile.command.ts
@@ -8,7 +8,7 @@ import {
VoiceChannel
} from 'discord.js';
import { GroupAudio } from './AudioTypes.js';
-import { isAudioFile } from './util/isAudioFile.js';
+import { isAudioFile } from '../../audioplayer/util/isAudioFile.js';
import { generateErrorEmbed } from '../../utilities/generateErrorEmbed.js';
import i18next from 'i18next';
diff --git a/src/commands/audio/playing.command.ts b/src/commands/audio/playing.command.ts
index 49d3441..db06604 100644
--- a/src/commands/audio/playing.command.ts
+++ b/src/commands/audio/playing.command.ts
@@ -4,7 +4,7 @@ import { GroupAudio } from './AudioTypes.js';
import {
AudioCommandWrapperInteraction,
AudioCommandWrapperText
-} from './util/AudioCommandWrappers.js';
+} from '../../audioplayer/util/AudioCommandWrappers.js';
import { splitBar } from '../../utilities/splitBar.js';
import { Queue } from 'distube';
import i18next from 'i18next';
@@ -50,7 +50,7 @@ export function generatePlayingMessage(guild: Guild): EmbedBuilder {
if (queue) {
const song = queue.songs[0];
embed.setTitle(song.name!);
- embed.setURL(song.url);
+ embed.setURL(song.url!);
embed.setAuthor({ name: `${i18next.t('commands:playing_now_playing')}:` });
embed.addFields({
name: i18next.t('commands:playing_song_length'),
diff --git a/src/commands/audio/previous.command.ts b/src/commands/audio/previous.command.ts
index 354624b..0254766 100644
--- a/src/commands/audio/previous.command.ts
+++ b/src/commands/audio/previous.command.ts
@@ -1,12 +1,13 @@
import { ICommand } from '../../CommandTypes.js';
-import { GuildMember, PermissionsBitField, SlashCommandBuilder } from 'discord.js';
+import { EmbedBuilder, GuildMember, PermissionsBitField, SlashCommandBuilder } from 'discord.js';
import { GroupAudio } from './AudioTypes.js';
import {
AudioCommandWrapperInteraction,
AudioCommandWrapperText
-} from './util/AudioCommandWrappers.js';
+} from '../../audioplayer/util/AudioCommandWrappers.js';
import { Song } from 'distube';
import i18next from 'i18next';
+import { generateSimpleEmbed } from '../../utilities/generateSimpleEmbed.js';
export default function (): ICommand {
return {
@@ -18,10 +19,10 @@ export default function (): ICommand {
const song = await message.client.audioPlayer.previous(message.guild!);
if (song) {
await message.reply({
- content: generateMessageAudioPlayerPrevious(message.member as GuildMember, song)
+ embeds: [generateEmbedAudioPlayerPrevious(message.member as GuildMember, song)]
});
} else {
- await message.reply({ content: generateMessageAudioPlayerPreviousFailure() });
+ await message.reply({ embeds: [generateEmbedAudioPlayerPreviousFailure()] });
}
});
}
@@ -35,11 +36,11 @@ export default function (): ICommand {
const song = await interaction.client.audioPlayer.previous(interaction.guild!);
if (song) {
await interaction.reply({
- content: generateMessageAudioPlayerPrevious(interaction.member as GuildMember, song)
+ embeds: [generateEmbedAudioPlayerPrevious(interaction.member as GuildMember, song)]
});
} else {
await interaction.reply({
- content: generateMessageAudioPlayerPreviousFailure(),
+ embeds: [generateEmbedAudioPlayerPreviousFailure()],
ephemeral: true
});
}
@@ -56,10 +57,12 @@ export default function (): ICommand {
};
}
-export function generateMessageAudioPlayerPrevious(member: GuildMember, song: Song) {
- return `:rewind: ${member} ${i18next.t('previous_success')} ${song.name} :rewind:`;
+export function generateEmbedAudioPlayerPrevious(member: GuildMember, song: Song): EmbedBuilder {
+ return generateSimpleEmbed(
+ `:rewind: ${member} ${i18next.t('commands:previous_success')} ${song.name} - ${song.uploader.name} :rewind:`
+ );
}
-export function generateMessageAudioPlayerPreviousFailure() {
- return i18next.t('previous_error_song_not_exists');
+export function generateEmbedAudioPlayerPreviousFailure() {
+ return generateSimpleEmbed(i18next.t('commands:previous_error_song_not_exists'));
}
diff --git a/src/commands/audio/rewind.command.ts b/src/commands/audio/rewind.command.ts
index f0f76e5..3641e4a 100644
--- a/src/commands/audio/rewind.command.ts
+++ b/src/commands/audio/rewind.command.ts
@@ -1,12 +1,13 @@
import { CommandArgument, ICommand } from '../../CommandTypes.js';
-import { GuildMember, PermissionsBitField, SlashCommandBuilder } from 'discord.js';
+import { EmbedBuilder, GuildMember, PermissionsBitField, SlashCommandBuilder } from 'discord.js';
import { GroupAudio } from './AudioTypes.js';
import {
AudioCommandWrapperInteraction,
AudioCommandWrapperText
-} from './util/AudioCommandWrappers.js';
+} from '../../audioplayer/util/AudioCommandWrappers.js';
import { formatSecondsToTime } from '../../utilities/formatSecondsToTime.js';
import i18next from 'i18next';
+import { generateSimpleEmbed } from '../../utilities/generateSimpleEmbed.js';
export default function (): ICommand {
return {
@@ -21,11 +22,11 @@ export default function (): ICommand {
if (time) {
if (await message.client.audioPlayer.rewind(message.guild!, time)) {
await message.reply({
- content: generateMessageAudioPlayerRewind(message.member!, time)
+ embeds: [generateEmbedAudioPlayerRewind(message.member!, time)]
});
}
} else {
- await message.reply({ content: generateMessageAudioPlayerRewindFailure() });
+ await message.reply({ embeds: [generateEmbedAudioPlayerRewindFailure()] });
}
});
}
@@ -50,12 +51,12 @@ export default function (): ICommand {
if (time) {
if (await interaction.client.audioPlayer.rewind(interaction.guild!, time)) {
await interaction.reply({
- content: generateMessageAudioPlayerRewind(interaction.member as GuildMember, time)
+ embeds: [generateEmbedAudioPlayerRewind(interaction.member as GuildMember, time)]
});
}
} else {
await interaction.reply({
- content: generateMessageAudioPlayerRewindFailure(),
+ embeds: [generateEmbedAudioPlayerRewindFailure()],
ephemeral: true
});
}
@@ -93,10 +94,12 @@ function hmsToSeconds(str: string): number | undefined {
return s;
}
-export function generateMessageAudioPlayerRewind(member: GuildMember, time: number) {
- return `${member} ${i18next.t('commands:rewind_success')} ${formatSecondsToTime(time)}`;
+export function generateEmbedAudioPlayerRewind(member: GuildMember, time: number): EmbedBuilder {
+ return generateSimpleEmbed(
+ `${member} ${i18next.t('commands:rewind_success')} ${formatSecondsToTime(time)}`
+ );
}
-export function generateMessageAudioPlayerRewindFailure() {
- return i18next.t('commands:rewind_failure');
+export function generateEmbedAudioPlayerRewindFailure(): EmbedBuilder {
+ return generateSimpleEmbed(i18next.t('commands:rewind_failure'));
}
diff --git a/src/commands/audio/shuffle.command.ts b/src/commands/audio/shuffle.command.ts
index f70f3da..2728029 100644
--- a/src/commands/audio/shuffle.command.ts
+++ b/src/commands/audio/shuffle.command.ts
@@ -1,11 +1,18 @@
import { ICommand } from '../../CommandTypes.js';
-import { GuildMember, Message, PermissionsBitField, SlashCommandBuilder } from 'discord.js';
+import {
+ EmbedBuilder,
+ GuildMember,
+ Message,
+ PermissionsBitField,
+ SlashCommandBuilder
+} from 'discord.js';
import { GroupAudio } from './AudioTypes.js';
import {
AudioCommandWrapperInteraction,
AudioCommandWrapperText
-} from './util/AudioCommandWrappers.js';
+} from '../../audioplayer/util/AudioCommandWrappers.js';
import i18next from 'i18next';
+import { generateSimpleEmbed } from '../../utilities/generateSimpleEmbed.js';
export default function (): ICommand {
return {
text_data: {
@@ -14,9 +21,9 @@ export default function (): ICommand {
execute: async (message: Message): Promise => {
await AudioCommandWrapperText(message, async (): Promise => {
if (await message.client.audioPlayer.shuffle(message.guild!)) {
- await message.reply({ content: generateMessageAudioPlayerShuffle(message.member!) });
+ await message.reply({ embeds: [generateEmbedAudioPlayerShuffle(message.member!)] });
} else {
- await message.reply(generateMessageAudioPlayerShuffleFailure());
+ await message.reply({ embeds: [generateEmbedAudioPlayerShuffleFailure()] });
}
});
}
@@ -29,10 +36,10 @@ export default function (): ICommand {
await AudioCommandWrapperInteraction(interaction, async (): Promise => {
if (await interaction.client.audioPlayer.shuffle(interaction.guild!)) {
await interaction.reply({
- content: generateMessageAudioPlayerShuffle(interaction.member as GuildMember)
+ embeds: [generateEmbedAudioPlayerShuffle(interaction.member as GuildMember)]
});
} else {
- await interaction.reply(generateMessageAudioPlayerShuffleFailure());
+ await interaction.reply({ embeds: [generateEmbedAudioPlayerShuffleFailure()] });
}
});
}
@@ -47,10 +54,10 @@ export default function (): ICommand {
};
}
-export function generateMessageAudioPlayerShuffle(member: GuildMember): string {
- return `${member} ${i18next.t('commands:shuffle_success')}`;
+export function generateEmbedAudioPlayerShuffle(member: GuildMember): EmbedBuilder {
+ return generateSimpleEmbed(`${member} ${i18next.t('commands:shuffle_success')}`);
}
-export function generateMessageAudioPlayerShuffleFailure(): string {
- return i18next.t('commands:shuffle_failure');
+export function generateEmbedAudioPlayerShuffleFailure(): EmbedBuilder {
+ return generateSimpleEmbed(i18next.t('commands:shuffle_failure'));
}
diff --git a/src/commands/audio/skip.command.ts b/src/commands/audio/skip.command.ts
index e8181f6..b43b856 100644
--- a/src/commands/audio/skip.command.ts
+++ b/src/commands/audio/skip.command.ts
@@ -1,12 +1,19 @@
import { ICommand } from '../../CommandTypes.js';
-import { GuildMember, Message, PermissionsBitField, SlashCommandBuilder } from 'discord.js';
+import {
+ EmbedBuilder,
+ GuildMember,
+ Message,
+ PermissionsBitField,
+ SlashCommandBuilder
+} from 'discord.js';
import { GroupAudio } from './AudioTypes.js';
import {
AudioCommandWrapperInteraction,
AudioCommandWrapperText
-} from './util/AudioCommandWrappers.js';
+} from '../../audioplayer/util/AudioCommandWrappers.js';
import { Song } from 'distube';
import i18next from 'i18next';
+import { generateSimpleEmbed } from '../../utilities/generateSimpleEmbed.js';
export default function (): ICommand {
return {
@@ -17,9 +24,9 @@ export default function (): ICommand {
await AudioCommandWrapperText(message, async () => {
const song = await message.client.audioPlayer.skip(message.guild!);
if (song) {
- await message.reply({ content: generateSkipMessage(song, message.member!) });
+ await message.reply({ embeds: [generateSkipEmbed(song, message.member!)] });
} else {
- await message.reply({ content: generateSkipMessageFailure() });
+ await message.reply({ embeds: [generateSkipEmbedFailure()] });
}
});
}
@@ -33,10 +40,10 @@ export default function (): ICommand {
const song = await interaction.client.audioPlayer.skip(interaction.guild!);
if (song) {
await interaction.reply({
- content: generateSkipMessage(song, interaction.member as GuildMember)
+ embeds: [generateSkipEmbed(song, interaction.member as GuildMember)]
});
} else {
- await interaction.reply({ content: generateSkipMessageFailure(), ephemeral: true });
+ await interaction.reply({ embeds: [generateSkipEmbedFailure()], ephemeral: true });
}
});
}
@@ -51,10 +58,12 @@ export default function (): ICommand {
};
}
-export function generateSkipMessage(song: Song, member: GuildMember): string {
- return `:fast_forward: ${member} ${i18next.t('commands:skip_success')} ${song.name} - ${song.uploader.name} :fast_forward:`;
+export function generateSkipEmbed(song: Song, member: GuildMember): EmbedBuilder {
+ return generateSimpleEmbed(
+ `:fast_forward: ${member} ${i18next.t('commands:skip_success')} ${song.name} - ${song.uploader.name} :fast_forward:`
+ );
}
-export function generateSkipMessageFailure(): string {
- return i18next.t('commands:skip_failure');
+export function generateSkipEmbedFailure(): EmbedBuilder {
+ return generateSimpleEmbed(i18next.t('commands:skip_failure'));
}
diff --git a/src/commands/audio/stop.command.ts b/src/commands/audio/stop.command.ts
index 6ad3a12..1695468 100644
--- a/src/commands/audio/stop.command.ts
+++ b/src/commands/audio/stop.command.ts
@@ -1,11 +1,18 @@
import { ICommand } from '../../CommandTypes.js';
-import { GuildMember, Message, PermissionsBitField, SlashCommandBuilder } from 'discord.js';
+import {
+ EmbedBuilder,
+ GuildMember,
+ Message,
+ PermissionsBitField,
+ SlashCommandBuilder
+} from 'discord.js';
import { GroupAudio } from './AudioTypes.js';
import {
AudioCommandWrapperInteraction,
AudioCommandWrapperText
-} from './util/AudioCommandWrappers.js';
+} from '../../audioplayer/util/AudioCommandWrappers.js';
import i18next from 'i18next';
+import { generateSimpleEmbed } from '../../utilities/generateSimpleEmbed.js';
export default function (): ICommand {
return {
@@ -15,7 +22,7 @@ export default function (): ICommand {
execute: async (message: Message) => {
await AudioCommandWrapperText(message, async () => {
await message.client.audioPlayer.stop(message.guild!);
- await message.reply({ content: generateMessageAudioPlayerStop(message.member!) });
+ await message.reply({ embeds: [generateEmbedAudioPlayerStop(message.member!)] });
});
}
},
@@ -27,7 +34,7 @@ export default function (): ICommand {
await AudioCommandWrapperInteraction(interaction, async () => {
await interaction.client.audioPlayer.stop(interaction.guild!);
await interaction.reply({
- content: generateMessageAudioPlayerStop(interaction.member as GuildMember)
+ embeds: [generateEmbedAudioPlayerStop(interaction.member as GuildMember)]
});
});
}
@@ -42,6 +49,6 @@ export default function (): ICommand {
};
}
-export function generateMessageAudioPlayerStop(member: GuildMember): string {
- return `${member} ${i18next.t('commands:stop_success')}`;
+export function generateEmbedAudioPlayerStop(member: GuildMember): EmbedBuilder {
+ return generateSimpleEmbed(`${member} ${i18next.t('commands:stop_success')}`);
}
diff --git a/src/commands/info/report.command.ts b/src/commands/info/report.command.ts
index 858e725..ee33878 100644
--- a/src/commands/info/report.command.ts
+++ b/src/commands/info/report.command.ts
@@ -1,17 +1,13 @@
import { ICommand } from '../../CommandTypes.js';
import {
- ActionRowBuilder,
ChatInputCommandInteraction,
Message,
- ModalActionRowComponentBuilder,
- ModalBuilder,
PermissionsBitField,
- SlashCommandBuilder,
- TextInputBuilder,
- TextInputStyle
+ SlashCommandBuilder
} from 'discord.js';
import { GroupInfo } from './InfoTypes.js';
import i18next from 'i18next';
+import { generateSimpleEmbed } from '../../utilities/generateSimpleEmbed.js';
export default function (): ICommand {
return {
@@ -19,7 +15,7 @@ export default function (): ICommand {
name: 'report',
description: i18next.t('commands:report_desc'),
execute: async (message: Message) => {
- await message.reply(i18next.t('commands:report_text_error') as string);
+ await message.reply({ embeds: [generateReportEmbed()] });
}
},
slash_data: {
@@ -27,7 +23,7 @@ export default function (): ICommand {
.setName('report')
.setDescription(i18next.t('commands:report_desc')),
execute: async (interaction: ChatInputCommandInteraction) => {
- await interaction.showModal(generateModalWindow());
+ await interaction.reply({ embeds: [generateReportEmbed()], ephemeral: true });
}
},
group: GroupInfo,
@@ -35,24 +31,12 @@ export default function (): ICommand {
};
}
-function generateModalWindow() {
- const modal = new ModalBuilder()
- .setCustomId('reportModal')
- .setTitle(i18next.t('commands:report_modal_title'));
-
- const reportInput = new TextInputBuilder()
- .setCustomId('reportInput')
- .setLabel(i18next.t('commands:report_modal_text_label'))
- .setStyle(TextInputStyle.Paragraph)
- .setMinLength(20)
- .setPlaceholder(i18next.t('commands:report_modal_text_placeholder'))
- .setRequired(true);
-
- const firstActionRow = new ActionRowBuilder().addComponents(
- reportInput
+function generateReportEmbed() {
+ return generateSimpleEmbed(
+ i18next.t('commands:report_message', {
+ issueLink: 'https://github.com/AlexInCube/AlCoTest/issues/new/choose',
+ discussionLink: 'https://github.com/AlexInCube/AlCoTest/discussions/new?category=q-a',
+ interpolation: { escapeValue: false }
+ })
);
-
- modal.addComponents(firstActionRow);
-
- return modal;
}
diff --git a/src/commands/info/status.command.ts b/src/commands/info/status.command.ts
index e7ab0b5..a79afa1 100644
--- a/src/commands/info/status.command.ts
+++ b/src/commands/info/status.command.ts
@@ -8,8 +8,6 @@ import {
SlashCommandBuilder
} from 'discord.js';
import { GroupInfo } from './InfoTypes.js';
-// eslint-disable-next-line @typescript-eslint/ban-ts-comment
-// @ts-ignore
import node_os_pkg from 'node-os-utils';
import i18next from 'i18next';
diff --git a/src/events/interactionCreate.event.ts b/src/events/interactionCreate.event.ts
index 87cccd3..bc73dcb 100644
--- a/src/events/interactionCreate.event.ts
+++ b/src/events/interactionCreate.event.ts
@@ -1,7 +1,6 @@
import { BotEvent } from '../Types.js';
import { slashCommandHandler } from './interactionHandlers/slashCommandHandler.js';
import { autocompleteHandler } from './interactionHandlers/autocompleteHandler.js';
-import { modalsHandler } from './interactionHandlers/modalsHandler.js';
import { Client, Events, Interaction } from 'discord.js';
const event: BotEvent = {
@@ -9,7 +8,6 @@ const event: BotEvent = {
execute: async (client: Client, interaction: Interaction) => {
await slashCommandHandler(interaction);
await autocompleteHandler(interaction);
- await modalsHandler(interaction);
}
};
diff --git a/src/events/interactionHandlers/modalsHandler.ts b/src/events/interactionHandlers/modalsHandler.ts
deleted file mode 100644
index cb4a041..0000000
--- a/src/events/interactionHandlers/modalsHandler.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { submitReport } from '../../handlers/MongoSchemas/SchemaReport.js';
-import { Interaction } from 'discord.js';
-import i18next from 'i18next';
-import { ENV } from '../../EnvironmentVariables.js';
-
-export async function modalsHandler(interaction: Interaction) {
- if (!interaction.isModalSubmit()) return;
- if (interaction.customId === 'reportModal') {
- await interaction.reply({
- content: i18next.t('commands:report_modal_feedback') as string,
- ephemeral: true
- });
-
- const reportInput = interaction.fields.getTextInputValue('reportInput');
- const overpoweredHuman = interaction.client.users.cache.get(ENV.BOT_DISCORD_OVERPOWERED_ID);
- if (overpoweredHuman) {
- await overpoweredHuman.send(
- `New report from ${interaction.user.username} with ID: ${interaction.user.id}\n\n${reportInput}`
- );
- }
- await submitReport(interaction.user.id, reportInput);
- }
-}
diff --git a/src/events/interactionHandlers/slashCommandHandler.ts b/src/events/interactionHandlers/slashCommandHandler.ts
index 00b18a0..f7da309 100644
--- a/src/events/interactionHandlers/slashCommandHandler.ts
+++ b/src/events/interactionHandlers/slashCommandHandler.ts
@@ -72,9 +72,6 @@ export async function slashCommandHandler(interaction: Interaction) {
await command.slash_data.execute(interaction);
} catch (e) {
if (ENV.BOT_VERBOSE_LOGGING)
- loggerError(
- `${i18next.t('commandshandlers:slash_command_error')}: ${e}`,
- loggerPrefixCommandHandler
- );
+ loggerError(`Error when executing slash command: ${e}`, loggerPrefixCommandHandler);
}
}
diff --git a/src/events/messageCreate.event.ts b/src/events/messageCreate.event.ts
index 4360b0f..91b7490 100644
--- a/src/events/messageCreate.event.ts
+++ b/src/events/messageCreate.event.ts
@@ -1,7 +1,7 @@
import { BotEvent } from '../Types.js';
import { Client, Events, Message, TextChannel } from 'discord.js';
import { textCommandsHandler } from './messageHandlers/textCommandsHandler.js';
-import { playerMessageHandler } from './messageHandlers/playerMessageHandler.js';
+import { AudioPlayerEventMessageCreate } from '../audioplayer/eventsHandlers/AudioPlayerEventMessageCreate.js';
const event: BotEvent = {
name: Events.MessageCreate,
@@ -9,7 +9,7 @@ const event: BotEvent = {
await textCommandsHandler(client, message);
if (!message.guild) return;
- await playerMessageHandler(message.channel as TextChannel);
+ await AudioPlayerEventMessageCreate(message.channel as TextChannel);
}
};
diff --git a/src/events/messageDeleted.event.ts b/src/events/messageDeleted.event.ts
index 7fc9bf3..601f433 100644
--- a/src/events/messageDeleted.event.ts
+++ b/src/events/messageDeleted.event.ts
@@ -1,24 +1,13 @@
import { BotEvent } from '../Types.js';
-import { Client, Events, Message, TextChannel } from 'discord.js';
-import { ENV } from '../EnvironmentVariables.js';
-import { loggerError } from '../utilities/logger.js';
+import { Client, Events, Message } from 'discord.js';
+import {
+ AudioPlayerEventMessageDeleted
+} from '../audioplayer/eventsHandlers/AudioPlayerEventMessageDeleted.js';
const event: BotEvent = {
name: Events.MessageDelete,
execute: async (client: Client, message: Message) => {
- if (!message.guild) return;
-
- const textChannel = message.channel as TextChannel;
- const player = client.audioPlayer.playersManager.get(textChannel.guild.id);
- if (player) {
- if (player.textChannel.id !== textChannel.id) return;
- if (player.lastDeletedMessage?.id === message.id) return; // If player deleted message them self, then don`t "trigger" event
- try {
- await player.recreatePlayer();
- } catch (e) {
- if (ENV.BOT_VERBOSE_LOGGING) loggerError(e);
- }
- }
+ await AudioPlayerEventMessageDeleted(client, message);
}
};
diff --git a/src/events/messageHandlers/textCommandsHandler.ts b/src/events/messageHandlers/textCommandsHandler.ts
index ffa3f42..3f86b73 100644
--- a/src/events/messageHandlers/textCommandsHandler.ts
+++ b/src/events/messageHandlers/textCommandsHandler.ts
@@ -123,9 +123,6 @@ export async function textCommandsHandler(client: Client, message: Message) {
await command.text_data.execute(message, args);
} catch (e) {
if (ENV.BOT_VERBOSE_LOGGING)
- loggerError(
- `${i18next.t('commandshandlers:text_command_error')}: ${e}`,
- loggerPrefixCommandHandler
- );
+ loggerError(`commandshandlers:text_command_error: ${e}`, loggerPrefixCommandHandler);
}
}
diff --git a/src/events/onChannelDelete.event.ts b/src/events/onChannelDelete.event.ts
index 4787de5..8767974 100644
--- a/src/events/onChannelDelete.event.ts
+++ b/src/events/onChannelDelete.event.ts
@@ -1,13 +1,13 @@
import { BotEvent } from '../Types.js';
import { Client, Events, TextChannel } from 'discord.js';
+import {
+ AudioPlayerEventChannelDelete
+} from '../audioplayer/eventsHandlers/AudioPlayerEventChannelDelete.js';
const event: BotEvent = {
name: Events.ChannelDelete,
execute: async (client: Client, channel: TextChannel) => {
- const player = client.audioPlayer.playersManager.get(channel.guild.id);
- if (player?.textChannel.id === channel.id) {
- await client.audioPlayer.stop(channel.guild);
- }
+ await AudioPlayerEventChannelDelete(client, channel)
}
};
diff --git a/src/events/onReady.event.ts b/src/events/onReady.event.ts
index 2b5e5ac..cbb9c29 100644
--- a/src/events/onReady.event.ts
+++ b/src/events/onReady.event.ts
@@ -8,9 +8,7 @@ const event: BotEvent = {
execute: (client) => {
if (!client.user) return;
- loggerSend(
- `Bot ${client.user.username} is running, on version ${process.env.npm_package_version}`
- );
+ loggerSend(`Bot ${client.user.username} is successfully started!`);
client.user.setActivity('/help');
}
};
diff --git a/src/events/voiceChannelUpdate.event.ts b/src/events/voiceChannelUpdate.event.ts
new file mode 100644
index 0000000..299bff5
--- /dev/null
+++ b/src/events/voiceChannelUpdate.event.ts
@@ -0,0 +1,15 @@
+import { BotEvent } from '../Types';
+import { Client, Events, VoiceState } from 'discord.js';
+import {
+ AudioPlayerEventVoiceChannelUpdate
+} from '../audioplayer/eventsHandlers/AudioPlayerEventVoiceChannelUpdate.js';
+
+export const event: BotEvent = {
+ name: Events.VoiceStateUpdate,
+ execute: async (client: Client, oldState: VoiceState, newState: VoiceState) => {
+ //ENV.NODE_ENV === 'production' ? 120 : 5
+ await AudioPlayerEventVoiceChannelUpdate(client, oldState, newState)
+ }
+};
+
+export default event;
diff --git a/src/handlers/Command.handler.ts b/src/handlers/Command.handler.ts
index f78efd1..19e160c 100644
--- a/src/handlers/Command.handler.ts
+++ b/src/handlers/Command.handler.ts
@@ -19,7 +19,7 @@ const handler = async (client: Client) => {
const commandsDir = path.join(getDirName(import.meta.url), '../commands');
const scanResult: string[] = getAllCommandFilesInDir(commandsDir); // Recursion for scan "commands" folder for files end with ".command.js"
- const buildersArray: SlashBuilder[] = []; // Prepare builders array for send into Discord REST API
+ const buildersArray: SlashBuilder[] = []; // Prepare a builder array for sending into Discord REST API
for (const filePath of scanResult) {
const importPath = `file:///${filePath}`;
diff --git a/src/locales/en/audioplayer.json b/src/locales/en/audioplayer.json
index 46a4a0d..771800f 100644
--- a/src/locales/en/audioplayer.json
+++ b/src/locales/en/audioplayer.json
@@ -1,7 +1,7 @@
{
"audio_commands_wrapper_song_processing": "Song is processing, please wait",
"audio_commands_wrapper_player_not_exist": "Player is not exists",
- "play_error": "With this link is something wrong",
+ "play_error": "With this song is something wrong",
"download_song_error": "Something went wrong, when retrieving link to audio",
"show_queue_title": "Now playing",
"show_queue_songs_in_queue": "Songs in queue",
@@ -12,6 +12,7 @@
"event_add_song_author": "Author",
"event_add_list": "Playlist added",
"event_add_list_songs_count": "Songs count",
+ "event_add_list_limit": "Some songs are added, but its trimmed to {{queueLimit}}",
"player_embed_unknown": "Unknown",
"player_embed_requester": "Requester",
"player_embed_author": "Author",
diff --git a/src/locales/en/commands.json b/src/locales/en/commands.json
index dba8c7d..763f7f0 100644
--- a/src/locales/en/commands.json
+++ b/src/locales/en/commands.json
@@ -2,7 +2,7 @@
"set_prefix_desc": "Change prefix for TEXT commands and only for current server",
"set_prefix_arg_newprefix_desc": "Don't forget to inform the other server members about the changed prefix",
"set_prefix_restrict_prefixes": "You can't specify characters {{prefixes}} as a prefix",
- "set_prefix_length_error": "The prefix cannot be longer than one character",
+ "set_prefix_length_error": "The prefix cannot be longer than two characters",
"set_prefix_success_change": "Prefix successful changed on this server to {{prefix}}",
"help_desc": "Commands list",
"help_arg_command": "command name",
@@ -17,6 +17,7 @@
"play_desc": "Playing requested song",
"play_arg_link": "Links from {{services}} or any text",
"play_stream": "Live",
+ "play_error_songs_limit": "You cant add new songs, because queue hit the limit in {{queueLimit}} songs",
"download_desc": "Download song from the link",
"download_arg_request": "Links from {{services}}",
"download_please_wait": "Please wait, it can take a long time",
@@ -55,12 +56,8 @@
"stop_success": "turned off the audioplayer",
"alcotest_desc": "Writes the percentage of beer in your blood",
"alcotest_success": "You are consisting of beer on the",
- "report_desc": "Opens a modal window for sending a message to the developer",
- "report_text_error": "Unfortunately, this command only works if it is called with /. So write /report",
- "report_modal_title": "Creating a wish/complaint",
- "report_modal_text_label": "What functionality to add or what to fix",
- "report_modal_text_placeholder": "Describe clearly and precisely",
- "report_modal_feedback": "Maybe I'll listen to you.",
+ "report_desc": "Return links to Github Issues or GitHub Discussions",
+ "report_message": "Create [Issue]({{issueLink}}) or [Discussion]({{discussionLink}})",
"status_desc": "View bot status",
"status_embed_title": "Bot status",
"status_embed_bot_version": "Bot version",
diff --git a/src/locales/en/general.json b/src/locales/en/general.json
index 563c890..36dec00 100644
--- a/src/locales/en/general.json
+++ b/src/locales/en/general.json
@@ -1,5 +1,6 @@
{
"error": "Error",
+ "warning": "Warning",
"thinking": "I am thinking",
"page": "Page"
}
diff --git a/src/locales/ru/audioplayer.json b/src/locales/ru/audioplayer.json
index c5b8d14..16da67b 100644
--- a/src/locales/ru/audioplayer.json
+++ b/src/locales/ru/audioplayer.json
@@ -1,7 +1,8 @@
{
"audio_commands_wrapper_song_processing": "Песни всё ещё обрабатываются, подожди",
"audio_commands_wrapper_player_not_exist": "Плеера не существует",
- "play_error": "Попробуйте другую ссылку",
+ "play_error": "Попробуйте другую песню, с этой какая-то ерунда происходит.",
+ "download_song_error": "Что-то пошло не так при получении ссылки на скачивание",
"show_queue_title": "Сейчас играет",
"show_queue_songs_in_queue": "Песни в очереди",
"event_empty": "Все ушли от меня, значит я тоже ухожу",
@@ -11,6 +12,7 @@
"event_add_song_author": "Автор",
"event_add_list": "Добавлен плейлист",
"event_add_list_songs_count": "Количество песен",
+ "event_add_list_limit": "Некоторые песни добавлены, но их количество было ограничено до {{queueLimit}}",
"player_embed_unknown": "Неизвестно",
"player_embed_requester": "Запросил",
"player_embed_author": "Автор",
diff --git a/src/locales/ru/commands.json b/src/locales/ru/commands.json
index 9092f2c..7e64d87 100644
--- a/src/locales/ru/commands.json
+++ b/src/locales/ru/commands.json
@@ -2,7 +2,7 @@
"set_prefix_desc": "Меняет префикс для ТЕКСТОВЫХ команд и только для текущего сервера",
"set_prefix_arg_newprefix_desc": "Не забудьте сообщить остальным участникам сервера об изменённом префиксе",
"set_prefix_restrict_prefixes": "Нельзя указывать символы {{prefixes}} в качестве префикса",
- "set_prefix_length_error": "Префикс не может быть длиннее одного символа",
+ "set_prefix_length_error": "Префикс не может быть длиннее двух символов",
"set_prefix_success_change": "Префикс на этом сервере успешно изменён на {{prefix}}",
"help_desc": "Список команд",
"help_arg_command": "название команды",
@@ -17,6 +17,7 @@
"play_desc": "Проигрывает музыку указанную пользователем",
"play_arg_link": "Ссылка с {{services}} или любой текст",
"play_stream": "Стрим",
+ "play_error_songs_limit": "Вы не можете добавлять новые песни, потому-что достигнут лимит очереди в {{queueLimit}} песен",
"download_desc": "Скачивает песню по ссылке",
"download_arg_request": "Ссылка с {{services}}",
"download_please_wait": "Пожалуйста, подождите. Это может занять много времени",
@@ -55,12 +56,8 @@
"stop_success": "выключил(-а) плеер",
"alcotest_desc": "Пишет процент пива в твоей крови",
"alcotest_success": "Вы состоите из пива на",
- "report_desc": "Открывает окно для отправки сообщения разработчику",
- "report_text_error": "К сожалению эта команда работает только если она вызвана через /. Так что напишите /report",
- "report_modal_title": "Создание пожелания/жалобы",
- "report_modal_text_label": "Какой функционал добавить или что исправить",
- "report_modal_text_placeholder": "Описывайте ясно и чётко",
- "report_modal_feedback": "Возможно я к тебе прислушаюсь",
+ "report_desc": "Возвращает ссылки на Github Issues или Github Discussions",
+ "report_message": "Создайте [Issue]({{issueLink}}) или [Discussion]({{discussionLink}})",
"status_desc": "Просмотр состояния бота",
"status_embed_title": "Состояние бота",
"status_embed_bot_version": "Версия бота",
diff --git a/src/locales/ru/commandshandlers.json b/src/locales/ru/commandshandlers.json
index bb1121d..a8d0bdc 100644
--- a/src/locales/ru/commandshandlers.json
+++ b/src/locales/ru/commandshandlers.json
@@ -1,6 +1,4 @@
{
- "text_command_error": "Ошибка исполнения текстовой команды",
- "slash_command_error": "Ошибка при исполнении \"/\" команды",
"bot_not_enough_permissions_1": "У БОТА недостаточно прав на этом канале или сервере",
"bot_not_enough_permissions_2": "Напишите /help (название команды), чтобы увидеть недостающие права",
"bot_not_enough_permissions_3": "А также попросите администрацию сервера их выдать боту",
diff --git a/src/locales/ru/general.json b/src/locales/ru/general.json
index dd13a3c..67012d1 100644
--- a/src/locales/ru/general.json
+++ b/src/locales/ru/general.json
@@ -1,5 +1,6 @@
{
"error": "Ошибка",
+ "warning": "Предупреждение",
"thinking": "Я думаю",
"page": "Страница"
}
diff --git a/src/main.ts b/src/main.ts
index 22423ea..85db499 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,14 +1,16 @@
+loggerSend(`Starting bot on version ${process.env.npm_package_version}`);
+
import { Client, GatewayIntentBits, Partials } from 'discord.js';
-import { loggerError } from './utilities/logger.js';
+import { loggerError, loggerSend } from './utilities/logger.js';
import { loginBot } from './utilities/loginBot.js';
-import { AudioPlayerCore } from './commands/audio/audioPlayer/AudioPlayerCore.js';
+import { AudioPlayerCore } from './audioplayer/AudioPlayerCore.js';
import loadLocale from './locales/Locale.js';
await loadLocale();
import { handlersLoad } from './handlers/handlersLoad.js';
-const client = new Client({
+const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildPresences,
diff --git a/src/utilities/generateErrorEmbed.ts b/src/utilities/generateErrorEmbed.ts
index 79e889e..38da149 100644
--- a/src/utilities/generateErrorEmbed.ts
+++ b/src/utilities/generateErrorEmbed.ts
@@ -1,9 +1,12 @@
import { EmbedBuilder } from 'discord.js';
import i18next from 'i18next';
-export function generateErrorEmbed(errorMessage: string): EmbedBuilder {
+export function generateErrorEmbed(
+ errorMessage: string,
+ errorName = i18next.t('general:error')
+): EmbedBuilder {
return new EmbedBuilder()
- .setTitle(`⚠️ ${i18next.t('general:error')}`)
+ .setTitle(`<:error:1257892426790731786> ${errorName}`)
.setColor('Red')
.setDescription(errorMessage.slice(0, 2048));
}
diff --git a/src/utilities/generateSimpleEmbed.ts b/src/utilities/generateSimpleEmbed.ts
new file mode 100644
index 0000000..3017c76
--- /dev/null
+++ b/src/utilities/generateSimpleEmbed.ts
@@ -0,0 +1,5 @@
+import { EmbedBuilder } from 'discord.js';
+
+export function generateSimpleEmbed(message: string): EmbedBuilder {
+ return new EmbedBuilder().setColor('Grey').setDescription(message.slice(0, 2048));
+}
diff --git a/src/utilities/generateWarningEmbed.ts b/src/utilities/generateWarningEmbed.ts
new file mode 100644
index 0000000..bcd09f2
--- /dev/null
+++ b/src/utilities/generateWarningEmbed.ts
@@ -0,0 +1,9 @@
+import { EmbedBuilder } from 'discord.js';
+import i18next from 'i18next';
+
+export function generateWarningEmbed(warningMessage: string): EmbedBuilder {
+ return new EmbedBuilder()
+ .setTitle(`<:warning:1257892727014817865> ${i18next.t('general:warning')}`)
+ .setColor('Yellow')
+ .setDescription(warningMessage.slice(0, 2048));
+}
diff --git a/src/utilities/isOverpoweredUser.ts b/src/utilities/isOverpoweredUser.ts
new file mode 100644
index 0000000..72f35ee
--- /dev/null
+++ b/src/utilities/isOverpoweredUser.ts
@@ -0,0 +1,5 @@
+import { ENV } from '../EnvironmentVariables.js';
+
+export function isOverpoweredUser(userId: string): boolean {
+ return userId === ENV.BOT_DISCORD_OVERPOWERED_ID;
+}
diff --git a/src/utilities/logger.ts b/src/utilities/logger.ts
index e6acdcc..d186e05 100644
--- a/src/utilities/logger.ts
+++ b/src/utilities/logger.ts
@@ -45,7 +45,7 @@ export function loggerSend(
if (prefix) {
console.log(`[ ${getCurrentTimestamp()} ] [ ${prefix} ] ${finalOutput}`);
} else {
- console.log(`[ ${getCurrentTimestamp()} ] [ UNKNOWN ] ${finalOutput}`);
+ console.log(`[ ${getCurrentTimestamp()} ] ${finalOutput}`);
}
}
diff --git a/tsconfig.json b/tsconfig.json
index 4ca1534..a0823dc 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,7 +1,8 @@
{
"compilerOptions": {
- "module": "NodeNext",
- "target": "es2021",
+ "baseUrl": "./",
+ "module": "preserve",
+ "target": "es2022",
"sourceMap": true,
"rootDir": "./src",
"outDir": "./build",
@@ -12,7 +13,8 @@
"resolveJsonModule": true,
"forceConsistentCasingInFileNames": false,
"allowSyntheticDefaultImports": true,
- "skipLibCheck": true
+ "preserveConstEnums": false,
+ "skipLibCheck": true,
},
"compileOnSave": true,
"include": [
@@ -22,5 +24,5 @@
"exclude": [
"node_modules",
"build"
- ],
+ ]
}
diff --git a/wiki/API-Configure.md b/wiki/API-Configure.md
new file mode 100644
index 0000000..4c13f4c
--- /dev/null
+++ b/wiki/API-Configure.md
@@ -0,0 +1,78 @@
+> [!CAUTION]
+> Don't share this API data with anyone because you can get compromised.
+> If this happens, reset the tokens and get them again.
+
+# Discord Developer Portal (required)
+
+1. Open the [Discord Developer Portal](https://discord.com/developers/applications) and log into your account.
+2. Click on the "New Application" button.
+3. Enter a name and confirm the pop-up window by clicking the "Create" button.
+
+You should see a page like this:
+
+![discord-dev-selected-app](images/api-configure/discord-dev-selected-app.png)
+
+You can edit your application's name, description, and avatar here. Once you've done that, then congratulations—you're now the proud owner of a shiny new Discord bot! You're not entirely done, though.
+
+4. On "General Information" page copies the Application ID, this is your Client ID.
+5. On the sidebar select section "Bot"
+6. Press "Reset token" button and copy token.
+7. Also enable all "Privileged Gateway Intents"
+
+![discord-dev-enable-intents](images/api-configure/discord-dev-enable-intents.png)
+
+# YouTube Cookie (optional)
+Preferable to provide cookies for YouTube.
+This will allow you to play 18+ videos and bypass YouTube rate limiting error (429 Error).
+I highly recommend that you create a new Google account from which you can get the cookie.
+
+> [!WARNING]
+> Time to time, cookies are resets by YouTube, so you need to retrieve it again.
+> It's so annoying, but hasn't figured out a way to automate the cookie retrieval process.
+> If you know workaround, please create the [issue](https://github.com/AlexInCube/AlCoTest/issues/new/choose)
+
+1. Install an extension for extracting cookie, [EditThisCookie](https://www.editthiscookie.com/blog/2014/03/install-editthiscookie/)
+2. Go to [YouTube](https://www.youtube.com/)
+3. Log in to your account. (You should use a new account for this purpose)
+4. Click on the extension icon and click "Export" button.
+5. Create file yt-cookies.json and paste cookie in this file
+
+# Yandex Music (optional)
+If you do not provide token and UID, Yandex Music will not work at all.
+
+> [!WARNING]
+> If your bot is outside Russia VDS, you must have a Yandex Plus subscription to play songs.
+
+## Token
+1. Login into [Yandex](https://passport.yandex.ru/auth) account.
+2. Download [browser extension](https://chromewebstore.google.com/detail/yandex-music-token/lcbjeookjibfhjjopieifgjnhlegmkib)
+This must look like this ![yandex-extension](images/api-configure/yandex-music-extension.png)
+3. Click "Скопировать токен" button.
+
+## UID
+1. Login into [Yandex](https://passport.yandex.ru/auth) account.
+2. You can retrieve uid by opening [Yandex Mail](https://mail.yandex.ru) and copy uid from the url in the address bar.
+![yandex-uid](images/api-configure/yandex-music-uid.png)
+
+# Spotify (optional)
+Spotify Module can work without provided data, but for more stability better provide custom application data.
+
+> [!WARNING]
+> If you want to fetch playlist with more than 100 songs, this API data is required!
+
+1. Login in [Spotify Developer Dashboard](https://developer.spotify.com/dashboard)
+2. Press "Create app" button![Spotify Dev Main](images/api-configure/spotify-dev-main.png)
+3. Fill the fields like this![Spotify Dev Create App](images/api-configure/spotify-dev-create-app.png)
+4. Press "Save"
+5. On the redirected page, press "Settings"
+6. On "Basic Information" section copy Client ID.
+7. Under the Client ID field, press "View Client Secret" and copy Client Secret.
+
+# Soundcloud (optional)
+
+1. Go to [SoundCloud](https://soundcloud.com) and login.
+2. Open up the dev tools (Right-click -> inspect) and go to the Network tab.
+3. Refresh the page with opened dev tools.
+4. Find the request that has the name session (you can filter by typing session in the filter box) and click on it
+5. Go to the Payload tab
+6. You should see your client id in the Query String Parameters section, and your oauth token (access_token) in the Request Payload section
diff --git a/wiki/Commands.md b/wiki/Commands.md
new file mode 100644
index 0000000..cd1769b
--- /dev/null
+++ b/wiki/Commands.md
@@ -0,0 +1,131 @@
+# About command system
+Bot supports slash and text command systems.
+
+## Slash commands
+Nothing special, start writing / and select command from the list
+
+## Text commands
+If a bot owner does not change the default prefix in .env.production file, the prefix is //
+
+> [!NOTE]
+> If bot prefix conflicting with another bot on server,
+> administrator can set the second text prefix for server using [/setPrefix](#setprefix) command
+
+# Commands list
+## Admin
+It Can be used only by server administrators (people who have a role with "Administrator" permission)
+
+### setPrefix
+Changes bot prefix for the server
+
+Example: /newPrefix $$
+
+Prefix symbols cannot be symbols: / @ #, because these symbols reserved for Discord purpose.
+Prefix length cannot be longer than two symbols.
+
+## Audio
+
+The bot philosophy built around audioplayer to reduce commands using.
+
+Use [/play](#play) or [/playfile](#playfile) to spawn audioplayer
+
+![play-audioplayer](images/commands/play-audioplayer.png)
+
+Most of the time of using bot, you need only add songs by [/play](#play) or [/playfile](#playfile)
+
+When any message created in chat where audioplayer is spawned,
+bot will recreate the player so that the player is always at the bottom of the chat room.
+
+> [!NOTE]
+> Highly recommended to create a text channel for the bot
+
+> [!WARNING]
+> Audio commands which change audioplayer state require audioplayer and be with bot in the same voice channel to exist.
+> Also this kind of commands needs to be written in the same channel where audioplayer was spawned.
+
+### play
+
+Example: /play https://open.spotify.com/track/46gSk82duJtX3TTA182ruG?si=c668ab77755f4d88
+
+Spawn audioplayer in a text channel if not exists.
+Accept songs/playlist from links.
+Support searching on YouTube
+when you write something like this ![play-autocomplete](images/commands/play-autocomplete.png)
+
+### playfile
+
+Do the same things as play command, but accept MP3/WAV/OGG files instead of text/links
+
+![play-file](images/commands/play-file.png)
+
+### playing
+
+Return the current playback time of the song
+
+![playing](images/commands/playing.png)
+
+### download
+
+Accept links you songs and return mp3 file in a text channel where the command is called.
+
+Example: /download https://www.youtube.com/watch?v=60ItHLz5WEA
+
+### jump
+
+If your queue has a large count of songs, you can jump to the desired song.
+To get the number of songs you want, press the button in audioplayer to get a queue songs list.
+
+Example: /jump 4
+
+### previous
+
+Returns to previous played/skipped song in queue
+
+### rewind
+
+Allow you to change the current playback time.
+Accept time in HH:MM:SS or MM:SS or SS format.
+
+Example: 1:02:32
+
+### shuffle
+
+Shuffle the next songs in the queue
+
+### skip
+
+Skip current playing song
+
+### stop
+
+Kill the audioplayer
+
+### audiodebug
+
+Give the current count of spawned audioplayers
+
+> [!NOTE]
+> This command supported only by text command system
+> Also you must be overpowered user.
+
+## Fun
+
+### alcotest
+Generate random number for 0 to 100
+
+## Info
+
+### help
+Return the command list or certain command description
+
+Command list example: /help
+Certain command example: /help play
+
+### inviteLink
+Return the link for inviting the bot. Give the link to the administrator on another server.
+
+### status
+Return bot status data, about: OS, Ram Usage, Cpu Model, Cpu Usage, AICoTest Version, Servers Count.
+
+### report
+Return links to GitHub Issues or GitHub Discussions.
diff --git a/wiki/Frequently-Asked-Questions.md b/wiki/Frequently-Asked-Questions.md
new file mode 100644
index 0000000..432c4f2
--- /dev/null
+++ b/wiki/Frequently-Asked-Questions.md
@@ -0,0 +1,4 @@
+## Spotify/Apple Music songs some times are wrong
+
+Bot can't get audio-stream from these services. So we can fetch only info about songs from these services.
+Then bot trying to find a song on YouTube and play it.
diff --git a/wiki/Home.md b/wiki/Home.md
new file mode 100644
index 0000000..fbf4f21
--- /dev/null
+++ b/wiki/Home.md
@@ -0,0 +1,10 @@
+# Welcome to AICoTest wiki
+
+Here you can find information on how to use or setup bot.
+
+## Getting started with AICoTest
+
+- You can explore features of the bot in [[Commands]]
+- If you want to set up bot on your own host, go to [[Setup]]
+- Prior to seeking assistance, please review the [[Frequently Asked Questions]] section for potential resolutions to your issue.
+- If you still require assistance or find a bug, create [issue](https://github.com/AlexInCube/AlCoTest/issues/new/choose) or [discussion](https://github.com/AlexInCube/AlCoTest/discussions/new?category=q-a).
diff --git a/wiki/Setup.md b/wiki/Setup.md
new file mode 100644
index 0000000..351960c
--- /dev/null
+++ b/wiki/Setup.md
@@ -0,0 +1,77 @@
+# ⚙️ Configure .env
+
+You can use Docker Compose or install all dependencies and source code locally.
+But in both cases, you need to configure .env file.
+
+Also you need retrieve token, client id and enable intents on Discord Developer Portal.
+
+- Create file .env.production
+- Fill all fields in .env.production. If the field is marked as (Optional), you can skip it.
+- (Required) To get Discord Token and enable intents, follow the [Discord Developer Portal](https://github.com/AlexInCube/AlCoTest/wiki/API-Configure#discord-developer-portal-required) section.
+- (Optional) To get Spotify Secret and ID, follow the [Spotify](https://github.com/AlexInCube/AlCoTest/wiki/API-Configure#spotify-optional) section.
+- (Optional) To get Yandex Music token, follow the [Yandex Music](https://github.com/AlexInCube/AlCoTest/wiki/API-Configure#yandex-music-optional) section.
+- (Optional) To get SoundCloud token, follow the [Soundcloud](https://github.com/AlexInCube/AlCoTest/wiki/API-Configure#soundcloud-optional) section.
+
+| Name | Example | Description | Required? |
+|------------------------------|-----------------------|---------------------------------------------------------------------------|-----------|
+| `BOT_VERBOSE_LOGGING` | false | The bot will give more information to the console, useful for debugging | ❌ |
+| `BOT_COMMAND_PREFIX` | // | Used only for text commands | ✔️ |
+| `BOT_LANGUAGE` | en | Supported values: en ru | ❌ |
+| `MONGO_URI` | mongodb://mongo:27017 | The public key for sending notifications | ✔️ |
+| `MONGO_DATABASE_NAME` | aicbot | Database name in MongoDB | ✔️ |
+| `BOT_DISCORD_TOKEN` | ODEzNzUwMTY1N... | Token from Discord Developer Portal | ✔️ |
+| `BOT_DISCORD_CLIENT_ID` | 813750165783... | Application ID from Discord Developer Portal | ✔️ |
+| `BOT_DISCORD_OVERPOWERED_ID` | 29016845994426.... | Discord bot owner user ID, required for having more bot control for owner | ✔️ |
+| `BOT_SPOTIFY_CLIENT_SECRET` | | Used when the Spotify module cannot get the credentials automatically | ❌ |
+| `BOT_SPOTIFY_CLIENT_ID` | | Used when the Spotify module get the credentials automatically | ❌ |
+| `BOT_YANDEXMUSIC_TOKEN` | | Provide to enable Yandex Music module | ❌ |
+| `BOT_YANDEXMUSIC_UID` | | Provide to enable Yandex Music module | ❌ |
+| `BOT_SOUNDCLOUD_CLIENT_ID` | | Provide to fetch more data with SoundCloud Go+ account | ❌ |
+| `BOT_SOUNDCLOUD_TOKEN` | | Provide to fetch more data with SoundCloud Go+ account | ❌ |
+
+# 🐋 Run in Docker (recommended)
+
+> [!NOTE]
+> Using Docker provides the auto-update feature
+
+- Install [Docker](https://www.docker.com/get-started/)
+- Copy docker-compose.yml, Dockerfile in empty folder
+- Follow the [Configure .env](#-configure-env) section and copy .env.production in folder with docker-compose.yml etc.
+- (Optional) Follow the [YouTube Cookie](https://github.com/AlexInCube/AlCoTest/wiki/API-Configure#-youtube-cookie-optional) section and copy yt-cookies.json in the folder with docker-compose.yml etc.
+- Your file structure must be like this
+
+```
+AICoTest/
+ ├─ .env.production
+ ├─ docker-compose.yml
+ ├─ yt-cookies.yml
+```
+
+- Run command `docker-compose up --detach --force-recreate` from folder with files
+
+# 🖥️ Run locally (if you are not a developer, this way is no sense)
+
+- Install [Node.js 22](https://nodejs.org/en/download/prebuilt-installer) or higher
+- Install [Python 3.12](https://www.python.org/downloads/)
+- Install C++ compiler. Follow this [guide](https://github.com/nodejs/node-gyp#on-windows)
+- Install FFMpeg. Follow this [guide](https://www.wikihow.com/Install-FFmpeg-on-Windows)
+- Clone repository to your computer
+- Follow the [Configure .env](#-configure-env) section and copy .env.production in folder with repository.
+- (Optional) Follow the [YouTube Cookie](https://github.com/AlexInCube/AlCoTest/wiki/API-Configure#-youtube-cookie-optional) and copy yt-cookies.json in the folder with repository.
+- Install Node.js packages in the folder with repository
+
+```npm
+npm install
+```
+
+- Compile bot
+
+```
+npm run build
+```
+
+- Run the bot
+
+```
+npm run production
+```
diff --git a/wiki/images/api-configure/discord-dev-enable-intents.png b/wiki/images/api-configure/discord-dev-enable-intents.png
new file mode 100644
index 0000000..ebdeffe
Binary files /dev/null and b/wiki/images/api-configure/discord-dev-enable-intents.png differ
diff --git a/wiki/images/api-configure/discord-dev-selected-app.png b/wiki/images/api-configure/discord-dev-selected-app.png
new file mode 100644
index 0000000..0d8e3ae
Binary files /dev/null and b/wiki/images/api-configure/discord-dev-selected-app.png differ
diff --git a/wiki/images/api-configure/spotify-dev-create-app.png b/wiki/images/api-configure/spotify-dev-create-app.png
new file mode 100644
index 0000000..92727af
Binary files /dev/null and b/wiki/images/api-configure/spotify-dev-create-app.png differ
diff --git a/wiki/images/api-configure/spotify-dev-main.png b/wiki/images/api-configure/spotify-dev-main.png
new file mode 100644
index 0000000..aad0be3
Binary files /dev/null and b/wiki/images/api-configure/spotify-dev-main.png differ
diff --git a/wiki/images/api-configure/yandex-music-extension.png b/wiki/images/api-configure/yandex-music-extension.png
new file mode 100644
index 0000000..de67842
Binary files /dev/null and b/wiki/images/api-configure/yandex-music-extension.png differ
diff --git a/wiki/images/api-configure/yandex-music-uid.png b/wiki/images/api-configure/yandex-music-uid.png
new file mode 100644
index 0000000..4b89766
Binary files /dev/null and b/wiki/images/api-configure/yandex-music-uid.png differ
diff --git a/wiki/images/commands/play-audioplayer.png b/wiki/images/commands/play-audioplayer.png
new file mode 100644
index 0000000..ad93649
Binary files /dev/null and b/wiki/images/commands/play-audioplayer.png differ
diff --git a/wiki/images/commands/play-autocomplete.png b/wiki/images/commands/play-autocomplete.png
new file mode 100644
index 0000000..a5d9d84
Binary files /dev/null and b/wiki/images/commands/play-autocomplete.png differ
diff --git a/wiki/images/commands/play-file.png b/wiki/images/commands/play-file.png
new file mode 100644
index 0000000..aff3396
Binary files /dev/null and b/wiki/images/commands/play-file.png differ
diff --git a/wiki/images/commands/playing.png b/wiki/images/commands/playing.png
new file mode 100644
index 0000000..ffebf5c
Binary files /dev/null and b/wiki/images/commands/playing.png differ