diff --git a/.env_example b/.env_example index eb104ce15..2b0eb6eba 100644 --- a/.env_example +++ b/.env_example @@ -62,6 +62,13 @@ DEV_GUILD=[""] # Default: production NODE_ENV="" +#============================================================================== +# Which youtube downloader do you want to use? Note: if you use play-dl, it will support a few sites. +# Example: STREAM_STRATEGY="youtube-dl" +# Available: play-dl, youtube-dl +# Default: youtube-dl +STREAM_STRATEGY="" + #============================================================================== # Do you want to enable slash command support? # Example: ENABLE_SLASH_COMMAND="yes" diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 66b2ea76a..f84585367 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,2 @@ # Global -* @mzrtamp @Mednoob @ZenShibata +* @mzrtamp @Mednoob diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 5b0052b05..44261fdff 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,2 @@ -patreon: zhycorp -custom: ["https://karyakarsa.com/zhycorp"] +patreon: mzrtamp +custom: ["https://karyakarsa.com/mozartrafi"] diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index b46e286b2..0086358db 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1 @@ blank_issues_enabled: true -contact_links: - - name: Discord Server - url: https://zhycorp.net/discord - about: Visit our Discord server for easier and faster respond. diff --git a/.github/images/disc-11.png b/.github/images/disc-11.png deleted file mode 100644 index 72f1febe0..000000000 Binary files a/.github/images/disc-11.png and /dev/null differ diff --git a/.github/images/rawon.png b/.github/images/rawon.png new file mode 100644 index 000000000..de100182f Binary files /dev/null and b/.github/images/rawon.png differ diff --git a/LICENSE b/LICENSE index cc143bb68..fa094f16b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2021, Zhycorp +Copyright (c) 2022, RB Project All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index 983a2554b..2df465ea1 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@ -![Splash](https://repository-images.githubusercontent.com/236645319/1da444e8-04ad-48a7-aee2-325cb3c7f6a7) +
+ Splash +
-# Disc 11 by Zhycorp +# Rawon -> A dedicated open-source Discord bot for Zhycorp based from [our Discord bot template](https://github.com/zhycorp/discord-bot-template) with more features. Easy to use, and with no coding required. +> A dedicated open-source music and moderation Discord bot. Easy to use, and with no coding required. -Discord Server - + -CI Status +CI Status ## Features - Interaction support. @@ -41,24 +42,23 @@ $ npm start ### Heroku You can host this bot to make it stay online on Heroku. -Deploy to Heroku +Deploy to Heroku ### Glitch You can use Glitch too for this project, featured with its code editor. -> Watch the tutorial video on YouTube! -> -> ▶️ **https://youtu.be/ILutlBl_Xyk** - 1. Star and fork this project 2. Go to [glitch.com](https://glitch.com) and make an account -3. Click **New Project** then **Import from GitHub**, specify the pop-up field with `https://github.com//disc-11` (without `<>`) +3. Click **New Project** then **Import from GitHub**, specify the pop-up field with `https://github.com//rawon` (without `<>`) 4. Please wait for a while, this process takes some minutes 5. Find `.env` file and delete it, find `.env_example` file and rename it back to `.env` 6. After specifying `.env`, open **Tools** > **Terminal** 7. Type `refresh`, and track the process from **Logs** -8. To make the bot stay online, please watch [this video](https://youtu.be/K2nqthN1xKQ?t=551) carefully. -Remix on Glitch +Remix on Glitch + +## Project Maintainer +- [@Mednoob](https://github.com/Mednoob) +- [@mzrtamp](https://github.com/mzrtamp) -> © 2021 Zhycorp Development +> © 2022 RB Project diff --git a/app.json b/app.json index d68569f75..c3895c6de 100644 --- a/app.json +++ b/app.json @@ -1,7 +1,7 @@ { - "name": "Disc 11", - "description": "A dedicated open-source Discord bot for Zhycorp based on our Discord bot template with more features. Easy to use, and with no coding required.", - "logo": "https://raw.githubusercontent.com/zhycorp/disc-11/main/.github/images/disc-11.png", + "name": "Rawon", + "description": "A dedicated open-sourced Discord bot with many features of utilization. Easy to use, and with no coding required.", + "logo": "https://raw.githubusercontent.com/mzrtamp/rawon/main/.github/images/rawon.png", "env": { "DISCORD_TOKEN": { "description": "What is your Discord bot's token? | Example: NTE5NjQ2MjIxNTU2Nzc2OTcw.XAcEQQ.0gjhNbGeWBsKP6FVuIyZWlG2cMd", @@ -52,6 +52,11 @@ "required": false, "value": "production" }, + "STREAM_STRATEGY": { + "description": "Which youtube downloader do you want to use? Note: if you use play-dl, it will support a few sites. | Example: \"play-dl\" | Available: \"play-dl\", \"youtube-dl\"", + "required": false, + "value": "youtube-dl" + }, "ENABLE_SLASH_COMMAND": { "description": "Do you want to enable slash command support? | Example: yes", "required": false, @@ -93,8 +98,8 @@ "value": "❌" } }, - "repository": "https://github.com/zhycorp/disc-11", - "website": "https://disc-11.zhycorp.net", + "repository": "https://github.com/mzrtamp/rawon", + "website": "https://rawon.tiramitzu.me", "formation": { "worker": { "quantity": 1, diff --git a/index.js b/index.js index c9b88b628..f952a3e0f 100644 --- a/index.js +++ b/index.js @@ -3,17 +3,6 @@ const { existsSync, rmSync } = require("fs"); const { resolve } = require("path"); const { Server } = require("https"); -try { - require("dotenv/config"); -} catch (err) { - console.info("[INFO] It seems dotenv hasn't been installed, trying to re-install all modules..."); - if (existsSync(resolve(process.cwd(), "node_modules"))) rmSync(resolve(process.cwd(), "node_modules"), { recursive: true }); - execSync("npm i --only=prod dotenv"); - console.info("[INFO] dotenv has been installed, trying to retrieve environment data..."); - require("dotenv/config"); - console.info("[INFO] Environment data has been retrieved."); -} - const isGlitch = ( process.env.PROJECT_DOMAIN !== undefined && process.env.PROJECT_INVITE_TOKEN !== undefined && @@ -57,36 +46,70 @@ const isGitHub = ( process.env.GITHUB_SERVER_URL !== undefined ) +function npmInstall(deleteDir = false, forceInstall = false, additionalArgs = []) { + if (deleteDir) { + const modulesPath = resolve(process.cwd(), "node_modules"); + + if (existsSync(modulesPath)) { + rmSync(modulesPath, { recursive: true }); + } + } + + execSync(`npm install${isGlitch ? " --only=prod" : ""}${forceInstall ? " --force" : ""} ${additionalArgs.join(" ")}`); +} + if (isGlitch) { - execSync("npm i --only=prod"); + try { + console.info("[INFO] Trying to re-install modules..."); + npmInstall(); + console.info("[INFO] Modules successfully re-installed."); + } catch (err) { + console.info("[INFO] Failed to re-install modules, trying to delete node_modules and re-install..."); + try { + npmInstall(true); + console.info("[INFO] Modules successfully re-installed."); + } catch { + console.info("[INFO] Failed to re-install modules, trying to delete node_modules and install modules forcefully..."); + try { + npmInstall(true, true); + console.info("[INFO] Modules successfully re-installed."); + } catch { + console.warn("[WARN] Failed to re-install modules, please re-install manually."); + } + } + } } if (isReplit) { console.warn("[WARN] We haven't added stable support for running this bot using Replit, bugs and errors may come up."); + + if (Number(process.versions.node.split(".")[0]) < 16) { + console.info("[INFO] This Replit doesn't use Node.js v16 or newer, trying to install Node.js v16..."); + execSync(`npm i --save-dev node@16.6.1 && npm config set prefix=$(pwd)/node_modules/node && export PATH=$(pwd)/node_modules/node/bin:$PATH`); + console.info("[INFO] Node.js v16 has been installed, please restart the bot."); + process.exit(0); + } } if (isGitHub) { console.warn("[WARN] Running this bot using GitHub is not recommended."); } -if (isReplit && (Number(process.versions.node.split(".")[0]) < 16)) { - console.info("[INFO] This Replit doesn't use Node.js v16 or newer, trying to install Node.js v16..."); - execSync(`npm i --save-dev node@16.6.1 && npm config set prefix=$(pwd)/node_modules/node && export PATH=$(pwd)/node_modules/node/bin:$PATH`); - console.info("[INFO] Node.js v16 has been installed, please restart the bot."); - process.exit(0); -} - if (!isGlitch) { - console.info("[INFO] This bot is not running on Glitch, trying to install ffmpeg-static..."); - execSync("npm i --no-save ffmpeg-static"); - console.info("[INFO] ffmpeg-static has been installed."); + try { + require("ffmpeg-static"); + } catch { + console.info("[INFO] This bot is not running on Glitch, trying to install ffmpeg-static..."); + npmInstall(false, false, ["--no-save", "ffmpeg-static"]); + console.info("[INFO] ffmpeg-static has been installed."); + } } if (isGlitch || isReplit) { new Server((req, res) => { const now = new Date().toLocaleString("en-US"); res.end(`OK (200) - ${now}`); - }).listen(Number(process.env.PORT) || 3000); + }).listen(Number(process.env.PORT || 3000) || 3000); console.info(`[INFO] ${isGlitch ? "Glitch" : "Replit"} environment detected, trying to compile...`); execSync(`npm run compile`); @@ -94,18 +117,37 @@ if (isGlitch || isReplit) { } (async () => { + const streamStrategy = process.env.STREAM_STRATEGY; const isUnix = ["aix", "android", "darwin", "freebsd", "linux", "openbsd", "sunos"].includes(process.platform.toLowerCase()); process.env.YOUTUBE_DL_HOST = "https://api.github.com/repos/yt-dlp/yt-dlp/releases?per_page=1"; process.env.YOUTUBE_DL_FILENAME = "yt-dlp"; - const ytdlBinaryDir = resolve(__dirname, "node_modules", "youtube-dl-exec", "bin") - if (!existsSync(resolve(ytdlBinaryDir, isUnix ? "yt-dlp" : "yt-dlp.exe"))) { - console.info("[INFO] Yt-dlp couldn't be found, trying to download..."); - if (existsSync(resolve(ytdlBinaryDir, isUnix ? "youtube-dl" : "youtube-dl.exe"))) rmSync(resolve(ytdlBinaryDir, isUnix ? "youtube-dl" : "youtube-dl.exe")); - await require("youtube-dl-exec/scripts/postinstall"); - console.info("[INFO] Yt-dlp has been downloaded."); - } + if (streamStrategy !== "play-dl") { + try { + require("youtube-dl-exec"); + } catch { + console.info("[INFO] Installing youtube-dl-exec..."); + npmInstall(false, false, ["youtube-dl-exec"]); + console.info("[INFO] Youtube-dl-exec has been installed."); + } + const ytdlBinaryDir = resolve(__dirname, "node_modules", "youtube-dl-exec", "bin") + if (!existsSync(resolve(ytdlBinaryDir, isUnix ? "yt-dlp" : "yt-dlp.exe"))) { + console.info("[INFO] Yt-dlp couldn't be found, trying to download..."); + if (existsSync(resolve(ytdlBinaryDir, isUnix ? "youtube-dl" : "youtube-dl.exe"))) rmSync(resolve(ytdlBinaryDir, isUnix ? "youtube-dl" : "youtube-dl.exe")); + await require("youtube-dl-exec/scripts/postinstall"); + console.info("[INFO] Yt-dlp has been downloaded."); + } + } + if (streamStrategy === "play-dl") { + try { + require("play-dl"); + } catch { + console.info("[INFO] Installing play-dl..."); + npmInstall(false, false, ["play-dl"]); + console.info("[INFO] Play-dl has been installed."); + } + } console.info("[INFO] Starting the bot..."); require("./dist/index.js"); })(); diff --git a/package-lock.json b/package-lock.json index d2ea24dfc..b4ebbeaef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,40 +1,43 @@ { - "name": "disc-11", - "version": "2.3.0", + "name": "rawon", + "version": "2.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "disc-11", - "version": "2.3.0", + "name": "rawon", + "version": "2.4.0", "license": "BSD-3-Clause", "dependencies": { - "@discordjs/voice": "^0.7.5", + "@discordjs/voice": "^0.8.0", "date-fns": "^2.28.0", - "discord.js": "^13.5.0", - "dotenv": "^10.0.0", + "discord.js": "^13.6.0", + "dotenv": "^16.0.0", "got": "^11.8.3", - "i18n": "0.13.4", + "i18n": "0.14.1", "opusscript": "^0.0.8", "prism-media": "^1.3.2", "soundcloud.ts": "^0.4.1", "sucrase": "^3.20.3", "tslib": "^2.3.1", "tweetnacl": "^1.0.3", - "youtube-dl-exec": "^2.0.2", - "youtubei": "^0.0.1-rc.23" + "youtubei": "^0.0.1-rc.28" }, "devDependencies": { "@types/i18n": "^0.13.2", - "@types/node": "^17.0.8", - "@typescript-eslint/eslint-plugin": "^5.9.0", - "@typescript-eslint/parser": "^5.9.0", - "@zhycorp/eslint-config": "^6.0.2", - "eslint": "^8.5.0", - "typescript": "^4.5.4" + "@types/node": "^17.0.15", + "@typescript-eslint/eslint-plugin": "^5.10.2", + "@typescript-eslint/parser": "^5.10.2", + "@zhycorp/eslint-config": "^7.1.0", + "eslint": "^8.8.0", + "typescript": "^4.5.5" }, "engines": { "node": ">=16.6.0" + }, + "optionalDependencies": { + "play-dl": "^1.8.1", + "youtube-dl-exec": "^2.0.2" } }, "node_modules/@discordjs/builders": { @@ -53,14 +56,6 @@ "npm": ">=7.0.0" } }, - "node_modules/@discordjs/builders/node_modules/discord-api-types": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz", - "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==", - "engines": { - "node": ">=12" - } - }, "node_modules/@discordjs/collection": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.4.0.tgz", @@ -71,20 +66,19 @@ } }, "node_modules/@discordjs/voice": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.7.5.tgz", - "integrity": "sha512-lUk+CmIXNKslT6DkC9IF9rpsqhzlTiedauUCPBzepjd4XWxwBZiyVIzR6QpbAirxkAwCoAbbje+3Ho71PGLEAw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.8.0.tgz", + "integrity": "sha512-o0JfVLMs3eLjUzPf6oxMydEeum40I7xzfUc66SLN+RrKpSAsTbngf5qnCF53nm+KDNSvrwg1AZqNm4LEAdxJIA==", "dependencies": { "@types/ws": "^8.2.0", - "discord-api-types": "^0.24.0", + "discord-api-types": "^0.26.1", "prism-media": "^1.3.2", "tiny-typed-emitter": "^2.1.0", "tslib": "^2.3.1", - "ws": "^8.2.3" + "ws": "^8.4.2" }, "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" + "node": ">=16.9.0" } }, "node_modules/@eslint/eslintrc": { @@ -136,6 +130,55 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@messageformat/core": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@messageformat/core/-/core-3.0.0.tgz", + "integrity": "sha512-mzMCyADGweNmnMwV/xjKxtXtkXJNVcK5ATOHx4Q0GVr2Z3++in1VfrB/y6jM43nleK27tFO0Y/9pds5vxWqDvQ==", + "dependencies": { + "@messageformat/date-skeleton": "^1.0.0", + "@messageformat/number-skeleton": "^1.0.0", + "@messageformat/parser": "^5.0.0", + "@messageformat/runtime": "^3.0.0", + "make-plural": "^6.2.1", + "safe-identifier": "^0.4.1" + } + }, + "node_modules/@messageformat/core/node_modules/make-plural": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-6.2.2.tgz", + "integrity": "sha512-8iTuFioatnTTmb/YJjywkVIHLjcwkFD9Ms0JpxjEm9Mo8eQYkh1z+55dwv4yc1jQ8ftVBxWQbihvZL1DfzGGWA==" + }, + "node_modules/@messageformat/date-skeleton": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@messageformat/date-skeleton/-/date-skeleton-1.0.0.tgz", + "integrity": "sha512-vvj5Sd3VyXUHGbYpiFsPsSQ8pkdUM9vrR/NUbyP6ga3UqJH4p9eCwzfwaCAZatZMYMTyiKG/8QbUyGKHeTZ5kw==" + }, + "node_modules/@messageformat/number-skeleton": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@messageformat/number-skeleton/-/number-skeleton-1.0.0.tgz", + "integrity": "sha512-Pe1HX/VG0q7tclM/ri85I4FKYd7Uc3gluSZbRaK1+jcXdT9Biw2hLAKyMsiz2tM6zLiK1xX+K0NMDO4RIstQig==" + }, + "node_modules/@messageformat/parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.0.0.tgz", + "integrity": "sha512-WiDKhi8F0zQaFU8cXgqq69eYFarCnTVxKcvhAONufKf0oUxbqLMW6JX6rV4Hqh+BEQWGyKKKHY4g1XA6bCLylA==", + "dependencies": { + "moo": "^0.5.1" + } + }, + "node_modules/@messageformat/runtime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@messageformat/runtime/-/runtime-3.0.0.tgz", + "integrity": "sha512-boV0oH8jnJM/qoynQKnIbnKK5M7JPpKM0y9QUB9nQMMt16qSlgi5FfUo8usgoq6wEYqxDmIqtUfBewcj2VP+yQ==", + "dependencies": { + "make-plural": "^6.2.1" + } + }, + "node_modules/@messageformat/runtime/node_modules/make-plural": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-6.2.2.tgz", + "integrity": "sha512-8iTuFioatnTTmb/YJjywkVIHLjcwkFD9Ms0JpxjEm9Mo8eQYkh1z+55dwv4yc1jQ8ftVBxWQbihvZL1DfzGGWA==" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -181,9 +224,9 @@ } }, "node_modules/@sindresorhus/is": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", - "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.3.0.tgz", + "integrity": "sha512-wwOvh0eO3PiTEivGJWiZ+b946SlMSb4pe+y+Ur/4S87cwo09pYi+FWHHnbrM3W9W7cBYKDqQXcrFYjYUCOJUEQ==", "engines": { "node": ">=10" }, @@ -239,9 +282,9 @@ } }, "node_modules/@types/node": { - "version": "17.0.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz", - "integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==" + "version": "17.0.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.15.tgz", + "integrity": "sha512-zWt4SDDv1S9WRBNxLFxFRHxdD9tvH8f5/kg5/IaLFdnSNXsDY4eL3Q3XXN+VxUnWIhyVFDwcsmAprvwXoM/ClA==" }, "node_modules/@types/node-fetch": { "version": "2.5.12", @@ -282,14 +325,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.0.tgz", - "integrity": "sha512-qT4lr2jysDQBQOPsCCvpPUZHjbABoTJW8V9ZzIYKHMfppJtpdtzszDYsldwhFxlhvrp7aCHeXD1Lb9M1zhwWwQ==", + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.2.tgz", + "integrity": "sha512-4W/9lLuE+v27O/oe7hXJKjNtBLnZE8tQAFpapdxwSVHqtmIoPB1gph3+ahNwVuNL37BX7YQHyGF9Xv6XCnIX2Q==", "dev": true, "dependencies": { - "@typescript-eslint/experimental-utils": "5.9.0", - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/type-utils": "5.9.0", + "@typescript-eslint/scope-manager": "5.10.2", + "@typescript-eslint/type-utils": "5.10.2", + "@typescript-eslint/utils": "5.10.2", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -314,65 +357,16 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz", - "integrity": "sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz", - "integrity": "sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz", - "integrity": "sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.9.0", - "eslint-visitor-keys": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.9.0.tgz", - "integrity": "sha512-ZnLVjBrf26dn7ElyaSKa6uDhqwvAi4jBBmHK1VxuFGPRAxhdi18ubQYSGA7SRiFiES3q9JiBOBHEBStOFkwD2g==", + "node_modules/@typescript-eslint/parser": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.10.2.tgz", + "integrity": "sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/typescript-estree": "5.9.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@typescript-eslint/scope-manager": "5.10.2", + "@typescript-eslint/types": "5.10.2", + "@typescript-eslint/typescript-estree": "5.10.2", + "debug": "^4.3.2" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -383,58 +377,6 @@ }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz", - "integrity": "sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz", - "integrity": "sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.0.tgz", - "integrity": "sha512-kxo3xL2mB7XmiVZcECbaDwYCt3qFXz99tBSuVJR4L/sR7CJ+UNAPrYILILktGj1ppfZ/jNt/cWYbziJUlHl1Pw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" }, "peerDependenciesMeta": { "typescript": { @@ -442,14 +384,14 @@ } } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz", - "integrity": "sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.10.2.tgz", + "integrity": "sha512-39Tm6f4RoZoVUWBYr3ekS75TYgpr5Y+X0xLZxXqcZNDWZdJdYbKd3q2IR4V9y5NxxiPu/jxJ8XP7EgHiEQtFnw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.9.0", - "eslint-visitor-keys": "^3.0.0" + "@typescript-eslint/types": "5.10.2", + "@typescript-eslint/visitor-keys": "5.10.2" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -459,16 +401,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.9.0.tgz", - "integrity": "sha512-/6pOPz8yAxEt4PLzgbFRDpZmHnXCeZgPDrh/1DaVKOjvn/UPMlWhbx/gA96xRi2JxY1kBl2AmwVbyROUqys5xQ==", + "node_modules/@typescript-eslint/type-utils": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.10.2.tgz", + "integrity": "sha512-uRKSvw/Ccs5FYEoXW04Z5VfzF2iiZcx8Fu7DGIB7RHozuP0VbKNzP1KfZkHBTM75pCpsWxIthEH1B33dmGBKHw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/typescript-estree": "5.9.0", - "debug": "^4.3.2" + "@typescript-eslint/utils": "5.10.2", + "debug": "^4.3.2", + "tsutils": "^3.21.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -478,7 +419,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "*" }, "peerDependenciesMeta": { "typescript": { @@ -486,15 +427,11 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz", - "integrity": "sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==", + "node_modules/@typescript-eslint/types": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.10.2.tgz", + "integrity": "sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0" - }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -503,27 +440,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz", - "integrity": "sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.0.tgz", - "integrity": "sha512-kxo3xL2mB7XmiVZcECbaDwYCt3qFXz99tBSuVJR4L/sR7CJ+UNAPrYILILktGj1ppfZ/jNt/cWYbziJUlHl1Pw==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.2.tgz", + "integrity": "sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0", + "@typescript-eslint/types": "5.10.2", + "@typescript-eslint/visitor-keys": "5.10.2", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -543,14 +467,18 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz", - "integrity": "sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==", + "node_modules/@typescript-eslint/utils": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.10.2.tgz", + "integrity": "sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.9.0", - "eslint-visitor-keys": "^3.0.0" + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.10.2", + "@typescript-eslint/types": "5.10.2", + "@typescript-eslint/typescript-estree": "5.10.2", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -558,17 +486,19 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.9.0.tgz", - "integrity": "sha512-uVCb9dJXpBrK1071ri5aEW7ZHdDHAiqEjYznF3HSSvAJXyrkxGOw2Ejibz/q6BXdT8lea8CMI0CzKNFTNI6TEQ==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.2.tgz", + "integrity": "sha512-zHIhYGGGrFJvvyfwHk5M08C5B5K4bewkm+rrvNTKk1/S15YHR+SA/QUF8ZWscXSfEaB8Nn2puZj+iHcoxVOD/Q==", "dev": true, "dependencies": { - "@typescript-eslint/experimental-utils": "5.9.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" + "@typescript-eslint/types": "5.10.2", + "eslint-visitor-keys": "^3.0.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -576,26 +506,22 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, "node_modules/@zhycorp/eslint-config": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@zhycorp/eslint-config/-/eslint-config-6.0.2.tgz", - "integrity": "sha512-V0jtxese5hixzzz5UTA+hl/uKzYbkdc/EcGVc3RD2WipiayuPVgt+zTjNlQxS+xE4vUeHqLEFGIA+dBTD+1z+g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@zhycorp/eslint-config/-/eslint-config-7.1.0.tgz", + "integrity": "sha512-KtiTkDduw8l0ctbEp+bzXISLyRmiGvCblgl7lhW0L0pjw2kXmKar03cVH+v8ULLICw6vTSCn6k0O3jp+8zgwbg==", "dev": true, + "dependencies": { + "strip-json-comments": "^3.1.1" + }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": ">=5.0.0", - "@typescript-eslint/parser": ">=5.0.0", - "eslint": ">=8.0.0", - "typescript": ">=3.3.1 <4.5.0" + "@types/node": "^17.0.9", + "@typescript-eslint/eslint-plugin": ">=5.10.0", + "@typescript-eslint/parser": ">=5.10.0", + "eslint": ">=8.7.0", + "typescript": ">=3.3.1 <4.6.0" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -646,15 +572,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -717,6 +634,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/boolean": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.4.tgz", + "integrity": "sha512-3hx0kwU3uzG6ReQ3pnaFQPSktpBw6RHN3/ivDKEuU8g1XSfafowyvDnadjv1xp8IZqhtSukxlwv9bF6FhX8m0w==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -842,6 +764,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "devOptional": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -855,6 +778,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "optional": true, "engines": { "node": ">=8" } @@ -947,17 +871,17 @@ } }, "node_modules/discord-api-types": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", - "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==", + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz", + "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==", "engines": { "node": ">=12" } }, "node_modules/discord.js": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.5.0.tgz", - "integrity": "sha512-K+ZcB0f+wA1ZzDhz3hlaAi4Ap7jSvVEUZ+U29T4DMoiNNUv22F4vu1byrOq8GyyLLDFiZ3iSudea0MvSHu3fQA==", + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.6.0.tgz", + "integrity": "sha512-tXNR8zgsEPxPBvGk3AQjJ9ljIIC6/LOPjzKwpwz8Y1Q2X66Vi3ZqFgRHYwnHKC0jC0F+l4LzxlhmOJsBZDNg9g==", "dependencies": { "@discordjs/builders": "^0.11.0", "@discordjs/collection": "^0.4.0", @@ -974,14 +898,6 @@ "npm": ">=7.0.0" } }, - "node_modules/discord.js/node_modules/discord-api-types": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz", - "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==", - "engines": { - "node": ">=12" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -995,11 +911,11 @@ } }, "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", + "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/end-of-stream": { @@ -1010,18 +926,6 @@ "once": "^1.4.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1035,9 +939,9 @@ } }, "node_modules/eslint": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.6.0.tgz", - "integrity": "sha512-UvxdOJ7mXFlw7iuHZA4jmzPaUqIw54mZrv+XPYKNbKdLR0et4rf60lIZUU9kiNtnzzMzGWxMV+tQ7uG7JG8DPw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", + "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.0.5", @@ -1047,11 +951,10 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.0", "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", + "eslint-visitor-keys": "^3.2.0", "espree": "^9.3.0", "esquery": "^1.4.0", "esutils": "^2.0.2", @@ -1060,7 +963,7 @@ "functional-red-black-tree": "^1.0.1", "glob-parent": "^6.0.1", "globals": "^13.6.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", @@ -1071,9 +974,7 @@ "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "progress": "^2.0.0", "regexpp": "^3.2.0", - "semver": "^7.2.1", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0", @@ -1130,9 +1031,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", + "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1160,15 +1061,6 @@ "node": ">=4.0" } }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/espree": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", @@ -1247,6 +1139,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "optional": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -1269,6 +1162,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "optional": true, "engines": { "node": ">=10" }, @@ -1283,9 +1177,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -1295,7 +1189,7 @@ "micromatch": "^4.0.4" }, "engines": { - "node": ">=8" + "node": ">=8.6.0" } }, "node_modules/fast-glob/node_modules/glob-parent": { @@ -1322,6 +1216,17 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -1375,9 +1280,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.14.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz", - "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==", + "version": "1.14.7", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", + "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==", "funding": [ { "type": "individual", @@ -1479,16 +1384,16 @@ } }, "node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" }, "engines": { @@ -1552,24 +1457,25 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "optional": true, "engines": { "node": ">=10.17.0" } }, "node_modules/i18n": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.13.4.tgz", - "integrity": "sha512-GZnXWeA15jTi9gc1jfgrJcSrNYDg7qbJXSYMuibqPYb1ThORmGCeM+gL6LrDagYRHh87/q/D0jRSOhAfv6wAow==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.14.1.tgz", + "integrity": "sha512-Mu7JS17Fv52jwBJ6q7ssIBlYi+ARkeBTehTV/brlVH0x5u6YzsK8l9fANE8CqUjVBoSEdVa+2vYPB0RF/QF58g==", "dependencies": { + "@messageformat/core": "^3.0.0", "debug": "^4.3.3", + "fast-printf": "^1.6.9", "make-plural": "^7.0.0", "math-interval-parser": "^2.0.1", - "messageformat": "^2.3.0", - "mustache": "^4.2.0", - "sprintf-js": "^1.1.2" + "mustache": "^4.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/mashpie" @@ -1657,6 +1563,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "optional": true, "engines": { "node": ">=8" }, @@ -1668,6 +1575,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-unix/-/is-unix-2.0.1.tgz", "integrity": "sha512-RyKp5JtlRnfOvnKtfBMPLw9ocqDe1NlPQ8Bt+geVzKGfMnLGj8z/Y2HOmk/aMf47P4EbrEt9dN6YGTT1fx4mZA==", + "optional": true, "engines": { "node": ">= 12" } @@ -1675,7 +1583,8 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "devOptional": true }, "node_modules/js-yaml": { "version": "4.1.0", @@ -1707,9 +1616,9 @@ "dev": true }, "node_modules/keyv": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.4.tgz", - "integrity": "sha512-vqNHbAc8BBsxk+7QBYLW0Y219rWcClspR6WSeoHYKG5mnsSoOH+BL1pWq02DDCVdvvuUny5rkBlzMRzoqc+GIg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.5.tgz", + "integrity": "sha512-531pkGLqV3BMg0eDqqJFI0R1mkK1Nm5xIP2mM6keP5P8WfFtCkg2IOwplTUmlGoTgIg9yQYZ/kdihhz89XH3vA==", "dependencies": { "json-buffer": "3.0.1" } @@ -1774,7 +1683,8 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "optional": true }, "node_modules/merge2": { "version": "1.4.1", @@ -1785,38 +1695,6 @@ "node": ">= 8" } }, - "node_modules/messageformat": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/messageformat/-/messageformat-2.3.0.tgz", - "integrity": "sha512-uTzvsv0lTeQxYI2y1NPa1lItL5VRI8Gb93Y2K2ue5gBPyrbJxfDi/EYWxh2PKv5yO42AJeeqblS9MJSh/IEk4w==", - "deprecated": "Package renamed as '@messageformat/core', see messageformat.github.io for more details. 'messageformat' will eventually provide a polyfill for Intl.MessageFormat, once it's been defined by Unicode & ECMA.", - "dependencies": { - "make-plural": "^4.3.0", - "messageformat-formatters": "^2.0.1", - "messageformat-parser": "^4.1.2" - } - }, - "node_modules/messageformat-formatters": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/messageformat-formatters/-/messageformat-formatters-2.0.1.tgz", - "integrity": "sha512-E/lQRXhtHwGuiQjI7qxkLp8AHbMD5r2217XNe/SREbBlSawe0lOqsFb7rflZJmlQFSULNLIqlcjjsCPlB3m3Mg==" - }, - "node_modules/messageformat-parser": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-4.1.3.tgz", - "integrity": "sha512-2fU3XDCanRqeOCkn7R5zW5VQHWf+T3hH65SzuqRvjatBK7r4uyFa5mEX+k6F9Bd04LVM5G4/BHBTUJsOdW7uyg==" - }, - "node_modules/messageformat/node_modules/make-plural": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-4.3.0.tgz", - "integrity": "sha512-xTYd4JVHpSCW+aqDof6w/MebaMVNTVYBZhbB/vi513xXdiPT92JMVCo0Jq8W2UZnzYRFeVbQiQ+I25l13JuKvA==", - "bin": { - "make-plural": "bin/make-plural" - }, - "optionalDependencies": { - "minimist": "^1.2.0" - } - }, "node_modules/micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", @@ -1853,6 +1731,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "optional": true, "engines": { "node": ">=6" } @@ -1876,16 +1755,11 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "optional": true - }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -1893,6 +1767,11 @@ "node": ">=10" } }, + "node_modules/moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -1923,14 +1802,22 @@ "dev": true }, "node_modules/node-fetch": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", - "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "dependencies": { "whatwg-url": "^5.0.0" }, "engines": { "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/normalize-url": { @@ -1948,6 +1835,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "optional": true, "dependencies": { "path-key": "^3.0.0" }, @@ -1975,6 +1863,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "optional": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -2039,6 +1928,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "devOptional": true, "engines": { "node": ">=8" } @@ -2053,9 +1943,9 @@ } }, "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { "node": ">=8.6" @@ -2072,6 +1962,24 @@ "node": ">= 6" } }, + "node_modules/play-audio": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/play-audio/-/play-audio-0.4.9.tgz", + "integrity": "sha512-An88OAvbCcFZH00n9eq6+t2LmJUPJgBCz8ycKXdvUWQz3GcZ3U4o1ZsSHfVFIuoiKuovX+ue5gKNcfSs4ophew==", + "optional": true + }, + "node_modules/play-dl": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/play-dl/-/play-dl-1.8.1.tgz", + "integrity": "sha512-lUoxDJlPmZhcUv0LW1xg/uoQx0uxdGLppSDr8xM/oasfC/FUadA98JQzJMB6stri1ReFF96ftPQP+ZqhpVBVdQ==", + "optional": true, + "dependencies": { + "play-audio": "^0.4.3" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2106,15 +2014,6 @@ } } }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -2246,6 +2145,11 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==" + }, "node_modules/semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -2265,6 +2169,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "devOptional": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -2276,6 +2181,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "devOptional": true, "engines": { "node": ">=8" } @@ -2283,7 +2189,8 @@ "node_modules/signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", + "optional": true }, "node_modules/slash": { "version": "3.0.0", @@ -2302,11 +2209,6 @@ "axios": "^0.21.1" } }, - "node_modules/sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -2323,6 +2225,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "optional": true, "engines": { "node": ">=6" } @@ -2503,9 +2406,9 @@ } }, "node_modules/typescript": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", - "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==", + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -2548,6 +2451,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, "dependencies": { "isexe": "^2.0.0" }, @@ -2573,9 +2477,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/ws": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", - "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz", + "integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==", "engines": { "node": ">=10.0.0" }, @@ -2603,6 +2507,7 @@ "resolved": "https://registry.npmjs.org/youtube-dl-exec/-/youtube-dl-exec-2.0.2.tgz", "integrity": "sha512-sRRjq+eifuqloLMb3OWdpIMZzeYf19iv+4ZFICZYPOeZR2AkawOOve9uCUtmRa1gc6pFBkh4+MMgPiIJUwk+Sg==", "hasInstallScript": true, + "optional": true, "dependencies": { "dargs": "~7.0.0", "execa": "~5.1.0", @@ -2615,9 +2520,9 @@ } }, "node_modules/youtubei": { - "version": "0.0.1-rc.27", - "resolved": "https://registry.npmjs.org/youtubei/-/youtubei-0.0.1-rc.27.tgz", - "integrity": "sha512-4pbKr6F9RpWQ/XLstD9KNTBd5dGkzXNm8sx2ooQFleCka/wknZQhu9HEoGbvJMb4izvfSs2e5TAAK+l6fYwxJQ==" + "version": "0.0.1-rc.28", + "resolved": "https://registry.npmjs.org/youtubei/-/youtubei-0.0.1-rc.28.tgz", + "integrity": "sha512-oWR1hK0C/TN7i34MrMAT/MGfTjP52LYuP13VD2rhxTO6Ia+jRw+bI+/gn65h6qxSxg7QC8LleSiNGWwEWkw4FA==" }, "node_modules/zod": { "version": "3.11.6", @@ -2639,13 +2544,6 @@ "ts-mixer": "^6.0.0", "tslib": "^2.3.1", "zod": "^3.11.6" - }, - "dependencies": { - "discord-api-types": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz", - "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==" - } } }, "@discordjs/collection": { @@ -2654,16 +2552,16 @@ "integrity": "sha512-zmjq+l/rV35kE6zRrwe8BHqV78JvIh2ybJeZavBi5NySjWXqN3hmmAKg7kYMMXSeiWtSsMoZ/+MQi0DiQWy2lw==" }, "@discordjs/voice": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.7.5.tgz", - "integrity": "sha512-lUk+CmIXNKslT6DkC9IF9rpsqhzlTiedauUCPBzepjd4XWxwBZiyVIzR6QpbAirxkAwCoAbbje+3Ho71PGLEAw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.8.0.tgz", + "integrity": "sha512-o0JfVLMs3eLjUzPf6oxMydEeum40I7xzfUc66SLN+RrKpSAsTbngf5qnCF53nm+KDNSvrwg1AZqNm4LEAdxJIA==", "requires": { "@types/ws": "^8.2.0", - "discord-api-types": "^0.24.0", + "discord-api-types": "^0.26.1", "prism-media": "^1.3.2", "tiny-typed-emitter": "^2.1.0", "tslib": "^2.3.1", - "ws": "^8.2.3" + "ws": "^8.4.2" } }, "@eslint/eslintrc": { @@ -2708,6 +2606,59 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@messageformat/core": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@messageformat/core/-/core-3.0.0.tgz", + "integrity": "sha512-mzMCyADGweNmnMwV/xjKxtXtkXJNVcK5ATOHx4Q0GVr2Z3++in1VfrB/y6jM43nleK27tFO0Y/9pds5vxWqDvQ==", + "requires": { + "@messageformat/date-skeleton": "^1.0.0", + "@messageformat/number-skeleton": "^1.0.0", + "@messageformat/parser": "^5.0.0", + "@messageformat/runtime": "^3.0.0", + "make-plural": "^6.2.1", + "safe-identifier": "^0.4.1" + }, + "dependencies": { + "make-plural": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-6.2.2.tgz", + "integrity": "sha512-8iTuFioatnTTmb/YJjywkVIHLjcwkFD9Ms0JpxjEm9Mo8eQYkh1z+55dwv4yc1jQ8ftVBxWQbihvZL1DfzGGWA==" + } + } + }, + "@messageformat/date-skeleton": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@messageformat/date-skeleton/-/date-skeleton-1.0.0.tgz", + "integrity": "sha512-vvj5Sd3VyXUHGbYpiFsPsSQ8pkdUM9vrR/NUbyP6ga3UqJH4p9eCwzfwaCAZatZMYMTyiKG/8QbUyGKHeTZ5kw==" + }, + "@messageformat/number-skeleton": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@messageformat/number-skeleton/-/number-skeleton-1.0.0.tgz", + "integrity": "sha512-Pe1HX/VG0q7tclM/ri85I4FKYd7Uc3gluSZbRaK1+jcXdT9Biw2hLAKyMsiz2tM6zLiK1xX+K0NMDO4RIstQig==" + }, + "@messageformat/parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.0.0.tgz", + "integrity": "sha512-WiDKhi8F0zQaFU8cXgqq69eYFarCnTVxKcvhAONufKf0oUxbqLMW6JX6rV4Hqh+BEQWGyKKKHY4g1XA6bCLylA==", + "requires": { + "moo": "^0.5.1" + } + }, + "@messageformat/runtime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@messageformat/runtime/-/runtime-3.0.0.tgz", + "integrity": "sha512-boV0oH8jnJM/qoynQKnIbnKK5M7JPpKM0y9QUB9nQMMt16qSlgi5FfUo8usgoq6wEYqxDmIqtUfBewcj2VP+yQ==", + "requires": { + "make-plural": "^6.2.1" + }, + "dependencies": { + "make-plural": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-6.2.2.tgz", + "integrity": "sha512-8iTuFioatnTTmb/YJjywkVIHLjcwkFD9Ms0JpxjEm9Mo8eQYkh1z+55dwv4yc1jQ8ftVBxWQbihvZL1DfzGGWA==" + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2740,9 +2691,9 @@ "integrity": "sha512-CbXaGwwlEMq+l1TRu01FJCvySJ1CEFKFclHT48nIfNeZXaAAmmwwy7scUKmYHPUa3GhoMp6Qr1B3eAJux6XgOQ==" }, "@sindresorhus/is": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", - "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==" + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.3.0.tgz", + "integrity": "sha512-wwOvh0eO3PiTEivGJWiZ+b946SlMSb4pe+y+Ur/4S87cwo09pYi+FWHHnbrM3W9W7cBYKDqQXcrFYjYUCOJUEQ==" }, "@szmarczak/http-timer": { "version": "4.0.6", @@ -2789,9 +2740,9 @@ } }, "@types/node": { - "version": "17.0.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz", - "integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==" + "version": "17.0.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.15.tgz", + "integrity": "sha512-zWt4SDDv1S9WRBNxLFxFRHxdD9tvH8f5/kg5/IaLFdnSNXsDY4eL3Q3XXN+VxUnWIhyVFDwcsmAprvwXoM/ClA==" }, "@types/node-fetch": { "version": "2.5.12", @@ -2831,179 +2782,108 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.0.tgz", - "integrity": "sha512-qT4lr2jysDQBQOPsCCvpPUZHjbABoTJW8V9ZzIYKHMfppJtpdtzszDYsldwhFxlhvrp7aCHeXD1Lb9M1zhwWwQ==", + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.2.tgz", + "integrity": "sha512-4W/9lLuE+v27O/oe7hXJKjNtBLnZE8tQAFpapdxwSVHqtmIoPB1gph3+ahNwVuNL37BX7YQHyGF9Xv6XCnIX2Q==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "5.9.0", - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/type-utils": "5.9.0", + "@typescript-eslint/scope-manager": "5.10.2", + "@typescript-eslint/type-utils": "5.10.2", + "@typescript-eslint/utils": "5.10.2", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", "regexpp": "^3.2.0", "semver": "^7.3.5", "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz", - "integrity": "sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0" - } - }, - "@typescript-eslint/types": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz", - "integrity": "sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==", - "dev": true - }, - "@typescript-eslint/visitor-keys": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz", - "integrity": "sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.9.0", - "eslint-visitor-keys": "^3.0.0" - } - } } }, - "@typescript-eslint/experimental-utils": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.9.0.tgz", - "integrity": "sha512-ZnLVjBrf26dn7ElyaSKa6uDhqwvAi4jBBmHK1VxuFGPRAxhdi18ubQYSGA7SRiFiES3q9JiBOBHEBStOFkwD2g==", + "@typescript-eslint/parser": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.10.2.tgz", + "integrity": "sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg==", "dev": true, "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/typescript-estree": "5.9.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz", - "integrity": "sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0" - } - }, - "@typescript-eslint/types": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz", - "integrity": "sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.0.tgz", - "integrity": "sha512-kxo3xL2mB7XmiVZcECbaDwYCt3qFXz99tBSuVJR4L/sR7CJ+UNAPrYILILktGj1ppfZ/jNt/cWYbziJUlHl1Pw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz", - "integrity": "sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.9.0", - "eslint-visitor-keys": "^3.0.0" - } - } + "@typescript-eslint/scope-manager": "5.10.2", + "@typescript-eslint/types": "5.10.2", + "@typescript-eslint/typescript-estree": "5.10.2", + "debug": "^4.3.2" } }, - "@typescript-eslint/parser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.9.0.tgz", - "integrity": "sha512-/6pOPz8yAxEt4PLzgbFRDpZmHnXCeZgPDrh/1DaVKOjvn/UPMlWhbx/gA96xRi2JxY1kBl2AmwVbyROUqys5xQ==", + "@typescript-eslint/scope-manager": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.10.2.tgz", + "integrity": "sha512-39Tm6f4RoZoVUWBYr3ekS75TYgpr5Y+X0xLZxXqcZNDWZdJdYbKd3q2IR4V9y5NxxiPu/jxJ8XP7EgHiEQtFnw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/typescript-estree": "5.9.0", - "debug": "^4.3.2" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz", - "integrity": "sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0" - } - }, - "@typescript-eslint/types": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz", - "integrity": "sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.0.tgz", - "integrity": "sha512-kxo3xL2mB7XmiVZcECbaDwYCt3qFXz99tBSuVJR4L/sR7CJ+UNAPrYILILktGj1ppfZ/jNt/cWYbziJUlHl1Pw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz", - "integrity": "sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.9.0", - "eslint-visitor-keys": "^3.0.0" - } - } + "@typescript-eslint/types": "5.10.2", + "@typescript-eslint/visitor-keys": "5.10.2" } }, "@typescript-eslint/type-utils": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.9.0.tgz", - "integrity": "sha512-uVCb9dJXpBrK1071ri5aEW7ZHdDHAiqEjYznF3HSSvAJXyrkxGOw2Ejibz/q6BXdT8lea8CMI0CzKNFTNI6TEQ==", + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.10.2.tgz", + "integrity": "sha512-uRKSvw/Ccs5FYEoXW04Z5VfzF2iiZcx8Fu7DGIB7RHozuP0VbKNzP1KfZkHBTM75pCpsWxIthEH1B33dmGBKHw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "5.9.0", + "@typescript-eslint/utils": "5.10.2", "debug": "^4.3.2", "tsutils": "^3.21.0" } }, + "@typescript-eslint/types": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.10.2.tgz", + "integrity": "sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.2.tgz", + "integrity": "sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.10.2", + "@typescript-eslint/visitor-keys": "5.10.2", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.10.2.tgz", + "integrity": "sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.10.2", + "@typescript-eslint/types": "5.10.2", + "@typescript-eslint/typescript-estree": "5.10.2", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.2.tgz", + "integrity": "sha512-zHIhYGGGrFJvvyfwHk5M08C5B5K4bewkm+rrvNTKk1/S15YHR+SA/QUF8ZWscXSfEaB8Nn2puZj+iHcoxVOD/Q==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.10.2", + "eslint-visitor-keys": "^3.0.0" + } + }, "@zhycorp/eslint-config": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@zhycorp/eslint-config/-/eslint-config-6.0.2.tgz", - "integrity": "sha512-V0jtxese5hixzzz5UTA+hl/uKzYbkdc/EcGVc3RD2WipiayuPVgt+zTjNlQxS+xE4vUeHqLEFGIA+dBTD+1z+g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@zhycorp/eslint-config/-/eslint-config-7.1.0.tgz", + "integrity": "sha512-KtiTkDduw8l0ctbEp+bzXISLyRmiGvCblgl7lhW0L0pjw2kXmKar03cVH+v8ULLICw6vTSCn6k0O3jp+8zgwbg==", "dev": true, - "requires": {} + "requires": { + "strip-json-comments": "^3.1.1" + } }, "acorn": { "version": "8.7.0", @@ -3030,12 +2910,6 @@ "uri-js": "^4.2.2" } }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -3086,6 +2960,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "boolean": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.4.tgz", + "integrity": "sha512-3hx0kwU3uzG6ReQ3pnaFQPSktpBw6RHN3/ivDKEuU8g1XSfafowyvDnadjv1xp8IZqhtSukxlwv9bF6FhX8m0w==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3184,6 +3063,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "devOptional": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3193,7 +3073,8 @@ "dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==" + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "optional": true }, "date-fns": { "version": "2.28.0", @@ -3249,14 +3130,14 @@ } }, "discord-api-types": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", - "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==" + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz", + "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==" }, "discord.js": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.5.0.tgz", - "integrity": "sha512-K+ZcB0f+wA1ZzDhz3hlaAi4Ap7jSvVEUZ+U29T4DMoiNNUv22F4vu1byrOq8GyyLLDFiZ3iSudea0MvSHu3fQA==", + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.6.0.tgz", + "integrity": "sha512-tXNR8zgsEPxPBvGk3AQjJ9ljIIC6/LOPjzKwpwz8Y1Q2X66Vi3ZqFgRHYwnHKC0jC0F+l4LzxlhmOJsBZDNg9g==", "requires": { "@discordjs/builders": "^0.11.0", "@discordjs/collection": "^0.4.0", @@ -3267,13 +3148,6 @@ "form-data": "^4.0.0", "node-fetch": "^2.6.1", "ws": "^8.4.0" - }, - "dependencies": { - "discord-api-types": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz", - "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==" - } } }, "doctrine": { @@ -3286,9 +3160,9 @@ } }, "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", + "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==" }, "end-of-stream": { "version": "1.4.4", @@ -3298,15 +3172,6 @@ "once": "^1.4.0" } }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -3314,9 +3179,9 @@ "dev": true }, "eslint": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.6.0.tgz", - "integrity": "sha512-UvxdOJ7mXFlw7iuHZA4jmzPaUqIw54mZrv+XPYKNbKdLR0et4rf60lIZUU9kiNtnzzMzGWxMV+tQ7uG7JG8DPw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", + "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", "dev": true, "requires": { "@eslint/eslintrc": "^1.0.5", @@ -3326,11 +3191,10 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.0", "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", + "eslint-visitor-keys": "^3.2.0", "espree": "^9.3.0", "esquery": "^1.4.0", "esutils": "^2.0.2", @@ -3339,7 +3203,7 @@ "functional-red-black-tree": "^1.0.1", "glob-parent": "^6.0.1", "globals": "^13.6.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", @@ -3350,9 +3214,7 @@ "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "progress": "^2.0.0", "regexpp": "^3.2.0", - "semver": "^7.2.1", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0", @@ -3374,12 +3236,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true } } }, @@ -3411,9 +3267,9 @@ } }, "eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", + "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", "dev": true }, "espree": { @@ -3477,6 +3333,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "optional": true, "requires": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -3492,7 +3349,8 @@ "get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "optional": true } } }, @@ -3503,9 +3361,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -3538,6 +3396,14 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "requires": { + "boolean": "^3.1.4" + } + }, "fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -3582,9 +3448,9 @@ "dev": true }, "follow-redirects": { - "version": "1.14.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz", - "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==" + "version": "1.14.7", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", + "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==" }, "form-data": { "version": "4.0.0", @@ -3648,16 +3514,16 @@ } }, "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" } }, @@ -3702,19 +3568,20 @@ "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "optional": true }, "i18n": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.13.4.tgz", - "integrity": "sha512-GZnXWeA15jTi9gc1jfgrJcSrNYDg7qbJXSYMuibqPYb1ThORmGCeM+gL6LrDagYRHh87/q/D0jRSOhAfv6wAow==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.14.1.tgz", + "integrity": "sha512-Mu7JS17Fv52jwBJ6q7ssIBlYi+ARkeBTehTV/brlVH0x5u6YzsK8l9fANE8CqUjVBoSEdVa+2vYPB0RF/QF58g==", "requires": { + "@messageformat/core": "^3.0.0", "debug": "^4.3.3", + "fast-printf": "^1.6.9", "make-plural": "^7.0.0", "math-interval-parser": "^2.0.1", - "messageformat": "^2.3.0", - "mustache": "^4.2.0", - "sprintf-js": "^1.1.2" + "mustache": "^4.2.0" } }, "ignore": { @@ -3777,17 +3644,20 @@ "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "optional": true }, "is-unix": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-unix/-/is-unix-2.0.1.tgz", - "integrity": "sha512-RyKp5JtlRnfOvnKtfBMPLw9ocqDe1NlPQ8Bt+geVzKGfMnLGj8z/Y2HOmk/aMf47P4EbrEt9dN6YGTT1fx4mZA==" + "integrity": "sha512-RyKp5JtlRnfOvnKtfBMPLw9ocqDe1NlPQ8Bt+geVzKGfMnLGj8z/Y2HOmk/aMf47P4EbrEt9dN6YGTT1fx4mZA==", + "optional": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "devOptional": true }, "js-yaml": { "version": "4.1.0", @@ -3816,9 +3686,9 @@ "dev": true }, "keyv": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.4.tgz", - "integrity": "sha512-vqNHbAc8BBsxk+7QBYLW0Y219rWcClspR6WSeoHYKG5mnsSoOH+BL1pWq02DDCVdvvuUny5rkBlzMRzoqc+GIg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.5.tgz", + "integrity": "sha512-531pkGLqV3BMg0eDqqJFI0R1mkK1Nm5xIP2mM6keP5P8WfFtCkg2IOwplTUmlGoTgIg9yQYZ/kdihhz89XH3vA==", "requires": { "json-buffer": "3.0.1" } @@ -3871,7 +3741,8 @@ "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "optional": true }, "merge2": { "version": "1.4.1", @@ -3879,36 +3750,6 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, - "messageformat": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/messageformat/-/messageformat-2.3.0.tgz", - "integrity": "sha512-uTzvsv0lTeQxYI2y1NPa1lItL5VRI8Gb93Y2K2ue5gBPyrbJxfDi/EYWxh2PKv5yO42AJeeqblS9MJSh/IEk4w==", - "requires": { - "make-plural": "^4.3.0", - "messageformat-formatters": "^2.0.1", - "messageformat-parser": "^4.1.2" - }, - "dependencies": { - "make-plural": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-4.3.0.tgz", - "integrity": "sha512-xTYd4JVHpSCW+aqDof6w/MebaMVNTVYBZhbB/vi513xXdiPT92JMVCo0Jq8W2UZnzYRFeVbQiQ+I25l13JuKvA==", - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "messageformat-formatters": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/messageformat-formatters/-/messageformat-formatters-2.0.1.tgz", - "integrity": "sha512-E/lQRXhtHwGuiQjI7qxkLp8AHbMD5r2217XNe/SREbBlSawe0lOqsFb7rflZJmlQFSULNLIqlcjjsCPlB3m3Mg==" - }, - "messageformat-parser": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-4.1.3.tgz", - "integrity": "sha512-2fU3XDCanRqeOCkn7R5zW5VQHWf+T3hH65SzuqRvjatBK7r4uyFa5mEX+k6F9Bd04LVM5G4/BHBTUJsOdW7uyg==" - }, "micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", @@ -3935,7 +3776,8 @@ "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "optional": true }, "mimic-response": { "version": "1.0.1", @@ -3950,16 +3792,16 @@ "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "optional": true - }, "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true + }, + "moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" }, "ms": { "version": "2.1.2", @@ -3988,9 +3830,9 @@ "dev": true }, "node-fetch": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", - "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "requires": { "whatwg-url": "^5.0.0" } @@ -4004,6 +3846,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "optional": true, "requires": { "path-key": "^3.0.0" } @@ -4025,6 +3868,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "optional": true, "requires": { "mimic-fn": "^2.1.0" } @@ -4070,7 +3914,8 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "devOptional": true }, "path-type": { "version": "4.0.0", @@ -4079,9 +3924,9 @@ "dev": true }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "pirates": { @@ -4089,6 +3934,21 @@ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz", "integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==" }, + "play-audio": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/play-audio/-/play-audio-0.4.9.tgz", + "integrity": "sha512-An88OAvbCcFZH00n9eq6+t2LmJUPJgBCz8ycKXdvUWQz3GcZ3U4o1ZsSHfVFIuoiKuovX+ue5gKNcfSs4ophew==", + "optional": true + }, + "play-dl": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/play-dl/-/play-dl-1.8.1.tgz", + "integrity": "sha512-lUoxDJlPmZhcUv0LW1xg/uoQx0uxdGLppSDr8xM/oasfC/FUadA98JQzJMB6stri1ReFF96ftPQP+ZqhpVBVdQ==", + "optional": true, + "requires": { + "play-audio": "^0.4.3" + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4101,12 +3961,6 @@ "integrity": "sha512-L6UsGHcT6i4wrQhFF1aPK+MNYgjRqR2tUoIqEY+CG1NqVkMjPRKzS37j9f8GiYPlD6wG9ruBj+q5Ax+bH8Ik1g==", "requires": {} }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -4182,6 +4036,11 @@ "queue-microtask": "^1.2.2" } }, + "safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==" + }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -4195,6 +4054,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "devOptional": true, "requires": { "shebang-regex": "^3.0.0" } @@ -4202,12 +4062,14 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "devOptional": true }, "signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", + "optional": true }, "slash": { "version": "3.0.0", @@ -4223,11 +4085,6 @@ "axios": "^0.21.1" } }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" - }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4240,7 +4097,8 @@ "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "optional": true }, "strip-json-comments": { "version": "3.1.1", @@ -4379,9 +4237,9 @@ "dev": true }, "typescript": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", - "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==", + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", "dev": true }, "uri-js": { @@ -4417,6 +4275,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, "requires": { "isexe": "^2.0.0" } @@ -4433,9 +4292,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", - "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz", + "integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==", "requires": {} }, "yallist": { @@ -4448,6 +4307,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/youtube-dl-exec/-/youtube-dl-exec-2.0.2.tgz", "integrity": "sha512-sRRjq+eifuqloLMb3OWdpIMZzeYf19iv+4ZFICZYPOeZR2AkawOOve9uCUtmRa1gc6pFBkh4+MMgPiIJUwk+Sg==", + "optional": true, "requires": { "dargs": "~7.0.0", "execa": "~5.1.0", @@ -4457,9 +4317,9 @@ } }, "youtubei": { - "version": "0.0.1-rc.27", - "resolved": "https://registry.npmjs.org/youtubei/-/youtubei-0.0.1-rc.27.tgz", - "integrity": "sha512-4pbKr6F9RpWQ/XLstD9KNTBd5dGkzXNm8sx2ooQFleCka/wknZQhu9HEoGbvJMb4izvfSs2e5TAAK+l6fYwxJQ==" + "version": "0.0.1-rc.28", + "resolved": "https://registry.npmjs.org/youtubei/-/youtubei-0.0.1-rc.28.tgz", + "integrity": "sha512-oWR1hK0C/TN7i34MrMAT/MGfTjP52LYuP13VD2rhxTO6Ia+jRw+bI+/gn65h6qxSxg7QC8LleSiNGWwEWkw4FA==" }, "zod": { "version": "3.11.6", diff --git a/package.json b/package.json index f4b33359a..a4322eb3d 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { - "name": "disc-11", - "version": "2.3.0", + "name": "rawon", + "version": "2.4.0", "private": true, - "description": "A dedicated open-source Discord bot for Zhycorp based from our Discord bot template with more features. Easy to use, and with no coding required.", - "repository": "https://github.com/zhycorp/disc-11", + "description": "A dedicated open-sourced Discord bot with many features of utilization. Easy to use, and with no coding required.", + "repository": "https://github.com/mzrtamp/rawon", "license": "BSD-3-Clause", - "author": "Zhycorp ", + "author": "mzrtamp ", "main": "index.js", "scripts": { "build": "npm run lint && npm run compile", @@ -13,40 +13,46 @@ "tscompile": "tsc --build tsconfig.json", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --ext .ts --fix", - "start": "node ." + "start": "node -r dotenv/config ." }, "eslintConfig": { "parserOptions": { "project": "./tsconfig.json" }, - "extends": "@zhycorp/eslint-config/typescript" + "extends": "@zhycorp/eslint-config/typescript", + "rules": { + "@typescript-eslint/no-extra-parens": "off" + } }, "dependencies": { - "@discordjs/voice": "^0.7.5", + "@discordjs/voice": "^0.8.0", "date-fns": "^2.28.0", - "discord.js": "^13.5.0", - "dotenv": "^10.0.0", + "discord.js": "^13.6.0", + "dotenv": "^16.0.0", "got": "^11.8.3", - "i18n": "0.13.4", + "i18n": "0.14.1", "opusscript": "^0.0.8", "prism-media": "^1.3.2", "soundcloud.ts": "^0.4.1", "sucrase": "^3.20.3", "tslib": "^2.3.1", "tweetnacl": "^1.0.3", - "youtube-dl-exec": "^2.0.2", - "youtubei": "^0.0.1-rc.23" + "youtubei": "^0.0.1-rc.28" }, "devDependencies": { "@types/i18n": "^0.13.2", - "@types/node": "^17.0.8", - "@typescript-eslint/eslint-plugin": "^5.9.0", - "@typescript-eslint/parser": "^5.9.0", - "@zhycorp/eslint-config": "^6.0.2", - "eslint": "^8.5.0", - "typescript": "^4.5.4" + "@types/node": "^17.0.15", + "@typescript-eslint/eslint-plugin": "^5.10.2", + "@typescript-eslint/parser": "^5.10.2", + "@zhycorp/eslint-config": "^7.1.0", + "eslint": "^8.8.0", + "typescript": "^4.5.5" }, "engines": { "node": ">=16.6.0" + }, + "optionalDependencies": { + "play-dl": "^1.8.1", + "youtube-dl-exec": "^2.0.2" } } diff --git a/src/bot.ts b/src/bot.ts index c77e5f847..74e79f54d 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -1,8 +1,8 @@ import { NoStackError } from "./utils/NoStackError"; import { clientOptions } from "./config"; -import { Disc } from "./structures/Disc"; +import { Rawon } from "./structures/Rawon"; -const client = new Disc(clientOptions); +const client = new Rawon(clientOptions); process.on("exit", code => { client.logger.info(`NodeJS process exited with code ${code}`); @@ -15,7 +15,7 @@ process.on("uncaughtException", err => { process.on("unhandledRejection", reason => { client.logger.error("UNHANDLED_REJECTION:", (reason as Error).stack ? reason : new NoStackError(reason as string)); }); -process.on("warning", client.logger.warn); +process.on("warning", (...args) => client.logger.warn(...args)); client.build() .catch(e => client.logger.error("PROMISE_ERR:", e)); diff --git a/src/commands/developers/EvalCommand.ts b/src/commands/developers/EvalCommand.ts index a1f7f7c41..b5379b8cf 100644 --- a/src/commands/developers/EvalCommand.ts +++ b/src/commands/developers/EvalCommand.ts @@ -18,7 +18,7 @@ export class EvalCommand extends BaseCommand { }); } - public async execute(ctx: CommandContext): Promise { + public async execute(ctx: CommandContext): Promise { const msg = ctx; const client = this.client; @@ -27,7 +27,7 @@ export class EvalCommand extends BaseCommand { try { let code = ctx.args.join(" "); - if (!code) return ctx.send({ embeds: [createEmbed("error", i18n.__("commands.developers.eval.noCode"), true)] }); + if (!code) return await ctx.send({ embeds: [createEmbed("error", i18n.__("commands.developers.eval.noCode"), true)] }); let evaled; if (code.includes("--silent") && code.includes("--async")) { code = code.replace("--async", "").replace("--silent", ""); @@ -75,10 +75,11 @@ export class EvalCommand extends BaseCommand { reference: ctx.author.id }, embeds: [embed] - }).catch(e => this.client.logger.error("PROMISE_ERR:", e)); + }).catch(er => this.client.logger.error("PROMISE_ERR:", er)); } } + // eslint-disable-next-line class-methods-use-this private clean(text: string): string { if (typeof text === "string") { return text @@ -90,10 +91,10 @@ export class EvalCommand extends BaseCommand { } private async hastebin(text: string): Promise { - const result = await this.client.request.post("https://bin.zhycorp.net/documents", { + const result = await this.client.request.post("https://bin.tiramitzu.me/documents", { body: text }).json<{ key: string }>(); - return `https://bin.zhycorp.net/${result.key}`; + return `https://bin.tiramitzu.me/${result.key}`; } } diff --git a/src/commands/general/AboutCommand.ts b/src/commands/general/AboutCommand.ts index f208df705..b39b05cd7 100644 --- a/src/commands/general/AboutCommand.ts +++ b/src/commands/general/AboutCommand.ts @@ -3,6 +3,7 @@ import { version as BotVersion } from "../../../package.json"; import { BaseCommand } from "../../structures/BaseCommand"; import { createEmbed } from "../../utils/createEmbed"; import { formatMS } from "../../utils/formatMS"; +import { createTable } from "../../utils/functions/createTable"; import i18n from "../../config"; import { version as DJSVersion } from "discord.js"; import { uptime } from "os"; @@ -31,13 +32,9 @@ export class AboutCommand extends BaseCommand { [i18n.__("commands.general.about.ffmpegVersionString"), this.client.utils.getFFmpegVersion()], [i18n.__("commands.general.about.botVersionString"), BotVersion], [""], - [i18n.__("commands.general.about.sourceCodeString"), "https://github.com/zhycorp/disc-11"] + [i18n.__("commands.general.about.sourceCodeString"), "https://github.com/mzrtamp/rawon"] ]; - const value = values.map(x => `${x.map((y, i) => { - const sortingArr = [...values]; - - return `${y}${" ".repeat(sortingArr.sort((a, b) => (b[i] ?? "").length - (a[i] ?? "").length)[0][i].length - y.length)}`; - }).join(" :: ")}`).join("\n"); + const value = createTable(values); void ctx.reply({ embeds: [ @@ -47,7 +44,7 @@ ${value} \`\`\` `) .setAuthor({ - name: i18n.__mf("commands.general.about.aboutFooter", { botname: this.client.user?.username as string }) + name: i18n.__mf("commands.general.about.aboutFooter", { botname: this.client.user?.username ?? "Unknown" }) }) ] }).catch(e => this.client.logger.error("ABOUT_CMD_ERR:", e)); diff --git a/src/commands/general/HelpCommand.ts b/src/commands/general/HelpCommand.ts index 0f41a22be..00cd25b1b 100644 --- a/src/commands/general/HelpCommand.ts +++ b/src/commands/general/HelpCommand.ts @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-unnecessary-condition */ +/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain, @typescript-eslint/no-unnecessary-condition */ import { CommandContext } from "../../structures/CommandContext"; import { BaseCommand } from "../../structures/BaseCommand"; import { createEmbed } from "../../utils/createEmbed"; @@ -9,15 +9,15 @@ export class HelpCommand extends BaseCommand { private readonly listEmbed = createEmbed("info") .setAuthor({ name: i18n.__mf("commands.general.help.authorString", { username: this.client.user!.username }), - iconURL: this.client.user?.displayAvatarURL() as string + iconURL: this.client.user?.displayAvatarURL()! }) .setFooter({ text: i18n.__mf("commands.general.help.footerString", { prefix: this.client.config.mainPrefix }), - iconURL: "https://raw.githubusercontent.com/zhycorp/disc-11/main/.github/images/info.png" + iconURL: "https://raw.githubusercontent.com/mzrtamp/rawon/main/.github/images/info.png" }); private readonly infoEmbed = createEmbed("info") - .setThumbnail("https://raw.githubusercontent.com/zhycorp/disc-11/main/.github/images/question_mark.png"); + .setThumbnail("https://raw.githubusercontent.com/mzrtamp/rawon/main/.github/images/question_mark.png"); public constructor(client: BaseCommand["client"]) { super(client, { @@ -37,10 +37,10 @@ export class HelpCommand extends BaseCommand { }); } - public async execute(ctx: CommandContext): Promise { + public async execute(ctx: CommandContext): Promise { if (ctx.isInteraction() && !ctx.deferred) await ctx.deferReply(); this.infoEmbed.fields = []; - const val = ctx.args[0] ?? ctx.options?.getString("command") ?? (ctx.additionalArgs.get("values") ? ctx.additionalArgs.get("values")[0] : null); + const val = ctx.args[0] ?? ctx.options?.getString("command") ?? (ctx.additionalArgs.get("values") ? (ctx.additionalArgs.get("values") as string[])[0] : null); const command = this.client.commands.get(val) ?? this.client.commands.get(this.client.commands.aliases.get(val)!); if (!val) { const embed = this.listEmbed @@ -53,9 +53,10 @@ export class HelpCommand extends BaseCommand { if (category.hide && !isDev) continue; embed.addField(`**${category.name}**`, cmds.join(", ")); } - return ctx.send({ embeds: [embed] }, "editReply").catch(e => { + ctx.send({ embeds: [embed] }, "editReply").catch(e => { this.client.logger.error("PROMISE_ERR:", e); }); + return; } if (!command) { const matching = this.generateSelectMenu(val, ctx.author.id); @@ -83,7 +84,7 @@ export class HelpCommand extends BaseCommand { } // Disable selection menu if (ctx.isSelectMenu()) { - const channel = await ctx.channel; + const channel = ctx.channel; const msg = await channel!.messages.fetch((ctx.context as SelectMenuInteraction).message.id).catch(() => undefined); if (msg !== undefined) { const selection = msg.components[0].components.find(x => x.type === "SELECT_MENU"); @@ -97,15 +98,15 @@ export class HelpCommand extends BaseCommand { this.infoEmbed .setAuthor({ name: i18n.__mf("commands.general.help.commandDetailTitle", { username: this.client.user!.username, command: command.meta.name }), - iconURL: this.client.user?.displayAvatarURL() as string + iconURL: this.client.user?.displayAvatarURL()! }) .addField(i18n.__("commands.general.help.nameString"), `**\`${command.meta.name}\`**`, false) .addField(i18n.__("commands.general.help.descriptionString"), `${command.meta.description!}`, true) - .addField(i18n.__("commands.general.help.aliasesString"), Number(command.meta.aliases?.length) > 0 ? command.meta.aliases?.map(c => `**\`${c}\`**`).join(", ") as string : "None.", false) + .addField(i18n.__("commands.general.help.aliasesString"), Number(command.meta.aliases?.length) > 0 ? command.meta.aliases?.map(c => `**\`${c}\`**`).join(", ")! : "None.", false) .addField(i18n.__("commands.general.help.usageString"), `**\`${command.meta.usage!.replace(/{prefix}/g, this.client.config.mainPrefix)}\`**`, true) .setFooter({ text: i18n.__mf("commands.general.help.commandUsageFooter", { devOnly: command.meta.devOnly ? "(developer-only command)" : "" }), - iconURL: "https://raw.githubusercontent.com/zhycorp/disc-11/main/.github/images/info.png" + iconURL: "https://raw.githubusercontent.com/mzrtamp/rawon/.github/images/info.png" }) ] }, "editReply"); diff --git a/src/commands/general/InviteCommand.ts b/src/commands/general/InviteCommand.ts index 198a9470d..e49e61826 100644 --- a/src/commands/general/InviteCommand.ts +++ b/src/commands/general/InviteCommand.ts @@ -18,7 +18,7 @@ export class InviteCommand extends BaseCommand { } public async execute(ctx: CommandContext): Promise { - const invite = await this.client.generateInvite({ + const invite = this.client.generateInvite({ permissions: [ Permissions.FLAGS.VIEW_CHANNEL, Permissions.FLAGS.SEND_MESSAGES, diff --git a/src/commands/general/PingCommand.ts b/src/commands/general/PingCommand.ts index 1401e1032..1b466ad0a 100644 --- a/src/commands/general/PingCommand.ts +++ b/src/commands/general/PingCommand.ts @@ -51,7 +51,8 @@ export class PingCommand extends BaseCommand { msg.edit({ content: " ", embeds: [embed] }).catch(e => this.client.logger.error("PROMISE_ERR:", e)); } - private searchHex(ms: string | number): ColorResolvable { + // eslint-disable-next-line class-methods-use-this + private searchHex(ms: number | string): ColorResolvable { const listColorHex = [ [0, 20, "GREEN"], [21, 50, "GREEN"], @@ -65,7 +66,7 @@ export class PingCommand extends BaseCommand { const min = listColorHex.map(e => e[0]); const max = listColorHex.map(e => e[1]); const hex = listColorHex.map(e => e[2]); - let ret: string | number = "#000000"; + let ret: number | string = "#000000"; for (let i = 0; i < listColorHex.length; i++) { if (min[i] <= ms && ms <= max[i]) { diff --git a/src/commands/moderation/BanCommand.ts b/src/commands/moderation/BanCommand.ts index abb755af3..04dac4387 100644 --- a/src/commands/moderation/BanCommand.ts +++ b/src/commands/moderation/BanCommand.ts @@ -61,7 +61,7 @@ export class BanCommand extends BaseCommand { const ban = await ctx.guild.members.ban(user, { reason - }).catch(err => new Error(err as string|undefined)); + }).catch(err => new Error(err as string | undefined)); if (ban instanceof Error) return ctx.reply({ embeds: [createEmbed("error", i18n.__mf("commands.moderation.ban.banFail", { message: ban.message }), true)] }); return ctx.reply({ embeds: [createEmbed("success", i18n.__mf("commands.moderation.ban.banSuccess", { user: user.tag }), true)] }); diff --git a/src/commands/moderation/KickCommand.ts b/src/commands/moderation/KickCommand.ts index 10c1399c4..8d0111bba 100644 --- a/src/commands/moderation/KickCommand.ts +++ b/src/commands/moderation/KickCommand.ts @@ -56,7 +56,7 @@ export class KickCommand extends BaseCommand { }); } - const kick = await member.kick(reason).catch(err => new Error(err as string|undefined)); + const kick = await member.kick(reason).catch(err => new Error(err as string | undefined)); if (kick instanceof Error) return ctx.reply({ embeds: [createEmbed("error", i18n.__mf("commands.moderation.kick.kickFail", { message: kick.message }), true)] }); return ctx.reply({ embeds: [createEmbed("success", i18n.__mf("commands.moderation.kick.kickSuccess", { user: member.user.tag }), true)] }); diff --git a/src/commands/moderation/MuteCommand.ts b/src/commands/moderation/MuteCommand.ts index 28d018b5f..62f34c4c7 100644 --- a/src/commands/moderation/MuteCommand.ts +++ b/src/commands/moderation/MuteCommand.ts @@ -61,7 +61,7 @@ export class MuteCommand extends BaseCommand { }); } - const mute = await member.roles.add(muteRole, reason).catch(err => new Error(err as string|undefined)); + const mute = await member.roles.add(muteRole, reason).catch(err => new Error(err as string | undefined)); if (mute instanceof Error) return ctx.reply({ embeds: [createEmbed("error", i18n.__mf("commands.moderation.mute.muteFail", { message: mute.message }), true)] }); return ctx.reply({ embeds: [createEmbed("success", i18n.__mf("commands.moderation.mute.muteSuccess", { user: member.user.tag }), true)] }); diff --git a/src/commands/moderation/PurgeCommand.ts b/src/commands/moderation/PurgeCommand.ts index 173909d46..a3365d531 100644 --- a/src/commands/moderation/PurgeCommand.ts +++ b/src/commands/moderation/PurgeCommand.ts @@ -23,7 +23,7 @@ export class PurgeCommand extends BaseCommand { }); } - public async execute(ctx: CommandContext): Promise { + public async execute(ctx: CommandContext): Promise { if (!ctx.member?.permissions.has("MANAGE_MESSAGES")) return ctx.reply({ embeds: [createEmbed("error", i18n.__("commands.moderation.purge.userNoPermission"), true)] }); if (!ctx.guild?.me?.permissions.has("MANAGE_MESSAGES")) return ctx.reply({ embeds: [createEmbed("error", i18n.__("commands.moderation.purge.botNoPermission"), true)] }); @@ -31,7 +31,7 @@ export class PurgeCommand extends BaseCommand { if (isNaN(amount)) return ctx.reply({ embeds: [createEmbed("warn", i18n.__("commands.moderation.purge.invalidAmount"))] }); const purge = await (ctx.channel as TextChannel).bulkDelete(amount + 1, true) - .catch(err => new Error(err as string|undefined)); + .catch(err => new Error(err as string | undefined)); if (purge instanceof Error) return ctx.reply({ embeds: [createEmbed("warn", i18n.__mf("commands.moderation.purge.purgeFail", { message: purge.message }), true)] }); return ctx.reply({ embeds: [createEmbed("success", `🧹 **|** ${i18n.__mf("commands.moderation.purge.purgeSuccess", { amount: purge.size })}`)] }); diff --git a/src/commands/moderation/UnBanCommand.ts b/src/commands/moderation/UnBanCommand.ts index e4159b343..d9b324acc 100644 --- a/src/commands/moderation/UnBanCommand.ts +++ b/src/commands/moderation/UnBanCommand.ts @@ -35,13 +35,13 @@ export class UnBanCommand extends BaseCommand { const memberId = ctx.args.shift()?.replace(/[^0-9]/g, "") ?? ctx.options?.getUser("user")?.id ?? ctx.options?.getString("memberid"); const user = await this.client.users.fetch(memberId!, { force: false }).catch(() => undefined); - const resolved = ctx.guild.bans.resolve(user?.id as string); + const resolved = ctx.guild.bans.resolve(user?.id ?? ""); if (!user) return ctx.reply({ embeds: [createEmbed("warn", i18n.__("commands.moderation.common.noUserSpecified"))] }); if (!resolved) return ctx.reply({ embeds: [createEmbed("warn", i18n.__("commands.moderation.unban.alreadyUnban"))] }); const unban = await ctx.guild.bans.remove(user.id, ctx.options?.getString("reason") ?? (ctx.args.length ? ctx.args.join(" ") : i18n.__("commands.moderation.common.noReasonString"))) - .catch(err => new Error(err as string|undefined)); + .catch(err => new Error(err as string | undefined)); if (unban instanceof Error) return ctx.reply({ embeds: [createEmbed("error", i18n.__mf("commands.moderation.unban.unbanFail", { message: unban.message }), true)] }); return ctx.reply({ embeds: [createEmbed("success", i18n.__mf("commands.moderation.unban.ubanSuccess", { user: user.tag }), true)] }); diff --git a/src/commands/moderation/UnMuteCommand.ts b/src/commands/moderation/UnMuteCommand.ts index 2b527ec88..4daf97421 100644 --- a/src/commands/moderation/UnMuteCommand.ts +++ b/src/commands/moderation/UnMuteCommand.ts @@ -59,7 +59,7 @@ export class UnMuteCommand extends BaseCommand { }); } - const unmute = await member.roles.remove(muteRole, reason).catch(err => new Error(err as string|undefined)); + const unmute = await member.roles.remove(muteRole, reason).catch(err => new Error(err as string | undefined)); if (unmute instanceof Error) return ctx.reply({ embeds: [createEmbed("error", i18n.__mf("commands.moderation.unmute.unmuteFail", { message: unmute.message }), true)] }); return ctx.reply({ embeds: [createEmbed("success", i18n.__mf("commands.moderation.unmute.unmuteSuccess", { user: member.user.tag }), true)] }); diff --git a/src/commands/moderation/WarnCommand.ts b/src/commands/moderation/WarnCommand.ts index cb3178191..8da6c2f68 100644 --- a/src/commands/moderation/WarnCommand.ts +++ b/src/commands/moderation/WarnCommand.ts @@ -32,7 +32,7 @@ export class WarnCommand extends BaseCommand { public async execute(ctx: CommandContext): Promise { if (!ctx.member?.permissions.has("MANAGE_GUILD")) return ctx.reply({ embeds: [createEmbed("error", i18n.__("commands.moderation.warn.userNoPermission"), true)] }); - const member = ctx.guild?.members.resolve(ctx.args.shift()?.replace(/[^0-9]/g, "") as string)?.user ?? ctx.options?.getUser("member", true); + const member = ctx.guild?.members.resolve(ctx.args.shift()?.replace(/[^0-9]/g, "") ?? "")?.user ?? ctx.options?.getUser("member", true); if (!member) return ctx.reply({ embeds: [createEmbed("warn", i18n.__("commands.moderation.common.noUserSpecified"))] }); const dm = await member.createDM().catch(() => undefined); diff --git a/src/commands/music/LyricsCommand.ts b/src/commands/music/LyricsCommand.ts index 8b9d7f809..99e645d4a 100644 --- a/src/commands/music/LyricsCommand.ts +++ b/src/commands/music/LyricsCommand.ts @@ -28,32 +28,33 @@ export class LyricsCommand extends BaseCommand { }); } - public execute(ctx: CommandContext): Promise { - const query = ctx.args.length >= 1 ? ctx.args.join(" ") : ctx.options?.getString("query") ? ctx.options.getString("query") : ((((ctx.guild?.queue?.player?.state as AudioPlayerPlayingState).resource as AudioResource | undefined)?.metadata as IQueueSong | undefined)?.song.title); + public execute(ctx: CommandContext): Promise | undefined { + // eslint-disable-next-line no-nested-ternary + const query = ctx.args.length >= 1 ? ctx.args.join(" ") : ctx.options?.getString("query") ? ctx.options.getString("query") : (((ctx.guild?.queue?.player?.state as AudioPlayerPlayingState).resource as AudioResource | undefined)?.metadata as IQueueSong | undefined)?.song.title; if (!query) return ctx.reply({ embeds: [createEmbed("error", i18n.__("commands.music.lyrics.noQuery"), true)] }); - return this.getLyrics(ctx, query); + this.getLyrics(ctx, query); } - private async getLyrics(ctx: CommandContext, song: string): Promise { + private getLyrics(ctx: CommandContext, song: string): void { const url = `https://api.lxndr.dev/lyrics/?song=${encodeURI(song)}&from=${encodeURI(this.client.user!.id)}`; this.client.request.get(url).json>() .then(async data => { if ((data as { error: boolean }).error) { - return ctx.reply({ embeds: [createEmbed("error", i18n.__mf("commands.music.lyrics.apiError", { song: `\`${song}\``, message: `\`${(data as {message?: string}).message!}\`` }), true)] }); + return ctx.reply({ embeds: [createEmbed("error", i18n.__mf("commands.music.lyrics.apiError", { song: `\`${song}\``, message: `\`${(data as { message?: string }).message!}\`` }), true)] }); } - const albumArt = data.album_art ?? "https://api.zhycorp.net/assets/images/icon.png"; - const pages: string[] = chunk(data.lyrics as string, 2048); + const albumArt = data.album_art ?? "https://api.tiramitzu.me/assets/images/icon.png"; + const pages: string[] = chunk(data.lyrics!, 2048); const embed = createEmbed("info", pages[0]).setAuthor({ name: data.song && data.artist ? `${data.song} - ${data.artist}` : song.toUpperCase() }).setThumbnail(albumArt); const msg = await ctx.reply({ embeds: [embed] }); - return (new ButtonPagination(msg, { + return new ButtonPagination(msg, { author: ctx.author.id, edit: (i, e, p) => e.setDescription(p).setFooter({ text: i18n.__mf("reusable.pageFooter", { actual: i + 1, total: pages.length }) }), embed, pages - })).start(); + }).start(); }) .catch(error => console.error(error)); } diff --git a/src/commands/music/NowPlayingCommand.ts b/src/commands/music/NowPlayingCommand.ts index f30f2fcea..b9b3a1ea3 100644 --- a/src/commands/music/NowPlayingCommand.ts +++ b/src/commands/music/NowPlayingCommand.ts @@ -24,9 +24,11 @@ export class NowPlayingCommand extends BaseCommand { if (!haveQueue(ctx)) return; function getEmbed(): MessageEmbed { - const song = ((ctx.guild?.queue?.player?.state as (AudioPlayerState & { resource: AudioResource|undefined })|undefined)?.resource?.metadata as IQueueSong|undefined)?.song; + const song = ((ctx.guild?.queue?.player?.state as (AudioPlayerState & { + resource: AudioResource | undefined; + }) | undefined)?.resource?.metadata as IQueueSong | undefined)?.song; - return createEmbed("info", `${ctx.guild?.queue?.playing ? "▶" : "⏸"} **|** ${song ? `**[${song.title}](${song.url})**` : i18n.__("commands.music.nowplaying.emptyQueue")}`).setThumbnail(song?.thumbnail ?? "https://api.zhycorp.net/assets/images/icon.png"); + return createEmbed("info", `${ctx.guild?.queue?.playing ? "▶" : "⏸"} **|** ${song ? `**[${song.title}](${song.url})**` : i18n.__("commands.music.nowplaying.emptyQueue")}`).setThumbnail(song?.thumbnail ?? "https://api.tiramitzu.me/assets/images/icon.png"); } const buttons = new MessageActionRow() @@ -55,7 +57,7 @@ export class NowPlayingCommand extends BaseCommand { const msg = await ctx.reply({ embeds: [getEmbed()], components: [buttons] }); const collector = msg.createMessageComponentCollector({ - filter: i => i.isButton() && (i.user.id === ctx.author.id), + filter: i => i.isButton() && i.user.id === ctx.author.id, idle: 30000 }); diff --git a/src/commands/music/PauseCommand.ts b/src/commands/music/PauseCommand.ts index 32f9d8256..79c5735e9 100644 --- a/src/commands/music/PauseCommand.ts +++ b/src/commands/music/PauseCommand.ts @@ -17,7 +17,7 @@ export class PauseCommand extends BaseCommand { }); } - public execute(ctx: CommandContext): Promise|void { + public execute(ctx: CommandContext): Promise | undefined { if (!inVC(ctx)) return; if (!haveQueue(ctx)) return; if (!sameVC(ctx)) return; diff --git a/src/commands/music/PlayCommand.ts b/src/commands/music/PlayCommand.ts index 387a09d1b..b294ee6a7 100644 --- a/src/commands/music/PlayCommand.ts +++ b/src/commands/music/PlayCommand.ts @@ -28,7 +28,7 @@ export class PlayCommand extends BaseCommand { }); } - public async execute(ctx: CommandContext): Promise { + public async execute(ctx: CommandContext): Promise { if (!inVC(ctx)) return; if (!validVC(ctx)) return; if (!sameVC(ctx)) return; @@ -45,6 +45,7 @@ export class PlayCommand extends BaseCommand { } return handleVideos(this.client, ctx, toQueue, voiceChannel); } + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access const query = (ctx.args.join(" ") || ctx.options?.getString("query")) ?? (ctx.additionalArgs.get("values") ? ctx.additionalArgs.get("values")[0] : undefined) as string | undefined; if (!query) { @@ -53,15 +54,16 @@ export class PlayCommand extends BaseCommand { }); } + // eslint-disable-next-line prefer-named-capture-group const url = query.replace(/<(.+)>/g, "$1"); if (ctx.guild?.queue && voiceChannel.id !== ctx.guild.queue.connection?.joinConfig.channelId) { - return ctx.reply({ embeds: [createEmbed("warn", i18n.__mf("commands.music.play.alreadyPlaying", { voiceChannel: ctx.guild.channels.cache.get(ctx.guild.queue.connection?.joinConfig.channelId as string)?.name ?? "#unknown-channel" }))] }); + return ctx.reply({ embeds: [createEmbed("warn", i18n.__mf("commands.music.play.alreadyPlaying", { voiceChannel: ctx.guild.channels.cache.get((ctx.guild.queue.connection?.joinConfig as { channelId: string }).channelId)?.name ?? "#unknown-channel" }))] }); } const queryCheck = checkQuery(url); const songs = await searchTrack(this.client, url).catch(() => undefined); - if (!songs || (songs.items.length <= 0)) return ctx.reply({ embeds: [createEmbed("error", i18n.__("commands.music.play.noSongData"), true)] }); + if (!songs || songs.items.length <= 0) return ctx.reply({ embeds: [createEmbed("error", i18n.__("commands.music.play.noSongData"), true)] }); return handleVideos(this.client, ctx, queryCheck.type === "playlist" ? songs.items : [songs.items[0]], voiceChannel); } diff --git a/src/commands/music/QueueCommand.ts b/src/commands/music/QueueCommand.ts index 2175a5f54..310dcadf4 100644 --- a/src/commands/music/QueueCommand.ts +++ b/src/commands/music/QueueCommand.ts @@ -40,11 +40,11 @@ export class QueueCommand extends BaseCommand { const embed = createEmbed("info", pages[0]); const msg = await ctx.reply({ embeds: [embed] }); - return (new ButtonPagination(msg, { + return new ButtonPagination(msg, { author: ctx.author.id, edit: (i, e, p) => e.setDescription(p).setFooter({ text: i18n.__mf("reusable.pageFooter", { actual: i + 1, total: pages.length }) }), embed, pages - })).start(); + }).start(); } } diff --git a/src/commands/music/RemoveCommand.ts b/src/commands/music/RemoveCommand.ts index 8b4ca9f7e..bdcffb52f 100644 --- a/src/commands/music/RemoveCommand.ts +++ b/src/commands/music/RemoveCommand.ts @@ -52,8 +52,8 @@ export class RemoveCommand extends BaseCommand { ctx.guild!.queue!.songs.delete(song.key); } - const np = (ctx.guild?.queue?.player?.state as (AudioPlayerState & { resource: AudioResource|undefined })|undefined)?.resource?.metadata as IQueueSong|undefined; - const isSkip = songs.map(x => x.key).includes(np?.key as string); + const np = (ctx.guild?.queue?.player?.state as (AudioPlayerState & { resource: AudioResource | undefined }) | undefined)?.resource?.metadata as IQueueSong | undefined; + const isSkip = songs.map(x => x.key).includes(np?.key ?? ""); if (isSkip) { this.client.commands.get("skip")?.execute(ctx); } diff --git a/src/commands/music/RepeatCommand.ts b/src/commands/music/RepeatCommand.ts index 81c93fa0f..950ecbe8a 100644 --- a/src/commands/music/RepeatCommand.ts +++ b/src/commands/music/RepeatCommand.ts @@ -35,7 +35,7 @@ export class RepeatCommand extends BaseCommand { }); } - public execute(ctx: CommandContext): Promise|void { + public execute(ctx: CommandContext): Promise | undefined { if (!inVC(ctx)) return; if (!haveQueue(ctx)) return; if (!sameVC(ctx)) return; @@ -54,7 +54,10 @@ export class RepeatCommand extends BaseCommand { emoji: "🔂" } }; - const selection = ctx.options?.getSubcommand() || ctx.args[0] ? Object.keys(mode).find(key => mode[key as LoopMode].aliases.includes(ctx.args[0] ?? ctx.options!.getSubcommand())) : undefined; + const selection = ctx.options?.getSubcommand() || + ctx.args[0] + ? Object.keys(mode).find(key => mode[key as LoopMode].aliases.includes(ctx.args[0] ?? ctx.options!.getSubcommand())) + : undefined; if (!selection) return ctx.reply({ embeds: [createEmbed("info", `${mode[ctx.guild!.queue!.loopMode].emoji} **|** ${i18n.__mf("commands.music.repeat.actualMode", { mode: `\`${ctx.guild!.queue!.loopMode}\`` })}`)] }); ctx.guild!.queue!.loopMode = selection as LoopMode; diff --git a/src/commands/music/ResumeCommand.ts b/src/commands/music/ResumeCommand.ts index 148d7283e..1fb3c41db 100644 --- a/src/commands/music/ResumeCommand.ts +++ b/src/commands/music/ResumeCommand.ts @@ -17,7 +17,7 @@ export class ResumeCommand extends BaseCommand { }); } - public execute(ctx: CommandContext): Promise|void { + public execute(ctx: CommandContext): Promise | undefined { if (!inVC(ctx)) return; if (!haveQueue(ctx)) return; if (!sameVC(ctx)) return; diff --git a/src/commands/music/SearchCommand.ts b/src/commands/music/SearchCommand.ts index 63e194d1a..eb6001875 100644 --- a/src/commands/music/SearchCommand.ts +++ b/src/commands/music/SearchCommand.ts @@ -45,7 +45,7 @@ export class SearchCommand extends BaseCommand { }); } - public async execute(ctx: CommandContext): Promise { + public async execute(ctx: CommandContext): Promise { if (!inVC(ctx)) return; if (!validVC(ctx)) return; if (!sameVC(ctx)) return; @@ -67,7 +67,7 @@ export class SearchCommand extends BaseCommand { return; } const source = ctx.options?.getString("source") ?? (["youtube", "soundcloud"].includes(ctx.args.slice(-1)[0]?.toLowerCase()) ? ctx.args.pop()! : "youtube"); - const query = (ctx.args.join(" ") || ctx.options?.getString("query")) ?? (ctx.options as CommandInteractionOptionResolver<"present">|null)?.getMessage("message")?.content; + const query = (ctx.args.join(" ") || ctx.options?.getString("query")) ?? (ctx.options as CommandInteractionOptionResolver<"present"> | null)?.getMessage("message")?.content; if (!query) { return ctx.send({ @@ -81,8 +81,8 @@ export class SearchCommand extends BaseCommand { return this.client.commands.get("play")!.execute(newCtx); } - const tracks = await searchTrack(this.client, query, source as "youtube" | "soundcloud").then(x => ({ items: x.items.slice(0, 10), type: x.type })).catch(() => undefined); - if (!tracks || (tracks.items.length <= 0)) return ctx.reply({ embeds: [createEmbed("error", i18n.__("commands.music.search.noTracks"), true)] }); + const tracks = await searchTrack(this.client, query, source as "soundcloud" | "youtube").then(x => ({ items: x.items.slice(0, 10), type: x.type })).catch(() => undefined); + if (!tracks || tracks.items.length <= 0) return ctx.reply({ embeds: [createEmbed("error", i18n.__("commands.music.search.noTracks"), true)] }); if (this.client.config.musicSelectionType === "selectmenu") { return ctx.send({ content: i18n.__("commands.music.search.interactionContent"), @@ -102,7 +102,7 @@ export class SearchCommand extends BaseCommand { const msg = await ctx.send({ embeds: [ - createEmbed("info", `${i18n.__mf("commands.music.search.queueEmbed", { separator: `\`,\``, example: `\`1, 2, 3\`` })}\`\`\`\n${tracks.items.map((x, i) => `${i + 1} - ${Util.escapeMarkdown(parseHTMLElements(x.title))}`).join("\n")}\`\`\``) + createEmbed("info", `${i18n.__mf("commands.music.search.queueEmbed", { separator: "`,`", example: "`1, 2, 3`" })}\`\`\`\n${tracks.items.map((x, i) => `${i + 1} - ${Util.escapeMarkdown(parseHTMLElements(x.title))}`).join("\n")}\`\`\``) .setAuthor({ name: i18n.__("commands.music.search.trackSelectionMessage"), iconURL: this.client.user?.displayAvatarURL() }) .setFooter({ text: i18n.__mf("commands.music.search.cancelMessage", { cancel: "cancel", c: "c" }) }) ] @@ -112,7 +112,7 @@ export class SearchCommand extends BaseCommand { filter: m => { const nums = m.content.split(/, /).filter(x => Number(x) > 0 && Number(x) <= tracks.items.length); - return (m.author.id === ctx.author.id) && (["c", "cancel"].includes(m.content.toLowerCase()) || (nums.length >= 1)); + return m.author.id === ctx.author.id && (["c", "cancel"].includes(m.content.toLowerCase()) || nums.length >= 1); }, max: 1 }).catch(() => undefined); @@ -120,7 +120,7 @@ export class SearchCommand extends BaseCommand { msg.delete().catch(err => this.client.logger.error("SEARCH_SELECTION_DELETE_MSG_ERR:", err)); return ctx.reply({ embeds: [createEmbed("error", i18n.__("commands.music.search.noSelection"), true)] }); } - if (["c", "cancel"].includes(respond.first()?.content.toLowerCase() as string)) { + if (["c", "cancel"].includes(respond.first()?.content.toLowerCase() ?? "")) { msg.delete().catch(err => this.client.logger.error("SEARCH_SELECTION_DELETE_MSG_ERR:", err)); return ctx.reply({ embeds: [createEmbed("info", i18n.__("commands.music.search.canceledMessage"), true)] }); } @@ -137,6 +137,7 @@ export class SearchCommand extends BaseCommand { this.client.commands.get("play")!.execute(newCtx); } + // eslint-disable-next-line class-methods-use-this private generateSelectMenu(tracks: ISong[]): MessageSelectOptionData[] { const emojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟"]; diff --git a/src/commands/music/ShuffleCommand.ts b/src/commands/music/ShuffleCommand.ts index 6ff3b121a..e82c51144 100644 --- a/src/commands/music/ShuffleCommand.ts +++ b/src/commands/music/ShuffleCommand.ts @@ -43,7 +43,7 @@ export class ShuffleCommand extends BaseCommand { return; } - ctx.guild!.queue!.shuffle = (newState === "enable"); + ctx.guild!.queue!.shuffle = newState === "enable"; const isShuffle = ctx.guild?.queue?.shuffle; void ctx.reply({ embeds: [createEmbed("success", `${isShuffle ? "🔀" : "▶"} **|** ${i18n.__mf("commands.music.shuffle.newState", { state: `\`${isShuffle ? "ENABLED" : "DISABLED"}\`` })}`)] }); diff --git a/src/commands/music/SkipCommand.ts b/src/commands/music/SkipCommand.ts index e98d1349c..7f9709c49 100644 --- a/src/commands/music/SkipCommand.ts +++ b/src/commands/music/SkipCommand.ts @@ -32,20 +32,28 @@ export class SkipCommand extends BaseCommand { const song = (ctx.guild!.queue!.player!.state as AudioPlayerPlayingState).resource.metadata as IQueueSong; function ableToSkip(member: GuildMember): boolean { - return member.roles.cache.has(djRole?.id as string) || member.permissions.has("MANAGE_GUILD") || (song.requester.id === member.id); + return member.roles.cache.has(djRole?.id ?? "") || member.permissions.has("MANAGE_GUILD") || song.requester.id === member.id; } if (!ableToSkip(ctx.member!)) { const required = this.client.utils.requiredVoters(ctx.guild!.me!.voice.channel!.members.size); if (ctx.guild?.queue?.skipVoters.includes(ctx.author.id)) { - this.manager.add(() => ctx.guild!.queue!.skipVoters = ctx.guild!.queue!.skipVoters.filter(x => x !== ctx.author.id)); + this.manager.add(() => { + ctx.guild!.queue!.skipVoters = ctx.guild!.queue!.skipVoters.filter(x => x !== ctx.author.id); + + return undefined; + }); await ctx.reply(i18n.__mf("commands.music.skip.voteResultMessage", { length: ctx.guild.queue.skipVoters.length, required })); return; } - this.manager.add(() => ctx.guild?.queue?.skipVoters.push(ctx.author.id)); + this.manager.add(() => { + ctx.guild?.queue?.skipVoters.push(ctx.author.id); + + return undefined; + }); const length = ctx.guild!.queue!.skipVoters.length; await ctx.reply(i18n.__mf("commands.music.skip.voteResultMessage", { length, required })); diff --git a/src/commands/music/SkipToCommand.ts b/src/commands/music/SkipToCommand.ts index d1ddbab66..94c9ded0d 100644 --- a/src/commands/music/SkipToCommand.ts +++ b/src/commands/music/SkipToCommand.ts @@ -45,7 +45,7 @@ export class SkipToCommand extends BaseCommand { }); } - public async execute(ctx: CommandContext): Promise { + public async execute(ctx: CommandContext): Promise { if (!inVC(ctx)) return; if (!haveQueue(ctx)) return; if (!sameVC(ctx)) return; diff --git a/src/commands/music/StayInQueueCommand.ts b/src/commands/music/StayInQueueCommand.ts index e7e31c4ec..0deb988e6 100644 --- a/src/commands/music/StayInQueueCommand.ts +++ b/src/commands/music/StayInQueueCommand.ts @@ -35,7 +35,7 @@ export class StayInQueueCommand extends BaseCommand { }); } - public execute(ctx: CommandContext): Promise|void { + public execute(ctx: CommandContext): Promise | undefined { if (!inVC(ctx)) return; if (!haveQueue(ctx)) return; if (!sameVC(ctx)) return; @@ -45,7 +45,7 @@ export class StayInQueueCommand extends BaseCommand { if (!newState) return ctx.reply({ embeds: [createEmbed("info", i18n.__mf("commands.music.stayInQueue.actualState", { state: `\`${ctx.guild?.queue?.stayInVC ? "ENABLED" : "DISABLED"}\`` }))] }); - ctx.guild!.queue!.stayInVC = (newState === "enable"); + ctx.guild!.queue!.stayInVC = newState === "enable"; return ctx.reply({ embeds: [createEmbed("success", i18n.__mf("commands.music.stayInQueue.newState", { state: `\`${ctx.guild?.queue?.stayInVC ? "ENABLED" : "DISABLED"}\`` }), true)] }); } diff --git a/src/commands/music/VolumeCommand.ts b/src/commands/music/VolumeCommand.ts index 3969a7f75..aa5e1fbe8 100644 --- a/src/commands/music/VolumeCommand.ts +++ b/src/commands/music/VolumeCommand.ts @@ -26,7 +26,7 @@ export class VolumeCommand extends BaseCommand { }); } - public execute(ctx: CommandContext): Promise|void { + public execute(ctx: CommandContext): Promise | undefined { if (!inVC(ctx)) return; if (!validVC(ctx)) return; if (!sameVC(ctx)) return; @@ -36,7 +36,7 @@ export class VolumeCommand extends BaseCommand { if (isNaN(volume)) return ctx.reply({ embeds: [createEmbed("info", `🔊 **|** ${i18n.__mf("commands.music.volume.currentVolume", { volume: `\`${resVolume.volume * 100}\`` })}`).setFooter({ text: i18n.__("commands.music.volume.changeVolume") })] }); if (volume <= 0) return ctx.reply({ embeds: [createEmbed("warn", i18n.__mf("commands.music.volume.plsPause", { volume: `\`${volume}\`` }))] }); - if (volume > 100) return ctx.reply({ embeds: [createEmbed("error", i18n.__mf("commands.music.volume.volumeLimit", { maxVol: `\`100\`` }), true)] }); + if (volume > 100) return ctx.reply({ embeds: [createEmbed("error", i18n.__mf("commands.music.volume.volumeLimit", { maxVol: "`100`" }), true)] }); resVolume.setVolume(volume / 100); return ctx.reply({ embeds: [createEmbed("success", `🔊 **|** ${i18n.__mf("commands.music.volume.newVolume", { volume })}`)] }); diff --git a/src/config.ts b/src/config.ts index 9d49f3b52..bd0b2d17b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,5 @@ import { IpresenceData } from "./typings"; -import { ActivityType, ClientOptions, ClientPresenceStatus, Intents, LimitedCollection, Options, ShardingManagerMode } from "discord.js"; +import { ActivityType, ClientOptions, ClientPresenceStatus, Intents, Options, ShardingManagerMode, Sweepers } from "discord.js"; import { join } from "path"; import i18n from "i18n"; @@ -10,14 +10,14 @@ export const clientOptions: ClientOptions = { MessageManager: { maxSize: Infinity, sweepInterval: 300, - sweepFilter: LimitedCollection.filterByLifetime({ + sweepFilter: Sweepers.filterByLifetime({ lifetime: 10800 }) }, ThreadManager: { maxSize: Infinity, sweepInterval: 300, - sweepFilter: LimitedCollection.filterByLifetime({ + sweepFilter: Sweepers.filterByLifetime({ lifetime: 10800, getComparisonTimestamp: e => e.archiveTimestamp!, excludeFromSweep: e => !e.archived @@ -28,22 +28,23 @@ export const clientOptions: ClientOptions = { }; export const shardsCount: number | "auto" = "auto"; export const shardingMode: ShardingManagerMode = "worker"; -export const embedColor = process.env.EMBED_COLOR?.toUpperCase() as string || "3CAAFF"; -export const lang = process.env.LOCALE?.toLowerCase() as string || "en"; +export const embedColor = (process.env.EMBED_COLOR?.toUpperCase() ?? "") || "3CAAFF"; +export const lang = (process.env.LOCALE?.toLowerCase() ?? "") || "en"; export const owners: string[] = JSON.parse(process.env.OWNERS ?? "[]"); export const devGuild = JSON.parse(process.env.DEV_GUILD ?? "[]"); export const isDev = process.env.NODE_ENV?.toLowerCase() === "development"; export const isProd = !isDev; -export const mainPrefix = isDev ? "d!" : (process.env.MAIN_PREFIX as string || "!"); -export const altPrefixes: string[] = (JSON.parse(process.env.ALT_PREFIX as string || "[\"{mention}\"]") as string[]).filter((x, i, a) => (a.indexOf(x) === i) && x !== mainPrefix); +export const mainPrefix = isDev ? "d!" : process.env.MAIN_PREFIX! || "!"; +export const altPrefixes: string[] = (JSON.parse(process.env.ALT_PREFIX! || "[\"{mention}\"]") as string[]).filter((x, i, a) => a.indexOf(x) === i && x !== mainPrefix); export const enableSlashCommand = process.env.ENABLE_SLASH_COMMAND?.toLowerCase() !== "no"; -export const musicSelectionType = process.env.MUSIC_SELECTION_TYPE?.toLowerCase() as string || "message"; +export const musicSelectionType = (process.env.MUSIC_SELECTION_TYPE?.toLowerCase() ?? "") || "message"; export const is247Allowed = process.env.ENABLE_24_7_COMMAND?.toLowerCase() === "yes"; export const stayInVCAfterFinished = process.env.STAY_IN_VC_AFTER_FINISHED?.toLowerCase() === "yes"; export const djRoleName = process.env.DJ_ROLE_NAME! || "DJ"; export const muteRoleName = process.env.MUTE_ROLE_NAME! || "Muted"; export const yesEmoji = process.env.YES_EMOJI! || "✅"; export const noEmoji = process.env.NO_EMOJI! || "❌"; +export const streamStrategy = process.env.STREAM_STRATEGY! || "youtube-dl"; export const presenceData: IpresenceData = { activities: (JSON.parse(process.env.ACTIVITIES! || "[]") as string[]).map((x, i) => ({ diff --git a/src/events/ChannelUpdateEvent.ts b/src/events/ChannelUpdateEvent.ts index 9be927b87..d3b8238a1 100644 --- a/src/events/ChannelUpdateEvent.ts +++ b/src/events/ChannelUpdateEvent.ts @@ -10,7 +10,7 @@ export class ChannelUpdateEvent extends BaseEvent { } public async execute(oldChannel: GuildChannel, newChannel: GuildChannel): Promise { - if (!newChannel.guild.queue || (newChannel.id !== newChannel.guild.queue.connection?.joinConfig.channelId) || (oldChannel.type !== "GUILD_VOICE" && oldChannel.type !== "GUILD_STAGE_VOICE") || (newChannel.type !== "GUILD_VOICE" && newChannel.type !== "GUILD_STAGE_VOICE")) return; + if (!newChannel.guild.queue || newChannel.id !== newChannel.guild.queue.connection?.joinConfig.channelId || (oldChannel.type !== "GUILD_VOICE" && oldChannel.type !== "GUILD_STAGE_VOICE") || (newChannel.type !== "GUILD_VOICE" && newChannel.type !== "GUILD_STAGE_VOICE")) return; if ((oldChannel as VoiceChannel).rtcRegion !== (newChannel as VoiceChannel).rtcRegion) { const queue = newChannel.guild.queue; diff --git a/src/events/InteractionCreateEvent.ts b/src/events/InteractionCreateEvent.ts index cc71d3c5a..8aa6c1e09 100644 --- a/src/events/InteractionCreateEvent.ts +++ b/src/events/InteractionCreateEvent.ts @@ -16,7 +16,7 @@ export class InteractionCreateEvent extends BaseEvent { const user = val.split("_")[0] ?? ""; const cmd = val.split("_")[1] ?? ""; if (cmd === "delete-msg") { - if (interaction.user.id !== user && !new Permissions(interaction.member.permissions as BitFieldResolvable|undefined).has("MANAGE_MESSAGES")) { + if (interaction.user.id !== user && !new Permissions(interaction.member.permissions as BitFieldResolvable | undefined).has("MANAGE_MESSAGES")) { void interaction.reply({ ephemeral: true, embeds: [ @@ -34,7 +34,7 @@ export class InteractionCreateEvent extends BaseEvent { const context = new CommandContext(interaction); if (interaction.isContextMenu()) { const data = interaction.options.getUser("user") ?? interaction.options.getMessage("message"); - const cmd = this.client.commands.find(x => (data as any).type === "MESSAGE" ? x.meta.contextChat === interaction.commandName : x.meta.contextUser === interaction.commandName); + const cmd = this.client.commands.find(x => (data as { type: string }).type === "MESSAGE" ? x.meta.contextChat === interaction.commandName : x.meta.contextUser === interaction.commandName); if (cmd) { context.additionalArgs.set("options", data); void cmd.execute(context); diff --git a/src/events/MessageCreateEvent.ts b/src/events/MessageCreateEvent.ts index eee790daa..baf34aa52 100644 --- a/src/events/MessageCreateEvent.ts +++ b/src/events/MessageCreateEvent.ts @@ -8,7 +8,7 @@ export class MessageCreateEvent extends BaseEvent { super(client, "messageCreate"); } - public async execute(message: Message): Promise { + public execute(message: Message): Message | undefined { if (message.author.bot || message.channel.type === "DM" || !this.client.commands.isReady) return message; if (this.getUserFromMention(message.content)?.id === this.client.user?.id) { @@ -17,7 +17,8 @@ export class MessageCreateEvent extends BaseEvent { const pref = this.client.config.altPrefixes.concat(this.client.config.mainPrefix).find(p => { if (p === "{mention}") { - const userMention = /<@(!)?\d*?>/.exec(message.content); + // eslint-disable-next-line prefer-named-capture-group + const userMention = (/<@(!)?\d*?>/).exec(message.content); if (userMention?.index !== 0) return false; const user = this.getUserFromMention(userMention[0]); @@ -27,11 +28,14 @@ export class MessageCreateEvent extends BaseEvent { return message.content.startsWith(p); }); - if (pref) return this.client.commands.handle(message, pref); + if (pref) { + this.client.commands.handle(message, pref); + } } private getUserFromMention(mention: string): User | undefined { - const matches = /^<@!?(\d+)>$/.exec(mention); + // eslint-disable-next-line prefer-named-capture-group + const matches = (/^<@!?(\d+)>$/).exec(mention); if (!matches) return undefined; const id = matches[1]; diff --git a/src/events/ReadyEvent.ts b/src/events/ReadyEvent.ts index 769fc37b5..706846b21 100644 --- a/src/events/ReadyEvent.ts +++ b/src/events/ReadyEvent.ts @@ -40,23 +40,25 @@ export class ReadyEvent extends BaseEvent { return newText .replace(/{prefix}/g, this.client.config.mainPrefix) - .replace(/{username}/g, this.client.user?.username as string); + .replace(/{username}/g, this.client.user!.username); } private async setPresence(random: boolean): Promise { const activityNumber = random ? Math.floor(Math.random() * this.client.config.presenceData.activities.length) : 0; const statusNumber = random ? Math.floor(Math.random() * this.client.config.presenceData.status.length) : 0; - const activity = (await Promise.all(this.client.config.presenceData.activities.map(async a => Object.assign(a, { name: await this.formatString(a.name) }))))[activityNumber]; + const activity = (await Promise.all( + this.client.config.presenceData.activities.map(async a => Object.assign(a, { name: await this.formatString(a.name) })) + ))[activityNumber]; return this.client.user!.setPresence({ - activities: (activity as { name: string }|undefined) ? [activity] : [], + activities: (activity as { name: string } | undefined) ? [activity] : [], status: this.client.config.presenceData.status[statusNumber] }); } private async doPresence(): Promise { try { - return this.setPresence(false); + return await this.setPresence(false); } catch (e) { if ((e as Error).message !== "Shards are still being spawned.") this.client.logger.error(String(e)); return undefined; diff --git a/src/events/VoiceStateUpdateEvent.ts b/src/events/VoiceStateUpdateEvent.ts index e0041d1b5..a3fa1e346 100644 --- a/src/events/VoiceStateUpdateEvent.ts +++ b/src/events/VoiceStateUpdateEvent.ts @@ -12,7 +12,7 @@ export class VoiceStateUpdateEvent extends BaseEvent { super(client, "voiceStateUpdate"); } - public async execute(oldState: VoiceState, newState: VoiceState): Promise { + public async execute(oldState: VoiceState, newState: VoiceState): Promise { const queue = newState.guild.queue; if (!queue) return; @@ -20,7 +20,7 @@ export class VoiceStateUpdateEvent extends BaseEvent { const oldVC = oldState.channel; const newID = newVC?.id; const oldID = oldVC?.id; - const queueVC = newState.guild.channels.cache.get(queue.connection!.joinConfig.channelId!)! as VoiceChannel | StageChannel; + const queueVC = newState.guild.channels.cache.get(queue.connection!.joinConfig.channelId!)! as StageChannel | VoiceChannel; const member = newState.member; const oldMember = oldState.member; const newVCMembers = newVC?.members.filter(m => !m.user.bot); @@ -50,7 +50,7 @@ export class VoiceStateUpdateEvent extends BaseEvent { try { await entersState(queue.connection!, VoiceConnectionStatus.Ready, 20000); void msg.edit({ embeds: [createEmbed("success", i18n.__("events.voiceStateUpdate.connectionReconfigured"), true)] }); - } catch (err) { + } catch { queue.destroy(); this.client.logger.info(`${this.client.shard ? `[Shard #${this.client.shard.ids[0]}]` : ""} Unable to re-configure networking on ${newState.guild.name} voice channel, the queue was deleted.`); void msg.edit({ embeds: [createEmbed("error", i18n.__("events.voiceStateUpdate.unableReconfigureConnection"), true)] }); @@ -61,13 +61,14 @@ export class VoiceStateUpdateEvent extends BaseEvent { const msg = await queue.textChannel.send({ embeds: [createEmbed("info", i18n.__("events.voiceStateUpdate.joiningAsSpeaker"))] }); const suppress = await newState.setSuppressed(false).catch(err => ({ error: err })); - if (suppress && ("error" in suppress)) { + if (suppress && "error" in suppress) { queue.destroy(); this.client.logger.info(`${this.client.shard ? `[Shard #${this.client.shard.ids[0]}]` : ""} Unable to join as Speaker at ${newState.guild.name} stage channel, the queue was deleted.`); - return queue.textChannel.send({ embeds: [createEmbed("error", i18n.__("events.voiceStateUpdate.unableJoinStageMessage"), true)] }) + void queue.textChannel.send({ embeds: [createEmbed("error", i18n.__("events.voiceStateUpdate.unableJoinStageMessage"), true)] }) .catch(e => { this.client.logger.error("VOICE_STATE_UPDATE_EVENT_ERR:", e); }); + return; } await msg.edit({ embeds: [createEmbed("success", i18n.__("events.voiceStateUpdate.joinStageMessage"), true)] }); @@ -87,6 +88,7 @@ export class VoiceStateUpdateEvent extends BaseEvent { if (newID === queueVC.id && !member?.user.bot && queue.timeout) this.resume(queueVCMembers, queue, newState); } + // eslint-disable-next-line class-methods-use-this private timeout(vcMembers: VoiceChannel["members"], queue: ServerQueue, state: VoiceState): void { if (vcMembers.size !== 0) return; @@ -106,6 +108,7 @@ export class VoiceStateUpdateEvent extends BaseEvent { .then(msg => queue.lastVSUpdateMsg = msg.id); } + // eslint-disable-next-line class-methods-use-this private resume(vcMembers: VoiceChannel["members"], queue: ServerQueue, state: VoiceState): void { if (vcMembers.size <= 0) return; diff --git a/src/index.ts b/src/index.ts index fc72840f5..df8fc7d19 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,10 @@ import "dotenv/config"; import { isProd, shardingMode, shardsCount } from "./config"; -import { DiscLogger } from "./utils/DiscLogger"; +import { RawonLogger } from "./utils/RawonLogger"; import { ShardingManager } from "discord.js"; import { resolve } from "path"; -const log = new DiscLogger({ prod: isProd }); +const log = new RawonLogger({ prod: isProd }); const manager = new ShardingManager(resolve(__dirname, "bot.js"), { totalShards: shardsCount, diff --git a/src/structures/BaseCommand.ts b/src/structures/BaseCommand.ts index 20cc0ca50..1788f388a 100644 --- a/src/structures/BaseCommand.ts +++ b/src/structures/BaseCommand.ts @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { CommandContext } from "./CommandContext"; import { ICommandComponent } from "../typings"; -import { Disc } from "./Disc"; +import { Rawon } from "./Rawon"; import { CommandInteraction, Message, SelectMenuInteraction } from "discord.js"; export abstract class BaseCommand implements ICommandComponent { - public constructor(public client: Disc, public meta: ICommandComponent["meta"]) {} + public constructor(public client: Rawon, public meta: ICommandComponent["meta"]) {} public abstract execute(ctx: CommandContext): any; } diff --git a/src/structures/BaseEvent.ts b/src/structures/BaseEvent.ts index cc9760d0f..7674a8e74 100644 --- a/src/structures/BaseEvent.ts +++ b/src/structures/BaseEvent.ts @@ -1,8 +1,8 @@ import { IEvent } from "../typings"; -import { Disc } from "./Disc"; +import { Rawon } from "./Rawon"; export abstract class BaseEvent implements IEvent { - public constructor(public client: Disc, public readonly name: IEvent["name"]) {} + public constructor(public client: Rawon, public readonly name: IEvent["name"]) {} public abstract execute(...args: any): any; } diff --git a/src/structures/CommandContext.ts b/src/structures/CommandContext.ts index 9098eef7e..304936874 100644 --- a/src/structures/CommandContext.ts +++ b/src/structures/CommandContext.ts @@ -5,10 +5,10 @@ import { ButtonInteraction, Collection, CommandInteraction, ContextMenuInteracti export class CommandContext { public additionalArgs: Collection = new Collection(); - public channel: TextBasedChannel|null = this.context.channel; + public channel: TextBasedChannel | null = this.context.channel; public guild = this.context.guild; - public constructor(public readonly context: Interaction|CommandInteraction|SelectMenuInteraction|ContextMenuInteraction|Message, public args: string[] = []) {} + public constructor(public readonly context: CommandInteraction | ContextMenuInteraction | Interaction | Message | SelectMenuInteraction, public args: string[] = []) {} public async deferReply(): Promise { if (this.isInteraction()) { @@ -17,33 +17,41 @@ export class CommandContext { return Promise.resolve(undefined); } - public async reply(options: { askDeletion?: { reference: string } }|string|MessagePayload|MessageOptions|InteractionReplyOptions, autoedit?: boolean): Promise { + public async reply(options: InteractionReplyOptions + | MessageOptions + | MessagePayload + | string + | { askDeletion?: { reference: string } }, autoedit?: boolean): Promise { if (this.isInteraction()) { if ((this.context as Interaction).isCommand() && (this.context as CommandInteraction).replied && !autoedit) throw new Error("Interaction is already replied."); } - const context = this.context as Message|CommandInteraction; - const rep = await this.send(options, this.isInteraction() ? ((context as Interaction).isCommand() ? (((context as CommandInteraction).replied || (context as CommandInteraction).deferred) ? "editReply" : "reply") : "reply") : "reply").catch(e => ({ error: e })); + const context = this.context as CommandInteraction | Message; + // eslint-disable-next-line no-nested-ternary + const rep = await this.send(options, this.isInteraction() ? (context as Interaction).isCommand() ? (context as CommandInteraction).replied || (context as CommandInteraction).deferred ? "editReply" : "reply" : "reply" : "reply").catch(e => ({ error: e })); if (!rep || "error" in rep) throw new Error(`Unable to reply context, because: ${rep ? (rep.error as Error).message : "Unknown"}`); // @ts-expect-error-next-line - return (rep instanceof Message ? rep : new Message(this.context.client, rep)); + return rep instanceof Message ? rep : new Message(this.context.client, rep); } - public async send(options: { askDeletion?: { reference: string } }|string|MessagePayload|MessageOptions|InteractionReplyOptions, type: MessageInteractionAction = "editReply"): Promise { + public async send(options: InteractionReplyOptions | MessageOptions | MessagePayload | string | { askDeletion?: { reference: string } }, type: MessageInteractionAction = "editReply"): Promise { const deletionBtn = new MessageActionRow() .addComponents( new MessageButton() .setEmoji("🗑️") .setStyle("DANGER") ); - if ((options as any).askDeletion) { - deletionBtn.components[0].setCustomId(Buffer.from(`${(options as any).askDeletion.reference}_delete-msg`).toString("base64")); - (options as InteractionReplyOptions).components ? (options as InteractionReplyOptions).components!.push(deletionBtn) : (options as InteractionReplyOptions).components = [deletionBtn]; + if ((options as { askDeletion?: { reference: string } }).askDeletion) { + deletionBtn.components[0].setCustomId(Buffer.from(`${(options as { askDeletion: { reference: string } }).askDeletion.reference}_delete-msg`).toString("base64")); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + (options as InteractionReplyOptions).components + ? (options as InteractionReplyOptions).components!.push(deletionBtn) + : (options as InteractionReplyOptions).components = [deletionBtn]; } if (this.isInteraction()) { (options as InteractionReplyOptions).fetchReply = true; - const msg = await (this.context as CommandInteraction)[type](options as string|MessagePayload|InteractionReplyOptions) as Message; + const msg = await (this.context as CommandInteraction)[type](options as InteractionReplyOptions | MessagePayload | string) as Message; const channel = this.context.channel; const res = await channel!.messages.fetch(msg.id).catch(() => null); return res ?? msg; @@ -51,7 +59,7 @@ export class CommandContext { if ((options as InteractionReplyOptions).ephemeral) { throw new Error("Cannot send ephemeral message in a non-interaction context."); } - return this.context.channel!.send(options as string|MessagePayload|MessageOptions); + return this.context.channel!.send(options as MessageOptions | MessagePayload | string); } public isInteraction(): boolean { @@ -84,7 +92,7 @@ export class CommandContext { ); } - public get mentions(): MessageMentions|null { + public get mentions(): MessageMentions | null { return this.context instanceof Message ? this.context.mentions : null; } @@ -92,7 +100,7 @@ export class CommandContext { return this.context instanceof Interaction ? (this.context as CommandInteraction).deferred : false; } - public get options(): CommandInteraction["options"]|null { + public get options(): CommandInteraction["options"] | null { return this.context instanceof Interaction ? (this.context as CommandInteraction).options : null; } @@ -100,7 +108,7 @@ export class CommandContext { return this.context instanceof Interaction ? this.context.user : this.context.author; } - public get member(): GuildMember|null { + public get member(): GuildMember | null { return this.guild!.members.resolve(this.author.id); } } diff --git a/src/structures/Disc.ts b/src/structures/Rawon.ts similarity index 79% rename from src/structures/Disc.ts rename to src/structures/Rawon.ts index 11070b11b..1e449d56f 100644 --- a/src/structures/Disc.ts +++ b/src/structures/Rawon.ts @@ -2,7 +2,7 @@ import { soundcloud } from "../utils/handlers/SoundCloudUtil"; import { CommandManager } from "../utils/CommandManager"; import { EventsLoader } from "../utils/EventsLoader"; import { ClientUtils } from "../utils/ClientUtils"; -import { DiscLogger } from "../utils/DiscLogger"; +import { RawonLogger } from "../utils/RawonLogger"; import { formatMS } from "../utils/formatMS"; import * as config from "../config"; import { Client, ClientOptions } from "discord.js"; @@ -10,9 +10,9 @@ import { resolve } from "path"; import got from "got"; import { SpotifyUtil } from "../utils/handlers/SpotifyUtil"; -export class Disc extends Client { +export class Rawon extends Client { public readonly config = config; - public readonly logger = new DiscLogger({ prod: this.config.isProd }); + public readonly logger = new RawonLogger({ prod: this.config.isProd }); public readonly request = got; public readonly commands = new CommandManager(this, resolve(__dirname, "..", "commands")); public readonly events = new EventsLoader(this, resolve(__dirname, "..", "events")); @@ -22,14 +22,14 @@ export class Disc extends Client { public constructor(opt: ClientOptions) { super(opt); } - public async build(): Promise { + public build: () => Promise = async () => { const start = Date.now(); this.events.load(); - this.on("ready", async () => { - await this.commands.load(); + this.on("ready", () => { + this.commands.load(); this.logger.info(`Ready took ${formatMS(Date.now() - start)}`); }); await this.login(); return this; - } + }; } diff --git a/src/structures/ServerQueue.ts b/src/structures/ServerQueue.ts index 9770326c6..96bad99a4 100644 --- a/src/structures/ServerQueue.ts +++ b/src/structures/ServerQueue.ts @@ -7,14 +7,14 @@ export class ServerQueue { public loopMode: LoopMode = "OFF"; public shuffle = false; public stayInVC = this.textChannel.client.config.stayInVCAfterFinished; - public connection: VoiceConnection|null = null; - public player: AudioPlayer|null = null; - public dcTimeout: NodeJS.Timeout|null = null; - public timeout: NodeJS.Timeout|null = null; + public connection: VoiceConnection | null = null; + public player: AudioPlayer | null = null; + public dcTimeout: NodeJS.Timeout | null = null; + public timeout: NodeJS.Timeout | null = null; public readonly songs = new SongManager(); private _skipVoters: Snowflake[] = []; - private _lastMusicMsg: Snowflake|null = null; - private _lastVSUpdateMsg: Snowflake|null = null; + private _lastMusicMsg: Snowflake | null = null; + private _lastVSUpdateMsg: Snowflake | null = null; public constructor(public readonly textChannel: TextBasedChannel) { Object.defineProperties(this, { @@ -45,15 +45,19 @@ export class ServerQueue { } } + public get skipVoters(): Snowflake[] { + return this._skipVoters; + } + public set skipVoters(value: Snowflake[]) { this._skipVoters = value; } - public get skipVoters(): Snowflake[] { - return this._skipVoters; + public get lastMusicMsg(): Snowflake | null { + return this._lastMusicMsg; } - public set lastMusicMsg(value: Snowflake|null) { + public set lastMusicMsg(value: Snowflake | null) { if (this._lastMusicMsg !== null) { this.textChannel.messages.fetch(this._lastMusicMsg, { cache: false }) .then(msg => { @@ -64,11 +68,11 @@ export class ServerQueue { this._lastMusicMsg = value; } - public get lastMusicMsg(): Snowflake|null { - return this._lastMusicMsg; + public get lastVSUpdateMsg(): Snowflake | null { + return this._lastVSUpdateMsg; } - public set lastVSUpdateMsg(value: Snowflake|null) { + public set lastVSUpdateMsg(value: Snowflake | null) { if (this._lastVSUpdateMsg !== null) { this.textChannel.messages.fetch(this._lastVSUpdateMsg, { cache: false }) .then(msg => { @@ -79,8 +83,8 @@ export class ServerQueue { this._lastVSUpdateMsg = value; } - public get lastVSUpdateMsg(): Snowflake|null { - return this._lastVSUpdateMsg; + public get playing(): boolean { + return this.player?.state.status === AudioPlayerStatus.Playing; } public set playing(value: boolean) { @@ -91,11 +95,7 @@ export class ServerQueue { } } - public get playing(): boolean { - return this.player?.state.status === AudioPlayerStatus.Playing; - } - public get idle(): boolean { - return (this.player?.state.status === AudioPlayerStatus.Idle) && (this.songs.size === 0); + return this.player?.state.status === AudioPlayerStatus.Idle && this.songs.size === 0; } } diff --git a/src/typings/enum.ts b/src/typings/enum.ts index 124ad59c6..d7d1caccc 100644 --- a/src/typings/enum.ts +++ b/src/typings/enum.ts @@ -1,11 +1,12 @@ +/* eslint-disable @typescript-eslint/naming-convention */ export enum MessageComponentTypes { ACTION_ROW = 1, BUTTON = 2, - SELECT_MENU = 3, + SELECT_MENU = 3 } export enum InteractionTypes { PING = 1, APPLICATION_COMMAND = 2, - MESSAGE_COMPONENT = 3, + MESSAGE_COMPONENT = 3 } diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts index b302deee0..35c472afe 100644 --- a/src/typings/index.d.ts +++ b/src/typings/index.d.ts @@ -1,19 +1,28 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { CommandContext } from "../structures/CommandContext"; import { ServerQueue } from "../structures/ServerQueue"; -import { Disc } from "../structures/Disc"; +import { Rawon } from "../structures/Rawon"; import { ActivityType, ApplicationCommandOptionData, ApplicationCommandType, ClientEvents, ClientPresenceStatus, Client as OClient, Collection, GuildMember, MessageEmbed } from "discord.js"; -export type MessageInteractionAction = "editReply" | "reply" | "followUp"; +export type MessageInteractionAction = "editReply" | "followUp" | "reply"; export interface QueryData { isURL: boolean; - sourceType?: "youtube" | "spotify" | "soundcloud" | "query" | "unknown"; - type?: "track" | "playlist" | "unknown"; + sourceType?: "query" | "soundcloud" | "spotify" | "unknown" | "youtube"; + type?: "playlist" | "track" | "unknown"; +} + +export interface basicYoutubeVideoInfo { + id: string; + url: string; + title: string; + thumbnails: { url: string; width: number; height: number }[]; + duration: number; } export interface SearchTrackResult { - type?: "selection"|"results"; + type?: "results" | "selection"; items: ISong[]; } @@ -22,10 +31,10 @@ export interface PaginationPayload { content?: string; pages: string[]; embed: MessageEmbed; - edit(index: number, embed: MessageEmbed, page: string): unknown; + edit: (index: number, embed: MessageEmbed, page: string) => unknown; } -export interface IDiscLoggerOptions { +export interface IRawonLoggerOptions { prod: boolean; } @@ -45,7 +54,7 @@ export interface IpresenceData { export interface IEvent { readonly name: keyof ClientEvents; - execute(...args: any): void; + execute: (...args: any) => void; } export interface ICommandComponent { @@ -63,7 +72,7 @@ export interface ICommandComponent { contextChat?: string; contextUser?: string; }; - execute(context: CommandContext): any; + execute: (context: CommandContext) => any; } export interface ICategoryMeta { @@ -75,17 +84,17 @@ export interface ICategoryMeta { declare module "discord.js" { // @ts-expect-error Override typings export interface Client extends OClient { - config: Disc["config"]; - logger: Disc["logger"]; - request: Disc["request"]; - commands: Disc["commands"]; - events: Disc["events"]; + config: Rawon["config"]; + logger: Rawon["logger"]; + request: Rawon["request"]; + commands: Rawon["commands"]; + events: Rawon["events"]; - build(token: string): Promise; + build: () => Promise; } export interface Guild { - client: Disc; + client: Rawon; queue?: ServerQueue; } } @@ -105,7 +114,7 @@ export interface IQueueSong { key: string; } -export type LoopMode = "OFF"|"SONG"|"QUEUE"; +export type LoopMode = "OFF" | "QUEUE" | "SONG"; export interface ILyricsAPIResult { error: E; @@ -115,7 +124,7 @@ export interface ILyricsAPIResult { lyrics?: E extends true ? null : string; url?: E extends true ? null : string; message?: E extends true ? string : never; - synced: E extends true ? never : boolean|string; + synced: E extends true ? never : boolean | string; } export interface ISpotifyAccessTokenAPIResult { diff --git a/src/utils/ButtonPagination.ts b/src/utils/ButtonPagination.ts index 78f9e5283..63db16195 100644 --- a/src/utils/ButtonPagination.ts +++ b/src/utils/ButtonPagination.ts @@ -30,7 +30,11 @@ const DATAS: InteractionButtonOptions[] = [ ]; export class ButtonPagination { - public constructor(public readonly msg: Interaction|CommandInteraction|SelectMenuInteraction|ContextMenuInteraction|Message, public readonly payload: PaginationPayload) {} + public constructor(public readonly msg: CommandInteraction + | ContextMenuInteraction + | Interaction + | Message + | SelectMenuInteraction, public readonly payload: PaginationPayload) {} public async start(): Promise { const embed = this.payload.embed; diff --git a/src/utils/ClientUtils.ts b/src/utils/ClientUtils.ts index ecd3dea78..b3eec178b 100644 --- a/src/utils/ClientUtils.ts +++ b/src/utils/ClientUtils.ts @@ -1,10 +1,11 @@ -import { Disc } from "../structures/Disc"; +/* eslint-disable class-methods-use-this */ +import { Rawon } from "../structures/Rawon"; import { Guild, Role } from "discord.js"; import { parse, resolve } from "path"; import { FFmpeg } from "prism-media"; export class ClientUtils { - public constructor(public readonly client: Disc) {} + public constructor(public readonly client: Rawon) {} public async fetchMuteRole(guild: Guild): Promise { return guild.roles.cache.find(x => x.name === this.client.config.muteRoleName) ?? guild.roles.create({ @@ -95,15 +96,15 @@ export class ClientUtils { } public async import(path: string, ...args: any[]): Promise { - const file = (await import(resolve(path)).then(m => m[parse(path).name])); - return file ? new file(...args) : undefined; + const file = await import(resolve(path)).then(m => (m as Record T) | undefined>)[parse(path).name]); + return file ? new file(...(args as unknown[])) : undefined; } public getFFmpegVersion(): string { try { const ffmpeg = FFmpeg.getInfo(); - return ffmpeg.version.split(/_|-| /).find(x => /[0-9.]/.test(x))?.replace(/[^0-9.]/g, "") ?? "Unknown"; - } catch (e) { + return ffmpeg.version.split(/_|-| /).find(x => (/[0-9.]/).test(x))?.replace(/[^0-9.]/g, "") ?? "Unknown"; + } catch { return "Unknown"; } } diff --git a/src/utils/CommandManager.ts b/src/utils/CommandManager.ts index e13e53b4d..a0a677d7a 100644 --- a/src/utils/CommandManager.ts +++ b/src/utils/CommandManager.ts @@ -1,7 +1,7 @@ import { CommandContext } from "../structures/CommandContext"; import { ICategoryMeta, ICommandComponent } from "../typings"; import { createEmbed } from "./createEmbed"; -import { Disc } from "../structures/Disc"; +import { Rawon } from "../structures/Rawon"; import i18n from "../config"; import { ApplicationCommandData, Collection, Message, Snowflake, TextChannel } from "discord.js"; import { promises as fs } from "fs"; @@ -13,7 +13,7 @@ export class CommandManager extends Collection { public readonly aliases: Collection = new Collection(); private readonly cooldowns: Collection> = new Collection(); - public constructor(public client: Disc, private readonly path: string) { super(); } + public constructor(public client: Rawon, private readonly path: string) { super(); } public load(): void { fs.readdir(resolve(this.path)) @@ -46,7 +46,7 @@ export class CommandManager extends Collection { if (command.meta.contextChat) { if (this.client.config.isDev) { - for (const guild of this.client.config.devGuild) { + for (const guild of this.client.config.devGuild as string) { const g = await this.client.guilds.fetch({ guild }); await g.commands.create({ @@ -66,7 +66,7 @@ export class CommandManager extends Collection { } if (command.meta.contextUser) { if (this.client.config.isDev) { - for (const guild of this.client.config.devGuild) { + for (const guild of this.client.config.devGuild as string) { const g = await this.client.guilds.fetch({ guild }); await g.commands.create({ @@ -89,7 +89,7 @@ export class CommandManager extends Collection { if (!command.meta.slash.description) Object.assign(command.meta.slash, { description: command.meta.description }); if (this.client.config.isDev) { - for (const guild of this.client.config.devGuild) { + for (const guild of this.client.config.devGuild as string) { const g = await this.client.guilds.fetch({ guild }); await g.commands.create(command.meta.slash as ApplicationCommandData) .catch(() => this.client.logger.info(`Missing access on ${guild} [SLASH_COMMAND]`)); @@ -109,7 +109,7 @@ export class CommandManager extends Collection { return { disabledCount, files }; }) .then(data => { - this.categories.set(category, Object.assign(meta, { cmds: this.filter(({ meta }) => meta.category === category) })); + this.categories.set(category, Object.assign(meta, { cmds: this.filter(c => c.meta.category === category) })); this.client.logger.info(`Done loading ${data.files.length} commands in ${category} category.`); if (data.disabledCount !== 0) this.client.logger.info(`${data.disabledCount} out of ${data.files.length} commands in ${category} category is disabled.`); }) @@ -125,8 +125,9 @@ export class CommandManager extends Collection { }); } - public async handle(message: Message, pref: string): Promise { - const prefix = pref === "{mention}" ? /<@(!)?\d*?>/.exec(message.content)![0] : pref; + public handle(message: Message, pref: string): void { + // eslint-disable-next-line prefer-named-capture-group + const prefix = pref === "{mention}" ? (/<@(!)?\d*?>/).exec(message.content)![0] : pref; const args = message.content.substring(prefix.length).trim().split(/ +/); const cmd = args.shift()?.toLowerCase(); const command = this.get(cmd!) ?? this.get(this.aliases.get(cmd!)!); diff --git a/src/utils/EventsLoader.ts b/src/utils/EventsLoader.ts index d01faf30c..979e8ddb8 100644 --- a/src/utils/EventsLoader.ts +++ b/src/utils/EventsLoader.ts @@ -1,10 +1,10 @@ -import { Disc } from "../structures/Disc"; +import { Rawon } from "../structures/Rawon"; import { IEvent } from "../typings"; import { promises as fs } from "fs"; import { resolve } from "path"; export class EventsLoader { - public constructor(public client: Disc, public path: string) {} + public constructor(public client: Rawon, public path: string) {} public load(): void { fs.readdir(resolve(this.path)) .then(async events => { diff --git a/src/utils/OperationManager.ts b/src/utils/OperationManager.ts index 27ea871c9..ec93ac7c8 100644 --- a/src/utils/OperationManager.ts +++ b/src/utils/OperationManager.ts @@ -1,6 +1,6 @@ export class OperationManager { private _runningOperation!: boolean; - private readonly operations: (() => void)[] = []; + private readonly operations: (() => Promise | undefined)[] = []; public constructor() { Object.defineProperty(this, "_runningOperation", { @@ -15,7 +15,7 @@ export class OperationManager { return this._runningOperation; } - public add(operation: () => void): void { + public add(operation: () => undefined): void { this.operations.push(operation); if (!this.runningOperation) { diff --git a/src/utils/DiscLogger.ts b/src/utils/RawonLogger.ts similarity index 50% rename from src/utils/DiscLogger.ts rename to src/utils/RawonLogger.ts index fcd79cec0..6c9619b69 100644 --- a/src/utils/DiscLogger.ts +++ b/src/utils/RawonLogger.ts @@ -1,4 +1,4 @@ -import { IDiscLoggerOptions } from "../typings"; +import { IRawonLoggerOptions } from "../typings"; import { format } from "date-fns"; enum Colors { @@ -9,8 +9,8 @@ enum Colors { Blue = "\x1b[34m" } -export class DiscLogger { - public constructor(public readonly options: IDiscLoggerOptions) {} +export class RawonLogger { + public constructor(public readonly options: IRawonLoggerOptions) {} public info(...messages: any[]): void { this.log(messages, "info"); @@ -28,9 +28,10 @@ export class DiscLogger { this.log(messages, "warn"); } - private log(messages: any[], level: "info"|"debug"|"error"|"warn" = "info"): void { + private log(messages: any[], level: "debug" | "error" | "info" | "warn" = "info"): void { if (this.options.prod && level === "debug") return; - console[level](`${this.options.prod ? "" : (level === "debug" ? Colors.Blue : (level === "error" ? Colors.Red : (level === "warn" ? Colors.Yellow : Colors.Green)))}[${format(Date.now(), "yyyy-MM-dd HH:mm:ss (x)")}] [${level}]: ${messages.map(x => String(x)).join(" ")} ${Colors.Reset}`); + // eslint-disable-next-line no-nested-ternary + console[level](`${this.options.prod ? "" : level === "debug" ? Colors.Blue : level === "error" ? Colors.Red : level === "warn" ? Colors.Yellow : Colors.Green}[${format(Date.now(), "yyyy-MM-dd HH:mm:ss (x)")}] [${level}]: ${messages.map(x => String(x)).join(" ")} ${Colors.Reset}`); } } diff --git a/src/utils/SongManager.ts b/src/utils/SongManager.ts index cb19fef89..5a17536c6 100644 --- a/src/utils/SongManager.ts +++ b/src/utils/SongManager.ts @@ -15,7 +15,7 @@ export class SongManager extends Collection { return key; } - public sortByIndex(): SongManager { + public sortByIndex(): this { return this.sort((a, b) => a.index - b.index); } } diff --git a/src/utils/chunk.ts b/src/utils/chunk.ts index aefbfe5e1..235e88a24 100644 --- a/src/utils/chunk.ts +++ b/src/utils/chunk.ts @@ -3,6 +3,6 @@ export function chunk(arr: string, len: number): string[]; export function chunk(...args: any[]): any[] { const [arr, len] = args as [any, number]; const rest: (typeof arr)[] = []; - for (let i = 0; i < arr.length; i += len) { rest.push(arr.slice(i, i + len)); } + for (let i = 0; i < (arr as string).length; i += len) { rest.push((arr as string).slice(i, i + len)); } return rest; } diff --git a/src/utils/createEmbed.ts b/src/utils/createEmbed.ts index 0e6205533..2d01e0ea0 100644 --- a/src/utils/createEmbed.ts +++ b/src/utils/createEmbed.ts @@ -1,7 +1,7 @@ import { embedColor, noEmoji, yesEmoji } from "../config"; import { ColorResolvable, MessageEmbed } from "discord.js"; -type hexColorsType = "info" | "warn" | "error" | "success"; +type hexColorsType = "error" | "info" | "success" | "warn"; const hexColors: Record = { error: "RED", info: embedColor, diff --git a/src/utils/functions/createTable.ts b/src/utils/functions/createTable.ts new file mode 100644 index 000000000..721890111 --- /dev/null +++ b/src/utils/functions/createTable.ts @@ -0,0 +1,16 @@ +export function createTable(values: string[][]): string { + const value = values.map(x => `${x.map((y, i) => { + const sortingArr = [...values]; + const spacing = " ".repeat( + sortingArr.sort( + (a, b) => (b[i] ?? "").length - (a[i] ?? "").length + )[0][i].length - y.length + ); + + return `${y}${spacing}`; + }) + .join(" :: ")}`) + .join("\n"); + + return value; +} diff --git a/src/utils/handlers/GeneralUtil.ts b/src/utils/handlers/GeneralUtil.ts index cda5bf2c4..766cc281e 100644 --- a/src/utils/handlers/GeneralUtil.ts +++ b/src/utils/handlers/GeneralUtil.ts @@ -5,7 +5,7 @@ import { parseHTMLElements } from "../parseHTMLElements"; import { ButtonPagination } from "../ButtonPagination"; import { getInfo, getStream } from "./YTDLUtil"; import { createEmbed } from "../createEmbed"; -import { Disc } from "../../structures/Disc"; +import { Rawon } from "../../structures/Rawon"; import { youtube } from "./YouTubeUtil"; import { chunk } from "../chunk"; import i18n from "../../config"; @@ -14,7 +14,7 @@ import { Guild, Message, StageChannel, Util, VoiceChannel } from "discord.js"; import { SearchResult, Video } from "youtubei"; import { URL } from "url"; -export async function searchTrack(client: Disc, query: string, source: "soundcloud" | "youtube" | undefined = "youtube"): Promise { +export async function searchTrack(client: Rawon, query: string, source: "soundcloud" | "youtube" | undefined = "youtube"): Promise { const result: SearchTrackResult = { items: [] }; @@ -61,7 +61,7 @@ export async function searchTrack(client: Disc, query: string, source: "soundclo } } else if (queryData.sourceType === "youtube") { if (queryData.type === "track") { - const track = await youtube.getVideo(url.toString()); + const track = await youtube.getVideo((/youtu\.be/g).exec(url.hostname) ? url.pathname.replace("/", "") : url.toString()); if (track) { result.items = [{ @@ -88,6 +88,7 @@ export async function searchTrack(client: Disc, query: string, source: "soundclo } } } else if (queryData.sourceType === "spotify") { + // eslint-disable-next-line no-inner-declarations function sortVideos(track: SpotifyTrack, videos: SearchResult<"video">): SearchResult<"video"> { return videos.sort((a, b) => { let aValue = 0; @@ -98,13 +99,13 @@ export async function searchTrack(client: Disc, query: string, source: "soundclo if (a.title.toLowerCase().includes(track.name.toLowerCase())) aValue--; if (track.artists.some(x => a.channel?.name.toLowerCase().includes(x.name))) aValue--; if (a.channel?.name.endsWith("- Topic")) aValue -= 2; - if (aDurationDiff ? (aDurationDiff <= 5000 && aDurationDiff >= -5000) : false) aValue -= 2; + if (aDurationDiff ? aDurationDiff <= 5000 && aDurationDiff >= -5000 : false) aValue -= 2; // "b" variable check if (b.title.toLowerCase().includes(track.name.toLowerCase())) bValue++; if (track.artists.some(x => b.channel?.name.toLowerCase().includes(x.name))) bValue++; if (b.channel?.name.endsWith(" - Topic")) bValue += 2; - if (bDurationDiff ? (bDurationDiff <= 5000 && bDurationDiff >= -5000) : false) bValue += 2; + if (bDurationDiff ? bDurationDiff <= 5000 && bDurationDiff >= -5000 : false) bValue += 2; return aValue + bValue; }); @@ -184,7 +185,7 @@ export function checkQuery(string: string): QueryData { let url: URL; try { url = new URL(string); - } catch (e) { + } catch { return { isURL: false, sourceType: "query" @@ -195,7 +196,7 @@ export function checkQuery(string: string): QueryData { isURL: true }; - if (/soundcloud|snd/g.exec(url.hostname)) { + if ((/soundcloud|snd/g).exec(url.hostname)) { result.sourceType = "soundcloud"; if (url.pathname.includes("/sets/")) { @@ -203,17 +204,17 @@ export function checkQuery(string: string): QueryData { } else { result.type = "track"; } - } else if (/youtube|youtu\.be/g.exec(url.hostname)) { + } else if ((/youtube|youtu\.be/g).exec(url.hostname)) { result.sourceType = "youtube"; - if (!/youtu\.be/g.exec(url.hostname) && url.pathname.startsWith("/playlist")) { + if (!(/youtu\.be/g).exec(url.hostname) && url.pathname.startsWith("/playlist")) { result.type = "playlist"; - } else if ((/youtube/g.exec(url.hostname) && url.pathname.startsWith("/watch")) || (/youtu\.be/g.exec(url.hostname) && (url.pathname !== ""))) { + } else if (((/youtube/g).exec(url.hostname) && url.pathname.startsWith("/watch")) || ((/youtu\.be/g).exec(url.hostname) && url.pathname !== "")) { result.type = "track"; } else { result.type = "unknown"; } - } else if (/spotify/g.exec(url.hostname)) { + } else if ((/spotify/g).exec(url.hostname)) { result.sourceType = "spotify"; if (url.pathname.startsWith("/playlist")) { @@ -231,7 +232,7 @@ export function checkQuery(string: string): QueryData { return result; } -export async function handleVideos(client: Disc, ctx: CommandContext, toQueue: ISong[], voiceChannel: VoiceChannel | StageChannel): Promise { +export async function handleVideos(client: Rawon, ctx: CommandContext, toQueue: ISong[], voiceChannel: StageChannel | VoiceChannel): Promise { const wasIdle = ctx.guild?.queue?.idle; async function sendPagination(): Promise { @@ -286,17 +287,18 @@ export async function handleVideos(client: Disc, ctx: CommandContext, toQueue: I delete ctx.guild!.queue; client.logger.error("PLAY_CMD_ERR:", error); - return ctx.channel!.send({ + void ctx.channel!.send({ embeds: [createEmbed("error", i18n.__mf("utils.generalHandler.errorJoining", { message: `\`${(error as Error).message}\`` }), true)] }).catch(e => { client.logger.error("PLAY_CMD_ERR:", e); }); + return; } void play(client, ctx.guild!); } -export async function play(client: Disc, guild: Guild, nextSong?: string, wasIdle?: boolean): Promise { +export async function play(client: Rawon, guild: Guild, nextSong?: string, wasIdle?: boolean): Promise { const queue = guild.queue; if (!queue) return; if (queue.player === null) queue.player = createAudioPlayer(); @@ -329,7 +331,7 @@ export async function play(client: Disc, guild: Guild, nextSong?: string, wasIdl async function playResource(): Promise { if (guild.channels.cache.get(queue!.connection!.joinConfig.channelId!)?.type === "GUILD_STAGE_VOICE") { const suppressed = await guild.me?.voice.setSuppressed(false).catch(err => ({ error: err })); - if (suppressed && ("error" in suppressed)) { + if (suppressed && "error" in suppressed) { queue?.player?.emit("error", new AudioPlayerError(suppressed.error as Error, resource)); return; } @@ -348,6 +350,7 @@ export async function play(client: Disc, guild: Guild, nextSong?: string, wasIdl if (wasIdle) { void playResource(); } else { + // eslint-disable-next-line max-lines entersState(queue.connection!, VoiceConnectionStatus.Ready, 15000) .then(async () => { await playResource(); @@ -358,8 +361,10 @@ export async function play(client: Disc, guild: Guild, nextSong?: string, wasIdl }); } + queue.player.removeAllListeners(); + queue.player.on("stateChange", (oldState, newState) => { - if ((newState.status === AudioPlayerStatus.Playing) && (oldState.status !== AudioPlayerStatus.Paused)) { + if (newState.status === AudioPlayerStatus.Playing && oldState.status !== AudioPlayerStatus.Paused) { const newSong = ((queue.player!.state as AudioPlayerPlayingState).resource.metadata as IQueueSong).song; sendStartPlayingMsg(newSong); } else if (newState.status === AudioPlayerStatus.Idle) { @@ -369,16 +374,17 @@ export async function play(client: Disc, guild: Guild, nextSong?: string, wasIdl queue.songs.delete(song.key); } - const nextSong = (queue.shuffle && (queue.loopMode !== "SONG")) ? queue.songs.random()?.key : (queue.loopMode === "SONG" ? song.key : queue.songs.sortByIndex().filter(x => x.index > song.index).first()?.key ?? (queue.loopMode === "QUEUE" ? (queue.songs.sortByIndex().first()?.key ?? "") : "")); + // eslint-disable-next-line no-nested-ternary + const nextS = queue.shuffle && queue.loopMode !== "SONG" ? queue.songs.random()?.key : queue.loopMode === "SONG" ? song.key : queue.songs.sortByIndex().filter(x => x.index > song.index).first()?.key ?? (queue.loopMode === "QUEUE" ? queue.songs.sortByIndex().first()?.key ?? "" : ""); queue.textChannel.send({ embeds: [createEmbed("info", `⏹ **|** ${i18n.__mf("utils.generalHandler.stopPlaying", { song: `[${song.song.title}](${song.song.url})` })}`).setThumbnail(song.song.thumbnail)] }) .then(m => queue.lastMusicMsg = m.id) .catch(e => client.logger.error("PLAY_ERR:", e)) .finally(() => { queue.player = null; - play(client, guild, nextSong).catch(e => { - queue.textChannel.send({ embeds: [createEmbed("error", i18n.__mf("utils.generalHandler.errorPlaying", { message: `\`${e}\`` }), true)] }) - .catch(e => client.logger.error("PLAY_ERR:", e)); + play(client, guild, nextS).catch(e => { + queue.textChannel.send({ embeds: [createEmbed("error", i18n.__mf("utils.generalHandler.errorPlaying", { message: `\`${e as string}\`` }), true)] }) + .catch(er => client.logger.error("PLAY_ERR:", er)); queue.connection?.disconnect(); return client.logger.error("PLAY_ERR:", e); }); diff --git a/src/utils/handlers/SpotifyUtil.ts b/src/utils/handlers/SpotifyUtil.ts index 3a04e78e3..c22023e33 100644 --- a/src/utils/handlers/SpotifyUtil.ts +++ b/src/utils/handlers/SpotifyUtil.ts @@ -1,12 +1,13 @@ -import { Disc } from "../../structures/Disc"; +import { Rawon } from "../../structures/Rawon"; import { ISpotifyAccessTokenAPIResult, SpotifyPlaylist, SpotifyTrack } from "../../typings"; export class SpotifyUtil { - public spotifyRegex = /(?:https:\/\/open\.spotify\.com\/|spotify:)(?:.+)?(track|playlist|album)[\/:]([A-Za-z0-9]+)/; + // eslint-disable-next-line prefer-named-capture-group + public spotifyRegex = /(?:https:\/\/open\.spotify\.com\/|spotify:)(?:.+)?(track|playlist|album)[/:]([A-Za-z0-9]+)/; public baseURI = "https://api.spotify.com/v1"; private token!: string; - public constructor(public client: Disc) {} + public constructor(public client: Rawon) {} public async fetchToken(): Promise { const { accessToken, accessTokenExpirationTimestampMs } = await this.client.request.get("https://open.spotify.com/get_access_token?reason=transport&productType=embed", { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59" } }).json(); @@ -20,8 +21,8 @@ export class SpotifyUtil { setTimeout(() => this.renew(), lastRenew); } - public resolveTracks(url: string): Promise | Promise<{ track: SpotifyTrack }[]> | void { - const [, type, id] = url.match(this.spotifyRegex) ?? []; + public resolveTracks(url: string): Promise<{ track: SpotifyTrack }[]> | Promise | undefined { + const [, type, id] = this.spotifyRegex.exec(url) ?? []; switch (type) { case "track": { return this.getTrack(id); diff --git a/src/utils/handlers/YTDLUtil.ts b/src/utils/handlers/YTDLUtil.ts index f1bda7c16..ca76de8bb 100644 --- a/src/utils/handlers/YTDLUtil.ts +++ b/src/utils/handlers/YTDLUtil.ts @@ -1,7 +1,21 @@ -import ytdl, { exec, YtResponse } from "youtube-dl-exec"; +import { basicYoutubeVideoInfo } from "../../typings"; +import { soundcloud } from "./SoundCloudUtil"; +import { streamStrategy } from "../../config"; +import { checkQuery } from "./GeneralUtil"; +import { stream as pldlStream, video_basic_info } from "play-dl"; +import ytdl, { exec } from "youtube-dl-exec"; import { Readable } from "stream"; -export function getStream(url: string): Promise { +export async function getStream(url: string): Promise { + if (streamStrategy === "play-dl") { + const isSoundcloudUrl = checkQuery(url); + if (isSoundcloudUrl.sourceType === "soundcloud") { + return soundcloud.util.streamTrack(url) as unknown as Readable; + } + const rawPlayDlStream = await pldlStream(url, { discordPlayerCompatibility: true }); + return rawPlayDlStream.stream; + } + return new Promise((resolve, reject) => { const stream = exec( url, @@ -21,13 +35,22 @@ export function getStream(url: string): Promise { } void stream.on("spawn", () => { - resolve(stream.stdout as Readable); + resolve(stream.stdout!); }); }); } -export async function getInfo(url: string): Promise { - return ytdl(url, { +export async function getInfo(url: string): Promise { + if (streamStrategy === "play-dl") { + const rawPlayDlVideoInfo = await video_basic_info(url); + return { + duration: rawPlayDlVideoInfo.video_details.durationInSec * 1000, + id: rawPlayDlVideoInfo.video_details.id!, + thumbnails: rawPlayDlVideoInfo.video_details.thumbnails, + title: rawPlayDlVideoInfo.video_details.title!, + url: rawPlayDlVideoInfo.video_details.url + }; + } return ytdl(url, { dumpJson: true }); }