diff --git a/.gitignore b/.gitignore index d5f8e9e..012962c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ docker-compose.yml dist/ # Databse -*.sqlite3 +*.sqlite3* # Debug file src/events/player/debug.ts diff --git a/package-lock.json b/package-lock.json index bb3a72b..dfe19ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,21 +11,19 @@ "dependencies": { "@discord-player/extractor": "^4.5.1", "@discordjs/rest": "^2.4.0", - "@types/sqlite3": "^3.1.11", - "@types/uuid": "^10.0.0", "discord-player": "^6.7.1", - "discord-player-youtubei": "^1.3.2", + "discord-player-youtubei": "^1.3.4", "discord.js": "^14.16.3", "mediaplex": "^0.0.9", "moment-timezone": "^0.5.46", "sqlite3": "^5.1.7", "typescript": "^5.6.3", - "uuid": "^10.0.0" + "uuid": "^11.0.2" }, "devDependencies": { - "@types/jest": "~29.5.13", - "@typescript-eslint/eslint-plugin": "~8.8.1", - "@typescript-eslint/parser": "~8.8.1", + "@types/jest": "~29.5.14", + "@typescript-eslint/eslint-plugin": "~8.12.2", + "@typescript-eslint/parser": "~8.12.2", "dotenv": "~16.4.5", "jest": "~29.7.0", "prettier-eslint": "~16.3.0", @@ -48,13 +46,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", - "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -62,9 +61,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz", - "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", "dev": true, "license": "MIT", "engines": { @@ -72,22 +71,22 @@ } }, "node_modules/@babel/core": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.8.tgz", - "integrity": "sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.25.7", - "@babel/generator": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helpers": "^7.25.7", - "@babel/parser": "^7.25.8", - "@babel/template": "^7.25.7", - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.8", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -113,13 +112,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", - "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.7", + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -129,14 +129,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", - "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -156,30 +156,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", - "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", - "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-simple-access": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -189,33 +188,19 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", - "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", - "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, "license": "MIT", "engines": { @@ -223,9 +208,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "license": "MIT", "engines": { @@ -233,9 +218,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", - "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, "license": "MIT", "engines": { @@ -243,121 +228,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", - "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", - "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", - "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.8" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -422,13 +313,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", - "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -464,13 +355,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.7.tgz", - "integrity": "sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -590,13 +481,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", - "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -606,32 +497,32 @@ } }, "node_modules/@babel/template": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", - "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", - "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/generator": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7", + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -650,15 +541,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", - "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -672,9 +562,9 @@ "license": "MIT" }, "node_modules/@bufbuild/protobuf": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.0.tgz", - "integrity": "sha512-+imAQkHf7U/Rwvu0wk1XWgsP3WnpCWmK7B48f0XqSNzgk64+grljTKC7pnO/xBiEMUziF7vKRfbBnOQhg126qQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.2.tgz", + "integrity": "sha512-UNtPCbrwrenpmrXuRwn9jYpPoweNXj8X5sMvYgsqYyaH8jQ6LfUJSk3dJLnBK+6sfYPrF4iAIo5sd5HQ+tg75A==", "license": "(Apache-2.0 AND BSD-3-Clause)" }, "node_modules/@cspotcode/source-map-support": { @@ -866,25 +756,28 @@ "license": "MIT" }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { @@ -1747,9 +1640,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.13", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.13.tgz", - "integrity": "sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==", + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1758,21 +1651,12 @@ } }, "node_modules/@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "version": "22.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", + "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@types/sqlite3": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@types/sqlite3/-/sqlite3-3.1.11.tgz", - "integrity": "sha512-KYF+QgxAnnAh7DWPdNDroxkDI3/MspH1NMx6m/N/6fT1G6+jvsw4/ZePt8R8cr7ta58aboeTfYFBDxTJ5yv15w==", - "license": "MIT", - "dependencies": { - "@types/node": "*" + "undici-types": "~6.19.8" } }, "node_modules/@types/stack-utils": { @@ -1796,16 +1680,10 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "license": "MIT" - }, "node_modules/@types/ws": { - "version": "8.5.12", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", - "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -1829,17 +1707,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz", - "integrity": "sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.2.tgz", + "integrity": "sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.8.1", - "@typescript-eslint/type-utils": "8.8.1", - "@typescript-eslint/utils": "8.8.1", - "@typescript-eslint/visitor-keys": "8.8.1", + "@typescript-eslint/scope-manager": "8.12.2", + "@typescript-eslint/type-utils": "8.12.2", + "@typescript-eslint/utils": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1863,16 +1741,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.1.tgz", - "integrity": "sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.2.tgz", + "integrity": "sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.8.1", - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/typescript-estree": "8.8.1", - "@typescript-eslint/visitor-keys": "8.8.1", + "@typescript-eslint/scope-manager": "8.12.2", + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/typescript-estree": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2", "debug": "^4.3.4" }, "engines": { @@ -1892,14 +1770,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz", - "integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz", + "integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/visitor-keys": "8.8.1" + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1910,14 +1788,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.1.tgz", - "integrity": "sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.12.2.tgz", + "integrity": "sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.8.1", - "@typescript-eslint/utils": "8.8.1", + "@typescript-eslint/typescript-estree": "8.12.2", + "@typescript-eslint/utils": "8.12.2", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1935,9 +1813,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz", - "integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz", + "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==", "dev": true, "license": "MIT", "engines": { @@ -1949,14 +1827,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz", - "integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz", + "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/visitor-keys": "8.8.1", + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1978,16 +1856,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz", - "integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz", + "integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.8.1", - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/typescript-estree": "8.8.1" + "@typescript-eslint/scope-manager": "8.12.2", + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/typescript-estree": "8.12.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2001,13 +1879,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz", - "integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz", + "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/types": "8.12.2", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2052,9 +1930,9 @@ "optional": true }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -2405,6 +2283,15 @@ ], "license": "MIT" }, + "node_modules/bgutils-js": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bgutils-js/-/bgutils-js-3.1.0.tgz", + "integrity": "sha512-2S80c/B4OQFubJLD5ddRRp74utrvjA70x9U0RsIVK7gJaDnaPrbw+bnXWxnEnc0euLznmO9jxOtTTC7FxGmv6w==", + "funding": [ + "https://github.com/sponsors/LuanRT" + ], + "license": "MIT" + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2468,9 +2355,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", - "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -2488,10 +2375,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001663", - "electron-to-chromium": "^1.5.28", + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -2625,9 +2512,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001668", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz", - "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==", + "version": "1.0.30001676", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz", + "integrity": "sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==", "dev": true, "funding": [ { @@ -3087,18 +2974,30 @@ } }, "node_modules/discord-player-youtubei": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/discord-player-youtubei/-/discord-player-youtubei-1.3.2.tgz", - "integrity": "sha512-NtKtLiR9HMYfTDXYvBeQCE+k3eegjB+ttaBq7gYdldIghBZ4fYHb0ERsAcY6lN4bQyAq0DaPFRIRbyk9Pi0TSg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/discord-player-youtubei/-/discord-player-youtubei-1.3.4.tgz", + "integrity": "sha512-8CHI32h7BR+9wX2gMfpnnmbkhfERzelOQtLJ285ZUMP9pfg2iBdzJZAFk6oecHzEtPQhe/fv9qZukiy1C97LVQ==", "license": "Creative Commons", "dependencies": { + "bgutils-js": "^3.1.0", + "happy-dom": "^15.7.4", "tiny-typed-emitter": "^2.1.0", - "youtubei.js": "^10.5.0" + "undici": "^6.20.0", + "youtubei.js": "^11.0.1" }, "bin": { "discord-player-youtubei": "bin/index.js" } }, + "node_modules/discord-player-youtubei/node_modules/undici": { + "version": "6.20.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.20.1.tgz", + "integrity": "sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/discord-voip": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/discord-voip/-/discord-voip-0.1.3.tgz", @@ -3273,9 +3172,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.36", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.36.tgz", - "integrity": "sha512-HYTX8tKge/VNp6FGO+f/uVDmUkq+cEfcxYhKf15Akc4M5yxt5YmorwlAitKWjWhWQnKcDRBAQKXkhqqXMqcrjw==", + "version": "1.5.50", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", + "integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==", "dev": true, "license": "ISC" }, @@ -4097,6 +3996,20 @@ "dev": true, "license": "MIT" }, + "node_modules/happy-dom": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-15.8.0.tgz", + "integrity": "sha512-LwBvPvR4MQ1xfrf4gbWRJzeL2xQqWiEiHvZF5uA1AwlCCgjH9ht0fGVXciRGQCghdHAIXw1zGX1mJ6a3O0fpeA==", + "license": "MIT", + "dependencies": { + "entities": "^4.5.0", + "webidl-conversions": "^7.0.0", + "whatwg-mimetype": "^3.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -5207,9 +5120,9 @@ } }, "node_modules/jintr": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/jintr/-/jintr-2.1.1.tgz", - "integrity": "sha512-89cwX4ouogeDGOBsEVsVYsnWWvWjchmwXBB4kiBhmjOKw19FiOKhNhMhpxhTlK2ctl7DS+d/ethfmuBpzoNNgA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jintr/-/jintr-3.0.2.tgz", + "integrity": "sha512-5g2EBudeJFOopjAX4exAv5OCCW1DgUISfoioCsm1h9Q9HJ41LmnZ6J52PCsqBlQihsmp0VDuxreAVzM7yk5nFA==", "funding": [ "https://github.com/sponsors/LuanRT" ], @@ -6022,9 +5935,9 @@ "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "license": "MIT", "optional": true, "engines": { @@ -6032,9 +5945,9 @@ } }, "node_modules/node-abi": { - "version": "3.68.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.68.0.tgz", - "integrity": "sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==", + "version": "3.71.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz", + "integrity": "sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==", "license": "MIT", "dependencies": { "semver": "^7.3.5" @@ -6397,9 +6310,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -7647,16 +7560,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7704,9 +7607,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", "dev": true, "license": "MIT", "engines": { @@ -7898,9 +7801,9 @@ } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/tunnel-agent": { @@ -8056,16 +7959,16 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.2.tgz", + "integrity": "sha512-14FfcOJmqdjbBPdDjFQyk/SdT4NySW4eM0zcG+HqbHP5jzuH56xO3J1DGhgs/cEMCfwYi3HQI1gnTO62iaG+tQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { @@ -8135,10 +8038,22 @@ } }, "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "license": "MIT", + "engines": { + "node": ">=12" + } }, "node_modules/whatwg-url": { "version": "5.0.0", @@ -8150,6 +8065,12 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/whatwg-url/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8331,16 +8252,16 @@ "license": "Apache-2.0" }, "node_modules/youtubei.js": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/youtubei.js/-/youtubei.js-10.5.0.tgz", - "integrity": "sha512-iyA+VF28c15tCCKH9ExM2RKC3zYiHzA/eixGlJ3vERANkuI+xYKzAZ4vtOhmyqwrAddu88R/DkzEsmpph5NWjg==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/youtubei.js/-/youtubei.js-11.0.1.tgz", + "integrity": "sha512-ZsbOd+5XF2Ofi3FrLMfYd+f9g9H8xswlouFhjhOqbwT68dMJtX6CRGsHNj5VTFCR/+L/865x1lnUlllB2dDDTA==", "funding": [ "https://github.com/sponsors/LuanRT" ], "license": "MIT", "dependencies": { "@bufbuild/protobuf": "^2.0.0", - "jintr": "^2.1.1", + "jintr": "^3.0.2", "tslib": "^2.5.0", "undici": "^5.19.1" } diff --git a/package.json b/package.json index 51f64eb..229b936 100644 --- a/package.json +++ b/package.json @@ -21,21 +21,19 @@ "dependencies": { "@discord-player/extractor": "^4.5.1", "@discordjs/rest": "^2.4.0", - "@types/sqlite3": "^3.1.11", - "@types/uuid": "^10.0.0", "discord-player": "^6.7.1", - "discord-player-youtubei": "^1.3.2", + "discord-player-youtubei": "^1.3.4", "discord.js": "^14.16.3", "mediaplex": "^0.0.9", "moment-timezone": "^0.5.46", "sqlite3": "^5.1.7", "typescript": "^5.6.3", - "uuid": "^10.0.0" + "uuid": "^11.0.2" }, "devDependencies": { - "@types/jest": "~29.5.13", - "@typescript-eslint/eslint-plugin": "~8.8.1", - "@typescript-eslint/parser": "~8.8.1", + "@types/jest": "~29.5.14", + "@typescript-eslint/eslint-plugin": "~8.12.2", + "@typescript-eslint/parser": "~8.12.2", "dotenv": "~16.4.5", "jest": "~29.7.0", "prettier-eslint": "~16.3.0", diff --git a/src/commands/misc/help.ts b/src/commands/misc/help.ts index 45e7210..a3811c3 100644 --- a/src/commands/misc/help.ts +++ b/src/commands/misc/help.ts @@ -1,8 +1,20 @@ import { SlashCommandBuilder } from "@discordjs/builders"; -import { ChatInputCommandInteraction, Client, Colors, EmbedBuilder } from "discord.js"; +import { + ApplicationCommandOptionType, + ChatInputCommandInteraction, + Client, + Colors, + EmbedBuilder, +} from "discord.js"; import "../../modules/string"; import { getLocale, getLocalizations } from "../../utils/locales"; import { getFilename } from "../../utils/misc"; +import { + goodDescription, + goodName, + NameNotLocalized, + SubnameNotLocalized, +} from "../../utils/commands/help"; export default { scope: () => [], @@ -47,16 +59,35 @@ export default { }[] = []; // Load all the command per categories - // TODO: Check if the command exist in the context (guild) - // TODO: List subcommands too - // https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/issues/47 client.commands.categories.forEach((commands_name, category) => { - const commands = commands_name.reduce((data, command_name) => { - return data + `\`/${command_name}\`, `; - }, ""); + // Check if the command exist in the context (guild) + commands_name = commands_name.filter((command) => { + const scope = client.commands.list.get(command)?.scope(); + return scope!.length === 0 || scope?.find((v) => v === interaction.guildId) !== undefined; + }); + + // Add subcommands + const all_commands: string[] = []; + commands_name.forEach((command) => { + const data = client.commands.list.get(command)?.data; + const name = goodName(data!, interaction.locale); + all_commands.push(name); + + data + ?.toJSON() + .options?.filter((option) => option.type === ApplicationCommandOptionType.Subcommand) + .forEach((subcommand) => + all_commands.push(name + " " + goodName(subcommand, interaction.locale)), + ); + }); + + const commands = all_commands.reduce( + (data, command_name) => data + `\`/${command_name}\`, `, + "", + ); fields.push({ - name: category.capitalize() + ` (${commands_name.length})`, + name: category.capitalize() + ` (${all_commands.length})`, value: commands.slice(0, -2), }); }); @@ -73,30 +104,49 @@ export default { }); } - // If a command is specified - // TODO: Check if the command exist in the context (guild) - // https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/issues/187 - const command = client.commands.list.get(desired_command); + const error = `${loc.get("c_help3")} \`${desired_command}\``; + + const [possible_command, possible_subcommand] = desired_command.split(" "); + + const command = NameNotLocalized(client, possible_command); if (!command) { - // Command don't exist - return interaction.reply({ - content: `${loc.get("c_help3")} \`${desired_command}\``, - ephemeral: true, - }); + return interaction.reply({ content: error, ephemeral: true }); } + const scope = client.commands.list.get(command.name)?.scope(); + if (scope!.length > 0 && scope?.find((id) => id === interaction.guildId) === undefined) { + // Command not available for the current guild + return interaction.reply({ content: error, ephemeral: true }); + } + + let subcommand = undefined; + if (possible_subcommand) { + subcommand = SubnameNotLocalized(command, possible_subcommand); + } else { + subcommand = null; + } + + if (!command || subcommand === undefined) { + // Sub/Command don't exist + return interaction.reply({ content: error, ephemeral: true }); + } + + // Loads the data according to the user's locals + const requestedName = + goodName(command, interaction.locale) + + (subcommand !== null ? " " + goodName(subcommand, interaction.locale) : ""); + const requestedDesc = goodDescription( + subcommand !== null ? subcommand : command, + interaction.locale, + ); + // Send information about the command return interaction.reply({ embeds: [ new EmbedBuilder() .setColor(Colors.Blurple) - .setTitle("`/" + command.data.name + "`") - .setDescription( - // Loads the description - // according to the user's locals - command.data.description_localizations?.[interaction.locale] ?? - command.data.description, - ), + .setTitle("`/" + requestedName + "`") + .setDescription(requestedDesc), ], }); }, diff --git a/src/commands/music/lyrics.ts b/src/commands/music/lyrics.ts index 416ff5c..d420d85 100644 --- a/src/commands/music/lyrics.ts +++ b/src/commands/music/lyrics.ts @@ -1,8 +1,9 @@ import { SlashCommandBuilder } from "@discordjs/builders"; import { useMainPlayer, useQueue } from "discord-player"; -import { ChatInputCommandInteraction, Client, EmbedBuilder } from "discord.js"; +import { ChatInputCommandInteraction, Client, EmbedBuilder, Message } from "discord.js"; import { getLocale, getLocalizations } from "../../utils/locales"; import { getFilename } from "../../utils/misc"; +import { discord_limit_message } from "../../utils/constants"; export default { scope: () => [], @@ -57,7 +58,7 @@ export default { ), ) - // Synced + // Synced start .addSubcommand((subcommand) => subcommand .setName(loc_default.get(`c_${filename}_sub3_name`)!.toLowerCase()) @@ -65,6 +66,15 @@ export default { .setNameLocalizations(getLocalizations(client, `c_${filename}_sub3_name`, true)) .setDescriptionLocalizations(getLocalizations(client, `c_${filename}_sub3_desc`)), ) + + // Synced stop + .addSubcommand((subcommand) => + subcommand + .setName(loc_default.get(`c_${filename}_sub4_name`)!.toLowerCase()) + .setDescription(loc_default.get(`c_${filename}_sub4_desc`)!) + .setNameLocalizations(getLocalizations(client, `c_${filename}_sub4_name`, true)) + .setDescriptionLocalizations(getLocalizations(client, `c_${filename}_sub4_desc`)), + ) ); }, @@ -123,30 +133,69 @@ export default { } // Load lyrics - const syncedLyrics = queue.syncedLyrics(data[0]); + if (queue.syncedLyricsMemory !== undefined) { + return await interaction.followUp(loc.get("c_lyrics9")); + } + const syncedLyrics = queue.syncedLyrics(data[0]); + queue.syncedLyricsMemory = syncedLyrics; + + let message: Message; syncedLyrics?.onChange(async (lyrics) => { - const content = `[${data[0].trackName}]: ${lyrics}`; if (interaction.channel?.isSendable()) { - await interaction.channel?.send({ - content, - }); + if (message) { + const payload = message.cleanContent + "\n" + lyrics; + if (payload.length < discord_limit_message) { + message.edit(payload); + return; + } + } + message = await interaction.channel?.send( + (message ? loc.get("c_lyrics6") + " " : "") + + `${data[0].artistName} : **${data[0].trackName}**\n\n` + + lyrics, + ); } else { - await interaction.followUp({ - content, - }); + await interaction.followUp(loc.get("c_lyrics5")); } }); // Live update syncedLyrics.subscribe(); + syncedLyrics.onUnsubscribe(() => { + queue.syncedLyricsMemory = undefined; + }); + return await interaction.followUp({ content: `đŸŽ€ | ${loc.get("c_lyrics4")}`, ephemeral: true, }); } + if ( + interaction.options.getSubcommand() === + loc_default?.get(`c_${filename}_sub4_name`)?.toLowerCase() + ) { + if (queue === null) { + return await interaction.followUp(`❌ | ${loc.get("c_lyrics1")}`); + } + + if (data === null || !data[0] || !data[0].syncedLyrics) { + return await interaction.followUp( + `❌ | ${loc.get("c_lyrics3")} \`${queue.currentTrack?.cleanTitle}\``, + ); + } + + // Load lyrics + if (queue.syncedLyricsMemory !== undefined && queue.syncedLyricsMemory.isSubscribed()) { + queue.syncedLyricsMemory.unsubscribe(); + return await interaction.followUp(loc.get("c_lyrics7")); + } + + return await interaction.followUp(loc.get("c_lyrics8")); + } + if (data && data.length > 0 && data[0].plainLyrics !== null) { const title = data[0]; const limit_desc = 4096; diff --git a/src/commands/music/play.ts b/src/commands/music/play.ts index 95dd2c1..7b0f34e 100644 --- a/src/commands/music/play.ts +++ b/src/commands/music/play.ts @@ -9,6 +9,11 @@ import { import { getLocale, getLocalizations } from "../../utils/locales"; import { Metadata } from "../../utils/metadata"; import { getFilename } from "../../utils/misc"; +import { + discord_limit_autocompletion_list_length, + discord_limit_autocompletion_value_length, +} from "../../utils/constants"; +import { timeToString } from "../../utils/time"; export default { scope: () => [], @@ -175,12 +180,29 @@ export default { queue.node.play(); } - // TODO: When added to an existing queue (size of queue > 0): - // - Add position in queue - // - Add estimated time until playing - // https://git.mylloon.fr/ConfrerieDuKassoulait/Botanique/issues/184 + const positionEstimation = () => { + const pos = queue.node.getTrackPosition(result.tracks[0]) + 1; + + if (pos === 0) { + return loc.get("c_play_sub2_name"); + } + + const estimation = timeToString( + [queue.currentTrack, ...queue.tracks.toArray()] + .filter((t) => t !== null) + .slice(0, pos) + .reduce((total, t) => { + if (total === 0) { + return queue.dispatcher ? t.durationMS - queue.dispatcher.streamTime : t.durationMS; + } + return total + t.durationMS; + }, 0), + ); + return `${loc.get("c_play10")} ${pos} (${loc.get("c_play11")} ≈${estimation})`; + }; + return await interaction.followUp({ - content: `⏱ | \`${title}\` ${loc.get("c_play5")}.`, + content: `⏱ | \`${title}\` ${loc.get("c_play5")}, ${loc.get("c_play12")} ${positionEstimation()}.`, }); }, @@ -192,7 +214,10 @@ export default { const player = useMainPlayer(); const query = interaction.options.getString(loc_default!.get(`c_${filename}_opt1_name`)!, true); - const limit_value_discord = 100; + const limit_value_discord = discord_limit_autocompletion_value_length; + const limit_element_discord = discord_limit_autocompletion_list_length; + + const query_discord = query.slice(0, limit_value_discord); if (query) { /* Since Discord wanna receive a response within 3 secs and results is async @@ -208,7 +233,7 @@ export default { /* Create a race between a timeout and the search * At the end, Discord will always receive a response */ - let tracks = await Promise.race([ + const tracks = await Promise.race([ delay, player.search(query, { requestedBy: interaction.user, @@ -225,23 +250,18 @@ export default { // If tracks found if (tracks.length > 0) { - if (tracks.length > 25) { - tracks = tracks - // Assure that URL is under the limit of Discord - .filter((v) => v.url.length < limit_value_discord) - // Slice the list if needed to the 25 first results - .slice(0, 25); - } - - // Returns a list of songs with their title and author - return interaction.respond( - tracks.map((t) => { + const payload = tracks + // Assure that URL is under the limit of Discord + .filter((v) => v.url.length < limit_value_discord) + // Slice the list to respect the limit of Discord + .slice(0, limit_element_discord - 1) + .map((t) => { let title = t.title; let author = t.author; let name = `${title} ‱ ${author}`; - // Slice returned data if needed to not exceed the length limit (100) - if (name.length > 100) { + // Slice returned data if needed to not exceed the length limit + if (name.length > limit_value_discord) { const newTitle = title.substring(0, 40); if (title.length != newTitle.length) { title = `${newTitle}...`; @@ -257,12 +277,18 @@ export default { name, value: t.url, }; - }), - ); + }); + + payload.unshift({ + name: query_discord, + value: query_discord, + }); + + // Returns a list of songs with their title and author + return interaction.respond(payload); } } - return interaction.respond([ - { name: loc.get("c_play9"), value: query.slice(0, limit_value_discord) }, - ]); + + return interaction.respond([{ name: loc.get("c_play9"), value: query_discord }]); }, }; diff --git a/src/events/client/ready.ts b/src/events/client/ready.ts index 2c8aa4e..d27bc42 100644 --- a/src/events/client/ready.ts +++ b/src/events/client/ready.ts @@ -9,6 +9,7 @@ import { setTimeoutReminder, updateReminder, } from "../../utils/commands/reminder"; +import { readSQL } from "../../utils/db"; export const once = true; @@ -19,7 +20,7 @@ export default async (client: Client) => { // Restart all the timeout about reminders here new Promise((ok, ko) => { // Fetch all reminders - client.db.all("SELECT * FROM reminder", [], (err, row) => { + client.db.all(readSQL("reminder/select"), [], (err, row) => { if (err) { ko(err); } diff --git a/src/load.ts b/src/load.ts index 13277c3..ff68b03 100644 --- a/src/load.ts +++ b/src/load.ts @@ -61,11 +61,11 @@ export const run = async (isDev: boolean) => { console.log(logStart(client_name, true)); console.log(`Botanique "${client.user?.username}" v${client.config.version} started!`); - // ^C - process.on("SIGINT", () => quit(client)); - - // Container force closed - process.on("SIGTERM", () => quit(client)); + // Handle quit + process.on("exit", () => quit(client)); + process.on("SIGHUP", () => process.exit(128 + 1)); + process.on("SIGINT", () => process.exit(128 + 2)); + process.on("SIGTERM", () => process.exit(128 + 15)); }) .catch((err) => { console.error(err); diff --git a/src/locales/en-US.json b/src/locales/en-US.json index fd60ed6..4385cb5 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -96,6 +96,9 @@ "c_play7": "Currently playing", "c_play8": "Asked by", "c_play9": "No results were found", + "c_play10": "in position", + "c_play11": "estimation", + "c_play12": "play", "c_stop_name": "stop", "c_stop_desc": "Stop the music", @@ -148,12 +151,19 @@ "c_lyrics_sub2_desc": "Search for romanized lyrics (e.g., hangul → Latin)", "c_lyrics_sub3_name": "synced", "c_lyrics_sub3_desc": "Synchronized lyrics search (updates in live)", + "c_lyrics_sub4_name": "stop-synced", + "c_lyrics_sub4_desc": "Stop Synchronized lyrics", "c_lyrics_opt1_name": "song", "c_lyrics_opt1_desc": "Wanted song", "c_lyrics1": "The bot is not playing anything at the moment, and no songs are specified.", "c_lyrics2": "Unable to find the lyrics for", "c_lyrics3": "Unable to find synchronized lyrics for", "c_lyrics4": "It's karaoke time!", + "c_lyrics5": "Unable to post the lyrics here.", + "c_lyrics6": "More of :", + "c_lyrics7": "Stop synchronized lyrics.", + "c_lyrics8": "No synchronized lyrics currently posted.", + "c_lyrics9": "Synchronized lyrics currently posted.", "c_repeat_name": "repeat", "c_repeat_desc": "Command for the type of music repetition", diff --git a/src/locales/fr.json b/src/locales/fr.json index a31d70e..e83b8ae 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -96,6 +96,9 @@ "c_play7": "Joue actuellement", "c_play8": "DemandĂ© par", "c_play9": "Aucun rĂ©sultat trouvĂ©", + "c_play10": "en position", + "c_play11": "estimation", + "c_play12": "joue", "c_stop_name": "stop", "c_stop_desc": "Stop la musique", @@ -148,12 +151,19 @@ "c_lyrics_sub2_desc": "Recherche de paroles romanisĂ©es (ex: hangul → latin)", "c_lyrics_sub3_name": "synced", "c_lyrics_sub3_desc": "Recherche de paroles synchronisĂ©es (se mettent Ă  jour avec la chanson en direct)", + "c_lyrics_sub4_name": "stop-synced", + "c_lyrics_sub4_desc": "ArrĂȘte les paroles synchronisĂ©es", "c_lyrics_opt1_name": "chanson", "c_lyrics_opt1_desc": "Chanson recherchĂ©e", "c_lyrics1": "Le bot ne joue rien en ce moment et aucune chanson n'est renseignĂ©e.", "c_lyrics2": "Impossible de trouver les paroles pour", "c_lyrics3": "Impossible de trouver les paroles synchronisĂ©es pour", "c_lyrics4": "C'est parti !", + "c_lyrics5": "Impossible de poster les paroles ici.", + "c_lyrics6": "Suite de :", + "c_lyrics7": "ArrĂȘt des paroles synchronisĂ©es.", + "c_lyrics8": "Pas de paroles synchronisĂ©es en cours.", + "c_lyrics9": "Paroles synchronisĂ©es dĂ©jĂ  en cours.", "c_repeat_name": "repeat", "c_repeat_desc": "Commande relative Ă  la rĂ©pĂ©tition des musiques", diff --git a/src/modules/client.ts b/src/modules/client.ts index fb9efcf..a0c485b 100644 --- a/src/modules/client.ts +++ b/src/modules/client.ts @@ -75,6 +75,8 @@ declare module "discord.js" { string, /** Command itself */ { + /** Guilds where the command is active */ + scope: () => string[]; /** Data about the command */ data: SlashCommandBuilder; /** How the command interact */ diff --git a/src/modules/player.ts b/src/modules/player.ts new file mode 100644 index 0000000..1fc72ac --- /dev/null +++ b/src/modules/player.ts @@ -0,0 +1,12 @@ +export {}; + +declare module "discord-player" { + export interface GuildQueue { + syncedLyricsMemory: + | { + isSubscribed: () => unknown; + unsubscribe: () => unknown; + } + | undefined; + } +} diff --git a/src/sql/init.sql b/src/sql/init.sql new file mode 100644 index 0000000..abe3b62 --- /dev/null +++ b/src/sql/init.sql @@ -0,0 +1,13 @@ +CREATE TABLE IF NOT EXISTS + reminder ( + id INTEGER PRIMARY KEY, + data TEXT, + expiration_date TEXT, + option_id INTEGER, + channel_id TEXT, + creation_date TEXT, + user_id TEXT, + guild_id TEXT, + locale TEXT, + timeout_id TEXT + ); diff --git a/src/sql/reminder/add.sql b/src/sql/reminder/add.sql new file mode 100644 index 0000000..d703484 --- /dev/null +++ b/src/sql/reminder/add.sql @@ -0,0 +1,14 @@ +INSERT INTO + reminder ( + data, + expiration_date, + option_id, + channel_id, + creation_date, + user_id, + guild_id, + locale, + timeout_id + ) +VALUES + (?, ?, ?, ?, ?, ?, ?, ?, ?); diff --git a/src/sql/reminder/find.sql b/src/sql/reminder/find.sql new file mode 100644 index 0000000..f7ad878 --- /dev/null +++ b/src/sql/reminder/find.sql @@ -0,0 +1,13 @@ +SELECT + data, + creation_date, + expiration_date, + id +FROM + reminder +WHERE + user_id = ? + AND ( + guild_id = ? + OR guild_id = 0 + ) diff --git a/src/sql/reminder/findById.sql b/src/sql/reminder/findById.sql new file mode 100644 index 0000000..8592f27 --- /dev/null +++ b/src/sql/reminder/findById.sql @@ -0,0 +1,6 @@ +SELECT + * +FROM + reminder +WHERE + id = ? diff --git a/src/sql/reminder/ownership_check.sql b/src/sql/reminder/ownership_check.sql new file mode 100644 index 0000000..17e7eca --- /dev/null +++ b/src/sql/reminder/ownership_check.sql @@ -0,0 +1,14 @@ +SELECT + EXISTS ( + SELECT + 1 + FROM + reminder + WHERE + id = ? + AND user_id = ? + AND ( + guild_id = ? + OR guild_id = 0 + ) + ) diff --git a/src/sql/reminder/remove.sql b/src/sql/reminder/remove.sql new file mode 100644 index 0000000..c9bca24 --- /dev/null +++ b/src/sql/reminder/remove.sql @@ -0,0 +1,4 @@ +DELETE FROM reminder +WHERE + creation_date = ? + AND user_id = ? diff --git a/src/sql/reminder/select.sql b/src/sql/reminder/select.sql new file mode 100644 index 0000000..8095263 --- /dev/null +++ b/src/sql/reminder/select.sql @@ -0,0 +1,4 @@ +SELECT + * +FROM + reminder diff --git a/src/sql/reminder/update.sql b/src/sql/reminder/update.sql new file mode 100644 index 0000000..d1a499b --- /dev/null +++ b/src/sql/reminder/update.sql @@ -0,0 +1,13 @@ +UPDATE reminder +SET + data = ?, + expiration_date = ?, + option_id = ?, + channel_id = ?, + creation_date = ?, + user_id = ?, + guild_id = ?, + locale = ?, + timeout_id = ? +WHERE + ID = ? diff --git a/src/utils/client.ts b/src/utils/client.ts index 14a3874..2ab5276 100644 --- a/src/utils/client.ts +++ b/src/utils/client.ts @@ -5,6 +5,7 @@ import { Database } from "sqlite3"; import "../modules/client"; import { loadLocales } from "./locales"; import { YoutubeiExtractor } from "discord-player-youtubei"; +import { readSQL } from "./db"; /** Creation of the client and definition of its properties */ export default async (isDev: boolean) => { @@ -59,7 +60,7 @@ export default async (isDev: boolean) => { client.db = new Database(`${process.env.DOCKERIZED === "1" ? "/config" : "./config"}/db.sqlite3`); - initDatabase(client.db); + client.db.run(readSQL("init")); return client; }; @@ -75,25 +76,3 @@ export const quit = (client: Client) => { // Close client client.destroy(); }; - -/** - * Initalize the database - * @param db Database - */ -const initDatabase = (db: Database) => { - // Table for reminders - db.run( - "CREATE TABLE IF NOT EXISTS reminder ( \ - id INTEGER PRIMARY KEY, \ - data TEXT, \ - expiration_date TEXT, \ - option_id INTEGER, \ - channel_id TEXT, \ - creation_date TEXT, \ - user_id TEXT, \ - guild_id TEXT, \ - locale TEXT, \ - timeout_id TEXT \ - );", - ); -}; diff --git a/src/utils/commands/help.ts b/src/utils/commands/help.ts new file mode 100644 index 0000000..84ee417 --- /dev/null +++ b/src/utils/commands/help.ts @@ -0,0 +1,73 @@ +import { + APIApplicationCommandSubcommandOption, + ApplicationCommandOptionType, + Client, + Locale, + SlashCommandBuilder, +} from "discord.js"; + +type Data = SlashCommandBuilder | APIApplicationCommandSubcommandOption; + +/** + * Find the name of the command, trying to get the correct locale + * @param data Command data + * @param locale Locale wanted + * @returns Command's name + */ +export const goodName = (data: Data, locale: Locale) => + data.name_localizations?.[locale] ?? data.name; + +/** + * Find the description of the command, trying to get the correct locale + * @param data Command data + * @param locale Locale wanted + * @returns Command's description + */ +export const goodDescription = (data: Data, locale: Locale) => + data.description_localizations?.[locale] ?? data.description; + +/** + * Aux function for Sub/NameNotLocalized + * @param cmd data + * @param command command researched + * @returns if we found or not the researched command + */ +const filterLocalizations = (cmd: Data, command: string) => { + let res = false; + for (const key in cmd?.name_localizations) { + res = res || cmd.name_localizations?.[key as Locale] === command; + } + + return res; +}; + +/** + * Find a command based on any string, localized or not + * @param command string + * @returns the not localized corresponding string's command name + */ +export const NameNotLocalized = (client: Client, command: string): SlashCommandBuilder | null => { + const list = client.commands.list.map((cmd) => cmd.data); + + return ( + list.find((cmd) => cmd.name === command) || + list.filter((cmd) => filterLocalizations(cmd, command))[0] + ); +}; + +/** + * Find a subcommand of a command based on any string, localized or not + * @param parent command of the subcommand + * @param command string + * @returns the not localized corresponding string's subcommand name + */ +export const SubnameNotLocalized = (parent: SlashCommandBuilder, command: string) => { + const list = parent + ?.toJSON() + .options?.filter((option) => option.type === ApplicationCommandOptionType.Subcommand); + + return ( + list?.find((cmd) => cmd?.name === command) || + list?.filter((cmd) => filterLocalizations(cmd, command))[0] + ); +}; diff --git a/src/utils/commands/music.ts b/src/utils/commands/music.ts index c49f0b9..4b9c534 100644 --- a/src/utils/commands/music.ts +++ b/src/utils/commands/music.ts @@ -3,6 +3,7 @@ import { GuildQueue, QueueRepeatMode } from "discord-player"; import { Client } from "discord.js"; import { getLocale } from "../locales"; import { blank } from "../misc"; +import { discord_limit_embed_field } from "../constants"; export const embedListQueue = ( client: Client, @@ -17,8 +18,7 @@ export const embedListQueue = ( // Add the current song at the top of the list tracks.unshift(queue.history.currentTrack!); - // Limit of discord is 25 - const limit_fields = 25; + const limit_fields = discord_limit_embed_field; const pageMax = Math.ceil(tracks.length / limit_fields); diff --git a/src/utils/commands/reminder.ts b/src/utils/commands/reminder.ts index 139a534..19627fc 100644 --- a/src/utils/commands/reminder.ts +++ b/src/utils/commands/reminder.ts @@ -3,6 +3,7 @@ import { getLocale } from "../locales"; import { blank, cleanCodeBlock } from "../misc"; import { showDate, strToSeconds, timeDeltaToString } from "../time"; import { RegexC, RegExpFlags } from "../regex"; +import { readSQL } from "../db"; /** * Option possible for reminders @@ -92,9 +93,7 @@ export const newReminder = async (client: Client, time: string, info: infoRemind // Add the remind to the db client.db.run( - "INSERT INTO reminder ( \ - data, expiration_date, option_id, channel_id, creation_date, user_id, guild_id, locale, timeout_id \ - ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? );", + readSQL("reminder/add"), [ info.message, `${expiration_date}`, @@ -127,19 +126,15 @@ export const newReminder = async (client: Client, time: string, info: infoRemind export const deleteReminder = (client: Client, createdAt: string, userId: string) => { // Delete the reminder for the database return new Promise((ok, ko) => { - // Add the remind to the db - client.db.run( - "DELETE FROM reminder WHERE creation_date = ? AND user_id = ?", - [createdAt, userId], - (err) => { - if (err) { - ko(err); - } + // Remove the remind to the db + client.db.run(readSQL("reminder/remove"), [createdAt, userId], (err) => { + if (err) { + ko(err); + } - // Send confirmation to user - ok(true); - }, - ); + // Send confirmation to user + ok(true); + }); }); }; @@ -199,16 +194,20 @@ const sendReminderAux = (client: Client, info: infoReminder, option: OptionRemin // Channel client.channels.fetch(info.channelId!).then((channel) => { if (channel?.isSendable()) { - let content = `<@${info.userId}>`; + const author_mention = `<@${info.userId}>`; + + let content = author_mention; embed.setFooter({ text: `${loc.get("c_reminder17")} ${timeDeltaToString(info.createdAt)}`, }); // Mention everybody if needed if (option === OptionReminder.Mention) { - (info.message?.match(/<@\d+>/g) ?? []).forEach((mention) => { - content += " " + mention; - }); + [...new Set(info.message?.match(/<@\d+>/g) ?? [])] + .filter((mention) => mention !== author_mention) + .forEach((mention: string) => { + content += " " + mention; + }); } channel.send({ content, embeds: [embed] }); @@ -276,12 +275,7 @@ export const checkOwnershipReminder = async ( const data = (await new Promise((ok, ko) => { // Check the ownership client.db.all( - "SELECT EXISTS ( \ - SELECT 1 FROM reminder \ - WHERE id = ? \ - AND user_id = ? \ - AND (guild_id = ? OR guild_id = 0) \ - )", + readSQL("reminder/ownership_check"), [id, userId, guildId], (err, row) => { if (err) { @@ -304,19 +298,14 @@ export const checkOwnershipReminder = async ( export const getReminderInfo = async (client: Client, id: number) => { return (await new Promise((ok, ko) => { // Check the ownership - client.db.all( - "SELECT * FROM reminder \ - WHERE id = ?", - [id], - (err, row) => { - if (err) { - ko(err); - } + client.db.all(readSQL("reminder/findById"), [id], (err, row) => { + if (err) { + ko(err); + } - // Send all the current reminders - ok(row[0]); - }, - ); + // Send all the current reminders + ok(row[0]); + }); })) as dbReminder; }; @@ -330,17 +319,7 @@ export const updateReminder = (client: Client, data: dbReminder) => { return new Promise((ok, ko) => { // Update the db client.db.run( - "UPDATE reminder \ - SET data = ?, \ - expiration_date = ?, \ - option_id = ?, \ - channel_id = ?, \ - creation_date = ?, \ - user_id = ?, \ - guild_id = ?, \ - locale = ?, \ - timeout_id = ? \ - WHERE ID = ?", + readSQL("reminder/update"), [ data.data, data.expiration_date, @@ -374,19 +353,14 @@ export const updateReminder = (client: Client, data: dbReminder) => { const listReminders = async (client: Client, userId: string, guildId: string | null) => { return (await new Promise((ok, ko) => { // Check the ownership - client.db.all( - "SELECT data, creation_date, expiration_date, id FROM reminder \ - WHERE user_id = ? AND (guild_id = ? OR guild_id = 0)", - [userId, guildId ?? 0], - (err, row) => { - if (err) { - ko(err); - } + client.db.all(readSQL("reminder/find"), [userId, guildId ?? 0], (err, row) => { + if (err) { + ko(err); + } - // Send all the current reminders - ok(row); - }, - ); + // Send all the current reminders + ok(row); + }); })) as dbReminder[]; }; diff --git a/src/utils/constants.ts b/src/utils/constants.ts new file mode 100644 index 0000000..75353a1 --- /dev/null +++ b/src/utils/constants.ts @@ -0,0 +1,11 @@ +/** Max message length */ +export const discord_limit_message = 2000; + +/** Max embed field an embed can have */ +export const discord_limit_embed_field = 25; + +/** Max element the autocompletion of slash commands can have */ +export const discord_limit_autocompletion_list_length = 25; + +/** Max length of an element in autocompletion of slash commands */ +export const discord_limit_autocompletion_value_length = 100; diff --git a/src/utils/db.ts b/src/utils/db.ts new file mode 100644 index 0000000..5d3aa4b --- /dev/null +++ b/src/utils/db.ts @@ -0,0 +1,15 @@ +import fs from "node:fs"; + +export const readSQL = (path: string) => { + const dir = "./src/sql/"; + if (!path.startsWith(dir)) { + path = dir + path; + } + + const ext = ".sql"; + if (!path.endsWith(ext)) { + path += ext; + } + + return fs.readFileSync(path, "utf8"); +}; diff --git a/src/utils/time.ts b/src/utils/time.ts index 0c719da..045e09d 100644 --- a/src/utils/time.ts +++ b/src/utils/time.ts @@ -94,14 +94,12 @@ export const strToSeconds = (time: string) => { }; /** - * Calculating the difference between a date and now - * @param lang Locale - * @param time Time - * @returns Delta between the time and now + * Returns the time in a readable way + * @param seconds Time in milliseconds + * @returns Time as string */ -export const timeDeltaToString = (time: number) => { - const now = Date.now(); - let secondsDifference = Math.abs(Math.ceil((time - now) / 1000)); +export const timeToString = (time: number) => { + let secondsDifference = Math.abs(Math.ceil(time / 1000)); if (secondsDifference === 0) { return "0s"; @@ -123,3 +121,13 @@ export const timeDeltaToString = (time: number) => { .filter(Boolean) .join(" "); }; + +/** + * Calculating the difference between a date and now + * @param time Time in milliseconds + * @returns Delta between the time and now + */ +export const timeDeltaToString = (time: number) => { + const now = Date.now(); + return timeToString(time - now); +};