From 5c70395f50699f17577fdd3703ea893ed8d51fb3 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 15:27:38 +0700 Subject: [PATCH 01/63] Updated discord.js to v14 --- package.json | 3 +- yarn.lock | 249 +++++++++++++++++++++++---------------------------- 2 files changed, 112 insertions(+), 140 deletions(-) diff --git a/package.json b/package.json index 57bf49b..db9d3ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,5 @@ { "dependencies": { - "@discordjs/builders": "^0.15.0", "@discordjs/opus": "^0.7.0", "@discordjs/rest": "^0.5.0", "@discordjs/voice": "^0.10.0", @@ -12,7 +11,7 @@ "country-code-emoji": "^2.3.0", "country-code-lookup": "^0.0.20", "discord-api-types": "^0.35.0", - "discord.js": "^13.8.1", + "discord.js": "14.0.0-dev.1656158629-c4653f9", "dotenv": "^16.0.1", "i18n": "^0.15.0", "libsodium-wrappers": "^0.7.10", diff --git a/yarn.lock b/yarn.lock index 1c1d820..31eefb0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,26 +23,13 @@ enabled "2.0.x" kuler "^2.0.0" -"@discordjs/builders@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.14.0.tgz#1915af10fa1c30d738b08b1ed0ae3c224fd491d7" - integrity sha512-+fqLIqa9wN3R+kvlld8sgG0nt04BAZxdCDP4t2qZ9TJsquLWA+xMtT8Waibb3d4li4AQS+IOfjiHAznv/dhHgQ== +"@discordjs/builders@^0.16.0-dev": + version "0.16.0-dev.1656158607-c4653f9" + resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.16.0-dev.1656158607-c4653f9.tgz#141f8ee5150a193d708c67df4d8f1be59a7e0701" + integrity sha512-kylgqqmw/6uO+5xy/0etmwjV0TL9HLuA9JtPFRt8Xwb9feRqKTYMSKxQ/SQl5HqBwWNzMxxUo2eqU44KqD/0BQ== dependencies: - "@sapphire/shapeshift" "^3.1.0" - "@sindresorhus/is" "^4.6.0" - discord-api-types "^0.33.3" - fast-deep-equal "^3.1.3" - ts-mixer "^6.0.1" - tslib "^2.4.0" - -"@discordjs/builders@^0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.15.0.tgz#f76318f2de0b057c21bb25bb010ef2317039793d" - integrity sha512-w1UfCPzx2iKycn6qh/f0c+PcDpcTHzHr7TXALXu/a4gKHGamiSg3lP8GhYswweSJk/Q5cbFLHZUsnoY3MVKNAg== - dependencies: - "@sapphire/shapeshift" "^3.1.0" - "@sindresorhus/is" "^4.6.0" - discord-api-types "^0.33.3" + "@sapphire/shapeshift" "^3.2.0" + discord-api-types "^0.33.5" fast-deep-equal "^3.1.3" ts-mixer "^6.0.1" tslib "^2.4.0" @@ -52,6 +39,11 @@ resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.7.0.tgz#1a6c00198b744ba2b73a64442145da637ac073b8" integrity sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA== +"@discordjs/collection@^0.8.0-dev": + version "0.8.0-dev.1656158612-c4653f9" + resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.8.0-dev.1656158612-c4653f9.tgz#fd934b123cd1999a0fc4ff3e5f7b6513e0afc453" + integrity sha512-xQKf3cS0M6Q3NVsY7tSmNmSrbGKt6P/h2+O2H3+CZbTQNAQSpF+Y9Bwt44Jq0XjsxFvv8FKh8/tg5DtG9bOz8g== + "@discordjs/node-pre-gyp@^0.4.2": version "0.4.2" resolved "https://registry.yarnpkg.com/@discordjs/node-pre-gyp/-/node-pre-gyp-0.4.2.tgz#37dd27f8d353eeb87372fcce059c5249550b37ab" @@ -87,6 +79,18 @@ tslib "^2.4.0" undici "^5.4.0" +"@discordjs/rest@^0.6.0-dev": + version "0.6.0-dev.1656158624-c4653f9" + resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-0.6.0-dev.1656158624-c4653f9.tgz#ce0d5fe32db32f697967d875c87137f92d6d6ef9" + integrity sha512-LerWi+sNv4kXFgxZERzEOyrNsMZ5G7MpiWtG83zSCMyE/ySZZzeSvlDshPaL+yoReSo4Bq+LAbrX4EGznMhjFA== + dependencies: + "@discordjs/collection" "^0.8.0-dev" + "@sapphire/async-queue" "^1.3.1" + "@sapphire/snowflake" "^3.2.2" + discord-api-types "^0.33.5" + tslib "^2.4.0" + undici "^5.5.1" + "@discordjs/voice@^0.10.0": version "0.10.0" resolved "https://registry.yarnpkg.com/@discordjs/voice/-/voice-0.10.0.tgz#5c911b5ce276233b232a98c92141e07f1f52168b" @@ -100,14 +104,14 @@ ws "^8.7.0" "@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== + version "3.0.8" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz#687cc2bbf243f4e9a868ecf2262318e2658873a1" + integrity sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w== "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" - integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -190,40 +194,35 @@ resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.3.1.tgz#9d861e626dbffae02d808e13f823d4510e450a78" integrity sha512-FFTlPOWZX1kDj9xCAsRzH5xEJfawg1lNoYAA+ecOWJMHOfiZYb1uXOI3ne9U4UILSEPwfE68p3T9wUHwIQfR0g== -"@sapphire/shapeshift@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@sapphire/shapeshift/-/shapeshift-3.1.0.tgz#e4719fd03ab1d3ea01170f9c37b9cb64f5794759" - integrity sha512-PkxFXd3QJ1qAPS05Dy2UkVGYPm/asF1Ugt2Xyzmv4DHzO3+G7l+873C4XFFcJ9M5Je+eCMC7SSifgPTSur5QuA== +"@sapphire/shapeshift@^3.2.0": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@sapphire/shapeshift/-/shapeshift-3.3.2.tgz#505c0fe2c5256415916ceff4db4c1c0ddfa57c67" + integrity sha512-8+M8sLmT4RTXJCvI1Z69UiB56himVup8WJVm7ubt5j3HJmVK+l1OI4xTLkLVh1efupOhZR9jrl2YBIv4Lsag7A== "@sapphire/snowflake@^3.2.2": version "3.2.2" resolved "https://registry.yarnpkg.com/@sapphire/snowflake/-/snowflake-3.2.2.tgz#faacdc1b5f7c43145a71eddba917de2b707ef780" integrity sha512-ula2O0kpSZtX9rKXNeQMrHwNd7E4jPDJYUXmEGTFdMRfyfMw+FPyh04oKMjAiDuOi64bYgVkOV3MjK+loImFhQ== -"@sindresorhus/is@^4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" - integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== - "@tsconfig/node10@^1.0.7": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" - integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== "@tsconfig/node12@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" - integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== "@tsconfig/node14@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" - integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" - integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== "@types/bluebird@^3.5.36": version "3.5.36" @@ -240,20 +239,7 @@ resolved "https://registry.yarnpkg.com/@types/i18n/-/i18n-0.13.3.tgz#88db5b33ccbbd57de54c8c2da01002e8fb48efc3" integrity sha512-o6MlrxjGUDANSmMmQ6p/f7ea3+kJFeNWebxylKE3pLjWbIa0Npr/DT2Qf941oqovdopadAfV+PuBMTKg4p37NA== -"@types/node-fetch@^2.6.1": - version "2.6.1" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.1.tgz#8f127c50481db65886800ef496f20bbf15518975" - integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - -"@types/node@*": - version "17.0.40" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.40.tgz#76ee88ae03650de8064a6cf75b8d95f9f4a16090" - integrity sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg== - -"@types/node@^18.0.0": +"@types/node@*", "@types/node@^18.0.0": version "18.0.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.0.tgz#67c7b724e1bcdd7a8821ce0d5ee184d3b4dd525a" integrity sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA== @@ -416,9 +402,9 @@ call-bind@^1.0.0: get-intrinsic "^1.0.2" canvas@^2.5.0: - version "2.9.1" - resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.9.1.tgz#58ec841cba36cef0675bc7a74ebd1561f0b476b0" - integrity sha512-vSQti1uG/2gjv3x6QLOZw7TctfufaerTWbVe+NSduHxxLGB+qf3kFgQ6n66DSnuoINtVUjrLLIK2R+lxrBG07A== + version "2.9.3" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.9.3.tgz#8723c4f970442d4cdcedba5221579f9660a58bdb" + integrity sha512-WOUM7ghii5TV2rbhaZkh1youv/vW1/Canev6Yx6BG2W+1S07w8jKZqKkPnbiPpQEDsnJdN8ouDd7OvQEGXDcUw== dependencies: "@mapbox/node-pre-gyp" "^1.0.0" nan "^2.15.0" @@ -612,30 +598,32 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -discord-api-types@^0.33.3: - version "0.33.3" - resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.33.3.tgz#882c39331871f619035917a1f80d486f605b3e7a" - integrity sha512-P3A1RJXKEDmGPHrFTN5+gYLsBPGUVGj+D3+fa3m0K/umc+LMfqGuEad+p7cNq7ry/icReVhS3bz9jvBvne/BRA== +discord-api-types@^0.33.3, discord-api-types@^0.33.5: + version "0.33.5" + resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.33.5.tgz#6548b70520f7b944c60984dca4ab58654d664a12" + integrity sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg== discord-api-types@^0.35.0: version "0.35.0" resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.35.0.tgz#85c6ea95f27580ad13b7a08444b16cb31d41e5e2" integrity sha512-aaIbVgPk7OA3y/HdG00tRM2nB8B3sSPH6KXgamBLRrcAJEQ8XZJNNKeRr0WVzw/lprdpKHKuTNX1DNrYnD5cOw== -discord.js@^13.8.1: - version "13.8.1" - resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-13.8.1.tgz#37627154a887ac395ca72dd814bc7366776bb90a" - integrity sha512-jOsD+4tEZWWx0RHVyH+FBcqoTrsL+d5Mm5p+ULQOdU0qSaxhLNkWYig+yDHNZoND7nlkXX3qi+BW+gO5erWylg== +discord.js@14.0.0-dev.1656158629-c4653f9: + version "14.0.0-dev.1656158629-c4653f9" + resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.0.0-dev.1656158629-c4653f9.tgz#1d78ff80fd6edc95aedd586bc1c4af63504e0cb5" + integrity sha512-lgHs1LGbAdlpBY5te+8iXMEAoA5FFB9wzFLqfzTedLCDM5IKuadXVUxwLktUmQk/jjeAzGD4+lQ+eEVfWTvWXQ== dependencies: - "@discordjs/builders" "^0.14.0" - "@discordjs/collection" "^0.7.0" - "@sapphire/async-queue" "^1.3.1" - "@types/node-fetch" "^2.6.1" + "@discordjs/builders" "^0.16.0-dev" + "@discordjs/collection" "^0.8.0-dev" + "@discordjs/rest" "^0.6.0-dev" + "@sapphire/snowflake" "^3.2.2" "@types/ws" "^8.5.3" - discord-api-types "^0.33.3" - form-data "^4.0.0" - node-fetch "^2.6.1" - ws "^8.7.0" + discord-api-types "^0.33.5" + fast-deep-equal "^3.1.3" + lodash.snakecase "^4.1.1" + tslib "^2.4.0" + undici "^5.5.1" + ws "^8.8.0" dotenv@^16.0.1: version "16.0.1" @@ -707,15 +695,6 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - formidable@^1.2.2: version "1.2.6" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.6.tgz#d2a51d60162bbc9b4a055d8457a7c75315d1a168" @@ -764,13 +743,13 @@ get-caller-file@^2.0.5: integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-intrinsic@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + version "1.1.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" + integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== dependencies: function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" + has-symbols "^1.0.3" glob-parent@~5.1.2: version "5.1.2" @@ -791,7 +770,7 @@ glob@^7.0.5, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -has-symbols@^1.0.1: +has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== @@ -853,7 +832,7 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-core-module@^2.8.1: +is-core-module@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== @@ -914,7 +893,12 @@ libsodium@^0.7.0: resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.7.10.tgz#c2429a7e4c0836f879d701fec2c8a208af024159" integrity sha512-eY+z7hDrDKxkAK+QKZVNv92A5KYkxfvIshtBJkmg5TSiCnYqZP3i9OO9whE79Pwgm4jGaoHgkM4ao/b9Cyu4zQ== -logform@^2.2.0: +lodash.snakecase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" + integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw== + +logform@^2.2.0, logform@^2.3.2: version "2.4.1" resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.1.tgz#512c9eaef738044d1c619790ba0f806c80d9d3a9" integrity sha512-7XB/tqc3VRbri9pRjU6E97mQ8vC27ivJ3lct4jhyT+n0JNDd4YKldFl0D75NqDp46hk8RC7Ma1Vjv/UPf67S+A== @@ -925,17 +909,6 @@ logform@^2.2.0: safe-stable-stringify "^2.3.1" triple-beam "^1.3.0" -logform@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.0.tgz#131651715a17d50f09c2a2c1a524ff1a4164bcfe" - integrity sha512-CPSJw4ftjf517EhXZGGvTHHkYobo7ZCc0kvwUoOYcjfR2UVrI66RHj8MCrfAdEitdmFqbu2BYdYs8FHHZSb6iw== - dependencies: - "@colors/colors" "1.5.0" - fecha "^4.2.0" - ms "^2.1.1" - safe-stable-stringify "^2.3.1" - triple-beam "^1.3.0" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -1005,9 +978,9 @@ minimist@^1.2.6: integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== minipass@^3.0.0: - version "3.1.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" - integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + version "3.3.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.4.tgz#ca99f95dd77c43c7a76bf51e6d200025eee0ffae" + integrity sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw== dependencies: yallist "^4.0.0" @@ -1054,7 +1027,7 @@ node-addon-api@^4.2.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== -node-fetch@^2.6.1, node-fetch@^2.6.5, node-fetch@^2.6.7: +node-fetch@^2.6.5, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== @@ -1190,9 +1163,9 @@ q@1.x: integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== qs@^6.9.4: - version "6.10.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" - integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" @@ -1208,7 +1181,7 @@ readable-stream@^3.4.0, readable-stream@^3.6.0: readable-stream@~1.0.31: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -1238,14 +1211,14 @@ readdirp@~3.6.0: require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== resolve@^1.0.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: - is-core-module "^2.8.1" + is-core-module "^2.9.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -1298,7 +1271,7 @@ semver@^7.3.2, semver@^7.3.5: set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== side-channel@^1.0.4: version "1.0.4" @@ -1331,7 +1304,7 @@ simple-get@^3.0.3: simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== dependencies: is-arrayish "^0.3.1" @@ -1351,7 +1324,7 @@ source-map@^0.6.0: stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" @@ -1372,7 +1345,7 @@ string_decoder@^1.1.1: string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== string_decoder@~1.1.1: version "1.1.1" @@ -1391,12 +1364,12 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-json-comments@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== superagent@^5.2.1: version "5.3.1" @@ -1460,7 +1433,7 @@ to-regex-range@^5.0.1: tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== tree-kill@^1.2.2: version "1.2.2" @@ -1542,10 +1515,10 @@ underscore@^1.12.0: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.4.tgz#7886b46bbdf07f768e0052f1828e1dcab40c0dee" integrity sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ== -undici@^5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.4.0.tgz#c474fae02743d4788b96118d46008a24195024d2" - integrity sha512-A1SRXysDg7J+mVP46jF+9cKANw0kptqSFZ8tGyL+HBiv0K1spjxPX8Z4EGu+Eu6pjClJUBdnUPlxrOafR668/g== +undici@^5.4.0, undici@^5.5.1: + version "5.5.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.5.1.tgz#baaf25844a99eaa0b22e1ef8d205bffe587c8f43" + integrity sha512-MEvryPLf18HvlCbLSzCW0U00IMftKGI5udnjrQbC5D4P0Hodwffhv+iGfWuJwg16Y/TK11ZFK8i+BPVW2z/eAw== untildify@^4.0.0: version "4.0.0" @@ -1562,7 +1535,7 @@ utf-8-validate@^5.0.9: util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== v8-compile-cache-lib@^3.0.1: version "3.0.1" @@ -1577,12 +1550,12 @@ validator@^13.7.0: webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" @@ -1630,12 +1603,12 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.7.0.tgz#eaf9d874b433aa00c0e0d8752532444875db3957" - integrity sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg== +ws@^8.7.0, ws@^8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.0.tgz#8e71c75e2f6348dbf8d78005107297056cb77769" + integrity sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ== xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" From 0f73f8f464688a32a82cefbd5f1fedd3d6fff736 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 15:27:42 +0700 Subject: [PATCH 02/63] Fixed discord.js v14 breaking changes --- src/discord/Core.ts | 4 +- src/discord/Developer/Debug.ts | 16 +- src/discord/Developer/ServiceAnnouncement.ts | 38 ++-- src/discord/InteractionManager.ts | 44 ++--- src/discord/MembershipScreening.ts | 191 ++++++++++--------- src/discord/MusicPlayer/Join.ts | 20 +- src/discord/MusicPlayer/Loop.ts | 4 +- src/discord/MusicPlayer/NowPlaying.ts | 8 +- src/discord/MusicPlayer/Play.ts | 24 +-- src/discord/MusicPlayer/Search.ts | 12 +- src/discord/Ping.ts | 2 +- src/discord/Say.ts | 16 +- src/discord/Settings/Prefix.ts | 8 +- src/discord/Settings/ServiceAnnouncement.ts | 22 +-- src/discord/Settings/index.ts | 2 +- src/discord/UserInfo.ts | 60 +++--- src/discord/osu.ts | 71 +++---- src/providers/Discord.ts | 18 +- src/providers/DiscordMusicPlayer.ts | 71 ++++--- src/utils/DiscordMessage.ts | 19 +- src/utils/DiscordModule.ts | 16 +- 21 files changed, 340 insertions(+), 326 deletions(-) diff --git a/src/discord/Core.ts b/src/discord/Core.ts index 3e42eb2..7a57e6f 100644 --- a/src/discord/Core.ts +++ b/src/discord/Core.ts @@ -1,4 +1,4 @@ -import { Guild } from 'discord.js'; +import { ActivityType, Guild } from 'discord.js'; import DiscordModule from '../utils/DiscordModule'; import DiscordProvider from '../providers/Discord'; @@ -48,7 +48,7 @@ export default class Core extends DiscordModule { private setActivity() { DiscordProvider.client.user!.setActivity('for your heart 💖', { - type: 'COMPETING' + type: ActivityType.Competing }); } } diff --git a/src/discord/Developer/Debug.ts b/src/discord/Developer/Debug.ts index dd8a0ad..328e856 100644 --- a/src/discord/Developer/Debug.ts +++ b/src/discord/Developer/Debug.ts @@ -1,11 +1,11 @@ import { User as PrismaUser, Guild as PrismaGuild } from '@prisma/client'; import { Message, - Interaction, + ActionRowBuilder, CommandInteraction, - MessageActionRow, - MessageButton, - ButtonInteraction + ButtonInteraction, + ButtonBuilder, + ButtonStyle } from 'discord.js'; import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule'; @@ -162,14 +162,14 @@ export default class Debug extends DiscordModule { }); }, invalidInteraction: async (data: HybridInteractionMessage) => { - const row = new MessageActionRow().addComponents( - new MessageButton() + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() .setEmoji('😥') .setLabel( ' Make invalid interaction (Wait 7 seconds, check error in console or logs)' ) .setCustomId('dev_make_invalid_interaction') - .setStyle('PRIMARY') + .setStyle(ButtonStyle.Primary) ); await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.INVALID_TEST(data)], @@ -187,7 +187,7 @@ export default class Debug extends DiscordModule { }); query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { query = args.getSubcommand(); } diff --git a/src/discord/Developer/ServiceAnnouncement.ts b/src/discord/Developer/ServiceAnnouncement.ts index f721fae..00f3e43 100644 --- a/src/discord/Developer/ServiceAnnouncement.ts +++ b/src/discord/Developer/ServiceAnnouncement.ts @@ -1,4 +1,4 @@ -import { Message, MessageEmbed, Interaction, CommandInteraction, TextChannel } from 'discord.js'; +import { Message, EmbedBuilder, Interaction, CommandInteraction, TextChannel, BaseInteraction } from 'discord.js'; import { Promise } from 'bluebird'; import fs from 'fs'; import path from 'path'; @@ -22,7 +22,7 @@ import Prisma from '../../providers/Prisma'; import Users from '../../services/Users'; const EMBEDS = { - ANNOUNCEMENT_INFO: (data: Message | Interaction) => { + ANNOUNCEMENT_INFO: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'Service Announcement', description: `This module contains management tool for announcement feed\n The announcement message is located in \`\`configs/ServiceAnnouncement.json\`\``, @@ -32,14 +32,14 @@ const EMBEDS = { value: '``reload`` ``previewNews`` ``sendNews`` ``previewMaintenance`` ``sendMaintenance`` ``previewMessage`` ``sendMessage`` ``previewAlert`` ``sendAlert``' } ], - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NOT_DEVELOPER: (data: Message | Interaction) => { + NOT_DEVELOPER: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Developer only', description: `This command is restricted to the developers only`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, MAKE_PAYLOAD: (payload: any) => { @@ -60,40 +60,40 @@ const EMBEDS = { if (payload.description) payload.description = payload.description.replaceAll('{bot_username}', user?.username); - return new MessageEmbed(payload); + return new EmbedBuilder(payload); }, - RELOADED: (data: Message | Interaction) => { + RELOADED: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Service Announcement Configuration Reloaded', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - RELOAD_ERROR: (data: Message | Interaction, error: string) => { + RELOAD_ERROR: (data: Message | BaseInteraction, error: string) => { return makeErrorEmbed({ title: 'Unable to reload Service Announcement Configuration', description: `\`\`\`${error}\`\`\``, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - SENDING_SERVICE_ANNOUNCEMENT: (data: Message | Interaction) => { + SENDING_SERVICE_ANNOUNCEMENT: (data: Message | BaseInteraction) => { return makeProcessingEmbed({ title: 'Service Announcement', description: `Broadcasting Service Announcement`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - SERVICE_ANNOUNCEMENT_SENT: (data: Message | Interaction) => { + SERVICE_ANNOUNCEMENT_SENT: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Service Announcement', description: `Broadcasted Service Announcement`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS: (data: Message | Interaction) => { + SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS: (data: Message | BaseInteraction) => { return makeWarningEmbed({ title: 'Service Announcement', description: `Broadcasted Service Announcement with errors, check console for more info`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); } }; @@ -298,7 +298,7 @@ export default class ServiceAnnouncement extends DiscordModule { EMBEDS.SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS(data.getRaw()) ] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { @@ -313,7 +313,7 @@ export default class ServiceAnnouncement extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_SENT(data.getRaw())] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_SENT(data.getRaw())] }, @@ -331,7 +331,7 @@ export default class ServiceAnnouncement extends DiscordModule { embeds: [EMBEDS.ANNOUNCEMENT_INFO(data.getRaw())] }); query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { query = args.getSubcommand(); } diff --git a/src/discord/InteractionManager.ts b/src/discord/InteractionManager.ts index a94ce68..ac051b5 100644 --- a/src/discord/InteractionManager.ts +++ b/src/discord/InteractionManager.ts @@ -1,4 +1,4 @@ -import { Message, Interaction, CommandInteraction } from 'discord.js'; +import { Message, Interaction, CommandInteraction, BaseInteraction } from 'discord.js'; import Users from '../services/Users'; @@ -18,7 +18,7 @@ import { } from '../utils/DiscordInteraction'; const EMBEDS = { - INTERACTION_INFO: (data: Message | Interaction) => { + INTERACTION_INFO: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'Interaction', description: `This module contains management tool for interaction based contents`, @@ -28,47 +28,47 @@ const EMBEDS = { value: '``reloadAll`` ``unloadAll`` ``reloadglobal``' } ], - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - PROCESSING: (data: Message | Interaction) => { + PROCESSING: (data: Message | BaseInteraction) => { return makeProcessingEmbed({ icon: data instanceof Message ? undefined : '⌛', title: `Performing actions`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NOT_DEVELOPER: (data: Message | Interaction) => { + NOT_DEVELOPER: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Developer only', description: `This command is restricted to the developers only`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - UNLOADALL_SUCCESS: (data: Message | Interaction) => { + UNLOADALL_SUCCESS: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Unloaded all Interaction', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - UNLOADALL_ERROR: (data: Message | Interaction, err: any) => { + UNLOADALL_ERROR: (data: Message | BaseInteraction, err: any) => { return makeErrorEmbed({ title: 'An error occurred while trying to unload interaction', description: '```' + err + '```', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - RELOADALL_SUCCESS: (data: Message | Interaction) => { + RELOADALL_SUCCESS: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Reloaded all Interaction', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - RELOADALL_ERROR: (data: Message | Interaction, err: any) => { + RELOADALL_ERROR: (data: Message | BaseInteraction, err: any) => { return makeErrorEmbed({ title: 'An error occurred while trying to reload interaction', description: '```' + err + '```', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); } }; @@ -111,7 +111,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.UNLOADALL_SUCCESS(data.getRaw())] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.UNLOADALL_SUCCESS(data.getRaw())] }, @@ -122,7 +122,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.UNLOADALL_ERROR(data.getRaw(), err)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.UNLOADALL_ERROR(data.getRaw(), err)] }, @@ -146,7 +146,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }, @@ -157,7 +157,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }, @@ -181,7 +181,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }, @@ -192,7 +192,7 @@ export default class InteractionManager extends DiscordModule { return placeholder .getMessage() .edit({ embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }, @@ -211,7 +211,7 @@ export default class InteractionManager extends DiscordModule { }); query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { query = args.getSubcommand(); } diff --git a/src/discord/MembershipScreening.ts b/src/discord/MembershipScreening.ts index 03aaa00..7179b5e 100644 --- a/src/discord/MembershipScreening.ts +++ b/src/discord/MembershipScreening.ts @@ -3,15 +3,20 @@ import { GuildChannel, GuildMember, Message, - Permissions, TextChannel, - MessageActionRow, - MessageButton, - Interaction, + ButtonBuilder, CommandInteraction, Role, ThreadChannel, - ButtonInteraction + ButtonInteraction, + BaseInteraction, + PermissionsBitField, + EmbedBuilder, + ButtonStyle, + ActionRowBuilder, + ActionRowData, + ActionRowComponent, + MessageActionRowComponentBuilder } from 'discord.js'; import DiscordProvider from '../providers/Discord'; @@ -27,44 +32,44 @@ import { import DiscordModule, { HybridInteractionMessage } from '../utils/DiscordModule'; const EMBEDS = { - NO_PERMISSION: (data: Message | Interaction) => { + NO_PERMISSION: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'You need ``ADMINISTRATOR`` permission on this guild!', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_PARAMETER: (data: Message | Interaction) => { + NO_PARAMETER: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Missing parameter', description: `You must define membership screening channel and role to enable this feature`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_ROLE_MENTIONED: (data: Message | Interaction) => { + NO_ROLE_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'No role mentioned', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_ROLE_FOUND: (data: Message | Interaction) => { + NO_ROLE_FOUND: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Cannot find that role', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_CHANNEL_MENTIONED: (data: Message | Interaction) => { + NO_CHANNEL_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'No channel mentioned', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_CHANNEL_FOUND: (data: Message | Interaction) => { + NO_CHANNEL_FOUND: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Cannot find that channel', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - MSINFO: (data: Message | Interaction) => { + MSINFO: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'Membership Screening', description: `Membership Screening is a feature to prevent unwanted people to join your guild, similar to whitelist feature. Moderators can approve or deny join request`, @@ -74,58 +79,58 @@ const EMBEDS = { value: '``setRole`` ``setChannel`` ``createMessage``' } ], - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - ALREADY_ENABLED: (data: Message | Interaction) => { + ALREADY_ENABLED: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'Membership Screening is already enabled', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - MESSAGE_CREATED: (data: Message | Interaction) => { + MESSAGE_CREATED: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Membership Screening message created', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - ALREADY_DISABLED: (data: Message | Interaction) => { + ALREADY_DISABLED: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'Membership Screening is already disabled', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - ENABLED: (data: Message | Interaction) => { + ENABLED: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Enabled Membership Screening', description: `All new member join request will be sent in your defined channel`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - DISABLED: (data: Message | Interaction) => { + DISABLED: (data: Message | BaseInteraction) => { return makeSuccessEmbed({ title: 'Disabled Membership Screening', description: `No longer accepting request, all new member can join directly`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - MANAGED_ROLE: (data: Message | Interaction, role: Role) => { + MANAGED_ROLE: (data: Message | BaseInteraction, role: Role) => { return makeErrorEmbed({ title: 'You cannot use this role', description: '``' + role.name + '``' + ' is managed by external service and cannot be used', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - CONFIGURED_ROLE: (data: Message | Interaction, role: Role) => { + CONFIGURED_ROLE: (data: Message | BaseInteraction, role: Role) => { return makeSuccessEmbed({ title: 'Configured Membership Screening Role', description: 'New member will be given a ' + '``' + role.name + '``' + ' role after approval', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - CONFIGURED_CHANNEL: (data: Message | Interaction, channel: GuildChannel) => { + CONFIGURED_CHANNEL: (data: Message | BaseInteraction, channel: GuildChannel) => { return makeSuccessEmbed({ title: 'Configured Membership Screening Channel', description: @@ -134,18 +139,18 @@ const EMBEDS = { channel.name + '``' + ' can approve or deny request', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - INVALID_CHANNEL: (data: Message | Interaction, channel: GuildChannel) => { + INVALID_CHANNEL: (data: Message | BaseInteraction, channel: GuildChannel) => { return makeErrorEmbed({ title: 'Invalid channel type, only TextChannel is supported', description: '``' + channel.name + '``' + ' is not a text channel', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, INVALID_CHANNEL_THREAD: ( - data: Message | Interaction, + data: Message | BaseInteraction, channel: GuildChannel | ThreadChannel ) => { return makeErrorEmbed({ @@ -155,38 +160,38 @@ const EMBEDS = { channel.name + '``' + ' is a thread channel. Please use a regular text channel', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - BOT_NO_PERMISSION: (data: Message | Interaction, channel: GuildChannel) => { + BOT_NO_PERMISSION: (data: Message | BaseInteraction, channel: GuildChannel) => { return makeErrorEmbed({ title: `I don't have permission`, description: 'I cannot access/send message in ' + '``' + channel.name + '``', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_LONGER_VALID_ROLE: (data: Message | Interaction) => { + NO_LONGER_VALID_ROLE: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'The configured role is no longer valid. Please update the role in configuration', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - CANNOT_PERFORM_ASSIGN_ROLE: (data: Message | Interaction) => { + CANNOT_PERFORM_ASSIGN_ROLE: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Cannot grant the role to user, make sure I have permission to do that', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - CANNOT_PERFORM_ASSIGN_KICK: (data: Message | Interaction) => { + CANNOT_PERFORM_ASSIGN_KICK: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Cannot kick the user, make sure I have permission to do that', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - CANNOT_PERFORM_ASSIGN_BAN: (data: Message | Interaction) => { + CANNOT_PERFORM_ASSIGN_BAN: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: 'Cannot ban the user, make sure I have permission to do that', - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, CREATE_MESSAGE: () => { @@ -246,10 +251,12 @@ export default class MembershipScreening extends DiscordModule { ) return; - embed[0].footer = { + const newEmbed = new EmbedBuilder(embed[0].data); + + newEmbed.setFooter({ text: `${interaction.user.username} | v${App.version}`, iconURL: `${interaction.user.displayAvatarURL()}?size=4096` - }; + }); if (['approve', 'deny', 'ban'].includes(payload.a)) { if (!payload.d.requester) return; @@ -268,26 +275,29 @@ export default class MembershipScreening extends DiscordModule { }); if (!requesterMember) { - embed[0].addField('❌ Invalid', `Unable to find the user. User left already?`); - return await message.edit({ components: [], embeds: embed }); + newEmbed.addFields({ + name: '❌ Invalid', + value: `Unable to find the user. User left already?` + }); + return await message.edit({ components: [], embeds: [newEmbed] }); } if (requesterMember.roles.cache.has(PrismaGuild.MembershipScreening_GivenRole)) { - embed[0].addField( - '✅ Approved', - `By: Unknown (User already obtained the role by other means)` - ); - return await message.edit({ components: [], embeds: embed }); + newEmbed.addFields({ + name: '✅ Approved', + value: `By: Unknown (User already obtained the role by other means)` + }); + return await message.edit({ components: [], embeds: [newEmbed] }); } if (payload.a === 'approve') { try { await requesterMember.roles.add(role); - embed[0].addField( - '✅ Approved', - `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` - ); - await message.edit({ components: [], embeds: embed }); + newEmbed.addFields({ + name: '✅ Approved', + value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` + }); + await message.edit({ components: [], embeds: [newEmbed] }); } catch (err) { return interaction.reply({ ephemeral: true, @@ -297,11 +307,11 @@ export default class MembershipScreening extends DiscordModule { } else if (payload.a === 'deny') { try { await requesterMember.kick(); - embed[0].addField( - '❌ Denied', - `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` - ); - await message.edit({ components: [], embeds: embed }); + newEmbed.addFields({ + name: '❌ Denied', + value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` + }); + await message.edit({ components: [], embeds: [newEmbed] }); } catch (err) { return interaction.reply({ ephemeral: true, @@ -313,11 +323,11 @@ export default class MembershipScreening extends DiscordModule { await requesterMember.ban({ reason: `Membership Screening, action issued by ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` }); - embed[0].addField( - '🔪 Banned', - `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` - ); - await message.edit({ components: [], embeds: embed }); + newEmbed.addFields({ + name: '🔪 Banned', + value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` + }); + await message.edit({ components: [], embeds: [newEmbed] }); } catch (err) { return interaction.reply({ ephemeral: true, @@ -395,9 +405,9 @@ export default class MembershipScreening extends DiscordModule { role = data.getMessage().mentions.roles.first() || guild.roles.cache.find((role) => role.name === _name); - } else if (data.isSlashCommand()) + } else if (data.isApplicationCommand()) role = guild.roles.cache.find( - (role) => role.id === data.getSlashCommand().options.getRole('role')?.id + (role) => role.id === data.getSlashCommand().options.get('role')?.role?.id ); if (!role) @@ -427,8 +437,8 @@ export default class MembershipScreening extends DiscordModule { embeds: [EMBEDS.NO_CHANNEL_MENTIONED(data.getRaw())] }); mentionChannel = data.getMessage().mentions.channels.first(); - } else if (data.isSlashCommand()) - mentionChannel = data.getSlashCommand().options.getChannel('channel'); + } else if (data.isApplicationCommand()) + mentionChannel = data.getSlashCommand().options.get('channel', true).channel; if (!mentionChannel) return await sendHybridInteractionMessageResponse(data, { @@ -443,15 +453,14 @@ export default class MembershipScreening extends DiscordModule { embeds: [EMBEDS.INVALID_CHANNEL_THREAD(data.getRaw(), TargetChannel)] }); - if (!TargetChannel.isText()) + if (!TargetChannel.isTextBased()) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.INVALID_CHANNEL(data.getRaw(), TargetChannel)] }); if ( - !guild - .me!.permissionsIn(TargetChannel) - .has([Permissions.FLAGS.SEND_MESSAGES, Permissions.FLAGS.VIEW_CHANNEL]) + !guild.members.me?.permissionsIn(TargetChannel) + .has([PermissionsBitField.Flags.SendMessages, PermissionsBitField.Flags.ViewChannel]) ) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.BOT_NO_PERMISSION(data.getRaw(), TargetChannel)] @@ -470,7 +479,7 @@ export default class MembershipScreening extends DiscordModule { return await sendMessage(channel, undefined, { embeds: [EMBEDS.CREATE_MESSAGE()] }); - else if (data.isSlashCommand()) { + else if (data.isApplicationCommand()) { await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.MESSAGE_CREATED(data.getRaw())] }); @@ -483,7 +492,7 @@ export default class MembershipScreening extends DiscordModule { let query; - if (!member.permissions.has([Permissions.FLAGS.ADMINISTRATOR])) + if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.NO_PERMISSION(data.getRaw())] }); @@ -495,7 +504,7 @@ export default class MembershipScreening extends DiscordModule { }); query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) query = args.getSubcommand(); + } else if (data.isApplicationCommand()) query = args.getSubcommand(); switch (query) { case 'enable': @@ -549,9 +558,9 @@ export default class MembershipScreening extends DiscordModule { embed.setThumbnail(`${member.user.displayAvatarURL()}?size=4096`); - const row = new MessageActionRow() + const row = new ActionRowBuilder() .addComponents( - new MessageButton() + new ButtonBuilder() .setCustomId( JSON.stringify({ m: 'MembershipScreening', @@ -563,10 +572,10 @@ export default class MembershipScreening extends DiscordModule { ) .setEmoji('✅') .setLabel(' Approve') - .setStyle('SUCCESS') + .setStyle(ButtonStyle.Success) ) .addComponents( - new MessageButton() + new ButtonBuilder() .setCustomId( JSON.stringify({ m: 'MembershipScreening', @@ -578,10 +587,10 @@ export default class MembershipScreening extends DiscordModule { ) .setEmoji('⛔') .setLabel(' Deny and kick') - .setStyle('DANGER') + .setStyle(ButtonStyle.Danger) ) .addComponents( - new MessageButton() + new ButtonBuilder() .setCustomId( JSON.stringify({ m: 'MembershipScreening', @@ -593,7 +602,7 @@ export default class MembershipScreening extends DiscordModule { ) .setEmoji('🔪') .setLabel(' Vision Hunt Decree (Ban)') - .setStyle('DANGER') + .setStyle(ButtonStyle.Danger) ); await channel.send({ content: '\u200b', embeds: [embed], components: [row] }); diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index 2f5fb66..75fd345 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -7,10 +7,12 @@ import { GuildMember, DMChannel, StageChannel, - MessageActionRow, - MessageButton, + ActionRowBuilder, + ButtonBuilder, TextChannel, - VoiceBasedChannel + VoiceBasedChannel, + PermissionsBitField, + ButtonStyle } from 'discord.js'; import { I18n } from 'i18n'; @@ -116,7 +118,7 @@ export async function joinVoiceChannelProcedure( instance: DiscordMusicPlayerInstance | null, voiceChannel: VoiceChannel | StageChannel ) { - const isSlashCommand = data.isSlashCommand(); + const isSlashCommand = data.isApplicationCommand(); const isAcceptableInteraction = data.isSelectMenu() || data.isButton(); const isMessage = data.isMessage(); if (!isSlashCommand && !isAcceptableInteraction && !isMessage) return; @@ -133,7 +135,7 @@ export async function joinVoiceChannelProcedure( const memberVoiceChannel = member.voice.channel; //isMessage ? member.voice.channel : DiscordProvider.client.guilds.cache.get(guild.id)!.members.cache.get((data as Interaction).user.id)?.voice.channel; if (!memberVoiceChannel) return; - const bot = guild.me; + const bot = guild.members.me; if (!bot) return; const locale = await Locale.getGuildLocale(guild.id); @@ -179,7 +181,7 @@ export async function joinVoiceChannelProcedure( EMBEDS.VOICECHANNEL_INUSE( data, locale, - member.permissions.has([Permissions.FLAGS.MOVE_MEMBERS]) + member.permissions.has([PermissionsBitField.Flags.MoveMembers]) ) ] }); @@ -223,12 +225,12 @@ export async function joinVoiceChannelProcedure( if (event.instance.queue.track[0] !== previousTrack) isLoopMessageSent = false; else if (event.instance.queue.track[0] === previousTrack && isLoopMessageSent) return; - const row = new MessageActionRow().addComponents( - new MessageButton() + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() .setEmoji('▶️') .setLabel(' Open on YouTube') .setURL(encodeURI(`https://www.youtube.com/watch?v=${event.instance.queue.track[0].id}`)) - .setStyle('LINK') + .setStyle(ButtonStyle.Link) ); if (event.instance.textChannel) { diff --git a/src/discord/MusicPlayer/Loop.ts b/src/discord/MusicPlayer/Loop.ts index 2dafc78..4edac7d 100644 --- a/src/discord/MusicPlayer/Loop.ts +++ b/src/discord/MusicPlayer/Loop.ts @@ -1,5 +1,5 @@ import { I18n } from "i18n"; -import { Message, CommandInteraction, Interaction, MessageActionRow, ButtonInteraction, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; +import { Message, CommandInteraction } from "discord.js"; import DiscordMusicPlayer, { DiscordMusicPlayerLoopMode } from "../../providers/DiscordMusicPlayer"; import Locale from "../../services/Locale"; @@ -81,7 +81,7 @@ export default class Loop extends DiscordModule { if (args.length !== 0) query = args.join(' '); } - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) query = args.getSubcommand(); const voiceChannel = member.voice.channel; diff --git a/src/discord/MusicPlayer/NowPlaying.ts b/src/discord/MusicPlayer/NowPlaying.ts index eec9eed..bae412f 100644 --- a/src/discord/MusicPlayer/NowPlaying.ts +++ b/src/discord/MusicPlayer/NowPlaying.ts @@ -1,4 +1,4 @@ -import { Message, CommandInteraction, MessageActionRow, MessageButton } from "discord.js"; +import { Message, CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js"; import { I18n } from "i18n"; import DiscordProvider from "../../providers/Discord"; @@ -55,13 +55,13 @@ export default class NowPlaying extends DiscordModule { const instance = DiscordMusicPlayer.getGuildInstance(guild.id); if(!instance || !instance.queue.track[0]) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.NO_MUSIC_PLAYING(data, locale)] }); - const row = new MessageActionRow() + const row = new ActionRowBuilder() .addComponents( - new MessageButton() + new ButtonBuilder() .setEmoji('▶️') .setLabel(' Open on YouTube') .setURL(encodeURI(`https://www.youtube.com/watch?v=${instance.queue.track[0].id}`)) - .setStyle('LINK'), + .setStyle(ButtonStyle.Link), ) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.NOW_PLAYING(data, locale, instance.queue.track[0])], components: [row] }); diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index 82dcce6..2649100 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -1,13 +1,13 @@ import { Message, CommandInteraction, - Interaction, VoiceChannel, - MessageActionRow, - MessageButton, + ActionRowBuilder, + ButtonBuilder, SelectMenuInteraction, ButtonInteraction, - StageChannel + StageChannel, + ButtonStyle } from 'discord.js'; import { I18n } from 'i18n'; @@ -286,8 +286,8 @@ export default class Play extends DiscordModule { return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.PLAY_INFO(data, locale)] }); query = args.join(' '); - } else if (data.isSlashCommand()) { - query = data.getSlashCommand().options.getString('query'); + } else if (data.isApplicationCommand()) { + query = data.getSlashCommand().options.get('query', true).value?.toString(); } if (!query) return; @@ -350,8 +350,8 @@ export default class Play extends DiscordModule { instance.addTrackToQueue(result); if (linkData.list) { - const row = new MessageActionRow().addComponents( - new MessageButton() + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() .setEmoji('✅') .setCustomId( JSON.stringify({ @@ -361,7 +361,7 @@ export default class Play extends DiscordModule { }) ) .setLabel(' Add the remaining songs in the playlist') - .setStyle('PRIMARY') + .setStyle(ButtonStyle.Primary) ); return await sendHybridInteractionMessageResponse(data, { @@ -387,8 +387,8 @@ export default class Play extends DiscordModule { // The query length is too long to fit in json if (query.length > 100 - 51) return; - const row = new MessageActionRow().addComponents( - new MessageButton() + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() .setEmoji('🔎') .setCustomId( JSON.stringify({ @@ -400,7 +400,7 @@ export default class Play extends DiscordModule { }) ) .setLabel(' Not this? Search!') - .setStyle('PRIMARY') + .setStyle(ButtonStyle.Primary) ); return await sendHybridInteractionMessageResponse(data, { diff --git a/src/discord/MusicPlayer/Search.ts b/src/discord/MusicPlayer/Search.ts index 6a2ae7b..5aadebd 100644 --- a/src/discord/MusicPlayer/Search.ts +++ b/src/discord/MusicPlayer/Search.ts @@ -1,4 +1,4 @@ -import { Message, CommandInteraction, Interaction, MessageActionRow, ButtonInteraction, MessageSelectMenu, MessageSelectOptionData } from "discord.js"; +import { Message, CommandInteraction, BaseInteraction, ActionRowBuilder, ButtonInteraction, SelectMenuBuilder, SelectMenuComponentOptionData } from "discord.js"; import { I18n } from "i18n"; import { joinVoiceChannelProcedure } from "./Join"; @@ -96,8 +96,8 @@ export default class Search extends DiscordModule { query = args.join(' '); } - else if (data.isSlashCommand()) - query = data.getSlashCommand().options.getString('query'); + else if (data.isApplicationCommand()) + query = data.getSlashCommand().options.get('query', true).value?.toString(); else if (data.isButton()) query = args; @@ -126,9 +126,9 @@ export default class Search extends DiscordModule { let result = await DiscordMusicPlayer.searchYouTubeByQuery(query); if (!result) return; // TODO: Handle when search returned nothing - const menuOptions: MessageSelectOptionData[] = []; + const menuOptions: SelectMenuComponentOptionData[] = []; - const messageSelectMenu = new MessageSelectMenu(); + const messageSelectMenu = new SelectMenuBuilder(); /* Discord have 100 char custom id char limit So we need to shorten our json. @@ -157,7 +157,7 @@ export default class Search extends DiscordModule { messageSelectMenu.addOptions(menuOptions); - const row = new MessageActionRow(); + const row = new ActionRowBuilder(); row.addComponents(messageSelectMenu); return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.SEARCH_RESULT(data, locale, result)], components: [row] }); diff --git a/src/discord/Ping.ts b/src/discord/Ping.ts index c525e28..eff4d65 100644 --- a/src/discord/Ping.ts +++ b/src/discord/Ping.ts @@ -123,7 +123,7 @@ export default class Ping extends DiscordModule { }` ); - if (data.isSlashCommand()) + if (data.isApplicationCommand()) return await data .getMessageComponentInteraction() .editReply({ embeds: [EMBEDS.PING_INFO(data, locale, finalString.join('\n'))] }); diff --git a/src/discord/Say.ts b/src/discord/Say.ts index b9de61b..9203a48 100644 --- a/src/discord/Say.ts +++ b/src/discord/Say.ts @@ -1,4 +1,4 @@ -import { Message, Permissions, Interaction, CommandInteraction } from 'discord.js'; +import { Message, Permissions, Interaction, CommandInteraction, PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; import DiscordModule, { HybridInteractionMessage } from '../utils/DiscordModule'; @@ -78,9 +78,9 @@ export default class Say extends DiscordModule { if ( !message.member.permissions.has([ - Permissions.FLAGS.VIEW_CHANNEL, - Permissions.FLAGS.SEND_MESSAGES, - Permissions.FLAGS.MANAGE_CHANNELS + PermissionsBitField.Flags.ViewChannel, + PermissionsBitField.Flags.SendMessages, + PermissionsBitField.Flags.ManageChannels, ]) ) return await sendHybridInteractionMessageResponse(data, { @@ -93,22 +93,22 @@ export default class Say extends DiscordModule { }); query = args.join(' '); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { const interaction = data.getSlashCommand(); if ( !data .getGuild()! .members.cache.get(interaction.user.id) - ?.permissions.has([Permissions.FLAGS.ADMINISTRATOR]) + ?.permissions.has([PermissionsBitField.Flags.Administrator]) ) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.NO_PERMISSION(data, locale)] }); - query = interaction.options.getString('message'); + query = interaction.options.get('message', true).value?.toString(); } - if (data.isSlashCommand() && data.getChannel()) { + if (data.isApplicationCommand() && data.getChannel()) { try { await data.getChannel()!.send({ content: query }); await data diff --git a/src/discord/Settings/Prefix.ts b/src/discord/Settings/Prefix.ts index 757208d..3862022 100644 --- a/src/discord/Settings/Prefix.ts +++ b/src/discord/Settings/Prefix.ts @@ -1,4 +1,4 @@ -import { Permissions, Guild } from 'discord.js'; +import { Permissions, Guild, PermissionFlagsBits, PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; import DiscordProvider from '../../providers/Discord'; @@ -54,7 +54,7 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l if (!GuildCache) return; const prefix = GuildCache.prefix; - if (!member.permissions.has([Permissions.FLAGS.ADMINISTRATOR])) + if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) return await sendHybridInteractionMessageResponse(data, { embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] }); @@ -71,7 +71,7 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l __name.shift(); _name = __name.join(' '); newPrefix = _name; - } else if (data.isSlashCommand()) newPrefix = data.getSlashCommand().options.getString('prefix'); + } else if (data.isApplicationCommand()) newPrefix = data.getSlashCommand().options.get('prefix', true).value?.toString(); if (!newPrefix) return await sendHybridInteractionMessageResponse(data, { @@ -103,7 +103,7 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l if (data && data.isMessage() && placeholder && placeholder.isMessage()) return placeholder.getMessage().edit({ embeds: [EMBEDS.PREFIX_UPDATED(data, locale, newPrefix)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { embeds: [EMBEDS.PREFIX_UPDATED(data, locale, newPrefix)] }, diff --git a/src/discord/Settings/ServiceAnnouncement.ts b/src/discord/Settings/ServiceAnnouncement.ts index 21d4a0c..7320e40 100644 --- a/src/discord/Settings/ServiceAnnouncement.ts +++ b/src/discord/Settings/ServiceAnnouncement.ts @@ -1,4 +1,4 @@ -import { Permissions, Guild, GuildChannel, ThreadChannel, Message } from 'discord.js'; +import { Permissions, Guild, GuildChannel, ThreadChannel, Message, PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; import DiscordProvider from '../../providers/Discord'; @@ -104,7 +104,7 @@ export const setEnableServiceAnnouncement = async ( let member = data.getMember(); if (!member) return; - if (!member.permissions.has([Permissions.FLAGS.ADMINISTRATOR])) + if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) return await sendHybridInteractionMessageResponse(data, { embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] }); @@ -124,7 +124,7 @@ export const setEnableServiceAnnouncement = async ( __name.shift(); _name = __name.join(' '); newStatus = _name; - } else if (data.isSlashCommand()) newStatus = data.getSlashCommand().options.getString('status')!; + } else if (data.isApplicationCommand()) newStatus = data.getSlashCommand().options.get('status', true).value?.toString(); if (!newStatus) return await sendHybridInteractionMessageResponse(data, { @@ -165,7 +165,7 @@ export const setEnableServiceAnnouncement = async ( return await (placeholder as Message).edit({ embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_STATUS_UPDATED(data, locale, newStatusBool)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { @@ -184,7 +184,7 @@ export const setServiceAnnouncementChannel = async ( let member = data.getMember(); if (!member) return; - if (!member.permissions.has([Permissions.FLAGS.ADMINISTRATOR])) + if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) return await sendHybridInteractionMessageResponse(data, { embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] }); @@ -196,7 +196,7 @@ export const setServiceAnnouncementChannel = async ( embeds: [EMBEDS.NO_CHANNEL_MENTIONED(data, locale)] }); channel = data.getMessage().mentions.channels.first(); - } else if (data.isSlashCommand()) channel = data.getSlashCommand().options.getChannel('channel'); + } else if (data.isApplicationCommand()) channel = data.getSlashCommand().options.get('channel', true).channel; if (!channel) return await sendHybridInteractionMessageResponse(data, { @@ -211,16 +211,14 @@ export const setServiceAnnouncementChannel = async ( embeds: [EMBEDS.INVALID_CHANNEL_THREAD(data, locale, TargetChannel)] }); - if (!TargetChannel.isText()) + if (!TargetChannel.isTextBased()) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.INVALID_CHANNEL(data, locale, TargetChannel)] }); if ( - !data - .getGuild()! - .me?.permissionsIn(TargetChannel) - .has([Permissions.FLAGS.SEND_MESSAGES, Permissions.FLAGS.VIEW_CHANNEL]) + !data.getGuild()?.members.me?.permissionsIn(TargetChannel) + .has([PermissionsBitField.Flags.SendMessages, PermissionsBitField.Flags.ViewChannel]) ) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.BOT_NO_PERMISSION(data, locale, TargetChannel)] @@ -239,7 +237,7 @@ export const setServiceAnnouncementChannel = async ( return await (placeholder as Message).edit({ embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_CONFIGURED_CHANNEL(data, locale, TargetChannel)] }); - else if (data.isSlashCommand()) + else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, { diff --git a/src/discord/Settings/index.ts b/src/discord/Settings/index.ts index 5f222b9..4d2d61a 100644 --- a/src/discord/Settings/index.ts +++ b/src/discord/Settings/index.ts @@ -91,7 +91,7 @@ export default class Settings extends DiscordModule { }); query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { query = args.getSubcommand(); } diff --git a/src/discord/UserInfo.ts b/src/discord/UserInfo.ts index 1f39ce5..535ba66 100644 --- a/src/discord/UserInfo.ts +++ b/src/discord/UserInfo.ts @@ -1,4 +1,4 @@ -import { Message, CommandInteraction, Presence, PresenceStatus } from 'discord.js'; +import { Message, CommandInteraction, Presence, PresenceStatus, ActivityType } from 'discord.js'; import { getColorFromURL, Palette } from 'color-thief-node'; import { I18n } from 'i18n'; @@ -73,10 +73,10 @@ const EMBEDS = { if (user.presence?.activities) { for (let activity of user.presence?.activities) { - if (activity.type === 'CUSTOM') - embed.addField( - `✨ ${locale.__('userinfo.custom_status')}`, - `${ + if (activity.type === ActivityType.Custom) + embed.addFields({ + name: `✨ ${locale.__('userinfo.custom_status')}`, + value: `${ !activity.emoji ? '' : `${ @@ -88,49 +88,51 @@ const EMBEDS = { }` } ${activity.state === null ? '' : activity.state} \u200b`, - false - ); + inline: false + }); else { let title = ''; switch (activity.type) { - case 'PLAYING': - title = `'🕹 ${locale.__('userinfo.playing_x', {NAME: activity.name})}`; + case ActivityType.Playing: + title = `'🕹 ${locale.__('userinfo.playing_x', { NAME: activity.name })}`; break; - case 'STREAMING': - title = `'🔴 ${locale.__('userinfo.streaming_x', {NAME: activity.name})}`; + case ActivityType.Streaming: + title = `'🔴 ${locale.__('userinfo.streaming_x', { NAME: activity.name })}`; break; - case 'LISTENING': - title = `🎵 ${locale.__('userinfo.listening_x', {NAME: activity.name})}`; + case ActivityType.Listening: + title = `🎵 ${locale.__('userinfo.listening_x', { NAME: activity.name })}`; break; - case 'WATCHING': - title = `📺 ${locale.__('userinfo.watching_x', {NAME: activity.name})}`; + case ActivityType.Watching: + title = `📺 ${locale.__('userinfo.watching_x', { NAME: activity.name })}`; break; - case 'COMPETING': - title = `'🌠 ${locale.__('userinfo.competing_x', {NAME: activity.name})}`; + case ActivityType.Competing: + title = `'🌠 ${locale.__('userinfo.competing_x', { NAME: activity.name })}`; break; } - embed.addField( - `${title}`, - `${activity.details === null ? '' : activity.details} + embed.addFields({ + name: `${title}`, + value: `${activity.details === null ? '' : activity.details} ${activity.state === null ? '' : activity.state} Since \u200b`, - false - ); + inline: false + }); } } } - embed.addField( - `📰 ${locale.__('userinfo.user_guild_info')}`, - `${ + embed.addFields({ + name: `📰 ${locale.__('userinfo.user_guild_info')}`, + value: `${ user.joinedAt === null ? locale.__('userinfo.join_date_unknown') - : locale.__('userinfo.join_date', {TIME: ``}) + : locale.__('userinfo.join_date', { + TIME: `` + }) } ${user.isGuildOwner ? `${locale.__('userinfo.guild_owner')}` : ''} ` - ); + }); embed.setThumbnail(user.displayAvatarURL + '?size=4096'); embed.setAuthor({ @@ -172,7 +174,7 @@ export default class UserInfo extends DiscordModule { if (typeof data.getMessage().mentions.users.first() !== 'undefined') query = data.getMessage().mentions.users.first()?.id; else query = args[0]; - } else if (data.isSlashCommand()) query = data.getSlashCommand().options.getUser('user')?.id; + } else if (data.isApplicationCommand()) query = data.getSlashCommand().options.getUser('user')?.id; // Find the user want to look up let TargetMember = (await guild.members.fetch()).get(query); @@ -181,7 +183,7 @@ export default class UserInfo extends DiscordModule { embeds: [EMBEDS.USER_NOT_FOUND(data, locale)] }); - if (data.isSlashCommand()) await data.getMessageComponentInteraction().deferReply(); + if (data.isApplicationCommand()) await data.getMessageComponentInteraction().deferReply(); let colorthief = null; try { diff --git a/src/discord/osu.ts b/src/discord/osu.ts index 4375a3c..e2c8faf 100644 --- a/src/discord/osu.ts +++ b/src/discord/osu.ts @@ -1,9 +1,10 @@ import { Message, - MessageActionRow, - MessageButton, - Interaction, - CommandInteraction + ActionRowBuilder, + ButtonBuilder, + CommandInteraction, + BaseInteraction, + ButtonStyle } from 'discord.js'; import validator from 'validator'; import countryLookup from 'country-code-lookup'; @@ -20,7 +21,7 @@ import { } from '../utils/DiscordMessage'; const EMBEDS = { - osu_INFO: (data: Message | Interaction) => { + osu_INFO: (data: Message | BaseInteraction) => { return makeInfoEmbed({ title: 'osu!', description: `[osu!](https://osu.ppy.sh/home) is a free-to-play rhythm game primarily developed, published, and created by Dean "peppy" Herbert`, @@ -34,43 +35,43 @@ const EMBEDS = { value: '``user``' } ], - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_USER_FOUND: (data: Message | Interaction) => { + NO_USER_FOUND: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `That user doesn't exists on osu!`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_USER_MENTIONED: (data: Message | Interaction) => { + NO_USER_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `No osu! username or user id provided`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - INVALID_USER_MENTIONED: (data: Message | Interaction) => { + INVALID_USER_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `Not a valid osu username or id`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - INVALID_BEATMAP_ID_MENTIONED: (data: Message | Interaction) => { + INVALID_BEATMAP_ID_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `Not a valid osu beatmap id`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_BEATMAP_FOUND: (data: Message | Interaction) => { + NO_BEATMAP_FOUND: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `That beatmap doesn't exists on osu!`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); }, - NO_BEATMAP_MENTIONED: (data: Message | Interaction) => { + NO_BEATMAP_MENTIONED: (data: Message | BaseInteraction) => { return makeErrorEmbed({ title: `No osu! beatmap id provided`, - user: data instanceof Interaction ? data.user : data.author + user: data instanceof BaseInteraction ? data.user : data.author }); } }; @@ -102,8 +103,8 @@ export default class osu extends DiscordModule { }); const [removed, ...newArgs] = args; user = newArgs.join(' '); - } else if (data.isSlashCommand()) - user = data.getSlashCommand().options.getString('user'); + } else if (data.isApplicationCommand()) + user = data.getSlashCommand().options.get('user')?.value?.toString(); if (!validator.isNumeric(user) && !this.validate_osu_username(user)) return await sendHybridInteractionMessageResponse(data, { @@ -117,7 +118,7 @@ export default class osu extends DiscordModule { embeds: [EMBEDS.NO_USER_FOUND(data.getRaw())] }); - if (data.isSlashCommand()) { + if (data.isApplicationCommand()) { await data.getSlashCommand().deferReply(); } @@ -258,12 +259,12 @@ export default class osu extends DiscordModule { 'https://osu.ppy.sh/images/layout/avatar-guest.png' ); - const row = new MessageActionRow().addComponents( - new MessageButton() + const row = new ActionRowBuilder().addComponents( + new ButtonBuilder() .setEmoji('🔗') .setLabel(' Open Profile') .setURL(`https://osu.ppy.sh/users/${result.id}`) - .setStyle('LINK') + .setStyle(ButtonStyle.Link) ); return await sendHybridInteractionMessageResponse(data, { @@ -280,8 +281,8 @@ export default class osu extends DiscordModule { }); const [removed, ...newArgs] = args; beatmap = newArgs.join(' '); - } else if (data.isSlashCommand()) - beatmap = data.getSlashCommand().options.getString('beatmap'); + } else if (data.isApplicationCommand()) + beatmap = data.getSlashCommand().options.get('beatmap')?.value?.toString(); if (!validator.isNumeric(beatmap)) return await sendHybridInteractionMessageResponse(data, { @@ -295,7 +296,7 @@ export default class osu extends DiscordModule { embeds: [EMBEDS.NO_BEATMAP_FOUND(data.getRaw())] }); - if (data.isSlashCommand()) await data.getSlashCommand().deferReply(); + if (data.isApplicationCommand()) await data.getSlashCommand().deferReply(); const bm_result = result[0]; @@ -436,32 +437,32 @@ export default class osu extends DiscordModule { `https://assets.ppy.sh/beatmaps/${bm_result.beatmapSetId}/covers/cover.jpg` ); - const row = new MessageActionRow(); + const row = new ActionRowBuilder(); if (bm_result.hasDownload) row.addComponents( - new MessageButton() + new ButtonBuilder() .setEmoji('🌎') .setLabel(' Download (Beatconnect)') .setURL(`https://beatconnect.io/b/${bm_result.beatmapSetId}/`) - .setStyle('LINK') + .setStyle(ButtonStyle.Link) ); row.addComponents( - new MessageButton() + new ButtonBuilder() .setEmoji('🔗') .setLabel(' Open listing') .setURL( `https://osu.ppy.sh/beatmapsets/${bm_result.beatmapSetId}${url_mode}/${bm_result.id}` ) - .setStyle('LINK') + .setStyle(ButtonStyle.Link) ); row.addComponents( - new MessageButton() + new ButtonBuilder() .setEmoji('💬') .setLabel(' Open discussion') .setURL( `https://osu.ppy.sh/beatmapsets/${bm_result.beatmapSetId}/discussion` ) - .setStyle('LINK') + .setStyle(ButtonStyle.Link) ); return await sendHybridInteractionMessageResponse(data, { @@ -480,7 +481,7 @@ export default class osu extends DiscordModule { }); } query = args[0].toLowerCase(); - } else if (data.isSlashCommand()) { + } else if (data.isApplicationCommand()) { query = args.getSubcommand(); } diff --git a/src/providers/Discord.ts b/src/providers/Discord.ts index 1169dd6..e2db41f 100644 --- a/src/providers/Discord.ts +++ b/src/providers/Discord.ts @@ -1,4 +1,4 @@ -import { Guild, Client, GuildMember, Intents, Interaction, Message, TextChannel, BaseGuildTextChannel } from 'discord.js'; +import { Guild, Client, GuildMember, IntentsBitField, Interaction, Message, TextChannel, BaseGuildTextChannel, TextBasedChannelMixin, ChannelType, BaseGuildVoiceChannel, InteractionType } from 'discord.js'; import Logger from '../libs/Logger'; import Environment from './Environment'; @@ -38,13 +38,13 @@ class Discord { constructor() { this.client = new Client({ - //partials: ['MESSAGE', 'CHANNEL', 'REACTION'], intents: [ - Intents.FLAGS.GUILDS, - Intents.FLAGS.GUILD_MESSAGES, - Intents.FLAGS.GUILD_MEMBERS, - Intents.FLAGS.GUILD_PRESENCES, - Intents.FLAGS.GUILD_VOICE_STATES + IntentsBitField.Flags.MessageContent, + IntentsBitField.Flags.Guilds, + IntentsBitField.Flags.GuildMessages, + IntentsBitField.Flags.GuildMembers, + IntentsBitField.Flags.GuildPresences, + IntentsBitField.Flags.GuildVoiceStates ] }); } @@ -127,7 +127,7 @@ class Discord { if (interaction.guild) { thisModule.GuildInteractionCreate(interaction); - if (interaction.isCommand() && interaction.commandName && thisModule.commandInteractionName) { + if (interaction.type === InteractionType.ApplicationCommand && interaction.commandName && thisModule.commandInteractionName) { thisModule.GuildCommandInteractionCreate(interaction); if (interaction.commandName.toLowerCase() === thisModule.commandInteractionName) thisModule.GuildModuleCommandInteractionCreate(interaction); @@ -160,7 +160,7 @@ class Discord { // Handling guild commands this.client.on('messageCreate', async (message: Message) => { - if (!(message.channel instanceof BaseGuildTextChannel)) return; + if (!(message.channel instanceof BaseGuildTextChannel || message.channel instanceof BaseGuildVoiceChannel)) return; if (message.author.bot) return; if (typeof message.guild?.id === 'undefined') return; diff --git a/src/providers/DiscordMusicPlayer.ts b/src/providers/DiscordMusicPlayer.ts index 2013f21..112ed0c 100644 --- a/src/providers/DiscordMusicPlayer.ts +++ b/src/providers/DiscordMusicPlayer.ts @@ -1,4 +1,12 @@ -import { VoiceChannel, Snowflake, TextChannel, StageChannel, Guild } from 'discord.js'; +import { + VoiceChannel, + Snowflake, + TextChannel, + StageChannel, + Guild, + PermissionsBitField, + BaseGuildVoiceChannel +} from 'discord.js'; import { AudioPlayer, VoiceConnection, @@ -98,10 +106,7 @@ export class DiscordMusicPlayerInstance { this.player.on(AudioPlayerStatus.Idle, async (oldStage, newStage) => { //The player stopped - if ( - newStage.status === AudioPlayerStatus.Idle && - oldStage.status !== AudioPlayerStatus.Idle - ) { + if (newStage.status === AudioPlayerStatus.Idle && oldStage.status !== AudioPlayerStatus.Idle) { // Loop mode is set to current song if (this.loopMode === DiscordMusicPlayerLoopMode.Current) { if (this.queue.track.length !== 0) { @@ -149,7 +154,7 @@ export class DiscordMusicPlayerInstance { public joinVoiceChannel(voiceChannel: VoiceChannel | StageChannel, textChannel?: TextChannel) { const permissions = voiceChannel.permissionsFor(DiscordProvider.client.user!); - if (!permissions || !voiceChannel.joinable || !permissions.has('CONNECT')) + if (!permissions || !voiceChannel.joinable || !permissions.has(PermissionsBitField.Flags.Connect)) throw new Error('No permissions'); if (textChannel) this.textChannel = textChannel; @@ -157,17 +162,18 @@ export class DiscordMusicPlayerInstance { this.voiceConnection = joinVoiceChannel({ channelId: this.voiceChannel.id, guildId: this.voiceChannel.guild.id, - adapterCreator: this.voiceChannel.guild - .voiceAdapterCreator as DiscordGatewayAdapterCreator + adapterCreator: this.voiceChannel.guild.voiceAdapterCreator as DiscordGatewayAdapterCreator }); this.voiceConnection.on( VoiceConnectionStatus.Ready, - (oldState: VoiceConnectionState, newState: VoiceConnectionState) => { - let currentVC = DiscordProvider.client.guilds.cache.get(voiceChannel.guild.id)?.me - ?.voice.channel; - if (currentVC && currentVC.id !== this.voiceChannel.id) { - this.voiceChannel = currentVC; + async (oldState: VoiceConnectionState, newState: VoiceConnectionState) => { + let guild = DiscordProvider.client.guilds.cache.get(voiceChannel.guild.id); + if (guild) { + let currentVC = guild?.members.me?.voice.channel; + if (currentVC && currentVC.id !== this.voiceChannel.id) { + this.voiceChannel = currentVC; + } } } ); @@ -175,12 +181,12 @@ export class DiscordMusicPlayerInstance { this.voiceConnection.on( VoiceConnectionStatus.Disconnected, (oldState: VoiceConnectionState, newState: VoiceConnectionState) => { - setTimeout(() => { - if ( - !DiscordProvider.client.guilds.cache.get(voiceChannel.guildId!)!.me!.voice - .channelId - ) { - this.events.emit('disconnect', new VoiceDisconnectedEvent(this)); + setTimeout(async () => { + let guild = DiscordProvider.client.guilds.cache.get(voiceChannel.guildId); + if(guild) { + if (!guild?.members.me?.voice.channelId) { + this.events.emit('disconnect', new VoiceDisconnectedEvent(this)); + } } }, 2000); } @@ -190,9 +196,10 @@ export class DiscordMusicPlayerInstance { public async leaveVoiceChannel() { if (this.player) this.player.pause(); - if (DiscordProvider.client.guilds.cache.get(this.voiceChannel.guild.id)?.me?.voice) { - this.voiceConnection?.disconnect(); - } + const guild = DiscordProvider.client.guilds.cache.get(this.voiceChannel.guild.id); + if (!guild) return; + + if (guild.members.me?.voice) this.voiceConnection?.disconnect(); } public async pausePlayer() { @@ -286,10 +293,7 @@ export class DiscordMusicPlayerInstance { const stream = 'https://fakestream:42069/fake/stream/fake/audio/fake.mp3'; const resource = createAudioResource(stream); this.player.play(resource); - this.player.emit( - 'error', - new AudioPlayerError(new Error('Music player was manually crashed'), null!) - ); + this.player.emit('error', new AudioPlayerError(new Error('Music player was manually crashed'), null!)); } } @@ -328,10 +332,9 @@ class DiscordMusicPlayer { public async searchYouTubeByYouTubeLink(youtubeLink: YouTubeLink) { // Search the url - const searched: YouTubeVideo[] = await playdl.search( - 'https://www.youtube.com/watch?v=' + youtubeLink.videoId, - { source: { youtube: 'video' } } - ); + const searched: YouTubeVideo[] = await playdl.search('https://www.youtube.com/watch?v=' + youtubeLink.videoId, { + source: { youtube: 'video' } + }); for (let video of searched) { if (video.id === youtubeLink.videoId) return video; } @@ -345,9 +348,7 @@ class DiscordMusicPlayer { } // Last resort, search the title - const videoInfo = await playdl.video_basic_info( - 'https://www.youtube.com/watch?v=' + youtubeLink.videoId - ); + const videoInfo = await playdl.video_basic_info('https://www.youtube.com/watch?v=' + youtubeLink.videoId); if (videoInfo?.video_details?.title) { const searched: YouTubeVideo[] = await playdl.search(videoInfo.video_details.title, { source: { youtube: 'video' } @@ -357,9 +358,7 @@ class DiscordMusicPlayer { } } - let yt_info = await playdl.video_info( - 'https://www.youtube.com/watch?v=' + youtubeLink.videoId - ); + let yt_info = await playdl.video_info('https://www.youtube.com/watch?v=' + youtubeLink.videoId); if (yt_info) { return new YouTubeVideo({ id: yt_info.video_details.id, diff --git a/src/utils/DiscordMessage.ts b/src/utils/DiscordMessage.ts index 4c30fdf..9977d6d 100644 --- a/src/utils/DiscordMessage.ts +++ b/src/utils/DiscordMessage.ts @@ -1,5 +1,5 @@ import { - MessageEmbed, + EmbedBuilder, User, MessagePayload, MessageOptions, @@ -11,7 +11,8 @@ import { Message, ColorResolvable, Interaction, - InteractionReplyOptions + InteractionReplyOptions, + BaseInteraction } from 'discord.js'; import App from '..'; @@ -43,7 +44,7 @@ interface EmbedDataPresets { } export function makeEmbed(data: EmbedData) { - const embed = new MessageEmbed(); + const embed = new EmbedBuilder(); embed.setColor(data.color || '#FFFFFF'); if (!data.icon) embed.setTitle(data.title); @@ -54,14 +55,14 @@ export function makeEmbed(data: EmbedData) { if (data.setTimestamp) embed.setTimestamp(); if (data.user) - embed.footer = { + embed.setFooter({ text: `${data.user.username} | v${App.version}`, iconURL: `${data.user.displayAvatarURL()}?size=4096` - }; + }); else - embed.footer = { + embed.setFooter({ text: `v${App.version}` - }; + }); if (data.fields) embed.addFields(data.fields); @@ -160,8 +161,8 @@ export async function sendHybridInteractionMessageResponse( data: HybridInteractionMessage, payload: MessageOptions | InteractionReplyOptions, replace = false -): Promise { - if (data.isSlashCommand() || data.isButton() || data.isSelectMenu()) { +): Promise { + if (data.isApplicationCommand() || data.isButton() || data.isSelectMenu()) { const messageComponent = data.getMessageComponentInteraction(); if (!messageComponent.replied) { diff --git a/src/utils/DiscordModule.ts b/src/utils/DiscordModule.ts index a2293fe..22aebc4 100644 --- a/src/utils/DiscordModule.ts +++ b/src/utils/DiscordModule.ts @@ -8,7 +8,9 @@ import { TextBasedChannel, MessageComponentInteraction, User, - SelectMenuInteraction + SelectMenuInteraction, + InteractionType, + BaseInteraction } from 'discord.js'; export default class DiscordModule { @@ -56,17 +58,17 @@ export default class DiscordModule { } export class HybridInteractionMessage { - public data: Interaction | Message; - constructor(data: Interaction | Message) { + public data: BaseInteraction | Message; + constructor(data: BaseInteraction | Message) { this.data = data; } public isInteraction(): boolean { - return this.data instanceof Interaction; + return this.data instanceof BaseInteraction; } - public isSlashCommand(): boolean { - return this.data instanceof CommandInteraction && this.data.isCommand(); + public isApplicationCommand(): boolean { + return this.data instanceof CommandInteraction && this.data.type === InteractionType.ApplicationCommand; } public isButton(): boolean { @@ -130,7 +132,7 @@ export class HybridInteractionMessage { return this.data as Message; } - public getRaw(): Interaction | Message { + public getRaw(): BaseInteraction | Message { return this.data; } } From 7d4b3add1499446ae9375066954cc13e697bf83e Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 18:58:49 +0700 Subject: [PATCH 03/63] Add instance check --- src/discord/MusicPlayer/Play.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index 2649100..d5d7f1a 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -158,6 +158,7 @@ export default class Play extends DiscordModule { await joinVoiceChannelProcedure(new HybridInteractionMessage(interaction), null, voiceChannel); let instance = DiscordMusicPlayer.getGuildInstance(guild.id); + if(!instance) return; if (instance!.voiceChannel.id !== member.voice.channel.id) return await sendHybridInteractionMessageResponse( @@ -235,6 +236,7 @@ export default class Play extends DiscordModule { await joinVoiceChannelProcedure(new HybridInteractionMessage(interaction), null, voiceChannel); let instance = DiscordMusicPlayer.getGuildInstance(guild.id); + if(!instance) return; if (instance!.voiceChannel.id !== member.voice.channel.id) return await sendHybridInteractionMessageResponse( @@ -304,6 +306,7 @@ export default class Play extends DiscordModule { } let instance = DiscordMusicPlayer.getGuildInstance(guild.id); + if(!instance) return; if (instance!.voiceChannel.id !== member.voice.channel.id) return await sendHybridInteractionMessageResponse( From 6110dd876e59d3b1cf9d4019e02fe472a8949d78 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 18:59:06 +0700 Subject: [PATCH 04/63] Support voice text channel --- src/discord/MusicPlayer/Join.ts | 6 ++++-- src/providers/Discord.ts | 2 +- src/providers/DiscordMusicPlayer.ts | 7 ++++--- src/utils/DiscordMessage.ts | 11 ++++++++--- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index 75fd345..e5ff954 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -12,7 +12,9 @@ import { TextChannel, VoiceBasedChannel, PermissionsBitField, - ButtonStyle + ButtonStyle, + BaseGuildTextChannel, + BaseGuildVoiceChannel } from 'discord.js'; import { I18n } from 'i18n'; @@ -130,7 +132,7 @@ export async function joinVoiceChannelProcedure( if (!member || !channel || !guild) return; if (channel instanceof DMChannel) return; - if (!(channel instanceof TextChannel)) return; + if (!(channel instanceof BaseGuildTextChannel || channel instanceof BaseGuildVoiceChannel)) return; const memberVoiceChannel = member.voice.channel; //isMessage ? member.voice.channel : DiscordProvider.client.guilds.cache.get(guild.id)!.members.cache.get((data as Interaction).user.id)?.voice.channel; if (!memberVoiceChannel) return; diff --git a/src/providers/Discord.ts b/src/providers/Discord.ts index e2db41f..68a9a29 100644 --- a/src/providers/Discord.ts +++ b/src/providers/Discord.ts @@ -261,7 +261,7 @@ class Discord { // Handling mentions this.client.on('messageCreate', async (message: Message) => { // TODO: Handle DMs commands soon - if (!(message.channel instanceof TextChannel)) return; + if (!(message.channel instanceof BaseGuildTextChannel || message.channel instanceof BaseGuildVoiceChannel)) return; if (message.author.bot) return; if (typeof message.guild?.id === 'undefined') return; diff --git a/src/providers/DiscordMusicPlayer.ts b/src/providers/DiscordMusicPlayer.ts index 112ed0c..f834aa6 100644 --- a/src/providers/DiscordMusicPlayer.ts +++ b/src/providers/DiscordMusicPlayer.ts @@ -5,7 +5,8 @@ import { StageChannel, Guild, PermissionsBitField, - BaseGuildVoiceChannel + BaseGuildVoiceChannel, + BaseGuildTextChannel } from 'discord.js'; import { AudioPlayer, @@ -83,7 +84,7 @@ export enum DiscordMusicPlayerLoopMode { export class DiscordMusicPlayerInstance { public queue: Queue; public player: AudioPlayer; - public textChannel?: TextChannel; + public textChannel?: BaseGuildTextChannel | BaseGuildVoiceChannel; public voiceChannel: VoiceChannel | StageChannel; public voiceConnection?: VoiceConnection; public previousTrack?: ValidTracks; @@ -151,7 +152,7 @@ export class DiscordMusicPlayerInstance { return true; } - public joinVoiceChannel(voiceChannel: VoiceChannel | StageChannel, textChannel?: TextChannel) { + public joinVoiceChannel(voiceChannel: VoiceChannel | StageChannel, textChannel?: BaseGuildTextChannel | BaseGuildVoiceChannel) { const permissions = voiceChannel.permissionsFor(DiscordProvider.client.user!); if (!permissions || !voiceChannel.joinable || !permissions.has(PermissionsBitField.Flags.Connect)) diff --git a/src/utils/DiscordMessage.ts b/src/utils/DiscordMessage.ts index 9977d6d..c469628 100644 --- a/src/utils/DiscordMessage.ts +++ b/src/utils/DiscordMessage.ts @@ -12,7 +12,9 @@ import { ColorResolvable, Interaction, InteractionReplyOptions, - BaseInteraction + BaseInteraction, + BaseGuildVoiceChannel, + VoiceChannel } from 'discord.js'; import App from '..'; @@ -130,14 +132,17 @@ export function makeProcessingEmbed(data: EmbedDataPresets) { } export async function sendMessage( - channel: TextChannel | DMChannel | BaseGuildTextChannel | GuildTextBasedChannel | PartialDMChannel, + channel: TextChannel | DMChannel | BaseGuildTextChannel | GuildTextBasedChannel | PartialDMChannel | BaseGuildTextChannel | BaseGuildVoiceChannel, user: User | undefined, options: string | MessagePayload | MessageOptions ) { let message; try { - message = await channel.send(options); + if(channel instanceof BaseGuildVoiceChannel) + message = await (channel as VoiceChannel).send(options); + else + message = await channel.send(options); } catch (error) { if (typeof user === 'undefined') { return Logger.error( From 081d76668617bfb8d5a9ef74bf1f9fbea409b9bc Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 19:59:53 +0700 Subject: [PATCH 05/63] Add support command --- .env.example | 1 + locales/en.json | 5 ++++ locales/jp.json | 5 ++++ locales/th.json | 5 ++++ src/discord/Help.ts | 4 +-- src/discord/Support.ts | 54 ++++++++++++++++++++++++++++++++++++ src/providers/Discord.ts | 2 ++ src/providers/Environment.ts | 2 ++ 8 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 src/discord/Support.ts diff --git a/.env.example b/.env.example index a73c170..877f3d9 100644 --- a/.env.example +++ b/.env.example @@ -7,6 +7,7 @@ DATABASE_URL=postgresql://user:password@host:port/dbName?schema=public DISCORD_TOKEN=SuperSecretDiscordToken DEVELOPER_IDS=DEV1_ID,DEV2_ID PRIVATE_BOT=true +SUPPORT_URL=https://example.com/support OSU_API_KEY=SuperSecretosu!Key YOUTUBE_COOKIE_BASE64=SuperSecretCookie_EncodeItInBase64_AndThen_RemoveTheLastEqualToo \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index 9b9913e..96ac2b6 100644 --- a/locales/en.json +++ b/locales/en.json @@ -145,5 +145,10 @@ "title_processing": "Measuring network performance ( ◕▿◕ )", "running_on": "Running on {{HOST}}", "development_environment": "Development Environment" + }, + "support": { + "title": "Support", + "info": "[Join {{BOT_NAME}}'s support server]({{{LINK}}})", + "not_available": "{{BOT_NAME}}'s support server is currently unavailable" } } \ No newline at end of file diff --git a/locales/jp.json b/locales/jp.json index 9487362..87c6aef 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -145,5 +145,10 @@ "title_processing": "ネットワーク性能の測定 ( ◕▿◕ )", "running_on": "{{HOST}}で実行中", "development_environment": "開発環境" + }, + "support": { + "title": "サポート", + "info": "[{{BOT_NAME}}のサポートサーバーに参加する]({{{LINK}}})", + "not_available": "{{BOT_NAME}}のサポートサーバーは現在利用できません" } } \ No newline at end of file diff --git a/locales/th.json b/locales/th.json index da987f6..797c412 100644 --- a/locales/th.json +++ b/locales/th.json @@ -145,5 +145,10 @@ "title_processing": "กำลังวัดประสิทธิภาพของเครือข่าย ( ◕▿◕ )", "running_on": "ทำงานอยู่บน {{HOST}}", "development_environment": "โหมดกำลังพัฒนา" + }, + "support": { + "title": "ติดต่อฝ่ายสนับสนุน", + "info": "[เข้าร่วมเซิร์ฟเวอร์สนับสนุนของ {{BOT_NAME}}]({{{LINK}}})", + "not_available": "เซิร์ฟเวอร์สนับสนุนของ {{BOT_NAME}} ไม่พร้อมใช้งานในขณะนี้" } } \ No newline at end of file diff --git a/src/discord/Help.ts b/src/discord/Help.ts index 17f1835..fb10f2e 100644 --- a/src/discord/Help.ts +++ b/src/discord/Help.ts @@ -1,4 +1,4 @@ -import { CommandInteraction, Interaction, Message } from 'discord.js'; +import { CommandInteraction, Message } from 'discord.js'; import { I18n } from 'i18n'; import DiscordProvider from '../providers/Discord'; @@ -24,7 +24,7 @@ const EMBEDS = { fields: [ { name: `☕ ${locale.__('help.general')}`, - value: `help, ping, invite, userinfo, stats`, + value: `help, ping, invite, userinfo, stats, support`, inline: true }, { diff --git a/src/discord/Support.ts b/src/discord/Support.ts new file mode 100644 index 0000000..75816b9 --- /dev/null +++ b/src/discord/Support.ts @@ -0,0 +1,54 @@ +import { Message, CommandInteraction } from 'discord.js'; +import { I18n } from 'i18n'; + +import Environment from '../providers/Environment'; +import DiscordProvider from '../providers/Discord'; +import Locale from '../services/Locale'; + +import DiscordModule, { HybridInteractionMessage } from '../utils/DiscordModule'; +import { sendHybridInteractionMessageResponse, makeInfoEmbed } from '../utils/DiscordMessage'; + +const EMBEDS = { + SUPPORT_INFO: (data: HybridInteractionMessage, locale: I18n) => { + const user = data.getUser(); + let message; + if (Environment.get().SUPPORT_URL) + message = locale.__('support.info', { BOT_NAME: DiscordProvider.client.user!.username, LINK: Environment.get().SUPPORT_URL}); + + return makeInfoEmbed({ + title: locale.__('support.title'), + description: message || locale.__('support.not_available', { BOT_NAME: DiscordProvider.client.user!.username}), + user + }); + } +}; + +export default class Support extends DiscordModule { + public id: string = 'Discord_Support'; + public commands = ['support']; + public commandInteractionName = 'support'; + + async GuildOnModuleCommand(args: any, message: Message) { + await this.run(new HybridInteractionMessage(message), args); + } + + async GuildModuleCommandInteractionCreate(interaction: CommandInteraction) { + await this.run(new HybridInteractionMessage(interaction), interaction.options); + } + + async run(data: HybridInteractionMessage, args: any) { + const guild = data.getGuild(); + if (!guild) return; + + const locale = await Locale.getGuildLocale(guild.id); + + await sendHybridInteractionMessageResponse(data, { + embeds: [EMBEDS.SUPPORT_INFO(data, locale)] + }); + + if(Environment.get().SUPPORT_URL) + await sendHybridInteractionMessageResponse(data, { + content: Environment.get().SUPPORT_URL + }); + } +} diff --git a/src/providers/Discord.ts b/src/providers/Discord.ts index 68a9a29..24ad2d6 100644 --- a/src/providers/Discord.ts +++ b/src/providers/Discord.ts @@ -14,6 +14,7 @@ import Discord_MembershipScreening from '../discord/MembershipScreening'; import Discord_osu from '../discord/osu'; import Discord_UserInfo from '../discord/UserInfo'; import Discord_Stats from '../discord/Stats'; +import Discord_Support from '../discord/Support'; import Discord_MusicPlayer_Play from '../discord/MusicPlayer/Play'; import Discord_MusicPlayer_Skip from '../discord/MusicPlayer/Skip'; @@ -64,6 +65,7 @@ class Discord { new Discord_InteractionManager(), new Discord_osu(), new Discord_Settings(), + new Discord_Support(), new Discord_MusicPlayer_Play(), new Discord_MusicPlayer_NowPlaying(), diff --git a/src/providers/Environment.ts b/src/providers/Environment.ts index 19c9a6e..77e17c2 100644 --- a/src/providers/Environment.ts +++ b/src/providers/Environment.ts @@ -29,6 +29,7 @@ class Environment { const DISCORD_TOKEN = process.env.DISCORD_TOKEN; const DEVELOPER_IDS = process.env.DEVELOPER_IDS; const PRIVATE_BOT = process.env.PRIVATE_BOT; + const SUPPORT_URL = process.env.SUPPORT_URL; const OSU_API_KEY = process.env.OSU_API_KEY; const YOUTUBE_COOKIE_BASE64 = process.env.YOUTUBE_COOKIE_BASE64; @@ -39,6 +40,7 @@ class Environment { DISCORD_TOKEN, DEVELOPER_IDS, PRIVATE_BOT, + SUPPORT_URL, OSU_API_KEY, YOUTUBE_COOKIE_BASE64 From c3bf7891e9862fd605e2b55c73c6883eb8b821c0 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 21:00:58 +0700 Subject: [PATCH 06/63] Fixed NaN date --- src/discord/UserInfo.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/discord/UserInfo.ts b/src/discord/UserInfo.ts index 535ba66..8dd4ade 100644 --- a/src/discord/UserInfo.ts +++ b/src/discord/UserInfo.ts @@ -106,15 +106,25 @@ const EMBEDS = { title = `📺 ${locale.__('userinfo.watching_x', { NAME: activity.name })}`; break; case ActivityType.Competing: - title = `'🌠 ${locale.__('userinfo.competing_x', { NAME: activity.name })}`; + title = `🌠 ${locale.__('userinfo.competing_x', { NAME: activity.name })}`; break; } + const startTime = activity.timestamps?.start; + const endTime = activity.timestamps?.end; embed.addFields({ name: `${title}`, value: `${activity.details === null ? '' : activity.details} - ${activity.state === null ? '' : activity.state} - Since - \u200b`, + ${activity.state === null ? '' : activity.state} + ${ + startTime + ? `Since ` + : '' + }${ + endTime + ? `\nEnd ` + : '' + } + \u200b`, inline: false }); } From 8252f4e2a3e21a83401a3ac35920eca62d4a4963 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 21:06:54 +0700 Subject: [PATCH 07/63] Add missing translation for userinfo --- locales/en.json | 4 +++- locales/jp.json | 4 +++- locales/th.json | 4 +++- src/discord/UserInfo.ts | 4 ++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/locales/en.json b/locales/en.json index 96ac2b6..3d8173b 100644 --- a/locales/en.json +++ b/locales/en.json @@ -35,7 +35,9 @@ "streaming_x": "Streaming {{NAME}}", "listening_x": "Listening to {{NAME}}", "watching_x": "Watching {{NAME}}", - "competing_x": "Competing {{NAME}}" + "competing_x": "Competing {{NAME}}", + "since": "Since {{{TIME}}}", + "end": "Ending {{{TIME}}}" }, "say": { "title": "Say", diff --git a/locales/jp.json b/locales/jp.json index 87c6aef..41182ab 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -35,7 +35,9 @@ "streaming_x": "{{NAME}}をストリーミング中", "listening_x": "{{NAME}}を再生中", "watching_x": "{{NAME}}鑑賞中", - "competing_x": "{{NAME}}に参戦中です" + "competing_x": "{{NAME}}に参戦中です", + "since": "{{{TIME}}}から", + "end": "{{{TIME}}}で終了" }, "say": { "title": "言うこと", diff --git a/locales/th.json b/locales/th.json index 797c412..461aaaf 100644 --- a/locales/th.json +++ b/locales/th.json @@ -35,7 +35,9 @@ "streaming_x": "กำลังสตรีม {{NAME}}", "listening_x": "กำลังฟัง {{NAME}}", "watching_x": "กำลังดู {{NAME}}", - "competing_x": "กำลังแข่งขัน {{NAME}}" + "competing_x": "กำลังแข่งขัน {{NAME}}", + "since": "ตั้งแต่ {{{TIME}}}", + "end": "สิ้นสุดใน {{{TIME}}}" }, "say": { "title": "สั่งพูด", diff --git a/src/discord/UserInfo.ts b/src/discord/UserInfo.ts index 8dd4ade..844dd9e 100644 --- a/src/discord/UserInfo.ts +++ b/src/discord/UserInfo.ts @@ -117,11 +117,11 @@ const EMBEDS = { ${activity.state === null ? '' : activity.state} ${ startTime - ? `Since ` + ? `${locale.__('userinfo.since', {TIME: `` })}` : '' }${ endTime - ? `\nEnd ` + ? `\n${locale.__('userinfo.end', {TIME: `` })}` : '' } \u200b`, From 872e8455e03e345d53457bb7beae3793203c7578 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 21:09:27 +0700 Subject: [PATCH 08/63] Bump version to 0.10 --- src/providers/App.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/App.ts b/src/providers/App.ts index 116ffd4..98c3855 100644 --- a/src/providers/App.ts +++ b/src/providers/App.ts @@ -7,7 +7,7 @@ import osu from './osuAPI'; import Logger from '../libs/Logger'; import Locale from './Locale'; class App { - public readonly versionNumber = `0.09`; + public readonly versionNumber = `0.10`; public readonly version = `${this.versionNumber}${ Environment.get().NODE_ENV === 'development' ? ' / Development Build' : '' }`; From 074bd35bddf18bb6922bd4731b1196da142a331f Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 21:38:35 +0700 Subject: [PATCH 09/63] Fix Service Announcement crash --- src/discord/Developer/ServiceAnnouncement.ts | 21 ++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/discord/Developer/ServiceAnnouncement.ts b/src/discord/Developer/ServiceAnnouncement.ts index 00f3e43..630e9fe 100644 --- a/src/discord/Developer/ServiceAnnouncement.ts +++ b/src/discord/Developer/ServiceAnnouncement.ts @@ -1,4 +1,4 @@ -import { Message, EmbedBuilder, Interaction, CommandInteraction, TextChannel, BaseInteraction } from 'discord.js'; +import { Message, EmbedBuilder, Interaction, CommandInteraction, TextChannel, BaseInteraction, EmbedData, EmbedFieldData, EmbedProviderData } from 'discord.js'; import { Promise } from 'bluebird'; import fs from 'fs'; import path from 'path'; @@ -21,6 +21,8 @@ import DiscordProvider from '../../providers/Discord'; import Prisma from '../../providers/Prisma'; import Users from '../../services/Users'; +const hexToDecimal = (hex: string) => parseInt(hex.replace('#', ''), 16); + const EMBEDS = { ANNOUNCEMENT_INFO: (data: Message | BaseInteraction) => { return makeInfoEmbed({ @@ -42,14 +44,14 @@ const EMBEDS = { user: data instanceof BaseInteraction ? data.user : data.author }); }, - MAKE_PAYLOAD: (payload: any) => { + MAKE_PAYLOAD: (payload: EmbedData) => { const user = DiscordProvider.client.user; payload.footer = { text: `${user?.username}`, iconURL: `${user?.displayAvatarURL()}?size=4096` }; - if (!payload.timestamp) payload.timestamp = new Date(); + if (!payload.timestamp) payload.timestamp = new Date().getTime() / 1000; if (payload.thumbnail?.url === 'bot_avatar') payload.thumbnail.url = `${user?.displayAvatarURL()}?size=4096`; @@ -58,7 +60,10 @@ const EMBEDS = { payload.image.url = `${user?.displayAvatarURL()}?size=4096`; if (payload.description) - payload.description = payload.description.replaceAll('{bot_username}', user?.username); + payload.description = payload.description.replaceAll('{bot_username}', user?.username!); + + if (payload.color && isNaN(payload.color)) + payload.color = hexToDecimal(payload.color.toString()); return new EmbedBuilder(payload); }, @@ -100,7 +105,7 @@ const EMBEDS = { let Announcements = { News: { - color: '#FAEDF0', + color: hexToDecimal('#FAEDF0'), title: '📰 Newsletter', description: 'Some description here', thumbnail: { @@ -108,7 +113,7 @@ let Announcements = { } }, Maintenance: { - color: '#383b80', + color: hexToDecimal('#383b80'), title: '🔧 Maintenance', description: 'The bot is going offline for maintenance.', thumbnail: { @@ -116,7 +121,7 @@ let Announcements = { } }, Message: { - color: '#A1DE93', + color: hexToDecimal('#A1DE93'), title: '✉️ Message', description: 'Some description here', thumbnail: { @@ -124,7 +129,7 @@ let Announcements = { } }, Alert: { - color: '#EC255A', + color: hexToDecimal('#EC255A'), title: '🚨 Alert', description: 'Some description here', thumbnail: { From 9e408d88f4ff3a0205dabc09b2e7ffe0b0c2721f Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 22:13:37 +0700 Subject: [PATCH 10/63] Add language settings --- src/discord/Settings/Language.ts | 103 +++++++++++++++++++++++++++++++ src/discord/Settings/index.ts | 4 +- 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 src/discord/Settings/Language.ts diff --git a/src/discord/Settings/Language.ts b/src/discord/Settings/Language.ts new file mode 100644 index 0000000..4e0dba2 --- /dev/null +++ b/src/discord/Settings/Language.ts @@ -0,0 +1,103 @@ +import { Permissions, Guild, PermissionFlagsBits, PermissionsBitField } from 'discord.js'; +import { I18n } from 'i18n'; + +import DiscordProvider from '../../providers/Discord'; +import Prisma from '../../providers/Prisma'; +import Cache from '../../providers/Cache'; + +import { HybridInteractionMessage } from '../../utils/DiscordModule'; +import { + makeInfoEmbed, + makeErrorEmbed, + makeSuccessEmbed, + sendHybridInteractionMessageResponse +} from '../../utils/DiscordMessage'; + +import { COMMON_EMBEDS } from '.'; +import Locale from '../../providers/Locale'; + +const EMBEDS = { + LANGUAGE_INFO: (data: HybridInteractionMessage, locale: I18n, currentLocale: string) => { + return makeInfoEmbed({ + title: locale.__('settings_language.info', { LANGUAGE: currentLocale}), + description: locale.__('settings_language.info_description', { LANGUAGES: Locale.getLocaleProvider('en').getLocales().join(', ') }), + user: data.getUser() + }); + }, + LANGUAGE_INVALID: (data: HybridInteractionMessage, locale: I18n) => { + return makeErrorEmbed({ + title: locale.__('settings_language.language_invalid'), + description: locale.__('settings_language.language_invalid_description'), + user: data.getUser() + }); + }, + LANGUAGE_UPDATED: (data: HybridInteractionMessage, locale: I18n, newLanguage: string) => { + return makeSuccessEmbed({ + title: locale.__({ phrase: 'settings_language.language_updated', locale: newLanguage }), + description: locale.__({ phrase: 'settings_language.language_updated_description', locale: newLanguage }, { LANGUAGE: newLanguage }), + user: data.getUser() + }); + } +}; + +export default async (data: HybridInteractionMessage, args: any, guild: Guild, locale: I18n) => { + let member = data.getMember(); + if (!member) return; + + const GuildCache = await Cache.getCachedGuild(guild.id); + if (!GuildCache) return; + const language = GuildCache.locale; + + if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) + return await sendHybridInteractionMessageResponse(data, { + embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] + }); + + let newLanguage: string | null | undefined; + if (data.isMessage()) { + let _name: string; + if (typeof args[1] === 'undefined') + return await sendHybridInteractionMessageResponse(data, { + embeds: [EMBEDS.LANGUAGE_INFO(data, locale, language)] + }); + + let __name = args; + __name.shift(); + _name = __name.join(' '); + newLanguage = _name; + } else if (data.isApplicationCommand()) newLanguage = data.getSlashCommand().options.get('language', true).value?.toString(); + + if (!newLanguage) + return await sendHybridInteractionMessageResponse(data, { + embeds: [EMBEDS.LANGUAGE_INFO(data, locale, language)] + }); + + newLanguage = newLanguage.toLowerCase(); + + if (!Locale.getLocaleProvider('en').getLocales().includes(newLanguage)) + return await sendHybridInteractionMessageResponse(data, { + embeds: [EMBEDS.LANGUAGE_INVALID(data, locale)] + }); + + let placeholder: HybridInteractionMessage | undefined; + + let _placeholder = await sendHybridInteractionMessageResponse(data, { + embeds: [COMMON_EMBEDS.PROCESSING(data, locale)] + }); + if (_placeholder) placeholder = new HybridInteractionMessage(_placeholder); + + await Prisma.client.guild.update({ + where: { id: guild.id }, + data: { locale: newLanguage } + }); + Cache.updateGuildCache(guild.id); + + if (data && data.isMessage() && placeholder && placeholder.isMessage()) + return placeholder.getMessage().edit({ embeds: [EMBEDS.LANGUAGE_UPDATED(data, locale, newLanguage)] }); + else if (data.isApplicationCommand()) + return await sendHybridInteractionMessageResponse( + data, + { embeds: [EMBEDS.LANGUAGE_UPDATED(data, locale, newLanguage)] }, + true + ); +}; diff --git a/src/discord/Settings/index.ts b/src/discord/Settings/index.ts index 4d2d61a..a47948f 100644 --- a/src/discord/Settings/index.ts +++ b/src/discord/Settings/index.ts @@ -1,6 +1,5 @@ import { Message, - Interaction, CommandInteraction, Permissions, ThreadChannel, @@ -24,6 +23,7 @@ import { } from '../../utils/DiscordMessage'; import * as PrefixModule from './Prefix'; +import * as LanguageModule from './Language'; import * as ServiceAnnouncementModule from './ServiceAnnouncement'; export const COMMON_EMBEDS = { @@ -102,6 +102,8 @@ export default class Settings extends DiscordModule { }); case 'prefix': return await PrefixModule.default(data, args, guild, locale); + case 'language': + return await LanguageModule.default(data, args, guild, locale); case 'enableserviceannouncement': return await ServiceAnnouncementModule.setEnableServiceAnnouncement(data, args, guild, locale); case 'serviceannouncementchannel': From 31be21fdd6cdf483813a3af7271a5f55a9c8b36f Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 22:13:48 +0700 Subject: [PATCH 11/63] Add locale for language settings --- locales/en.json | 10 +++++++++- locales/jp.json | 10 +++++++++- locales/th.json | 10 +++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/locales/en.json b/locales/en.json index 3d8173b..889594c 100644 --- a/locales/en.json +++ b/locales/en.json @@ -130,7 +130,7 @@ "settings": { "title": "Settings", "description": "Change how {{BOT_NAME}} behave on **{{GUILD_NAME}}**", - "valid_args": "``Prefix`` ``EnableServiceAnnouncement`` ``ServiceAnnouncementChannel``" + "valid_args": "``Prefix`` ``Language`` ``EnableServiceAnnouncement`` ``ServiceAnnouncementChannel``" }, "settings_prefix": { "info": "Current prefix is {{{PREFIX}}}", @@ -142,6 +142,14 @@ "prefix_updated": "Prefix updated", "prefix_updated_description": "From now onwards, I shall be called by using ``{{PREFIX}}``" }, + "settings_language": { + "info": "Current language is {{LANGUAGE}}", + "info_description": "Provide a new language to change\n**Available languages**: ``{{LANGUAGES}}``", + "language_invalid": "Invalid language", + "language_invalid_description": "The language code is invalid or not supported yet", + "language_updated": "Language updated", + "language_updated_description": "I will be using {{LANGUAGE}} from now on" + }, "ping": { "title": "Network performance", "title_processing": "Measuring network performance ( ◕▿◕ )", diff --git a/locales/jp.json b/locales/jp.json index 41182ab..7f0bcd8 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -130,7 +130,7 @@ "settings": { "title": "設定", "description": "**{{GUILD_NAME}}**サーバでの{{BOT_NAME}}の動作変更", - "valid_args": "``Prefix`` ``EnableServiceAnnouncement`` ``ServiceAnnouncementChannel``" + "valid_args": "``Prefix`` ``Language`` ``EnableServiceAnnouncement`` ``ServiceAnnouncementChannel``" }, "settings_prefix": { "info": "現在の接頭辞は「{{{PREFIX}}}」です。", @@ -142,6 +142,14 @@ "prefix_updated": "プレフィックスを更新", "prefix_updated_description": "これ以降、私は 「``{{PREFIX}}``」 を使って呼び出されることになります。" }, + "settings_language": { + "info": "現在の言語は{{LANGUAGE}}です", + "info_description": "変更する新しい言語を提供する\n**利用可能な言語**: ``{{LANGUAGES}}``", + "language_invalid": "無効な言語", + "language_invalid_description": "言語コードが無効であるか、まだサポートされていません", + "language_updated": "言語が変更されました", + "language_updated_description": "これからは{{LANGUAGE}}を使います" + }, "ping": { "title": "ネットワークパフォーマンス", "title_processing": "ネットワーク性能の測定 ( ◕▿◕ )", diff --git a/locales/th.json b/locales/th.json index 461aaaf..dc0eecb 100644 --- a/locales/th.json +++ b/locales/th.json @@ -130,7 +130,7 @@ "settings": { "title": "การตั้งค่า", "description": "เปลี่ยนพฤติกรรมของ {{BOT_NAME}} บน **{{GUILD_NAME}}**", - "valid_args": "``Prefix`` ``EnableServiceAnnouncement`` ``ServiceAnnouncementChannel``" + "valid_args": "``Prefix`` ``Language`` ``EnableServiceAnnouncement`` ``ServiceAnnouncementChannel``" }, "settings_prefix": { "info": "คำนำหน้าปัจจุบันคือ {{{PREFIX}}}", @@ -142,6 +142,14 @@ "prefix_updated": "อัปเดตคำนำหน้าแล้ว", "prefix_updated_description": "จากนี้ไป คุณสามารถเรียกฉันโดยใช้ ``{{PREFIX}}`` นะ" }, + "settings_language": { + "info": "ภาษาปัจจุบันตอนนี้คือ {{LANGUAGE}}", + "info_description": "ระบุภาษาใหม่เพื่อเปลี่ยน\n**ภาษาที่ใช้ได้**: ``{{LANGUAGES}}``", + "language_invalid": "ภาษาไม่ถูกต้อง", + "language_invalid_description": "รหัสภาษาไม่ถูกต้องหรือยังไม่รองรับ", + "language_updated": "เปลี่ยนภาษาเรียบร้อย", + "language_updated_description": "ตั้งแต่นี้ไปฉันจะใช้ภาษา {{LANGUAGE}}" + }, "ping": { "title": "ประสิทธิภาพของเครือข่าย", "title_processing": "กำลังวัดประสิทธิภาพของเครือข่าย ( ◕▿◕ )", From 25fff2cc34513aff9494bbbbca9e22fbd0615fa5 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Wed, 29 Jun 2022 22:20:24 +0700 Subject: [PATCH 12/63] Fixed wrong date --- src/discord/Developer/ServiceAnnouncement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/discord/Developer/ServiceAnnouncement.ts b/src/discord/Developer/ServiceAnnouncement.ts index 630e9fe..5a72754 100644 --- a/src/discord/Developer/ServiceAnnouncement.ts +++ b/src/discord/Developer/ServiceAnnouncement.ts @@ -51,7 +51,7 @@ const EMBEDS = { iconURL: `${user?.displayAvatarURL()}?size=4096` }; - if (!payload.timestamp) payload.timestamp = new Date().getTime() / 1000; + if (!payload.timestamp) payload.timestamp = Date.now(); if (payload.thumbnail?.url === 'bot_avatar') payload.thumbnail.url = `${user?.displayAvatarURL()}?size=4096`; From 2a8b7344dee8667db1c2d0b2539f4057d6c527d0 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Thu, 30 Jun 2022 01:00:45 +0700 Subject: [PATCH 13/63] Add SUPPORT_URL env to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 96ee0e0..255e30b 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ Take a look inside [.env.example](https://github.com/YuzuZensai/Yumi/blob/main/. - ``DISCORD_TOKEN`` Your discord bot token - ``DEVELOPER_IDS`` List of Discord Snowflake User ID that can access developer only modules, separated by ``,`` - ``PRIVATE_BOT`` Should the bot invite be public? ``true`` or ``false`` +- ``SUPPORT_URL`` URL to your support server (If not set, support module will show not available message) - ``OSU_API_KEY`` [osu! API v1 key](https://github.com/ppy/osu-api/wiki) - ``YOUTUBE_COOKIE_BASE64`` YouTube cookies encoded in base64 [How to get cookies?](https://github.com/play-dl/play-dl/tree/main/instructions#youtube-cookies=)* From ab9ca2a4f7362df0aef44d01a0877f8a54bfdc64 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 1 Jul 2022 16:09:53 +0700 Subject: [PATCH 14/63] Bump discord.js --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index db9d3ed..f4165b0 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "country-code-emoji": "^2.3.0", "country-code-lookup": "^0.0.20", "discord-api-types": "^0.35.0", - "discord.js": "14.0.0-dev.1656158629-c4653f9", + "discord.js": "14.0.0-dev.1656634282-819a1fd", "dotenv": "^16.0.1", "i18n": "^0.15.0", "libsodium-wrappers": "^0.7.10", diff --git a/yarn.lock b/yarn.lock index 31eefb0..1e00f27 100644 --- a/yarn.lock +++ b/yarn.lock @@ -608,10 +608,10 @@ discord-api-types@^0.35.0: resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.35.0.tgz#85c6ea95f27580ad13b7a08444b16cb31d41e5e2" integrity sha512-aaIbVgPk7OA3y/HdG00tRM2nB8B3sSPH6KXgamBLRrcAJEQ8XZJNNKeRr0WVzw/lprdpKHKuTNX1DNrYnD5cOw== -discord.js@14.0.0-dev.1656158629-c4653f9: - version "14.0.0-dev.1656158629-c4653f9" - resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.0.0-dev.1656158629-c4653f9.tgz#1d78ff80fd6edc95aedd586bc1c4af63504e0cb5" - integrity sha512-lgHs1LGbAdlpBY5te+8iXMEAoA5FFB9wzFLqfzTedLCDM5IKuadXVUxwLktUmQk/jjeAzGD4+lQ+eEVfWTvWXQ== +discord.js@14.0.0-dev.1656634282-819a1fd: + version "14.0.0-dev.1656634282-819a1fd" + resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.0.0-dev.1656634282-819a1fd.tgz#3e8630c34df05913fb24ee5c63b8139b7cc16e6e" + integrity sha512-FaLWAWMbGxId4c7HmdYtFkvFjBVmNsAigk3XZpJ+hqgu7rAijD6w6fDAZ0Obk2MspxVa8iKWcOmdt1S/N+emgQ== dependencies: "@discordjs/builders" "^0.16.0-dev" "@discordjs/collection" "^0.8.0-dev" From 929ef256abf0105d2602912e4b0f035c9bd2d171 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 1 Jul 2022 20:59:35 +0700 Subject: [PATCH 15/63] Add Spotify API environment vars --- src/providers/Environment.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/providers/Environment.ts b/src/providers/Environment.ts index 77e17c2..5a789e8 100644 --- a/src/providers/Environment.ts +++ b/src/providers/Environment.ts @@ -34,6 +34,11 @@ class Environment { const OSU_API_KEY = process.env.OSU_API_KEY; const YOUTUBE_COOKIE_BASE64 = process.env.YOUTUBE_COOKIE_BASE64; + const SPOTIFY_CLIENT_ID = process.env.SPOTIFY_CLIENT_ID; + const SPOTIFY_CLIENT_SECRET= process.env.SPOTIFY_CLIENT_SECRET; + const SPOTIFY_REFRESH_TOKEN= process.env.SPOTIFY_REFRESH_TOKEN; + const SPOTIFY_CLIENT_MARKET= process.env.SPOTIFY_CLIENT_MARKET; + return { NODE_ENV, @@ -43,7 +48,12 @@ class Environment { SUPPORT_URL, OSU_API_KEY, - YOUTUBE_COOKIE_BASE64 + YOUTUBE_COOKIE_BASE64, + + SPOTIFY_CLIENT_ID, + SPOTIFY_CLIENT_SECRET, + SPOTIFY_REFRESH_TOKEN, + SPOTIFY_CLIENT_MARKET }; } From 4c1293b31923b4236775abffa25eaf9aa2b3a617 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 1 Jul 2022 22:04:37 +0700 Subject: [PATCH 16/63] Support Spotify track, playlist, and album --- src/providers/DiscordMusicPlayer.ts | 195 ++++++++++++++++++++++++++-- 1 file changed, 187 insertions(+), 8 deletions(-) diff --git a/src/providers/DiscordMusicPlayer.ts b/src/providers/DiscordMusicPlayer.ts index f834aa6..6c937f7 100644 --- a/src/providers/DiscordMusicPlayer.ts +++ b/src/providers/DiscordMusicPlayer.ts @@ -1,7 +1,6 @@ import { VoiceChannel, Snowflake, - TextChannel, StageChannel, Guild, PermissionsBitField, @@ -16,27 +15,91 @@ import { createAudioResource, VoiceConnectionStatus, AudioPlayerStatus, - AudioPlayerState, NoSubscriberBehavior, VoiceConnectionState, AudioPlayerError, DiscordGatewayAdapterCreator } from '@discordjs/voice'; -import playdl, { YouTubeVideo } from 'play-dl'; +import playdl, { Spotify, SpotifyPlaylist, SpotifyTrack, YouTubeVideo } from 'play-dl'; import { EventEmitter } from 'stream'; import DiscordProvider from './Discord'; import Environment from './Environment'; -export type ValidTracks = YouTubeVideo; +export type ValidTracks = YouTubeVideo | SpotifyTrack; +declare class YouTubeThumbnail { + url: string; + width: number; + height: number; + constructor(data: any); + toJSON(): { + url: string; + width: number; + height: number; + }; +} + +interface SpotifyThumbnail { + height: number; + width: number; + url: string; +} if (Environment.get().YOUTUBE_COOKIE_BASE64) { playdl.setToken({ youtube: { cookie: Buffer.from(Environment.get().YOUTUBE_COOKIE_BASE64, 'base64').toString() + }, + spotify: { + client_id: Environment.get().SPOTIFY_CLIENT_ID, + client_secret: Environment.get().SPOTIFY_CLIENT_SECRET, + refresh_token: Environment.get().SPOTIFY_REFRESH_TOKEN, + market: Environment.get().SPOTIFY_CLIENT_MARKET, } }); } + +export class TrackUtils { + public static getTitle(track: ValidTracks) { + if (track instanceof YouTubeVideo) { + return track.title; + } else if (track instanceof SpotifyTrack) { + let artistNames = ""; + for(let artist of track.artists) + artistNames += artist.name + " "; + + return `${artistNames} - ${track.name}`;; + } else { + throw new Error('Invalid track type'); + } + } + public static async getThumbnails(track: ValidTracks) { + if (track instanceof YouTubeVideo) { + return track.thumbnails; + } else if (track instanceof SpotifyTrack) { + if (track.thumbnail) + return [track.thumbnail]; + else { + // Try to find the thumbnail again + const result = await DiscordMusicPlayer_Instance.searchSpotifyBySpotifyLink(track); + if(!result) return null; + if(result.thumbnail) + return [result.thumbnail]; + return null; + } + } else { + throw new Error('Invalid track type'); + } + } + public static getHighestResolutionThumbnail(thumbnails: (YouTubeThumbnail[] | SpotifyThumbnail[] | null)) { + if(!thumbnails) return null; + + return (thumbnails as any[]).reduce((prev: any, current: any) => + prev.height * prev.width > current.height * current.width ? prev : current + ); + } +} + export class Queue { public track: ValidTracks[] = []; } @@ -51,6 +114,18 @@ export class YouTubeLink { } } +export class SpotifyLink { + public id: string; + public type: 'track' | 'playlist' | 'album'; + public url: string; + + constructor(id: string, type: ('track' | 'playlist' | 'album'), url: string) { + this.id = id; + this.type = type; + this.url = url; + } +} + export class PlayerPlayingEvent { public instance: DiscordMusicPlayerInstance; @@ -92,6 +167,8 @@ export class DiscordMusicPlayerInstance { public paused: boolean = false; public loopMode: DiscordMusicPlayerLoopMode = DiscordMusicPlayerLoopMode.None; + public actualPlaybackURL?: string; + public readonly events: EventEmitter; constructor({ voiceChannel }: { voiceChannel: VoiceChannel | StageChannel }) { @@ -229,11 +306,26 @@ export class DiscordMusicPlayerInstance { if (!this.voiceConnection) throw new Error('No voice connection'); try { - const stream = await playdl.stream(track.url); - const resource = createAudioResource(stream.stream, { - inputType: stream.type - }); + let resource; + if(track instanceof YouTubeVideo) { + const stream = await playdl.stream(track.url); + resource = createAudioResource(stream.stream, { + inputType: stream.type + }); + this.actualPlaybackURL = track.url; + } else { + const search = await DiscordMusicPlayer_Instance.searchYouTubeBySpotifyLink(track); + if(!search) + throw new Error('Unable to find Spotify track on YouTube'); + + const stream = await playdl.stream(search.url); + resource = createAudioResource(stream.stream, { + inputType: stream.type + }); + this.actualPlaybackURL = search.url; + } + this.player.play(resource); this.voiceConnection.subscribe(this.player); } catch (error: any) { @@ -268,6 +360,10 @@ export class DiscordMusicPlayerInstance { return this.previousTrack; } + public getActualPlaybackURL() { + return this.actualPlaybackURL; + } + public isPaused() { return this.paused; } @@ -331,6 +427,41 @@ class DiscordMusicPlayer { return searched; } + public async searchYouTubeBySpotifyLink(spotifyLink: SpotifyLink) { + + const track = await this.searchSpotifyBySpotifyLink(spotifyLink); + if(!track) return; + + let artistNames = ""; + for(let artist of track.artists) + artistNames += artist.name + " "; + + const ytSearchResult = await this.searchYouTubeByQuery(`${artistNames} ${track.name}`); + if(!ytSearchResult) return null; + + return ytSearchResult[0]; + } + + public async searchSpotifyBySpotifyLink(spotifyLink: SpotifyLink) { + if(playdl.is_expired()) + await playdl.refreshToken(); + + if(spotifyLink.type != 'track') return; + + if(playdl.is_expired()) + await playdl.refreshToken(); + + if(spotifyLink.type != 'track') return; + + // Fetch data from spotify + const searched: Spotify = await playdl.spotify("https://open.spotify.com/track/" + spotifyLink.id); + if(!(searched instanceof SpotifyTrack)) return; + + if (!searched) return null; + const track = searched as unknown as SpotifyTrack; + return track; + } + public async searchYouTubeByYouTubeLink(youtubeLink: YouTubeLink) { // Search the url const searched: YouTubeVideo[] = await playdl.search('https://www.youtube.com/watch?v=' + youtubeLink.videoId, { @@ -393,6 +524,15 @@ class DiscordMusicPlayer { }); } + public async getSpotifySongsInPlayList(spotifyLink: string) { + const result = await playdl.spotify(spotifyLink); + + if(!(result.type == 'playlist' || result.type == 'album')) + throw new Error("Not a spotify playlist"); + + return result as unknown as SpotifyPlaylist; + } + public isYouTubeLink(link: string): boolean { try { this.parseYouTubeLink(link); @@ -402,6 +542,15 @@ class DiscordMusicPlayer { } } + public isSpotifyLink(link: string): boolean { + try { + this.parseSpotifyLink(link); + return true; + } catch (err) { + return false; + } + } + public parseYouTubeLink(query: string): YouTubeLink { if ( query.startsWith('https://www.youtube.com/watch?v=') || @@ -437,6 +586,36 @@ class DiscordMusicPlayer { } } + public parseSpotifyLink(query: string): SpotifyLink { + if (query.startsWith('https://open.spotify.com/track/')) { + let id = query.split('/')[4].split(/[?#]/)[0]; + return { + id: id, + type: 'track', + url: query.split(/[?#]/)[0] + }; + } + else if (query.startsWith('https://open.spotify.com/album/')) { + let id = query.split('/')[4].split(/[?#]/)[0]; + return { + id: id, + type: 'album', + url: query.split(/[?#]/)[0] + }; + } + else if (query.startsWith('https://open.spotify.com/playlist/')) { + let id = query.split('/')[4].split(/[?#]/)[0]; + return { + id: id, + type: 'playlist', + url: query.split(/[?#]/)[0] + }; + } + else { + throw new Error('Spotify link is invalid'); + } + } + private parseURLQuery(query: string) { let queryObject: any = {}; if (query.indexOf('?') >= 0) { From 67c0c752a41770fb99512ff0231468c763b47f64 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 1 Jul 2022 22:04:54 +0700 Subject: [PATCH 17/63] Music player embed for Spotify --- src/discord/MusicPlayer/Join.ts | 65 ++++++++++++-------- src/discord/MusicPlayer/NowPlaying.ts | 43 ++++++++----- src/discord/MusicPlayer/Play.ts | 87 +++++++++++++++++++++------ src/discord/MusicPlayer/Queue.ts | 16 ++--- src/discord/MusicPlayer/Search.ts | 4 +- 5 files changed, 149 insertions(+), 66 deletions(-) diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index e5ff954..f614015 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -32,11 +32,13 @@ import DiscordMusicPlayer, { VoiceDisconnectedEvent, ValidTracks, DiscordMusicPlayerInstance, - DiscordMusicPlayerLoopMode + DiscordMusicPlayerLoopMode, + TrackUtils } from '../../providers/DiscordMusicPlayer'; import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule'; import Locale from '../../services/Locale'; +import { SpotifyTrack, YouTubeVideo } from 'play-dl'; const EMBEDS = { VOICECHANNEL_JOINED: (data: HybridInteractionMessage, locale: I18n) => { @@ -81,35 +83,37 @@ const EMBEDS = { user: data.getUser() }); }, - NOW_PLAYING: (data: HybridInteractionMessage, locale: I18n, track: ValidTracks) => { + NOW_PLAYING: async (data: HybridInteractionMessage, locale: I18n, track: ValidTracks) => { + + const title = TrackUtils.getTitle(track); + const thumbnails = await TrackUtils.getThumbnails(track); + const embed = makeInfoEmbed({ title: locale.__('musicplayer.now_playing'), icon: '🎵 ', - description: track.title, + description: title, user: DiscordProvider.client.user }); - const highestResolutionThumbnail = track.thumbnails.reduce((prev, current) => - prev.height * prev.width > current.height * current.width ? prev : current - ); - - if (highestResolutionThumbnail) embed.setImage(highestResolutionThumbnail.url); + if (TrackUtils.getHighestResolutionThumbnail(thumbnails)) + embed.setImage(TrackUtils.getHighestResolutionThumbnail(thumbnails).url); return embed; }, - NOW_REPEATING: (data: HybridInteractionMessage, locale: I18n, track: ValidTracks) => { + NOW_REPEATING: async (data: HybridInteractionMessage, locale: I18n, track: ValidTracks) => { + + const title = TrackUtils.getTitle(track); + const thumbnails = await TrackUtils.getThumbnails(track); + const embed = makeInfoEmbed({ title: locale.__('musicplayer.now_playing_repeating'), icon: '🎵 ', - description: `${track.title}`, + description: title, user: DiscordProvider.client.user }); - const highestResolutionThumbnail = track.thumbnails.reduce((prev, current) => - prev.height * prev.width > current.height * current.width ? prev : current - ); - - if (highestResolutionThumbnail) embed.setImage(highestResolutionThumbnail.url); + if (TrackUtils.getHighestResolutionThumbnail(thumbnails)) + embed.setImage(TrackUtils.getHighestResolutionThumbnail(thumbnails).url); return embed; } @@ -227,24 +231,37 @@ export async function joinVoiceChannelProcedure( if (event.instance.queue.track[0] !== previousTrack) isLoopMessageSent = false; else if (event.instance.queue.track[0] === previousTrack && isLoopMessageSent) return; - const row = new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setEmoji('▶️') - .setLabel(' Open on YouTube') - .setURL(encodeURI(`https://www.youtube.com/watch?v=${event.instance.queue.track[0].id}`)) - .setStyle(ButtonStyle.Link) - ); + const row = new ActionRowBuilder(); + if(event.instance.queue.track[0] instanceof SpotifyTrack) + row.addComponents( + new ButtonBuilder() + .setEmoji('🟢') + .setLabel(' Open on Spotify') + .setURL(encodeURI(`https://open.spotify.com/track/${event.instance.queue.track[0].id}`)) + .setStyle(ButtonStyle.Link), + ) + if(event.instance.queue.track[0] instanceof YouTubeVideo || event.instance.queue.track[0] instanceof SpotifyTrack) { + const actualPlaybackURL = event.instance.getActualPlaybackURL(); + if(event.instance.queue.track[0] instanceof SpotifyTrack && !actualPlaybackURL) return; + row.addComponents( + new ButtonBuilder() + .setEmoji('🔴') + .setLabel(' Open on YouTube') + .setURL(event.instance.queue.track[0] instanceof YouTubeVideo ? encodeURI(`https://www.youtube.com/watch?v=${event.instance.queue.track[0].id}`) : encodeURI(event.instance.getActualPlaybackURL()!)) + .setStyle(ButtonStyle.Link), + ) + } if (event.instance.textChannel) { if (event.instance.getLoopMode() === DiscordMusicPlayerLoopMode.Current) { isLoopMessageSent = true; await sendMessage(event.instance.textChannel, undefined, { - embeds: [EMBEDS.NOW_REPEATING(data, locale, event.instance.queue.track[0])], + embeds: [await EMBEDS.NOW_REPEATING(data, locale, event.instance.queue.track[0])], components: [row] }); } else { await sendMessage(event.instance.textChannel, undefined, { - embeds: [EMBEDS.NOW_PLAYING(data, locale, event.instance.queue.track[0])], + embeds: [await EMBEDS.NOW_PLAYING(data, locale, event.instance.queue.track[0])], components: [row] }); } diff --git a/src/discord/MusicPlayer/NowPlaying.ts b/src/discord/MusicPlayer/NowPlaying.ts index bae412f..b30ed2b 100644 --- a/src/discord/MusicPlayer/NowPlaying.ts +++ b/src/discord/MusicPlayer/NowPlaying.ts @@ -1,26 +1,29 @@ import { Message, CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js"; import { I18n } from "i18n"; +import { SpotifyTrack, YouTubeVideo } from "play-dl"; import DiscordProvider from "../../providers/Discord"; -import DiscordMusicPlayer, { ValidTracks } from "../../providers/DiscordMusicPlayer"; +import DiscordMusicPlayer, { TrackUtils, ValidTracks } from "../../providers/DiscordMusicPlayer"; import Locale from "../../services/Locale"; import { makeErrorEmbed, makeInfoEmbed, sendHybridInteractionMessageResponse } from "../../utils/DiscordMessage"; import DiscordModule, { HybridInteractionMessage } from "../../utils/DiscordModule"; const EMBEDS = { - NOW_PLAYING: (data: HybridInteractionMessage, locale: I18n, track: ValidTracks) => { + NOW_PLAYING: async (data: HybridInteractionMessage, locale: I18n, track: ValidTracks) => { + + const title = TrackUtils.getTitle(track); + const thumbnails = await TrackUtils.getThumbnails(track); + const embed = makeInfoEmbed({ title: locale.__('musicplayer.now_playing'), icon: '🎵 ', - description: track.title, + description: title, user: DiscordProvider.client.user }); - const highestResolutionThumbnail = track.thumbnails.reduce((prev, current) => (prev.height * prev.width > current.height * current.width) ? prev : current) - - if(highestResolutionThumbnail) - embed.setImage(highestResolutionThumbnail.url); + if (TrackUtils.getHighestResolutionThumbnail(thumbnails)) + embed.setImage(TrackUtils.getHighestResolutionThumbnail(thumbnails).url); return embed; }, @@ -55,15 +58,27 @@ export default class NowPlaying extends DiscordModule { const instance = DiscordMusicPlayer.getGuildInstance(guild.id); if(!instance || !instance.queue.track[0]) return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.NO_MUSIC_PLAYING(data, locale)] }); - const row = new ActionRowBuilder() - .addComponents( + const row = new ActionRowBuilder(); + + if(instance.queue.track[0] instanceof SpotifyTrack) + row.addComponents( new ButtonBuilder() - .setEmoji('▶️') - .setLabel(' Open on YouTube') - .setURL(encodeURI(`https://www.youtube.com/watch?v=${instance.queue.track[0].id}`)) + .setEmoji('🟢') + .setLabel(' Open on Spotify') + .setURL(encodeURI(`https://open.spotify.com/track/${instance.queue.track[0].id}`)) .setStyle(ButtonStyle.Link), ) - - return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.NOW_PLAYING(data, locale, instance.queue.track[0])], components: [row] }); + if(instance.queue.track[0] instanceof YouTubeVideo || instance.queue.track[0] instanceof SpotifyTrack) { + const actualPlaybackURL = instance.getActualPlaybackURL(); + if(instance.queue.track[0] instanceof SpotifyTrack && !actualPlaybackURL) return; + row.addComponents( + new ButtonBuilder() + .setEmoji('🔴') + .setLabel(' Open on YouTube') + .setURL(instance.queue.track[0] instanceof YouTubeVideo ? encodeURI(`https://www.youtube.com/watch?v=${instance.queue.track[0].id}`) : encodeURI(instance.getActualPlaybackURL()!)) + .setStyle(ButtonStyle.Link), + ) + } + return await sendHybridInteractionMessageResponse(data, { embeds: [await EMBEDS.NOW_PLAYING(data, locale, instance.queue.track[0])], components: [row] }); } } \ No newline at end of file diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index d5d7f1a..9ce5ef6 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -14,7 +14,7 @@ import { I18n } from 'i18n'; import { joinVoiceChannelProcedure } from './Join'; import DiscordProvider from '../../providers/Discord'; -import DiscordMusicPlayer, { ValidTracks } from '../../providers/DiscordMusicPlayer'; +import DiscordMusicPlayer, { TrackUtils, ValidTracks } from '../../providers/DiscordMusicPlayer'; import Locale from '../../services/Locale'; import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule'; @@ -24,6 +24,7 @@ import { sendHybridInteractionMessageResponse, makeInfoEmbed } from '../../utils/DiscordMessage'; +import { SpotifyTrack, YouTubeVideo } from 'play-dl'; const EMBEDS = { PLAY_INFO: (data: HybridInteractionMessage, locale: I18n) => { @@ -33,24 +34,25 @@ const EMBEDS = { fields: [ { name: locale.__('common.available_args'), - value: locale.__('musicplayer_play.valid_args'), + value: locale.__('musicplayer_play.valid_args') } ], user: data.getUser() }); }, - ADDED_QUEUE: (data: HybridInteractionMessage, locale: I18n, track: ValidTracks) => { + ADDED_QUEUE: async (data: HybridInteractionMessage, locale: I18n, track: ValidTracks) => { + + const title = TrackUtils.getTitle(track); + const thumbnails = await TrackUtils.getThumbnails(track); + let embed = makeSuccessEmbed({ title: locale.__('musicplayer_play.queue_added_song'), - description: track.title, + description: title, user: data.getUser() }); - const highestResolutionThumbnail = track.thumbnails.reduce((prev, current) => - prev.height * prev.width > current.height * current.width ? prev : current - ); - - if (highestResolutionThumbnail) embed.setImage(highestResolutionThumbnail.url); + if (TrackUtils.getHighestResolutionThumbnail(thumbnails)) + embed.setImage(TrackUtils.getHighestResolutionThumbnail(thumbnails).url); return embed; }, @@ -158,7 +160,7 @@ export default class Play extends DiscordModule { await joinVoiceChannelProcedure(new HybridInteractionMessage(interaction), null, voiceChannel); let instance = DiscordMusicPlayer.getGuildInstance(guild.id); - if(!instance) return; + if (!instance) return; if (instance!.voiceChannel.id !== member.voice.channel.id) return await sendHybridInteractionMessageResponse( @@ -223,7 +225,8 @@ export default class Play extends DiscordModule { const voiceChannel = DiscordProvider.client.guilds.cache.get(guild.id)?.channels.cache.get(payload.d.v); //let member = DiscordProvider.client.guilds.cache.get(guild.id)?.members.cache.get(user.id); - if (!voiceChannel || !(voiceChannel instanceof VoiceChannel || voiceChannel instanceof StageChannel)) return; + if (!voiceChannel || !(voiceChannel instanceof VoiceChannel || voiceChannel instanceof StageChannel)) + return; if (!member.voice.channel) return await sendHybridInteractionMessageResponse( @@ -236,12 +239,16 @@ export default class Play extends DiscordModule { await joinVoiceChannelProcedure(new HybridInteractionMessage(interaction), null, voiceChannel); let instance = DiscordMusicPlayer.getGuildInstance(guild.id); - if(!instance) return; + if (!instance) return; if (instance!.voiceChannel.id !== member.voice.channel.id) return await sendHybridInteractionMessageResponse( hybridData, - { embeds: [EMBEDS.USER_NOT_IN_SAME_VOICECHANNEL(new HybridInteractionMessage(interaction), locale)] }, + { + embeds: [ + EMBEDS.USER_NOT_IN_SAME_VOICECHANNEL(new HybridInteractionMessage(interaction), locale) + ] + }, true ); @@ -267,7 +274,7 @@ export default class Play extends DiscordModule { instance.addTrackToQueue(result); return await sendHybridInteractionMessageResponse( hybridData, - { embeds: [EMBEDS.ADDED_QUEUE(new HybridInteractionMessage(interaction), locale, result)] }, + { embeds: [await EMBEDS.ADDED_QUEUE(new HybridInteractionMessage(interaction), locale, result)] }, true ); } @@ -306,7 +313,7 @@ export default class Play extends DiscordModule { } let instance = DiscordMusicPlayer.getGuildInstance(guild.id); - if(!instance) return; + if (!instance) return; if (instance!.voiceChannel.id !== member.voice.channel.id) return await sendHybridInteractionMessageResponse( @@ -368,13 +375,55 @@ export default class Play extends DiscordModule { ); return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.ADDED_QUEUE(data, locale, result)], + embeds: [await EMBEDS.ADDED_QUEUE(data, locale, result)], components: [row] }); } else return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.ADDED_QUEUE(data, locale, result)] + embeds: [await EMBEDS.ADDED_QUEUE(data, locale, result)] }); + } else if (DiscordMusicPlayer.isSpotifyLink(query)) { + let linkData = DiscordMusicPlayer.parseSpotifyLink(query); + + if (linkData.type === 'playlist' || linkData.type === 'album') { + let playlist = await DiscordMusicPlayer.getSpotifySongsInPlayList(query); + const songs = await playlist.all_tracks(); + + for (const song of songs) { + instance.addTrackToQueue(song); + } + + return await sendHybridInteractionMessageResponse( + data, + { embeds: [EMBEDS.ADDED_SONGS_QUEUE(data, locale, songs)] }, + true + ); + } else if (false) { + sendHybridInteractionMessageResponse( + data, + { embeds: [EMBEDS.LOOKUP_ERROR(data, locale, new Error('Album not supported for now'))] }, + true + ); + return null; + } + + let result = await DiscordMusicPlayer.searchSpotifyBySpotifyLink(linkData).catch((err) => { + sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.LOOKUP_ERROR(data, locale, err)] }, true); + return null; + }); + + if (!result) return; + + if (data.isMessage() && data.getMessage().embeds.length > 0) { + data.getMessage().suppressEmbeds(true); + } + + instance.addTrackToQueue(result); + + return await sendHybridInteractionMessageResponse(data, { + embeds: [await EMBEDS.ADDED_QUEUE(data, locale, result)] + }); + } else { let result = await DiscordMusicPlayer.searchYouTubeByQuery(query); @@ -407,13 +456,13 @@ export default class Play extends DiscordModule { ); return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.ADDED_QUEUE(data, locale, result[0])], + embeds: [await EMBEDS.ADDED_QUEUE(data, locale, result[0])], components: [row] }); } return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.ADDED_QUEUE(data, locale, result[0])] + embeds: [await EMBEDS.ADDED_QUEUE(data, locale, result[0])] }); } } diff --git a/src/discord/MusicPlayer/Queue.ts b/src/discord/MusicPlayer/Queue.ts index d818b7f..9f68fc5 100644 --- a/src/discord/MusicPlayer/Queue.ts +++ b/src/discord/MusicPlayer/Queue.ts @@ -3,7 +3,8 @@ import { I18n } from 'i18n'; import DiscordMusicPlayer, { DiscordMusicPlayerInstance, - DiscordMusicPlayerLoopMode + DiscordMusicPlayerLoopMode, + TrackUtils } from '../../providers/DiscordMusicPlayer'; import Locale from '../../services/Locale'; @@ -21,14 +22,15 @@ const EMBEDS = { user: data.getUser() }); else { + const nowPlayingText = `${ instance.getLoopMode() === DiscordMusicPlayerLoopMode.Current ? ` ${locale.__('musicplayer_queue.looping_current')}` : '' - }: [${queue.track[0].title}](${queue.track[0].url})`; + }: [${TrackUtils.getTitle(queue.track[0])}](${queue.track[0].url})`; if (queue.track.length == 1) { - let queueString = `1. [${queue.track[0].title}](${queue.track[0].url})`; + let queueString = `1. [${TrackUtils.getTitle(queue.track[0])}](${queue.track[0].url})`; return makeInfoEmbed({ title: locale.__('musicplayer_queue.title'), description: `${locale.__('musicplayer_queue.now_playing')}${nowPlayingText}\n @@ -36,10 +38,10 @@ const EMBEDS = { user: data.getUser() }); } else if (queue.track.length >= 10) { - const upcomingText = `[${queue.track[1].title}](${queue.track[1].url})`; + const upcomingText = `[${TrackUtils.getTitle(queue.track[1])}](${queue.track[1].url})`; const first10 = queue.track.slice(0, 10); let queueString = first10 - .map((track, index) => `${index + 1}. [${track.title}](${track.url})`) + .map((track, index) => `${index + 1}. [${TrackUtils.getTitle(track)}](${track.url})`) .join('\n'); return makeInfoEmbed({ title: locale.__('musicplayer_queue.title'), @@ -50,9 +52,9 @@ const EMBEDS = { user: data.getUser() }); } else { - const upcomingText = `[${queue.track[1].title}](${queue.track[1].url})`; + const upcomingText = `[${TrackUtils.getTitle(queue.track[1])}](${queue.track[1].url})`; const queueString = queue.track - .map((track, index) => `${index + 1}. [${track.title}](${track.url})`) + .map((track, index) => `${index + 1}. [${TrackUtils.getTitle(track)}](${track.url})`) .join('\n'); return makeInfoEmbed({ title: locale.__('musicplayer_queue.title'), diff --git a/src/discord/MusicPlayer/Search.ts b/src/discord/MusicPlayer/Search.ts index 5aadebd..a8f018f 100644 --- a/src/discord/MusicPlayer/Search.ts +++ b/src/discord/MusicPlayer/Search.ts @@ -3,7 +3,7 @@ import { I18n } from "i18n"; import { joinVoiceChannelProcedure } from "./Join"; -import DiscordMusicPlayer, { ValidTracks } from "../../providers/DiscordMusicPlayer"; +import DiscordMusicPlayer, { TrackUtils, ValidTracks } from "../../providers/DiscordMusicPlayer"; import Locale from "../../services/Locale"; import DiscordModule, { HybridInteractionMessage } from "../../utils/DiscordModule"; @@ -28,7 +28,7 @@ const EMBEDS = { title: locale.__('musicplayer_search.title_result'), description: `${locale.__('musicplayer_search.x_results_found', { COUNT: result.length.toString() - })}\n\n${result.map(track => `- [${track.title}](${track.url})`).join('\n')}`, + })}\n\n${result.map(track => `- [${TrackUtils.getTitle(track)}](${track.url})`).join('\n')}`, user: data.getUser() }); }, From c58cc971630c64ca1876e97b7c78b0b9a53c525b Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 1 Jul 2022 23:08:33 +0700 Subject: [PATCH 18/63] Typo --- src/discord/MusicPlayer/Join.ts | 4 ++-- src/discord/MusicPlayer/NowPlaying.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index f614015..c393d24 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -236,7 +236,7 @@ export async function joinVoiceChannelProcedure( row.addComponents( new ButtonBuilder() .setEmoji('🟢') - .setLabel(' Open on Spotify') + .setLabel(' Open in Spotify') .setURL(encodeURI(`https://open.spotify.com/track/${event.instance.queue.track[0].id}`)) .setStyle(ButtonStyle.Link), ) @@ -246,7 +246,7 @@ export async function joinVoiceChannelProcedure( row.addComponents( new ButtonBuilder() .setEmoji('🔴') - .setLabel(' Open on YouTube') + .setLabel(' Open in YouTube') .setURL(event.instance.queue.track[0] instanceof YouTubeVideo ? encodeURI(`https://www.youtube.com/watch?v=${event.instance.queue.track[0].id}`) : encodeURI(event.instance.getActualPlaybackURL()!)) .setStyle(ButtonStyle.Link), ) diff --git a/src/discord/MusicPlayer/NowPlaying.ts b/src/discord/MusicPlayer/NowPlaying.ts index b30ed2b..32139be 100644 --- a/src/discord/MusicPlayer/NowPlaying.ts +++ b/src/discord/MusicPlayer/NowPlaying.ts @@ -64,7 +64,7 @@ export default class NowPlaying extends DiscordModule { row.addComponents( new ButtonBuilder() .setEmoji('🟢') - .setLabel(' Open on Spotify') + .setLabel(' Open in Spotify') .setURL(encodeURI(`https://open.spotify.com/track/${instance.queue.track[0].id}`)) .setStyle(ButtonStyle.Link), ) @@ -74,7 +74,7 @@ export default class NowPlaying extends DiscordModule { row.addComponents( new ButtonBuilder() .setEmoji('🔴') - .setLabel(' Open on YouTube') + .setLabel(' Open in YouTube') .setURL(instance.queue.track[0] instanceof YouTubeVideo ? encodeURI(`https://www.youtube.com/watch?v=${instance.queue.track[0].id}`) : encodeURI(instance.getActualPlaybackURL()!)) .setStyle(ButtonStyle.Link), ) From 303c44a625dd73477a48398c7fc293bcad075c01 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Sat, 2 Jul 2022 00:04:34 +0700 Subject: [PATCH 19/63] Fix locale not updating for music player --- src/discord/MusicPlayer/Join.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index c393d24..5f61117 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -225,6 +225,7 @@ export async function joinVoiceChannelProcedure( // Register Event Listeners instance.events.on('playing', async (event: PlayerPlayingEvent) => { + const locale = await Locale.getGuildLocale(guild.id); if (!event.instance.queue || !event.instance.queue.track || event.instance.queue.track.length === 0) return; previousTrack = event.instance.getPreviousTrack(); From ecfce7e3c4dd6c6d76826a2d7ae329ffd9f12867 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 4 Jul 2022 21:27:36 +0700 Subject: [PATCH 20/63] Remove unused code --- src/discord/MusicPlayer/Join.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index 5f61117..b315767 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -138,7 +138,7 @@ export async function joinVoiceChannelProcedure( if (channel instanceof DMChannel) return; if (!(channel instanceof BaseGuildTextChannel || channel instanceof BaseGuildVoiceChannel)) return; - const memberVoiceChannel = member.voice.channel; //isMessage ? member.voice.channel : DiscordProvider.client.guilds.cache.get(guild.id)!.members.cache.get((data as Interaction).user.id)?.voice.channel; + const memberVoiceChannel = member.voice.channel; if (!memberVoiceChannel) return; const bot = guild.members.me; From 949240a23ab79926d978f17a4536ce2f6a1abeb4 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 4 Jul 2022 21:28:04 +0700 Subject: [PATCH 21/63] Changed required permissions for settings --- src/discord/Settings/Language.ts | 6 ++++-- src/discord/Settings/Prefix.ts | 6 ++++-- src/discord/Settings/ServiceAnnouncement.ts | 14 +++++++++----- src/discord/Settings/index.ts | 18 ++++++++++-------- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/discord/Settings/Language.ts b/src/discord/Settings/Language.ts index 4e0dba2..43345f2 100644 --- a/src/discord/Settings/Language.ts +++ b/src/discord/Settings/Language.ts @@ -48,9 +48,11 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l if (!GuildCache) return; const language = GuildCache.locale; - if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) + const requiredPermissions = [PermissionsBitField.Flags.ManageGuild]; + + if (!member.permissions.has(requiredPermissions)) return await sendHybridInteractionMessageResponse(data, { - embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] + embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale, requiredPermissions)] }); let newLanguage: string | null | undefined; diff --git a/src/discord/Settings/Prefix.ts b/src/discord/Settings/Prefix.ts index 3862022..8462985 100644 --- a/src/discord/Settings/Prefix.ts +++ b/src/discord/Settings/Prefix.ts @@ -54,9 +54,11 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l if (!GuildCache) return; const prefix = GuildCache.prefix; - if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) + const requiredPermissions = [PermissionsBitField.Flags.ManageGuild]; + + if (!member.permissions.has(requiredPermissions)) return await sendHybridInteractionMessageResponse(data, { - embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] + embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale, requiredPermissions)] }); let newPrefix: string | null | undefined; diff --git a/src/discord/Settings/ServiceAnnouncement.ts b/src/discord/Settings/ServiceAnnouncement.ts index 7320e40..56b1ac8 100644 --- a/src/discord/Settings/ServiceAnnouncement.ts +++ b/src/discord/Settings/ServiceAnnouncement.ts @@ -1,4 +1,4 @@ -import { Permissions, Guild, GuildChannel, ThreadChannel, Message, PermissionsBitField } from 'discord.js'; +import { Permissions, Guild, GuildChannel, ThreadChannel, Message, PermissionsBitField, PermissionFlags, PermissionFlagsBits, PermissionResolvable } from 'discord.js'; import { I18n } from 'i18n'; import DiscordProvider from '../../providers/Discord'; @@ -104,9 +104,11 @@ export const setEnableServiceAnnouncement = async ( let member = data.getMember(); if (!member) return; - if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) + const requiredPermissions = [PermissionsBitField.Flags.Administrator]; + + if (!member.permissions.has(requiredPermissions)) return await sendHybridInteractionMessageResponse(data, { - embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] + embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale, requiredPermissions)] }); let GuildCache = await Cache.getCachedGuild(guild.id); @@ -184,9 +186,11 @@ export const setServiceAnnouncementChannel = async ( let member = data.getMember(); if (!member) return; - if (!member.permissions.has([PermissionsBitField.Flags.Administrator])) + const requiredPermissions: PermissionResolvable[] = [PermissionsBitField.Flags.Administrator]; + + if (!member.permissions.has(requiredPermissions)) return await sendHybridInteractionMessageResponse(data, { - embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale)] + embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale, requiredPermissions)] }); let channel; diff --git a/src/discord/Settings/index.ts b/src/discord/Settings/index.ts index a47948f..af4988f 100644 --- a/src/discord/Settings/index.ts +++ b/src/discord/Settings/index.ts @@ -1,16 +1,13 @@ import { Message, CommandInteraction, - Permissions, - ThreadChannel, - GuildChannel, - Guild + Guild, + PermissionsBitField, + PermissionResolvable } from 'discord.js'; import { I18n } from 'i18n'; import DiscordProvider from '../../providers/Discord'; -import Prisma from '../../providers/Prisma'; -import Cache from '../../providers/Cache'; import Locale from '../../services/Locale'; import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule'; @@ -27,10 +24,15 @@ import * as LanguageModule from './Language'; import * as ServiceAnnouncementModule from './ServiceAnnouncement'; export const COMMON_EMBEDS = { - NO_PERMISSION: (data: HybridInteractionMessage, locale: I18n) => { + NO_PERMISSION: (data: HybridInteractionMessage, locale: I18n, permissions: PermissionResolvable[]) => { + + let allPermissions = []; + for(const value of permissions) { + allPermissions.push(new PermissionsBitField(value).toArray()); + } return makeErrorEmbed({ title: locale.__('common.no_permissions'), - description: locale.__('common.no_permissions_description', { PERMISSIONS: 'ADMINISTRATOR'}), + description: locale.__('common.no_permissions_description', { PERMISSIONS: allPermissions.join(', ')}), user: data.getUser() }); }, From c3a0892a7ba773eaea254d017b64f1496bc69da4 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 4 Jul 2022 21:29:20 +0700 Subject: [PATCH 22/63] Fixed guild name being encoded --- locales/en.json | 2 +- locales/jp.json | 2 +- locales/th.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/locales/en.json b/locales/en.json index 889594c..de0a33b 100644 --- a/locales/en.json +++ b/locales/en.json @@ -129,7 +129,7 @@ }, "settings": { "title": "Settings", - "description": "Change how {{BOT_NAME}} behave on **{{GUILD_NAME}}**", + "description": "Change how {{BOT_NAME}} behave on **{{{GUILD_NAME}}}**", "valid_args": "``Prefix`` ``Language`` ``EnableServiceAnnouncement`` ``ServiceAnnouncementChannel``" }, "settings_prefix": { diff --git a/locales/jp.json b/locales/jp.json index 7f0bcd8..12ab5e5 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -129,7 +129,7 @@ }, "settings": { "title": "設定", - "description": "**{{GUILD_NAME}}**サーバでの{{BOT_NAME}}の動作変更", + "description": "**{{{GUILD_NAME}}}**サーバでの{{BOT_NAME}}の動作変更", "valid_args": "``Prefix`` ``Language`` ``EnableServiceAnnouncement`` ``ServiceAnnouncementChannel``" }, "settings_prefix": { diff --git a/locales/th.json b/locales/th.json index dc0eecb..2fc9094 100644 --- a/locales/th.json +++ b/locales/th.json @@ -129,7 +129,7 @@ }, "settings": { "title": "การตั้งค่า", - "description": "เปลี่ยนพฤติกรรมของ {{BOT_NAME}} บน **{{GUILD_NAME}}**", + "description": "เปลี่ยนพฤติกรรมของ {{BOT_NAME}} บน **{{{GUILD_NAME}}}**", "valid_args": "``Prefix`` ``Language`` ``EnableServiceAnnouncement`` ``ServiceAnnouncementChannel``" }, "settings_prefix": { From 23c0817a67030177922b97d0a35d30926a38ed0f Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 4 Jul 2022 21:30:31 +0700 Subject: [PATCH 23/63] Removed extra type --- src/discord/Settings/ServiceAnnouncement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/discord/Settings/ServiceAnnouncement.ts b/src/discord/Settings/ServiceAnnouncement.ts index 56b1ac8..3f84273 100644 --- a/src/discord/Settings/ServiceAnnouncement.ts +++ b/src/discord/Settings/ServiceAnnouncement.ts @@ -186,7 +186,7 @@ export const setServiceAnnouncementChannel = async ( let member = data.getMember(); if (!member) return; - const requiredPermissions: PermissionResolvable[] = [PermissionsBitField.Flags.Administrator]; + const requiredPermissions = [PermissionsBitField.Flags.Administrator]; if (!member.permissions.has(requiredPermissions)) return await sendHybridInteractionMessageResponse(data, { From d3cd143897e972b1105f821b8b0b9f5a57d04719 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 14:53:19 +0700 Subject: [PATCH 24/63] Removed unused code --- src/discord/MusicPlayer/Play.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index 9ce5ef6..4fd4a88 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -398,13 +398,6 @@ export default class Play extends DiscordModule { { embeds: [EMBEDS.ADDED_SONGS_QUEUE(data, locale, songs)] }, true ); - } else if (false) { - sendHybridInteractionMessageResponse( - data, - { embeds: [EMBEDS.LOOKUP_ERROR(data, locale, new Error('Album not supported for now'))] }, - true - ); - return null; } let result = await DiscordMusicPlayer.searchSpotifyBySpotifyLink(linkData).catch((err) => { From 00e558b5cbe5678583643d6a8bb7372311628526 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 14:54:08 +0700 Subject: [PATCH 25/63] Implemented PlayMy feature --- locales/en.json | 3 + locales/jp.json | 3 + locales/th.json | 3 + src/discord/MusicPlayer/PlayMy.ts | 161 ++++++++++++++++++++++++++++++ src/providers/Discord.ts | 2 + 5 files changed, 172 insertions(+) create mode 100644 src/discord/MusicPlayer/PlayMy.ts diff --git a/locales/en.json b/locales/en.json index de0a33b..c2c24df 100644 --- a/locales/en.json +++ b/locales/en.json @@ -108,6 +108,9 @@ "queue_added_songs_description": "Added {{COUNT}} songs to the queue", "error": "Error while looking up the song" }, + "musicplayer_playmy": { + "not_detected": "You don't seem to be listening to any music currently according to your activity" + }, "musicplayer_queue": { "title": "Queue", "empty": "The queue is empty! (っ˘ω˘ς )", diff --git a/locales/jp.json b/locales/jp.json index 12ab5e5..9e30df3 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -108,6 +108,9 @@ "queue_added_songs_description": "キューに{{COUNT}}曲を追加", "error": "曲の検索中にエラーが発生" }, + "musicplayer_playmy": { + "not_detected": "あなたの活動状況を見ると、現在、音楽を聴いていないようですね" + }, "musicplayer_queue": { "title": "キュー", "empty": "キューは空です! (っ˘ω˘ς )", diff --git a/locales/th.json b/locales/th.json index 2fc9094..9d4da6e 100644 --- a/locales/th.json +++ b/locales/th.json @@ -108,6 +108,9 @@ "queue_added_songs_description": "เพิ่ม {{COUNT}} เพลงในคิว", "error": "เกิดข้อผิดพลาดขณะค้นหาเพลง" }, + "musicplayer_playmy": { + "not_detected": "เท่าที่ดูจากกิจกรรมของคุณ เหมือนว่าตอนนี้คุณไม่ได้เล่นเพลงอะไรอยู่นะ" + }, "musicplayer_queue": { "title": "คิวเพลง", "empty": "ตอนนี้คิวว่างนะ (っ˘ω˘ς )", diff --git a/src/discord/MusicPlayer/PlayMy.ts b/src/discord/MusicPlayer/PlayMy.ts new file mode 100644 index 0000000..c64089f --- /dev/null +++ b/src/discord/MusicPlayer/PlayMy.ts @@ -0,0 +1,161 @@ +import { I18n } from "i18n"; +import { Message, CommandInteraction, ActivityType, ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js"; + +import DiscordMusicPlayer, { TrackUtils, ValidTracks } from "../../providers/DiscordMusicPlayer"; +import Locale from "../../services/Locale"; + +import { makeSuccessEmbed, makeErrorEmbed, sendHybridInteractionMessageResponse } from "../../utils/DiscordMessage"; +import DiscordModule, { HybridInteractionMessage } from "../../utils/DiscordModule"; +import { joinVoiceChannelProcedure } from "./Join"; + +const EMBEDS = { + NOT_DETECTED: (data: HybridInteractionMessage, locale: I18n) => { + return makeErrorEmbed({ + title: locale.__('musicplayer_playmy.not_detected'), + user: data.getUser() + }); + }, + USER_NOT_IN_VOICECHANNEL: (data: HybridInteractionMessage, locale: I18n) => { + return makeErrorEmbed({ + title: locale.__('musicplayer.not_in_voice'), + user: data.getUser() + }); + }, + USER_NOT_IN_SAME_VOICECHANNEL: (data: HybridInteractionMessage, locale: I18n) => { + return makeErrorEmbed({ + title: locale.__('musicplayer.different_voice_channel'), + user: data.getUser() + }); + }, + ADDED_QUEUE: async (data: HybridInteractionMessage, locale: I18n, track: ValidTracks) => { + + const title = TrackUtils.getTitle(track); + const thumbnails = await TrackUtils.getThumbnails(track); + + let embed = makeSuccessEmbed({ + title: locale.__('musicplayer_play.queue_added_song'), + description: title, + user: data.getUser() + }); + + if (TrackUtils.getHighestResolutionThumbnail(thumbnails)) + embed.setImage(TrackUtils.getHighestResolutionThumbnail(thumbnails).url); + + return embed; + } +} + +export default class PlayMy extends DiscordModule { + + public id = "Discord_MusicPlayer_PlayMy"; + public commands = ["playmy"]; + public commandInteractionName = "playmy"; + + async GuildOnModuleCommand(args: any, message: Message) { + await this.run(new HybridInteractionMessage(message), args); + } + + async GuildModuleCommandInteractionCreate(interaction: CommandInteraction) { + await this.run(new HybridInteractionMessage(interaction), interaction.options); + } + + async run(data: HybridInteractionMessage, args: any) { + + const guild = data.getGuild(); + const member = data.getMember(); + + if(!guild || !member) return; + + const locale = await Locale.getGuildLocale(guild.id); + + if (!member.voice.channel) + return await sendHybridInteractionMessageResponse(data, { + embeds: [EMBEDS.USER_NOT_IN_VOICECHANNEL(data, locale)] + }); + + const voiceChannel = member.voice.channel; + + if (!DiscordMusicPlayer.isGuildInstanceExists(guild.id)) { + await joinVoiceChannelProcedure(data, null, voiceChannel); + } + + let instance = DiscordMusicPlayer.getGuildInstance(guild.id); + if (!instance) return; + + if (instance!.voiceChannel.id !== member.voice.channel.id) + return await sendHybridInteractionMessageResponse( + data, + { embeds: [EMBEDS.USER_NOT_IN_SAME_VOICECHANNEL(data, locale)] }, + true + ); + + if (!instance!.isConnected()) { + await joinVoiceChannelProcedure(data, instance!, voiceChannel); + instance = DiscordMusicPlayer.getGuildInstance(guild.id); + } + + if(!instance) return; + if(!member.presence) return; + if(!member.presence.activities) return; + + let query; + let found = false; + for (const activity of member.presence.activities) { + if(activity.type === ActivityType.Listening) { + if(!activity.details) continue; + found = true; + + if(activity.name == "Spotify") + query = `${activity.state} - ${activity.details}` + else + query = `${activity.state} - ${activity.details}` // TODO: Find better query formula + + const result = await DiscordMusicPlayer.searchYouTubeByQuery(query); + if (!result) continue; + instance.addTrackToQueue(result[0]); + + let row; + if (result.length > 1) { + // TODO: Find a better logic than this + // If the first result title is exact match with the query or first title contains half the space of the query, it's probably a sentence + // then we don't need to show the search results + // if(result[0].title === query || result[0].title && (Math.ceil((result[0].title.split(" ").length - 1) / 2) === Math.ceil((query.split(" ").length - 1) / 2))) return; + + // The query length is too long to fit in json + if (query.length > 100 - 51) return; + + row = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setEmoji('🔎') + .setCustomId( + JSON.stringify({ + m: 'MP_S', + a: 'search', + d: { + q: query + } + }) + ) + .setLabel(' Not this? Search!') + .setStyle(ButtonStyle.Primary) + ); + } + + if(!row) + await sendHybridInteractionMessageResponse(data, { + embeds: [await EMBEDS.ADDED_QUEUE(data, locale, result[0])] + }); + else + await sendHybridInteractionMessageResponse(data, { + embeds: [await EMBEDS.ADDED_QUEUE(data, locale, result[0])], + components: [row] + }); + } + } + + if(!found) + await sendHybridInteractionMessageResponse(data, { embeds:[EMBEDS.NOT_DETECTED(data, locale)] }); + + return; + } +} \ No newline at end of file diff --git a/src/providers/Discord.ts b/src/providers/Discord.ts index 24ad2d6..6e4b556 100644 --- a/src/providers/Discord.ts +++ b/src/providers/Discord.ts @@ -17,6 +17,7 @@ import Discord_Stats from '../discord/Stats'; import Discord_Support from '../discord/Support'; import Discord_MusicPlayer_Play from '../discord/MusicPlayer/Play'; +import Discord_MusicPlayer_PlayMy from '../discord/MusicPlayer/PlayMy'; import Discord_MusicPlayer_Skip from '../discord/MusicPlayer/Skip'; import Discord_MusicPlayer_Join from '../discord/MusicPlayer/Join'; import Discord_MusicPlayer_Leave from '../discord/MusicPlayer/Leave'; @@ -68,6 +69,7 @@ class Discord { new Discord_Support(), new Discord_MusicPlayer_Play(), + new Discord_MusicPlayer_PlayMy(), new Discord_MusicPlayer_NowPlaying(), new Discord_MusicPlayer_Skip(), new Discord_MusicPlayer_Join(), From 58e8e53a9b40ed0aaaa96821f3a5ae68aaa4cbc6 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 14:58:27 +0700 Subject: [PATCH 26/63] Removed unused imports --- src/discord/InteractionManager.ts | 2 +- src/discord/Invite.ts | 2 +- src/discord/MembershipScreening.ts | 3 --- src/discord/MusicPlayer/Join.ts | 5 ----- src/discord/MusicPlayer/Pause.ts | 1 - src/discord/MusicPlayer/Queue.ts | 2 +- src/discord/MusicPlayer/Resume.ts | 1 - src/discord/MusicPlayer/Search.ts | 4 ++-- src/discord/MusicPlayer/Skip.ts | 4 ++-- src/discord/Ping.ts | 2 +- src/discord/Say.ts | 2 +- src/discord/Settings/Language.ts | 3 +-- src/discord/Settings/Prefix.ts | 2 +- src/discord/Settings/ServiceAnnouncement.ts | 3 +-- src/discord/Settings/index.ts | 1 - src/utils/DiscordMessage.ts | 1 - 16 files changed, 12 insertions(+), 26 deletions(-) diff --git a/src/discord/InteractionManager.ts b/src/discord/InteractionManager.ts index ac051b5..95be3ce 100644 --- a/src/discord/InteractionManager.ts +++ b/src/discord/InteractionManager.ts @@ -1,4 +1,4 @@ -import { Message, Interaction, CommandInteraction, BaseInteraction } from 'discord.js'; +import { Message, CommandInteraction, BaseInteraction } from 'discord.js'; import Users from '../services/Users'; diff --git a/src/discord/Invite.ts b/src/discord/Invite.ts index 111edbe..c6c62bf 100644 --- a/src/discord/Invite.ts +++ b/src/discord/Invite.ts @@ -1,4 +1,4 @@ -import { Message, CommandInteraction, Interaction } from 'discord.js'; +import { Message, CommandInteraction } from 'discord.js'; import { I18n } from 'i18n'; import Environment from '../providers/Environment'; diff --git a/src/discord/MembershipScreening.ts b/src/discord/MembershipScreening.ts index 7179b5e..a591a7d 100644 --- a/src/discord/MembershipScreening.ts +++ b/src/discord/MembershipScreening.ts @@ -14,9 +14,6 @@ import { EmbedBuilder, ButtonStyle, ActionRowBuilder, - ActionRowData, - ActionRowComponent, - MessageActionRowComponentBuilder } from 'discord.js'; import DiscordProvider from '../providers/Discord'; diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index b315767..ace9409 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -1,16 +1,11 @@ import { Message, CommandInteraction, - Interaction, VoiceChannel, - Permissions, - GuildMember, DMChannel, StageChannel, ActionRowBuilder, ButtonBuilder, - TextChannel, - VoiceBasedChannel, PermissionsBitField, ButtonStyle, BaseGuildTextChannel, diff --git a/src/discord/MusicPlayer/Pause.ts b/src/discord/MusicPlayer/Pause.ts index 8528929..223c70d 100644 --- a/src/discord/MusicPlayer/Pause.ts +++ b/src/discord/MusicPlayer/Pause.ts @@ -1,7 +1,6 @@ import { Message, CommandInteraction, Interaction } from "discord.js"; import { I18n } from "i18n"; -import DiscordProvider from "../../providers/Discord"; import DiscordMusicPlayer from "../../providers/DiscordMusicPlayer"; import Locale from "../../services/Locale"; diff --git a/src/discord/MusicPlayer/Queue.ts b/src/discord/MusicPlayer/Queue.ts index 9f68fc5..4f084d9 100644 --- a/src/discord/MusicPlayer/Queue.ts +++ b/src/discord/MusicPlayer/Queue.ts @@ -1,4 +1,4 @@ -import { Message, CommandInteraction, Interaction, TextChannel } from 'discord.js'; +import { Message, CommandInteraction } from 'discord.js'; import { I18n } from 'i18n'; import DiscordMusicPlayer, { diff --git a/src/discord/MusicPlayer/Resume.ts b/src/discord/MusicPlayer/Resume.ts index 7b7dd37..e3c6902 100644 --- a/src/discord/MusicPlayer/Resume.ts +++ b/src/discord/MusicPlayer/Resume.ts @@ -1,7 +1,6 @@ import { Message, CommandInteraction, Interaction } from "discord.js"; import { I18n } from "i18n"; -import DiscordProvider from "../../providers/Discord"; import DiscordMusicPlayer from "../../providers/DiscordMusicPlayer"; import DiscordModule, { HybridInteractionMessage } from "../../utils/DiscordModule"; diff --git a/src/discord/MusicPlayer/Search.ts b/src/discord/MusicPlayer/Search.ts index a8f018f..9b9ada0 100644 --- a/src/discord/MusicPlayer/Search.ts +++ b/src/discord/MusicPlayer/Search.ts @@ -1,4 +1,4 @@ -import { Message, CommandInteraction, BaseInteraction, ActionRowBuilder, ButtonInteraction, SelectMenuBuilder, SelectMenuComponentOptionData } from "discord.js"; +import { Message, CommandInteraction, ActionRowBuilder, ButtonInteraction, SelectMenuBuilder, SelectMenuComponentOptionData } from "discord.js"; import { I18n } from "i18n"; import { joinVoiceChannelProcedure } from "./Join"; @@ -7,7 +7,7 @@ import DiscordMusicPlayer, { TrackUtils, ValidTracks } from "../../providers/Dis import Locale from "../../services/Locale"; import DiscordModule, { HybridInteractionMessage } from "../../utils/DiscordModule"; -import { makeErrorEmbed, makeSuccessEmbed, sendHybridInteractionMessageResponse, makeInfoEmbed } from "../../utils/DiscordMessage"; +import { makeErrorEmbed, sendHybridInteractionMessageResponse, makeInfoEmbed } from "../../utils/DiscordMessage"; const EMBEDS = { SEARCH_INFO: (data: HybridInteractionMessage, locale: I18n) => { diff --git a/src/discord/MusicPlayer/Skip.ts b/src/discord/MusicPlayer/Skip.ts index 4e30a10..a50e870 100644 --- a/src/discord/MusicPlayer/Skip.ts +++ b/src/discord/MusicPlayer/Skip.ts @@ -1,8 +1,8 @@ import DiscordModule, { HybridInteractionMessage } from "../../utils/DiscordModule"; -import { Message, CommandInteraction, Interaction } from "discord.js"; +import { Message, CommandInteraction } from "discord.js"; import { makeSuccessEmbed, makeErrorEmbed, sendHybridInteractionMessageResponse } from "../../utils/DiscordMessage"; -import DiscordProvider from "../../providers/Discord"; + import DiscordMusicPlayer from "../../providers/DiscordMusicPlayer"; import { I18n } from "i18n"; import Locale from "../../services/Locale"; diff --git a/src/discord/Ping.ts b/src/discord/Ping.ts index eff4d65..a4312c5 100644 --- a/src/discord/Ping.ts +++ b/src/discord/Ping.ts @@ -1,4 +1,4 @@ -import { CommandInteraction, Message, Interaction } from 'discord.js'; +import { CommandInteraction, Message } from 'discord.js'; import os from 'os'; import NodePing from 'ping'; import { Promise } from 'bluebird'; diff --git a/src/discord/Say.ts b/src/discord/Say.ts index 9203a48..0bac9b7 100644 --- a/src/discord/Say.ts +++ b/src/discord/Say.ts @@ -1,4 +1,4 @@ -import { Message, Permissions, Interaction, CommandInteraction, PermissionsBitField } from 'discord.js'; +import { Message, CommandInteraction, PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; import DiscordModule, { HybridInteractionMessage } from '../utils/DiscordModule'; diff --git a/src/discord/Settings/Language.ts b/src/discord/Settings/Language.ts index 43345f2..a712c8b 100644 --- a/src/discord/Settings/Language.ts +++ b/src/discord/Settings/Language.ts @@ -1,7 +1,6 @@ -import { Permissions, Guild, PermissionFlagsBits, PermissionsBitField } from 'discord.js'; +import { Guild, PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; -import DiscordProvider from '../../providers/Discord'; import Prisma from '../../providers/Prisma'; import Cache from '../../providers/Cache'; diff --git a/src/discord/Settings/Prefix.ts b/src/discord/Settings/Prefix.ts index 8462985..6b8ce60 100644 --- a/src/discord/Settings/Prefix.ts +++ b/src/discord/Settings/Prefix.ts @@ -1,4 +1,4 @@ -import { Permissions, Guild, PermissionFlagsBits, PermissionsBitField } from 'discord.js'; +import { Guild, PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; import DiscordProvider from '../../providers/Discord'; diff --git a/src/discord/Settings/ServiceAnnouncement.ts b/src/discord/Settings/ServiceAnnouncement.ts index 3f84273..f25181b 100644 --- a/src/discord/Settings/ServiceAnnouncement.ts +++ b/src/discord/Settings/ServiceAnnouncement.ts @@ -1,7 +1,6 @@ -import { Permissions, Guild, GuildChannel, ThreadChannel, Message, PermissionsBitField, PermissionFlags, PermissionFlagsBits, PermissionResolvable } from 'discord.js'; +import { Guild, GuildChannel, ThreadChannel, Message, PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; -import DiscordProvider from '../../providers/Discord'; import Prisma from '../../providers/Prisma'; import Cache from '../../providers/Cache'; diff --git a/src/discord/Settings/index.ts b/src/discord/Settings/index.ts index af4988f..3250071 100644 --- a/src/discord/Settings/index.ts +++ b/src/discord/Settings/index.ts @@ -14,7 +14,6 @@ import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModu import { makeInfoEmbed, makeErrorEmbed, - makeSuccessEmbed, makeProcessingEmbed, sendHybridInteractionMessageResponse } from '../../utils/DiscordMessage'; diff --git a/src/utils/DiscordMessage.ts b/src/utils/DiscordMessage.ts index c469628..981ca10 100644 --- a/src/utils/DiscordMessage.ts +++ b/src/utils/DiscordMessage.ts @@ -10,7 +10,6 @@ import { BaseGuildTextChannel, Message, ColorResolvable, - Interaction, InteractionReplyOptions, BaseInteraction, BaseGuildVoiceChannel, From 8a34621964c98cae08d0c108e85642a55cb8a18a Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 20:00:03 +0700 Subject: [PATCH 27/63] Moved member permission check to utils --- src/discord/Settings/Language.ts | 25 +++++++++++--------- src/discord/Settings/Prefix.ts | 9 +++---- src/discord/Settings/ServiceAnnouncement.ts | 17 ++++---------- src/utils/DiscordPermission.ts | 26 +++++++++++++++++++++ 4 files changed, 48 insertions(+), 29 deletions(-) create mode 100644 src/utils/DiscordPermission.ts diff --git a/src/discord/Settings/Language.ts b/src/discord/Settings/Language.ts index a712c8b..4c51cda 100644 --- a/src/discord/Settings/Language.ts +++ b/src/discord/Settings/Language.ts @@ -14,12 +14,15 @@ import { import { COMMON_EMBEDS } from '.'; import Locale from '../../providers/Locale'; +import { checkMemberPermissions } from '../../utils/DiscordPermission'; const EMBEDS = { LANGUAGE_INFO: (data: HybridInteractionMessage, locale: I18n, currentLocale: string) => { return makeInfoEmbed({ - title: locale.__('settings_language.info', { LANGUAGE: currentLocale}), - description: locale.__('settings_language.info_description', { LANGUAGES: Locale.getLocaleProvider('en').getLocales().join(', ') }), + title: locale.__('settings_language.info', { LANGUAGE: currentLocale }), + description: locale.__('settings_language.info_description', { + LANGUAGES: Locale.getLocaleProvider('en').getLocales().join(', ') + }), user: data.getUser() }); }, @@ -33,7 +36,10 @@ const EMBEDS = { LANGUAGE_UPDATED: (data: HybridInteractionMessage, locale: I18n, newLanguage: string) => { return makeSuccessEmbed({ title: locale.__({ phrase: 'settings_language.language_updated', locale: newLanguage }), - description: locale.__({ phrase: 'settings_language.language_updated_description', locale: newLanguage }, { LANGUAGE: newLanguage }), + description: locale.__( + { phrase: 'settings_language.language_updated_description', locale: newLanguage }, + { LANGUAGE: newLanguage } + ), user: data.getUser() }); } @@ -44,15 +50,11 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l if (!member) return; const GuildCache = await Cache.getCachedGuild(guild.id); - if (!GuildCache) return; + if (!GuildCache) return; const language = GuildCache.locale; - const requiredPermissions = [PermissionsBitField.Flags.ManageGuild]; - - if (!member.permissions.has(requiredPermissions)) - return await sendHybridInteractionMessageResponse(data, { - embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale, requiredPermissions)] - }); + if (!(await checkMemberPermissions({ member, data, locale, permissions: [PermissionsBitField.Flags.ManageGuild] }))) + return; let newLanguage: string | null | undefined; if (data.isMessage()) { @@ -66,7 +68,8 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l __name.shift(); _name = __name.join(' '); newLanguage = _name; - } else if (data.isApplicationCommand()) newLanguage = data.getSlashCommand().options.get('language', true).value?.toString(); + } else if (data.isApplicationCommand()) + newLanguage = data.getSlashCommand().options.get('language', true).value?.toString(); if (!newLanguage) return await sendHybridInteractionMessageResponse(data, { diff --git a/src/discord/Settings/Prefix.ts b/src/discord/Settings/Prefix.ts index 6b8ce60..e4c5a37 100644 --- a/src/discord/Settings/Prefix.ts +++ b/src/discord/Settings/Prefix.ts @@ -14,6 +14,7 @@ import { } from '../../utils/DiscordMessage'; import { COMMON_EMBEDS } from '.'; +import { checkMemberPermissions } from '../../utils/DiscordPermission'; const EMBEDS = { PREFIX_INFO: (data: HybridInteractionMessage, locale: I18n, currentPrefix: string) => { @@ -54,12 +55,8 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l if (!GuildCache) return; const prefix = GuildCache.prefix; - const requiredPermissions = [PermissionsBitField.Flags.ManageGuild]; - - if (!member.permissions.has(requiredPermissions)) - return await sendHybridInteractionMessageResponse(data, { - embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale, requiredPermissions)] - }); + if (!(await checkMemberPermissions({ member, data, locale, permissions: [PermissionsBitField.Flags.ManageGuild] }))) + return; let newPrefix: string | null | undefined; if (data.isMessage()) { diff --git a/src/discord/Settings/ServiceAnnouncement.ts b/src/discord/Settings/ServiceAnnouncement.ts index f25181b..f524a5c 100644 --- a/src/discord/Settings/ServiceAnnouncement.ts +++ b/src/discord/Settings/ServiceAnnouncement.ts @@ -13,6 +13,7 @@ import { } from '../../utils/DiscordMessage'; import { COMMON_EMBEDS } from '.'; +import { checkMemberPermissions } from '../../utils/DiscordPermission'; const EMBEDS = { SERVICE_ANNOUNCEMENT_INVALID_STATUS: (data: HybridInteractionMessage, locale: I18n) => { @@ -103,12 +104,8 @@ export const setEnableServiceAnnouncement = async ( let member = data.getMember(); if (!member) return; - const requiredPermissions = [PermissionsBitField.Flags.Administrator]; - - if (!member.permissions.has(requiredPermissions)) - return await sendHybridInteractionMessageResponse(data, { - embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale, requiredPermissions)] - }); + if (!(await checkMemberPermissions({ member, data, locale, permissions: [PermissionsBitField.Flags.Administrator] }))) + return; let GuildCache = await Cache.getCachedGuild(guild.id); if(!GuildCache) return; @@ -185,12 +182,8 @@ export const setServiceAnnouncementChannel = async ( let member = data.getMember(); if (!member) return; - const requiredPermissions = [PermissionsBitField.Flags.Administrator]; - - if (!member.permissions.has(requiredPermissions)) - return await sendHybridInteractionMessageResponse(data, { - embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale, requiredPermissions)] - }); + if (!(await checkMemberPermissions({ member, data, locale, permissions: [PermissionsBitField.Flags.Administrator] }))) + return; let channel; if (data.isMessage()) { diff --git a/src/utils/DiscordPermission.ts b/src/utils/DiscordPermission.ts new file mode 100644 index 0000000..b067082 --- /dev/null +++ b/src/utils/DiscordPermission.ts @@ -0,0 +1,26 @@ +import { GuildMember } from 'discord.js'; +import { I18n } from 'i18n'; +import { COMMON_EMBEDS } from '../discord/Settings'; +import { sendHybridInteractionMessageResponse } from './DiscordMessage'; +import { HybridInteractionMessage } from './DiscordModule'; + +export async function checkMemberPermissions({ + member, + permissions, + data, + locale +}: { + member: GuildMember; + permissions: bigint[]; + data?: HybridInteractionMessage; + locale?: I18n; +}): Promise { + const hasPermissions = member.permissions.has(permissions); + + if (!hasPermissions && data && locale) + await sendHybridInteractionMessageResponse(data, { + embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale, permissions)] + }); + + return hasPermissions; +} From 2090162d7834825e3893d6b06f2785f9650bc46c Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 20:34:20 +0700 Subject: [PATCH 28/63] Updated locale for permissions check --- locales/en.json | 6 ++++-- locales/jp.json | 6 ++++-- locales/th.json | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/locales/en.json b/locales/en.json index c2c24df..2bb2361 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1,8 +1,10 @@ { "common": { "available_args": "Available arguments", - "no_permissions": "Access denied (O_O;)", - "no_permissions_description": "You need ``{{PERMISSIONS}}`` permission on this guild", + "member_no_permissions": "Access denied (O_O;)", + "member_no_permissions_description": "You need ``{{PERMISSIONS}}`` permissions on this guild", + "bot_no_permissions": "I don't have permission (O_O;)", + "bot_no_permissions_description": "I need ``{{PERMISSIONS}}`` permissions", "processing": "Please wait a moment~", "processing_description": "Getting it done right now! (งᓀ‸ᓂ)ง" }, diff --git a/locales/jp.json b/locales/jp.json index 9e30df3..4ad38dd 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -1,8 +1,10 @@ { "common": { "available_args": "Available arguments", - "no_permissions": "許可していない (O_O;)", - "no_permissions_description": "このギルドでは ``{{PERMISSIONS}}`` の許可が必要です!", + "member_no_permissions": "許可していない (O_O;)", + "member_no_permissions_description": "このギルドでは ``{{PERMISSIONS}}`` の許可が必要です!", + "bot_no_permissions": "許可がない (O_O;)", + "bot_no_permissions_description": "そのためには、あたしの``{{PERMISSIONS}}``の権限が必要です", "processing": "アクションの実行", "processing_description": "今これを成し遂げています (งᓀ‸ᓂ)ง" }, diff --git a/locales/th.json b/locales/th.json index 9d4da6e..be8e3cf 100644 --- a/locales/th.json +++ b/locales/th.json @@ -1,8 +1,10 @@ { "common": { "available_args": "อาร์กิวเมนต์ ตัวเลือกที่ใช้ได้", - "no_permissions": "คุณไม่มีสิทธิ์เข้าถึง (O_O;)", - "no_permissions_description": "คุณต้องมีสิทธิ์เข้าถึง ``{{PERMISSIONS}}`` ในกิลด์นี้!", + "member_no_permissions": "คุณไม่มีสิทธิ์เข้าถึง (O_O;)", + "member_no_permissions_description": "คุณต้องมีสิทธิ์เข้าถึง ``{{PERMISSIONS}}`` ในกิลด์นี้!", + "bot_no_permissions": "ฉันไม่มีสิทธิ์เข้าถึง (O_O;)", + "bot_no_permissions_description": "ฉันต้องการสิทธิ์เข้าถึง ``{{PERMISSIONS}}``", "processing": "รอแปปนึงน้า", "processing_description": "ฉันกำลังดำเนินการให้อยู่ (งᓀ‸ᓂ)ง" }, From 95534294d1f99f18168a8c03928b3eebcae1e0cf Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 20:34:55 +0700 Subject: [PATCH 29/63] Permission check utils --- src/utils/DiscordPermission.ts | 54 ++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/utils/DiscordPermission.ts b/src/utils/DiscordPermission.ts index b067082..29ec053 100644 --- a/src/utils/DiscordPermission.ts +++ b/src/utils/DiscordPermission.ts @@ -1,4 +1,4 @@ -import { GuildMember } from 'discord.js'; +import { BaseGuildTextChannel, BaseGuildVoiceChannel, Guild, GuildChannelResolvable, GuildMember, VoiceBasedChannel } from 'discord.js'; import { I18n } from 'i18n'; import { COMMON_EMBEDS } from '../discord/Settings'; import { sendHybridInteractionMessageResponse } from './DiscordMessage'; @@ -19,8 +19,58 @@ export async function checkMemberPermissions({ if (!hasPermissions && data && locale) await sendHybridInteractionMessageResponse(data, { - embeds: [COMMON_EMBEDS.NO_PERMISSION(data, locale, permissions)] + embeds: [COMMON_EMBEDS.MEMBER_NO_PERMISSION(data, locale, permissions)] }); return hasPermissions; } + +export async function checkBotPermissions({ + guild, + permissions, + data, + locale +}: { + guild: Guild; + permissions: bigint[]; + data?: HybridInteractionMessage; + locale?: I18n; +}): Promise { + const member = guild.members.me; + if(!member) return false; + + const hasPermissions = member.permissions.has(permissions); + + if (!hasPermissions && data && locale) + await sendHybridInteractionMessageResponse(data, { + embeds: [COMMON_EMBEDS.BOT_NO_PERMISSION(data, locale, permissions)] + }); + + return hasPermissions; +} + +export async function checkBotPermissionsInChannel({ + guild, + channel, + permissions, + data, + locale +}: { + guild: Guild; + channel: GuildChannelResolvable; + permissions: bigint[]; + data?: HybridInteractionMessage; + locale?: I18n; +}): Promise { + const member = guild.members.me; + if(!member) return false; + + const hasPermissions = member.permissionsIn(channel).has(permissions); + + if (!hasPermissions && data && locale) + await sendHybridInteractionMessageResponse(data, { + embeds: [COMMON_EMBEDS.BOT_NO_PERMISSION(data, locale, permissions)] + }); + + return hasPermissions; +} \ No newline at end of file From 5c3cf99184ffcd866758cc57902ff3021554d1c2 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 20:35:22 +0700 Subject: [PATCH 30/63] Update permission checks embed --- src/discord/Settings/index.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/discord/Settings/index.ts b/src/discord/Settings/index.ts index 3250071..d99847f 100644 --- a/src/discord/Settings/index.ts +++ b/src/discord/Settings/index.ts @@ -23,15 +23,27 @@ import * as LanguageModule from './Language'; import * as ServiceAnnouncementModule from './ServiceAnnouncement'; export const COMMON_EMBEDS = { - NO_PERMISSION: (data: HybridInteractionMessage, locale: I18n, permissions: PermissionResolvable[]) => { + MEMBER_NO_PERMISSION: (data: HybridInteractionMessage, locale: I18n, permissions: PermissionResolvable[]) => { let allPermissions = []; for(const value of permissions) { allPermissions.push(new PermissionsBitField(value).toArray()); } return makeErrorEmbed({ - title: locale.__('common.no_permissions'), - description: locale.__('common.no_permissions_description', { PERMISSIONS: allPermissions.join(', ')}), + title: locale.__('common.member_no_permissions'), + description: locale.__('common.member_no_permissions_description', { PERMISSIONS: allPermissions.join(', ')}), + user: data.getUser() + }); + }, + BOT_NO_PERMISSION: (data: HybridInteractionMessage, locale: I18n, permissions: PermissionResolvable[]) => { + + let allPermissions = []; + for(const value of permissions) { + allPermissions.push(new PermissionsBitField(value).toArray()); + } + return makeErrorEmbed({ + title: locale.__('common.bot_no_permissions'), + description: locale.__('common.bot_no_permissions_description', { PERMISSIONS: allPermissions.join(', ')}), user: data.getUser() }); }, From d349103b1fe6d29335fa37685d8827f904021780 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 20:38:07 +0700 Subject: [PATCH 31/63] Join voice channel permissions check --- src/discord/MusicPlayer/Join.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index ace9409..f5f6b8d 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -34,6 +34,7 @@ import DiscordMusicPlayer, { import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule'; import Locale from '../../services/Locale'; import { SpotifyTrack, YouTubeVideo } from 'play-dl'; +import { checkBotPermissions, checkBotPermissionsInChannel } from '../../utils/DiscordPermission'; const EMBEDS = { VOICECHANNEL_JOINED: (data: HybridInteractionMessage, locale: I18n) => { @@ -140,6 +141,8 @@ export async function joinVoiceChannelProcedure( if (!bot) return; const locale = await Locale.getGuildLocale(guild.id); + + if(!await checkBotPermissionsInChannel({ guild, data, locale, channel: memberVoiceChannel, permissions: [PermissionsBitField.Flags.ViewChannel, PermissionsBitField.Flags.Connect]})) return; // If already in VoiceChannel if (bot.voice.channelId) { From 00b44a0600d8160a2fc1a046ce9cd711c8af070b Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 20:40:16 +0700 Subject: [PATCH 32/63] Renamed functions for permission checks --- src/discord/MusicPlayer/Join.ts | 2 +- src/discord/Settings/Language.ts | 4 ++-- src/discord/Settings/Prefix.ts | 4 ++-- src/discord/Settings/ServiceAnnouncement.ts | 6 +++--- src/utils/DiscordPermission.ts | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index f5f6b8d..7e288e9 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -34,7 +34,7 @@ import DiscordMusicPlayer, { import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule'; import Locale from '../../services/Locale'; import { SpotifyTrack, YouTubeVideo } from 'play-dl'; -import { checkBotPermissions, checkBotPermissionsInChannel } from '../../utils/DiscordPermission'; +import { checkBotPermissionsInChannel } from '../../utils/DiscordPermission'; const EMBEDS = { VOICECHANNEL_JOINED: (data: HybridInteractionMessage, locale: I18n) => { diff --git a/src/discord/Settings/Language.ts b/src/discord/Settings/Language.ts index 4c51cda..f1faa1b 100644 --- a/src/discord/Settings/Language.ts +++ b/src/discord/Settings/Language.ts @@ -14,7 +14,7 @@ import { import { COMMON_EMBEDS } from '.'; import Locale from '../../providers/Locale'; -import { checkMemberPermissions } from '../../utils/DiscordPermission'; +import { checkMemberPermissionsInGuild } from '../../utils/DiscordPermission'; const EMBEDS = { LANGUAGE_INFO: (data: HybridInteractionMessage, locale: I18n, currentLocale: string) => { @@ -53,7 +53,7 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l if (!GuildCache) return; const language = GuildCache.locale; - if (!(await checkMemberPermissions({ member, data, locale, permissions: [PermissionsBitField.Flags.ManageGuild] }))) + if (!(await checkMemberPermissionsInGuild({ member, data, locale, permissions: [PermissionsBitField.Flags.ManageGuild] }))) return; let newLanguage: string | null | undefined; diff --git a/src/discord/Settings/Prefix.ts b/src/discord/Settings/Prefix.ts index e4c5a37..c4162a5 100644 --- a/src/discord/Settings/Prefix.ts +++ b/src/discord/Settings/Prefix.ts @@ -14,7 +14,7 @@ import { } from '../../utils/DiscordMessage'; import { COMMON_EMBEDS } from '.'; -import { checkMemberPermissions } from '../../utils/DiscordPermission'; +import { checkMemberPermissionsInGuild } from '../../utils/DiscordPermission'; const EMBEDS = { PREFIX_INFO: (data: HybridInteractionMessage, locale: I18n, currentPrefix: string) => { @@ -55,7 +55,7 @@ export default async (data: HybridInteractionMessage, args: any, guild: Guild, l if (!GuildCache) return; const prefix = GuildCache.prefix; - if (!(await checkMemberPermissions({ member, data, locale, permissions: [PermissionsBitField.Flags.ManageGuild] }))) + if (!(await checkMemberPermissionsInGuild({ member, data, locale, permissions: [PermissionsBitField.Flags.ManageGuild] }))) return; let newPrefix: string | null | undefined; diff --git a/src/discord/Settings/ServiceAnnouncement.ts b/src/discord/Settings/ServiceAnnouncement.ts index f524a5c..c00ce0e 100644 --- a/src/discord/Settings/ServiceAnnouncement.ts +++ b/src/discord/Settings/ServiceAnnouncement.ts @@ -13,7 +13,7 @@ import { } from '../../utils/DiscordMessage'; import { COMMON_EMBEDS } from '.'; -import { checkMemberPermissions } from '../../utils/DiscordPermission'; +import { checkMemberPermissionsInGuild } from '../../utils/DiscordPermission'; const EMBEDS = { SERVICE_ANNOUNCEMENT_INVALID_STATUS: (data: HybridInteractionMessage, locale: I18n) => { @@ -104,7 +104,7 @@ export const setEnableServiceAnnouncement = async ( let member = data.getMember(); if (!member) return; - if (!(await checkMemberPermissions({ member, data, locale, permissions: [PermissionsBitField.Flags.Administrator] }))) + if (!(await checkMemberPermissionsInGuild({ member, data, locale, permissions: [PermissionsBitField.Flags.Administrator] }))) return; let GuildCache = await Cache.getCachedGuild(guild.id); @@ -182,7 +182,7 @@ export const setServiceAnnouncementChannel = async ( let member = data.getMember(); if (!member) return; - if (!(await checkMemberPermissions({ member, data, locale, permissions: [PermissionsBitField.Flags.Administrator] }))) + if (!(await checkMemberPermissionsInGuild({ member, data, locale, permissions: [PermissionsBitField.Flags.Administrator] }))) return; let channel; diff --git a/src/utils/DiscordPermission.ts b/src/utils/DiscordPermission.ts index 29ec053..d9dcf28 100644 --- a/src/utils/DiscordPermission.ts +++ b/src/utils/DiscordPermission.ts @@ -4,7 +4,7 @@ import { COMMON_EMBEDS } from '../discord/Settings'; import { sendHybridInteractionMessageResponse } from './DiscordMessage'; import { HybridInteractionMessage } from './DiscordModule'; -export async function checkMemberPermissions({ +export async function checkMemberPermissionsInGuild({ member, permissions, data, @@ -25,7 +25,7 @@ export async function checkMemberPermissions({ return hasPermissions; } -export async function checkBotPermissions({ +export async function checkBotPermissionsInGuild({ guild, permissions, data, From e3c8a58f780bb5d61649c52d7b8a3d253b5b683f Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 20:40:50 +0700 Subject: [PATCH 33/63] Removed unused imports --- src/utils/DiscordPermission.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/DiscordPermission.ts b/src/utils/DiscordPermission.ts index d9dcf28..a301631 100644 --- a/src/utils/DiscordPermission.ts +++ b/src/utils/DiscordPermission.ts @@ -1,4 +1,4 @@ -import { BaseGuildTextChannel, BaseGuildVoiceChannel, Guild, GuildChannelResolvable, GuildMember, VoiceBasedChannel } from 'discord.js'; +import { Guild, GuildChannelResolvable, GuildMember } from 'discord.js'; import { I18n } from 'i18n'; import { COMMON_EMBEDS } from '../discord/Settings'; import { sendHybridInteractionMessageResponse } from './DiscordMessage'; From 4a84a1befe8c403483705f04908fc58ac8300950 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 20:45:44 +0700 Subject: [PATCH 34/63] Add member permissions check in channel --- src/utils/DiscordPermission.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/utils/DiscordPermission.ts b/src/utils/DiscordPermission.ts index a301631..f611caf 100644 --- a/src/utils/DiscordPermission.ts +++ b/src/utils/DiscordPermission.ts @@ -25,6 +25,29 @@ export async function checkMemberPermissionsInGuild({ return hasPermissions; } +export async function checkMemberPermissionsInChannel({ + member, + channel, + permissions, + data, + locale +}: { + member: GuildMember; + channel: GuildChannelResolvable; + permissions: bigint[]; + data?: HybridInteractionMessage; + locale?: I18n; +}): Promise { + const hasPermissions = member.permissionsIn(channel).has(permissions); + + if (!hasPermissions && data && locale) + await sendHybridInteractionMessageResponse(data, { + embeds: [COMMON_EMBEDS.MEMBER_NO_PERMISSION(data, locale, permissions)] + }); + + return hasPermissions; +} + export async function checkBotPermissionsInGuild({ guild, permissions, From 55aa91eb9d3a8e7df4a340330562fa3a5db36030 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 21:21:11 +0700 Subject: [PATCH 35/63] Bump discord.js --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f4165b0..f67c8d4 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "country-code-emoji": "^2.3.0", "country-code-lookup": "^0.0.20", "discord-api-types": "^0.35.0", - "discord.js": "14.0.0-dev.1656634282-819a1fd", + "discord.js": "14.0.0-dev.1657022642-fd1c240", "dotenv": "^16.0.1", "i18n": "^0.15.0", "libsodium-wrappers": "^0.7.10", diff --git a/yarn.lock b/yarn.lock index 1e00f27..c56188a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -608,10 +608,10 @@ discord-api-types@^0.35.0: resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.35.0.tgz#85c6ea95f27580ad13b7a08444b16cb31d41e5e2" integrity sha512-aaIbVgPk7OA3y/HdG00tRM2nB8B3sSPH6KXgamBLRrcAJEQ8XZJNNKeRr0WVzw/lprdpKHKuTNX1DNrYnD5cOw== -discord.js@14.0.0-dev.1656634282-819a1fd: - version "14.0.0-dev.1656634282-819a1fd" - resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.0.0-dev.1656634282-819a1fd.tgz#3e8630c34df05913fb24ee5c63b8139b7cc16e6e" - integrity sha512-FaLWAWMbGxId4c7HmdYtFkvFjBVmNsAigk3XZpJ+hqgu7rAijD6w6fDAZ0Obk2MspxVa8iKWcOmdt1S/N+emgQ== +discord.js@14.0.0-dev.1657022642-fd1c240: + version "14.0.0-dev.1657022642-fd1c240" + resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.0.0-dev.1657022642-fd1c240.tgz#487bcb0b6608b67dcdd5caf54e2ff72b9e73aabb" + integrity sha512-sIJXapK7099aIRDll5PXLlBatXpudMfomt/v0FOIEP63MzVLI+TMRpd9hHj62rguhmK21vv/9zbHrpnDu81YpQ== dependencies: "@discordjs/builders" "^0.16.0-dev" "@discordjs/collection" "^0.8.0-dev" From c7884a52e3d7239b293b3c9e94fca0fadc02162c Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 21:45:55 +0700 Subject: [PATCH 36/63] Removed extra characters --- src/discord/UserInfo.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/discord/UserInfo.ts b/src/discord/UserInfo.ts index 844dd9e..dbcb9e0 100644 --- a/src/discord/UserInfo.ts +++ b/src/discord/UserInfo.ts @@ -94,10 +94,10 @@ const EMBEDS = { let title = ''; switch (activity.type) { case ActivityType.Playing: - title = `'🕹 ${locale.__('userinfo.playing_x', { NAME: activity.name })}`; + title = `🕹 ${locale.__('userinfo.playing_x', { NAME: activity.name })}`; break; case ActivityType.Streaming: - title = `'🔴 ${locale.__('userinfo.streaming_x', { NAME: activity.name })}`; + title = `🔴 ${locale.__('userinfo.streaming_x', { NAME: activity.name })}`; break; case ActivityType.Listening: title = `🎵 ${locale.__('userinfo.listening_x', { NAME: activity.name })}`; From 0d0ac1baf99e45e4d2164aea3d69e2b1796ac855 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 22:02:43 +0700 Subject: [PATCH 37/63] Updated .env example --- .env.example | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 877f3d9..da5dd08 100644 --- a/.env.example +++ b/.env.example @@ -10,4 +10,8 @@ PRIVATE_BOT=true SUPPORT_URL=https://example.com/support OSU_API_KEY=SuperSecretosu!Key -YOUTUBE_COOKIE_BASE64=SuperSecretCookie_EncodeItInBase64_AndThen_RemoveTheLastEqualToo \ No newline at end of file +YOUTUBE_COOKIE_BASE64=SuperSecretCookie_EncodeItInBase64_AndThen_RemoveTheLastEqualToo +SPOTIFY_CLIENT_ID=SpotfyClientID +SPOTIFY_CLIENT_SECRET=SpotfyClientSecret +SPOTIFY_REFRESH_TOKEN=SpotfyRefreshToken +SPOTIFY_CLIENT_MARKET=CountryCodeHere From 0c486a2e769df86241ee131a0950ad4a3077871e Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 22:07:47 +0700 Subject: [PATCH 38/63] Update README.md --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 71fe2de..b1c0d89 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,13 @@ Take a look inside [.env.example](https://github.com/YuzuZensai/Yumi/blob/main/. - ``DISCORD_TOKEN`` Your discord bot token - ``DEVELOPER_IDS`` List of Discord Snowflake User ID that can access developer only modules, separated by ``,`` - ``PRIVATE_BOT`` Should the bot invite be public? ``true`` or ``false`` -- ``SUPPORT_URL`` URL to your support server (If not set, support module will show not available message) +- ``SUPPORT_URL`` (Optional) URL to your support server (If not set, support module will show not available message) - ``OSU_API_KEY`` [osu! API v1 key](https://github.com/ppy/osu-api/wiki) -- ``YOUTUBE_COOKIE_BASE64`` YouTube cookies encoded in base64 [How to get cookies?](https://github.com/play-dl/play-dl/tree/main/instructions#youtube-cookies=)* +- ``YOUTUBE_COOKIE_BASE64`` YouTube cookies encoded in base64 [How to get cookies?](https://github.com/play-dl/play-dl/tree/main/instructions#youtube-cookies=) * +- ``SPOTIFY_CLIENT_ID`` Spotify client ID +- ``SPOTIFY_CLIENT_SECRET`` Spotify client secret +- ``SPOTIFY_REFRESH_TOKEN`` Spotify refresh token ** +- ``SPOTIFY_CLIENT_MARKET`` Spotify market country code \* Encode the cookies from the request headers base64 and put it in here instead of creating new file with ``play.authorization();`` code +\*\* Get refresh token from ``https://accounts.spotify.com/en/authorize?client_id=&response_type=code&redirect_uri=`` From 4bf324efed201502bd3fb55e691c644637ac5bdd Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 22:08:39 +0700 Subject: [PATCH 39/63] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b1c0d89..1be715e 100644 --- a/README.md +++ b/README.md @@ -48,4 +48,5 @@ Take a look inside [.env.example](https://github.com/YuzuZensai/Yumi/blob/main/. - ``SPOTIFY_CLIENT_MARKET`` Spotify market country code \* Encode the cookies from the request headers base64 and put it in here instead of creating new file with ``play.authorization();`` code + \*\* Get refresh token from ``https://accounts.spotify.com/en/authorize?client_id=&response_type=code&redirect_uri=`` From c914bd87c9dc3c527d8576d414a3b7aaf7a36b8a Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 22:10:39 +0700 Subject: [PATCH 40/63] Added PlayMy command to help --- src/discord/Help.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/discord/Help.ts b/src/discord/Help.ts index fb10f2e..05f3f8c 100644 --- a/src/discord/Help.ts +++ b/src/discord/Help.ts @@ -34,7 +34,7 @@ const EMBEDS = { }, { name: `🎵 ${locale.__('help.music')}`, - value: `play (p), search, skip, pause, resume, queue (q), nowplaying (np), repeat (loop), summon (join), disconnect (leave, dc)`, + value: `play (p), playmy, search, skip, pause, resume, queue (q), nowplaying (np), repeat (loop), summon (join), disconnect (leave, dc)`, inline: true }, { From 8d86380b8e55c2ef7ec9e92e50b0421a7499b7f4 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 22:10:54 +0700 Subject: [PATCH 41/63] Added PlayMy to slash command --- src/utils/DiscordInteraction.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/DiscordInteraction.ts b/src/utils/DiscordInteraction.ts index 14117eb..758b8a8 100644 --- a/src/utils/DiscordInteraction.ts +++ b/src/utils/DiscordInteraction.ts @@ -28,6 +28,7 @@ export const GLOBAL_COMMANDS: Object[] = [ .setName('search') .setDescription('Search for music') .addStringOption((option) => option.setName('query').setDescription('Search query').setRequired(true)), + new SlashCommandBuilder().setName('playmy').setDescription('Play the detected songs you are listening to'), new SlashCommandBuilder().setName('skip').setDescription('Skip the current song'), new SlashCommandBuilder().setName('pause').setDescription('Pause the current music'), new SlashCommandBuilder().setName('resume').setDescription('Resume paused music'), From c59281e951eac1dec62bc22ba49f4cf50bc19e3e Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 12 Jul 2022 12:27:52 +0700 Subject: [PATCH 42/63] Support YouTube Music links --- src/providers/DiscordMusicPlayer.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/providers/DiscordMusicPlayer.ts b/src/providers/DiscordMusicPlayer.ts index 6c937f7..1ce333d 100644 --- a/src/providers/DiscordMusicPlayer.ts +++ b/src/providers/DiscordMusicPlayer.ts @@ -554,7 +554,9 @@ class DiscordMusicPlayer { public parseYouTubeLink(query: string): YouTubeLink { if ( query.startsWith('https://www.youtube.com/watch?v=') || - query.startsWith('http://www.youtube.com/watch?v=') + query.startsWith('http://www.youtube.com/watch?v=') || + query.startsWith('https://music.youtube.com/watch?v=') || + query.startsWith('https://music.youtube.com/watch?v=') ) { let data = this.parseURLQuery(query); if (!data.v) throw new Error('YouTube link is invalid'); From c925a5187c1661f1769a5d8934c719bfe181a96e Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 12 Jul 2022 12:30:04 +0700 Subject: [PATCH 43/63] Added empty result error message --- src/discord/MusicPlayer/Play.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index 4fd4a88..cf966bc 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -420,7 +420,15 @@ export default class Play extends DiscordModule { } else { let result = await DiscordMusicPlayer.searchYouTubeByQuery(query); - if (!result) return; + if (!result) { + // TODO: Send not found embed + await sendHybridInteractionMessageResponse( + data, + { embeds: [EMBEDS.LOOKUP_ERROR(data, locale, new Error('Cannot find that song'))] }, + true + ); + return; + } instance.addTrackToQueue(result[0]); if (result.length > 1) { From d723128ce873c8089ab3302e3b020485848f751c Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 12 Jul 2022 12:40:06 +0700 Subject: [PATCH 44/63] Bump version --- src/providers/App.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/App.ts b/src/providers/App.ts index 98c3855..d16ad66 100644 --- a/src/providers/App.ts +++ b/src/providers/App.ts @@ -7,7 +7,7 @@ import osu from './osuAPI'; import Logger from '../libs/Logger'; import Locale from './Locale'; class App { - public readonly versionNumber = `0.10`; + public readonly versionNumber = `0.11`; public readonly version = `${this.versionNumber}${ Environment.get().NODE_ENV === 'development' ? ' / Development Build' : '' }`; From d637935856ba931c75e00333a6af902a319859c9 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 15 Jul 2022 14:57:40 +0700 Subject: [PATCH 45/63] Fixed Spotify crash --- src/discord/MusicPlayer/Play.ts | 7 ++++++- src/providers/DiscordMusicPlayer.ts | 22 ++++++++++++++-------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index cf966bc..3b41e59 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -386,7 +386,12 @@ export default class Play extends DiscordModule { let linkData = DiscordMusicPlayer.parseSpotifyLink(query); if (linkData.type === 'playlist' || linkData.type === 'album') { - let playlist = await DiscordMusicPlayer.getSpotifySongsInPlayList(query); + let playlist = await DiscordMusicPlayer.getSpotifySongsInPlayList(query).catch((err) => { + sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.LOOKUP_ERROR(data, locale, err)] }, true); + return null; + }); + + if(!playlist) return; const songs = await playlist.all_tracks(); for (const song of songs) { diff --git a/src/providers/DiscordMusicPlayer.ts b/src/providers/DiscordMusicPlayer.ts index 1ce333d..7fbfa08 100644 --- a/src/providers/DiscordMusicPlayer.ts +++ b/src/providers/DiscordMusicPlayer.ts @@ -25,6 +25,7 @@ import { EventEmitter } from 'stream'; import DiscordProvider from './Discord'; import Environment from './Environment'; +import Logger from '../libs/Logger'; export type ValidTracks = YouTubeVideo | SpotifyTrack; declare class YouTubeThumbnail { @@ -45,7 +46,8 @@ interface SpotifyThumbnail { url: string; } -if (Environment.get().YOUTUBE_COOKIE_BASE64) { +// TODO: Make proper check later +if (Environment.get().YOUTUBE_COOKIE_BASE64 && Environment.get().SPOTIFY_CLIENT_ID) { playdl.setToken({ youtube: { cookie: Buffer.from(Environment.get().YOUTUBE_COOKIE_BASE64, 'base64').toString() @@ -443,18 +445,16 @@ class DiscordMusicPlayer { } public async searchSpotifyBySpotifyLink(spotifyLink: SpotifyLink) { - if(playdl.is_expired()) - await playdl.refreshToken(); - - if(spotifyLink.type != 'track') return; - if(playdl.is_expired()) await playdl.refreshToken(); if(spotifyLink.type != 'track') return; // Fetch data from spotify - const searched: Spotify = await playdl.spotify("https://open.spotify.com/track/" + spotifyLink.id); + const searched: Spotify = await playdl.spotify("https://open.spotify.com/track/" + spotifyLink.id).catch((err) => { + Logger.error(err.message); + throw new Error('Error while searching on Spotify'); + }); if(!(searched instanceof SpotifyTrack)) return; if (!searched) return null; @@ -525,7 +525,13 @@ class DiscordMusicPlayer { } public async getSpotifySongsInPlayList(spotifyLink: string) { - const result = await playdl.spotify(spotifyLink); + if(playdl.is_expired()) + await playdl.refreshToken(); + + const result = await playdl.spotify(spotifyLink).catch((err) => { + Logger.error(err.message); + throw new Error('Error while searching on Spotify'); + }); if(!(result.type == 'playlist' || result.type == 'album')) throw new Error("Not a spotify playlist"); From b207ca5cb3bb77ba87f6d39308d5ed86b13d96a9 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 15 Jul 2022 15:08:03 +0700 Subject: [PATCH 46/63] Bump deps --- package.json | 16 ++--- yarn.lock | 189 +++++++++++++++++++++++++++++---------------------- 2 files changed, 117 insertions(+), 88 deletions(-) diff --git a/package.json b/package.json index f67c8d4..68b430a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@discordjs/opus": "^0.7.0", + "@discordjs/opus": "^0.8.0", "@discordjs/rest": "^0.5.0", "@discordjs/voice": "^0.10.0", "@types/color-thief-node": "^1.0.1", @@ -10,8 +10,8 @@ "color-thief-node": "^1.0.4", "country-code-emoji": "^2.3.0", "country-code-lookup": "^0.0.20", - "discord-api-types": "^0.35.0", - "discord.js": "14.0.0-dev.1657022642-fd1c240", + "discord-api-types": "^0.36.2", + "discord.js": "14.0.0-dev.1657757514-fe34f48", "dotenv": "^16.0.1", "i18n": "^0.15.0", "libsodium-wrappers": "^0.7.10", @@ -27,14 +27,14 @@ "zlib-sync": "^0.1.7" }, "devDependencies": { - "@prisma/client": "^3.15.2", + "@prisma/client": "^4.0.0", "@types/bluebird": "^3.5.36", - "@types/i18n": "^0.13.3", - "@types/node": "^18.0.0", + "@types/i18n": "^0.13.4", + "@types/node": "^18.0.4", "@types/ping": "^0.4.1", - "@types/validator": "^13.7.3", + "@types/validator": "^13.7.4", "copyfiles": "^2.4.1", - "prisma": "^3.15.2", + "prisma": "^4.0.0", "ts-node-dev": "^2.0.0" }, "scripts": { diff --git a/yarn.lock b/yarn.lock index c56188a..cbe12c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,12 +24,12 @@ kuler "^2.0.0" "@discordjs/builders@^0.16.0-dev": - version "0.16.0-dev.1656158607-c4653f9" - resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.16.0-dev.1656158607-c4653f9.tgz#141f8ee5150a193d708c67df4d8f1be59a7e0701" - integrity sha512-kylgqqmw/6uO+5xy/0etmwjV0TL9HLuA9JtPFRt8Xwb9feRqKTYMSKxQ/SQl5HqBwWNzMxxUo2eqU44KqD/0BQ== + version "0.16.0-dev.1657757509-fe34f48" + resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.16.0-dev.1657757509-fe34f48.tgz#d5a0376940c68059874b74c26389c114c1bda02b" + integrity sha512-pxaG7OHRqsnd8MPhfVYQUirrvVmMWxwjSL0j4adHz1w7gWUtgchxOVcOCLgWdFDCoN4bNwRjkstNcI+yLpNE7w== dependencies: - "@sapphire/shapeshift" "^3.2.0" - discord-api-types "^0.33.5" + "@sapphire/shapeshift" "^3.4.1" + discord-api-types "^0.36.1" fast-deep-equal "^3.1.3" ts-mixer "^6.0.1" tslib "^2.4.0" @@ -40,32 +40,32 @@ integrity sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA== "@discordjs/collection@^0.8.0-dev": - version "0.8.0-dev.1656158612-c4653f9" - resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.8.0-dev.1656158612-c4653f9.tgz#fd934b123cd1999a0fc4ff3e5f7b6513e0afc453" - integrity sha512-xQKf3cS0M6Q3NVsY7tSmNmSrbGKt6P/h2+O2H3+CZbTQNAQSpF+Y9Bwt44Jq0XjsxFvv8FKh8/tg5DtG9bOz8g== + version "0.8.0-dev.1657757511-fe34f48" + resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.8.0-dev.1657757511-fe34f48.tgz#6a618261667aca2f147055ec035f5f84fb93dfc7" + integrity sha512-r4ixU8TXVMb3D9TvlVISrrwrV+uxJJBIKuZWI5AJr1M1rJdt41lFtD4ZsO3SuyE8pBo1eU/XSTc6lsTmNMhy1A== -"@discordjs/node-pre-gyp@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@discordjs/node-pre-gyp/-/node-pre-gyp-0.4.2.tgz#37dd27f8d353eeb87372fcce059c5249550b37ab" - integrity sha512-V239Czn+DXFGLhhuccwEDBoTdgMGrRu30dOlzm1GzrSIjwFj01ZJerNX7x+CEX1NG1Q/1gGfOOkeZFNHjycrRA== +"@discordjs/node-pre-gyp@^0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@discordjs/node-pre-gyp/-/node-pre-gyp-0.4.4.tgz#33eea1038784ffc5715ef775e4f9d6cffaa96c73" + integrity sha512-x569MMtdk6jdGo2S58iiZoyv4p/N2Ju8Nh6vvzZb1wyouV7IE3VuU0hg2kqUmTfD0z6r4uD6acvMTuc+iA3f8g== dependencies: - detect-libc "^1.0.3" + detect-libc "^2.0.0" https-proxy-agent "^5.0.0" make-dir "^3.1.0" - node-fetch "^2.6.5" + node-fetch "^2.6.7" nopt "^5.0.0" npmlog "^5.0.1" rimraf "^3.0.2" semver "^7.3.5" tar "^6.1.11" -"@discordjs/opus@^0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@discordjs/opus/-/opus-0.7.0.tgz#69e9611a6412ea470f8e640f54478da89326ca3b" - integrity sha512-3Xxa3dh7taSDwBAR5fLALZ/KTxvbMmHCMxYLYve6NlPO7Ms1CLmKqp/R4ZoVzkRGQVUVWEhaB1s0v9jfa2tfDg== +"@discordjs/opus@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@discordjs/opus/-/opus-0.8.0.tgz#dae2d220a7942736343021f9af2b2b921d482c46" + integrity sha512-uHE7OmHEmP8YM0yvsH3iSdacdeghO0qTkF0CIkV07Tg0qdyOLUVkoZHj5Zcpge9rC4qb/JvTS2xRgttSZLM43Q== dependencies: - "@discordjs/node-pre-gyp" "^0.4.2" - node-addon-api "^4.2.0" + "@discordjs/node-pre-gyp" "^0.4.4" + node-addon-api "^5.0.0" "@discordjs/rest@^0.5.0": version "0.5.0" @@ -80,16 +80,16 @@ undici "^5.4.0" "@discordjs/rest@^0.6.0-dev": - version "0.6.0-dev.1656158624-c4653f9" - resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-0.6.0-dev.1656158624-c4653f9.tgz#ce0d5fe32db32f697967d875c87137f92d6d6ef9" - integrity sha512-LerWi+sNv4kXFgxZERzEOyrNsMZ5G7MpiWtG83zSCMyE/ySZZzeSvlDshPaL+yoReSo4Bq+LAbrX4EGznMhjFA== + version "0.6.0-dev.1657757537-fe34f48" + resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-0.6.0-dev.1657757537-fe34f48.tgz#c512d8e600bfdd7b67d5e6dadeb2aceaec5b7119" + integrity sha512-jJA5tedKJiVLmieAvBffBNM5409ZOPxFi3A+6KMfmxBYgI5N6lfDIcRgd+oosi1l0t37lyxozofwdivS4aHNGA== dependencies: "@discordjs/collection" "^0.8.0-dev" - "@sapphire/async-queue" "^1.3.1" + "@sapphire/async-queue" "^1.3.2" "@sapphire/snowflake" "^3.2.2" - discord-api-types "^0.33.5" + discord-api-types "^0.36.1" tslib "^2.4.0" - undici "^5.5.1" + undici "^5.6.0" "@discordjs/voice@^0.10.0": version "0.10.0" @@ -172,32 +172,40 @@ dependencies: make-plural "^7.0.0" -"@prisma/client@^3.15.2": - version "3.15.2" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-3.15.2.tgz#2181398147afc79bfe0d83c03a88dc45b49bd365" - integrity sha512-ErqtwhX12ubPhU4d++30uFY/rPcyvjk+mdifaZO5SeM21zS3t4jQrscy8+6IyB0GIYshl5ldTq6JSBo1d63i8w== +"@prisma/client@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.0.0.tgz#ed2f46930a1da0d8ae88d7965485973576b04270" + integrity sha512-g1h2OGoRo7anBVQ9Cw3gsbjwPtvf7i0pkGxKeZICtwkvE5CZXW+xZF4FZdmrViYkKaAShbISL0teNpu9ecpf4g== dependencies: - "@prisma/engines-version" "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e" + "@prisma/engines-version" "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11" -"@prisma/engines-version@3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e": - version "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz#bf5e2373ca68ce7556b967cb4965a7095e93fe53" - integrity sha512-e3k2Vd606efd1ZYy2NQKkT4C/pn31nehyLhVug6To/q8JT8FpiMrDy7zmm3KLF0L98NOQQcutaVtAPhzKhzn9w== +"@prisma/engines-version@3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11": + version "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11.tgz#4b5efe5eee2feef12910e4627a572cd96ed83236" + integrity sha512-PiZhdD624SrYEjyLboI0X7OugNbxUzDJx9v/6ldTKuqNDVUCmRH/Z00XwDi/dgM4FlqOSO+YiUsSiSKjxxG8cw== -"@prisma/engines@3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e": - version "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz#f691893df506b93e3cb1ccc15ec6e5ac64e8e570" - integrity sha512-NHlojO1DFTsSi3FtEleL9QWXeSF/UjhCW0fgpi7bumnNZ4wj/eQ+BJJ5n2pgoOliTOGv9nX2qXvmHap7rJMNmg== +"@prisma/engines@3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11": + version "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11.tgz#82f0018153cffa05d61422f9c0c7b0479b180f75" + integrity sha512-u/rG4lDHALolWBLr3yebZ+N2qImp3SDMcu7bHNJuRDaYvYEXy/MqfNRNEgd9GoPsXL3gofYf0VzJf2AmCG3YVw== "@sapphire/async-queue@^1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.3.1.tgz#9d861e626dbffae02d808e13f823d4510e450a78" integrity sha512-FFTlPOWZX1kDj9xCAsRzH5xEJfawg1lNoYAA+ecOWJMHOfiZYb1uXOI3ne9U4UILSEPwfE68p3T9wUHwIQfR0g== -"@sapphire/shapeshift@^3.2.0": - version "3.3.2" - resolved "https://registry.yarnpkg.com/@sapphire/shapeshift/-/shapeshift-3.3.2.tgz#505c0fe2c5256415916ceff4db4c1c0ddfa57c67" - integrity sha512-8+M8sLmT4RTXJCvI1Z69UiB56himVup8WJVm7ubt5j3HJmVK+l1OI4xTLkLVh1efupOhZR9jrl2YBIv4Lsag7A== +"@sapphire/async-queue@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.3.2.tgz#befe5f5025e2e317a9eba2d1a24ca5d2e4576f86" + integrity sha512-rUpMLATsoAMnlN3gecAcr9Ecnw1vG7zi5Xr+IX22YzRzi1k9PF9vKzoT8RuEJbiIszjcimu3rveqUnvwDopz8g== + +"@sapphire/shapeshift@^3.4.1": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@sapphire/shapeshift/-/shapeshift-3.5.0.tgz#3d5b9bdc29be0608f571db1781662b3fda438848" + integrity sha512-r6Iw3ZWgwzWcWDtsPwHKHnc6LCD84AqyXi1IolSS8TGLodTuggYxQ63V+Si5Jb7KVLhMYPCdlwM0HEDHEeZ9Iw== + dependencies: + fast-deep-equal "^3.1.3" + lodash.uniqwith "^4.5.0" "@sapphire/snowflake@^3.2.2": version "3.2.2" @@ -234,16 +242,21 @@ resolved "https://registry.yarnpkg.com/@types/color-thief-node/-/color-thief-node-1.0.1.tgz#851a82b48a5560e4d2c051324e42c21a25e5802c" integrity sha512-UU2pvvjtxvugMdCpoG7If9EqbaeITyczSXymIA/h/Quzbf4HwvT1uBKDG0R42jzHlHGOsRqCRb+RP5Kj1RIBaQ== -"@types/i18n@^0.13.3": - version "0.13.3" - resolved "https://registry.yarnpkg.com/@types/i18n/-/i18n-0.13.3.tgz#88db5b33ccbbd57de54c8c2da01002e8fb48efc3" - integrity sha512-o6MlrxjGUDANSmMmQ6p/f7ea3+kJFeNWebxylKE3pLjWbIa0Npr/DT2Qf941oqovdopadAfV+PuBMTKg4p37NA== +"@types/i18n@^0.13.4": + version "0.13.4" + resolved "https://registry.yarnpkg.com/@types/i18n/-/i18n-0.13.4.tgz#fe3d27d08337f9d4a972d1f460d1471d6f79e163" + integrity sha512-PN4ZsplbpHZ2eaYixFNWkZKN51pcB02K2UKvqHVbrzq2jTO0sChPMuKKYAW1ZbElyHUvPgFeYsz9rqktChGyMw== -"@types/node@*", "@types/node@^18.0.0": +"@types/node@*": version "18.0.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.0.tgz#67c7b724e1bcdd7a8821ce0d5ee184d3b4dd525a" integrity sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA== +"@types/node@^18.0.4": + version "18.0.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.4.tgz#48aedbf35efb3af1248e4cd4d792c730290cd5d6" + integrity sha512-M0+G6V0Y4YV8cqzHssZpaNCqvYwlCiulmm0PwpNLF55r/+cT8Ol42CHRU1SEaYFH2rTwiiE1aYg/2g2rrtGdPA== + "@types/os-utils@^0.0.1": version "0.0.1" resolved "https://registry.yarnpkg.com/@types/os-utils/-/os-utils-0.0.1.tgz#f1ec7830c60be563d6e9566a0ae3b23ea5497493" @@ -264,10 +277,10 @@ resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== -"@types/validator@^13.7.3": - version "13.7.3" - resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.3.tgz#3193c0a3c03a7d1189016c62b4fba4b149ef5e33" - integrity sha512-DNviAE5OUcZ5s+XEQHRhERLg8fOp8gSgvyJ4aaFASx5wwaObm+PBwTIMXiOFm1QrSee5oYwEAYb7LMzX2O88gA== +"@types/validator@^13.7.4": + version "13.7.4" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.4.tgz#33cc949ee87dd47c63e35ba4ad94f6888852be04" + integrity sha512-uAaSWegu2lymY18l+s5nmcXu3sFeeTOl1zhSGoYzcr6T3wz1M+3OcW4UjfPhIhHGd13tIMRDsEpR+d8w/MexwQ== "@types/ws@^8.5.3": version "8.5.3" @@ -583,11 +596,6 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== - detect-libc@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" @@ -598,31 +606,31 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -discord-api-types@^0.33.3, discord-api-types@^0.33.5: +discord-api-types@^0.33.3: version "0.33.5" resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.33.5.tgz#6548b70520f7b944c60984dca4ab58654d664a12" integrity sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg== -discord-api-types@^0.35.0: - version "0.35.0" - resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.35.0.tgz#85c6ea95f27580ad13b7a08444b16cb31d41e5e2" - integrity sha512-aaIbVgPk7OA3y/HdG00tRM2nB8B3sSPH6KXgamBLRrcAJEQ8XZJNNKeRr0WVzw/lprdpKHKuTNX1DNrYnD5cOw== +discord-api-types@^0.36.1, discord-api-types@^0.36.2: + version "0.36.2" + resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.36.2.tgz#2362bc544837be965ec99a5919f900c9699a7028" + integrity sha512-TunPAvzwneK/m5fr4hxH3bMsrtI22nr9yjfHyo5NBGMjpsAauGNiGCmwoFf0oO3jSd2mZiKUvZwCKDaB166u2Q== -discord.js@14.0.0-dev.1657022642-fd1c240: - version "14.0.0-dev.1657022642-fd1c240" - resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.0.0-dev.1657022642-fd1c240.tgz#487bcb0b6608b67dcdd5caf54e2ff72b9e73aabb" - integrity sha512-sIJXapK7099aIRDll5PXLlBatXpudMfomt/v0FOIEP63MzVLI+TMRpd9hHj62rguhmK21vv/9zbHrpnDu81YpQ== +discord.js@14.0.0-dev.1657757514-fe34f48: + version "14.0.0-dev.1657757514-fe34f48" + resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.0.0-dev.1657757514-fe34f48.tgz#2aa0570fbb0995acaee205ee74f1b10af8042091" + integrity sha512-warixUTyz+NIyoTQht21Seo1bC1UPSRw3/b/uUtPB/BGu4e1X1orwcEP1wepQuwyqLIf8yo0vRJo21vRvwILvg== dependencies: "@discordjs/builders" "^0.16.0-dev" "@discordjs/collection" "^0.8.0-dev" "@discordjs/rest" "^0.6.0-dev" "@sapphire/snowflake" "^3.2.2" "@types/ws" "^8.5.3" - discord-api-types "^0.33.5" + discord-api-types "^0.36.1" fast-deep-equal "^3.1.3" lodash.snakecase "^4.1.1" tslib "^2.4.0" - undici "^5.5.1" + undici "^5.6.0" ws "^8.8.0" dotenv@^16.0.1: @@ -898,7 +906,23 @@ lodash.snakecase@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw== -logform@^2.2.0, logform@^2.3.2: +lodash.uniqwith@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz#7a0cbf65f43b5928625a9d4d0dc54b18cadc7ef3" + integrity sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q== + +logform@^2.2.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.2.tgz#a617983ac0334d0c3b942c34945380062795b47c" + integrity sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw== + dependencies: + "@colors/colors" "1.5.0" + fecha "^4.2.0" + ms "^2.1.1" + safe-stable-stringify "^2.3.1" + triple-beam "^1.3.0" + +logform@^2.3.2: version "2.4.1" resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.1.tgz#512c9eaef738044d1c619790ba0f806c80d9d3a9" integrity sha512-7XB/tqc3VRbri9pRjU6E97mQ8vC27ivJ3lct4jhyT+n0JNDd4YKldFl0D75NqDp46hk8RC7Ma1Vjv/UPf67S+A== @@ -1022,12 +1046,12 @@ nan@^2.14.0, nan@^2.15.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.16.0.tgz#664f43e45460fb98faf00edca0bb0d7b8dce7916" integrity sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA== -node-addon-api@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" - integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== +node-addon-api@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.0.0.tgz#7d7e6f9ef89043befdb20c1989c905ebde18c501" + integrity sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA== -node-fetch@^2.6.5, node-fetch@^2.6.7: +node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== @@ -1145,12 +1169,12 @@ prism-media@^1.3.2: resolved "https://registry.yarnpkg.com/prism-media/-/prism-media-1.3.2.tgz#a1f04423ec15d22f3d62b1987b6a25dc49aad13b" integrity sha512-L6UsGHcT6i4wrQhFF1aPK+MNYgjRqR2tUoIqEY+CG1NqVkMjPRKzS37j9f8GiYPlD6wG9ruBj+q5Ax+bH8Ik1g== -prisma@^3.15.2: - version "3.15.2" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-3.15.2.tgz#4ebe32fb284da3ac60c49fbc16c75e56ecf32067" - integrity sha512-nMNSMZvtwrvoEQ/mui8L/aiCLZRCj5t6L3yujKpcDhIPk7garp8tL4nMx2+oYsN0FWBacevJhazfXAbV1kfBzA== +prisma@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-4.0.0.tgz#4ddb8fcd4f64d33aff8c198a6986dcce66dc8152" + integrity sha512-Dtsar03XpCBkcEb2ooGWO/WcgblDTLzGhPcustbehwlFXuTMliMDRzXsfygsgYwQoZnAUKRd1rhpvBNEUziOVw== dependencies: - "@prisma/engines" "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e" + "@prisma/engines" "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11" process-nextick-args@~2.0.0: version "2.0.1" @@ -1515,11 +1539,16 @@ underscore@^1.12.0: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.4.tgz#7886b46bbdf07f768e0052f1828e1dcab40c0dee" integrity sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ== -undici@^5.4.0, undici@^5.5.1: +undici@^5.4.0: version "5.5.1" resolved "https://registry.yarnpkg.com/undici/-/undici-5.5.1.tgz#baaf25844a99eaa0b22e1ef8d205bffe587c8f43" integrity sha512-MEvryPLf18HvlCbLSzCW0U00IMftKGI5udnjrQbC5D4P0Hodwffhv+iGfWuJwg16Y/TK11ZFK8i+BPVW2z/eAw== +undici@^5.6.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.7.0.tgz#979f89229c01505573cb274d0e11ea8d82b4004f" + integrity sha512-ORgxwDkiPS+gK2VxE7iyVeR7JliVn5DqhZ4LgQqYLBXsuK+lwOEmnJ66dhvlpLM0tC3fC7eYF1Bti2frbw2eAA== + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" From 8b5f3ac2f8218eec9a8ac44c21533d96e9302e24 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 15 Jul 2022 15:41:29 +0700 Subject: [PATCH 47/63] Fixed breaking changes --- src/discord/Developer/Debug.ts | 4 +- src/discord/MembershipScreening.ts | 61 +++++++++++++++------------ src/discord/MusicPlayer/Join.ts | 12 +++--- src/discord/MusicPlayer/NowPlaying.ts | 8 ++-- src/discord/MusicPlayer/Play.ts | 7 +-- src/discord/MusicPlayer/PlayMy.ts | 4 +- src/discord/MusicPlayer/Search.ts | 2 +- src/discord/UserInfo.ts | 12 +++--- src/discord/osu.ts | 40 ++++++++---------- 9 files changed, 77 insertions(+), 73 deletions(-) diff --git a/src/discord/Developer/Debug.ts b/src/discord/Developer/Debug.ts index 328e856..87d726d 100644 --- a/src/discord/Developer/Debug.ts +++ b/src/discord/Developer/Debug.ts @@ -162,7 +162,7 @@ export default class Debug extends DiscordModule { }); }, invalidInteraction: async (data: HybridInteractionMessage) => { - const row = new ActionRowBuilder().addComponents( + const row = new ActionRowBuilder().addComponents([ new ButtonBuilder() .setEmoji('😥') .setLabel( @@ -170,7 +170,7 @@ export default class Debug extends DiscordModule { ) .setCustomId('dev_make_invalid_interaction') .setStyle(ButtonStyle.Primary) - ); + ]); await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.INVALID_TEST(data)], components: [row] diff --git a/src/discord/MembershipScreening.ts b/src/discord/MembershipScreening.ts index a591a7d..475feb6 100644 --- a/src/discord/MembershipScreening.ts +++ b/src/discord/MembershipScreening.ts @@ -272,28 +272,34 @@ export default class MembershipScreening extends DiscordModule { }); if (!requesterMember) { - newEmbed.addFields({ - name: '❌ Invalid', - value: `Unable to find the user. User left already?` - }); + newEmbed.addFields([ + { + name: '❌ Invalid', + value: `Unable to find the user. User left already?` + } + ]); return await message.edit({ components: [], embeds: [newEmbed] }); } if (requesterMember.roles.cache.has(PrismaGuild.MembershipScreening_GivenRole)) { - newEmbed.addFields({ - name: '✅ Approved', - value: `By: Unknown (User already obtained the role by other means)` - }); + newEmbed.addFields([ + { + name: '✅ Approved', + value: `By: Unknown (User already obtained the role by other means)` + } + ]); return await message.edit({ components: [], embeds: [newEmbed] }); } if (payload.a === 'approve') { try { await requesterMember.roles.add(role); - newEmbed.addFields({ - name: '✅ Approved', - value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` - }); + newEmbed.addFields([ + { + name: '✅ Approved', + value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` + } + ]); await message.edit({ components: [], embeds: [newEmbed] }); } catch (err) { return interaction.reply({ @@ -304,10 +310,12 @@ export default class MembershipScreening extends DiscordModule { } else if (payload.a === 'deny') { try { await requesterMember.kick(); - newEmbed.addFields({ - name: '❌ Denied', - value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` - }); + newEmbed.addFields([ + { + name: '❌ Denied', + value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` + } + ]); await message.edit({ components: [], embeds: [newEmbed] }); } catch (err) { return interaction.reply({ @@ -320,10 +328,12 @@ export default class MembershipScreening extends DiscordModule { await requesterMember.ban({ reason: `Membership Screening, action issued by ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` }); - newEmbed.addFields({ - name: '🔪 Banned', - value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` - }); + newEmbed.addFields([ + { + name: '🔪 Banned', + value: `By: ${interaction.user.username}#${interaction.user.discriminator} (${interaction.user.id})` + } + ]); await message.edit({ components: [], embeds: [newEmbed] }); } catch (err) { return interaction.reply({ @@ -556,7 +566,7 @@ export default class MembershipScreening extends DiscordModule { embed.setThumbnail(`${member.user.displayAvatarURL()}?size=4096`); const row = new ActionRowBuilder() - .addComponents( + .addComponents([ new ButtonBuilder() .setCustomId( JSON.stringify({ @@ -569,9 +579,7 @@ export default class MembershipScreening extends DiscordModule { ) .setEmoji('✅') .setLabel(' Approve') - .setStyle(ButtonStyle.Success) - ) - .addComponents( + .setStyle(ButtonStyle.Success), new ButtonBuilder() .setCustomId( JSON.stringify({ @@ -584,9 +592,7 @@ export default class MembershipScreening extends DiscordModule { ) .setEmoji('⛔') .setLabel(' Deny and kick') - .setStyle(ButtonStyle.Danger) - ) - .addComponents( + .setStyle(ButtonStyle.Danger), new ButtonBuilder() .setCustomId( JSON.stringify({ @@ -600,6 +606,7 @@ export default class MembershipScreening extends DiscordModule { .setEmoji('🔪') .setLabel(' Vision Hunt Decree (Ban)') .setStyle(ButtonStyle.Danger) + ] ); await channel.send({ content: '\u200b', embeds: [embed], components: [row] }); diff --git a/src/discord/MusicPlayer/Join.ts b/src/discord/MusicPlayer/Join.ts index 7e288e9..694cd74 100644 --- a/src/discord/MusicPlayer/Join.ts +++ b/src/discord/MusicPlayer/Join.ts @@ -232,23 +232,23 @@ export async function joinVoiceChannelProcedure( const row = new ActionRowBuilder(); if(event.instance.queue.track[0] instanceof SpotifyTrack) - row.addComponents( + row.addComponents([ new ButtonBuilder() .setEmoji('🟢') .setLabel(' Open in Spotify') .setURL(encodeURI(`https://open.spotify.com/track/${event.instance.queue.track[0].id}`)) - .setStyle(ButtonStyle.Link), - ) + .setStyle(ButtonStyle.Link) + ]); if(event.instance.queue.track[0] instanceof YouTubeVideo || event.instance.queue.track[0] instanceof SpotifyTrack) { const actualPlaybackURL = event.instance.getActualPlaybackURL(); if(event.instance.queue.track[0] instanceof SpotifyTrack && !actualPlaybackURL) return; - row.addComponents( + row.addComponents([ new ButtonBuilder() .setEmoji('🔴') .setLabel(' Open in YouTube') .setURL(event.instance.queue.track[0] instanceof YouTubeVideo ? encodeURI(`https://www.youtube.com/watch?v=${event.instance.queue.track[0].id}`) : encodeURI(event.instance.getActualPlaybackURL()!)) - .setStyle(ButtonStyle.Link), - ) + .setStyle(ButtonStyle.Link) + ]); } if (event.instance.textChannel) { diff --git a/src/discord/MusicPlayer/NowPlaying.ts b/src/discord/MusicPlayer/NowPlaying.ts index 32139be..9f93310 100644 --- a/src/discord/MusicPlayer/NowPlaying.ts +++ b/src/discord/MusicPlayer/NowPlaying.ts @@ -61,23 +61,23 @@ export default class NowPlaying extends DiscordModule { const row = new ActionRowBuilder(); if(instance.queue.track[0] instanceof SpotifyTrack) - row.addComponents( + row.addComponents([ new ButtonBuilder() .setEmoji('🟢') .setLabel(' Open in Spotify') .setURL(encodeURI(`https://open.spotify.com/track/${instance.queue.track[0].id}`)) .setStyle(ButtonStyle.Link), - ) + ]); if(instance.queue.track[0] instanceof YouTubeVideo || instance.queue.track[0] instanceof SpotifyTrack) { const actualPlaybackURL = instance.getActualPlaybackURL(); if(instance.queue.track[0] instanceof SpotifyTrack && !actualPlaybackURL) return; - row.addComponents( + row.addComponents([ new ButtonBuilder() .setEmoji('🔴') .setLabel(' Open in YouTube') .setURL(instance.queue.track[0] instanceof YouTubeVideo ? encodeURI(`https://www.youtube.com/watch?v=${instance.queue.track[0].id}`) : encodeURI(instance.getActualPlaybackURL()!)) .setStyle(ButtonStyle.Link), - ) + ]); } return await sendHybridInteractionMessageResponse(data, { embeds: [await EMBEDS.NOW_PLAYING(data, locale, instance.queue.track[0])], components: [row] }); } diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index 3b41e59..b5d0d1b 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -360,7 +360,7 @@ export default class Play extends DiscordModule { instance.addTrackToQueue(result); if (linkData.list) { - const row = new ActionRowBuilder().addComponents( + const row = new ActionRowBuilder().addComponents([ new ButtonBuilder() .setEmoji('✅') .setCustomId( @@ -372,6 +372,7 @@ export default class Play extends DiscordModule { ) .setLabel(' Add the remaining songs in the playlist') .setStyle(ButtonStyle.Primary) + ] ); return await sendHybridInteractionMessageResponse(data, { @@ -445,7 +446,7 @@ export default class Play extends DiscordModule { // The query length is too long to fit in json if (query.length > 100 - 51) return; - const row = new ActionRowBuilder().addComponents( + const row = new ActionRowBuilder().addComponents([ new ButtonBuilder() .setEmoji('🔎') .setCustomId( @@ -459,7 +460,7 @@ export default class Play extends DiscordModule { ) .setLabel(' Not this? Search!') .setStyle(ButtonStyle.Primary) - ); + ]); return await sendHybridInteractionMessageResponse(data, { embeds: [await EMBEDS.ADDED_QUEUE(data, locale, result[0])], diff --git a/src/discord/MusicPlayer/PlayMy.ts b/src/discord/MusicPlayer/PlayMy.ts index c64089f..a2b3884 100644 --- a/src/discord/MusicPlayer/PlayMy.ts +++ b/src/discord/MusicPlayer/PlayMy.ts @@ -124,7 +124,7 @@ export default class PlayMy extends DiscordModule { // The query length is too long to fit in json if (query.length > 100 - 51) return; - row = new ActionRowBuilder().addComponents( + row = new ActionRowBuilder().addComponents([ new ButtonBuilder() .setEmoji('🔎') .setCustomId( @@ -138,7 +138,7 @@ export default class PlayMy extends DiscordModule { ) .setLabel(' Not this? Search!') .setStyle(ButtonStyle.Primary) - ); + ]); } if(!row) diff --git a/src/discord/MusicPlayer/Search.ts b/src/discord/MusicPlayer/Search.ts index 9b9ada0..e5a8e86 100644 --- a/src/discord/MusicPlayer/Search.ts +++ b/src/discord/MusicPlayer/Search.ts @@ -158,7 +158,7 @@ export default class Search extends DiscordModule { messageSelectMenu.addOptions(menuOptions); const row = new ActionRowBuilder(); - row.addComponents(messageSelectMenu); + row.addComponents([messageSelectMenu]); return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.SEARCH_RESULT(data, locale, result)], components: [row] }); } diff --git a/src/discord/UserInfo.ts b/src/discord/UserInfo.ts index dbcb9e0..d1e4047 100644 --- a/src/discord/UserInfo.ts +++ b/src/discord/UserInfo.ts @@ -74,7 +74,7 @@ const EMBEDS = { if (user.presence?.activities) { for (let activity of user.presence?.activities) { if (activity.type === ActivityType.Custom) - embed.addFields({ + embed.addFields([{ name: `✨ ${locale.__('userinfo.custom_status')}`, value: `${ !activity.emoji @@ -89,7 +89,7 @@ const EMBEDS = { } ${activity.state === null ? '' : activity.state} \u200b`, inline: false - }); + }]); else { let title = ''; switch (activity.type) { @@ -111,7 +111,7 @@ const EMBEDS = { } const startTime = activity.timestamps?.start; const endTime = activity.timestamps?.end; - embed.addFields({ + embed.addFields([{ name: `${title}`, value: `${activity.details === null ? '' : activity.details} ${activity.state === null ? '' : activity.state} @@ -126,12 +126,12 @@ const EMBEDS = { } \u200b`, inline: false - }); + }]); } } } - embed.addFields({ + embed.addFields([{ name: `📰 ${locale.__('userinfo.user_guild_info')}`, value: `${ user.joinedAt === null @@ -142,7 +142,7 @@ const EMBEDS = { } ${user.isGuildOwner ? `${locale.__('userinfo.guild_owner')}` : ''} ` - }); + }]); embed.setThumbnail(user.displayAvatarURL + '?size=4096'); embed.setAuthor({ diff --git a/src/discord/osu.ts b/src/discord/osu.ts index e2c8faf..e2e0d0a 100644 --- a/src/discord/osu.ts +++ b/src/discord/osu.ts @@ -259,13 +259,13 @@ export default class osu extends DiscordModule { 'https://osu.ppy.sh/images/layout/avatar-guest.png' ); - const row = new ActionRowBuilder().addComponents( + const row = new ActionRowBuilder().addComponents([ new ButtonBuilder() .setEmoji('🔗') .setLabel(' Open Profile') .setURL(`https://osu.ppy.sh/users/${result.id}`) .setStyle(ButtonStyle.Link) - ); + ]); return await sendHybridInteractionMessageResponse(data, { embeds: [embed], @@ -439,31 +439,27 @@ export default class osu extends DiscordModule { const row = new ActionRowBuilder(); if (bm_result.hasDownload) - row.addComponents( + row.addComponents([ new ButtonBuilder() .setEmoji('🌎') .setLabel(' Download (Beatconnect)') .setURL(`https://beatconnect.io/b/${bm_result.beatmapSetId}/`) + .setStyle(ButtonStyle.Link), + new ButtonBuilder() + .setEmoji('🔗') + .setLabel(' Open listing') + .setURL( + `https://osu.ppy.sh/beatmapsets/${bm_result.beatmapSetId}${url_mode}/${bm_result.id}` + ) + .setStyle(ButtonStyle.Link), + new ButtonBuilder() + .setEmoji('💬') + .setLabel(' Open discussion') + .setURL( + `https://osu.ppy.sh/beatmapsets/${bm_result.beatmapSetId}/discussion` + ) .setStyle(ButtonStyle.Link) - ); - row.addComponents( - new ButtonBuilder() - .setEmoji('🔗') - .setLabel(' Open listing') - .setURL( - `https://osu.ppy.sh/beatmapsets/${bm_result.beatmapSetId}${url_mode}/${bm_result.id}` - ) - .setStyle(ButtonStyle.Link) - ); - row.addComponents( - new ButtonBuilder() - .setEmoji('💬') - .setLabel(' Open discussion') - .setURL( - `https://osu.ppy.sh/beatmapsets/${bm_result.beatmapSetId}/discussion` - ) - .setStyle(ButtonStyle.Link) - ); + ]); return await sendHybridInteractionMessageResponse(data, { embeds: [embed2], From c6b306a60e044ea8ee18ca100509f35b79cecaa6 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 15 Jul 2022 15:42:04 +0700 Subject: [PATCH 48/63] Changed permission bit for invite --- src/discord/Invite.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/discord/Invite.ts b/src/discord/Invite.ts index c6c62bf..fc97df9 100644 --- a/src/discord/Invite.ts +++ b/src/discord/Invite.ts @@ -14,7 +14,7 @@ const EMBEDS = { const user = data.getUser(); let message; if (!Environment.get().PRIVATE_BOT || user != null && Users.isDeveloper(user.id)) - message = locale.__('invite.info', { BOT_NAME: DiscordProvider.client.user!.username, LINK: `https://discord.com/api/oauth2/authorize?client_id=${DiscordProvider.client.user?.id}&permissions=0&scope=bot%20applications.commands`}); + message = locale.__('invite.info', { BOT_NAME: DiscordProvider.client.user!.username, LINK: `https://discord.com/api/oauth2/authorize?client_id=${DiscordProvider.client.user?.id}&permissions=8&scope=bot%20applications.commands`}); return makeInfoEmbed({ title: `Invite`, From c7cedf562404fd872e83daaa48db448bc2eae3c6 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 15 Jul 2022 15:56:15 +0700 Subject: [PATCH 49/63] Fixed suppress embeds crash --- src/discord/MusicPlayer/Play.ts | 10 ++++++---- src/utils/DiscordModule.ts | 11 ++++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index b5d0d1b..3477052 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -7,7 +7,8 @@ import { SelectMenuInteraction, ButtonInteraction, StageChannel, - ButtonStyle + ButtonStyle, + PermissionsBitField } from 'discord.js'; import { I18n } from 'i18n'; @@ -25,6 +26,7 @@ import { makeInfoEmbed } from '../../utils/DiscordMessage'; import { SpotifyTrack, YouTubeVideo } from 'play-dl'; +import { checkBotPermissionsInChannel } from '../../utils/DiscordPermission'; const EMBEDS = { PLAY_INFO: (data: HybridInteractionMessage, locale: I18n) => { @@ -283,7 +285,7 @@ export default class Play extends DiscordModule { async run(data: HybridInteractionMessage, args: any) { let query; const guild = data.getGuild(); - const channel = data.getChannel(); + const channel = data.getGuildChannel(); const member = data.getMember(); if (!guild || !channel || !member) return; @@ -353,7 +355,7 @@ export default class Play extends DiscordModule { if (!result) return; - if (data.isMessage() && data.getMessage().embeds.length > 0) { + if (data.isMessage() && data.getMessage().embeds.length > 0 && await checkBotPermissionsInChannel({ guild, data, locale, channel, permissions: [PermissionsBitField.Flags.ManageMessages]})) { data.getMessage().suppressEmbeds(true); } @@ -413,7 +415,7 @@ export default class Play extends DiscordModule { if (!result) return; - if (data.isMessage() && data.getMessage().embeds.length > 0) { + if (data.isMessage() && data.getMessage().embeds.length > 0 && await checkBotPermissionsInChannel({ guild, data, locale, channel, permissions: [PermissionsBitField.Flags.ManageMessages]})) { data.getMessage().suppressEmbeds(true); } diff --git a/src/utils/DiscordModule.ts b/src/utils/DiscordModule.ts index 22aebc4..d5dabdf 100644 --- a/src/utils/DiscordModule.ts +++ b/src/utils/DiscordModule.ts @@ -10,7 +10,9 @@ import { User, SelectMenuInteraction, InteractionType, - BaseInteraction + BaseInteraction, + GuildBasedChannel, + ChannelType } from 'discord.js'; export default class DiscordModule { @@ -87,6 +89,13 @@ export class HybridInteractionMessage { return this.data.channel; } + public getGuildChannel(): GuildBasedChannel | null { + if (this.data.channel && this.data.channel.type !== ChannelType.DM) { + return this.getChannel() as GuildBasedChannel; + } + return null; + } + public getGuild(): Guild | null { return this.data.guild; } From d696d7df978f9cd32718ffc60878a3a8e50f3db0 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 15 Jul 2022 15:59:17 +0700 Subject: [PATCH 50/63] Bump NodeJS to 18 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 526ed27..c8244d7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ RUN DEBIAN_FRONTEND=noninteractive RUN apt-get update -y RUN apt-get -y install curl gnupg git python2 make g++ iputils-ping ffmpeg -RUN curl -sL https://deb.nodesource.com/setup_17.x | bash - +RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - RUN apt-get -y install nodejs RUN npm i -g yarn @@ -18,7 +18,7 @@ WORKDIR /home/node/app RUN apt-get update -y RUN apt-get -y install curl gnupg git python2 make g++ iputils-ping ffmpeg -RUN curl -sL https://deb.nodesource.com/setup_17.x | bash - +RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - RUN apt-get -y install nodejs RUN npm i -g yarn From 826cec7d4edf2a511c34aa950ab5c586d00f38d3 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 15 Jul 2022 16:01:06 +0700 Subject: [PATCH 51/63] Reverted to NodeJS 16 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index c8244d7..6b56ea1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ RUN DEBIAN_FRONTEND=noninteractive RUN apt-get update -y RUN apt-get -y install curl gnupg git python2 make g++ iputils-ping ffmpeg -RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - +RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - RUN apt-get -y install nodejs RUN npm i -g yarn @@ -18,7 +18,7 @@ WORKDIR /home/node/app RUN apt-get update -y RUN apt-get -y install curl gnupg git python2 make g++ iputils-ping ffmpeg -RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - +RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - RUN apt-get -y install nodejs RUN npm i -g yarn From 667ed920f78a0a331451460862035a06ca93f253 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 15 Jul 2022 16:10:57 +0700 Subject: [PATCH 52/63] Silenced suppress embeds permission check message --- src/discord/MusicPlayer/Play.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index 3477052..08a9774 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -355,7 +355,7 @@ export default class Play extends DiscordModule { if (!result) return; - if (data.isMessage() && data.getMessage().embeds.length > 0 && await checkBotPermissionsInChannel({ guild, data, locale, channel, permissions: [PermissionsBitField.Flags.ManageMessages]})) { + if (data.isMessage() && data.getMessage().embeds.length > 0 && await checkBotPermissionsInChannel({ guild, channel, permissions: [PermissionsBitField.Flags.ManageMessages]})) { data.getMessage().suppressEmbeds(true); } @@ -415,7 +415,7 @@ export default class Play extends DiscordModule { if (!result) return; - if (data.isMessage() && data.getMessage().embeds.length > 0 && await checkBotPermissionsInChannel({ guild, data, locale, channel, permissions: [PermissionsBitField.Flags.ManageMessages]})) { + if (data.isMessage() && data.getMessage().embeds.length > 0 && await checkBotPermissionsInChannel({ guild, channel, permissions: [PermissionsBitField.Flags.ManageMessages]})) { data.getMessage().suppressEmbeds(true); } From 52cc086a7fd8328baa5091cec01e533ec5d04a5a Mon Sep 17 00:00:00 2001 From: Yuzu Date: Fri, 15 Jul 2022 16:26:40 +0700 Subject: [PATCH 53/63] Fixed invite command --- src/discord/Invite.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/discord/Invite.ts b/src/discord/Invite.ts index fc97df9..513352d 100644 --- a/src/discord/Invite.ts +++ b/src/discord/Invite.ts @@ -13,7 +13,7 @@ const EMBEDS = { INVITE_INFO: (data: HybridInteractionMessage, locale: I18n) => { const user = data.getUser(); let message; - if (!Environment.get().PRIVATE_BOT || user != null && Users.isDeveloper(user.id)) + if (!(Environment.get().PRIVATE_BOT === 'true') || user != null && Users.isDeveloper(user.id)) message = locale.__('invite.info', { BOT_NAME: DiscordProvider.client.user!.username, LINK: `https://discord.com/api/oauth2/authorize?client_id=${DiscordProvider.client.user?.id}&permissions=8&scope=bot%20applications.commands`}); return makeInfoEmbed({ From 09d42ace4b7eb07cade78500216529fc56e9c217 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 18 Jul 2022 13:22:49 +0700 Subject: [PATCH 54/63] Changed embeds to HybridInteractionMessage --- src/discord/Developer/ServiceAnnouncement.ts | 48 +++++++-------- src/discord/InteractionManager.ts | 64 ++++++++++---------- src/discord/osu.ts | 42 ++++++------- 3 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/discord/Developer/ServiceAnnouncement.ts b/src/discord/Developer/ServiceAnnouncement.ts index 5a72754..faddf89 100644 --- a/src/discord/Developer/ServiceAnnouncement.ts +++ b/src/discord/Developer/ServiceAnnouncement.ts @@ -24,7 +24,7 @@ import Users from '../../services/Users'; const hexToDecimal = (hex: string) => parseInt(hex.replace('#', ''), 16); const EMBEDS = { - ANNOUNCEMENT_INFO: (data: Message | BaseInteraction) => { + ANNOUNCEMENT_INFO: (data: HybridInteractionMessage) => { return makeInfoEmbed({ title: 'Service Announcement', description: `This module contains management tool for announcement feed\n The announcement message is located in \`\`configs/ServiceAnnouncement.json\`\``, @@ -34,14 +34,14 @@ const EMBEDS = { value: '``reload`` ``previewNews`` ``sendNews`` ``previewMaintenance`` ``sendMaintenance`` ``previewMessage`` ``sendMessage`` ``previewAlert`` ``sendAlert``' } ], - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - NOT_DEVELOPER: (data: Message | BaseInteraction) => { + NOT_DEVELOPER: (data: HybridInteractionMessage) => { return makeErrorEmbed({ title: 'Developer only', description: `This command is restricted to the developers only`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, MAKE_PAYLOAD: (payload: EmbedData) => { @@ -67,38 +67,38 @@ const EMBEDS = { return new EmbedBuilder(payload); }, - RELOADED: (data: Message | BaseInteraction) => { + RELOADED: (data: HybridInteractionMessage) => { return makeSuccessEmbed({ title: 'Service Announcement Configuration Reloaded', - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - RELOAD_ERROR: (data: Message | BaseInteraction, error: string) => { + RELOAD_ERROR: (data: HybridInteractionMessage, error: string) => { return makeErrorEmbed({ title: 'Unable to reload Service Announcement Configuration', description: `\`\`\`${error}\`\`\``, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - SENDING_SERVICE_ANNOUNCEMENT: (data: Message | BaseInteraction) => { + SENDING_SERVICE_ANNOUNCEMENT: (data: HybridInteractionMessage) => { return makeProcessingEmbed({ title: 'Service Announcement', description: `Broadcasting Service Announcement`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - SERVICE_ANNOUNCEMENT_SENT: (data: Message | BaseInteraction) => { + SERVICE_ANNOUNCEMENT_SENT: (data: HybridInteractionMessage) => { return makeSuccessEmbed({ title: 'Service Announcement', description: `Broadcasted Service Announcement`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS: (data: Message | BaseInteraction) => { + SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS: (data: HybridInteractionMessage) => { return makeWarningEmbed({ title: 'Service Announcement', description: `Broadcasted Service Announcement with errors, check console for more info`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); } }; @@ -167,7 +167,7 @@ export default class ServiceAnnouncement extends DiscordModule { async run(data: HybridInteractionMessage, args: any) { if (!Users.isDeveloper(data.getUser()!.id)) return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.NOT_DEVELOPER(data.getRaw())] + embeds: [EMBEDS.NOT_DEVELOPER(data)] }); const channel = data.getChannel(); @@ -185,7 +185,7 @@ export default class ServiceAnnouncement extends DiscordModule { } catch (err: any) { Logger.error('Unable to load custom ServiceAnnouncement config: ' + err); return await sendMessage(channel, undefined, { - embeds: [EMBEDS.RELOAD_ERROR(data.getRaw(), err)] + embeds: [EMBEDS.RELOAD_ERROR(data, err)] }); } } else { @@ -197,7 +197,7 @@ export default class ServiceAnnouncement extends DiscordModule { } return await sendMessage(channel, undefined, { - embeds: [EMBEDS.RELOADED(data.getRaw())] + embeds: [EMBEDS.RELOADED(data)] }); }, previewNews: async (data: HybridInteractionMessage) => { @@ -252,7 +252,7 @@ export default class ServiceAnnouncement extends DiscordModule { let _placeholder = await sendHybridInteractionMessageResponse( data, - { embeds: [EMBEDS.SENDING_SERVICE_ANNOUNCEMENT(data.getRaw())] }, + { embeds: [EMBEDS.SENDING_SERVICE_ANNOUNCEMENT(data)] }, true ); if (_placeholder) placeholder = new HybridInteractionMessage(_placeholder); @@ -300,7 +300,7 @@ export default class ServiceAnnouncement extends DiscordModule { .getMessage() .edit({ embeds: [ - EMBEDS.SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS(data.getRaw()) + EMBEDS.SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS(data) ] }); else if (data.isApplicationCommand()) @@ -308,7 +308,7 @@ export default class ServiceAnnouncement extends DiscordModule { data, { embeds: [ - EMBEDS.SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS(data.getRaw()) + EMBEDS.SERVICE_ANNOUNCEMENT_SENT_WITH_ERRORS(data) ] }, true @@ -317,11 +317,11 @@ export default class ServiceAnnouncement extends DiscordModule { if (data && data.isMessage() && placeholder && placeholder.isMessage()) return placeholder .getMessage() - .edit({ embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_SENT(data.getRaw())] }); + .edit({ embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_SENT(data)] }); else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, - { embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_SENT(data.getRaw())] }, + { embeds: [EMBEDS.SERVICE_ANNOUNCEMENT_SENT(data)] }, true ); } @@ -333,7 +333,7 @@ export default class ServiceAnnouncement extends DiscordModule { if (data.isMessage()) { if (args.length === 0) return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.ANNOUNCEMENT_INFO(data.getRaw())] + embeds: [EMBEDS.ANNOUNCEMENT_INFO(data)] }); query = args[0].toLowerCase(); } else if (data.isApplicationCommand()) { @@ -343,7 +343,7 @@ export default class ServiceAnnouncement extends DiscordModule { switch (query) { case 'info': return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.ANNOUNCEMENT_INFO(data.getRaw())] + embeds: [EMBEDS.ANNOUNCEMENT_INFO(data)] }); case 'reload': return await funct.reload(data); diff --git a/src/discord/InteractionManager.ts b/src/discord/InteractionManager.ts index 95be3ce..7f02d80 100644 --- a/src/discord/InteractionManager.ts +++ b/src/discord/InteractionManager.ts @@ -18,7 +18,7 @@ import { } from '../utils/DiscordInteraction'; const EMBEDS = { - INTERACTION_INFO: (data: Message | BaseInteraction) => { + INTERACTION_INFO: (data: HybridInteractionMessage) => { return makeInfoEmbed({ title: 'Interaction', description: `This module contains management tool for interaction based contents`, @@ -28,47 +28,47 @@ const EMBEDS = { value: '``reloadAll`` ``unloadAll`` ``reloadglobal``' } ], - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - PROCESSING: (data: Message | BaseInteraction) => { + PROCESSING: (data: HybridInteractionMessage) => { return makeProcessingEmbed({ icon: data instanceof Message ? undefined : '⌛', title: `Performing actions`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - NOT_DEVELOPER: (data: Message | BaseInteraction) => { + NOT_DEVELOPER: (data: HybridInteractionMessage) => { return makeErrorEmbed({ title: 'Developer only', description: `This command is restricted to the developers only`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - UNLOADALL_SUCCESS: (data: Message | BaseInteraction) => { + UNLOADALL_SUCCESS: (data: HybridInteractionMessage) => { return makeSuccessEmbed({ title: 'Unloaded all Interaction', - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - UNLOADALL_ERROR: (data: Message | BaseInteraction, err: any) => { + UNLOADALL_ERROR: (data: HybridInteractionMessage, err: any) => { return makeErrorEmbed({ title: 'An error occurred while trying to unload interaction', description: '```' + err + '```', - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - RELOADALL_SUCCESS: (data: Message | BaseInteraction) => { + RELOADALL_SUCCESS: (data: HybridInteractionMessage) => { return makeSuccessEmbed({ title: 'Reloaded all Interaction', - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - RELOADALL_ERROR: (data: Message | BaseInteraction, err: any) => { + RELOADALL_ERROR: (data: HybridInteractionMessage, err: any) => { return makeErrorEmbed({ title: 'An error occurred while trying to reload interaction', description: '```' + err + '```', - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); } }; @@ -92,7 +92,7 @@ export default class InteractionManager extends DiscordModule { if (!Users.isDeveloper(user.id)) return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.NOT_DEVELOPER(data.getRaw())] + embeds: [EMBEDS.NOT_DEVELOPER(data)] }); const funct = { @@ -100,7 +100,7 @@ export default class InteractionManager extends DiscordModule { let placeholder: HybridInteractionMessage | undefined; let _placeholder = await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.PROCESSING(data.getRaw())] + embeds: [EMBEDS.PROCESSING(data)] }); if (_placeholder) placeholder = new HybridInteractionMessage(_placeholder); @@ -110,22 +110,22 @@ export default class InteractionManager extends DiscordModule { if (data && data.isMessage() && placeholder && placeholder.isMessage()) return placeholder .getMessage() - .edit({ embeds: [EMBEDS.UNLOADALL_SUCCESS(data.getRaw())] }); + .edit({ embeds: [EMBEDS.UNLOADALL_SUCCESS(data)] }); else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, - { embeds: [EMBEDS.UNLOADALL_SUCCESS(data.getRaw())] }, + { embeds: [EMBEDS.UNLOADALL_SUCCESS(data)] }, true ); } catch (err) { if (data && data.isMessage() && placeholder && placeholder.isMessage()) return placeholder .getMessage() - .edit({ embeds: [EMBEDS.UNLOADALL_ERROR(data.getRaw(), err)] }); + .edit({ embeds: [EMBEDS.UNLOADALL_ERROR(data, err)] }); else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, - { embeds: [EMBEDS.UNLOADALL_ERROR(data.getRaw(), err)] }, + { embeds: [EMBEDS.UNLOADALL_ERROR(data, err)] }, true ); } @@ -134,7 +134,7 @@ export default class InteractionManager extends DiscordModule { let placeholder: HybridInteractionMessage | undefined; let _placeholder = await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.PROCESSING(data.getRaw())] + embeds: [EMBEDS.PROCESSING(data)] }); if (_placeholder) placeholder = new HybridInteractionMessage(_placeholder); @@ -145,22 +145,22 @@ export default class InteractionManager extends DiscordModule { if (data && data.isMessage() && placeholder && placeholder.isMessage()) return placeholder .getMessage() - .edit({ embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }); + .edit({ embeds: [EMBEDS.RELOADALL_SUCCESS(data)] }); else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, - { embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }, + { embeds: [EMBEDS.RELOADALL_SUCCESS(data)] }, true ); } catch (err) { if (data && data.isMessage() && placeholder && placeholder.isMessage()) return placeholder .getMessage() - .edit({ embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }); + .edit({ embeds: [EMBEDS.RELOADALL_ERROR(data, err)] }); else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, - { embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }, + { embeds: [EMBEDS.RELOADALL_ERROR(data, err)] }, true ); } @@ -169,7 +169,7 @@ export default class InteractionManager extends DiscordModule { let placeholder: HybridInteractionMessage | undefined; let _placeholder = await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.PROCESSING(data.getRaw())] + embeds: [EMBEDS.PROCESSING(data)] }); if (_placeholder) placeholder = new HybridInteractionMessage(_placeholder); @@ -180,22 +180,22 @@ export default class InteractionManager extends DiscordModule { if (data && data.isMessage() && placeholder && placeholder.isMessage()) return placeholder .getMessage() - .edit({ embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }); + .edit({ embeds: [EMBEDS.RELOADALL_SUCCESS(data)] }); else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, - { embeds: [EMBEDS.RELOADALL_SUCCESS(data.getRaw())] }, + { embeds: [EMBEDS.RELOADALL_SUCCESS(data)] }, true ); } catch (err) { if (data && data.isMessage() && placeholder && placeholder.isMessage()) return placeholder .getMessage() - .edit({ embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }); + .edit({ embeds: [EMBEDS.RELOADALL_ERROR(data, err)] }); else if (data.isApplicationCommand()) return await sendHybridInteractionMessageResponse( data, - { embeds: [EMBEDS.RELOADALL_ERROR(data.getRaw(), err)] }, + { embeds: [EMBEDS.RELOADALL_ERROR(data, err)] }, true ); } @@ -207,7 +207,7 @@ export default class InteractionManager extends DiscordModule { if (data.isMessage()) { if (args.length === 0) return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.INTERACTION_INFO(data.getRaw())] + embeds: [EMBEDS.INTERACTION_INFO(data)] }); query = args[0].toLowerCase(); @@ -218,7 +218,7 @@ export default class InteractionManager extends DiscordModule { switch (query) { case 'info': return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.INTERACTION_INFO(data.getRaw())] + embeds: [EMBEDS.INTERACTION_INFO(data)] }); case 'reloadall': return await funct.reloadAll(data); diff --git a/src/discord/osu.ts b/src/discord/osu.ts index e2e0d0a..bf0623a 100644 --- a/src/discord/osu.ts +++ b/src/discord/osu.ts @@ -21,7 +21,7 @@ import { } from '../utils/DiscordMessage'; const EMBEDS = { - osu_INFO: (data: Message | BaseInteraction) => { + osu_INFO: (data: HybridInteractionMessage) => { return makeInfoEmbed({ title: 'osu!', description: `[osu!](https://osu.ppy.sh/home) is a free-to-play rhythm game primarily developed, published, and created by Dean "peppy" Herbert`, @@ -35,43 +35,43 @@ const EMBEDS = { value: '``user``' } ], - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - NO_USER_FOUND: (data: Message | BaseInteraction) => { + NO_USER_FOUND: (data: HybridInteractionMessage) => { return makeErrorEmbed({ title: `That user doesn't exists on osu!`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - NO_USER_MENTIONED: (data: Message | BaseInteraction) => { + NO_USER_MENTIONED: (data: HybridInteractionMessage) => { return makeErrorEmbed({ title: `No osu! username or user id provided`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - INVALID_USER_MENTIONED: (data: Message | BaseInteraction) => { + INVALID_USER_MENTIONED: (data: HybridInteractionMessage) => { return makeErrorEmbed({ title: `Not a valid osu username or id`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - INVALID_BEATMAP_ID_MENTIONED: (data: Message | BaseInteraction) => { + INVALID_BEATMAP_ID_MENTIONED: (data: HybridInteractionMessage) => { return makeErrorEmbed({ title: `Not a valid osu beatmap id`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - NO_BEATMAP_FOUND: (data: Message | BaseInteraction) => { + NO_BEATMAP_FOUND: (data: HybridInteractionMessage) => { return makeErrorEmbed({ title: `That beatmap doesn't exists on osu!`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); }, - NO_BEATMAP_MENTIONED: (data: Message | BaseInteraction) => { + NO_BEATMAP_MENTIONED: (data: HybridInteractionMessage) => { return makeErrorEmbed({ title: `No osu! beatmap id provided`, - user: data instanceof BaseInteraction ? data.user : data.author + user: data.getUser() }); } }; @@ -99,7 +99,7 @@ export default class osu extends DiscordModule { if (data.isMessage()) { if (typeof args[1] === 'undefined') return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.NO_USER_MENTIONED(data.getRaw())] + embeds: [EMBEDS.NO_USER_MENTIONED(data)] }); const [removed, ...newArgs] = args; user = newArgs.join(' '); @@ -108,14 +108,14 @@ export default class osu extends DiscordModule { if (!validator.isNumeric(user) && !this.validate_osu_username(user)) return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.INVALID_USER_MENTIONED(data.getRaw())] + embeds: [EMBEDS.INVALID_USER_MENTIONED(data)] }); let result = await osuAPI.client.getUser({ u: user }); if (result instanceof Array && result.length === 0) return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.NO_USER_FOUND(data.getRaw())] + embeds: [EMBEDS.NO_USER_FOUND(data)] }); if (data.isApplicationCommand()) { @@ -277,7 +277,7 @@ export default class osu extends DiscordModule { if (data.isMessage()) { if (typeof args[1] === 'undefined') return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.NO_BEATMAP_MENTIONED(data.getRaw())] + embeds: [EMBEDS.NO_BEATMAP_MENTIONED(data)] }); const [removed, ...newArgs] = args; beatmap = newArgs.join(' '); @@ -286,14 +286,14 @@ export default class osu extends DiscordModule { if (!validator.isNumeric(beatmap)) return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.INVALID_BEATMAP_ID_MENTIONED(data.getRaw())] + embeds: [EMBEDS.INVALID_BEATMAP_ID_MENTIONED(data)] }); let result = await osuAPI.client.getBeatmaps({ b: beatmap }); if (result instanceof Array && result.length === 0) return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.NO_BEATMAP_FOUND(data.getRaw())] + embeds: [EMBEDS.NO_BEATMAP_FOUND(data)] }); if (data.isApplicationCommand()) await data.getSlashCommand().deferReply(); @@ -473,7 +473,7 @@ export default class osu extends DiscordModule { if (data.isMessage()) { if (args.length === 0) { return await sendHybridInteractionMessageResponse(data, { - embeds: [EMBEDS.osu_INFO(data.getRaw())] + embeds: [EMBEDS.osu_INFO(data)] }); } query = args[0].toLowerCase(); From 38f89e85a74b04a810de7d8fa24430b2a4d2bae8 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 18 Jul 2022 14:16:26 +0700 Subject: [PATCH 55/63] Added clear queue feature --- locales/en.json | 3 ++- locales/jp.json | 3 ++- locales/th.json | 3 ++- src/discord/MusicPlayer/Queue.ts | 27 ++++++++++++++++++---- src/providers/DiscordMusicPlayer.ts | 35 +++++++++++++++++------------ 5 files changed, 50 insertions(+), 21 deletions(-) diff --git a/locales/en.json b/locales/en.json index 2bb2361..9484d8c 100644 --- a/locales/en.json +++ b/locales/en.json @@ -119,7 +119,8 @@ "now_playing": "Now playing", "upcoming_song": "Upcoming song", "looping_current": "(Looping current)", - "song_x_in_queue": "There are {{COUNT}} song in the queue!" + "song_x_in_queue": "There are {{COUNT}} song in the queue!", + "cleared": "Queue cleared~ (。•ˇ‸ˇ•。)" }, "musicplayer_search": { "title": "Search", diff --git a/locales/jp.json b/locales/jp.json index 4ad38dd..0fd10bd 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -119,7 +119,8 @@ "now_playing": "再生中", "upcoming_song": "次の曲", "looping_current": "(この曲の繰り返し)", - "song_x_in_queue": "{{COUNT}}曲も並んでいますよ。" + "song_x_in_queue": "{{COUNT}}曲も並んでいますよ。", + "cleared": "キューがクリアされました (。•ˇ‸ˇ•。)" }, "musicplayer_search": { "title": "検索", diff --git a/locales/th.json b/locales/th.json index be8e3cf..e1319bb 100644 --- a/locales/th.json +++ b/locales/th.json @@ -119,7 +119,8 @@ "now_playing": "กำลังเล่น", "upcoming_song": "เพลงต่อไป", "looping_current": "(กำลังวนซ้ำเพลงนี้)", - "song_x_in_queue": "ตอนนี้มี {{COUNT}} เพลงอยู่ในคิว!" + "song_x_in_queue": "ตอนนี้มี {{COUNT}} เพลงอยู่ในคิว!", + "cleared": "เคลียร์คิวเรียบร้อยละ~ (。•ˇ‸ˇ•。)" }, "musicplayer_search": { "title": "ค้นหา", diff --git a/src/discord/MusicPlayer/Queue.ts b/src/discord/MusicPlayer/Queue.ts index 4f084d9..38a6338 100644 --- a/src/discord/MusicPlayer/Queue.ts +++ b/src/discord/MusicPlayer/Queue.ts @@ -9,7 +9,7 @@ import DiscordMusicPlayer, { import Locale from '../../services/Locale'; import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule'; -import { makeErrorEmbed, sendHybridInteractionMessageResponse, makeInfoEmbed } from '../../utils/DiscordMessage'; +import { makeErrorEmbed, sendHybridInteractionMessageResponse, makeSuccessEmbed, makeInfoEmbed } from '../../utils/DiscordMessage'; const EMBEDS = { QUEUE: (data: HybridInteractionMessage, locale: I18n, instance: DiscordMusicPlayerInstance) => { @@ -67,6 +67,12 @@ const EMBEDS = { } } }, + QUEUE_CLEARED: (data: HybridInteractionMessage, locale: I18n) => { + return makeSuccessEmbed({ + title: locale.__('musicplayer_queue.cleared'), + user: data.getUser() + }); + }, NO_MUSIC_PLAYING: (data: HybridInteractionMessage, locale: I18n) => { return makeErrorEmbed({ title: locale.__('musicplayer.no_music_playing'), @@ -89,10 +95,11 @@ export default class QueueCommand extends DiscordModule { } async run(data: HybridInteractionMessage, args: any) { - const guild = data.getGuild(); + const guild = data.getGuild(); if (!guild) return; + let query; const locale = await Locale.getGuildLocale(guild.id); const instance = DiscordMusicPlayer.getGuildInstance(guild.id); @@ -101,8 +108,20 @@ export default class QueueCommand extends DiscordModule { embeds: [EMBEDS.NO_MUSIC_PLAYING(data, locale)] }); - await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.QUEUE(data, locale, instance)] }); + if (data.isMessage()) { + if (args.length === 0) + return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.QUEUE(data, locale, instance)] }); + + query = args.join(' '); + } else if (data.isApplicationCommand()) { + //query = data.getSlashCommand().options.get('query', true).value?.toString(); + } + + if (!query) return; + if(query.toLowerCase() !== 'clear') return; - return; + instance.clearQueue(); + + return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.QUEUE_CLEARED(data, locale)] }); } } diff --git a/src/providers/DiscordMusicPlayer.ts b/src/providers/DiscordMusicPlayer.ts index 7fbfa08..a6e3971 100644 --- a/src/providers/DiscordMusicPlayer.ts +++ b/src/providers/DiscordMusicPlayer.ts @@ -217,20 +217,6 @@ export class DiscordMusicPlayerInstance { }); } - public isReady() { - if (!this.voiceConnection) return false; - return this.voiceConnection.state.status === VoiceConnectionStatus.Ready; - } - - public isConnected() { - if (!this.voiceConnection) return false; - - if (this.voiceConnection.state.status === VoiceConnectionStatus.Destroyed) return false; - if (this.voiceConnection.state.status === VoiceConnectionStatus.Disconnected) return false; - - return true; - } - public joinVoiceChannel(voiceChannel: VoiceChannel | StageChannel, textChannel?: BaseGuildTextChannel | BaseGuildVoiceChannel) { const permissions = voiceChannel.permissionsFor(DiscordProvider.client.user!); @@ -350,6 +336,13 @@ export class DiscordMusicPlayerInstance { } } + public clearQueue() { + if (!this.voiceConnection) throw new Error('No voice connection'); + + if(!this.queue.track || this.queue.track.length === 0) return; + this.queue.track = [this.queue.track[0]]; + } + public setLoopMode(mode: DiscordMusicPlayerLoopMode) { this.loopMode = mode; } @@ -366,6 +359,20 @@ export class DiscordMusicPlayerInstance { return this.actualPlaybackURL; } + public isReady() { + if (!this.voiceConnection) return false; + return this.voiceConnection.state.status === VoiceConnectionStatus.Ready; + } + + public isConnected() { + if (!this.voiceConnection) return false; + + if (this.voiceConnection.state.status === VoiceConnectionStatus.Destroyed) return false; + if (this.voiceConnection.state.status === VoiceConnectionStatus.Disconnected) return false; + + return true; + } + public isPaused() { return this.paused; } From 11e0a8f94ae58a4f92a0f05a378bcfcd3d729885 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 18 Jul 2022 14:18:58 +0700 Subject: [PATCH 56/63] Code clean up --- src/discord/MusicPlayer/Queue.ts | 58 ++++++++++++++++---------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/discord/MusicPlayer/Queue.ts b/src/discord/MusicPlayer/Queue.ts index 38a6338..9b7c36b 100644 --- a/src/discord/MusicPlayer/Queue.ts +++ b/src/discord/MusicPlayer/Queue.ts @@ -9,7 +9,12 @@ import DiscordMusicPlayer, { import Locale from '../../services/Locale'; import DiscordModule, { HybridInteractionMessage } from '../../utils/DiscordModule'; -import { makeErrorEmbed, sendHybridInteractionMessageResponse, makeSuccessEmbed, makeInfoEmbed } from '../../utils/DiscordMessage'; +import { + makeErrorEmbed, + sendHybridInteractionMessageResponse, + makeSuccessEmbed, + makeInfoEmbed +} from '../../utils/DiscordMessage'; const EMBEDS = { QUEUE: (data: HybridInteractionMessage, locale: I18n, instance: DiscordMusicPlayerInstance) => { @@ -22,49 +27,43 @@ const EMBEDS = { user: data.getUser() }); else { - const nowPlayingText = `${ instance.getLoopMode() === DiscordMusicPlayerLoopMode.Current ? ` ${locale.__('musicplayer_queue.looping_current')}` : '' }: [${TrackUtils.getTitle(queue.track[0])}](${queue.track[0].url})`; + let description; if (queue.track.length == 1) { let queueString = `1. [${TrackUtils.getTitle(queue.track[0])}](${queue.track[0].url})`; - return makeInfoEmbed({ - title: locale.__('musicplayer_queue.title'), - description: `${locale.__('musicplayer_queue.now_playing')}${nowPlayingText}\n - There are ${queue.track.length} song in the queue!\n${queueString}`, - user: data.getUser() - }); + description = `${locale.__('musicplayer_queue.now_playing')}${nowPlayingText}\n + There are ${queue.track.length} song in the queue!\n${queueString}`; } else if (queue.track.length >= 10) { const upcomingText = `[${TrackUtils.getTitle(queue.track[1])}](${queue.track[1].url})`; const first10 = queue.track.slice(0, 10); let queueString = first10 .map((track, index) => `${index + 1}. [${TrackUtils.getTitle(track)}](${track.url})`) .join('\n'); - return makeInfoEmbed({ - title: locale.__('musicplayer_queue.title'), - description: `${locale.__('musicplayer_queue.now_playing')}${nowPlayingText} - ${locale.__('musicplayer_queue.upcoming_song')} ${upcomingText}\n - ${locale.__('musicplayer_queue.song_x_in_queue', { COUNT: queue.track.length.toString()})} - ${queueString}\n${queue.track.length > 10 ? `...${queue.track.length - 10} more songs` : ''}`, - user: data.getUser() - }); + description = `${locale.__('musicplayer_queue.now_playing')}${nowPlayingText} + ${locale.__('musicplayer_queue.upcoming_song')} ${upcomingText}\n + ${locale.__('musicplayer_queue.song_x_in_queue', { COUNT: queue.track.length.toString() })} + ${queueString}\n${queue.track.length > 10 ? `...${queue.track.length - 10} more songs` : ''}`; } else { const upcomingText = `[${TrackUtils.getTitle(queue.track[1])}](${queue.track[1].url})`; const queueString = queue.track .map((track, index) => `${index + 1}. [${TrackUtils.getTitle(track)}](${track.url})`) .join('\n'); - return makeInfoEmbed({ - title: locale.__('musicplayer_queue.title'), - description: `${locale.__('musicplayer_queue.now_playing')}${nowPlayingText} - ${locale.__('musicplayer_queue.upcoming_song')} ${upcomingText}\n - ${locale.__('musicplayer_queue.song_x_in_queue', { COUNT: queue.track.length.toString()})} - ${queueString}`, - user: data.getUser() - }); + description = `${locale.__('musicplayer_queue.now_playing')}${nowPlayingText} + ${locale.__('musicplayer_queue.upcoming_song')} ${upcomingText}\n + ${locale.__('musicplayer_queue.song_x_in_queue', { COUNT: queue.track.length.toString() })} + ${queueString}`; } + + return makeInfoEmbed({ + title: locale.__('musicplayer_queue.title'), + description: description, + user: data.getUser() + }); } }, QUEUE_CLEARED: (data: HybridInteractionMessage, locale: I18n) => { @@ -95,7 +94,6 @@ export default class QueueCommand extends DiscordModule { } async run(data: HybridInteractionMessage, args: any) { - const guild = data.getGuild(); if (!guild) return; @@ -110,15 +108,17 @@ export default class QueueCommand extends DiscordModule { if (data.isMessage()) { if (args.length === 0) - return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.QUEUE(data, locale, instance)] }); - + return await sendHybridInteractionMessageResponse(data, { + embeds: [EMBEDS.QUEUE(data, locale, instance)] + }); + query = args.join(' '); } else if (data.isApplicationCommand()) { //query = data.getSlashCommand().options.get('query', true).value?.toString(); } - + if (!query) return; - if(query.toLowerCase() !== 'clear') return; + if (query.toLowerCase() !== 'clear') return; instance.clearQueue(); From 2b4a534e0c8a6c7b8066aef0548b2dfb8fc2e903 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 18 Jul 2022 14:33:05 +0700 Subject: [PATCH 57/63] Added available args to queue embed --- locales/en.json | 1 + locales/jp.json | 1 + locales/th.json | 1 + src/discord/MusicPlayer/Queue.ts | 6 ++++++ 4 files changed, 9 insertions(+) diff --git a/locales/en.json b/locales/en.json index 9484d8c..d051317 100644 --- a/locales/en.json +++ b/locales/en.json @@ -115,6 +115,7 @@ }, "musicplayer_queue": { "title": "Queue", + "valid_args": "``clear``", "empty": "The queue is empty! (っ˘ω˘ς )", "now_playing": "Now playing", "upcoming_song": "Upcoming song", diff --git a/locales/jp.json b/locales/jp.json index 0fd10bd..34d749d 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -115,6 +115,7 @@ }, "musicplayer_queue": { "title": "キュー", + "valid_args": "``clear``", "empty": "キューは空です! (っ˘ω˘ς )", "now_playing": "再生中", "upcoming_song": "次の曲", diff --git a/locales/th.json b/locales/th.json index e1319bb..653db6b 100644 --- a/locales/th.json +++ b/locales/th.json @@ -115,6 +115,7 @@ }, "musicplayer_queue": { "title": "คิวเพลง", + "valid_args": "``clear``", "empty": "ตอนนี้คิวว่างนะ (っ˘ω˘ς )", "now_playing": "กำลังเล่น", "upcoming_song": "เพลงต่อไป", diff --git a/src/discord/MusicPlayer/Queue.ts b/src/discord/MusicPlayer/Queue.ts index 9b7c36b..d8b7d79 100644 --- a/src/discord/MusicPlayer/Queue.ts +++ b/src/discord/MusicPlayer/Queue.ts @@ -62,6 +62,12 @@ const EMBEDS = { return makeInfoEmbed({ title: locale.__('musicplayer_queue.title'), description: description, + fields: [ + { + name: locale.__('common.available_args'), + value: locale.__('musicplayer_queue.valid_args') + } + ], user: data.getUser() }); } From 97398bf1e2b5969361e0f0a5e7caaf6d761d8369 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 18 Jul 2022 14:53:35 +0700 Subject: [PATCH 58/63] Added queue shuffle --- locales/en.json | 5 +++-- locales/jp.json | 5 +++-- locales/th.json | 5 +++-- src/discord/MusicPlayer/Queue.ts | 19 ++++++++++++++----- src/providers/DiscordMusicPlayer.ts | 18 ++++++++++++++++++ 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/locales/en.json b/locales/en.json index d051317..7f8b1b9 100644 --- a/locales/en.json +++ b/locales/en.json @@ -115,13 +115,14 @@ }, "musicplayer_queue": { "title": "Queue", - "valid_args": "``clear``", + "valid_args": "``clear`` ``shuffle``", "empty": "The queue is empty! (っ˘ω˘ς )", "now_playing": "Now playing", "upcoming_song": "Upcoming song", "looping_current": "(Looping current)", "song_x_in_queue": "There are {{COUNT}} song in the queue!", - "cleared": "Queue cleared~ (。•ˇ‸ˇ•。)" + "cleared": "Queue cleared~ (。•ˇ‸ˇ•。)", + "shuffled": "Queue shuffled" }, "musicplayer_search": { "title": "Search", diff --git a/locales/jp.json b/locales/jp.json index 34d749d..bfe83ad 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -115,13 +115,14 @@ }, "musicplayer_queue": { "title": "キュー", - "valid_args": "``clear``", + "valid_args": "``clear`` ``shuffle``", "empty": "キューは空です! (っ˘ω˘ς )", "now_playing": "再生中", "upcoming_song": "次の曲", "looping_current": "(この曲の繰り返し)", "song_x_in_queue": "{{COUNT}}曲も並んでいますよ。", - "cleared": "キューがクリアされました (。•ˇ‸ˇ•。)" + "cleared": "キューがクリアされました (。•ˇ‸ˇ•。)", + "shuffled": "キューがシャッフルされました" }, "musicplayer_search": { "title": "検索", diff --git a/locales/th.json b/locales/th.json index 653db6b..adc7b06 100644 --- a/locales/th.json +++ b/locales/th.json @@ -115,13 +115,14 @@ }, "musicplayer_queue": { "title": "คิวเพลง", - "valid_args": "``clear``", + "valid_args": "``clear`` ``shuffle``", "empty": "ตอนนี้คิวว่างนะ (っ˘ω˘ς )", "now_playing": "กำลังเล่น", "upcoming_song": "เพลงต่อไป", "looping_current": "(กำลังวนซ้ำเพลงนี้)", "song_x_in_queue": "ตอนนี้มี {{COUNT}} เพลงอยู่ในคิว!", - "cleared": "เคลียร์คิวเรียบร้อยละ~ (。•ˇ‸ˇ•。)" + "cleared": "เคลียร์คิวเรียบร้อยละ~ (。•ˇ‸ˇ•。)", + "shuffled": "สุ่มคิวเรียบร้อยละ" }, "musicplayer_search": { "title": "ค้นหา", diff --git a/src/discord/MusicPlayer/Queue.ts b/src/discord/MusicPlayer/Queue.ts index d8b7d79..0a98aad 100644 --- a/src/discord/MusicPlayer/Queue.ts +++ b/src/discord/MusicPlayer/Queue.ts @@ -78,6 +78,12 @@ const EMBEDS = { user: data.getUser() }); }, + QUEUE_SHUFFLED: (data: HybridInteractionMessage, locale: I18n) => { + return makeSuccessEmbed({ + title: locale.__('musicplayer_queue.shuffled'), + user: data.getUser() + }); + }, NO_MUSIC_PLAYING: (data: HybridInteractionMessage, locale: I18n) => { return makeErrorEmbed({ title: locale.__('musicplayer.no_music_playing'), @@ -124,10 +130,13 @@ export default class QueueCommand extends DiscordModule { } if (!query) return; - if (query.toLowerCase() !== 'clear') return; - - instance.clearQueue(); - - return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.QUEUE_CLEARED(data, locale)] }); + switch (query.toLowerCase()) { + case 'clear': + instance.clearQueue(); + return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.QUEUE_CLEARED(data, locale)] }); + case 'shuffle': + instance.shuffleQueue(); + return await sendHybridInteractionMessageResponse(data, { embeds: [EMBEDS.QUEUE_SHUFFLED(data, locale)] }); + } } } diff --git a/src/providers/DiscordMusicPlayer.ts b/src/providers/DiscordMusicPlayer.ts index a6e3971..cdcb861 100644 --- a/src/providers/DiscordMusicPlayer.ts +++ b/src/providers/DiscordMusicPlayer.ts @@ -343,6 +343,24 @@ export class DiscordMusicPlayerInstance { this.queue.track = [this.queue.track[0]]; } + public shuffleQueue() { + if (!this.voiceConnection) throw new Error('No voice connection'); + + const shuffleFixedFirst = (queue: ValidTracks[]) => { + if(queue.length <= 2) return queue; + + const fixedFirst = queue.shift(); + if(!fixedFirst) return queue; + + queue.sort(() => Math.random() - 0.5); + queue.unshift(fixedFirst); + return queue; + } + + if(!this.queue.track || this.queue.track.length === 0) return; + this.queue.track = shuffleFixedFirst(this.queue.track); + } + public setLoopMode(mode: DiscordMusicPlayerLoopMode) { this.loopMode = mode; } From c6725c0beaf38a7306ef2b31c70b92dee2ffdb49 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 18 Jul 2022 14:55:07 +0700 Subject: [PATCH 59/63] Capitalized first letter --- locales/en.json | 2 +- locales/jp.json | 2 +- locales/th.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/locales/en.json b/locales/en.json index 7f8b1b9..69350ce 100644 --- a/locales/en.json +++ b/locales/en.json @@ -115,7 +115,7 @@ }, "musicplayer_queue": { "title": "Queue", - "valid_args": "``clear`` ``shuffle``", + "valid_args": "``Clear`` ``Shuffle``", "empty": "The queue is empty! (っ˘ω˘ς )", "now_playing": "Now playing", "upcoming_song": "Upcoming song", diff --git a/locales/jp.json b/locales/jp.json index bfe83ad..648c074 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -115,7 +115,7 @@ }, "musicplayer_queue": { "title": "キュー", - "valid_args": "``clear`` ``shuffle``", + "valid_args": "``Clear`` ``Shuffle``", "empty": "キューは空です! (っ˘ω˘ς )", "now_playing": "再生中", "upcoming_song": "次の曲", diff --git a/locales/th.json b/locales/th.json index adc7b06..c31dd49 100644 --- a/locales/th.json +++ b/locales/th.json @@ -115,7 +115,7 @@ }, "musicplayer_queue": { "title": "คิวเพลง", - "valid_args": "``clear`` ``shuffle``", + "valid_args": "``Clear`` ``Shuffle``", "empty": "ตอนนี้คิวว่างนะ (っ˘ω˘ς )", "now_playing": "กำลังเล่น", "upcoming_song": "เพลงต่อไป", From 01c01661715c03ab80ec86cc40c9d64645cdbb3a Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 18 Jul 2022 15:01:37 +0700 Subject: [PATCH 60/63] YouTube and Spotify token check --- src/providers/DiscordMusicPlayer.ts | 46 +++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/providers/DiscordMusicPlayer.ts b/src/providers/DiscordMusicPlayer.ts index cdcb861..825b660 100644 --- a/src/providers/DiscordMusicPlayer.ts +++ b/src/providers/DiscordMusicPlayer.ts @@ -46,21 +46,41 @@ interface SpotifyThumbnail { url: string; } -// TODO: Make proper check later -if (Environment.get().YOUTUBE_COOKIE_BASE64 && Environment.get().SPOTIFY_CLIENT_ID) { - playdl.setToken({ - youtube: { - cookie: Buffer.from(Environment.get().YOUTUBE_COOKIE_BASE64, 'base64').toString() - }, - spotify: { - client_id: Environment.get().SPOTIFY_CLIENT_ID, - client_secret: Environment.get().SPOTIFY_CLIENT_SECRET, - refresh_token: Environment.get().SPOTIFY_REFRESH_TOKEN, - market: Environment.get().SPOTIFY_CLIENT_MARKET, - } - }); +interface TokenOptions { + spotify?: { + client_id: string; + client_secret: string; + refresh_token: string; + market: string; + }; + soundcloud?: { + client_id: string; + }; + youtube?: { + cookie: string; + }; + useragent?: string[]; } +let tokenObject: TokenOptions = {}; + +if (Environment.get().YOUTUBE_COOKIE_BASE64) { + tokenObject.youtube = { + cookie: Buffer.from(Environment.get().YOUTUBE_COOKIE_BASE64, 'base64').toString() + } +} + +if (Environment.get().SPOTIFY_CLIENT_ID && Environment.get().SPOTIFY_CLIENT_SECRET && Environment.get().SPOTIFY_REFRESH_TOKEN && Environment.get().SPOTIFY_CLIENT_MARKET) { + tokenObject.spotify = { + client_id: Environment.get().SPOTIFY_CLIENT_ID, + client_secret: Environment.get().SPOTIFY_CLIENT_SECRET, + refresh_token: Environment.get().SPOTIFY_REFRESH_TOKEN, + market: Environment.get().SPOTIFY_CLIENT_MARKET + } +} + +playdl.setToken(tokenObject); + export class TrackUtils { public static getTitle(track: ValidTracks) { if (track instanceof YouTubeVideo) { From 34351d492befb0d925ecd3712dd2140bfc2e4e7a Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 18 Jul 2022 15:08:41 +0700 Subject: [PATCH 61/63] Bump to stable discord.js v14.0.1 --- package.json | 2 +- yarn.lock | 121 ++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 88 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 68b430a..15b8778 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "country-code-emoji": "^2.3.0", "country-code-lookup": "^0.0.20", "discord-api-types": "^0.36.2", - "discord.js": "14.0.0-dev.1657757514-fe34f48", + "discord.js": "14.0.1", "dotenv": "^16.0.1", "i18n": "^0.15.0", "libsodium-wrappers": "^0.7.10", diff --git a/yarn.lock b/yarn.lock index cbe12c9..b851902 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,13 +23,13 @@ enabled "2.0.x" kuler "^2.0.0" -"@discordjs/builders@^0.16.0-dev": - version "0.16.0-dev.1657757509-fe34f48" - resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-0.16.0-dev.1657757509-fe34f48.tgz#d5a0376940c68059874b74c26389c114c1bda02b" - integrity sha512-pxaG7OHRqsnd8MPhfVYQUirrvVmMWxwjSL0j4adHz1w7gWUtgchxOVcOCLgWdFDCoN4bNwRjkstNcI+yLpNE7w== +"@discordjs/builders@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-1.0.0.tgz#1ddc5a7f9d20977e7414c02989169bb7f55294ba" + integrity sha512-8y91ZfpOHubiGJu5tVyGI9tQCEyHZDTeqUWVcJd0dq7B96xIf84S0L4fwmD1k9zTe1eqEFSk0gc7BpY+FKn7Ww== dependencies: - "@sapphire/shapeshift" "^3.4.1" - discord-api-types "^0.36.1" + "@sapphire/shapeshift" "^3.5.1" + discord-api-types "^0.36.2" fast-deep-equal "^3.1.3" ts-mixer "^6.0.1" tslib "^2.4.0" @@ -39,10 +39,10 @@ resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.7.0.tgz#1a6c00198b744ba2b73a64442145da637ac073b8" integrity sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA== -"@discordjs/collection@^0.8.0-dev": - version "0.8.0-dev.1657757511-fe34f48" - resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.8.0-dev.1657757511-fe34f48.tgz#6a618261667aca2f147055ec035f5f84fb93dfc7" - integrity sha512-r4ixU8TXVMb3D9TvlVISrrwrV+uxJJBIKuZWI5AJr1M1rJdt41lFtD4ZsO3SuyE8pBo1eU/XSTc6lsTmNMhy1A== +"@discordjs/collection@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-1.0.0.tgz#4d777d87e56640a200200e7f5605c0fba05ac1b8" + integrity sha512-nAxDQYE5dNAzEGQ7HU20sujDsG5vLowUKCEqZkKUIlrXERZFTt/60zKUj/g4+AVCGeq+pXC5hivMaNtiC+PY5Q== "@discordjs/node-pre-gyp@^0.4.4": version "0.4.4" @@ -79,17 +79,18 @@ tslib "^2.4.0" undici "^5.4.0" -"@discordjs/rest@^0.6.0-dev": - version "0.6.0-dev.1657757537-fe34f48" - resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-0.6.0-dev.1657757537-fe34f48.tgz#c512d8e600bfdd7b67d5e6dadeb2aceaec5b7119" - integrity sha512-jJA5tedKJiVLmieAvBffBNM5409ZOPxFi3A+6KMfmxBYgI5N6lfDIcRgd+oosi1l0t37lyxozofwdivS4aHNGA== +"@discordjs/rest@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-1.0.0.tgz#624ac48cf8f66f46d47371323963a0c0617ddd63" + integrity sha512-uDAvnE0P2a8axMdD4C51EGjvCRQ2HZk2Yxf6vHWZgIqG87D8DGKMPwmquIxrrB07MjV+rwci2ObU+mGhGP+bJg== dependencies: - "@discordjs/collection" "^0.8.0-dev" + "@discordjs/collection" "^1.0.0" "@sapphire/async-queue" "^1.3.2" "@sapphire/snowflake" "^3.2.2" - discord-api-types "^0.36.1" + discord-api-types "^0.36.2" + file-type "^17.1.2" tslib "^2.4.0" - undici "^5.6.0" + undici "^5.7.0" "@discordjs/voice@^0.10.0": version "0.10.0" @@ -199,10 +200,10 @@ resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.3.2.tgz#befe5f5025e2e317a9eba2d1a24ca5d2e4576f86" integrity sha512-rUpMLATsoAMnlN3gecAcr9Ecnw1vG7zi5Xr+IX22YzRzi1k9PF9vKzoT8RuEJbiIszjcimu3rveqUnvwDopz8g== -"@sapphire/shapeshift@^3.4.1": - version "3.5.0" - resolved "https://registry.yarnpkg.com/@sapphire/shapeshift/-/shapeshift-3.5.0.tgz#3d5b9bdc29be0608f571db1781662b3fda438848" - integrity sha512-r6Iw3ZWgwzWcWDtsPwHKHnc6LCD84AqyXi1IolSS8TGLodTuggYxQ63V+Si5Jb7KVLhMYPCdlwM0HEDHEeZ9Iw== +"@sapphire/shapeshift@^3.5.1": + version "3.5.1" + resolved "https://registry.yarnpkg.com/@sapphire/shapeshift/-/shapeshift-3.5.1.tgz#3bfd0e6bcfdced4ac26a6f450b5f7b8e49f4f2cc" + integrity sha512-7JFsW5IglyOIUQI1eE0g6h06D/Far6HqpcowRScgCiLSqTf3hhkPWCWotVTtVycnDCMYIwPeaw6IEPBomKC8pA== dependencies: fast-deep-equal "^3.1.3" lodash.uniqwith "^4.5.0" @@ -212,6 +213,11 @@ resolved "https://registry.yarnpkg.com/@sapphire/snowflake/-/snowflake-3.2.2.tgz#faacdc1b5f7c43145a71eddba917de2b707ef780" integrity sha512-ula2O0kpSZtX9rKXNeQMrHwNd7E4jPDJYUXmEGTFdMRfyfMw+FPyh04oKMjAiDuOi64bYgVkOV3MjK+loImFhQ== +"@tokenizer/token@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" + integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -611,27 +617,27 @@ discord-api-types@^0.33.3: resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.33.5.tgz#6548b70520f7b944c60984dca4ab58654d664a12" integrity sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg== -discord-api-types@^0.36.1, discord-api-types@^0.36.2: +discord-api-types@^0.36.2: version "0.36.2" resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.36.2.tgz#2362bc544837be965ec99a5919f900c9699a7028" integrity sha512-TunPAvzwneK/m5fr4hxH3bMsrtI22nr9yjfHyo5NBGMjpsAauGNiGCmwoFf0oO3jSd2mZiKUvZwCKDaB166u2Q== -discord.js@14.0.0-dev.1657757514-fe34f48: - version "14.0.0-dev.1657757514-fe34f48" - resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.0.0-dev.1657757514-fe34f48.tgz#2aa0570fbb0995acaee205ee74f1b10af8042091" - integrity sha512-warixUTyz+NIyoTQht21Seo1bC1UPSRw3/b/uUtPB/BGu4e1X1orwcEP1wepQuwyqLIf8yo0vRJo21vRvwILvg== +discord.js@14.0.1: + version "14.0.1" + resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.0.1.tgz#2de95035294b361689ec1c9de935f0b6c21923b1" + integrity sha512-MZ2cvvk1WCpTUCLcchX5e/mBM22JCPAYle76qEuAfQfVTFdxE2YoKgRWMwWm6s/OJdkXyzglRWj405hg4vikEg== dependencies: - "@discordjs/builders" "^0.16.0-dev" - "@discordjs/collection" "^0.8.0-dev" - "@discordjs/rest" "^0.6.0-dev" + "@discordjs/builders" "^1.0.0" + "@discordjs/collection" "^1.0.0" + "@discordjs/rest" "^1.0.0" "@sapphire/snowflake" "^3.2.2" "@types/ws" "^8.5.3" - discord-api-types "^0.36.1" + discord-api-types "^0.36.2" fast-deep-equal "^3.1.3" lodash.snakecase "^4.1.1" tslib "^2.4.0" - undici "^5.6.0" - ws "^8.8.0" + undici "^5.7.0" + ws "^8.8.1" dotenv@^16.0.1: version "16.0.1" @@ -682,6 +688,15 @@ fecha@^4.2.0: resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== +file-type@^17.1.2: + version "17.1.2" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-17.1.2.tgz#9257437a64e0c3623f70d9f27430522d978b1384" + integrity sha512-3thBUSfa9YEUEGO/NAAiQGvjujZxZiJTF6xNwyDn6kB0NcEtwMn5ttkGG9jGwm/Nt/t8U1bpBNqyBNZCz4F4ig== + dependencies: + readable-web-to-node-stream "^3.0.2" + strtok3 "^7.0.0-alpha.7" + token-types "^5.0.0-alpha.2" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -815,6 +830,11 @@ i18n@^0.15.0: math-interval-parser "^2.0.1" mustache "^4.2.0" +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1139,6 +1159,11 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +peek-readable@^5.0.0-alpha.5: + version "5.0.0-alpha.5" + resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.0.0-alpha.5.tgz#ace5dfedf7bc33f17c9b5170b9d54f69a4fba79b" + integrity sha512-pJohF/tDwV3ntnT5+EkUo4E700q/j/OCDuPxtM+5/kFGjyOai/sK4/We4Cy1MB2OiTQliWU5DxPvYIKQAdPqAA== + picomatch@^2.0.4, picomatch@^2.2.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -1225,6 +1250,13 @@ readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-web-to-node-stream@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb" + integrity sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw== + dependencies: + readable-stream "^3.6.0" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -1395,6 +1427,14 @@ strip-json-comments@^2.0.0: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== +strtok3@^7.0.0-alpha.7: + version "7.0.0-alpha.8" + resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-7.0.0-alpha.8.tgz#23a7870974e0494b58b14af6dd1c2c67cf13314d" + integrity sha512-u+k19v+rTxBjGYxncRQjGvZYwYvEd0uP3D+uHKe/s4WB1eXS5ZwpZsTlBu5xSS4zEd89mTXECXg6WW3FSeV8cA== + dependencies: + "@tokenizer/token" "^0.3.0" + peek-readable "^5.0.0-alpha.5" + superagent@^5.2.1: version "5.3.1" resolved "https://registry.yarnpkg.com/superagent/-/superagent-5.3.1.tgz#d62f3234d76b8138c1320e90fa83dc1850ccabf1" @@ -1454,6 +1494,14 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +token-types@^5.0.0-alpha.2: + version "5.0.0-alpha.2" + resolved "https://registry.yarnpkg.com/token-types/-/token-types-5.0.0-alpha.2.tgz#e43d63b2a8223a593d1c782a5149bec18f1abf97" + integrity sha512-EsG9UxAW4M6VATrEEjhPFTKEUi1OiJqTUMIZOGBN49fGxYjZB36k0p7to3HZSmWRoHm1QfZgrg3e02fpqAt5fQ== + dependencies: + "@tokenizer/token" "^0.3.0" + ieee754 "^1.2.1" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -1544,7 +1592,7 @@ undici@^5.4.0: resolved "https://registry.yarnpkg.com/undici/-/undici-5.5.1.tgz#baaf25844a99eaa0b22e1ef8d205bffe587c8f43" integrity sha512-MEvryPLf18HvlCbLSzCW0U00IMftKGI5udnjrQbC5D4P0Hodwffhv+iGfWuJwg16Y/TK11ZFK8i+BPVW2z/eAw== -undici@^5.6.0: +undici@^5.7.0: version "5.7.0" resolved "https://registry.yarnpkg.com/undici/-/undici-5.7.0.tgz#979f89229c01505573cb274d0e11ea8d82b4004f" integrity sha512-ORgxwDkiPS+gK2VxE7iyVeR7JliVn5DqhZ4LgQqYLBXsuK+lwOEmnJ66dhvlpLM0tC3fC7eYF1Bti2frbw2eAA== @@ -1634,11 +1682,16 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@^8.7.0, ws@^8.8.0: +ws@^8.7.0: version "8.8.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.0.tgz#8e71c75e2f6348dbf8d78005107297056cb77769" integrity sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ== +ws@^8.8.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" + integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA== + xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" From ee13f3ce3f9fe2bc59c65b28b81f201912e446ba Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 18 Jul 2022 15:08:55 +0700 Subject: [PATCH 62/63] Code clean up --- src/discord/Developer/ServiceAnnouncement.ts | 2 +- src/discord/MusicPlayer/Play.ts | 1 - src/index.ts | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/discord/Developer/ServiceAnnouncement.ts b/src/discord/Developer/ServiceAnnouncement.ts index faddf89..12b78aa 100644 --- a/src/discord/Developer/ServiceAnnouncement.ts +++ b/src/discord/Developer/ServiceAnnouncement.ts @@ -1,4 +1,4 @@ -import { Message, EmbedBuilder, Interaction, CommandInteraction, TextChannel, BaseInteraction, EmbedData, EmbedFieldData, EmbedProviderData } from 'discord.js'; +import { Message, EmbedBuilder, CommandInteraction, TextChannel, EmbedData } from 'discord.js'; import { Promise } from 'bluebird'; import fs from 'fs'; import path from 'path'; diff --git a/src/discord/MusicPlayer/Play.ts b/src/discord/MusicPlayer/Play.ts index 08a9774..744f076 100644 --- a/src/discord/MusicPlayer/Play.ts +++ b/src/discord/MusicPlayer/Play.ts @@ -25,7 +25,6 @@ import { sendHybridInteractionMessageResponse, makeInfoEmbed } from '../../utils/DiscordMessage'; -import { SpotifyTrack, YouTubeVideo } from 'play-dl'; import { checkBotPermissionsInChannel } from '../../utils/DiscordPermission'; const EMBEDS = { diff --git a/src/index.ts b/src/index.ts index 39f61b1..0f22973 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,5 +10,4 @@ App.loadLocale(); App.loadDiscord(); App.load_osu(); - export default App; From b749da667cf57c1d375e2aae47c73c5ffb790d12 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Mon, 18 Jul 2022 15:09:07 +0700 Subject: [PATCH 63/63] Update embed --- src/discord/Developer/ServiceAnnouncement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/discord/Developer/ServiceAnnouncement.ts b/src/discord/Developer/ServiceAnnouncement.ts index 12b78aa..161347d 100644 --- a/src/discord/Developer/ServiceAnnouncement.ts +++ b/src/discord/Developer/ServiceAnnouncement.ts @@ -31,7 +31,7 @@ const EMBEDS = { fields: [ { name: 'Available arguments', - value: '``reload`` ``previewNews`` ``sendNews`` ``previewMaintenance`` ``sendMaintenance`` ``previewMessage`` ``sendMessage`` ``previewAlert`` ``sendAlert``' + value: '``Reload`` ``PreviewNews`` ``SendNews`` ``PreviewMaintenance`` ``SendMaintenance`` ``PreviewMessage`` ``SendMessage`` ``PreviewAlert`` ``SendAlert``' } ], user: data.getUser()