diff --git a/package-lock.json b/package-lock.json index 6882fde..f526582 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,15 +12,14 @@ "dependencies": { "canvas": "^2.7.0", "chalk": "^4.1.0", - "discord.js": "github:discordjs/discord.js", - "discord.js-lavalink-lib": "^0.1.8", + "discord.js": "^13.2.0", "figlet": "^1.5.0", "glob": "^7.1.6", "inquirer": "^7.3.3", "mathjs": "^9.3.0", "moment": "^2.29.1", "ms": "^2.1.3", - "onion-lasers": "^1.2.0-unstable.0", + "onion-lasers": "npm:onion-lasers-v13@^2.0.0", "pet-pet-gif": "^1.0.8", "relevant-urban": "^2.0.0", "translate-google": "^1.4.3", @@ -41,7 +40,7 @@ "rimraf": "^3.0.2", "ts-jest": "^26.4.4", "tsc-watch": "^4.2.9", - "typescript": "^4.2.4" + "typescript": "^4.4.4" }, "optionalDependencies": { "fsevents": "^2.1.2" @@ -572,10 +571,43 @@ "node": ">=0.1.95" } }, + "node_modules/@discordjs/builders": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.6.0.tgz", + "integrity": "sha512-mH3Gx61LKk2CD05laCI9K5wp+a3NyASHDUGx83DGJFkqJlRlSV5WMJNY6RS37A5SjqDtGMF4wVR9jzFaqShe6Q==", + "dependencies": { + "@sindresorhus/is": "^4.0.1", + "discord-api-types": "^0.22.0", + "ow": "^0.27.0", + "ts-mixer": "^6.0.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@discordjs/builders/node_modules/discord-api-types": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz", + "integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@discordjs/builders/node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, "node_modules/@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.4.tgz", + "integrity": "sha512-PVrEJH+V6Ob0OwfagYQ/57kwt/HNEJxt5jqY4P+S3st9y29t9iokdnGMQoJXG5VEMAQIPbzu9Snw1F6yE8PdLA==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } }, "node_modules/@discordjs/form-data": { "version": "3.0.1", @@ -842,21 +874,6 @@ "node": ">= 10.14.2" } }, - "node_modules/@lavacord/discord.js": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@lavacord/discord.js/-/discord.js-0.0.5.tgz", - "integrity": "sha512-qc2lw0zB48fq4SrSlpMJOmogUXIeM5YvufQfPg0ubjp7jqm20JnOXF9fliy1MPdcKPnZ8LwIZ222H0+ghGzP/Q==", - "dependencies": { - "lavacord": "latest" - }, - "engines": { - "node": ">=10", - "npm": ">=5" - }, - "peerDependencies": { - "discord.js": "^12.1.1" - } - }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", @@ -876,10 +893,54 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@sapphire/async-queue": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.8.tgz", + "integrity": "sha512-Oi4EEi8vOne8RM1tCdQ3kYAtl/J6ztak3Th6wwGFqA2SVNJtedw196LjsLX0bK8Li8cwaljbFf08N+0zeqhkWQ==", + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", + "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==", "engines": { "node": ">=10" }, @@ -1146,17 +1207,6 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/acorn": { "version": "8.2.4", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.4.tgz", @@ -1519,14 +1569,6 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, - "node_modules/axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", - "dependencies": { - "follow-redirects": "^1.10.0" - } - }, "node_modules/babel-jest": { "version": "26.6.3", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", @@ -1849,7 +1891,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -2347,32 +2388,71 @@ "node": ">= 10.14.2" } }, - "node_modules/discord.js": { - "version": "12.5.0", - "resolved": "git+ssh://git@github.com/discordjs/discord.js.git#ab82cafcde0ee259a32ef14303c1b4a64dea8fae", - "license": "Apache-2.0", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "dependencies": { - "@discordjs/collection": "^0.1.6", - "@discordjs/form-data": "^3.0.1", - "abort-controller": "^3.0.0", - "node-fetch": "^2.6.1", - "prism-media": "^1.2.2", - "tweetnacl": "^1.0.3", - "ws": "^7.3.1" + "path-type": "^4.0.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=8" } }, - "node_modules/discord.js-lavalink-lib": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/discord.js-lavalink-lib/-/discord.js-lavalink-lib-0.1.8.tgz", - "integrity": "sha512-Kv4ps5AW4xYxMuJypHJrPL1occlV817CjHiIL7J09EdgzNRcKRIif0U6XMxWxi45Pg3DOl41Lw1V+J2GRsMgcw==", + "node_modules/discord-api-types": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.23.1.tgz", + "integrity": "sha512-igWmn+45mzXRWNEPU25I/pr8MwxHb767wAr51oy3VRLRcTlp5ADBbrBR0lq3SA1Rfw3MtM4TQu1xo3kxscfVdQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/discord.js": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.2.0.tgz", + "integrity": "sha512-nyxUvL8wuQG38zx13wUMkpcA8koFszyiXdkSLwwM9opKW2LC2H5gD0cTZxImeJ6GtEnKPWT8xBiE8lLBmbNIhw==", "dependencies": { - "@lavacord/discord.js": "0.0.5", - "axios": ">=0.21.1", - "discord.js": "^12.2.0", - "lavacord": "^1.1.7" + "@discordjs/builders": "^0.6.0", + "@discordjs/collection": "^0.2.1", + "@discordjs/form-data": "^3.0.1", + "@sapphire/async-queue": "^1.1.5", + "@types/ws": "^8.2.0", + "discord-api-types": "^0.23.1", + "node-fetch": "^2.6.1", + "ws": "^8.2.3" + }, + "engines": { + "node": ">=16.6.0", + "npm": ">=7.0.0" + } + }, + "node_modules/discord.js/node_modules/@types/ws": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.0.tgz", + "integrity": "sha512-cyeefcUCgJlEk+hk2h3N+MqKKsPViQgF5boi9TTHSK+PoR9KWBb/C5ccPcDyAqgsbAYHTwulch725DV84+pSpg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/discord.js/node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/docopt": { @@ -2573,14 +2653,6 @@ "through": "~2.3.1" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/exec-sh": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", @@ -2879,6 +2951,174 @@ } } }, + "node_modules/findup-sync/node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -4657,17 +4897,128 @@ "node": ">=6" } }, - "node_modules/lavacord": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/lavacord/-/lavacord-1.1.9.tgz", - "integrity": "sha512-haZghbblO1w3Hodc9q63ZWgV5zA/jB6xFKS17fImK5aIdn0PkKuZ6AsJBxMFpR275v8GNYOxg6cTQBYBQ+batQ==", + "node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, "dependencies": { - "node-fetch": "^2.6.0", - "ws": "^7.3.0" + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" }, "engines": { - "node": ">=10", - "npm": ">=5" + "node": ">= 0.10" + } + }, + "node_modules/lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/liftoff/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/leven": { @@ -4720,6 +5071,11 @@ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -5405,11 +5761,12 @@ } }, "node_modules/onion-lasers": { - "version": "1.2.0-unstable.0", - "resolved": "https://registry.npmjs.org/onion-lasers/-/onion-lasers-1.2.0-unstable.0.tgz", - "integrity": "sha512-seKXo0CouLNNp2p/M0eORqQ56eJ6MNJe1dSXCI251we8OMJTI5+qRpzB1+OhR2/G4zRkNuWb2aXTUPYNsmVZrA==", + "name": "onion-lasers-v13", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/onion-lasers-v13/-/onion-lasers-v13-2.0.0.tgz", + "integrity": "sha512-HtMNLvFqSVt9mFkUJX7rwnH4d0894YmQ7167lLdtE8Wi/U2HYRSHHpB4xcLXrOPMMzcWZ4l+1knYN1OL0nL9mA==", "dependencies": { - "discord.js": "github:discordjs/discord.js", + "discord.js": "^13.2.0", "glob": "^7.1.6" } }, @@ -5438,6 +5795,50 @@ "node": ">=0.10.0" } }, + "node_modules/ow": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", + "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", + "dependencies": { + "@sindresorhus/is": "^4.0.1", + "callsites": "^3.1.0", + "dot-prop": "^6.0.1", + "lodash.isequal": "^4.5.0", + "type-fest": "^1.2.1", + "vali-date": "^1.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ow/node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ow/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -5672,29 +6073,13 @@ "node": ">= 10" } }, - "node_modules/prism-media": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.9.tgz", - "integrity": "sha512-UHCYuqHipbTR1ZsXr5eg4JUmHER8Ss4YEb9Azn+9zzJ7/jlTtD1h0lc4g6tNx3eMlB8Mp6bfll0LPMAV4R6r3Q==", - "peerDependencies": { - "@discordjs/opus": "^0.5.0", - "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0", - "node-opus": "^0.3.3", - "opusscript": "^0.0.8" - }, - "peerDependenciesMeta": { - "@discordjs/opus": { - "optional": true - }, - "ffmpeg-static": { - "optional": true - }, - "node-opus": { - "optional": true - }, - "opusscript": { - "optional": true - } + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true, + "engines": { + "node": ">= 0.8" } }, "node_modules/process-nextick-args": { @@ -7368,6 +7753,11 @@ "typescript": ">=3.8 <5.0" } }, + "node_modules/ts-mixer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", + "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" + }, "node_modules/tsc-watch": { "version": "4.2.9", "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-4.2.9.tgz", @@ -7406,10 +7796,11 @@ "node": "*" } }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true }, "node_modules/type-check": { "version": "0.3.2", @@ -7460,9 +7851,9 @@ } }, "node_modules/typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -7639,6 +8030,26 @@ "node": ">= 8" } }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -7830,6 +8241,7 @@ "version": "7.4.5", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", + "dev": true, "engines": { "node": ">=8.3.0" }, @@ -8353,10 +8765,34 @@ "minimist": "^1.2.0" } }, + "@discordjs/builders": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.6.0.tgz", + "integrity": "sha512-mH3Gx61LKk2CD05laCI9K5wp+a3NyASHDUGx83DGJFkqJlRlSV5WMJNY6RS37A5SjqDtGMF4wVR9jzFaqShe6Q==", + "requires": { + "@sindresorhus/is": "^4.0.1", + "discord-api-types": "^0.22.0", + "ow": "^0.27.0", + "ts-mixer": "^6.0.0", + "tslib": "^2.3.1" + }, + "dependencies": { + "discord-api-types": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz", + "integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==" + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, "@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.4.tgz", + "integrity": "sha512-PVrEJH+V6Ob0OwfagYQ/57kwt/HNEJxt5jqY4P+S3st9y29t9iokdnGMQoJXG5VEMAQIPbzu9Snw1F6yE8PdLA==" }, "@discordjs/form-data": { "version": "3.0.1", @@ -8579,14 +9015,6 @@ "chalk": "^4.0.0" } }, - "@lavacord/discord.js": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@lavacord/discord.js/-/discord.js-0.0.5.tgz", - "integrity": "sha512-qc2lw0zB48fq4SrSlpMJOmogUXIeM5YvufQfPg0ubjp7jqm20JnOXF9fliy1MPdcKPnZ8LwIZ222H0+ghGzP/Q==", - "requires": { - "lavacord": "latest" - } - }, "@mapbox/node-pre-gyp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", @@ -8603,10 +9031,41 @@ "tar": "^6.1.0" } }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, + "@sapphire/async-queue": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.8.tgz", + "integrity": "sha512-Oi4EEi8vOne8RM1tCdQ3kYAtl/J6ztak3Th6wwGFqA2SVNJtedw196LjsLX0bK8Li8cwaljbFf08N+0zeqhkWQ==" + }, "@sindresorhus/is": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", - "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", + "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==" }, "@sinonjs/commons": { "version": "1.8.3", @@ -8864,14 +9323,6 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, "acorn": { "version": "8.2.4", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.4.tgz", @@ -9144,14 +9595,6 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, - "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", - "requires": { - "follow-redirects": "^1.10.0" - } - }, "babel-jest": { "version": "26.6.3", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", @@ -9413,8 +9856,7 @@ "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, "camelcase": { "version": "5.3.1", @@ -9793,28 +10235,49 @@ "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", "dev": true }, - "discord.js": { - "version": "git+ssh://git@github.com/discordjs/discord.js.git#ab82cafcde0ee259a32ef14303c1b4a64dea8fae", - "from": "discord.js@github:discordjs/discord.js", + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "requires": { - "@discordjs/collection": "^0.1.6", - "@discordjs/form-data": "^3.0.1", - "abort-controller": "^3.0.0", - "node-fetch": "^2.6.1", - "prism-media": "^1.2.2", - "tweetnacl": "^1.0.3", - "ws": "^7.3.1" + "path-type": "^4.0.0" } }, - "discord.js-lavalink-lib": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/discord.js-lavalink-lib/-/discord.js-lavalink-lib-0.1.8.tgz", - "integrity": "sha512-Kv4ps5AW4xYxMuJypHJrPL1occlV817CjHiIL7J09EdgzNRcKRIif0U6XMxWxi45Pg3DOl41Lw1V+J2GRsMgcw==", + "discord-api-types": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.23.1.tgz", + "integrity": "sha512-igWmn+45mzXRWNEPU25I/pr8MwxHb767wAr51oy3VRLRcTlp5ADBbrBR0lq3SA1Rfw3MtM4TQu1xo3kxscfVdQ==" + }, + "discord.js": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.2.0.tgz", + "integrity": "sha512-nyxUvL8wuQG38zx13wUMkpcA8koFszyiXdkSLwwM9opKW2LC2H5gD0cTZxImeJ6GtEnKPWT8xBiE8lLBmbNIhw==", "requires": { - "@lavacord/discord.js": "0.0.5", - "axios": ">=0.21.1", - "discord.js": "^12.2.0", - "lavacord": "^1.1.7" + "@discordjs/builders": "^0.6.0", + "@discordjs/collection": "^0.2.1", + "@discordjs/form-data": "^3.0.1", + "@sapphire/async-queue": "^1.1.5", + "@types/ws": "^8.2.0", + "discord-api-types": "^0.23.1", + "node-fetch": "^2.6.1", + "ws": "^8.2.3" + }, + "dependencies": { + "@types/ws": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.0.tgz", + "integrity": "sha512-cyeefcUCgJlEk+hk2h3N+MqKKsPViQgF5boi9TTHSK+PoR9KWBb/C5ccPcDyAqgsbAYHTwulch725DV84+pSpg==", + "requires": { + "@types/node": "*" + } + }, + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "requires": {} + } } }, "docopt": { @@ -9968,11 +10431,6 @@ "through": "~2.3.1" } }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, "exec-sh": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", @@ -10199,10 +10657,153 @@ "path-exists": "^4.0.0" } }, - "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } }, "for-in": { "version": "1.0.2", @@ -11597,13 +12198,41 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, - "lavacord": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/lavacord/-/lavacord-1.1.9.tgz", - "integrity": "sha512-haZghbblO1w3Hodc9q63ZWgV5zA/jB6xFKS17fImK5aIdn0PkKuZ6AsJBxMFpR275v8GNYOxg6cTQBYBQ+batQ==", + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, "requires": { - "node-fetch": "^2.6.0", - "ws": "^7.3.0" + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" } }, "leven": { @@ -11647,6 +12276,11 @@ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -12182,11 +12816,11 @@ } }, "onion-lasers": { - "version": "1.2.0-unstable.0", - "resolved": "https://registry.npmjs.org/onion-lasers/-/onion-lasers-1.2.0-unstable.0.tgz", - "integrity": "sha512-seKXo0CouLNNp2p/M0eORqQ56eJ6MNJe1dSXCI251we8OMJTI5+qRpzB1+OhR2/G4zRkNuWb2aXTUPYNsmVZrA==", + "version": "npm:onion-lasers-v13@2.0.0", + "resolved": "https://registry.npmjs.org/onion-lasers-v13/-/onion-lasers-v13-2.0.0.tgz", + "integrity": "sha512-HtMNLvFqSVt9mFkUJX7rwnH4d0894YmQ7167lLdtE8Wi/U2HYRSHHpB4xcLXrOPMMzcWZ4l+1knYN1OL0nL9mA==", "requires": { - "discord.js": "github:discordjs/discord.js", + "discord.js": "^13.2.0", "glob": "^7.1.6" } }, @@ -12209,6 +12843,34 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, + "ow": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", + "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", + "requires": { + "@sindresorhus/is": "^4.0.1", + "callsites": "^3.1.0", + "dot-prop": "^6.0.1", + "lodash.isequal": "^4.5.0", + "type-fest": "^1.2.1", + "vali-date": "^1.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "requires": { + "is-obj": "^2.0.0" + } + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==" + } + } + }, "p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -12374,11 +13036,11 @@ "react-is": "^17.0.1" } }, - "prism-media": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.9.tgz", - "integrity": "sha512-UHCYuqHipbTR1ZsXr5eg4JUmHER8Ss4YEb9Azn+9zzJ7/jlTtD1h0lc4g6tNx3eMlB8Mp6bfll0LPMAV4R6r3Q==", - "requires": {} + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true }, "process-nextick-args": { "version": "2.0.1", @@ -13700,6 +14362,11 @@ "yargs-parser": "20.x" } }, + "ts-mixer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", + "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" + }, "tsc-watch": { "version": "4.2.9", "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-4.2.9.tgz", @@ -13726,10 +14393,11 @@ "safe-buffer": "^5.0.1" } }, - "tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true }, "type-check": { "version": "0.3.2", @@ -13765,9 +14433,9 @@ } }, "typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", "dev": true }, "underscore": { @@ -13909,6 +14577,20 @@ } } }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -14069,6 +14751,7 @@ "version": "7.4.5", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", + "dev": true, "requires": {} }, "xdg-basedir": { diff --git a/package.json b/package.json index ead310f..a6721c6 100644 --- a/package.json +++ b/package.json @@ -12,20 +12,19 @@ "dev-instance": "rimraf dist && tsc && node . dev", "test": "jest", "format": "prettier --write **/*", - "postinstall": "node patch.js && husky install" + "postinstall": "husky install" }, "dependencies": { "canvas": "^2.7.0", "chalk": "^4.1.0", - "discord.js": "github:discordjs/discord.js", - "discord.js-lavalink-lib": "^0.1.8", + "discord.js": "^13.2.0", "figlet": "^1.5.0", "glob": "^7.1.6", "inquirer": "^7.3.3", "mathjs": "^9.3.0", "moment": "^2.29.1", "ms": "^2.1.3", - "onion-lasers": "^1.2.0-unstable.0", + "onion-lasers": "npm:onion-lasers-v13@^2.0.0", "pet-pet-gif": "^1.0.8", "relevant-urban": "^2.0.0", "translate-google": "^1.4.3", @@ -46,7 +45,7 @@ "rimraf": "^3.0.2", "ts-jest": "^26.4.4", "tsc-watch": "^4.2.9", - "typescript": "^4.2.4" + "typescript": "^4.4.4" }, "optionalDependencies": { "fsevents": "^2.1.2" diff --git a/patch.js b/patch.js deleted file mode 100644 index 3338d00..0000000 --- a/patch.js +++ /dev/null @@ -1,23 +0,0 @@ -// This is a nightmarishly bad way to handle module patches... but oh well, it's on the unstable branch for a reason. -const fs = require("fs"); -const DECLARATION_FILE = "node_modules/discord.js/typings/index.d.ts"; - -fs.readFile(DECLARATION_FILE, "utf-8", (err, data) => { - if (err) console.error(err); - else { - const declaration = data.split(/\r?\n/); - - // "discord-api-types/v8" is apparently not found so just ignore it to get the typings to work. - for (let i = 0; i < declaration.length; i++) { - const line = declaration[i]; - - if (line.includes("@ts-ignore")) { - break; - } else if (line.includes("discord-api-types/v8")) { - declaration.splice(i, 0, "// @ts-ignore"); - fs.writeFile(DECLARATION_FILE, declaration.join("\n"), () => {}); - break; - } - } - } -}); diff --git a/src/commands/fun/figlet.ts b/src/commands/fun/figlet.ts index 8764ff4..ae97069 100644 --- a/src/commands/fun/figlet.ts +++ b/src/commands/fun/figlet.ts @@ -1,5 +1,6 @@ import {NamedCommand, RestCommand} from "onion-lasers"; import figlet from "figlet"; +import {Util} from "discord.js"; export default new NamedCommand({ description: "Generates a figlet of your input.", @@ -7,12 +8,11 @@ export default new NamedCommand({ any: new RestCommand({ async run({send, combined}) { return send( - figlet.textSync(combined, { - horizontalLayout: "full" - }), - { - code: true - } + `\`\`\`\n${Util.cleanCodeBlockContent( + figlet.textSync(combined, { + horizontalLayout: "full" + }) + )}\n\`\`\`` ); } }) diff --git a/src/commands/fun/insult.ts b/src/commands/fun/insult.ts index 76491b3..05603d9 100644 --- a/src/commands/fun/insult.ts +++ b/src/commands/fun/insult.ts @@ -3,12 +3,12 @@ import {NamedCommand} from "onion-lasers"; export default new NamedCommand({ description: "Insult TravBot! >:D", async run({send, channel, author}) { - channel.startTyping(); + channel.sendTyping(); setTimeout(() => { send( `${author} What the fuck did you just fucking say about me, you little bitch? I'll have you know I graduated top of my class in the Navy Seals, and I've been involved in numerous secret raids on Al-Quaeda, and I have over 300 confirmed kills. I am trained in gorilla warfare and I'm the top sniper in the entire US armed forces. You are nothing to me but just another target. I will wipe you the fuck out with precision the likes of which has never been seen before on this Earth, mark my fucking words. You think you can get away with saying that shit to me over the Internet? Think again, fucker. As we speak I am contacting my secret network of spies across the USA and your IP is being traced right now so you better prepare for the storm, maggot. The storm that wipes out the pathetic little thing you call your life. You're fucking dead, kid. I can be anywhere, anytime, and I can kill you in over seven hundred ways, and that's just with my bare hands. Not only am I extensively trained in unarmed combat, but I have access to the entire arsenal of the United States Marine Corps and I will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit. If only you could have known what unholy retribution your little "clever" comment was about to bring down upon you, maybe you would have held your fucking tongue. But you couldn't, you didn't, and now you're paying the price, you goddamn idiot. I will shit fury all over you and you will drown in it. You're fucking dead, kiddo.` ); - channel.stopTyping(); + channel.sendTyping(); }, 60000); } }); diff --git a/src/commands/fun/modules/eco-bet.ts b/src/commands/fun/modules/eco-bet.ts index 0fb6096..9852f6a 100644 --- a/src/commands/fun/modules/eco-bet.ts +++ b/src/commands/fun/modules/eco-bet.ts @@ -39,9 +39,12 @@ export const BetCommand = new NamedCommand({ // handle invalid amount if (amount <= 0) return send("You must bet at least one Mon!"); else if (sender.money < amount) - return send("You don't have enough Mons for that.", getMoneyEmbed(author)); + return send({content: "You don't have enough Mons for that.", embeds: [getMoneyEmbed(author)]}); else if (receiver.money < amount) - return send("They don't have enough Mons for that.", getMoneyEmbed(target)); + return send({ + content: "They don't have enough Mons for that.", + embeds: [getMoneyEmbed(target)] + }); return send("How long until the bet ends?"); } else return; @@ -67,9 +70,15 @@ export const BetCommand = new NamedCommand({ // handle invalid amount if (amount <= 0) return send("You must bet at least one Mon!"); else if (sender.money < amount) - return send("You don't have enough Mons for that.", getMoneyEmbed(author)); + return send({ + content: "You don't have enough Mons for that.", + embeds: [getMoneyEmbed(author)] + }); else if (receiver.money < amount) - return send("They don't have enough Mons for that.", getMoneyEmbed(target)); + return send({ + content: "They don't have enough Mons for that.", + embeds: [getMoneyEmbed(target)] + }); // handle invalid duration if (duration <= 0) return send("Invalid bet duration"); @@ -107,7 +116,7 @@ export const BetCommand = new NamedCommand({ ); // Wait for the duration of the bet. - return client.setTimeout(async () => { + return setTimeout(async () => { // In debug mode, saving the storage will break the references, so you have to redeclare sender and receiver for it to actually save. const sender = Storage.getUser(author.id); const receiver = Storage.getUser(target.id); diff --git a/src/commands/fun/modules/eco-core.ts b/src/commands/fun/modules/eco-core.ts index 388f576..841b736 100644 --- a/src/commands/fun/modules/eco-core.ts +++ b/src/commands/fun/modules/eco-core.ts @@ -16,27 +16,26 @@ export const DailyCommand = new NamedCommand({ user.lastReceived = now; Storage.save(); send({ - embed: { - title: "Daily Reward", - description: "You received 1 Mon!", - color: ECO_EMBED_COLOR, - fields: [ - { - name: "New balance:", - value: pluralise(user.money, "Mon", "s") - } - ] - } + embeds: [ + { + title: "Daily Reward", + description: "You received 1 Mon!", + color: ECO_EMBED_COLOR + } + ] }); } else send({ - embed: { - title: "Daily Reward", - description: `It's too soon to pick up your daily Mons. Try again at .`, - color: ECO_EMBED_COLOR - } + embeds: [ + { + title: "Daily Reward", + description: `It's too soon to pick up your daily Mons. You have about ${( + (user.lastReceived + 79200000 - now) / + 3600000 + ).toFixed(1)} hours to go.`, + color: ECO_EMBED_COLOR + } + ] }); } } @@ -55,25 +54,27 @@ export const GuildCommand = new NamedCommand({ } send({ - embed: { - title: `The Bank of ${guild!.name}`, - color: ECO_EMBED_COLOR, - fields: [ - { - name: "Accounts", - value: Object.keys(users).length, - inline: true - }, - { - name: "Total Mons", - value: totalAmount, - inline: true + embeds: [ + { + title: `The Bank of ${guild!.name}`, + color: ECO_EMBED_COLOR, + fields: [ + { + name: "Accounts", + value: Object.keys(users).length.toString(), + inline: true + }, + { + name: "Total Mons", + value: totalAmount.toString(), + inline: true + } + ], + thumbnail: { + url: guild?.iconURL() ?? "" } - ], - thumbnail: { - url: guild?.iconURL() ?? "" } - } + ] }); } } @@ -100,14 +101,16 @@ export const LeaderboardCommand = new NamedCommand({ } send({ - embed: { - title: "Top 10 Richest Players", - color: ECO_EMBED_COLOR, - fields: fields, - thumbnail: { - url: guild?.iconURL() ?? "" + embeds: [ + { + title: "Top 10 Richest Players", + color: ECO_EMBED_COLOR, + fields: fields, + thumbnail: { + url: guild?.iconURL() ?? "" + } } - } + ] }); } } @@ -130,7 +133,7 @@ export const PayCommand = new NamedCommand({ if (amount <= 0) return send("You must send at least one Mon!"); else if (sender.money < amount) - return send("You don't have enough Mons for that.", getMoneyEmbed(author)); + return send({content: "You don't have enough Mons for that.", embeds: [getMoneyEmbed(author)]}); else if (target.id === author.id) return send("You can't send Mons to yourself!"); else if (target.bot && !IS_DEV_MODE) return send("You can't send Mons to a bot!"); @@ -157,7 +160,7 @@ export const PayCommand = new NamedCommand({ if (amount <= 0) return send("You must send at least one Mon!"); else if (sender.money < amount) - return send("You don't have enough Mons to do that!", getMoneyEmbed(author)); + return send({content: "You don't have enough Mons to do that!", embeds: [getMoneyEmbed(author)]}); else if (!guild) return send("You have to use this in a server if you want to send Mons with a username!"); @@ -168,17 +171,20 @@ export const PayCommand = new NamedCommand({ else if (user.bot && !IS_DEV_MODE) return send("You can't send Mons to a bot!"); const confirmed = await confirm( - await send(`Are you sure you want to send ${pluralise(amount, "Mon", "s")} to this person?`, { - embed: { - color: ECO_EMBED_COLOR, - author: { - name: user.tag, - icon_url: user.displayAvatarURL({ - format: "png", - dynamic: true - }) + await send({ + content: `Are you sure you want to send ${pluralise(amount, "Mon", "s")} to this person?`, + embeds: [ + { + color: ECO_EMBED_COLOR, + author: { + name: user.tag, + icon_url: user.displayAvatarURL({ + format: "png", + dynamic: true + }) + } } - } + ] }), author.id ); diff --git a/src/commands/fun/modules/eco-extras.ts b/src/commands/fun/modules/eco-extras.ts index d3a3519..35a46b4 100644 --- a/src/commands/fun/modules/eco-extras.ts +++ b/src/commands/fun/modules/eco-extras.ts @@ -21,7 +21,7 @@ export const MondayCommand = new NamedCommand({ user.money++; user.lastMonday = now.getTime(); Storage.save(); - send("It is **Mon**day, my dudes.", getMoneyEmbed(author)); + send({content: "It is **Mon**day, my dudes.", embeds: [getMoneyEmbed(author)]}); } else send("You've already claimed your **Mon**day reward for this week."); } else { const weekdayName = WEEKDAY[weekday]; @@ -47,7 +47,7 @@ export const AwardCommand = new NamedCommand({ const user = Storage.getUser(target.id); user.money++; Storage.save(); - send(`1 Mon given to ${target.username}.`, getMoneyEmbed(target)); + send({content: `1 Mon given to ${target.username}.`, embeds: [getMoneyEmbed(target)]}); } else { send("This command is restricted to the bean."); } @@ -62,7 +62,10 @@ export const AwardCommand = new NamedCommand({ const user = Storage.getUser(target.id); user.money += amount; Storage.save(); - send(`${pluralise(amount, "Mon", "s")} given to ${target.username}.`, getMoneyEmbed(target)); + send({ + content: `${pluralise(amount, "Mon", "s")} given to ${target.username}.`, + embeds: [getMoneyEmbed(target)] + }); } else { send("You need to enter a number greater than 0."); } diff --git a/src/commands/fun/modules/eco-shop-items.ts b/src/commands/fun/modules/eco-shop-items.ts index f3cf143..bc5d58c 100644 --- a/src/commands/fun/modules/eco-shop-items.ts +++ b/src/commands/fun/modules/eco-shop-items.ts @@ -52,7 +52,8 @@ export const ShopItems: ShopItem[] = [ description: "Buys what is technically a laser bridge.", usage: "laser bridge", run(message) { - message.channel.send(random(lines), { + message.channel.send({ + content: random(lines), files: [ { attachment: diff --git a/src/commands/fun/modules/eco-shop.ts b/src/commands/fun/modules/eco-shop.ts index 8092854..ec36820 100644 --- a/src/commands/fun/modules/eco-shop.ts +++ b/src/commands/fun/modules/eco-shop.ts @@ -3,13 +3,13 @@ import {pluralise, split} from "../../../lib"; import {Storage, getPrefix} from "../../../structures"; import {isAuthorized, ECO_EMBED_COLOR} from "./eco-utils"; import {ShopItems, ShopItem} from "./eco-shop-items"; -import {EmbedField} from "discord.js"; +import {EmbedField, MessageEmbedOptions} from "discord.js"; export const ShopCommand = new NamedCommand({ description: "Displays the list of items you can buy in the shop.", async run({send, guild, channel, author}) { if (isAuthorized(guild, channel)) { - function getShopEmbed(selection: ShopItem[], title: string) { + function getShopEmbed(selection: ShopItem[], title: string): MessageEmbedOptions { const fields: EmbedField[] = []; for (const item of selection) @@ -20,13 +20,11 @@ export const ShopCommand = new NamedCommand({ }); return { - embed: { - color: ECO_EMBED_COLOR, - title: title, - fields: fields, - footer: { - text: "Mon Shop | TravBot Services" - } + color: ECO_EMBED_COLOR, + title: title, + fields: fields, + footer: { + text: "Mon Shop | TravBot Services" } }; } @@ -35,10 +33,14 @@ export const ShopCommand = new NamedCommand({ const pageAmount = shopPages.length; paginate(send, author.id, pageAmount, (page, hasMultiplePages) => { - return getShopEmbed( - shopPages[page], - hasMultiplePages ? `Shop (Page ${page + 1} of ${pageAmount})` : "Shop" - ); + return { + embeds: [ + getShopEmbed( + shopPages[page], + hasMultiplePages ? `Shop (Page ${page + 1} of ${pageAmount})` : "Shop" + ) + ] + }; }); } } diff --git a/src/commands/fun/modules/eco-utils.ts b/src/commands/fun/modules/eco-utils.ts index 08ef031..53bc7f4 100644 --- a/src/commands/fun/modules/eco-utils.ts +++ b/src/commands/fun/modules/eco-utils.ts @@ -1,6 +1,6 @@ import {pluralise} from "../../../lib"; import {Storage} from "../../../structures"; -import {User, Guild, TextChannel, DMChannel, NewsChannel} from "discord.js"; +import {User, Guild, TextChannel, DMChannel, NewsChannel, Channel, TextBasedChannels} from "discord.js"; export const ECO_EMBED_COLOR = 0xf1c40f; @@ -61,18 +61,10 @@ export function getSendEmbed(sender: User, receiver: User, amount: number): obje }; } -export function isAuthorized(guild: Guild | null, channel: TextChannel | DMChannel | NewsChannel): boolean { - if (IS_DEV_MODE) { - return true; - } - - if (guild?.id !== "637512823676600330") { - channel.send("Sorry, this command can only be used in Monika's emote server."); +export function isAuthorized(guild: Guild | null, channel: TextBasedChannels): boolean { + if ((guild?.id === "637512823676600330" && channel?.id === "669464416420364288") || IS_DEV_MODE) return true; + else { + channel.send("Sorry, this command can only be used in Monika's emote server. (#mon-stocks)"); return false; - } else if (channel?.id !== "669464416420364288") { - channel.send("Sorry, this command can only be used in <#669464416420364288>."); - return false; - } else { - return true; } } diff --git a/src/commands/fun/pat.ts b/src/commands/fun/pat.ts index f60b41b..a1e91fb 100644 --- a/src/commands/fun/pat.ts +++ b/src/commands/fun/pat.ts @@ -10,11 +10,11 @@ export default new NamedCommand({ const attachment = message.attachments.first()!; const gif = await petPetGif(attachment.url); const file = new MessageAttachment(gif, "pat.gif"); - send(file); + send({attachments: [file]}); } else { const gif = await petPetGif(author.displayAvatarURL({format: "png"})); const file = new MessageAttachment(gif, "pat.gif"); - send(file); + send({attachments: [file]}); } }, id: "user", @@ -24,7 +24,7 @@ export default new NamedCommand({ const user: User = args[0]; const gif = await petPetGif(user.displayAvatarURL({format: "png"})); const file = new MessageAttachment(gif, "pat.gif"); - send(file); + send({attachments: [file]}); } }), any: new RestCommand({ @@ -36,7 +36,7 @@ export default new NamedCommand({ else { const gif = await petPetGif(user.displayAvatarURL({format: "png"})); const file = new MessageAttachment(gif, "pat.gif"); - send(file); + send({attachments: [file]}); } } }) diff --git a/src/commands/fun/poll.ts b/src/commands/fun/poll.ts index 5cfd446..40f9287 100644 --- a/src/commands/fun/poll.ts +++ b/src/commands/fun/poll.ts @@ -33,26 +33,35 @@ async function execPoll(send: SendFunction, message: Message, user: User, questi dynamic: true, size: 2048 }) || user.defaultAvatarURL; - const msg = await send( - new MessageEmbed() - .setAuthor(`Poll created by ${message.author.username}`, icon) - .setColor(0xffffff) - .setFooter("React to vote.") - .setDescription(question) - ); + const msg = await send({ + embeds: [ + new MessageEmbed() + .setAuthor(`Poll created by ${message.author.username}`, icon) + .setColor(0xffffff) + .setFooter("React to vote.") + .setDescription(question) + ] + }); const results = await poll(msg, [AGREE, DISAGREE], duration); - send( - new MessageEmbed() - .setAuthor(`The results of ${message.author.username}'s poll:`, icon) - .setTitle(question) - .setDescription( - `${AGREE} - ${pluralise( - results[AGREE], - "", - "people who agree", - "person who agrees" - )}\n${DISAGREE} - ${pluralise(results[DISAGREE], "", "people who disagree", "person who disagrees")}` - ) - ); + send({ + embeds: [ + new MessageEmbed() + .setAuthor(`The results of ${message.author.username}'s poll:`, icon) + .setTitle(question) + .setDescription( + `${AGREE} - ${pluralise( + results[AGREE], + "", + "people who agree", + "person who agrees" + )}\n${DISAGREE} - ${pluralise( + results[DISAGREE], + "", + "people who disagree", + "person who disagrees" + )}` + ) + ] + }); msg.delete(); } diff --git a/src/commands/fun/ravi.ts b/src/commands/fun/ravi.ts index b1b0b4c..d5ef2ef 100644 --- a/src/commands/fun/ravi.ts +++ b/src/commands/fun/ravi.ts @@ -6,15 +6,17 @@ export default new NamedCommand({ usage: "[number from 1 to 9]", async run({send}) { send({ - embed: { - title: "Ravioli ravioli...", - image: { - url: `https://raw.githubusercontent.com/keanuplayz/TravBot/master/assets/ravi${Random.int( - 1, - 10 - )}.png` + embeds: [ + { + title: "Ravioli ravioli...", + image: { + url: `https://raw.githubusercontent.com/keanuplayz/TravBot/master/assets/ravi${Random.int( + 1, + 10 + )}.png` + } } - } + ] }); }, number: new Command({ @@ -23,12 +25,14 @@ export default new NamedCommand({ if (arg >= 1 && arg <= 9) { send({ - embed: { - title: "Ravioli ravioli...", - image: { - url: `https://raw.githubusercontent.com/keanuplayz/TravBot/master/assets/ravi${arg}.png` + embeds: [ + { + title: "Ravioli ravioli...", + image: { + url: `https://raw.githubusercontent.com/keanuplayz/TravBot/master/assets/ravi${arg}.png` + } } - } + ] }); } else { send("Please provide a number between 1 and 9."); diff --git a/src/commands/fun/thonk.ts b/src/commands/fun/thonk.ts index 76e3d17..2dc420c 100644 --- a/src/commands/fun/thonk.ts +++ b/src/commands/fun/thonk.ts @@ -36,25 +36,25 @@ export default new NamedCommand({ usage: "([text])", async run({send, author}) { const msg = await send(transform(phrase)); - msg.createReactionCollector( - (reaction, user) => { + msg.createReactionCollector({ + filter: (reaction, user) => { if (user.id === author.id && reaction.emoji.name === "❌") msg.delete(); return false; }, - {time: 60000} - ); + time: 60000 + }); }, any: new RestCommand({ async run({send, author, combined}) { phrase = combined; const msg = await send(transform(phrase)); - msg.createReactionCollector( - (reaction, user) => { + msg.createReactionCollector({ + filter: (reaction, user) => { if (user.id === author.id && reaction.emoji.name === "❌") msg.delete(); return false; }, - {time: 60000} - ); + time: 60000 + }); } }) }); diff --git a/src/commands/fun/urban.ts b/src/commands/fun/urban.ts index 94aca51..e5d1efe 100644 --- a/src/commands/fun/urban.ts +++ b/src/commands/fun/urban.ts @@ -21,7 +21,7 @@ export default new NamedCommand({ if (res.tags && res.tags.length > 0 && res.tags.join(" ").length < 1024) embed.addField("Tags", res.tags.join(", "), true); - send(embed); + send({embeds: [embed]}); }) .catch(() => { send("Sorry, that word was not found."); diff --git a/src/commands/fun/weather.ts b/src/commands/fun/weather.ts index 9246dc1..9720256 100644 --- a/src/commands/fun/weather.ts +++ b/src/commands/fun/weather.ts @@ -29,7 +29,7 @@ export default new NamedCommand({ .addField("Winds", current.winddisplay, true) .addField("Humidity", `${current.humidity}%`, true); return send({ - embed + embeds: [embed] }); } ); diff --git a/src/commands/fun/whois.ts b/src/commands/fun/whois.ts index 9996e7b..08a7e59 100644 --- a/src/commands/fun/whois.ts +++ b/src/commands/fun/whois.ts @@ -57,7 +57,7 @@ export default new NamedCommand({ const id = author.id; if (id in registry) { - send(`${author} ${registry[id]}`, {allowedMentions: {parse: []}}); + send({content: `${author} ${registry[id]}`, allowedMentions: {parse: []}}); } else { send("You haven't been added to the registry yet!"); } @@ -69,9 +69,9 @@ export default new NamedCommand({ const id = user.id; if (id in registry) { - send(`${user} ${registry[id]}`, {allowedMentions: {parse: []}}); + send({content: `${user} ${registry[id]}`, allowedMentions: {parse: []}}); } else { - send(`${user} hasn't been added to the registry yet!`, {allowedMentions: {parse: []}}); + send({content: `${user} hasn't been added to the registry yet!`, allowedMentions: {parse: []}}); } } }), @@ -81,9 +81,9 @@ export default new NamedCommand({ if (typeof user !== "string") { if (user.id in registry) { - send(`${user} ${registry[user.id]}`, {allowedMentions: {parse: []}}); + send({content: `${user} ${registry[user.id]}`, allowedMentions: {parse: []}}); } else { - send(`${user} hasn't been added to the registry yet!`, {allowedMentions: {parse: []}}); + send({content: `${user} hasn't been added to the registry yet!`, allowedMentions: {parse: []}}); } } else { send(user); diff --git a/src/commands/system/admin.ts b/src/commands/system/admin.ts index 088d77e..0809672 100644 --- a/src/commands/system/admin.ts +++ b/src/commands/system/admin.ts @@ -1,9 +1,7 @@ import {Command, NamedCommand, getPermissionLevel, getPermissionName, CHANNEL_TYPE, RestCommand} from "onion-lasers"; -import {clean} from "../../lib"; import {Config, Storage} from "../../structures"; -import {Permissions, TextChannel, User, Role, Channel} from "discord.js"; +import {Permissions, TextChannel, User, Role, Channel, Util} from "discord.js"; import {logs} from "../../modules/globals"; -import {inspect} from "util"; function getLogBuffer(type: string) { return { @@ -372,28 +370,34 @@ export default new NamedCommand({ } }) }), - eval: new NamedCommand({ - description: "Evaluate code.", - usage: "", - permission: PERMISSIONS.BOT_OWNER, - run: "You have to enter some code to execute first.", - any: new RestCommand({ - // You have to bring everything into scope to use them. AFAIK, there isn't a more maintainable way to do this, but at least TS will let you know if anything gets removed. - async run({send, message, channel, guild, author, member, client, args, combined}) { - try { - let evaled: unknown = eval(combined); - // If promises like message.channel.send() are invoked, await them so unnecessary error reports don't leak into the command handler. - // Also, it's more useful to see the value rather than Promise { }. - if (evaled instanceof Promise) evaled = await evaled; - if (typeof evaled !== "string") evaled = inspect(evaled); - // Also await this send call so that if the message is empty, it doesn't leak into the command handler. - await send(clean(evaled), {code: "js", split: true}); - } catch (err) { - send(clean(err), {code: "js", split: true}); - } - } - }) - }), + // TODO: Reimplement this entire command, for `send` doesn't allow + // types like `unknown` to be sent anymore. Perhaps try to echo + // whatever `evaled` is into an empty buffer and send this. + // (see: `Buffer.alloc(...)`) This is unlikely to work though, since + // `Buffer.alloc(...)` requires a length, which we can't retrieve from + // an `unknown` variable. + // eval: new NamedCommand({ + // description: "Evaluate code.", + // usage: "", + // permission: PERMISSIONS.BOT_OWNER, + // run: "You have to enter some code to execute first.", + // any: new RestCommand({ + // // You have to bring everything into scope to use them. AFAIK, there isn't a more maintainable way to do this, but at least TS will let you know if anything gets removed. + // async run({send, message, channel, guild, author, member, client, args, combined}) { + // try { + // let evaled: unknown = eval(combined); + // // If promises like message.channel.send() are invoked, await them so unnecessary error reports don't leak into the command handler. + // // Also, it's more useful to see the value rather than Promise { }. + // if (evaled instanceof Promise) evaled = await evaled; + // if (typeof evaled !== "string") evaled = inspect(evaled); + // // Also await this send call so that if the message is empty, it doesn't leak into the command handler. + // await send(clean(evaled), {code: "js", split: true}); + // } catch (err) { + // send(clean(err), {code: "js", split: true}); + // } + // } + // }) + // }), nick: new NamedCommand({ description: "Change the bot's nickname.", permission: PERMISSIONS.BOT_SUPPORT, @@ -410,8 +414,12 @@ export default new NamedCommand({ description: "Shows a list of all guilds the bot is a member of.", permission: PERMISSIONS.BOT_SUPPORT, async run({send, client}) { - const guildList = client.guilds.cache.array().map((e) => e.name); - send(guildList, {split: true}); + const guildList = Util.splitMessage( + Array.from(client.guilds.cache.map((e) => e.name).values()).join("\n") + ); + for (let guildListPart of guildList) { + send(guildListPart); + } } }), activity: new NamedCommand({ diff --git a/src/commands/system/help.ts b/src/commands/system/help.ts index f1d9b51..9079999 100644 --- a/src/commands/system/help.ts +++ b/src/commands/system/help.ts @@ -22,7 +22,7 @@ export default new NamedCommand({ const helpMenuPages: [string, string][] = []; // An array of (category, description) tuples. // Prevent the description of one category from overflowing by splitting it into multiple pages if needed. - for (const category of commands.keyArray()) { + for (const category of commands.keys()) { const commandList = commands.get(category)!; let output = LEGEND; @@ -45,10 +45,16 @@ export default new NamedCommand({ paginate(send, author.id, helpMenuPages.length, (page, hasMultiplePages) => { const [category, output] = helpMenuPages[page]; - return new MessageEmbed() - .setTitle(hasMultiplePages ? `${category} (Page ${page + 1} of ${helpMenuPages.length})` : category) - .setDescription(output) - .setColor(EMBED_COLOR); + return { + embeds: [ + new MessageEmbed() + .setTitle( + hasMultiplePages ? `${category} (Page ${page + 1} of ${helpMenuPages.length})` : category + ) + .setDescription(output) + .setColor(EMBED_COLOR) + ] + }; }); }, any: new RestCommand({ @@ -87,43 +93,45 @@ export default new NamedCommand({ aliases = formattedAliases.join(", ") || "None"; } - return send( - new MessageEmbed() - .setTitle(header) - .setDescription(command.description) - .setColor(EMBED_COLOR) - .addFields( - { - name: "Aliases", - value: aliases, - inline: true - }, - { - name: "Category", - value: category, - inline: true - }, - { - name: "Permission Required", - value: `\`${getPermissionName(result.permission)}\` (Level ${result.permission})`, - inline: true - }, - { - name: "Channel Type", - value: getChannelTypeName(result.channelType), - inline: true - }, - { - name: "NSFW Only?", - value: result.nsfw ? "Yes" : "No", - inline: true - }, - { - name: "Usages", - value: append - } - ) - ); + return send({ + embeds: [ + new MessageEmbed() + .setTitle(header) + .setDescription(command.description) + .setColor(EMBED_COLOR) + .addFields( + { + name: "Aliases", + value: aliases, + inline: true + }, + { + name: "Category", + value: category, + inline: true + }, + { + name: "Permission Required", + value: `\`${getPermissionName(result.permission)}\` (Level ${result.permission})`, + inline: true + }, + { + name: "Channel Type", + value: getChannelTypeName(result.channelType), + inline: true + }, + { + name: "NSFW Only?", + value: result.nsfw ? "Yes" : "No", + inline: true + }, + { + name: "Usages", + value: append + } + ) + ] + }); } }) }); diff --git a/src/commands/utility/calc.ts b/src/commands/utility/calc.ts index 0e85165..15fd85d 100644 --- a/src/commands/utility/calc.ts +++ b/src/commands/utility/calc.ts @@ -18,7 +18,7 @@ export default new NamedCommand({ .setTitle("Math Calculation") .addField("Input", `\`\`\`js\n${combined}\`\`\``) .addField("Output", `\`\`\`js\n${resp}\`\`\``); - return send(embed); + return send({embeds: [embed]}); } }) }); diff --git a/src/commands/utility/docs.ts b/src/commands/utility/docs.ts index 5f5b2be..fa874cc 100644 --- a/src/commands/utility/docs.ts +++ b/src/commands/utility/docs.ts @@ -11,16 +11,16 @@ export default new NamedCommand({ var queryString = args[0]; let url = new URL(`https://djsdocs.sorta.moe/v2/embed?src=master&q=${queryString}`); const content = await getContent(url.toString()); - const msg = await send({embed: content}); + const msg = await send({embeds: [content]}); const react = await msg.react("❌"); - const collector = msg.createReactionCollector( - (reaction, user) => { + const collector = msg.createReactionCollector({ + filter: (reaction, user) => { if (user.id === author.id && reaction.emoji.name === "❌") msg.delete(); return false; }, - {time: 60000} - ); + time: 60000 + }); collector.on("end", () => { if (!msg.deleted) react.users.remove(msg.author); diff --git a/src/commands/utility/info.ts b/src/commands/utility/info.ts index 3811a0c..e480771 100644 --- a/src/commands/utility/info.ts +++ b/src/commands/utility/info.ts @@ -1,15 +1,15 @@ -import {MessageEmbed, version as djsversion, Guild, User, GuildMember} from "discord.js"; +import {MessageEmbed, version as djsversion, Guild, User, GuildMember, TextChannel, VoiceChannel} from "discord.js"; import ms from "ms"; import os from "os"; import {Command, NamedCommand, getUserByNickname, CHANNEL_TYPE, getGuildByName, RestCommand} from "onion-lasers"; import {formatBytes, trimArray} from "../../lib"; -import {verificationLevels, filterLevels, regions} from "../../defs/info"; +import {verificationLevels, filterLevels} from "../../defs/info"; import moment, {utc} from "moment"; export default new NamedCommand({ description: "Command to provide all sorts of info about the current server, a user, etc.", async run({send, author, member}) { - send(await getUserInfo(author, member)); + send({embeds: [await getUserInfo(author, member)]}); }, subcommands: { avatar: new NamedCommand({ @@ -55,39 +55,47 @@ export default new NamedCommand({ const core = os.cpus()[0]; const embed = new MessageEmbed() .setColor(guild?.me?.displayHexColor || "BLUE") - .addField("General", [ - `**❯ Client:** ${client.user?.tag} (${client.user?.id})`, - `**❯ Servers:** ${client.guilds.cache.size.toLocaleString()}`, - `**❯ Users:** ${client.guilds.cache - .reduce((a: any, b: {memberCount: any}) => a + b.memberCount, 0) - .toLocaleString()}`, - `**❯ Channels:** ${client.channels.cache.size.toLocaleString()}`, - `**❯ Creation Date:** ${utc(client.user?.createdTimestamp).format("Do MMMM YYYY HH:mm:ss")}`, - `**❯ Node.JS:** ${process.version}`, - `**❯ Version:** v${BOT_VERSION}`, - `**❯ Discord.JS:** v${djsversion}`, - "\u200b" - ]) - .addField("System", [ - `**❯ Platform:** ${process.platform}`, - `**❯ Uptime:** ${ms(os.uptime() * 1000, { - long: true - })}`, - `**❯ CPU:**`, - `\u3000 • Cores: ${os.cpus().length}`, - `\u3000 • Model: ${core.model}`, - `\u3000 • Speed: ${core.speed}MHz`, - `**❯ Memory:**`, - `\u3000 • Total: ${formatBytes(process.memoryUsage().heapTotal)}`, - `\u3000 • Used: ${formatBytes(process.memoryUsage().heapUsed)}` - ]) + .addField( + "General", + [ + `**❯ Client:** ${client.user?.tag} (${client.user?.id})`, + `**❯ Servers:** ${client.guilds.cache.size.toLocaleString()}`, + `**❯ Users:** ${client.guilds.cache + .reduce((a: any, b: {memberCount: any}) => a + b.memberCount, 0) + .toLocaleString()}`, + `**❯ Channels:** ${client.channels.cache.size.toLocaleString()}`, + `**❯ Creation Date:** ${utc(client.user?.createdTimestamp).format( + "Do MMMM YYYY HH:mm:ss" + )}`, + `**❯ Node.JS:** ${process.version}`, + `**❯ Version:** v${process.env.npm_package_version}`, + `**❯ Discord.JS:** v${djsversion}`, + "\u200b" + ].join("\n") + ) + .addField( + "System", + [ + `**❯ Platform:** ${process.platform}`, + `**❯ Uptime:** ${ms(os.uptime() * 1000, { + long: true + })}`, + `**❯ CPU:**`, + `\u3000 • Cores: ${os.cpus().length}`, + `\u3000 • Model: ${core.model}`, + `\u3000 • Speed: ${core.speed}MHz`, + `**❯ Memory:**`, + `\u3000 • Total: ${formatBytes(process.memoryUsage().heapTotal)}`, + `\u3000 • Used: ${formatBytes(process.memoryUsage().heapUsed)}` + ].join("\n") + ) .setTimestamp(); const avatarURL = client.user?.displayAvatarURL({ dynamic: true, size: 2048 }); if (avatarURL) embed.setThumbnail(avatarURL); - send(embed); + send({embeds: [embed]}); } }), guild: new NamedCommand({ @@ -95,14 +103,14 @@ export default new NamedCommand({ usage: "(/)", channelType: CHANNEL_TYPE.GUILD, async run({send, guild}) { - send(await getGuildInfo(guild!, guild)); + send({embeds: [await getGuildInfo(guild!, guild)]}); }, id: "guild", guild: new Command({ description: "Display info about a guild by its ID.", async run({send, guild, args}) { const targetGuild = args[0] as Guild; - send(await getGuildInfo(targetGuild, guild)); + send({embeds: [await getGuildInfo(targetGuild, guild)]}); } }), any: new RestCommand({ @@ -111,7 +119,7 @@ export default new NamedCommand({ const targetGuild = getGuildByName(combined); if (typeof targetGuild !== "string") { - send(await getGuildInfo(targetGuild, guild)); + send({embeds: [await getGuildInfo(targetGuild, guild)]}); } else { send(targetGuild); } @@ -126,7 +134,7 @@ export default new NamedCommand({ const user = args[0] as User; // Transforms the User object into a GuildMember object of the current guild. const member = guild?.members.resolve(user); - send(await getUserInfo(user, member)); + send({embeds: [await getUserInfo(user, member)]}); } }), any: new RestCommand({ @@ -135,7 +143,7 @@ export default new NamedCommand({ const user = await getUserByNickname(combined, guild); // Transforms the User object into a GuildMember object of the current guild. const member = guild?.members.resolve(user); - if (typeof user !== "string") send(await getUserInfo(user, member)); + if (typeof user !== "string") send({embeds: [await getUserInfo(user, member)]}); else send(user); } }) @@ -147,20 +155,21 @@ async function getUserInfo(user: User, member: GuildMember | null | undefined): const embed = new MessageEmbed() .setThumbnail(user.displayAvatarURL({dynamic: true, size: 512})) .setColor("BLUE") - .addField("User", [ - `**❯ Username:** ${user.username}`, - `**❯ Discriminator:** ${user.discriminator}`, - `**❯ ID:** ${user.id}`, - `**❯ Flags:** ${userFlags.length ? userFlags.join(", ") : "None"}`, - `**❯ Avatar:** [Link to avatar](${user.displayAvatarURL({ - dynamic: true - })})`, - `**❯ Time Created:** ${moment(user.createdTimestamp).format("LT")} ${moment(user.createdTimestamp).format( - "LL" - )} ${moment(user.createdTimestamp).fromNow()}`, - `**❯ Status:** ${user.presence.status}`, - `**❯ Game:** ${user.presence.activities || "Not playing a game."}` - ]); + .addField( + "User", + [ + `**❯ Username:** ${user.username}`, + `**❯ Discriminator:** ${user.discriminator}`, + `**❯ ID:** ${user.id}`, + `**❯ Flags:** ${userFlags.length ? userFlags.join(", ") : "None"}`, + `**❯ Avatar:** [Link to avatar](${user.displayAvatarURL({ + dynamic: true + })})`, + `**❯ Time Created:** ${moment(user.createdTimestamp).format("LT")} ${moment( + user.createdTimestamp + ).format("LL")} ${moment(user.createdTimestamp).fromNow()}` + ].join("\n") + ); if (member) { const roles = member.roles.cache @@ -170,16 +179,21 @@ async function getUserInfo(user: User, member: GuildMember | null | undefined): embed .setColor(member.displayHexColor) - .addField("Member", [ - `**❯ Highest Role:** ${ - member.roles.highest.id === member.guild.id ? "None" : member.roles.highest.name - }`, - `**❯ Server Join Date:** ${moment(member.joinedAt).format("LL LTS")}`, - `**❯ Hoist Role:** ${member.roles.hoist ? member.roles.hoist.name : "None"}`, - `**❯ Roles:** [${roles.length}]: ${ - roles.length == 0 ? "None" : roles.length <= 10 ? roles.join(", ") : trimArray(roles).join(", ") - }` - ]); + .addField( + "Member", + [ + `**❯ Status:** ${member.presence?.status}`, + `**❯ Game:** ${member.presence?.activities ?? "Not playing a game."}`, + `**❯ Highest Role:** ${ + member.roles.highest.id === member.guild.id ? "None" : member.roles.highest.name + }`, + `**❯ Server Join Date:** ${moment(member.joinedAt).format("LL LTS")}`, + `**❯ Hoist Role:** ${member.roles.hoist ? member.roles.hoist.name : "None"}`, + `**❯ Roles:** [${roles.length}]: ${ + roles.length == 0 ? "None" : roles.length <= 10 ? roles.join(", ") : trimArray(roles).join(", ") + }` + ].join("\n") + ); } return embed; @@ -199,39 +213,47 @@ async function getGuildInfo(guild: Guild, currentGuild: Guild | null) { const owner = await guild.fetchOwner(); embed - .addField("General", [ - `**❯ Name:** ${guild.name}`, - `**❯ ID:** ${guild.id}`, - `**❯ Owner:** ${owner.user.tag} (${guild.ownerID})`, - `**❯ Region:** ${regions[guild.region]}`, - `**❯ Boost Tier:** ${guild.premiumTier ? `Tier ${guild.premiumTier}` : "None"}`, - `**❯ Explicit Filter:** ${filterLevels[guild.explicitContentFilter]}`, - `**❯ Verification Level:** ${verificationLevels[guild.verificationLevel]}`, - `**❯ Time Created:** ${moment(guild.createdTimestamp).format("LT")} ${moment(guild.createdTimestamp).format( - "LL" - )} ${moment(guild.createdTimestamp).fromNow()}`, - "\u200b" - ]) - .addField("Statistics", [ - `**❯ Role Count:** ${roles.length}`, - `**❯ Emoji Count:** ${emojis.size}`, - `**❯ Regular Emoji Count:** ${emojis.filter((emoji) => !emoji.animated).size}`, - `**❯ Animated Emoji Count:** ${emojis.filter((emoji) => emoji.animated).size}`, - `**❯ Member Count:** ${guild.memberCount}`, - `**❯ Humans:** ${members.filter((member) => !member.user.bot).size}`, - `**❯ Bots:** ${members.filter((member) => member.user.bot).size}`, - `**❯ Text Channels:** ${channels.filter((channel) => channel.type === "text").size}`, - `**❯ Voice Channels:** ${channels.filter((channel) => channel.type === "voice").size}`, - `**❯ Boost Count:** ${guild.premiumSubscriptionCount || "0"}`, - `\u200b` - ]) - .addField("Presence", [ - `**❯ Online:** ${members.filter((member) => member.presence.status === "online").size}`, - `**❯ Idle:** ${members.filter((member) => member.presence.status === "idle").size}`, - `**❯ Do Not Disturb:** ${members.filter((member) => member.presence.status === "dnd").size}`, - `**❯ Offline:** ${members.filter((member) => member.presence.status === "offline").size}`, - displayRoles ? "\u200b" : "" - ]) + .addField( + "General", + [ + `**❯ Name:** ${guild.name}`, + `**❯ ID:** ${guild.id}`, + `**❯ Owner:** ${owner.user.tag} (${guild.ownerId})`, + `**❯ Boost Tier:** ${guild.premiumTier ? `Tier ${guild.premiumTier}` : "None"}`, + `**❯ Explicit Filter:** ${filterLevels[guild.explicitContentFilter]}`, + `**❯ Verification Level:** ${verificationLevels[guild.verificationLevel]}`, + `**❯ Time Created:** ${moment(guild.createdTimestamp).format("LT")} ${moment( + guild.createdTimestamp + ).format("LL")} ${moment(guild.createdTimestamp).fromNow()}`, + "\u200b" + ].join("\n") + ) + .addField( + "Statistics", + [ + `**❯ Role Count:** ${roles.length}`, + `**❯ Emoji Count:** ${emojis.size}`, + `**❯ Regular Emoji Count:** ${emojis.filter((emoji) => !emoji.animated).size}`, + `**❯ Animated Emoji Count:** ${emojis.filter((emoji) => !!emoji.animated).size}`, + `**❯ Member Count:** ${guild.memberCount}`, + `**❯ Humans:** ${members.filter((member) => !member.user.bot).size}`, + `**❯ Bots:** ${members.filter((member) => member.user.bot).size}`, + `**❯ Text Channels:** ${channels.filter((channel) => channel instanceof TextChannel).size}`, + `**❯ Voice Channels:** ${channels.filter((channel) => channel instanceof VoiceChannel).size}`, + `**❯ Boost Count:** ${guild.premiumSubscriptionCount || "0"}`, + `\u200b` + ].join("\n") + ) + .addField( + "Presence", + [ + `**❯ Online:** ${members.filter((member) => member.presence?.status === "online").size}`, + `**❯ Idle:** ${members.filter((member) => member.presence?.status === "idle").size}`, + `**❯ Do Not Disturb:** ${members.filter((member) => member.presence?.status === "dnd").size}`, + `**❯ Offline:** ${members.filter((member) => member.presence?.status === "offline").size}`, + displayRoles ? "\u200b" : "" + ].join("\n") + ) .setTimestamp(); if (iconURL) embed.setThumbnail(iconURL); diff --git a/src/commands/utility/lsemotes.ts b/src/commands/utility/lsemotes.ts index 22498c2..933050b 100644 --- a/src/commands/utility/lsemotes.ts +++ b/src/commands/utility/lsemotes.ts @@ -9,7 +9,7 @@ export default new NamedCommand({ description: "Lists all emotes the bot has in it's registry,", usage: " (-flags)", async run({send, author, client}) { - displayEmoteList(client.emojis.cache.array(), send, author); + displayEmoteList(Array.from(client.emojis.cache.values()), send, author); }, any: new RestCommand({ description: @@ -20,7 +20,7 @@ export default new NamedCommand({ const guildID: string = args[0]; displayEmoteList( - client.emojis.cache.filter((emote) => emote.guild.id === guildID).array(), + Array.from(client.emojis.cache.filter((emote) => emote.guild.id === guildID).values()), send, author ); @@ -32,7 +32,7 @@ export default new NamedCommand({ flags = args.pop().substring(1); } - let emoteCollection = client.emojis.cache.array(); + let emoteCollection = Array.from(client.emojis.cache.values()); // Creates a sandbox to stop a regular expression if it takes too much time to search. // To avoid passing in a giant data structure, I'll just pass in the structure {[id: string]: [name: string]}. let emotes = new Map(); @@ -61,12 +61,18 @@ export default new NamedCommand({ emoteCollection = emoteCollection.filter((emote) => emotes.has(emote.id)); // Only allow emotes that haven't been deleted. displayEmoteList(emoteCollection, send, author); } catch (error) { - if (error.code === "ERR_SCRIPT_EXECUTION_TIMEOUT") { + // FIXME: `error` is of type `unknown` here. + // Also: + let errorName = "???"; + if (error instanceof Error) { + errorName = error.name; + } + if (errorName === "ERR_SCRIPT_EXECUTION_TIMEOUT") { send( `The regular expression you entered exceeded the time limit of ${REGEX_TIMEOUT_MS} milliseconds.` ); } else { - throw new Error(error); + throw new Error(errorName); } } } else { @@ -102,7 +108,7 @@ async function displayEmoteList(emotes: GuildEmoji[], send: SendFunction, author } embed.setDescription(desc); - return embed; + return {embeds: [embed]}; }); } else { send("No valid emotes found by that query."); diff --git a/src/commands/utility/react.ts b/src/commands/utility/react.ts index b11609c..bfc63e2 100644 --- a/src/commands/utility/react.ts +++ b/src/commands/utility/react.ts @@ -1,5 +1,5 @@ import {NamedCommand, RestCommand} from "onion-lasers"; -import {Message, Channel, TextChannel} from "discord.js"; +import {Message, Channel, TextChannel, TextBasedChannels} from "discord.js"; import {processEmoteQuery} from "./modules/emote-utils"; export default new NamedCommand({ @@ -15,7 +15,7 @@ export default new NamedCommand({ if (message.reference) { // If the command message is a reply to another message, use that as the react target. - target = await channel.messages.fetch(message.reference.messageID!); + target = await channel.messages.fetch(message.reference.messageId!); } // handles reacts by message id/distance else if (args.length >= 2) { @@ -29,7 +29,7 @@ export default new NamedCommand({ const guildID = match[1]; const channelID = match[2]; const messageID = match[3]; - let tmpChannel: Channel | undefined = channel; + let tmpChannel: TextBasedChannels | undefined = channel; if (guild?.id !== guildID) { try { @@ -39,12 +39,13 @@ export default new NamedCommand({ } } - if (tmpChannel.id !== channelID) tmpChannel = guild.channels.cache.get(channelID); + if (tmpChannel?.id !== channelID) + tmpChannel = guild.channels.cache.get(channelID) as TextBasedChannels; if (!tmpChannel) return send(`\`${channelID}\` is an invalid channel ID!`); if (message.id !== messageID) { try { - target = await (tmpChannel as TextChannel).messages.fetch(messageID); + target = await tmpChannel.messages.fetch(messageID); } catch { return send(`\`${messageID}\` is an invalid message ID!`); } @@ -57,14 +58,15 @@ export default new NamedCommand({ const match = copyIDPattern.exec(last)!; const channelID = match[1]; const messageID = match[2]; - let tmpChannel: Channel | undefined = channel; + let tmpChannel: TextBasedChannels | undefined = channel; - if (tmpChannel.id !== channelID) tmpChannel = guild?.channels.cache.get(channelID); + if (tmpChannel?.id !== channelID) + tmpChannel = guild?.channels.cache.get(channelID) as TextBasedChannels; if (!tmpChannel) return send(`\`${channelID}\` is an invalid channel ID!`); if (message.id !== messageID) { try { - target = await (tmpChannel as TextChannel).messages.fetch(messageID); + target = await tmpChannel.messages.fetch(messageID); } catch { return send(`\`${messageID}\` is an invalid message ID!`); } diff --git a/src/commands/utility/say.ts b/src/commands/utility/say.ts index 775297f..6cb9d16 100644 --- a/src/commands/utility/say.ts +++ b/src/commands/utility/say.ts @@ -29,7 +29,8 @@ export default new NamedCommand({ const resolvedMessage = resolveMessageWithEmotes(combined); if (resolvedMessage) - webhook.send(resolvedMessage, { + webhook.send({ + content: resolvedMessage, username: member!.nickname ?? author.username, // Webhooks cannot have animated avatars, so requesting the animated version is a moot point. avatarURL: @@ -38,12 +39,13 @@ export default new NamedCommand({ }) || author.defaultAvatarURL, allowedMentions: {parse: []}, // avoids double pings // "embeds" will not be included because it messes with the default ones that generate - files: message.attachments.array() + files: Array.from(message.attachments.values()) }); else send("Cannot send an empty message."); } else { const resolvedMessage = resolveMessageWithEmotes(combined); - if (resolvedMessage) send(`*${author} says:*\n${resolvedMessage}`, {allowedMentions: {parse: []}}); + if (resolvedMessage) + send({content: `*${author} says:*\n${resolvedMessage}`, allowedMentions: {parse: []}}); else send("Cannot send an empty message."); } diff --git a/src/commands/utility/scanemotes.ts b/src/commands/utility/scanemotes.ts index aed0d2a..0a70076 100644 --- a/src/commands/utility/scanemotes.ts +++ b/src/commands/utility/scanemotes.ts @@ -1,7 +1,7 @@ import {NamedCommand, CHANNEL_TYPE} from "onion-lasers"; import {pluralise} from "../../lib"; import moment from "moment"; -import {Collection, TextChannel} from "discord.js"; +import {Collection, TextChannel, Util} from "discord.js"; const lastUsedTimestamps = new Collection(); @@ -33,7 +33,7 @@ export default new NamedCommand({ let totalUserEmoteUsage = 0; // IMPORTANT: You MUST check if the bot actually has access to the channel in the first place. It will get the list of all channels, but that doesn't mean it has access to every channel. Without this, it'll require admin access and throw an annoying unhelpful DiscordAPIError: Missing Access otherwise. const allTextChannelsInCurrentGuild = guild!.channels.cache.filter( - (channel) => channel.type === "text" && channel.viewable + (channel) => channel instanceof TextChannel && channel.viewable ) as Collection; let messagesSearched = 0; let channelsSearched = 0; @@ -41,7 +41,7 @@ export default new NamedCommand({ const totalChannels = allTextChannelsInCurrentGuild.size; const statusMessage = await send("Gathering emotes..."); let warnings = 0; - channel.startTyping(); + channel.sendTyping(); // Initialize the emote stats object with every emote in the current guild. // The goal here is to cut the need to access guild.emojis.get() which'll make it faster and easier to work with. @@ -63,7 +63,7 @@ export default new NamedCommand({ for (const channel of allTextChannelsInCurrentGuild.values()) { currentChannelName = channel.name; - let selected = channel.lastMessageID ?? message.id; + let selected = channel.lastMessageId ?? message.id; let continueLoop = true; while (continueLoop) { @@ -161,7 +161,6 @@ export default new NamedCommand({ )}.` ); console.log("[scanemotes]", `Finished operation in ${finishTime - startTime} ms.`); - channel.stopTyping(); // Display stats on emote usage. // This can work outside the loop now that it's synchronous, and now it's clearer what code is meant to execute at the end. @@ -180,7 +179,10 @@ export default new NamedCommand({ ); } - return await send(lines, {split: true}); + let emoteList = Util.splitMessage(lines.join("\n")); + for (let emoteListPart of emoteList) { + return await send(emoteListPart); + } }, subcommands: { forcereset: new NamedCommand({ diff --git a/src/commands/utility/streaminfo.ts b/src/commands/utility/streaminfo.ts index a4ed019..1cf44a0 100644 --- a/src/commands/utility/streaminfo.ts +++ b/src/commands/utility/streaminfo.ts @@ -34,11 +34,14 @@ export default new NamedCommand({ const stream = streamList.get(userID)!; stream.description = combined; stream.update(); - send("Successfully set the stream description to:", { - embed: { - description: stream.description, - color: member!.displayColor - } + send({ + content: "Successfully set the stream description to:", + embeds: [ + { + description: stream.description, + color: member!.displayColor + } + ] }); } else { send("You can only use this command when streaming."); @@ -70,12 +73,15 @@ export default new NamedCommand({ const stream = streamList.get(userID)!; stream.thumbnail = combined; stream.update(); - send(`Successfully set the stream thumbnail to: ${combined}`, { - embed: { - description: stream.description, - thumbnail: {url: combined}, - color: member!.displayColor - } + send({ + content: `Successfully set the stream thumbnail to: ${combined}`, + embeds: [ + { + description: stream.description, + thumbnail: {url: combined}, + color: member!.displayColor + } + ] }); } else { send("You can only use this command when streaming."); diff --git a/src/commands/utility/time.ts b/src/commands/utility/time.ts index d55e37d..b02a88b 100644 --- a/src/commands/utility/time.ts +++ b/src/commands/utility/time.ts @@ -124,42 +124,40 @@ function getTimeEmbed(user: User) { } const embed = { - embed: { - color: TIME_EMBED_COLOR, - author: { - name: user.username, - icon_url: user.displayAvatarURL({ - format: "png", - dynamic: true - }) + color: TIME_EMBED_COLOR, + author: { + name: user.username, + icon_url: user.displayAvatarURL({ + format: "png", + dynamic: true + }) + }, + fields: [ + { + name: "Local Date", + value: localDate }, - fields: [ - { - name: "Local Date", - value: localDate - }, - { - name: "Day of the Week", - value: dayOfWeek - }, - { - name: "Local Time", - value: localTime - }, - { - name: daylightSavingsRegion !== null ? "Current Timezone Offset" : "Timezone Offset", - value: timezoneOffset - }, - { - name: "Observes Daylight Savings?", - value: daylightSavingsRegion ? "Yes" : "No" - } - ] - } + { + name: "Day of the Week", + value: dayOfWeek + }, + { + name: "Local Time", + value: localTime + }, + { + name: daylightSavingsRegion !== null ? "Current Timezone Offset" : "Timezone Offset", + value: timezoneOffset + }, + { + name: "Observes Daylight Savings?", + value: daylightSavingsRegion ? "Yes" : "No" + } + ] }; if (daylightSavingsRegion) { - embed.embed.fields.push( + embed.fields.push( { name: "Daylight Savings Active?", value: hasDaylightSavings(daylightSavingsRegion) ? "Yes" : "No" @@ -178,7 +176,7 @@ export default new NamedCommand({ description: "Show others what time it is for you.", aliases: ["tz"], async run({send, author}) { - send(getTimeEmbed(author)); + send({embeds: [getTimeEmbed(author)]}); }, subcommands: { // Welcome to callback hell. We hope you enjoy your stay here! @@ -298,10 +296,11 @@ export default new NamedCommand({ const finalize = () => { Storage.save(); - send( - "You've finished setting up your timezone! Just check to see if this looks right, and if it doesn't, run this setup again.", - getTimeEmbed(author) - ); + send({ + content: + "You've finished setting up your timezone! Just check to see if this looks right, and if it doesn't, run this setup again.", + embeds: [getTimeEmbed(author)] + }); }; if (hasDST) { @@ -358,23 +357,25 @@ export default new NamedCommand({ const time = moment().utc(); send({ - embed: { - color: TIME_EMBED_COLOR, - fields: [ - { - name: "Local Date", - value: time.format(DATE_FORMAT) - }, - { - name: "Day of the Week", - value: time.format(DOW_FORMAT) - }, - { - name: "Local Time", - value: time.format(TIME_FORMAT) - } - ] - } + embeds: [ + { + color: TIME_EMBED_COLOR, + fields: [ + { + name: "Local Date", + value: time.format(DATE_FORMAT) + }, + { + name: "Day of the Week", + value: time.format(DOW_FORMAT) + }, + { + name: "Local Time", + value: time.format(TIME_FORMAT) + } + ] + } + ] }); } }), @@ -387,14 +388,14 @@ export default new NamedCommand({ user: new Command({ description: "See what time it is for someone else.", async run({send, args}) { - send(getTimeEmbed(args[0])); + send({embeds: [getTimeEmbed(args[0])]}); } }), any: new RestCommand({ description: "See what time it is for someone else (by their username).", async run({send, guild, combined}) { const user = await getUserByNickname(combined, guild); - if (typeof user !== "string") send(getTimeEmbed(user)); + if (typeof user !== "string") send({embeds: [getTimeEmbed(user)]}); else send(user); } }) diff --git a/src/commands/utility/todo.ts b/src/commands/utility/todo.ts index e88eefc..da73eaa 100644 --- a/src/commands/utility/todo.ts +++ b/src/commands/utility/todo.ts @@ -17,7 +17,7 @@ export default new NamedCommand({ ); } - send(embed); + send({embeds: [embed]}); }, subcommands: { add: new NamedCommand({ diff --git a/src/commands/utility/translate.ts b/src/commands/utility/translate.ts index eb4075c..d275f0f 100644 --- a/src/commands/utility/translate.ts +++ b/src/commands/utility/translate.ts @@ -16,19 +16,21 @@ export default new NamedCommand({ }) .then((res) => { send({ - embed: { - title: "Translation", - fields: [ - { - name: "Input", - value: `\`\`\`${input}\`\`\`` - }, - { - name: "Output", - value: `\`\`\`${res}\`\`\`` - } - ] - } + embeds: [ + { + title: "Translation", + fields: [ + { + name: "Input", + value: `\`\`\`${input}\`\`\`` + }, + { + name: "Output", + value: `\`\`\`${res}\`\`\`` + } + ] + } + ] }); }) .catch((error) => { diff --git a/src/index.ts b/src/index.ts index ee3144e..18ab1dc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,18 @@ import path from "path"; // This is here in order to make it much less of a headache to access the client from other files. // This of course won't actually do anything until the setup process is complete and it logs in. -export const client = new Client({intents: Intents.ALL}); +export const client = new Client({ + intents: [ + Intents.FLAGS.GUILDS, + Intents.FLAGS.GUILD_MEMBERS, + Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS, + Intents.FLAGS.GUILD_VOICE_STATES, + Intents.FLAGS.GUILD_PRESENCES, + Intents.FLAGS.GUILD_MESSAGES, + Intents.FLAGS.GUILD_MESSAGE_REACTIONS, + Intents.FLAGS.DIRECT_MESSAGES + ] +}); import {launch} from "onion-lasers"; import setup from "./modules/setup"; @@ -44,7 +55,7 @@ launch(client, path.join(__dirname, "commands"), { { // OWNER // name: "Server Owner", - check: (_user, member) => !!member && member.guild.ownerID === member.id + check: (_user, member) => !!member && member.guild.ownerId === member.id }, { // BOT_SUPPORT // @@ -67,7 +78,8 @@ launch(client, path.join(__dirname, "commands"), { // Initialize Modules // import "./modules/ready"; import "./modules/presence"; -import "./modules/lavalink"; +// TODO: Reimplement entire music system, contact Sink +// import "./modules/lavalink"; import "./modules/emoteRegistry"; import "./modules/systemInfo"; import "./modules/intercept"; diff --git a/src/lib.ts b/src/lib.ts index c4f4167..b999791 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -154,7 +154,11 @@ export function getContent(url: string): Promise<{url: string}> { const parsedData = JSON.parse(rawData); resolve(parsedData); } catch (e) { - reject(`Error: ${e.message}`); + let errorMessage = "Something went wrong! We don't know what, though..."; + if (e instanceof Error) { + errorMessage = e.message; + } + reject(`Error: ${errorMessage}`); } }); }).on("error", (err: {message: any}) => { diff --git a/src/modules/emoteRegistry.ts b/src/modules/emoteRegistry.ts index e261390..502c379 100644 --- a/src/modules/emoteRegistry.ts +++ b/src/modules/emoteRegistry.ts @@ -11,8 +11,8 @@ function updateGlobalEmoteRegistry(): void { ref: emote.name, id: emote.id, name: emote.name, - requires_colons: emote.requiresColons || false, - animated: emote.animated, + requires_colons: emote.requiresColons ?? false, + animated: emote.animated ?? false, url: emote.url, guild_id: emote.guild.name, guild_name: emote.guild.name diff --git a/src/modules/guildMemberAdd.ts b/src/modules/guildMemberAdd.ts index 8e41bf6..5297cca 100644 --- a/src/modules/guildMemberAdd.ts +++ b/src/modules/guildMemberAdd.ts @@ -25,7 +25,7 @@ client.on("guildMemberAdd", async (member) => { if (welcomeChannel) { const channel = member.guild.channels.cache.get(welcomeChannel); - if (channel && channel.type === "text") { + if (channel && channel instanceof TextChannel) { if (welcomeType === "graphical") { const canvas = createCanvas(700, 250); const ctx = canvas.getContext("2d"); @@ -60,9 +60,9 @@ client.on("guildMemberAdd", async (member) => { ctx.drawImage(avatar, 25, 25, 200, 200); const attachment = new MessageAttachment(canvas.toBuffer("image/png"), "welcome-image.png"); - (channel as TextChannel).send(`Welcome \`${member.user.tag}\`!`, attachment); + channel.send({content: `Welcome \`${member.user.tag}\`!`, attachments: [attachment]}); } else if (welcomeType === "text") { - (channel as TextChannel).send( + channel.send( parseVars( welcomeMessage || "Say hello to `%user%`, everyone! We all need a warm welcome sometimes :D", { diff --git a/src/modules/lavalink.ts b/src/modules/lavalink.ts index 5eecaf3..fb43949 100644 --- a/src/modules/lavalink.ts +++ b/src/modules/lavalink.ts @@ -1,51 +1,49 @@ -import attachClientToLavalink from "discord.js-lavalink-lib"; -import {Config} from "../structures"; -import {client} from "../index"; - -if (Config.lavalink) { - // Although the example showed to do "client.music = LavaLink(...)" and "(client as any).music = Lavalink(...)" was done to match that, nowhere in the library is client.music ever actually used nor does the function return anything. In other words, client.music is undefined and is never used. - attachClientToLavalink(client, { - lavalink: { - restnode: { - host: "localhost", - port: 2333, - password: "youshallnotpass" - }, - nodes: [ - { - host: "localhost", - port: 2333, - password: "youshallnotpass" - } - ] - }, - prefix: Config.prefix, - helpCmd: "mhelp", - admins: ["717352467280691331"] - }); - - // Disable the unhandledRejection listener by Lavalink because it captures every single unhandled - // rejection and adds its message with it. Then replace it with a better, more selective error handler. - for (const listener of process.listeners("unhandledRejection")) { - if (listener.toString().includes("discord.js-lavalink-musicbot")) { - process.off("unhandledRejection", listener); - } - } - - process.on("unhandledRejection", (reason: any) => { - if (reason?.code === "ECONNREFUSED") { - // This is console.warn instead of console.error because on development environments, unless Lavalink is being tested, it won't interfere with the bot's functionality. - console.warn( - `[discord.js-lavalink-musicbot] Caught unhandled rejection: ${reason.stack}\nIf this is causing issues, head to the support server at https://discord.gg/dNN4azK` - ); - } - }); - - // It's unsafe to process uncaughtException because after an uncaught exception, the system - // becomes corrupted. So disable Lavalink from adding a hook to it. - for (const listener of process.listeners("uncaughtException")) { - if (listener.toString().includes("discord.js-lavalink-musicbot")) { - process.off("uncaughtException", listener); - } - } -} +// import attachClientToLavalink from "discord.js-lavalink-lib"; +// import {Config} from "../structures"; +// import {client} from "../index"; +// +// // Although the example showed to do "client.music = LavaLink(...)" and "(client as any).music = Lavalink(...)" was done to match that, nowhere in the library is client.music ever actually used nor does the function return anything. In other words, client.music is undefined and is never used. +// attachClientToLavalink(client, { +// lavalink: { +// restnode: { +// host: "localhost", +// port: 2333, +// password: "youshallnotpass" +// }, +// nodes: [ +// { +// host: "localhost", +// port: 2333, +// password: "youshallnotpass" +// } +// ] +// }, +// prefix: Config.prefix, +// helpCmd: "mhelp", +// admins: ["717352467280691331"] +// }); +// +// // Disable the unhandledRejection listener by Lavalink because it captures every single unhandled +// // rejection and adds its message with it. Then replace it with a better, more selective error handler. +// for (const listener of process.listeners("unhandledRejection")) { +// if (listener.toString().includes("discord.js-lavalink-musicbot")) { +// process.off("unhandledRejection", listener); +// } +// } +// +// process.on("unhandledRejection", (reason: any) => { +// if (reason?.code === "ECONNREFUSED") { +// // This is console.warn instead of console.error because on development environments, unless Lavalink is being tested, it won't interfere with the bot's functionality. +// console.warn( +// `[discord.js-lavalink-musicbot] Caught unhandled rejection: ${reason.stack}\nIf this is causing issues, head to the support server at https://discord.gg/dNN4azK` +// ); +// } +// }); +// +// // It's unsafe to process uncaughtException because after an uncaught exception, the system +// // becomes corrupted. So disable Lavalink from adding a hook to it. +// for (const listener of process.listeners("uncaughtException")) { +// if (listener.toString().includes("discord.js-lavalink-musicbot")) { +// process.off("uncaughtException", listener); +// } +// } diff --git a/src/modules/messageEmbed.ts b/src/modules/messageEmbed.ts index 050edf6..0c04c18 100644 --- a/src/modules/messageEmbed.ts +++ b/src/modules/messageEmbed.ts @@ -2,12 +2,9 @@ import {client} from "../index"; import {MessageEmbed} from "discord.js"; import {getPrefix} from "../structures"; import {getMessageByID} from "onion-lasers"; -import {Storage} from "../structures"; -client.on("message", async (message) => { - const {messageEmbeds} = Storage.getGuild(message.guild!.id); - - if (messageEmbeds) { +client.on("message", (message) => { + (async () => { // Only execute if the message is from a user and isn't a command. if (message.content.startsWith(getPrefix(message.guild)) || message.author.bot) return; const messageLink = extractFirstMessageLink(message.content); @@ -27,11 +24,7 @@ client.on("message", async (message) => { ]; if (!linkMessage.cleanContent && embeds.length === 0) { - return message.channel.send(new MessageEmbed().setDescription("🚫 The message is empty.")); - } - - if (linkMessage.cleanContent.length > 2048) { - return message.channel.send(new MessageEmbed().setDescription("🚫 This message is too long.")); + return message.channel.send({embeds: [new MessageEmbed().setDescription("🚫 The message is empty.")]}); } const infoEmbed = new MessageEmbed() @@ -49,8 +42,8 @@ client.on("message", async (message) => { infoEmbed.setImage(image!.url); } - return await message.channel.send(infoEmbed); - } else return; + return await message.channel.send({embeds: [infoEmbed]}); + })(); }); export function extractFirstMessageLink(message: string): [string, string, string] | null { diff --git a/src/modules/streamNotifications.ts b/src/modules/streamNotifications.ts index ab2f3ca..f53630c 100644 --- a/src/modules/streamNotifications.ts +++ b/src/modules/streamNotifications.ts @@ -38,7 +38,7 @@ function getStreamEmbed( // I decided to not include certain fields: // .addField("Activity", "CrossCode", true) - Probably too much presence data involved, increasing memory usage. // .addField("Viewers", 5, true) - There doesn't seem to currently be a way to track how many viewers there are. Presence data for "WATCHING" doesn't seem to affect it, and listening to raw client events doesn't seem to make it appear either. - .addField("Voice Channel", channel, true) + .addField("Voice Channel", channel.toString(), true) .addField("Category", category, true) .setColor(streamer.displayColor) .setFooter( @@ -90,21 +90,23 @@ client.on("voiceStateUpdate", async (before, after) => { streamer: member, channel: voiceChannel, category, - message: await textChannel.send( - streamNotificationPing, - getStreamEmbed(member, voiceChannel, streamStart, category) - ), + message: await textChannel.send({ + content: streamNotificationPing, + embeds: [getStreamEmbed(member, voiceChannel, streamStart, category)] + }), update(this: Stream) { - this.message.edit( - getStreamEmbed( - this.streamer, - this.channel, - streamStart, - this.category, - this.description, - this.thumbnail - ) - ); + this.message.edit({ + embeds: [ + getStreamEmbed( + this.streamer, + this.channel, + streamStart, + this.category, + this.description, + this.thumbnail + ) + ] + }); }, streamStart }); @@ -125,7 +127,7 @@ client.on("voiceStateUpdate", async (before, after) => { }); client.on("channelUpdate", (before, after) => { - if (before.type === "voice" && after.type === "voice") { + if (before instanceof VoiceChannel && after instanceof VoiceChannel) { for (const stream of streamList.values()) { if (after.id === stream.channel.id) { stream.update(); diff --git a/src/modules/systemInfo.ts b/src/modules/systemInfo.ts index 439e517..f442a8a 100644 --- a/src/modules/systemInfo.ts +++ b/src/modules/systemInfo.ts @@ -13,8 +13,8 @@ client.on("guildCreate", async (guild) => { if (Config.systemLogsChannel) { const channel = client.channels.cache.get(Config.systemLogsChannel); - if (channel && channel.type === "text") { - (channel as TextChannel).send( + if (channel instanceof TextChannel) { + channel.send( `TravBot joined: \`${guild.name}\`. The owner of this guild is: \`${owner.user.tag}\` (\`${owner.user.id}\`)` ); } else { @@ -29,8 +29,8 @@ client.on("guildDelete", (guild) => { if (Config.systemLogsChannel) { const channel = client.channels.cache.get(Config.systemLogsChannel); - if (channel && channel.type === "text") { - (channel as TextChannel).send(`\`${guild.name}\` (\`${guild.id}\`) removed the bot.`); + if (channel instanceof TextChannel) { + channel.send(`\`${guild.name}\` (\`${guild.id}\`) removed the bot.`); } else { console.warn( `${Config.systemLogsChannel} is not a valid text channel for system logs! Removing it from storage.` diff --git a/src/modules/webhookStorageManager.ts b/src/modules/webhookStorageManager.ts index 9cb17ff..ea6fb5f 100644 --- a/src/modules/webhookStorageManager.ts +++ b/src/modules/webhookStorageManager.ts @@ -61,7 +61,7 @@ export async function refreshWebhookCache(): Promise { // If there are stored webhook IDs/tokens that don't work, delete those webhooks from storage. try { const webhook = await client.fetchWebhook(id, token); - webhookStorage.set(webhook.channelID, webhook); + webhookStorage.set(webhook.channelId, webhook); } catch { delete Config.webhooks[id]; Config.save(); diff --git a/tsconfig.json b/tsconfig.json index 2b1714b..84b8702 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,7 @@ // Type Settings // "strict": true, // Enables all strict checks possible. - "noImplicitReturns": true, // Makes sure you don't accidentally return something + undefined. + "noImplicitReturns": false, // Makes sure you don't accidentally return something + undefined. "noFallthroughCasesInSwitch": true, // Prevents accidentally forgetting to break every switch case. Of course, if you know what you're doing, feel free to add a @ts-ignore, which also signals that it's not a mistake. "forceConsistentCasingInFileNames": true, // Make import paths case-sensitive. "./tEst" is no longer the same as "./test". "esModuleInterop": true, // Enables compatibility with Node.js' module system since the entire export can be whatever you want. allowSyntheticDefaultImports doesn't address runtime issues and is made redundant by this setting.