diff options
author | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2021-06-19 16:43:37 -0400 |
---|---|---|
committer | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2021-06-19 16:43:37 -0400 |
commit | ea64ebfff9aae32deb036643422d3427959dcd24 (patch) | |
tree | 5ab83558642bad282515837424637070f547a05e | |
parent | d055e0dbb86ef7fd4ee96a1531b51181e825fb4b (diff) | |
download | tanzanite-ea64ebfff9aae32deb036643422d3427959dcd24.tar.gz tanzanite-ea64ebfff9aae32deb036643422d3427959dcd24.tar.bz2 tanzanite-ea64ebfff9aae32deb036643422d3427959dcd24.zip |
feat(*): A bunch of stuff
- Remade logging
- updated dependencies
- started adding custom crap to the command handler
- added emojis to stuff
- can't remeber other stuff
Note: this is currently broken
BREAKING CHANGE:
52 files changed, 2882 insertions, 1598 deletions
diff --git a/.gitattributes b/.gitattributes index 94f480d..c93e4e8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,3 @@ -* text=auto eol=lf
\ No newline at end of file +* text=auto eol=l +.pnp.js linguist-generated +yarn.lock linguist-generated
\ No newline at end of file diff --git a/SETUP.md b/.github/workflows/SETUP.md index 782c204..751cfde 100644 --- a/SETUP.md +++ b/.github/workflows/SETUP.md @@ -4,14 +4,14 @@ 2. Run `yarn` to make sure dependencies are all set up 3. Copy `src/config/example-options.ts` to `src/config/options.ts` and change all the options to what you need -### Database +## Database 1. Make sure to have a postgresql db running on something you can access (postgres supports all OSes) 2. Make sure you have a db with the correct name (for dev it is `bush-bot-dev`, for non-dev it is `bush-bot`) Sequelize will handle tables for you, no need to do anything besides make the db -### Start +## Start In production, use `yarn start` to start the bot. In dev, use `yarn dev` to start the bot. @@ -39,30 +39,30 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [ ["@discordjs/voice", "npm:0.4.0"], ["@types/common-tags", "npm:1.8.0"], - ["@types/express", "npm:4.17.11"], - ["@types/node", "npm:14.17.0"], + ["@types/express", "npm:4.17.12"], + ["@types/node", "npm:14.17.3"], ["@types/uuid", "npm:8.3.0"], - ["@typescript-eslint/eslint-plugin", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.24.0"], - ["@typescript-eslint/parser", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.24.0"], + ["@typescript-eslint/eslint-plugin", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.27.0"], + ["@typescript-eslint/parser", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.27.0"], ["body-parser", "npm:1.19.0"], ["canvas", "npm:2.8.0"], ["chalk", "npm:4.1.1"], ["common-tags", "npm:1.8.0"], - ["discord-akairo", "https://github.com/IRONM00N-Development/discord-akairo.git#commit=690c219497dff280dd49360882f72ddd100fc148"], + ["discord-akairo", "https://github.com/NotEnoughUpdates/discord-akairo.git#commit=98309bfc2b384cb41610ab7221fcd683fe8e2f88"], ["discord-api-types", "npm:0.18.1"], - ["discord.js", "npm:13.0.0-dev.918921e8211fc16e9b12d2502f3168264246ea22"], - ["esbuild", "npm:0.12.1"], - ["eslint", "npm:7.26.0"], + ["discord.js", "npm:13.0.0-dev.807ea2d3c197c7c6556bd1c894114932f6657d49"], + ["esbuild", "npm:0.12.9"], + ["eslint", "npm:7.29.0"], ["eslint-config-prettier", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:8.3.0"], ["got", "npm:11.8.2"], ["moment", "npm:2.29.1"], ["pg", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:8.6.0"], - ["pg-hstore", "npm:2.3.3"], - ["prettier", "npm:2.3.0"], + ["pg-hstore", "npm:2.3.4"], + ["prettier", "npm:2.3.1"], ["rimraf", "npm:3.0.2"], ["sequelize", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:6.6.2"], ["source-map-support", "npm:0.5.19"], - ["typescript", "patch:typescript@npm%3A4.2.4#builtin<compat/typescript>::version=4.2.4&hash=ddfc1b"], + ["typescript", "patch:typescript@npm%3A4.3.4#builtin<compat/typescript>::version=4.3.4&hash=ddfc1b"], ["uuid", "npm:8.3.2"] ], "linkType": "SOFT", @@ -73,26 +73,26 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/@babel-code-frame-npm-7.12.11-1a9a1b277f-033d3fb3bf.zip/node_modules/@babel/code-frame/", "packageDependencies": [ ["@babel/code-frame", "npm:7.12.11"], - ["@babel/highlight", "npm:7.14.0"] + ["@babel/highlight", "npm:7.14.5"] ], "linkType": "HARD", }] ]], ["@babel/helper-validator-identifier", [ - ["npm:7.14.0", { - "packageLocation": "./.yarn/cache/@babel-helper-validator-identifier-npm-7.14.0-88c0d4b395-bd67b4a1a4.zip/node_modules/@babel/helper-validator-identifier/", + ["npm:7.14.5", { + "packageLocation": "./.yarn/cache/@babel-helper-validator-identifier-npm-7.14.5-d29d30a813-778312189a.zip/node_modules/@babel/helper-validator-identifier/", "packageDependencies": [ - ["@babel/helper-validator-identifier", "npm:7.14.0"] + ["@babel/helper-validator-identifier", "npm:7.14.5"] ], "linkType": "HARD", }] ]], ["@babel/highlight", [ - ["npm:7.14.0", { - "packageLocation": "./.yarn/cache/@babel-highlight-npm-7.14.0-54986133d5-0122fcd3cd.zip/node_modules/@babel/highlight/", + ["npm:7.14.5", { + "packageLocation": "./.yarn/cache/@babel-highlight-npm-7.14.5-4a18106cbc-a1ed599c26.zip/node_modules/@babel/highlight/", "packageDependencies": [ - ["@babel/highlight", "npm:7.14.0"], - ["@babel/helper-validator-identifier", "npm:7.14.0"], + ["@babel/highlight", "npm:7.14.5"], + ["@babel/helper-validator-identifier", "npm:7.14.5"], ["chalk", "npm:2.4.2"], ["js-tokens", "npm:4.0.0"] ], @@ -115,7 +115,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@discordjs/form-data", "npm:3.0.1"], ["asynckit", "npm:0.4.0"], ["combined-stream", "npm:1.0.8"], - ["mime-types", "npm:2.1.30"] + ["mime-types", "npm:2.1.31"] ], "linkType": "HARD", }] @@ -125,24 +125,24 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/@discordjs-voice-npm-0.4.0-275bceca0f-a1b65c946d.zip/node_modules/@discordjs/voice/", "packageDependencies": [ ["@discordjs/voice", "npm:0.4.0"], - ["@types/ws", "npm:7.4.4"], + ["@types/ws", "npm:7.4.5"], ["discord-api-types", "npm:0.18.1"], ["prism-media", "virtual:275bceca0f79f8e7aeb7f77acb5a6bd201e7eea264e9dfd8dcc0bcf35691357327303c09557dfc1495b9a1f8e9cf8278133d234783570df6cb70a249778f3198#npm:1.3.1"], ["tiny-typed-emitter", "npm:2.0.3"], - ["ws", "virtual:275bceca0f79f8e7aeb7f77acb5a6bd201e7eea264e9dfd8dcc0bcf35691357327303c09557dfc1495b9a1f8e9cf8278133d234783570df6cb70a249778f3198#npm:7.4.6"] + ["ws", "virtual:275bceca0f79f8e7aeb7f77acb5a6bd201e7eea264e9dfd8dcc0bcf35691357327303c09557dfc1495b9a1f8e9cf8278133d234783570df6cb70a249778f3198#npm:7.5.0"] ], "linkType": "HARD", }] ]], ["@eslint/eslintrc", [ - ["npm:0.4.1", { - "packageLocation": "./.yarn/cache/@eslint-eslintrc-npm-0.4.1-48933b2833-418f5810c8.zip/node_modules/@eslint/eslintrc/", + ["npm:0.4.2", { + "packageLocation": "./.yarn/cache/@eslint-eslintrc-npm-0.4.2-f8b688e654-60b66ce425.zip/node_modules/@eslint/eslintrc/", "packageDependencies": [ - ["@eslint/eslintrc", "npm:0.4.1"], + ["@eslint/eslintrc", "npm:0.4.2"], ["ajv", "npm:6.12.6"], - ["debug", "virtual:48933b28331d16c1d73786360e7ba20f54f6df4949c6ab5c13ac4c4353b5c70f2d36a97de9a9c531027ad3588d8fd7f384706f298f0eff0356b58bb9c47f63ec#npm:4.3.1"], + ["debug", "virtual:428f325a939c2653ad822eb3d75efb02ac311523dd0d4f9645afc39ea00bd86eceac35a9d59c9b6977d76b670a4ef0ae057ea572338a44729aa592711a8c05a3#npm:4.3.2"], ["espree", "npm:7.3.1"], - ["globals", "npm:12.4.0"], + ["globals", "npm:13.9.0"], ["ignore", "npm:4.0.6"], ["import-fresh", "npm:3.3.0"], ["js-yaml", "npm:3.14.1"], @@ -171,31 +171,31 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@nodelib/fs.scandir", [ - ["npm:2.1.4", { - "packageLocation": "./.yarn/cache/@nodelib-fs.scandir-npm-2.1.4-6f6ddb2372-30b3102ee3.zip/node_modules/@nodelib/fs.scandir/", + ["npm:2.1.5", { + "packageLocation": "./.yarn/cache/@nodelib-fs.scandir-npm-2.1.5-89c67370dd-91b3de88d9.zip/node_modules/@nodelib/fs.scandir/", "packageDependencies": [ - ["@nodelib/fs.scandir", "npm:2.1.4"], - ["@nodelib/fs.stat", "npm:2.0.4"], + ["@nodelib/fs.scandir", "npm:2.1.5"], + ["@nodelib/fs.stat", "npm:2.0.5"], ["run-parallel", "npm:1.2.0"] ], "linkType": "HARD", }] ]], ["@nodelib/fs.stat", [ - ["npm:2.0.4", { - "packageLocation": "./.yarn/cache/@nodelib-fs.stat-npm-2.0.4-0b2acf9d70-6454a79e94.zip/node_modules/@nodelib/fs.stat/", + ["npm:2.0.5", { + "packageLocation": "./.yarn/cache/@nodelib-fs.stat-npm-2.0.5-01f4dd3030-a4fcf7408f.zip/node_modules/@nodelib/fs.stat/", "packageDependencies": [ - ["@nodelib/fs.stat", "npm:2.0.4"] + ["@nodelib/fs.stat", "npm:2.0.5"] ], "linkType": "HARD", }] ]], ["@nodelib/fs.walk", [ - ["npm:1.2.6", { - "packageLocation": "./.yarn/cache/@nodelib-fs.walk-npm-1.2.6-b686194e9d-d0503ffd0b.zip/node_modules/@nodelib/fs.walk/", + ["npm:1.2.7", { + "packageLocation": "./.yarn/cache/@nodelib-fs.walk-npm-1.2.7-69f33ea303-ac8e2d9ca0.zip/node_modules/@nodelib/fs.walk/", "packageDependencies": [ - ["@nodelib/fs.walk", "npm:1.2.6"], - ["@nodelib/fs.scandir", "npm:2.1.4"], + ["@nodelib/fs.walk", "npm:1.2.7"], + ["@nodelib/fs.scandir", "npm:2.1.5"], ["fastq", "npm:1.11.0"] ], "linkType": "HARD", @@ -255,7 +255,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [ ["@types/body-parser", "npm:1.19.0"], ["@types/connect", "npm:3.4.34"], - ["@types/node", "npm:15.3.0"] + ["@types/node", "npm:15.12.4"] ], "linkType": "HARD", }] @@ -267,7 +267,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/cacheable-request", "npm:6.0.1"], ["@types/http-cache-semantics", "npm:4.0.0"], ["@types/keyv", "npm:3.1.1"], - ["@types/node", "npm:15.3.0"], + ["@types/node", "npm:15.12.4"], ["@types/responselike", "npm:1.0.0"] ], "linkType": "HARD", @@ -287,18 +287,18 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/@types-connect-npm-3.4.34-39e4f7bb55-6f712a0408.zip/node_modules/@types/connect/", "packageDependencies": [ ["@types/connect", "npm:3.4.34"], - ["@types/node", "npm:15.3.0"] + ["@types/node", "npm:15.12.4"] ], "linkType": "HARD", }] ]], ["@types/express", [ - ["npm:4.17.11", { - "packageLocation": "./.yarn/cache/@types-express-npm-4.17.11-1b3f17f056-2818120a0f.zip/node_modules/@types/express/", + ["npm:4.17.12", { + "packageLocation": "./.yarn/cache/@types-express-npm-4.17.12-d30bfc5b29-b1ab50e037.zip/node_modules/@types/express/", "packageDependencies": [ - ["@types/express", "npm:4.17.11"], + ["@types/express", "npm:4.17.12"], ["@types/body-parser", "npm:1.19.0"], - ["@types/express-serve-static-core", "npm:4.17.19"], + ["@types/express-serve-static-core", "npm:4.17.21"], ["@types/qs", "npm:6.9.6"], ["@types/serve-static", "npm:1.13.9"] ], @@ -306,11 +306,11 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@types/express-serve-static-core", [ - ["npm:4.17.19", { - "packageLocation": "./.yarn/cache/@types-express-serve-static-core-npm-4.17.19-3f514f7e12-b6c8c357c5.zip/node_modules/@types/express-serve-static-core/", + ["npm:4.17.21", { + "packageLocation": "./.yarn/cache/@types-express-serve-static-core-npm-4.17.21-a9ca773254-437165cc12.zip/node_modules/@types/express-serve-static-core/", "packageDependencies": [ - ["@types/express-serve-static-core", "npm:4.17.19"], - ["@types/node", "npm:15.3.0"], + ["@types/express-serve-static-core", "npm:4.17.21"], + ["@types/node", "npm:15.12.4"], ["@types/qs", "npm:6.9.6"], ["@types/range-parser", "npm:1.2.3"] ], @@ -340,7 +340,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/@types-keyv-npm-3.1.1-779a80f2c7-3aaf557d5b.zip/node_modules/@types/keyv/", "packageDependencies": [ ["@types/keyv", "npm:3.1.1"], - ["@types/node", "npm:15.3.0"] + ["@types/node", "npm:15.12.4"] ], "linkType": "HARD", }] @@ -355,17 +355,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@types/node", [ - ["npm:14.17.0", { - "packageLocation": "./.yarn/cache/@types-node-npm-14.17.0-2942ba859f-f437147b39.zip/node_modules/@types/node/", + ["npm:14.17.3", { + "packageLocation": "./.yarn/cache/@types-node-npm-14.17.3-e3cd89920d-0d3e3c3dbb.zip/node_modules/@types/node/", "packageDependencies": [ - ["@types/node", "npm:14.17.0"] + ["@types/node", "npm:14.17.3"] ], "linkType": "HARD", }], - ["npm:15.3.0", { - "packageLocation": "./.yarn/cache/@types-node-npm-15.3.0-7ebc66d6bc-44039665ab.zip/node_modules/@types/node/", + ["npm:15.12.4", { + "packageLocation": "./.yarn/cache/@types-node-npm-15.12.4-9b6a9838ed-64b121a7e8.zip/node_modules/@types/node/", "packageDependencies": [ - ["@types/node", "npm:15.3.0"] + ["@types/node", "npm:15.12.4"] ], "linkType": "HARD", }] @@ -393,7 +393,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/@types-responselike-npm-1.0.0-85dd08af42-e6e6613c80.zip/node_modules/@types/responselike/", "packageDependencies": [ ["@types/responselike", "npm:1.0.0"], - ["@types/node", "npm:15.3.0"] + ["@types/node", "npm:15.12.4"] ], "linkType": "HARD", }] @@ -404,7 +404,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [ ["@types/serve-static", "npm:1.13.9"], ["@types/mime", "npm:1.3.2"], - ["@types/node", "npm:15.3.0"] + ["@types/node", "npm:15.12.4"] ], "linkType": "HARD", }] @@ -419,40 +419,40 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@types/ws", [ - ["npm:7.4.4", { - "packageLocation": "./.yarn/cache/@types-ws-npm-7.4.4-63bcbe5794-6a02b31642.zip/node_modules/@types/ws/", + ["npm:7.4.5", { + "packageLocation": "./.yarn/cache/@types-ws-npm-7.4.5-3f11000a5b-b467f596cc.zip/node_modules/@types/ws/", "packageDependencies": [ - ["@types/ws", "npm:7.4.4"], - ["@types/node", "npm:15.3.0"] + ["@types/ws", "npm:7.4.5"], + ["@types/node", "npm:15.12.4"] ], "linkType": "HARD", }] ]], ["@typescript-eslint/eslint-plugin", [ - ["npm:4.24.0", { - "packageLocation": "./.yarn/cache/@typescript-eslint-eslint-plugin-npm-4.24.0-0ce39c60ea-b3fb023320.zip/node_modules/@typescript-eslint/eslint-plugin/", + ["npm:4.27.0", { + "packageLocation": "./.yarn/cache/@typescript-eslint-eslint-plugin-npm-4.27.0-0af934a50c-6f5e556c92.zip/node_modules/@typescript-eslint/eslint-plugin/", "packageDependencies": [ - ["@typescript-eslint/eslint-plugin", "npm:4.24.0"] + ["@typescript-eslint/eslint-plugin", "npm:4.27.0"] ], "linkType": "SOFT", }], - ["virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.24.0", { - "packageLocation": "./.yarn/$$virtual/@typescript-eslint-eslint-plugin-virtual-9a8b1f31df/0/cache/@typescript-eslint-eslint-plugin-npm-4.24.0-0ce39c60ea-b3fb023320.zip/node_modules/@typescript-eslint/eslint-plugin/", + ["virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.27.0", { + "packageLocation": "./.yarn/$$virtual/@typescript-eslint-eslint-plugin-virtual-5e3c68ea71/0/cache/@typescript-eslint-eslint-plugin-npm-4.27.0-0af934a50c-6f5e556c92.zip/node_modules/@typescript-eslint/eslint-plugin/", "packageDependencies": [ - ["@typescript-eslint/eslint-plugin", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.24.0"], + ["@typescript-eslint/eslint-plugin", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.27.0"], ["@types/eslint", null], ["@types/typescript-eslint__parser", null], - ["@typescript-eslint/experimental-utils", "virtual:9a8b1f31dfb77b858353b17f1156b28813da74b21de747b5c31939cc4aa66de00a18bbe787c84699160d9cbc5a6e50e8d05774ecfe3004ea2748f8e905a5daf3#npm:4.24.0"], - ["@typescript-eslint/parser", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.24.0"], - ["@typescript-eslint/scope-manager", "npm:4.24.0"], - ["debug", "virtual:48933b28331d16c1d73786360e7ba20f54f6df4949c6ab5c13ac4c4353b5c70f2d36a97de9a9c531027ad3588d8fd7f384706f298f0eff0356b58bb9c47f63ec#npm:4.3.1"], - ["eslint", "npm:7.26.0"], + ["@typescript-eslint/experimental-utils", "virtual:5e3c68ea71d0b85646d5a078b5b56e0e5243913f1ce1e78c84511da03cdd76ce978b3e42d3ba35119262d370b55b3e2f8b85ed81eb2b2f2ec218791b4ccc2dbb#npm:4.27.0"], + ["@typescript-eslint/parser", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.27.0"], + ["@typescript-eslint/scope-manager", "npm:4.27.0"], + ["debug", "virtual:428f325a939c2653ad822eb3d75efb02ac311523dd0d4f9645afc39ea00bd86eceac35a9d59c9b6977d76b670a4ef0ae057ea572338a44729aa592711a8c05a3#npm:4.3.2"], + ["eslint", "npm:7.29.0"], ["functional-red-black-tree", "npm:1.0.1"], ["lodash", "npm:4.17.21"], - ["regexpp", "npm:3.1.0"], + ["regexpp", "npm:3.2.0"], ["semver", "npm:7.3.5"], - ["tsutils", "virtual:9a8b1f31dfb77b858353b17f1156b28813da74b21de747b5c31939cc4aa66de00a18bbe787c84699160d9cbc5a6e50e8d05774ecfe3004ea2748f8e905a5daf3#npm:3.21.0"], - ["typescript", "patch:typescript@npm%3A4.2.4#builtin<compat/typescript>::version=4.2.4&hash=ddfc1b"] + ["tsutils", "virtual:5e3c68ea71d0b85646d5a078b5b56e0e5243913f1ce1e78c84511da03cdd76ce978b3e42d3ba35119262d370b55b3e2f8b85ed81eb2b2f2ec218791b4ccc2dbb#npm:3.21.0"], + ["typescript", "patch:typescript@npm%3A4.3.4#builtin<compat/typescript>::version=4.3.4&hash=ddfc1b"] ], "packagePeers": [ "@types/eslint", @@ -465,25 +465,25 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@typescript-eslint/experimental-utils", [ - ["npm:4.24.0", { - "packageLocation": "./.yarn/cache/@typescript-eslint-experimental-utils-npm-4.24.0-d90fb8ab66-09a28e2b8b.zip/node_modules/@typescript-eslint/experimental-utils/", + ["npm:4.27.0", { + "packageLocation": "./.yarn/cache/@typescript-eslint-experimental-utils-npm-4.27.0-fea7db542f-b8c66eceeb.zip/node_modules/@typescript-eslint/experimental-utils/", "packageDependencies": [ - ["@typescript-eslint/experimental-utils", "npm:4.24.0"] + ["@typescript-eslint/experimental-utils", "npm:4.27.0"] ], "linkType": "SOFT", }], - ["virtual:9a8b1f31dfb77b858353b17f1156b28813da74b21de747b5c31939cc4aa66de00a18bbe787c84699160d9cbc5a6e50e8d05774ecfe3004ea2748f8e905a5daf3#npm:4.24.0", { - "packageLocation": "./.yarn/$$virtual/@typescript-eslint-experimental-utils-virtual-00d4f768ef/0/cache/@typescript-eslint-experimental-utils-npm-4.24.0-d90fb8ab66-09a28e2b8b.zip/node_modules/@typescript-eslint/experimental-utils/", + ["virtual:5e3c68ea71d0b85646d5a078b5b56e0e5243913f1ce1e78c84511da03cdd76ce978b3e42d3ba35119262d370b55b3e2f8b85ed81eb2b2f2ec218791b4ccc2dbb#npm:4.27.0", { + "packageLocation": "./.yarn/$$virtual/@typescript-eslint-experimental-utils-virtual-e57695d830/0/cache/@typescript-eslint-experimental-utils-npm-4.27.0-fea7db542f-b8c66eceeb.zip/node_modules/@typescript-eslint/experimental-utils/", "packageDependencies": [ - ["@typescript-eslint/experimental-utils", "virtual:9a8b1f31dfb77b858353b17f1156b28813da74b21de747b5c31939cc4aa66de00a18bbe787c84699160d9cbc5a6e50e8d05774ecfe3004ea2748f8e905a5daf3#npm:4.24.0"], + ["@typescript-eslint/experimental-utils", "virtual:5e3c68ea71d0b85646d5a078b5b56e0e5243913f1ce1e78c84511da03cdd76ce978b3e42d3ba35119262d370b55b3e2f8b85ed81eb2b2f2ec218791b4ccc2dbb#npm:4.27.0"], ["@types/eslint", null], ["@types/json-schema", "npm:7.0.7"], - ["@typescript-eslint/scope-manager", "npm:4.24.0"], - ["@typescript-eslint/types", "npm:4.24.0"], - ["@typescript-eslint/typescript-estree", "virtual:00d4f768ef22a51647431e1ae9936afa118b642d86ded0fc8390d8b5c78f4c6b517fb84974a722b14fb74b78155de06450060dacb8edf35b4ec0acf103c6450f#npm:4.24.0"], - ["eslint", "npm:7.26.0"], + ["@typescript-eslint/scope-manager", "npm:4.27.0"], + ["@typescript-eslint/types", "npm:4.27.0"], + ["@typescript-eslint/typescript-estree", "virtual:e57695d83029b064e6336fe25471f739df8a339786b8a1316f12613926df9c9e05571d288732c3697d74eeca532d4849cea8bb96f8902aaccae4b7c39672c979#npm:4.27.0"], + ["eslint", "npm:7.29.0"], ["eslint-scope", "npm:5.1.1"], - ["eslint-utils", "npm:2.1.0"] + ["eslint-utils", "virtual:e57695d83029b064e6336fe25471f739df8a339786b8a1316f12613926df9c9e05571d288732c3697d74eeca532d4849cea8bb96f8902aaccae4b7c39672c979#npm:3.0.0"] ], "packagePeers": [ "@types/eslint", @@ -493,24 +493,24 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@typescript-eslint/parser", [ - ["npm:4.24.0", { - "packageLocation": "./.yarn/cache/@typescript-eslint-parser-npm-4.24.0-edf27f205d-30ff5e6b1e.zip/node_modules/@typescript-eslint/parser/", + ["npm:4.27.0", { + "packageLocation": "./.yarn/cache/@typescript-eslint-parser-npm-4.27.0-468acd136e-cfe1b6b2c1.zip/node_modules/@typescript-eslint/parser/", "packageDependencies": [ - ["@typescript-eslint/parser", "npm:4.24.0"] + ["@typescript-eslint/parser", "npm:4.27.0"] ], "linkType": "SOFT", }], - ["virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.24.0", { - "packageLocation": "./.yarn/$$virtual/@typescript-eslint-parser-virtual-7bb7c6f3eb/0/cache/@typescript-eslint-parser-npm-4.24.0-edf27f205d-30ff5e6b1e.zip/node_modules/@typescript-eslint/parser/", + ["virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.27.0", { + "packageLocation": "./.yarn/$$virtual/@typescript-eslint-parser-virtual-5af56ff49c/0/cache/@typescript-eslint-parser-npm-4.27.0-468acd136e-cfe1b6b2c1.zip/node_modules/@typescript-eslint/parser/", "packageDependencies": [ - ["@typescript-eslint/parser", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.24.0"], + ["@typescript-eslint/parser", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.27.0"], ["@types/eslint", null], - ["@typescript-eslint/scope-manager", "npm:4.24.0"], - ["@typescript-eslint/types", "npm:4.24.0"], - ["@typescript-eslint/typescript-estree", "virtual:7bb7c6f3eb88073237dc8bd329fee28f7e2588dfad4bba4d65b428475804ad37b87c371b15a187000b71c3d01e8132cf4e7496c0fbc07b0e26587102cd6e49d6#npm:4.24.0"], - ["debug", "virtual:48933b28331d16c1d73786360e7ba20f54f6df4949c6ab5c13ac4c4353b5c70f2d36a97de9a9c531027ad3588d8fd7f384706f298f0eff0356b58bb9c47f63ec#npm:4.3.1"], - ["eslint", "npm:7.26.0"], - ["typescript", "patch:typescript@npm%3A4.2.4#builtin<compat/typescript>::version=4.2.4&hash=ddfc1b"] + ["@typescript-eslint/scope-manager", "npm:4.27.0"], + ["@typescript-eslint/types", "npm:4.27.0"], + ["@typescript-eslint/typescript-estree", "virtual:5af56ff49cdc1acb6a87357d13c1523c79d7c7d4f960f9e1ba6e39e78b84263fa0d8c4d42471a368ec57993897e9a13a2d9b5a62bfeaf3579d0a24b94eb9bf13#npm:4.27.0"], + ["debug", "virtual:428f325a939c2653ad822eb3d75efb02ac311523dd0d4f9645afc39ea00bd86eceac35a9d59c9b6977d76b670a4ef0ae057ea572338a44729aa592711a8c05a3#npm:4.3.2"], + ["eslint", "npm:7.29.0"], + ["typescript", "patch:typescript@npm%3A4.3.4#builtin<compat/typescript>::version=4.3.4&hash=ddfc1b"] ], "packagePeers": [ "@types/eslint", @@ -521,63 +521,63 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@typescript-eslint/scope-manager", [ - ["npm:4.24.0", { - "packageLocation": "./.yarn/cache/@typescript-eslint-scope-manager-npm-4.24.0-3e86fd64d6-522d96e562.zip/node_modules/@typescript-eslint/scope-manager/", + ["npm:4.27.0", { + "packageLocation": "./.yarn/cache/@typescript-eslint-scope-manager-npm-4.27.0-0bb68362d5-5d39a2dda0.zip/node_modules/@typescript-eslint/scope-manager/", "packageDependencies": [ - ["@typescript-eslint/scope-manager", "npm:4.24.0"], - ["@typescript-eslint/types", "npm:4.24.0"], - ["@typescript-eslint/visitor-keys", "npm:4.24.0"] + ["@typescript-eslint/scope-manager", "npm:4.27.0"], + ["@typescript-eslint/types", "npm:4.27.0"], + ["@typescript-eslint/visitor-keys", "npm:4.27.0"] ], "linkType": "HARD", }] ]], ["@typescript-eslint/types", [ - ["npm:4.24.0", { - "packageLocation": "./.yarn/cache/@typescript-eslint-types-npm-4.24.0-bafa68a7d5-ed06724661.zip/node_modules/@typescript-eslint/types/", + ["npm:4.27.0", { + "packageLocation": "./.yarn/cache/@typescript-eslint-types-npm-4.27.0-58b825b72d-b9540fdf5c.zip/node_modules/@typescript-eslint/types/", "packageDependencies": [ - ["@typescript-eslint/types", "npm:4.24.0"] + ["@typescript-eslint/types", "npm:4.27.0"] ], "linkType": "HARD", }] ]], ["@typescript-eslint/typescript-estree", [ - ["npm:4.24.0", { - "packageLocation": "./.yarn/cache/@typescript-eslint-typescript-estree-npm-4.24.0-b44f4a8df5-7720b1f5e8.zip/node_modules/@typescript-eslint/typescript-estree/", + ["npm:4.27.0", { + "packageLocation": "./.yarn/cache/@typescript-eslint-typescript-estree-npm-4.27.0-fe38ab3ca4-dc9711dab7.zip/node_modules/@typescript-eslint/typescript-estree/", "packageDependencies": [ - ["@typescript-eslint/typescript-estree", "npm:4.24.0"] + ["@typescript-eslint/typescript-estree", "npm:4.27.0"] ], "linkType": "SOFT", }], - ["virtual:00d4f768ef22a51647431e1ae9936afa118b642d86ded0fc8390d8b5c78f4c6b517fb84974a722b14fb74b78155de06450060dacb8edf35b4ec0acf103c6450f#npm:4.24.0", { - "packageLocation": "./.yarn/$$virtual/@typescript-eslint-typescript-estree-virtual-24ccaee8f2/0/cache/@typescript-eslint-typescript-estree-npm-4.24.0-b44f4a8df5-7720b1f5e8.zip/node_modules/@typescript-eslint/typescript-estree/", - "packageDependencies": [ - ["@typescript-eslint/typescript-estree", "virtual:00d4f768ef22a51647431e1ae9936afa118b642d86ded0fc8390d8b5c78f4c6b517fb84974a722b14fb74b78155de06450060dacb8edf35b4ec0acf103c6450f#npm:4.24.0"], - ["@typescript-eslint/types", "npm:4.24.0"], - ["@typescript-eslint/visitor-keys", "npm:4.24.0"], - ["debug", "virtual:48933b28331d16c1d73786360e7ba20f54f6df4949c6ab5c13ac4c4353b5c70f2d36a97de9a9c531027ad3588d8fd7f384706f298f0eff0356b58bb9c47f63ec#npm:4.3.1"], - ["globby", "npm:11.0.3"], + ["virtual:5af56ff49cdc1acb6a87357d13c1523c79d7c7d4f960f9e1ba6e39e78b84263fa0d8c4d42471a368ec57993897e9a13a2d9b5a62bfeaf3579d0a24b94eb9bf13#npm:4.27.0", { + "packageLocation": "./.yarn/$$virtual/@typescript-eslint-typescript-estree-virtual-84a436f51d/0/cache/@typescript-eslint-typescript-estree-npm-4.27.0-fe38ab3ca4-dc9711dab7.zip/node_modules/@typescript-eslint/typescript-estree/", + "packageDependencies": [ + ["@typescript-eslint/typescript-estree", "virtual:5af56ff49cdc1acb6a87357d13c1523c79d7c7d4f960f9e1ba6e39e78b84263fa0d8c4d42471a368ec57993897e9a13a2d9b5a62bfeaf3579d0a24b94eb9bf13#npm:4.27.0"], + ["@typescript-eslint/types", "npm:4.27.0"], + ["@typescript-eslint/visitor-keys", "npm:4.27.0"], + ["debug", "virtual:428f325a939c2653ad822eb3d75efb02ac311523dd0d4f9645afc39ea00bd86eceac35a9d59c9b6977d76b670a4ef0ae057ea572338a44729aa592711a8c05a3#npm:4.3.2"], + ["globby", "npm:11.0.4"], ["is-glob", "npm:4.0.1"], ["semver", "npm:7.3.5"], - ["tsutils", "virtual:24ccaee8f2a84c341367a0ca54e599e765dd5def7c88fa690af51d687e0dcab63f6a9a9e082854fcee0c56f65cc121b7ea65bf2f8444c2333afcf117d3775385#npm:3.21.0"], - ["typescript", null] + ["tsutils", "virtual:5e3c68ea71d0b85646d5a078b5b56e0e5243913f1ce1e78c84511da03cdd76ce978b3e42d3ba35119262d370b55b3e2f8b85ed81eb2b2f2ec218791b4ccc2dbb#npm:3.21.0"], + ["typescript", "patch:typescript@npm%3A4.3.4#builtin<compat/typescript>::version=4.3.4&hash=ddfc1b"] ], "packagePeers": [ "typescript" ], "linkType": "HARD", }], - ["virtual:7bb7c6f3eb88073237dc8bd329fee28f7e2588dfad4bba4d65b428475804ad37b87c371b15a187000b71c3d01e8132cf4e7496c0fbc07b0e26587102cd6e49d6#npm:4.24.0", { - "packageLocation": "./.yarn/$$virtual/@typescript-eslint-typescript-estree-virtual-577ab8efad/0/cache/@typescript-eslint-typescript-estree-npm-4.24.0-b44f4a8df5-7720b1f5e8.zip/node_modules/@typescript-eslint/typescript-estree/", - "packageDependencies": [ - ["@typescript-eslint/typescript-estree", "virtual:7bb7c6f3eb88073237dc8bd329fee28f7e2588dfad4bba4d65b428475804ad37b87c371b15a187000b71c3d01e8132cf4e7496c0fbc07b0e26587102cd6e49d6#npm:4.24.0"], - ["@typescript-eslint/types", "npm:4.24.0"], - ["@typescript-eslint/visitor-keys", "npm:4.24.0"], - ["debug", "virtual:48933b28331d16c1d73786360e7ba20f54f6df4949c6ab5c13ac4c4353b5c70f2d36a97de9a9c531027ad3588d8fd7f384706f298f0eff0356b58bb9c47f63ec#npm:4.3.1"], - ["globby", "npm:11.0.3"], + ["virtual:e57695d83029b064e6336fe25471f739df8a339786b8a1316f12613926df9c9e05571d288732c3697d74eeca532d4849cea8bb96f8902aaccae4b7c39672c979#npm:4.27.0", { + "packageLocation": "./.yarn/$$virtual/@typescript-eslint-typescript-estree-virtual-16af2f56ad/0/cache/@typescript-eslint-typescript-estree-npm-4.27.0-fe38ab3ca4-dc9711dab7.zip/node_modules/@typescript-eslint/typescript-estree/", + "packageDependencies": [ + ["@typescript-eslint/typescript-estree", "virtual:e57695d83029b064e6336fe25471f739df8a339786b8a1316f12613926df9c9e05571d288732c3697d74eeca532d4849cea8bb96f8902aaccae4b7c39672c979#npm:4.27.0"], + ["@typescript-eslint/types", "npm:4.27.0"], + ["@typescript-eslint/visitor-keys", "npm:4.27.0"], + ["debug", "virtual:428f325a939c2653ad822eb3d75efb02ac311523dd0d4f9645afc39ea00bd86eceac35a9d59c9b6977d76b670a4ef0ae057ea572338a44729aa592711a8c05a3#npm:4.3.2"], + ["globby", "npm:11.0.4"], ["is-glob", "npm:4.0.1"], ["semver", "npm:7.3.5"], - ["tsutils", "virtual:9a8b1f31dfb77b858353b17f1156b28813da74b21de747b5c31939cc4aa66de00a18bbe787c84699160d9cbc5a6e50e8d05774ecfe3004ea2748f8e905a5daf3#npm:3.21.0"], - ["typescript", "patch:typescript@npm%3A4.2.4#builtin<compat/typescript>::version=4.2.4&hash=ddfc1b"] + ["tsutils", "virtual:16af2f56ad2b3a09ed5bd79b3980969472fcaef4f709b1eeb504d7929351e825862f727dd5f45329be93f78cd6ec914b29a54d9f2df679571d57b82c3a0d8e07#npm:3.21.0"], + ["typescript", null] ], "packagePeers": [ "typescript" @@ -586,11 +586,11 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["@typescript-eslint/visitor-keys", [ - ["npm:4.24.0", { - "packageLocation": "./.yarn/cache/@typescript-eslint-visitor-keys-npm-4.24.0-6745f8fb33-ec25df6705.zip/node_modules/@typescript-eslint/visitor-keys/", + ["npm:4.27.0", { + "packageLocation": "./.yarn/cache/@typescript-eslint-visitor-keys-npm-4.27.0-57c16a6eef-d600de56ce.zip/node_modules/@typescript-eslint/visitor-keys/", "packageDependencies": [ - ["@typescript-eslint/visitor-keys", "npm:4.24.0"], - ["@typescript-eslint/types", "npm:4.24.0"], + ["@typescript-eslint/visitor-keys", "npm:4.27.0"], + ["@typescript-eslint/types", "npm:4.27.0"], ["eslint-visitor-keys", "npm:2.1.0"] ], "linkType": "HARD", @@ -691,10 +691,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "HARD", }], - ["npm:8.4.0", { - "packageLocation": "./.yarn/cache/ajv-npm-8.4.0-1d671a4d5f-0dcdfe0eca.zip/node_modules/ajv/", + ["npm:8.6.0", { + "packageLocation": "./.yarn/cache/ajv-npm-8.6.0-74c534c16b-4eed9ee72e.zip/node_modules/ajv/", "packageDependencies": [ - ["ajv", "npm:8.4.0"], + ["ajv", "npm:8.6.0"], ["fast-deep-equal", "npm:3.1.3"], ["json-schema-traverse", "npm:1.0.0"], ["require-from-string", "npm:2.0.2"], @@ -893,30 +893,30 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["bush-bot", "workspace:."], ["@discordjs/voice", "npm:0.4.0"], ["@types/common-tags", "npm:1.8.0"], - ["@types/express", "npm:4.17.11"], - ["@types/node", "npm:14.17.0"], + ["@types/express", "npm:4.17.12"], + ["@types/node", "npm:14.17.3"], ["@types/uuid", "npm:8.3.0"], - ["@typescript-eslint/eslint-plugin", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.24.0"], - ["@typescript-eslint/parser", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.24.0"], + ["@typescript-eslint/eslint-plugin", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.27.0"], + ["@typescript-eslint/parser", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:4.27.0"], ["body-parser", "npm:1.19.0"], ["canvas", "npm:2.8.0"], ["chalk", "npm:4.1.1"], ["common-tags", "npm:1.8.0"], - ["discord-akairo", "https://github.com/IRONM00N-Development/discord-akairo.git#commit=690c219497dff280dd49360882f72ddd100fc148"], + ["discord-akairo", "https://github.com/NotEnoughUpdates/discord-akairo.git#commit=98309bfc2b384cb41610ab7221fcd683fe8e2f88"], ["discord-api-types", "npm:0.18.1"], - ["discord.js", "npm:13.0.0-dev.918921e8211fc16e9b12d2502f3168264246ea22"], - ["esbuild", "npm:0.12.1"], - ["eslint", "npm:7.26.0"], + ["discord.js", "npm:13.0.0-dev.807ea2d3c197c7c6556bd1c894114932f6657d49"], + ["esbuild", "npm:0.12.9"], + ["eslint", "npm:7.29.0"], ["eslint-config-prettier", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:8.3.0"], ["got", "npm:11.8.2"], ["moment", "npm:2.29.1"], ["pg", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:8.6.0"], - ["pg-hstore", "npm:2.3.3"], - ["prettier", "npm:2.3.0"], + ["pg-hstore", "npm:2.3.4"], + ["prettier", "npm:2.3.1"], ["rimraf", "npm:3.0.2"], ["sequelize", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:6.6.2"], ["source-map-support", "npm:0.5.19"], - ["typescript", "patch:typescript@npm%3A4.2.4#builtin<compat/typescript>::version=4.2.4&hash=ddfc1b"], + ["typescript", "patch:typescript@npm%3A4.3.4#builtin<compat/typescript>::version=4.3.4&hash=ddfc1b"], ["uuid", "npm:8.3.2"] ], "linkType": "SOFT", @@ -967,16 +967,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["cacheable-request", [ - ["npm:7.0.1", { - "packageLocation": "./.yarn/cache/cacheable-request-npm-7.0.1-d870be2496-fe0b6f3b8a.zip/node_modules/cacheable-request/", + ["npm:7.0.2", { + "packageLocation": "./.yarn/cache/cacheable-request-npm-7.0.2-e64cc641fc-176a1fceb9.zip/node_modules/cacheable-request/", "packageDependencies": [ - ["cacheable-request", "npm:7.0.1"], + ["cacheable-request", "npm:7.0.2"], ["clone-response", "npm:1.0.2"], ["get-stream", "npm:5.2.0"], ["http-cache-semantics", "npm:4.1.0"], ["keyv", "npm:4.0.3"], ["lowercase-keys", "npm:2.0.0"], - ["normalize-url", "npm:4.5.0"], + ["normalize-url", "npm:6.0.1"], ["responselike", "npm:2.0.0"] ], "linkType": "HARD", @@ -998,7 +998,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["canvas", "npm:2.8.0"], ["@mapbox/node-pre-gyp", "npm:1.0.5"], ["nan", "npm:2.14.2"], - ["node-gyp", "npm:8.0.0"], + ["node-gyp", "npm:8.1.0"], ["simple-get", "npm:3.1.0"] ], "linkType": "HARD", @@ -1171,13 +1171,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "SOFT", }], - ["npm:4.3.1", { - "packageLocation": "./.yarn/cache/debug-npm-4.3.1-22e08d605e-0d41ba5177.zip/node_modules/debug/", - "packageDependencies": [ - ["debug", "npm:4.3.1"] - ], - "linkType": "SOFT", - }], ["npm:4.3.2", { "packageLocation": "./.yarn/cache/debug-npm-4.3.2-f0148b6afe-5543570879.zip/node_modules/debug/", "packageDependencies": [ @@ -1197,18 +1190,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "HARD", }], - ["virtual:48933b28331d16c1d73786360e7ba20f54f6df4949c6ab5c13ac4c4353b5c70f2d36a97de9a9c531027ad3588d8fd7f384706f298f0eff0356b58bb9c47f63ec#npm:4.3.1", { - "packageLocation": "./.yarn/$$virtual/debug-virtual-9b1bbab664/0/cache/debug-npm-4.3.1-22e08d605e-0d41ba5177.zip/node_modules/debug/", - "packageDependencies": [ - ["debug", "virtual:48933b28331d16c1d73786360e7ba20f54f6df4949c6ab5c13ac4c4353b5c70f2d36a97de9a9c531027ad3588d8fd7f384706f298f0eff0356b58bb9c47f63ec#npm:4.3.1"], - ["ms", "npm:2.1.2"], - ["supports-color", null] - ], - "packagePeers": [ - "supports-color" - ], - "linkType": "HARD", - }], ["virtual:6e177cabfad012f413f9c41366539c04d8701f0567119998690ab02224012faa99ec3a16b9f74f4d7920ab472c12b3e70f47f8f143239c06d0e2569e60ed9f62#npm:2.6.9", { "packageLocation": "./.yarn/$$virtual/debug-virtual-53242bdd6a/0/cache/debug-npm-2.6.9-7d4cb597dc-559f44f98c.zip/node_modules/debug/", "packageDependencies": [ @@ -1305,10 +1286,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["discord-akairo", [ - ["https://github.com/IRONM00N-Development/discord-akairo.git#commit=690c219497dff280dd49360882f72ddd100fc148", { - "packageLocation": "./.yarn/cache/discord-akairo-https-7a05c1a24f-cfce18b1f6.zip/node_modules/discord-akairo/", + ["https://github.com/NotEnoughUpdates/discord-akairo.git#commit=98309bfc2b384cb41610ab7221fcd683fe8e2f88", { + "packageLocation": "./.yarn/cache/discord-akairo-https-c860bfd0e1-f00d40033a.zip/node_modules/discord-akairo/", "packageDependencies": [ - ["discord-akairo", "https://github.com/IRONM00N-Development/discord-akairo.git#commit=690c219497dff280dd49360882f72ddd100fc148"] + ["discord-akairo", "https://github.com/NotEnoughUpdates/discord-akairo.git#commit=98309bfc2b384cb41610ab7221fcd683fe8e2f88"] ], "linkType": "HARD", }] @@ -1323,18 +1304,18 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["discord.js", [ - ["npm:13.0.0-dev.918921e8211fc16e9b12d2502f3168264246ea22", { - "packageLocation": "./.yarn/cache/discord.js-npm-13.0.0-dev.918921e8211fc16e9b12d2502f3168264246ea22-1d25a578dd-be1707f530.zip/node_modules/discord.js/", + ["npm:13.0.0-dev.807ea2d3c197c7c6556bd1c894114932f6657d49", { + "packageLocation": "./.yarn/cache/discord.js-npm-13.0.0-dev.807ea2d3c197c7c6556bd1c894114932f6657d49-d346d07649-6b0cc16761.zip/node_modules/discord.js/", "packageDependencies": [ - ["discord.js", "npm:13.0.0-dev.918921e8211fc16e9b12d2502f3168264246ea22"], + ["discord.js", "npm:13.0.0-dev.807ea2d3c197c7c6556bd1c894114932f6657d49"], ["@discordjs/collection", "npm:0.1.6"], ["@discordjs/form-data", "npm:3.0.1"], ["@sapphire/async-queue", "npm:1.1.3"], - ["@types/ws", "npm:7.4.4"], + ["@types/ws", "npm:7.4.5"], ["abort-controller", "npm:3.0.0"], ["discord-api-types", "npm:0.18.1"], ["node-fetch", "npm:2.6.1"], - ["ws", "virtual:275bceca0f79f8e7aeb7f77acb5a6bd201e7eea264e9dfd8dcc0bcf35691357327303c09557dfc1495b9a1f8e9cf8278133d234783570df6cb70a249778f3198#npm:7.4.6"] + ["ws", "virtual:275bceca0f79f8e7aeb7f77acb5a6bd201e7eea264e9dfd8dcc0bcf35691357327303c09557dfc1495b9a1f8e9cf8278133d234783570df6cb70a249778f3198#npm:7.5.0"] ], "linkType": "HARD", }] @@ -1425,10 +1406,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["esbuild", [ - ["npm:0.12.1", { - "packageLocation": "./.yarn/unplugged/esbuild-npm-0.12.1-ce7e6881a2/node_modules/esbuild/", + ["npm:0.12.9", { + "packageLocation": "./.yarn/unplugged/esbuild-npm-0.12.9-4f6f42d5bd/node_modules/esbuild/", "packageDependencies": [ - ["esbuild", "npm:0.12.1"] + ["esbuild", "npm:0.12.9"] ], "linkType": "HARD", }] @@ -1440,31 +1421,40 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["escape-string-regexp", "npm:1.0.5"] ], "linkType": "HARD", + }], + ["npm:4.0.0", { + "packageLocation": "./.yarn/cache/escape-string-regexp-npm-4.0.0-4b531d8d59-c747be8d5f.zip/node_modules/escape-string-regexp/", + "packageDependencies": [ + ["escape-string-regexp", "npm:4.0.0"] + ], + "linkType": "HARD", }] ]], ["eslint", [ - ["npm:7.26.0", { - "packageLocation": "./.yarn/cache/eslint-npm-7.26.0-0bcc96e5d3-08f99befd7.zip/node_modules/eslint/", + ["npm:7.29.0", { + "packageLocation": "./.yarn/cache/eslint-npm-7.29.0-aec1968387-812f8c5123.zip/node_modules/eslint/", "packageDependencies": [ - ["eslint", "npm:7.26.0"], + ["eslint", "npm:7.29.0"], ["@babel/code-frame", "npm:7.12.11"], - ["@eslint/eslintrc", "npm:0.4.1"], + ["@eslint/eslintrc", "npm:0.4.2"], ["ajv", "npm:6.12.6"], ["chalk", "npm:4.1.1"], ["cross-spawn", "npm:7.0.3"], - ["debug", "virtual:48933b28331d16c1d73786360e7ba20f54f6df4949c6ab5c13ac4c4353b5c70f2d36a97de9a9c531027ad3588d8fd7f384706f298f0eff0356b58bb9c47f63ec#npm:4.3.1"], + ["debug", "virtual:428f325a939c2653ad822eb3d75efb02ac311523dd0d4f9645afc39ea00bd86eceac35a9d59c9b6977d76b670a4ef0ae057ea572338a44729aa592711a8c05a3#npm:4.3.2"], ["doctrine", "npm:3.0.0"], ["enquirer", "npm:2.3.6"], + ["escape-string-regexp", "npm:4.0.0"], ["eslint-scope", "npm:5.1.1"], ["eslint-utils", "npm:2.1.0"], ["eslint-visitor-keys", "npm:2.1.0"], ["espree", "npm:7.3.1"], ["esquery", "npm:1.4.0"], ["esutils", "npm:2.0.3"], + ["fast-deep-equal", "npm:3.1.3"], ["file-entry-cache", "npm:6.0.1"], ["functional-red-black-tree", "npm:1.0.1"], ["glob-parent", "npm:5.1.2"], - ["globals", "npm:13.8.0"], + ["globals", "npm:13.9.0"], ["ignore", "npm:4.0.6"], ["import-fresh", "npm:3.3.0"], ["imurmurhash", "npm:0.1.4"], @@ -1472,12 +1462,12 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["js-yaml", "npm:3.14.1"], ["json-stable-stringify-without-jsonify", "npm:1.0.1"], ["levn", "npm:0.4.1"], - ["lodash", "npm:4.17.21"], + ["lodash.merge", "npm:4.6.2"], ["minimatch", "npm:3.0.4"], ["natural-compare", "npm:1.4.0"], ["optionator", "npm:0.9.1"], ["progress", "npm:2.0.3"], - ["regexpp", "npm:3.1.0"], + ["regexpp", "npm:3.2.0"], ["semver", "npm:7.3.5"], ["strip-ansi", "npm:6.0.0"], ["strip-json-comments", "npm:3.1.1"], @@ -1501,7 +1491,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [ ["eslint-config-prettier", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:8.3.0"], ["@types/eslint", null], - ["eslint", "npm:7.26.0"] + ["eslint", "npm:7.29.0"] ], "packagePeers": [ "@types/eslint", @@ -1529,6 +1519,27 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["eslint-visitor-keys", "npm:1.3.0"] ], "linkType": "HARD", + }], + ["npm:3.0.0", { + "packageLocation": "./.yarn/cache/eslint-utils-npm-3.0.0-630b3a4013-035451529f.zip/node_modules/eslint-utils/", + "packageDependencies": [ + ["eslint-utils", "npm:3.0.0"] + ], + "linkType": "SOFT", + }], + ["virtual:e57695d83029b064e6336fe25471f739df8a339786b8a1316f12613926df9c9e05571d288732c3697d74eeca532d4849cea8bb96f8902aaccae4b7c39672c979#npm:3.0.0", { + "packageLocation": "./.yarn/$$virtual/eslint-utils-virtual-579c662e58/0/cache/eslint-utils-npm-3.0.0-630b3a4013-035451529f.zip/node_modules/eslint-utils/", + "packageDependencies": [ + ["eslint-utils", "virtual:e57695d83029b064e6336fe25471f739df8a339786b8a1316f12613926df9c9e05571d288732c3697d74eeca532d4849cea8bb96f8902aaccae4b7c39672c979#npm:3.0.0"], + ["@types/eslint", null], + ["eslint", "npm:7.29.0"], + ["eslint-visitor-keys", "npm:2.1.0"] + ], + "packagePeers": [ + "@types/eslint", + "eslint" + ], + "linkType": "HARD", }] ]], ["eslint-visitor-keys", [ @@ -1636,12 +1647,12 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/fast-glob-npm-3.2.5-0225b8bd94-1a33c4a68d.zip/node_modules/fast-glob/", "packageDependencies": [ ["fast-glob", "npm:3.2.5"], - ["@nodelib/fs.stat", "npm:2.0.4"], - ["@nodelib/fs.walk", "npm:1.2.6"], + ["@nodelib/fs.stat", "npm:2.0.5"], + ["@nodelib/fs.walk", "npm:1.2.7"], ["glob-parent", "npm:5.1.2"], ["merge2", "npm:1.4.1"], ["micromatch", "npm:4.0.4"], - ["picomatch", "npm:2.2.3"] + ["picomatch", "npm:2.3.0"] ], "linkType": "HARD", }] @@ -1795,28 +1806,20 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["globals", [ - ["npm:12.4.0", { - "packageLocation": "./.yarn/cache/globals-npm-12.4.0-02b5a6ba9c-0b9764bdea.zip/node_modules/globals/", - "packageDependencies": [ - ["globals", "npm:12.4.0"], - ["type-fest", "npm:0.8.1"] - ], - "linkType": "HARD", - }], - ["npm:13.8.0", { - "packageLocation": "./.yarn/cache/globals-npm-13.8.0-0988f60ed8-de85e5dc89.zip/node_modules/globals/", + ["npm:13.9.0", { + "packageLocation": "./.yarn/cache/globals-npm-13.9.0-364a8ebd6b-26d71f2c28.zip/node_modules/globals/", "packageDependencies": [ - ["globals", "npm:13.8.0"], + ["globals", "npm:13.9.0"], ["type-fest", "npm:0.20.2"] ], "linkType": "HARD", }] ]], ["globby", [ - ["npm:11.0.3", { - "packageLocation": "./.yarn/cache/globby-npm-11.0.3-bb0a10f600-f17da0f869.zip/node_modules/globby/", + ["npm:11.0.4", { + "packageLocation": "./.yarn/cache/globby-npm-11.0.4-592ce71cca-9f365b35b8.zip/node_modules/globby/", "packageDependencies": [ - ["globby", "npm:11.0.3"], + ["globby", "npm:11.0.4"], ["array-union", "npm:2.1.0"], ["dir-glob", "npm:3.0.1"], ["fast-glob", "npm:3.2.5"], @@ -1837,7 +1840,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/cacheable-request", "npm:6.0.1"], ["@types/responselike", "npm:1.0.0"], ["cacheable-lookup", "npm:5.0.4"], - ["cacheable-request", "npm:7.0.1"], + ["cacheable-request", "npm:7.0.2"], ["decompress-response", "npm:6.0.0"], ["http2-wrapper", "npm:1.0.3"], ["lowercase-keys", "npm:2.0.0"], @@ -2237,6 +2240,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["lodash.merge", [ + ["npm:4.6.2", { + "packageLocation": "./.yarn/cache/lodash.merge-npm-4.6.2-77cb4416bf-4e2bb42a87.zip/node_modules/lodash.merge/", + "packageDependencies": [ + ["lodash.merge", "npm:4.6.2"] + ], + "linkType": "HARD", + }] + ]], ["lodash.truncate", [ ["npm:4.4.2", { "packageLocation": "./.yarn/cache/lodash.truncate-npm-4.4.2-bc50fe1663-b1b0d7d993.zip/node_modules/lodash.truncate/", @@ -2323,26 +2335,26 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [ ["micromatch", "npm:4.0.4"], ["braces", "npm:3.0.2"], - ["picomatch", "npm:2.2.3"] + ["picomatch", "npm:2.3.0"] ], "linkType": "HARD", }] ]], ["mime-db", [ - ["npm:1.47.0", { - "packageLocation": "./.yarn/cache/mime-db-npm-1.47.0-a85d74ef62-f5f9220dd5.zip/node_modules/mime-db/", + ["npm:1.48.0", { + "packageLocation": "./.yarn/cache/mime-db-npm-1.48.0-d896dd3151-346d5df2ff.zip/node_modules/mime-db/", "packageDependencies": [ - ["mime-db", "npm:1.47.0"] + ["mime-db", "npm:1.48.0"] ], "linkType": "HARD", }] ]], ["mime-types", [ - ["npm:2.1.30", { - "packageLocation": "./.yarn/cache/mime-types-npm-2.1.30-500b101efd-c7ca8a9980.zip/node_modules/mime-types/", + ["npm:2.1.31", { + "packageLocation": "./.yarn/cache/mime-types-npm-2.1.31-fbe9a57bbf-0373e58e38.zip/node_modules/mime-types/", "packageDependencies": [ - ["mime-types", "npm:2.1.30"], - ["mime-db", "npm:1.47.0"] + ["mime-types", "npm:2.1.31"], + ["mime-db", "npm:1.48.0"] ], "linkType": "HARD", }] @@ -2510,7 +2522,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/unplugged/nan-npm-2.14.2-e3ede8ce5d/node_modules/nan/", "packageDependencies": [ ["nan", "npm:2.14.2"], - ["node-gyp", "npm:8.0.0"] + ["node-gyp", "npm:8.1.0"] ], "linkType": "HARD", }] @@ -2534,10 +2546,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["node-gyp", [ - ["npm:8.0.0", { - "packageLocation": "./.yarn/unplugged/node-gyp-npm-8.0.0-a27599670d/node_modules/node-gyp/", + ["npm:8.1.0", { + "packageLocation": "./.yarn/unplugged/node-gyp-npm-8.1.0-30cf500e19/node_modules/node-gyp/", "packageDependencies": [ - ["node-gyp", "npm:8.0.0"], + ["node-gyp", "npm:8.1.0"], ["env-paths", "npm:2.2.1"], ["glob", "npm:7.1.7"], ["graceful-fs", "npm:4.2.6"], @@ -2563,10 +2575,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["normalize-url", [ - ["npm:4.5.0", { - "packageLocation": "./.yarn/cache/normalize-url-npm-4.5.0-14a0c5430f-09794941db.zip/node_modules/normalize-url/", + ["npm:6.0.1", { + "packageLocation": "./.yarn/cache/normalize-url-npm-6.0.1-1df8202fbc-63fe38bbc1.zip/node_modules/normalize-url/", "packageDependencies": [ - ["normalize-url", "npm:4.5.0"] + ["normalize-url", "npm:6.0.1"] ], "linkType": "HARD", }] @@ -2741,10 +2753,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["pg-hstore", [ - ["npm:2.3.3", { - "packageLocation": "./.yarn/cache/pg-hstore-npm-2.3.3-b7efa5de02-8e496d4800.zip/node_modules/pg-hstore/", + ["npm:2.3.4", { + "packageLocation": "./.yarn/cache/pg-hstore-npm-2.3.4-50bf9a8242-336eef3626.zip/node_modules/pg-hstore/", "packageDependencies": [ - ["pg-hstore", "npm:2.3.3"], + ["pg-hstore", "npm:2.3.4"], ["underscore", "npm:1.13.1"] ], "linkType": "HARD", @@ -2815,10 +2827,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["picomatch", [ - ["npm:2.2.3", { - "packageLocation": "./.yarn/cache/picomatch-npm-2.2.3-3797e21cf0-f8c9323bc3.zip/node_modules/picomatch/", + ["npm:2.3.0", { + "packageLocation": "./.yarn/cache/picomatch-npm-2.3.0-5e60e6c82d-80113a0fb7.zip/node_modules/picomatch/", "packageDependencies": [ - ["picomatch", "npm:2.2.3"] + ["picomatch", "npm:2.3.0"] ], "linkType": "HARD", }] @@ -2870,10 +2882,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["prettier", [ - ["npm:2.3.0", { - "packageLocation": "./.yarn/cache/prettier-npm-2.3.0-29ef37e8b6-652640cc8b.zip/node_modules/prettier/", + ["npm:2.3.1", { + "packageLocation": "./.yarn/unplugged/prettier-npm-2.3.1-f8593fac45/node_modules/prettier/", "packageDependencies": [ - ["prettier", "npm:2.3.0"] + ["prettier", "npm:2.3.1"] ], "linkType": "HARD", }] @@ -3048,10 +3060,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["regexpp", [ - ["npm:3.1.0", { - "packageLocation": "./.yarn/cache/regexpp-npm-3.1.0-94a1868d49-69d0ce6b44.zip/node_modules/regexpp/", + ["npm:3.2.0", { + "packageLocation": "./.yarn/cache/regexpp-npm-3.2.0-2513f32cfc-91aaccadd0.zip/node_modules/regexpp/", "packageDependencies": [ - ["regexpp", "npm:3.1.0"] + ["regexpp", "npm:3.2.0"] ], "linkType": "HARD", }] @@ -3195,7 +3207,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/$$virtual/sequelize-virtual-d11c02af07/0/cache/sequelize-npm-6.6.2-c6128633b4-174b449f4d.zip/node_modules/sequelize/", "packageDependencies": [ ["sequelize", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:6.6.2"], - ["debug", "virtual:48933b28331d16c1d73786360e7ba20f54f6df4949c6ab5c13ac4c4353b5c70f2d36a97de9a9c531027ad3588d8fd7f384706f298f0eff0356b58bb9c47f63ec#npm:4.3.1"], + ["debug", "virtual:428f325a939c2653ad822eb3d75efb02ac311523dd0d4f9645afc39ea00bd86eceac35a9d59c9b6977d76b670a4ef0ae057ea572338a44729aa592711a8c05a3#npm:4.3.2"], ["dottie", "npm:2.0.2"], ["inflection", "npm:1.12.0"], ["lodash", "npm:4.17.21"], @@ -3204,7 +3216,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["moment-timezone", "npm:0.5.33"], ["mysql2", null], ["pg", "virtual:d7ae587dddcefd495158f5c047acecbca3203324d75e681c7d8657c07f901f74e152f0b39978f7428d3a91daad7b5020c47ece28de69c22fcbd49d04707bf15c#npm:8.6.0"], - ["pg-hstore", "npm:2.3.3"], + ["pg-hstore", "npm:2.3.4"], ["retry-as-promised", "npm:3.2.0"], ["semver", "npm:7.3.5"], ["sequelize-pool", "npm:6.1.0"], @@ -3520,7 +3532,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/table-npm-6.7.1-7d70e55c6d-66107046b7.zip/node_modules/table/", "packageDependencies": [ ["table", "npm:6.7.1"], - ["ajv", "npm:8.4.0"], + ["ajv", "npm:8.6.0"], ["lodash.clonedeep", "npm:4.5.0"], ["lodash.truncate", "npm:4.4.2"], ["slice-ansi", "npm:4.0.0"], @@ -3608,10 +3620,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "SOFT", }], - ["virtual:24ccaee8f2a84c341367a0ca54e599e765dd5def7c88fa690af51d687e0dcab63f6a9a9e082854fcee0c56f65cc121b7ea65bf2f8444c2333afcf117d3775385#npm:3.21.0", { - "packageLocation": "./.yarn/$$virtual/tsutils-virtual-8bce827154/0/cache/tsutils-npm-3.21.0-347e6636c5-a10e746258.zip/node_modules/tsutils/", + ["virtual:16af2f56ad2b3a09ed5bd79b3980969472fcaef4f709b1eeb504d7929351e825862f727dd5f45329be93f78cd6ec914b29a54d9f2df679571d57b82c3a0d8e07#npm:3.21.0", { + "packageLocation": "./.yarn/$$virtual/tsutils-virtual-5630d27e02/0/cache/tsutils-npm-3.21.0-347e6636c5-a10e746258.zip/node_modules/tsutils/", "packageDependencies": [ - ["tsutils", "virtual:24ccaee8f2a84c341367a0ca54e599e765dd5def7c88fa690af51d687e0dcab63f6a9a9e082854fcee0c56f65cc121b7ea65bf2f8444c2333afcf117d3775385#npm:3.21.0"], + ["tsutils", "virtual:16af2f56ad2b3a09ed5bd79b3980969472fcaef4f709b1eeb504d7929351e825862f727dd5f45329be93f78cd6ec914b29a54d9f2df679571d57b82c3a0d8e07#npm:3.21.0"], ["@types/typescript", null], ["tslib", "npm:1.14.1"], ["typescript", null] @@ -3622,13 +3634,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "HARD", }], - ["virtual:9a8b1f31dfb77b858353b17f1156b28813da74b21de747b5c31939cc4aa66de00a18bbe787c84699160d9cbc5a6e50e8d05774ecfe3004ea2748f8e905a5daf3#npm:3.21.0", { - "packageLocation": "./.yarn/$$virtual/tsutils-virtual-4f68179833/0/cache/tsutils-npm-3.21.0-347e6636c5-a10e746258.zip/node_modules/tsutils/", + ["virtual:5e3c68ea71d0b85646d5a078b5b56e0e5243913f1ce1e78c84511da03cdd76ce978b3e42d3ba35119262d370b55b3e2f8b85ed81eb2b2f2ec218791b4ccc2dbb#npm:3.21.0", { + "packageLocation": "./.yarn/$$virtual/tsutils-virtual-e63b247809/0/cache/tsutils-npm-3.21.0-347e6636c5-a10e746258.zip/node_modules/tsutils/", "packageDependencies": [ - ["tsutils", "virtual:9a8b1f31dfb77b858353b17f1156b28813da74b21de747b5c31939cc4aa66de00a18bbe787c84699160d9cbc5a6e50e8d05774ecfe3004ea2748f8e905a5daf3#npm:3.21.0"], + ["tsutils", "virtual:5e3c68ea71d0b85646d5a078b5b56e0e5243913f1ce1e78c84511da03cdd76ce978b3e42d3ba35119262d370b55b3e2f8b85ed81eb2b2f2ec218791b4ccc2dbb#npm:3.21.0"], ["@types/typescript", null], ["tslib", "npm:1.14.1"], - ["typescript", "patch:typescript@npm%3A4.2.4#builtin<compat/typescript>::version=4.2.4&hash=ddfc1b"] + ["typescript", "patch:typescript@npm%3A4.3.4#builtin<compat/typescript>::version=4.3.4&hash=ddfc1b"] ], "packagePeers": [ "@types/typescript", @@ -3654,13 +3666,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["type-fest", "npm:0.20.2"] ], "linkType": "HARD", - }], - ["npm:0.8.1", { - "packageLocation": "./.yarn/cache/type-fest-npm-0.8.1-351ad028fe-f8c4b4249f.zip/node_modules/type-fest/", - "packageDependencies": [ - ["type-fest", "npm:0.8.1"] - ], - "linkType": "HARD", }] ]], ["type-is", [ @@ -3669,16 +3674,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageDependencies": [ ["type-is", "npm:1.6.18"], ["media-typer", "npm:0.3.0"], - ["mime-types", "npm:2.1.30"] + ["mime-types", "npm:2.1.31"] ], "linkType": "HARD", }] ]], ["typescript", [ - ["patch:typescript@npm%3A4.2.4#builtin<compat/typescript>::version=4.2.4&hash=ddfc1b", { - "packageLocation": "./.yarn/cache/typescript-patch-4ce0948b1e-64658fdf27.zip/node_modules/typescript/", + ["patch:typescript@npm%3A4.3.4#builtin<compat/typescript>::version=4.3.4&hash=ddfc1b", { + "packageLocation": "./.yarn/cache/typescript-patch-e441ed4208-c8766e84a4.zip/node_modules/typescript/", "packageDependencies": [ - ["typescript", "patch:typescript@npm%3A4.2.4#builtin<compat/typescript>::version=4.2.4&hash=ddfc1b"] + ["typescript", "patch:typescript@npm%3A4.3.4#builtin<compat/typescript>::version=4.3.4&hash=ddfc1b"] ], "linkType": "HARD", }] @@ -3792,7 +3797,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./.yarn/cache/wkx-npm-0.5.0-fca5152cd8-ea38c886b8.zip/node_modules/wkx/", "packageDependencies": [ ["wkx", "npm:0.5.0"], - ["@types/node", "npm:15.3.0"] + ["@types/node", "npm:15.12.4"] ], "linkType": "HARD", }] @@ -3816,17 +3821,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["ws", [ - ["npm:7.4.6", { - "packageLocation": "./.yarn/cache/ws-npm-7.4.6-9c9a725604-ffeb626d92.zip/node_modules/ws/", + ["npm:7.5.0", { + "packageLocation": "./.yarn/cache/ws-npm-7.5.0-2736efb7e8-f9ac36310e.zip/node_modules/ws/", "packageDependencies": [ - ["ws", "npm:7.4.6"] + ["ws", "npm:7.5.0"] ], "linkType": "SOFT", }], - ["virtual:275bceca0f79f8e7aeb7f77acb5a6bd201e7eea264e9dfd8dcc0bcf35691357327303c09557dfc1495b9a1f8e9cf8278133d234783570df6cb70a249778f3198#npm:7.4.6", { - "packageLocation": "./.yarn/$$virtual/ws-virtual-652db7ea0b/0/cache/ws-npm-7.4.6-9c9a725604-ffeb626d92.zip/node_modules/ws/", + ["virtual:275bceca0f79f8e7aeb7f77acb5a6bd201e7eea264e9dfd8dcc0bcf35691357327303c09557dfc1495b9a1f8e9cf8278133d234783570df6cb70a249778f3198#npm:7.5.0", { + "packageLocation": "./.yarn/$$virtual/ws-virtual-61252c08ac/0/cache/ws-npm-7.5.0-2736efb7e8-f9ac36310e.zip/node_modules/ws/", "packageDependencies": [ - ["ws", "virtual:275bceca0f79f8e7aeb7f77acb5a6bd201e7eea264e9dfd8dcc0bcf35691357327303c09557dfc1495b9a1f8e9cf8278133d234783570df6cb70a249778f3198#npm:7.4.6"], + ["ws", "virtual:275bceca0f79f8e7aeb7f77acb5a6bd201e7eea264e9dfd8dcc0bcf35691357327303c09557dfc1495b9a1f8e9cf8278133d234783570df6cb70a249778f3198#npm:7.5.0"], ["@types/bufferutil", null], ["@types/utf-8-validate", null], ["bufferutil", null], diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 5c4d931..94a8b5c 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,10 @@ { - "recommendations": ["arcanis.vscode-zipfs", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] + "recommendations": [ + "aaron-bond.better-comments", + "arcanis.vscode-zipfs", + "dbaeumer.vscode-eslint", + "eamodio.gitlens", + "esbenp.prettier-vscode", + "streetsidesoftware.code-spell-checker" + ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 24dee80..8a07909 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,14 +5,30 @@ "version": "0.2.0", "configurations": [ { + "command": "yarn start", + "name": "Run yarn start", + "request": "launch", + "type": "node-terminal", + "skipFiles": [ + "<node_internals>/**", + "**/Yarn/**", + "**/node_modules/typescript/**", + "**/node_modules/bluebird/**" //"**/node_modules/**" + ] + }, + { "type": "pwa-node", "request": "launch", "name": "Launch Program", - "skipFiles": ["<node_internals>/**"], - "program": "${workspaceFolder}\\src\\bot.ts", + "skipFiles": [ + "<node_internals>/**", + "**/Yarn/**", + "**/node_modules/typescript/**", + "**/node_modules/bluebird/**" //"**/node_modules/**" + ], + "program": "${workspaceFolder}\\dist\\bot.js", "preLaunchTask": "tsc: build - tsconfig.json", - "outFiles": ["${workspaceFolder}/dist/**/*.js"], - "args": ["-r source-map-support/register"] + "outFiles": ["${workspaceFolder}/dist/**/*.js"] } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index d10e423..33fdb49 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,7 +5,8 @@ "**/.hg": true, "**/CVS": true, "**/.DS_Store": true, - "node_modules": true + "node_modules": true, + "dist": true }, "javascript.preferences.importModuleSpecifier": "project-relative", "typescript.preferences.importModuleSpecifier": "project-relative", @@ -14,14 +15,25 @@ "**/.yarn": true, "**/.pnp.*": true }, - "eslint.nodePath": ".yarn/sdks", - "prettier.prettierPath": ".yarn/sdks/prettier/index.js", - "typescript.tsdk": ".yarn/sdks/typescript/lib", - "editor.defaultFormatter": "esbenp.prettier-vscode", - "typescript.enablePromptUseWorkspaceTsdk": true, "editor.codeActionsOnSave": { "source.organizeImports": true, "source.fixAll.eslint": true, "source.format": true - } + }, + "editor.formatOnSave": true, + "diffEditor.wordWrap": "on", + "editor.insertSpaces": false, + "editor.wordWrap": "on", + "editor.tabSize": 2, + "prettier.printWidth": 170, + "prettier.singleQuote": true, + "prettier.trailingComma": "none", + "prettier.useTabs": true, + "prettier.configPath": "package.json", + "prettier.prettierPath": ".yarn/sdks/prettier/index.js", + "prettier.withNodeModules": true, + "prettier.useEditorConfig": false, + "eslint.nodePath": ".yarn/sdks", + "typescript.tsdk": ".yarn/sdks/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": true } diff --git a/.yarn/sdks/typescript/lib/tsc.js b/.yarn/sdks/typescript/lib/tsc.js index 32b20bd..e030711 100644 --- a/.yarn/sdks/typescript/lib/tsc.js +++ b/.yarn/sdks/typescript/lib/tsc.js @@ -1,19 +1,19 @@ #!/usr/bin/env node -const { existsSync } = require(`fs`); -const { createRequire, createRequireFromPath } = require(`module`); -const { resolve } = require(`path`); +const {existsSync} = require(`fs`); +const {createRequire, createRequireFromPath} = require(`module`); +const {resolve} = require(`path`); -const relPnpApiPath = '../../../../.pnp.js'; +const relPnpApiPath = "../../../../.pnp.js"; const absPnpApiPath = resolve(__dirname, relPnpApiPath); const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); if (existsSync(absPnpApiPath)) { - if (!process.versions.pnp) { - // Setup the environment to be able to require typescript/lib/tsc.js - require(absPnpApiPath).setup(); - } + if (!process.versions.pnp) { + // Setup the environment to be able to require typescript/lib/tsc.js + require(absPnpApiPath).setup(); + } } // Defer to the real typescript/lib/tsc.js your application uses diff --git a/.yarn/sdks/typescript/lib/tsserver.js b/.yarn/sdks/typescript/lib/tsserver.js index b1938d5..488c4b8 100644 --- a/.yarn/sdks/typescript/lib/tsserver.js +++ b/.yarn/sdks/typescript/lib/tsserver.js @@ -1,143 +1,142 @@ #!/usr/bin/env node -const { existsSync } = require(`fs`); -const { createRequire, createRequireFromPath } = require(`module`); -const { resolve } = require(`path`); +const {existsSync} = require(`fs`); +const {createRequire, createRequireFromPath} = require(`module`); +const {resolve} = require(`path`); -const relPnpApiPath = '../../../../.pnp.js'; +const relPnpApiPath = "../../../../.pnp.js"; const absPnpApiPath = resolve(__dirname, relPnpApiPath); const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); -const moduleWrapper = (tsserver) => { - const { isAbsolute } = require(`path`); - const pnpApi = require(`pnpapi`); - - const dependencyTreeRoots = new Set( - pnpApi.getDependencyTreeRoots().map((locator) => { - return `${locator.name}@${locator.reference}`; - }) - ); - - // VSCode sends the zip paths to TS using the "zip://" prefix, that TS - // doesn't understand. This layer makes sure to remove the protocol - // before forwarding it to TS, and to add it back on all returned paths. - - function toEditorPath(str) { - // We add the `zip:` prefix to both `.zip/` paths and virtual paths - if ( - isAbsolute(str) && - !str.match(/^\^zip:/) && - (str.match(/\.zip\//) || str.match(/\/(\$\$virtual|__virtual__)\//)) - ) { - // We also take the opportunity to turn virtual paths into physical ones; - // this makes is much easier to work with workspaces that list peer - // dependencies, since otherwise Ctrl+Click would bring us to the virtual - // file instances instead of the real ones. - // - // We only do this to modules owned by the the dependency tree roots. - // This avoids breaking the resolution when jumping inside a vendor - // with peer dep (otherwise jumping into react-dom would show resolution - // errors on react). - // - const resolved = pnpApi.resolveVirtual(str); - if (resolved) { - const locator = pnpApi.findPackageLocator(resolved); - if ( - locator && - dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) - ) { - str = resolved; - } - } - - str = str.replace(/\\/g, `/`); - str = str.replace(/^\/?/, `/`); - - // Absolute VSCode `Uri.fsPath`s need to start with a slash. - // VSCode only adds it automatically for supported schemes, - // so we have to do it manually for the `zip` scheme. - // The path needs to start with a caret otherwise VSCode doesn't handle the protocol - // - // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910 - // - if (str.match(/\.zip\//)) { - str = `${isVSCode ? `^` : ``}zip:${str}`; - } - } - - return str; - } - - function fromEditorPath(str) { - return process.platform === `win32` - ? str.replace(/^\^?zip:\//, ``) - : str.replace(/^\^?zip:/, ``); - } - - // Force enable 'allowLocalPluginLoads' - // TypeScript tries to resolve plugins using a path relative to itself - // which doesn't work when using the global cache - // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238 - // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but - // TypeScript already does local loads and if this code is running the user trusts the workspace - // https://github.com/microsoft/vscode/issues/45856 - const ConfiguredProject = tsserver.server.ConfiguredProject; - const { enablePluginsWithOptions: originalEnablePluginsWithOptions } = - ConfiguredProject.prototype; - ConfiguredProject.prototype.enablePluginsWithOptions = function () { - this.projectService.allowLocalPluginLoads = true; - return originalEnablePluginsWithOptions.apply(this, arguments); - }; - - // And here is the point where we hijack the VSCode <-> TS communications - // by adding ourselves in the middle. We locate everything that looks - // like an absolute path of ours and normalize it. - - const Session = tsserver.server.Session; - const { onMessage: originalOnMessage, send: originalSend } = - Session.prototype; - let isVSCode = false; - - return Object.assign(Session.prototype, { - onMessage(/** @type {string} */ message) { - const parsedMessage = JSON.parse(message); - - if ( - parsedMessage != null && - typeof parsedMessage === `object` && - parsedMessage.arguments && - parsedMessage.arguments.hostInfo === `vscode` - ) { - isVSCode = true; - } - - return originalOnMessage.call( - this, - JSON.stringify(parsedMessage, (key, value) => { - return typeof value === `string` ? fromEditorPath(value) : value; - }) - ); - }, - - send(/** @type {any} */ msg) { - return originalSend.call( - this, - JSON.parse( - JSON.stringify(msg, (key, value) => { - return typeof value === `string` ? toEditorPath(value) : value; - }) - ) - ); - } - }); +const moduleWrapper = tsserver => { + const {isAbsolute} = require(`path`); + const pnpApi = require(`pnpapi`); + + const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//); + const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`); + + const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => { + return `${locator.name}@${locator.reference}`; + })); + + // VSCode sends the zip paths to TS using the "zip://" prefix, that TS + // doesn't understand. This layer makes sure to remove the protocol + // before forwarding it to TS, and to add it back on all returned paths. + + function toEditorPath(str) { + // We add the `zip:` prefix to both `.zip/` paths and virtual paths + if (isAbsolute(str) && !str.match(/^\^zip:/) && (str.match(/\.zip\//) || isVirtual(str))) { + // We also take the opportunity to turn virtual paths into physical ones; + // this makes it much easier to work with workspaces that list peer + // dependencies, since otherwise Ctrl+Click would bring us to the virtual + // file instances instead of the real ones. + // + // We only do this to modules owned by the the dependency tree roots. + // This avoids breaking the resolution when jumping inside a vendor + // with peer dep (otherwise jumping into react-dom would show resolution + // errors on react). + // + const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str; + if (resolved) { + const locator = pnpApi.findPackageLocator(resolved); + if (locator && dependencyTreeRoots.has(`${locator.name}@${locator.reference}`)) { + str = resolved; + } + } + + str = normalize(str); + + if (str.match(/\.zip\//)) { + switch (hostInfo) { + // Absolute VSCode `Uri.fsPath`s need to start with a slash. + // VSCode only adds it automatically for supported schemes, + // so we have to do it manually for the `zip` scheme. + // The path needs to start with a caret otherwise VSCode doesn't handle the protocol + // + // Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910 + // + case `vscode`: { + str = `^zip:${str}`; + } break; + + // To make "go to definition" work, + // We have to resolve the actual file system path from virtual path + // and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip) + case `coc-nvim`: { + str = normalize(resolved).replace(/\.zip\//, `.zip::`); + str = resolve(`zipfile:${str}`); + } break; + + default: { + str = `zip:${str}`; + } break; + } + } + } + + return str; + } + + function fromEditorPath(str) { + return process.platform === `win32` + ? str.replace(/^\^?zip:\//, ``) + : str.replace(/^\^?zip:/, ``); + } + + // Force enable 'allowLocalPluginLoads' + // TypeScript tries to resolve plugins using a path relative to itself + // which doesn't work when using the global cache + // https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238 + // VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but + // TypeScript already does local loads and if this code is running the user trusts the workspace + // https://github.com/microsoft/vscode/issues/45856 + const ConfiguredProject = tsserver.server.ConfiguredProject; + const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype; + ConfiguredProject.prototype.enablePluginsWithOptions = function() { + this.projectService.allowLocalPluginLoads = true; + return originalEnablePluginsWithOptions.apply(this, arguments); + }; + + // And here is the point where we hijack the VSCode <-> TS communications + // by adding ourselves in the middle. We locate everything that looks + // like an absolute path of ours and normalize it. + + const Session = tsserver.server.Session; + const {onMessage: originalOnMessage, send: originalSend} = Session.prototype; + let hostInfo = `unknown`; + + return Object.assign(Session.prototype, { + onMessage(/** @type {string} */ message) { + const parsedMessage = JSON.parse(message) + + if ( + parsedMessage != null && + typeof parsedMessage === `object` && + parsedMessage.arguments && + typeof parsedMessage.arguments.hostInfo === `string` + ) { + hostInfo = parsedMessage.arguments.hostInfo; + } + + return originalOnMessage.call(this, JSON.stringify(parsedMessage, (key, value) => { + return typeof value === `string` ? fromEditorPath(value) : value; + })); + }, + + send(/** @type {any} */ msg) { + return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => { + return typeof value === `string` ? toEditorPath(value) : value; + }))); + } + }); }; if (existsSync(absPnpApiPath)) { - if (!process.versions.pnp) { - // Setup the environment to be able to require typescript/lib/tsserver.js - require(absPnpApiPath).setup(); - } + if (!process.versions.pnp) { + // Setup the environment to be able to require typescript/lib/tsserver.js + require(absPnpApiPath).setup(); + } } // Defer to the real typescript/lib/tsserver.js your application uses diff --git a/.yarn/sdks/typescript/lib/typescript.js b/.yarn/sdks/typescript/lib/typescript.js index c5caf71..7e3c852 100644 --- a/.yarn/sdks/typescript/lib/typescript.js +++ b/.yarn/sdks/typescript/lib/typescript.js @@ -1,19 +1,19 @@ #!/usr/bin/env node -const { existsSync } = require(`fs`); -const { createRequire, createRequireFromPath } = require(`module`); -const { resolve } = require(`path`); +const {existsSync} = require(`fs`); +const {createRequire, createRequireFromPath} = require(`module`); +const {resolve} = require(`path`); -const relPnpApiPath = '../../../../.pnp.js'; +const relPnpApiPath = "../../../../.pnp.js"; const absPnpApiPath = resolve(__dirname, relPnpApiPath); const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath); if (existsSync(absPnpApiPath)) { - if (!process.versions.pnp) { - // Setup the environment to be able to require typescript/lib/typescript.js - require(absPnpApiPath).setup(); - } + if (!process.versions.pnp) { + // Setup the environment to be able to require typescript/lib/typescript.js + require(absPnpApiPath).setup(); + } } // Defer to the real typescript/lib/typescript.js your application uses diff --git a/.yarn/sdks/typescript/package.json b/.yarn/sdks/typescript/package.json index 2abd3fe..1ae6045 100644 --- a/.yarn/sdks/typescript/package.json +++ b/.yarn/sdks/typescript/package.json @@ -1,6 +1,6 @@ { - "name": "typescript", - "version": "4.2.4-pnpify", - "main": "./lib/typescript.js", - "type": "commonjs" + "name": "typescript", + "version": "4.3.4-pnpify", + "main": "./lib/typescript.js", + "type": "commonjs" } @@ -1,21 +1,428 @@ -MIT License - -Copyright (c) 2021 Tyman-productions - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Attribution-NonCommercial-ShareAlike 4.0 International +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International +Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International Public License +("Public License"). To the extent this Public License may be +interpreted as a contract, You are granted the Licensed Rights in +consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the +Licensor receives from making the Licensed Material available under +these terms and conditions. + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-NC-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution, NonCommercial, and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + l. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + m. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + n. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-NC-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. @@ -1,3 +1,4 @@ +<!-- markdownlint-disable MD010 MD033 --> <h1 align = "center"> <img src="https://cdn.discordapp.com/avatars/767478359348740148/8e9fc569e00fa3973b9d2d89ce2acf62.png"> <br> @@ -15,7 +16,7 @@ Bush bot is a custom bot for the Moulberry's Bush discord server. -If you would like to set up for yourself, please see [SETUP.md](https://github.com/NotEnoughUpdates/bush-bot/blob/rewrite/SETUP.md) +If you would like to set up for yourself, please see [SETUP.md](https://github.com/NotEnoughUpdates/bush-bot/blob/rewrite/.github/SETUP.md) <h2 align="center">Contributing</h2> diff --git a/ecosystem.config.js b/ecosystem.config.js deleted file mode 100644 index 2e4b063..0000000 --- a/ecosystem.config.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - apps: [ - { - name: 'BushBot-Dev', - script: 'yarn', - args: 'start', - out_file: './combined-dev.log', - error_file: './combined-dev.log', - max_memory_restart: '2000M', - node_args: ['--max_old_space_size=2048'], - env: { - FORCE_COLOR: '3' - } - } - ] -}; diff --git a/ecosystem.config.json b/ecosystem.config.json new file mode 100644 index 0000000..a4ba731 --- /dev/null +++ b/ecosystem.config.json @@ -0,0 +1,16 @@ +{ + "apps": [ + { + "name": "BushBot-Dev", + "script": "yarn", + "args": "start", + "out_file": "./combined-dev.log", + "error_file": "./combined-dev.log", + "max_memory_restart": "2000M", + "node_args": ["--max_old_space_size=2048"], + "env": { + "FORCE_COLOR": "3" + } + } + ] +} diff --git a/package.json b/package.json index bcebf14..32d1a0a 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "dist/bot.js", "repository": "https://github.com/NotEnoughUpdates/bush-bot", "author": "Tyman, IRONM00N, and TrashCan", - "license": "MIT", + "license": "CC-BY-NC-SA-4.0", "scripts": { "build-esbuild": "yarn rimraf dist && yarn esbuild --sourcemap=inline --minify-whitespace --minify-syntax --outdir=dist --platform=node --target=es2020 --format=cjs src/**/*.ts", "build-tsc": "yarn rimraf dist && yarn tsc", @@ -37,7 +37,7 @@ "canvas": "^2.8.0", "chalk": "^4.1.1", "common-tags": "^1.8.0", - "discord-akairo": "IRONM00N-Development/discord-akairo", + "discord-akairo": "NotEnoughUpdates/discord-akairo", "discord-api-types": "^0.18.1", "discord.js": "dev", "got": "^11.8.1", @@ -68,7 +68,26 @@ "ignorePatterns": [ "dist", "node_modules" - ] + ], + "rules": { + "no-return-await": "off", + "@typescript-eslint/no-empty-interface": "warn", + "no-mixed-spaces-and-tabs": "off", + "no-duplicate-imports": "warn", + "no-empty-function": "off", + "@typescript-eslint/no-empty-function": "off", + "no-empty": "off", + "@typescript-eslint/ban-ts-comment": [ + "error", + { + "ts-expect-error": "allow-with-description", + "ts-ignore": "allow-with-description", + "ts-nocheck": "allow-with-description", + "ts-check": "allow-with-description", + "minimumDescriptionLength": 10 + } + ] + } }, "prettier": { "printWidth": 128, @@ -76,5 +95,10 @@ "quoteProps": "consistent", "singleQuote": true, "trailingComma": "none" + }, + "dependenciesMeta": { + "prettier@2.3.1": { + "unplugged": true + } } } diff --git a/src/commands/server-config/prefix.ts b/src/commands/config/prefix.ts index 9cdc331..c20cfa5 100644 --- a/src/commands/server-config/prefix.ts +++ b/src/commands/config/prefix.ts @@ -1,15 +1,15 @@ import { ApplicationCommandOptionType } from 'discord-api-types'; import { Guild as DiscordGuild, Message } from 'discord.js'; +import { SlashCommandOption } from '../../lib/extensions/BushClientUtil'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; -import { SlashCommandOption } from '../../lib/extensions/Util'; import { Guild } from '../../lib/models'; export default class PrefixCommand extends BushCommand { constructor() { super('prefix', { aliases: ['prefix'], - category: 'server config', + category: 'config', args: [ { id: 'prefix' diff --git a/src/commands/dev/eval.ts b/src/commands/dev/eval.ts index 2f1d45d..8bf88ff 100644 --- a/src/commands/dev/eval.ts +++ b/src/commands/dev/eval.ts @@ -1,16 +1,20 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { exec } from 'child_process'; import { Constants } from 'discord-akairo'; -import { Message, MessageEmbed, MessageEmbedOptions, Util } from 'discord.js'; +import { CommandInteraction, MessageEmbed, MessageEmbedOptions, Util } from 'discord.js'; import { transpile } from 'typescript'; import { inspect, promisify } from 'util'; import { BushCommand } from '../../lib/extensions/BushCommand'; +import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; +import { BushMessage } from '../../lib/extensions/BushMessage'; const clean = (text) => { if (typeof text === 'string') { return (text = Util.cleanCodeBlockContent(text)); } else return text; }; +const sh = promisify(exec); + export default class EvalCommand extends BushCommand { public constructor() { super('eval', { @@ -23,7 +27,7 @@ export default class EvalCommand extends BushCommand { }, args: [ { - id: 'selDepth', + id: 'sel_depth', match: Constants.ArgumentMatches.OPTION, type: Constants.ArgumentTypes.NUMBER, flag: '--depth', @@ -35,7 +39,7 @@ export default class EvalCommand extends BushCommand { flag: '--sudo' }, { - id: 'deleteMSG', + id: 'delete_msg', match: Constants.ArgumentMatches.FLAG, flag: '--delete' }, @@ -55,7 +59,7 @@ export default class EvalCommand extends BushCommand { flag: '--hidden' }, { - id: 'showProto', + id: 'show_proto', match: Constants.ArgumentMatches.FLAG, flag: '--proto' }, @@ -70,62 +74,99 @@ export default class EvalCommand extends BushCommand { } ], ownerOnly: true, - clientPermissions: ['EMBED_LINKS'] + slash: true, + slashOptions: [ + { + name: 'code', + description: 'The code you would like to evaluate.', + type: 'STRING', + required: true + }, + { + name: 'sel_depth', + description: 'How deep to display the output.', + type: 'INTEGER', + required: false + }, + { + name: 'sudo', + description: 'Whether or not to override checks.', + type: 'BOOLEAN', + required: false + }, + { + name: 'silent', + description: 'Whether or not to make the response silent', + type: 'BOOLEAN', + required: false + }, + { + name: 'typescript', + description: 'Whether or not to compile the code from typescript.', + type: 'BOOLEAN', + required: false + }, + { + name: 'hidden', + description: 'Whether or not to show hidden items.', + type: 'BOOLEAN', + required: false + }, + { + name: 'show_proto', + description: 'Show prototype.', + type: 'BOOLEAN', + required: false + } + ] }); } - private redactCredentials(old: string) { - const mapping = { - ['token']: 'Token', - ['devToken']: 'Dev Token', - ['MongoDB']: 'MongoDB URI', - ['hypixelApiKey']: 'Hypixel Api Key', - ['webhookID']: 'Webhook ID', - ['webhookToken']: 'Webhook Token' - }; - return mapping[old] || old; - } - public async exec( - message: Message, - { - selDepth, - code: codeArg, - sudo, - silent, - deleteMSG, - typescript, - hidden, - showProto - }: { - selDepth: number; + message: BushMessage | BushInteractionMessage, + args: { + sel_depth: number; code: string; sudo: boolean; silent: boolean; deleteMSG: boolean; typescript: boolean; hidden: boolean; - showProto: boolean; + show_proto: boolean; } ): Promise<unknown> { if (!this.client.config.owners.includes(message.author.id)) - return await message.channel.send(`${this.client.util.emojis.error} Only my developers can run this command.`); + return await message.util.reply(`${this.client.util.emojis.error} Only my developers can run this command.`); + if (message.util.isSlash) { + await (message as BushInteractionMessage).interaction.defer({ ephemeral: args.silent }); + } + const code: { js?: string | null; ts?: string | null; lang?: 'js' | 'ts' } = {}; - codeArg = codeArg.replace(/[“”]/g, '"'); - codeArg = codeArg.replace(/```/g, ''); - if (typescript) { - code.ts = codeArg; - code.js = transpile(codeArg); + args.code = args.code.replace(/[“”]/g, '"'); + args.code = args.code.replace(/```/g, ''); + if (args.typescript) { + code.ts = args.code; + code.js = transpile(args.code); code.lang = 'ts'; } else { code.ts = null; - code.js = codeArg; + code.js = args.code; code.lang = 'js'; } const embed: MessageEmbed = new MessageEmbed(); const bad_phrases: string[] = ['delete', 'destroy']; - if (bad_phrases.some((p) => code[code.lang].includes(p)) && !sudo) { + + function ae(old: string) { + const mapping = { + ['token']: 'Token', + ['devToken']: 'Dev Token', + ['hypixelApiKey']: 'Hypixel Api Key' + }; + return mapping[old] || old; + } + + if (bad_phrases.some((p) => code[code.lang].includes(p)) && !args.sudo) { return await message.util.send(`${this.client.util.emojis.error} This eval was blocked by smooth brain protection™.`); } const embeds: (MessageEmbed | MessageEmbedOptions)[] = [new MessageEmbed()]; @@ -140,10 +181,7 @@ export default class EvalCommand extends BushCommand { channel = message.channel, config = this.client.config, members = message.guild.members, - roles = message.guild.roles, - sh = promisify(exec), - models = this.client.db.models, - got = require('got'); // eslint-disable-line @typescript-eslint/no-var-requires + roles = message.guild.roles; if (code[code.lang].replace(/ /g, '').includes('9+10' || '10+9')) { output = 21; } else { @@ -151,15 +189,15 @@ export default class EvalCommand extends BushCommand { output = await output; } let proto, outputProto; - if (showProto) { + if (args.show_proto) { proto = Object.getPrototypeOf(output); outputProto = clean(inspect(proto, { depth: 1, getters: true, showHidden: true })); } if (typeof output !== 'string') - output = inspect(output, { depth: selDepth, showHidden: hidden, getters: true, showProxy: true }); + output = inspect(output, { depth: args.sel_depth || 0, showHidden: args.hidden, getters: true, showProxy: true }); for (const credentialName in this.client.config.credentials) { const credential = this.client.config.credentials[credentialName]; - const newCredential = this.redactCredentials(credentialName); + const newCredential = ae(credentialName); output = output.replace( new RegExp(credential.toString().replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), `[${newCredential} Omitted]` @@ -187,7 +225,7 @@ export default class EvalCommand extends BushCommand { embed.addField('📥 Input', await this.client.util.codeblock(inputJS, 1024, 'js')); } embed.addField('📤 Output', await this.client.util.codeblock(output, 1024, 'js')); - if (showProto) embed.addField('⚙️ Proto', await this.client.util.codeblock(outputProto, 1024, 'js')); + if (args.show_proto) embed.addField('⚙️ Proto', await this.client.util.codeblock(outputProto, 1024, 'js')); } catch (e) { const inputJS = clean(code.js); embed @@ -205,19 +243,21 @@ export default class EvalCommand extends BushCommand { } embed.addField('📤 Output', await this.client.util.codeblock(e?.stack, 1024, 'js')); } - if (!silent) { - await message.util.reply({ embeds: [embed] }); + if (!args.silent && !message.util.isSlash) { + await message.util.reply({ embeds: [embed], ephemeral: args.silent }); + } else if (message.util.isSlash) { + await (message.interaction as CommandInteraction).editReply({ embeds: [embed] }); } else { try { await message.author.send({ embeds: [embed] }); - if (!deleteMSG) await message.react(this.client.util.emojis.successFull); + if (!args.deleteMSG) await (message as BushMessage).react(this.client.util.emojis.successFull); } catch (e) { - if (!deleteMSG) await message.react(this.client.util.emojis.errorFull); + if (!args.deleteMSG) await (message as BushMessage).react(this.client.util.emojis.errorFull); } } - if (deleteMSG && message.deletable) { - await message.delete(); + if (args.deleteMSG && (message as BushMessage).deletable) { + await (message as BushMessage).delete(); } } } diff --git a/src/commands/dev/reload.ts b/src/commands/dev/reload.ts index 3194ce2..82a98a0 100644 --- a/src/commands/dev/reload.ts +++ b/src/commands/dev/reload.ts @@ -1,9 +1,9 @@ import { stripIndent } from 'common-tags'; import { ApplicationCommandOptionType } from 'discord-api-types'; import { Message } from 'discord.js'; +import { SlashCommandOption } from '../../lib/extensions/BushClientUtil'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; -import { SlashCommandOption } from '../../lib/extensions/Util'; export default class ReloadCommand extends BushCommand { constructor() { @@ -28,7 +28,7 @@ export default class ReloadCommand extends BushCommand { { type: ApplicationCommandOptionType.BOOLEAN, name: 'fast', - description: 'Wheather to use esbuild for fast compiling or not', + description: 'Whether to use esbuild for fast compiling or not', required: false } ] diff --git a/src/commands/dev/setLevel.ts b/src/commands/dev/setLevel.ts index 7401699..4f97528 100644 --- a/src/commands/dev/setLevel.ts +++ b/src/commands/dev/setLevel.ts @@ -1,8 +1,8 @@ import { ApplicationCommandOptionType } from 'discord-api-types'; import { Message, User } from 'discord.js'; +import { SlashCommandOption } from '../../lib/extensions/BushClientUtil'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; -import { SlashCommandOption } from '../../lib/extensions/Util'; import { Level } from '../../lib/models'; import AllowedMentions from '../../lib/utils/AllowedMentions'; diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts index 317091e..8dac8ee 100644 --- a/src/commands/info/help.ts +++ b/src/commands/info/help.ts @@ -1,9 +1,9 @@ import { stripIndent } from 'common-tags'; import { ApplicationCommandOptionType } from 'discord-api-types'; import { Message, MessageEmbed } from 'discord.js'; +import { SlashCommandOption } from '../../lib/extensions/BushClientUtil'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; -import { SlashCommandOption } from '../../lib/extensions/Util'; export default class HelpCommand extends BushCommand { constructor() { diff --git a/src/commands/info/ping.ts b/src/commands/info/ping.ts index feb48ad..f0d017e 100644 --- a/src/commands/info/ping.ts +++ b/src/commands/info/ping.ts @@ -16,7 +16,7 @@ export default class PingCommand extends BushCommand { } public async exec(message: Message): Promise<void> { - const sentMessage = await message.util.send('Pong!'); + const sentMessage = await message.util.send('Pong!') as Message; const timestamp: number = message.editedTimestamp ? message.editedTimestamp : message.createdTimestamp; const botLatency = `\`\`\`\n ${Math.floor(sentMessage.createdTimestamp - timestamp)}ms \`\`\``; const apiLatency = `\`\`\`\n ${Math.round(message.client.ws.ping)}ms \`\`\``; diff --git a/src/commands/info/pronouns.ts b/src/commands/info/pronouns.ts index faf3aa2..bade100 100644 --- a/src/commands/info/pronouns.ts +++ b/src/commands/info/pronouns.ts @@ -1,9 +1,9 @@ import { ApplicationCommandOptionType } from 'discord-api-types'; import { CommandInteraction, Message, MessageEmbed, User } from 'discord.js'; import got, { HTTPError } from 'got'; +import { SlashCommandOption } from '../../lib/extensions/BushClientUtil'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; -import { SlashCommandOption } from '../../lib/extensions/Util'; export const pronounMapping = { unspecified: 'Unspecified', diff --git a/src/commands/moderation/ban.ts b/src/commands/moderation/ban.ts index f843ac4..4847d19 100644 --- a/src/commands/moderation/ban.ts +++ b/src/commands/moderation/ban.ts @@ -1,9 +1,9 @@ import { ApplicationCommandOptionType } from 'discord-api-types'; import { CommandInteraction, Message, User } from 'discord.js'; import moment from 'moment'; +import { SlashCommandOption } from '../../lib/extensions/BushClientUtil'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; -import { SlashCommandOption } from '../../lib/extensions/Util'; import { Ban, Guild, Modlog, ModlogType } from '../../lib/models'; const durationAliases: Record<string, string[]> = { @@ -133,8 +133,8 @@ export default class BanCommand extends BushCommand { await modlogEnry.save(); await banEntry.save(); } catch (e) { - console.error(e); - yield 'Error saving to database. Please report this to a developer.'; + this.client.console.error(`BanCommand`, `Error saving to database. ${e?.stack}`); + yield `${this.client.util.emojis.error} Error saving to database. Please report this to a developer.`; return; } try { @@ -144,18 +144,18 @@ export default class BanCommand extends BushCommand { } with reason \`${reason || 'No reason given'}\`` ); } catch (e) { - yield 'Error sending message to user'; + yield `${this.client.util.emojis.warn} Unable to dm user`; } await message.guild.members.ban(user, { reason: `Banned by ${message instanceof CommandInteraction ? message.user.tag : message.author.tag} with ${ reason ? `reason ${reason}` : 'no reason' }` }); - yield `Banned <@!${user.id}> ${ + yield `${this.client.util.emojis.success} Banned <@!${user.id}> ${ translatedTime.length >= 1 ? `for ${translatedTime.join(', ')}` : 'permanently' } with reason \`${reason || 'No reason given'}\``; } catch { - yield 'Error banning :/'; + yield `${this.client.util.emojis.error} Error banning :/`; await banEntry.destroy(); await modlogEnry.destroy(); return; diff --git a/src/commands/moderation/kick.ts b/src/commands/moderation/kick.ts index eed0122..7bd53e0 100644 --- a/src/commands/moderation/kick.ts +++ b/src/commands/moderation/kick.ts @@ -71,14 +71,14 @@ export default class KickCommand extends BushCommand { }); await modlogEnry.save(); } catch (e) { - console.error(e); - yield 'Error saving to database. Please report this to a developer.'; + this.client.console.error(`BanCommand`, `Error saving to database. ${e?.stack}`); + yield `${this.client.util.emojis.error} Error saving to database. Please report this to a developer.`; return; } try { await user.send(`You were kicked in ${message.guild.name} with reason \`${reason || 'No reason given'}\``); } catch (e) { - yield 'Error sending message to user'; + yield `${this.client.util.emojis.warn} Unable to dm user`; } try { await user.kick( @@ -87,11 +87,11 @@ export default class KickCommand extends BushCommand { }` ); } catch { - yield 'Error kicking :/'; + yield `${this.client.util.emojis.error} Error kicking :/`; await modlogEnry.destroy(); return; } - yield `Kicked <@!${user.id}> with reason \`${reason || 'No reason given'}\``; + yield `${this.client.util.emojis.success} Kicked <@!${user.id}> with reason \`${reason || 'No reason given'}\``; } async exec(message: Message, { user, reason }: { user: GuildMember; reason?: string }): Promise<void> { diff --git a/src/commands/moderation/role.ts b/src/commands/moderation/role.ts index 8951560..1b82245 100644 --- a/src/commands/moderation/role.ts +++ b/src/commands/moderation/role.ts @@ -43,7 +43,7 @@ export default class RoleCommand extends BushCommand { type: 'member', prompt: { start: `What user do you want to add/remove the role on?`, - retry: `<:error:837123021016924261> Choose a valid user to add/remove the role on.` + retry: `{error} Choose a valid user to add/remove the role on.` } }, { @@ -52,7 +52,7 @@ export default class RoleCommand extends BushCommand { match: 'restContent', prompt: { start: `What role do you want to add/remove?`, - retry: `<:error:837123021016924261> Choose a valid role to add/remove.` + retry: `{error} Choose a valid role to add/remove.` } } ], @@ -78,7 +78,7 @@ export default class RoleCommand extends BushCommand { const mappedRole = this.client.util.moulberryBushRoleMap.find((m) => m.id === role.id); if (!mappedRole || !this.roleWhitelist[mappedRole.name]) { return message.util.reply({ - content: `<:error:837123021016924261> <@&${role.id}> is not whitelisted, and you do not have manage roles permission.`, + content: `${this.client.util.emojis.error} <@&${role.id}> is not whitelisted, and you do not have manage roles permission.`, allowedMentions: AllowedMentions.none() }); } @@ -87,7 +87,7 @@ export default class RoleCommand extends BushCommand { }); if (!message.member.roles.cache.some((role) => allowedRoles.includes(role.id))) { return message.util.reply({ - content: `<:error:837123021016924261> <@&${role.id}> is whitelisted, but you do not have any of the roles required to manage it.`, + content: `${this.client.util.emojis.error} <@&${role.id}> is whitelisted, but you do not have any of the roles required to manage it.`, allowedMentions: AllowedMentions.none() }); } @@ -95,19 +95,19 @@ export default class RoleCommand extends BushCommand { if (!this.client.ownerID.includes(message.author.id)) { if (role.comparePositionTo(message.member.roles.highest) >= 0) { return message.util.reply({ - content: `<:error:837123021016924261> <@&${role.id}> is higher or equal to your highest role.`, + content: `${this.client.util.emojis.error} <@&${role.id}> is higher or equal to your highest role.`, allowedMentions: AllowedMentions.none() }); } if (role.comparePositionTo(message.guild.me.roles.highest) >= 0) { return message.util.reply({ - content: `<:error:837123021016924261> <@&${role.id}> is higher or equal to my highest role.`, + content: `${this.client.util.emojis.error} <@&${role.id}> is higher or equal to my highest role.`, allowedMentions: AllowedMentions.none() }); } if (role.managed) { await message.util.reply({ - content: `<:error:837123021016924261> <@&${role.id}> is managed by an integration and cannot be managed.`, + content: `${this.client.util.emojis.error} <@&${role.id}> is managed by an integration and cannot be managed.`, allowedMentions: AllowedMentions.none() }); } @@ -118,12 +118,12 @@ export default class RoleCommand extends BushCommand { await user.roles.remove(role.id); } catch { return message.util.reply({ - content: `<:error:837123021016924261> Could not remove <@&${role.id}> from <@${user.id}>.`, + content: `${this.client.util.emojis.error} Could not remove <@&${role.id}> from <@${user.id}>.`, allowedMentions: AllowedMentions.none() }); } return message.util.reply({ - content: `<:checkmark:837109864101707807> Successfully removed <@&${role.id}> from <@${user.id}>!`, + content: `${this.client.util.emojis.success} Successfully removed <@&${role.id}> from <@${user.id}>!`, allowedMentions: AllowedMentions.none() }); } else { @@ -131,12 +131,12 @@ export default class RoleCommand extends BushCommand { await user.roles.add(role.id); } catch { return message.util.reply({ - content: `<:error:837123021016924261> Could not add <@&${role.id}> to <@${user.id}>.`, + content: `${this.client.util.emojis.error} Could not add <@&${role.id}> to <@${user.id}>.`, allowedMentions: AllowedMentions.none() }); } return message.util.reply({ - content: `<:checkmark:837109864101707807> Successfully added <@&${role.id}> to <@${user.id}>!`, + content: `${this.client.util.emojis.success} Successfully added <@&${role.id}> to <@${user.id}>!`, allowedMentions: AllowedMentions.none() }); } diff --git a/src/commands/moulberry-bush/capePerms.ts b/src/commands/moulberry-bush/capePerms.ts index 7eb90c5..380ed2d 100644 --- a/src/commands/moulberry-bush/capePerms.ts +++ b/src/commands/moulberry-bush/capePerms.ts @@ -1,9 +1,9 @@ import { ApplicationCommandOptionType } from 'discord-api-types'; import { Message, MessageEmbed } from 'discord.js'; import got from 'got'; +import { SlashCommandOption } from '../../lib/extensions/BushClientUtil'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; -import { SlashCommandOption } from '../../lib/extensions/Util'; interface Capeperms { success: boolean; @@ -57,7 +57,7 @@ export default class CapePermissionsCommand extends BushCommand { type: 'string', prompt: { start: 'Who would you like to see the cape permissions of?', - retry: '<:error:837123021016924261> Choose someone to see the capes their available capes.', + retry: '{error} Choose someone to see the capes their available capes.', optional: false } } @@ -79,7 +79,7 @@ export default class CapePermissionsCommand extends BushCommand { try { uuid = await this.client.util.mcUUID(user); } catch (e) { - return { content: `<:error:837123021016924261> \`${user}\` doesn't appear to be a valid username.` }; + return { content: `${this.client.util.emojis.error} \`${user}\` doesn't appear to be a valid username.` }; } try { @@ -88,11 +88,12 @@ export default class CapePermissionsCommand extends BushCommand { capeperms = null; } if (capeperms == null) { - return { content: `<:error:837123021016924261> There was an error finding cape perms for \`${user}\`.` }; + return { content: `${this.client.util.emojis.error} There was an error finding cape perms for \`${user}\`.` }; } else { if (capeperms?.perms) { const foundUser = capeperms.perms.find((u) => u._id === uuid); - if (foundUser == null) return { content: `<:error:837123021016924261> \`${user}\` does not appear to have any capes.` }; + if (foundUser == null) + return { content: `${this.client.util.emojis.error} \`${user}\` does not appear to have any capes.` }; const userPerm: string[] = foundUser.perms; const embed = this.client.util .createEmbed(this.client.util.colors.default) @@ -100,7 +101,7 @@ export default class CapePermissionsCommand extends BushCommand { .setDescription(userPerm.join('\n')); return { embeds: [embed] }; } else { - return { content: `<:error:837123021016924261> There was an error finding cape perms for ${user}.` }; + return { content: `${this.client.util.emojis.error} There was an error finding cape perms for ${user}.` }; } } } diff --git a/src/commands/moulberry-bush/giveawayPing.ts b/src/commands/moulberry-bush/giveawayPing.ts index 9a03140..d308602 100644 --- a/src/commands/moulberry-bush/giveawayPing.ts +++ b/src/commands/moulberry-bush/giveawayPing.ts @@ -24,9 +24,9 @@ export default class GiveawayPingCommand extends BushCommand { } public async exec(message: Message): Promise<unknown> { if (message.guild.id !== '516977525906341928') - return message.reply("<:error:837123021016924261> This command may only be run in Moulberry's Bush."); + return message.reply(`${this.client.util.emojis.error} This command may only be run in Moulberry's Bush.`); if (!['767782084981817344', '833855738501267456'].includes(message.channel.id)) - return message.reply('<:error:837123021016924261> This command may only be run in giveaway channels.'); + return message.reply(`${this.client.util.emojis.error} This command may only be run in giveaway channels.`); await message.delete().catch(() => undefined); const webhooks = await (message.channel as TextChannel | NewsChannel).fetchWebhooks(); let webhookClient: WebhookClient; @@ -38,8 +38,7 @@ export default class GiveawayPingCommand extends BushCommand { webhookClient = new WebhookClient(webhook.id, webhook.token); } return webhookClient.send({ - content: - '🎉 <@&767782793261875210> Giveaway.\n\n<:mad:783046135392239626> Spamming, line breaking, gibberish etc. disqualifies you from winning. We can and will ban you from giveaways. Winners will all be checked and rerolled if needed.', + content: `🎉 <@&767782793261875210> Giveaway.\n\n${this.client.util.emojis.mad} Spamming, line breaking, gibberish etc. disqualifies you from winning. We can and will ban you from giveaways. Winners will all be checked and rerolled if needed.`, username: `${message.member.nickname || message.author.username}`, avatarURL: message.author.avatarURL({ dynamic: true }), allowedMentions: AllowedMentions.roles() diff --git a/src/commands/moulberry-bush/rule.ts b/src/commands/moulberry-bush/rule.ts index b71b42f..674b776 100644 --- a/src/commands/moulberry-bush/rule.ts +++ b/src/commands/moulberry-bush/rule.ts @@ -1,9 +1,9 @@ import { Argument } from 'discord-akairo'; import { ApplicationCommandOptionType } from 'discord-api-types'; import { CommandInteraction, Message, MessageEmbed, User } from 'discord.js'; +import { SlashCommandOption } from '../../lib/extensions/BushClientUtil'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushInteractionMessage } from '../../lib/extensions/BushInteractionMessage'; -import { SlashCommandOption } from '../../lib/extensions/Util'; export default class RuleCommand extends BushCommand { private rules = [ @@ -80,7 +80,7 @@ export default class RuleCommand extends BushCommand { type: Argument.range('number', 1, 12, true), prompt: { start: 'What rule would you like to have cited?', - retry: '<:no:787549684196704257> Choose a valid rule.', + retry: '{error} Choose a valid rule.', optional: true }, default: undefined @@ -90,7 +90,7 @@ export default class RuleCommand extends BushCommand { type: 'user', prompt: { start: 'What user would you like to mention?', - retry: '<:no:787549684196704257> Choose a valid user to mention.', + retry: '{error} Choose a valid user to mention.', optional: true }, default: undefined @@ -123,7 +123,7 @@ export default class RuleCommand extends BushCommand { message.guild.id !== '516977525906341928' && !this.client.ownerID.includes(message instanceof Message ? message.author.id : message.user.id) ) { - return { content: "<:no:787549684196704257> This command can only be run in Moulberry's Bush." }; + return { content: `${this.client.util.emojis.error} This command can only be run in Moulberry's Bush.` }; } let rulesEmbed = new MessageEmbed().setColor('ef3929'); if (message instanceof Message) { diff --git a/src/config/example-options.ts b/src/config/example-options.ts index a00ba42..ce8f782 100644 --- a/src/config/example-options.ts +++ b/src/config/example-options.ts @@ -2,7 +2,9 @@ import { Snowflake } from 'discord.js'; // Credentials export const credentials = { - botToken: 'token here' + token: 'Token Here', + devToken: 'Token Here', + hypixelApiKey: 'API Key Here' }; // Options diff --git a/src/lib/extensions/BushClient.ts b/src/lib/extensions/BushClient.ts index e2e889b..1bd3493 100644 --- a/src/lib/extensions/BushClient.ts +++ b/src/lib/extensions/BushClient.ts @@ -1,26 +1,30 @@ import chalk from 'chalk'; -import { AkairoClient, InhibitorHandler, ListenerHandler, TaskHandler } from 'discord-akairo'; -import { Guild, Intents, Snowflake } from 'discord.js'; +import { AkairoClient, TaskHandler } from 'discord-akairo'; +import { APIMessage, Guild, Intents, Message, MessageOptions, Snowflake, UserResolvable } from 'discord.js'; import * as path from 'path'; import { exit } from 'process'; import { Sequelize } from 'sequelize'; import * as config from '../../config/options'; import * as Models from '../models'; import AllowedMentions from '../utils/AllowedMentions'; -import { BushLogger } from '../utils/Logger'; +import { BushCache } from '../utils/BushCache'; +import { BushLogger } from '../utils/BushLogger'; +import { BushClientUtil } from './BushClientUtil'; import { BushCommandHandler } from './BushCommandHandler'; -import { BushUtil } from './Util'; +import { BushInhibitorHandler } from './BushInhinitorHandler'; +import { BushListenerHandler } from './BushListenerHandler'; export type BotConfig = typeof config; +export type BushMessageType = string | APIMessage | (MessageOptions & { split?: false }); export class BushClient extends AkairoClient { public config: BotConfig; - public listenerHandler: ListenerHandler; - public inhibitorHandler: InhibitorHandler; + public listenerHandler: BushListenerHandler; + public inhibitorHandler: BushInhibitorHandler; public commandHandler: BushCommandHandler; public taskHandler: TaskHandler; - public util: BushUtil; - public ownerID: Snowflake[]; + public declare util: BushClientUtil; + public declare ownerID: Snowflake[]; public db: Sequelize; public logger: BushLogger; constructor(config: BotConfig) { @@ -36,19 +40,19 @@ export class BushClient extends AkairoClient { ); // Set token - this.token = config.credentials.botToken; + this.token = config.credentials.token; // Set config this.config = config; // Create listener handler - this.listenerHandler = new ListenerHandler(this, { + this.listenerHandler = new BushListenerHandler(this, { directory: path.join(__dirname, '..', '..', 'listeners'), automateCategories: true }); // Create inhibitor handler - this.inhibitorHandler = new InhibitorHandler(this, { + this.inhibitorHandler = new BushInhibitorHandler(this, { directory: path.join(__dirname, '..', '..', 'inhibitors'), automateCategories: true }); @@ -72,18 +76,24 @@ export class BushClient extends AkairoClient { commandUtilLifetime: 3e5, argumentDefaults: { prompt: { - timeout: 'Timed out.', - ended: 'Too many tries.', - cancel: 'Canceled.', + start: 'Placeholder argument prompt. If you see this please tell the devs.', + retry: 'Placeholder failed argument prompt. If you see this please tell the devs.', + modifyStart: (_: Message, str: string): string => `${str}\n\n Type \`cancel\` to cancel the command`, + modifyRetry: (_: Message, str: string): string => + `${str.replace('{error}', this.util.emojis.error)}\n\n Type \`cancel\` to cancel the command`, + timeout: 'You took too long the command has been cancelled', + ended: 'You exceeded the maximum amount of tries the command has been cancelled', + cancel: 'The command has been cancelled', + retries: 3, time: 3e4 - } + }, + otherwise: '' }, ignorePermissions: this.config.owners, - ignoreCooldown: this.config.owners, - automateCategories: true + ignoreCooldown: this.config.owners }); - this.util = new BushUtil(this); + this.util = new BushClientUtil(this); this.db = new Sequelize(this.config.dev ? 'bushbot-dev' : 'bushbot', this.config.db.username, this.config.db.password, { dialect: 'postgres', host: this.config.db.host, @@ -93,6 +103,10 @@ export class BushClient extends AkairoClient { this.logger = new BushLogger(this); } + get console(): BushLogger { + return this.logger; + } + // Initialize everything private async _init(): Promise<void> { this.commandHandler.useListenerHandler(this.listenerHandler); @@ -112,9 +126,9 @@ export class BushClient extends AkairoClient { for (const loader of Object.keys(loaders)) { try { loaders[loader].loadAll(); - this.logger.log(chalk.green('Successfully loaded ' + chalk.cyan(loader) + '.')); + this.logger.success('Startup', `Successfully loaded <<${loader}>>.` + chalk.cyan() + '.', false); } catch (e) { - console.error(chalk.red('Unable to load loader ' + chalk.cyan(loader) + ' with error ' + e)); + this.logger.error('Startup', `Unable to load loader <<${loader}>> with error:\n${e?.stack}`, false); } } this.taskHandler.startAll(); @@ -122,12 +136,14 @@ export class BushClient extends AkairoClient { } public async dbPreInit(): Promise<void> { - await this.db.authenticate(); - Models.Guild.initModel(this.db, this); - Models.Modlog.initModel(this.db); - Models.Ban.initModel(this.db); - Models.Level.initModel(this.db); - await this.db.sync(); // Sync all tables to fix everything if updated + try { + await this.db.authenticate(); + Models.Guild.initModel(this.db, this); + Models.Modlog.initModel(this.db); + Models.Ban.initModel(this.db); + Models.Level.initModel(this.db); + await this.db.sync(); // Sync all tables to fix everything if updated + } catch (error) {} } public async start(): Promise<void> { @@ -135,7 +151,7 @@ export class BushClient extends AkairoClient { await this._init(); await this.login(this.token); } catch (e) { - console.error(chalk.red(e.stack)); + this.console.error('Start', chalk.red(e.stack), false); exit(2); } } @@ -146,4 +162,12 @@ export class BushClient extends AkairoClient { return this.login(this.token); } } + + public isOwner(user: UserResolvable): boolean { + return this.config.owners.includes(this.users.resolveID(user)); + } + public isSuperUser(user: UserResolvable): boolean { + const userID = this.users.resolveID(user); + return !!BushCache?.superUsers?.includes(userID) || this.config.owners.includes(userID); + } } diff --git a/src/lib/extensions/BushClientUtil.ts b/src/lib/extensions/BushClientUtil.ts new file mode 100644 index 0000000..9b87efd --- /dev/null +++ b/src/lib/extensions/BushClientUtil.ts @@ -0,0 +1,879 @@ +import { exec } from 'child_process'; +import { ClientUtil, Command } from 'discord-akairo'; +import { + APIInteractionDataResolvedChannel, + APIInteractionDataResolvedGuildMember, + APIMessage, + APIRole, + ApplicationCommandOptionType +} from 'discord-api-types'; +import { + ButtonInteraction, + CommandInteraction, + CommandInteractionOption, + Constants, + Guild, + GuildChannel, + GuildMember, + InteractionReplyOptions, + Message, + MessageActionRow, + MessageButton, + MessageComponentInteraction, + MessageEditOptions, + MessageEmbed, + MessageOptions, + Role, + Snowflake, + TextChannel, + User, + Util, + WebhookEditMessageOptions +} from 'discord.js'; +import got from 'got'; +import { promisify } from 'util'; +import { BushClient } from './BushClient'; +import { BushMessage } from './BushMessage'; + +interface hastebinRes { + key: string; +} + +export interface uuidRes { + uuid: string; + username: string; + username_history?: { username: string }[] | null; + textures: { + custom: boolean; + slim: boolean; + skin: { + url: string; + data: string; + }; + raw: { + value: string; + signature: string; + }; + }; + created_at: string; +} + +export interface SlashCommandOption<T> { + name: string; + type: ApplicationCommandOptionType; + value?: T; + options?: CommandInteractionOption[]; + user?: User; + member?: GuildMember | APIInteractionDataResolvedGuildMember; + channel?: GuildChannel | APIInteractionDataResolvedChannel; + role?: Role | APIRole; +} + +export class BushClientUtil extends ClientUtil { + /** The client of this ClientUtil */ + public declare client: BushClient; + /** The hastebin urls used to post to hastebin, attempts to post in order */ + public hasteURLs: string[] = [ + 'https://hst.sh', + 'https://hasteb.in', + 'https://hastebin.com', + 'https://mystb.in', + 'https://haste.clicksminuteper.net', + 'https://paste.pythondiscord.com', + 'https://haste.unbelievaboat.com', + 'https://haste.tyman.tech' + ]; + public paginateEmojis = { + beginning: '853667381335162910', + back: '853667410203770881', + stop: '853667471110570034', + forward: '853667492680564747', + end: '853667514915225640' + }; + + /** A simple promise exec method */ + private exec = promisify(exec); + + /** + * Creates this client util + * @param client The client to initialize with + */ + constructor(client: BushClient) { + super(client); + } + + /** + * Maps an array of user ids to user objects. + * @param ids The list of IDs to map + * @returns The list of users mapped + */ + public async mapIDs(ids: Snowflake[]): Promise<User[]> { + return await Promise.all(ids.map((id) => this.client.users.fetch(id))); + } + + /** + * Capitalizes the first letter of the given text + * @param text The text to capitalize + * @returns The capitalized text + */ + public capitalize(text: string): string { + return text.charAt(0).toUpperCase() + text.slice(1); + } + + /** + * Runs a shell command and gives the output + * @param command The shell command to run + * @returns The stdout and stderr of the shell command + */ + public async shell(command: string): Promise<{ + stdout: string; + stderr: string; + }> { + return await this.exec(command); + } + + /** + * Posts text to hastebin + * @param content The text to post + * @returns The url of the posted text + */ + public async haste(content: string): Promise<string> { + for (const url of this.hasteURLs) { + try { + const res: hastebinRes = await got.post(`${url}/documents`, { body: content }).json(); + return `${url}/${res.key}`; + } catch (e) { + this.client.console.error('Haste', `Unable to upload haste to ${url}`); + continue; + } + } + return 'Unable to post'; + } + + /** + * Resolves a user-provided string into a user object, if possible + * @param text The text to try and resolve + * @returns The user resolved or null + */ + public async resolveUserAsync(text: string): Promise<User | null> { + const idReg = /\d{17,19}/; + const idMatch = text.match(idReg); + if (idMatch) { + try { + const user = await this.client.users.fetch(text as Snowflake); + return user; + } catch { + // pass + } + } + const mentionReg = /<@!?(?<id>\d{17,19})>/; + const mentionMatch = text.match(mentionReg); + if (mentionMatch) { + try { + const user = await this.client.users.fetch(mentionMatch.groups.id as Snowflake); + return user; + } catch { + // pass + } + } + const user = this.client.users.cache.find((u) => u.username === text); + if (user) return user; + return null; + } + + /** + * Appends the correct ordinal to the given number + * @param n The number to append an ordinal to + * @returns The number with the ordinal + */ + public ordinal(n: number): string { + const s = ['th', 'st', 'nd', 'rd'], + v = n % 100; + return n + (s[(v - 20) % 10] || s[v] || s[0]); + } + + /** + * Chunks an array to the specified size + * @param arr The array to chunk + * @param perChunk The amount of items per chunk + * @returns The chunked array + */ + public chunk<T>(arr: T[], perChunk: number): T[][] { + return arr.reduce((all, one, i) => { + const ch = Math.floor(i / perChunk); + all[ch] = [].concat(all[ch] || [], one); + return all; + }, []); + } + + /** Commonly Used Colors */ + public colors = { + default: '#1FD8F1', + error: '#EF4947', + warn: '#FEBA12', + success: '#3BB681', + info: '#3B78FF', + red: '#ff0000', + blue: '#0055ff', + aqua: '#00bbff', + purple: '#8400ff', + blurple: '#5440cd', + pink: '#ff00e6', + green: '#00ff1e', + darkGreen: '#008f11', + gold: '#b59400', + yellow: '#ffff00', + white: '#ffffff', + gray: '#a6a6a6', + lightGray: '#cfcfcf', + darkGray: '#7a7a7a', + black: '#000000', + orange: '#E86100' + }; + + /** Commonly Used Emojis */ + public emojis = { + success: '<:checkmark:837109864101707807>', + warn: '<:warn:848726900876247050> ', + error: '<:error:837123021016924261>', + successFull: '<:checkmark_full:850118767576088646>', + warnFull: '<:warn_full:850118767391539312>', + errorFull: '<:error_full:850118767295201350>', + mad: '<:mad:783046135392239626>', + join: '<:join:850198029809614858>', + leave: '<:leave:850198048205307919>', + loading: '<a:Loading:853419254619963392>' + }; + + /** + * A simple utility to create and embed with the needed style for the bot + */ + public createEmbed(color?: string, author?: User | GuildMember): MessageEmbed { + if (author instanceof GuildMember) { + author = author.user; // Convert to User if GuildMember + } + let embed = new MessageEmbed().setTimestamp(); + if (author) + embed = embed.setAuthor( + author.username, + author.displayAvatarURL({ dynamic: true }), + `https://discord.com/users/${author.id}` + ); + if (color) embed = embed.setColor(color); + return embed; + } + + public async mcUUID(username: string): Promise<string> { + const apiRes = (await got.get(`https://api.ashcon.app/mojang/v2/user/${username}`).json()) as uuidRes; + return apiRes.uuid.replace(/-/g, ''); + } + + public async syncSlashCommands(force = false, guild?: Snowflake): Promise<void> { + let fetchedGuild: Guild; + if (guild) fetchedGuild = this.client.guilds.cache.get(guild); + try { + const registered = + guild === undefined ? await this.client.application.commands.fetch() : await fetchedGuild.commands.fetch(); + for (const [, registeredCommand] of registered) { + if (!this.client.commandHandler.modules.find((cmd) => cmd.id == registeredCommand.name)?.execSlash || force) { + guild === undefined + ? await this.client.application.commands.delete(registeredCommand.id) + : await fetchedGuild.commands.delete(registeredCommand.id); + this.client.logger.verbose( + 'syncSlashCommands', + `Deleted slash command <<${registeredCommand.name}>>${ + guild !== undefined ? ` in guild <<${fetchedGuild.name}>>` : '' + }` + ); + } + } + + for (const [, botCommand] of this.client.commandHandler.modules) { + if (botCommand.execSlash) { + const found = registered.find((i) => i.name == botCommand.id); + Command; + const slashdata = { + name: botCommand.id, + description: botCommand.description.content, + options: botCommand.options.slashCommandOptions + }; + botCommand; + + if (found?.id && !force) { + if (slashdata.description !== found.description) { + guild === undefined + ? await this.client.application.commands.edit(found.id, slashdata) + : fetchedGuild.commands.edit(found.id, slashdata); + this.client.logger.verbose( + 'syncSlashCommands', + `Edited slash command <<${botCommand.id}>>${guild !== undefined ? ` in guild <<${fetchedGuild?.name}>>` : ''}` + ); + } + } else { + guild === undefined + ? await this.client.application.commands.create(slashdata) + : fetchedGuild.commands.create(slashdata); + this.client.logger.verbose( + 'syncSlashCommands', + `Created slash command <<${botCommand.id}>>${guild !== undefined ? ` in guild <<${fetchedGuild?.name}>>` : ''}}` + ); + } + } + } + + return this.client.logger.log( + 'syncSlashCommands', + `Slash commands registered${guild !== undefined ? ` in guild <<${fetchedGuild?.name}>>` : ''}` + ); + } catch (e) { + return this.client.logger.error( + 'syncSlashCommands', + `Slash commands not registered${ + guild !== undefined ? ` in guild <<${fetchedGuild?.name}>>` : '' + }, with the following error:\n${e?.stack}` + ); + } + } + + public moulberryBushRoleMap = [ + { name: '*', id: '792453550768390194' }, + { name: 'Admin Perms', id: '746541309853958186' }, + { name: 'Sr. Moderator', id: '782803470205190164' }, + { name: 'Moderator', id: '737308259823910992' }, + { name: 'Helper', id: '737440116230062091' }, + { name: 'Trial Helper', id: '783537091946479636' }, + { name: 'Contributor', id: '694431057532944425' }, + { name: 'Giveaway Donor', id: '784212110263451649' }, + { name: 'Giveaway (200m)', id: '810267756426690601' }, + { name: 'Giveaway (100m)', id: '801444430522613802' }, + { name: 'Giveaway (50m)', id: '787497512981757982' }, + { name: 'Giveaway (25m)', id: '787497515771232267' }, + { name: 'Giveaway (10m)', id: '787497518241153025' }, + { name: 'Giveaway (5m)', id: '787497519768403989' }, + { name: 'Giveaway (1m)', id: '787497521084891166' }, + { name: 'Suggester', id: '811922322767609877' }, + { name: 'Partner', id: '767324547312779274' }, + { name: 'Level Locked', id: '784248899044769792' }, + { name: 'No Files', id: '786421005039173633' }, + { name: 'No Reactions', id: '786421270924361789' }, + { name: 'No Links', id: '786421269356740658' }, + { name: 'No Bots', id: '786804858765312030' }, + { name: 'No VC', id: '788850482554208267' }, + { name: 'No Giveaways', id: '808265422334984203' }, + { name: 'No Support', id: '790247359824396319' } + ]; + + /** Paginates an array of embeds using buttons. */ + public async buttonPaginate( + message: BushMessage, + embeds: MessageEmbed[], + text: string | null = null, + deleteOnExit?: boolean + ): Promise<void> { + if (deleteOnExit === undefined) deleteOnExit = true; + + embeds.forEach((_e, i) => { + embeds[i] = embeds[i].setFooter(`Page ${i + 1}/${embeds.length}`); + }); + + const style = Constants.MessageButtonStyles.PRIMARY; + let curPage = 0; + if (typeof embeds !== 'object') throw 'embeds must be an object'; + const msg = (await message.util.reply({ + content: text, + embeds: [embeds[curPage]], + components: [getPaginationRow()] + })) as Message; + const filter = (interaction: ButtonInteraction) => + interaction.customID.startsWith('paginate_') && interaction.message == msg; + const collector = msg.createMessageComponentInteractionCollector(filter, { time: 300000 }); + collector.on('collect', async (interaction: MessageComponentInteraction) => { + if (interaction.user.id == message.author.id || this.client.config.owners.includes(interaction.user.id)) { + switch (interaction.customID) { + case 'paginate_beginning': { + curPage = 0; + await edit(interaction); + break; + } + case 'paginate_back': { + curPage--; + await edit(interaction); + break; + } + case 'paginate_stop': { + if (deleteOnExit) { + await interaction.deferUpdate().catch(() => {}); + if (msg.deletable && !msg.deleted) { + await msg.delete(); + } + } else { + await interaction + ?.update({ content: `${text ? text + '\n' : ''}Command closed by user.`, embeds: [], components: [] }) + .catch(() => {}); + } + return; + } + case 'paginate_next': { + curPage++; + await edit(interaction); + break; + } + case 'paginate_end': { + curPage = embeds.length - 1; + await edit(interaction); + break; + } + } + } else { + return await interaction?.deferUpdate().catch(() => {}); + } + }); + + collector.on('end', async () => { + await msg.edit({ content: text, embeds: [embeds[curPage]], components: [getPaginationRow(true)] }).catch(() => {}); + }); + + async function edit(interaction: MessageComponentInteraction): Promise<void> { + return await interaction + ?.update({ content: text, embeds: [embeds[curPage]], components: [getPaginationRow()] }) + .catch(() => {}); + } + const paginateEmojis = this.paginateEmojis; + function getPaginationRow(disableAll = false): MessageActionRow { + return new MessageActionRow().addComponents( + new MessageButton({ + style, + customID: 'paginate_beginning', + emoji: paginateEmojis.beginning, + disabled: disableAll || curPage == 0 + }), + new MessageButton({ + style, + customID: 'paginate_back', + emoji: paginateEmojis.back, + disabled: disableAll || curPage == 0 + }), + new MessageButton({ style, customID: 'paginate_stop', emoji: paginateEmojis.stop, disabled: disableAll }), + new MessageButton({ + style, + customID: 'paginate_next', + emoji: paginateEmojis.forward, + disabled: disableAll || curPage == embeds.length - 1 + }), + new MessageButton({ + style, + customID: 'paginate_end', + emoji: paginateEmojis.end, + disabled: disableAll || curPage == embeds.length - 1 + }) + ); + } + } + + /** Sends a message with a button for the user to delete it. */ + public async sendWithDeleteButton(message: BushMessage, options: MessageOptions): Promise<void> { + updateOptions(); + const msg = (await message.util.reply(options as MessageOptions & { split?: false })) as Message; + const filter = (interaction: ButtonInteraction) => interaction.customID == 'paginate__stop' && interaction.message == msg; + const collector = msg.createMessageComponentInteractionCollector(filter, { time: 300000 }); + collector.on('collect', async (interaction: MessageComponentInteraction) => { + if (interaction.user.id == message.author.id || this.client.config.owners.includes(interaction.user.id)) { + await interaction.deferUpdate().catch(() => {}); + if (msg.deletable && !msg.deleted) { + await msg.delete(); + } + return; + } else { + return await interaction?.deferUpdate().catch(() => {}); + } + }); + + collector.on('end', async () => { + updateOptions(true, true); + await msg.edit(options as MessageEditOptions).catch(() => {}); + }); + + const paginateEmojis = this.paginateEmojis; + function updateOptions(edit?: boolean, disable?: boolean) { + if (edit == undefined) edit = false; + if (disable == undefined) disable = false; + options.components = [ + new MessageActionRow().addComponents( + new MessageButton({ + style: Constants.MessageButtonStyles.PRIMARY, + customID: 'paginate__stop', + emoji: paginateEmojis.stop, + disabled: disable + }) + ) + ]; + if (edit) { + options.reply = undefined; + } + } + } + + /** + * Surrounds text in a code block with the specified language and puts it in a hastebin if its too long. + * + * * Embed Description Limit = 2048 characters + * * Embed Field Limit = 1024 characters + */ + public async codeblock(code: string, length: number, language: 'ts' | 'js' | 'sh' | 'json' | '' = ''): Promise<string> { + let hasteOut = ''; + const tildes = '```'; + const formattingLength = 2 * tildes.length + language.length + 2 * '\n'.length; + if (code.length + formattingLength > length) hasteOut = 'Too large to display. Hastebin: ' + (await this.haste(code)); + + const code2 = code.length > length ? code.substring(0, length - (hasteOut.length + '\n'.length + formattingLength)) : code; + return ( + tildes + language + '\n' + Util.cleanCodeBlockContent(code2) + '\n' + tildes + (hasteOut.length ? '\n' + hasteOut : '') + ); + } + + public async slashRespond( + interaction: CommandInteraction, + responseOptions: string | InteractionReplyOptions + ): Promise<Message | APIMessage | void> { + let newResponseOptions: InteractionReplyOptions | WebhookEditMessageOptions = {}; + if (typeof responseOptions === 'string') { + newResponseOptions.content = responseOptions; + } else { + newResponseOptions = responseOptions; + } + if (interaction.replied || interaction.deferred) { + //@ts-expect-error: stop being dumb + delete newResponseOptions.ephemeral; // Cannot change a preexisting message to be ephemeral + return (await interaction.editReply(newResponseOptions)) as APIMessage; + } else { + await interaction.reply(newResponseOptions); + return await interaction.fetchReply().catch(() => {}); + } + } + + /** Gets the channel configs as a TextChannel */ + public getConfigChannel(channel: 'log' | 'error' | 'dm'): Promise<TextChannel> { + return this.client.channels.fetch(this.client.config.channels[channel]) as Promise<TextChannel>; + } + + /** A bunch of mappings */ + public mappings = { + guilds: { + bush: '516977525906341928', + tree: '767448775450820639', + staff: '784597260465995796', + space_ship: '717176538717749358', + sbr: '839287012409999391' + }, + + permissions: { + CREATE_INSTANT_INVITE: { name: 'Create Invite', important: false }, + KICK_MEMBERS: { name: 'Kick Members', important: true }, + BAN_MEMBERS: { name: 'Ban Members', important: true }, + ADMINISTRATOR: { name: 'Administrator', important: true }, + MANAGE_CHANNELS: { name: 'Manage Channels', important: true }, + MANAGE_GUILD: { name: 'Manage Server', important: true }, + ADD_REACTIONS: { name: 'Add Reactions', important: false }, + VIEW_AUDIT_LOG: { name: 'View Audit Log', important: true }, + PRIORITY_SPEAKER: { name: 'Priority Speaker', important: true }, + STREAM: { name: 'Video', important: false }, + VIEW_CHANNEL: { name: 'View Channel', important: false }, + SEND_MESSAGES: { name: 'Send Messages', important: false }, + SEND_TTS_MESSAGES: { name: 'Send Text-to-Speech Messages', important: true }, + MANAGE_MESSAGES: { name: 'Manage Messages', important: true }, + EMBED_LINKS: { name: 'Embed Links', important: false }, + ATTACH_FILES: { name: 'Attach Files', important: false }, + READ_MESSAGE_HISTORY: { name: 'Read Message History', important: false }, + MENTION_EVERYONE: { name: 'Mention @everyone, @here, and All Roles', important: true }, // name has a zero-width space to prevent accidents + USE_EXTERNAL_EMOJIS: { name: 'Use External Emoji', important: false }, + VIEW_GUILD_INSIGHTS: { name: 'View Server Insights', important: true }, + CONNECT: { name: 'Connect', important: false }, + SPEAK: { name: 'Speak', important: false }, + MUTE_MEMBERS: { name: 'Mute Members', important: true }, + DEAFEN_MEMBERS: { name: 'Deafen Members', important: true }, + MOVE_MEMBERS: { name: 'Move Members', important: true }, + USE_VAD: { name: 'Use Voice Activity', important: false }, + CHANGE_NICKNAME: { name: 'Change Nickname', important: false }, + MANAGE_NICKNAMES: { name: 'Change Nicknames', important: true }, + MANAGE_ROLES: { name: 'Manage Roles', important: true }, + MANAGE_WEBHOOKS: { name: 'Manage Webhooks', important: true }, + MANAGE_EMOJIS: { name: 'Manage Emojis', important: true }, + USE_APPLICATION_COMMANDS: { name: 'Use Slash Commands', important: false }, + REQUEST_TO_SPEAK: { name: 'Request to Speak', important: false }, + USE_PUBLIC_THREADS: { name: 'Use Public Threads', important: false }, + USE_PRIVATE_THREADS: { name: 'Use Private Threads', important: true } + }, + + features: { + ANIMATED_ICON: { name: 'Animated Icon', important: false, emoji: '<:animatedIcon:850774498071412746>', weight: 14 }, + BANNER: { name: 'Banner', important: false, emoji: '<:banner:850786673150787614>', weight: 15 }, + COMMERCE: { name: 'Store Channels', important: true, emoji: '<:storeChannels:850786692432396338>', weight: 11 }, + COMMUNITY: { name: 'Community', important: false, emoji: '<:community:850786714271875094>', weight: 20 }, + DISCOVERABLE: { name: 'Discoverable', important: true, emoji: '<:discoverable:850786735360966656>', weight: 6 }, + ENABLED_DISCOVERABLE_BEFORE: { + name: 'Enabled Discovery Before', + important: false, + emoji: '<:enabledDiscoverableBefore:850786754670624828>', + weight: 7 + }, + FEATURABLE: { name: 'Featurable', important: true, emoji: '<:featurable:850786776372084756>', weight: 4 }, + INVITE_SPLASH: { name: 'Invite Splash', important: false, emoji: '<:inviteSplash:850786798246559754>', weight: 16 }, + MEMBER_VERIFICATION_GATE_ENABLED: { + name: 'Membership Verification Gate', + important: false, + emoji: '<:memberVerificationGateEnabled:850786829984858212>', + weight: 18 + }, + MONETIZATION_ENABLED: { name: 'Monetization Enabled', important: true, emoji: null, weight: 8 }, + MORE_EMOJI: { name: 'More Emoji', important: true, emoji: '<:moreEmoji:850786853497602080>', weight: 3 }, + MORE_STICKERS: { name: 'More Stickers', important: true, emoji: null, weight: 2 }, + NEWS: { + name: 'Announcement Channels', + important: false, + emoji: '<:announcementChannels:850790491796013067>', + weight: 17 + }, + PARTNERED: { name: 'Partnered', important: true, emoji: '<:partneredServer:850794851955507240>', weight: 1 }, + PREVIEW_ENABLED: { name: 'Preview Enabled', important: true, emoji: '<:previewEnabled:850790508266913823>', weight: 10 }, + RELAY_ENABLED: { name: 'Relay Enabled', important: true, emoji: '<:relayEnabled:850790531441229834>', weight: 5 }, + TICKETED_EVENTS_ENABLED: { name: 'Ticketed Events Enabled', important: true, emoji: null, weight: 9 }, + VANITY_URL: { name: 'Vanity URL', important: false, emoji: '<:vanityURL:850790553079644160>', weight: 12 }, + VERIFIED: { name: 'Verified', important: true, emoji: '<:verified:850795049817473066>', weight: 0 }, + VIP_REGIONS: { name: 'VIP Regions', important: false, emoji: '<:VIPRegions:850794697496854538>', weight: 13 }, + WELCOME_SCREEN_ENABLED: { + name: 'Welcome Screen Enabled', + important: false, + emoji: '<:welcomeScreenEnabled:850790575875817504>', + weight: 19 + } + }, + + otherEmojis: { + SERVER_BOOSTER_1: '<:serverBooster1:848740052091142145>', + SERVER_BOOSTER_2: '<:serverBooster2:848740090506510388>', + SERVER_BOOSTER_3: '<:serverBooster3:848740124992077835>', + SERVER_BOOSTER_6: '<:serverBooster6:848740155245461514>', + SERVER_BOOSTER_9: '<:serverBooster9:848740188846030889>', + SERVER_BOOSTER_12: '<:serverBooster12:848740304365551668>', + SERVER_BOOSTER_15: '<:serverBooster15:848740354890137680>', + SERVER_BOOSTER_18: '<:serverBooster18:848740402886606868>', + SERVER_BOOSTER_24: '<:serverBooster24:848740444628320256>', + NITRO: '<:nitro:848740498054971432>', + BOOSTER: '<:booster:848747775020892200>', + OWNER: '<:owner:848746439311753286>', + ADMIN: '<:admin:848963914628333598>', + SUPERUSER: '<:superUser:848947986326224926>', + DEVELOPER: '<:developer:848954538111139871>', + BUSH_VERIFIED: '<:verfied:853360152090771497>', + BOOST_1: '<:boostitle:853363736679940127>', + BOOST_2: '<:boostitle:853363752728789075>', + BOOST_3: '<:boostitle:853363769132056627>', + TEXT: '<:text:853375537791893524>', + NEWS: '<:announcements:853375553531674644>', + VOICE: '<:voice:853375566735212584>', + STAGE: '<:stage:853375583521210468>', + STORE: '<:store:853375601175691266>', + CATEGORY: '<:category:853375615260819476>' + }, + + userFlags: { + DISCORD_EMPLOYEE: '<:discordEmployee:848742947826434079>', + PARTNERED_SERVER_OWNER: '<:partneredServerOwner:848743051593777152>', + HYPESQUAD_EVENTS: '<:hypeSquadEvents:848743108283072553>', + BUGHUNTER_LEVEL_1: '<:bugHunter:848743239850393640>', + HOUSE_BRAVERY: '<:hypeSquadBravery:848742910563844127>', + HOUSE_BRILLIANCE: '<:hypeSquadBrilliance:848742840649646101>', + HOUSE_BALANCE: '<:hypeSquadBalance:848742877537370133>', + EARLY_SUPPORTER: '<:earlySupporter:848741030102171648>', + //'TEAM_USER': '', + //'SYSTEM': '', + BUGHUNTER_LEVEL_2: '<:bugHunterGold:848743283080822794>', + //'VERIFIED_BOT': '', + EARLY_VERIFIED_BOT_DEVELOPER: '<:earlyVerifiedBotDeveloper:848741079875846174>' + }, + + status: { + online: '<:online:848937141639577690>', + idle: '<:idle:848937158261211146>', + dnd: '<:dnd:848937173780135986>', + offline: '<:offline:848939387277672448>', + streaming: '<:streaming:848937187479519242>' + }, + + maybeNitroDiscrims: ['1111', '2222', '3333', '4444', '5555', '6666', '6969', '7777', '8888', '9999'], + + capes: [ + // supporter capes + { name: 'patreon1', index: 0 }, + { name: 'patreon2', index: 1 }, + { name: 'fade', custom: 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/fade.gif', index: 2 }, + { name: 'lava', custom: 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/lava.gif', index: 3 }, + { + name: 'mcworld', + custom: 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/mcworld_compressed.gif', + index: 4 + }, + { + name: 'negative', + custom: 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/negative_compressed.gif', + index: 5 + }, + { + name: 'space', + custom: 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/space_compressed.gif', + index: 6 + }, + { name: 'void', custom: 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/void.gif', index: 7 }, + { name: 'tunnel', custom: 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/tunnel.gif', index: 8 }, + // Staff capes + { name: 'contrib', index: 9 }, + { name: 'mbstaff', index: 10 }, + { name: 'ironmoon', index: 11 }, + { name: 'gravy', index: 12 }, + { name: 'nullzee', index: 13 }, + // partner capes + { name: 'thebakery', index: 14 }, + { name: 'dsm', index: 15 }, + { name: 'packshq', index: 16 }, + { name: 'furf', index: 17 }, + { name: 'skytils', index: 18 }, + { name: 'sbp', index: 19 }, + { name: 'subreddit_light', index: 20 }, + { name: 'subreddit_dark', index: 21 }, + // streamer capes + { name: 'alexxoffi', index: 22 }, + { name: 'jakethybro', index: 23 }, + { name: 'krusty', index: 24 }, + { name: 'soldier', index: 25 }, + { name: 'zera', index: 26 } + ], + roleMap: [ + { name: '*', id: '792453550768390194' }, + { name: 'Admin Perms', id: '746541309853958186' }, + { name: 'Sr. Moderator', id: '782803470205190164' }, + { name: 'Moderator', id: '737308259823910992' }, + { name: 'Helper', id: '737440116230062091' }, + { name: 'Trial Helper', id: '783537091946479636' }, + { name: 'Contributor', id: '694431057532944425' }, + { name: 'Giveaway Donor', id: '784212110263451649' }, + { name: 'Giveaway (200m)', id: '810267756426690601' }, + { name: 'Giveaway (100m)', id: '801444430522613802' }, + { name: 'Giveaway (50m)', id: '787497512981757982' }, + { name: 'Giveaway (25m)', id: '787497515771232267' }, + { name: 'Giveaway (10m)', id: '787497518241153025' }, + { name: 'Giveaway (5m)', id: '787497519768403989' }, + { name: 'Giveaway (1m)', id: '787497521084891166' }, + { name: 'Suggester', id: '811922322767609877' }, + { name: 'Partner', id: '767324547312779274' }, + { name: 'Level Locked', id: '784248899044769792' }, + { name: 'No Files', id: '786421005039173633' }, + { name: 'No Reactions', id: '786421270924361789' }, + { name: 'No Links', id: '786421269356740658' }, + { name: 'No Bots', id: '786804858765312030' }, + { name: 'No VC', id: '788850482554208267' }, + { name: 'No Giveaways', id: '808265422334984203' }, + { name: 'No Support', id: '790247359824396319' }, + { name: 'DJ', id: '782619038403919902' } + ], + roleWhitelist: { + 'Partner': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'Suggester': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator', 'Helper', 'Trial Helper', 'Contributor'], + 'Level Locked': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'No Files': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'No Reactions': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'No Links': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'No Bots': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'No VC': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'No Giveaways': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator', 'Helper'], + 'No Support': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'Giveaway Donor': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'Giveaway (200m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'Giveaway (100m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'Giveaway (50m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'Giveaway (25m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'Giveaway (10m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'Giveaway (5m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'Giveaway (1m)': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'], + 'DJ': ['*', 'Admin Perms', 'Sr. Moderator', 'Moderator'] + } + }; +} + +// I just copy pasted this code from stackoverflow don't yell at me if there is issues for it +export class CanvasProgressBar { + private x: number; + private y: number; + private w: number; + private h: number; + private color: string; + private percentage: number; + private p: number; + private ctx: CanvasRenderingContext2D; + + constructor( + ctx: CanvasRenderingContext2D, + dimension: { x: number; y: number; width: number; height: number }, + color: string, + percentage: number + ) { + ({ x: this.x, y: this.y, width: this.w, height: this.h } = dimension); + this.color = color; + this.percentage = percentage; + this.p; + this.ctx = ctx; + } + + draw(): void { + // ----------------- + this.p = this.percentage * this.w; + if (this.p <= this.h) { + this.ctx.beginPath(); + this.ctx.arc( + this.h / 2 + this.x, + this.h / 2 + this.y, + this.h / 2, + Math.PI - Math.acos((this.h - this.p) / this.h), + Math.PI + Math.acos((this.h - this.p) / this.h) + ); + this.ctx.save(); + this.ctx.scale(-1, 1); + this.ctx.arc( + this.h / 2 - this.p - this.x, + this.h / 2 + this.y, + this.h / 2, + Math.PI - Math.acos((this.h - this.p) / this.h), + Math.PI + Math.acos((this.h - this.p) / this.h) + ); + this.ctx.restore(); + this.ctx.closePath(); + } else { + this.ctx.beginPath(); + this.ctx.arc(this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, Math.PI / 2, (3 / 2) * Math.PI); + this.ctx.lineTo(this.p - this.h + this.x, 0 + this.y); + this.ctx.arc(this.p - this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, (3 / 2) * Math.PI, Math.PI / 2); + this.ctx.lineTo(this.h / 2 + this.x, this.h + this.y); + this.ctx.closePath(); + } + this.ctx.fillStyle = this.color; + this.ctx.fill(); + } + + // showWholeProgressBar(){ + // this.ctx.beginPath(); + // this.ctx.arc(this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, Math.PI / 2, 3 / 2 * Math.PI); + // this.ctx.lineTo(this.w - this.h + this.x, 0 + this.y); + // this.ctx.arc(this.w - this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, 3 / 2 *Math.PI, Math.PI / 2); + // this.ctx.lineTo(this.h / 2 + this.x, this.h + this.y); + // this.ctx.strokeStyle = '#000000'; + // this.ctx.stroke(); + // this.ctx.closePath(); + // } + + get PPercentage(): number { + return this.percentage * 100; + } + + set PPercentage(x: number) { + this.percentage = x / 100; + } +} diff --git a/src/lib/extensions/BushCommand.ts b/src/lib/extensions/BushCommand.ts index 2b34c69..9de2c95 100644 --- a/src/lib/extensions/BushCommand.ts +++ b/src/lib/extensions/BushCommand.ts @@ -1,8 +1,16 @@ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { Command, CommandOptions } from 'discord-akairo'; import { APIApplicationCommandOption } from 'discord-api-types'; +import { CommandInteraction, Snowflake } from 'discord.js'; import { BushClient } from './BushClient'; +import { BushInteractionMessage } from './BushInteractionMessage'; +import { BushMessage } from './BushMessage'; export interface BushCommandOptions extends CommandOptions { + hidden?: boolean; + restrictedChannels?: Snowflake[]; + restrictedGuilds?: Snowflake[]; slashCommandOptions?: APIApplicationCommandOption[]; description: { content: string; @@ -12,10 +20,33 @@ export interface BushCommandOptions extends CommandOptions { } export class BushCommand extends Command { - public client: BushClient; - options: BushCommandOptions; + public declare client: BushClient; + public options: BushCommandOptions; + /** The channels the command is limited to run in. */ + public restrictedChannels: Snowflake[]; + /** The guilds the command is limited to run in. */ + public restrictedGuilds: Snowflake[]; + /** Whether the command is hidden from the help command. */ + public hidden: boolean; constructor(id: string, options?: BushCommandOptions) { super(id, options); this.options = options; + this.hidden = options.hidden || false; + this.restrictedChannels = options.restrictedChannels; + this.restrictedGuilds = options.restrictedGuilds; + } + + public exec(message: BushMessage, args: any): any; + // @ts-ignore: They are close enough + public exec(message: BushMessage | BushInteractionMessage, args: any): any { + // @ts-ignore: They are close enough + super.exec(message, args); + } + + /** Be careful when using this with a slash command since only the interaction is parsed as the message */ + public before(message: BushMessage): any; + public before(message: BushMessage | CommandInteraction): any; + public before(message) { + super.before(message); } } diff --git a/src/lib/extensions/BushCommandHandler.ts b/src/lib/extensions/BushCommandHandler.ts index 6ef44d7..670125d 100644 --- a/src/lib/extensions/BushCommandHandler.ts +++ b/src/lib/extensions/BushCommandHandler.ts @@ -1,15 +1,279 @@ -import { CommandHandler, CommandHandlerOptions } from 'discord-akairo'; -import { Collection } from 'discord.js'; +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { AkairoMessage, Category, CommandHandler, CommandHandlerOptions, CommandUtil, Util } from 'discord-akairo'; +import { Collection, CommandInteraction, GuildMember, Interaction } from 'discord.js'; import { BushClient } from './BushClient'; import { BushCommand } from './BushCommand'; +import { BushMessage } from './BushMessage'; -export interface BushCommandHandlerOptions extends CommandHandlerOptions {} +export const ArgumentMatches = { + PHRASE: 'phrase', + FLAG: 'flag', + OPTION: 'option', + REST: 'rest', + SEPARATE: 'separate', + TEXT: 'text', + CONTENT: 'content', + REST_CONTENT: 'restContent', + NONE: 'none' +}; +export const ArgumentTypes = { + STRING: 'string', + LOWERCASE: 'lowercase', + UPPERCASE: 'uppercase', + CHAR_CODES: 'charCodes', + NUMBER: 'number', + INTEGER: 'integer', + BIGINT: 'bigint', + EMOJINT: 'emojint', + URL: 'url', + DATE: 'date', + COLOR: 'color', + USER: 'user', + USERS: 'users', + MEMBER: 'member', + MEMBERS: 'members', + RELEVANT: 'relevant', + RELEVANTS: 'relevants', + CHANNEL: 'channel', + CHANNELS: 'channels', + TEXT_CHANNEL: 'textChannel', + TEXT_CHANNELS: 'textChannels', + VOICE_CHANNEL: 'voiceChannel', + VOICE_CHANNELS: 'voiceChannels', + CATEGORY_CHANNEL: 'categoryChannel', + CATEGORY_CHANNELS: 'categoryChannels', + NEWS_CHANNEL: 'newsChannel', + NEWS_CHANNELS: 'newsChannels', + STORE_CHANNEL: 'storeChannel', + STORE_CHANNELS: 'storeChannels', + ROLE: 'role', + ROLES: 'roles', + EMOJI: 'emoji', + EMOJIS: 'emojis', + GUILD: 'guild', + GUILDS: 'guilds', + MESSAGE: 'message', + GUILD_MESSAGE: 'guildMessage', + RELEVANT_MESSAGE: 'relevantMessage', + INVITE: 'invite', + MEMBER_MENTION: 'memberMention', + CHANNEL_MENTION: 'channelMention', + ROLE_MENTION: 'roleMention', + EMOJI_MENTION: 'emojiMention', + COMMAND_ALIAS: 'commandAlias', + COMMAND: 'command', + INHIBITOR: 'inhibitor', + LISTENER: 'listener' +}; + +export const blockedReasons = { + DM: 'dm', + BOT: 'bot', + GUILD: 'guild', + OWNER: 'owner', + CLIENT: 'client', + DISABLED: 'disabled', + SUPERUSER: 'superuser', + ROLE_BLACKLIST: 'roleBlacklist', + USER_BLACKLIST: 'userBlacklist', + RESTRICTED_GUILD: 'restrictedGuild', + CHANNEL_BLACKLIST: 'channelBlacklist', + RESTRICTED_CHANNEL: 'restrictedChannel' +}; + +export const CommandHandlerEvents = { + MESSAGE_BLOCKED: 'messageBlocked', + MESSAGE_INVALID: 'messageInvalid', + COMMAND_BLOCKED: 'commandBlocked', + COMMAND_STARTED: 'commandStarted', + COMMAND_FINISHED: 'commandFinished', + COMMAND_CANCELLED: 'commandCancelled', + COMMAND_LOCKED: 'commandLocked', + COMMAND_INVALID: 'commandInvalid', + COMMAND_LOCKED_NSFW: 'commandLockedNsfw', + MISSING_PERMISSIONS: 'missingPermissions', + COOLDOWN: 'cooldown', + IN_PROMPT: 'inPrompt', + ERROR: 'error', + SLASH_COMMAND_BLOCKED: 'slashCommandBlocked' +}; + +// A large amount of this code is copied from Akairo so that I can add custom checks to it. export class BushCommandHandler extends CommandHandler { - public constructor(client: BushClient, options: BushCommandHandlerOptions) { + public declare client: BushClient; + public declare modules: Collection<string, BushCommand>; + public declare categories: Collection<string, Category<string, BushCommand>>; + public constructor(client: BushClient, options: CommandHandlerOptions) { super(client, options); this.client = client; } - declare modules: Collection<string, BushCommand>; + async handleSlash(interaction: Interaction): Promise<boolean> { + if (!interaction.isCommand()) return false; + + if (await this.runAllTypeInhibitors(interaction)) { + return false; + } + + if (!interaction.guildID) { + this.emit('slashGuildOnly', interaction); + return false; + } + const command = this.findCommand(interaction.commandName) as BushCommand; + const before = command.before(interaction); + if (Util.isPromise(before)) await before; + + if (!command) { + this.emit('slashNotFound', interaction); + return false; + } + + if (command.ownerOnly && !this.client.isOwner(interaction.user)) { + this.emit('slashBlocked', interaction, command, 'owner'); + return false; + } + if (command.superUserOnly && !this.client.isSuperUser(interaction.user)) { + this.emit('slashBlocked', interaction, command, 'superuser'); + return false; + } + + if (interaction.channel.type !== 'dm') { + const userPermissions = interaction.channel.permissionsFor(interaction.member as GuildMember).toArray(); + + if (command.userPermissions) { + const userMissingPermissions = + typeof command.userPermissions === 'object' + ? command.userPermissions.filter((p) => !userPermissions.includes(p)) + : ''; + if (command.userPermissions && command.userPermissions.length > 0 && userMissingPermissions.length > 0) { + this.emit('slashMissingPermissions', interaction, command, 'user', userMissingPermissions); + return false; + } + } + + const clientPermissions = interaction.channel.permissionsFor(interaction.guild.me).toArray(); + + if (command.clientPermissions) { + const clientMissingPermissions = command.clientPermissions.filter((p) => !clientPermissions.includes(p)); + if (command.clientPermissions && command.clientPermissions.length > 0 && clientMissingPermissions.length > 0) { + this.emit('slashMissingPermissions', interaction, command, 'client', clientMissingPermissions); + return false; + } + } + } + + //@ts-ignore: Typings are wrong + if (this.runCooldowns(interaction, command)) { + return true; + } + const message = new AkairoMessage(this.client, interaction, { + slash: true, + replied: this.autoDefer || command.slashEphemeral + }); + + if (this.commandUtil) { + if (this.commandUtils.has(message.id)) { + message.util = this.commandUtils.get(message.id); + } else { + message.util = new CommandUtil(this, message); + this.commandUtils.set(message.id, message.util); + } + } + + let parsed = await this.parseCommand(message); + if (!parsed.command) { + const overParsed = await this.parseCommandOverwrittenPrefixes(message); + if (overParsed.command || (parsed.prefix == null && overParsed.prefix != null)) { + parsed = overParsed; + } + } + + if (this.commandUtil) { + message.util.parsed = parsed; + } + + try { + if (this.autoDefer || command.slashEphemeral) { + await interaction.defer(command.slashEphemeral); + } + const convertedOptions = {}; + for (const option of interaction.options.values()) { + if (option.member) convertedOptions[option.name] = option.member; + else if (option.channel) convertedOptions[option.name] = option.channel; + else if (option.role) convertedOptions[option.name] = option.role; + else convertedOptions[option.name] = option.value; + } + this.emit('slashStarted', interaction, command); + + if (command.execSlash || this.execSlash) await command.execSlash(message, convertedOptions); + else await command.exec(message, convertedOptions); + + return true; + } catch (err) { + this.emit('slashError', err, message, command); + return false; + } + } + public async runPostTypeInhibitors(message: BushMessage, command: BushCommand): Promise<boolean> { + if (command.ownerOnly && !message.client.isOwner(message.author)) { + super.emit(CommandHandlerEvents.COMMAND_BLOCKED, message, command, blockedReasons.OWNER); + return true; + } + if (command.superUserOnly && !(this.client.isSuperUser(message.author) || this.client.isOwner(message.author))) { + super.emit(CommandHandlerEvents.COMMAND_BLOCKED, message, command, blockedReasons.SUPERUSER); + return true; + } + if (command.channel === 'guild' && !message.guild) { + this.emit(CommandHandlerEvents.COMMAND_BLOCKED, message, command, blockedReasons.GUILD); + return true; + } + if (command.channel === 'dm' && message.guild) { + this.emit(CommandHandlerEvents.COMMAND_BLOCKED, message, command, blockedReasons.DM); + return true; + } + if (command.restrictedChannels?.length && message.channel) { + if (!command.restrictedChannels.includes(message.channel.id)) { + this.emit(CommandHandlerEvents.COMMAND_BLOCKED, message, command, blockedReasons.RESTRICTED_CHANNEL); + return true; + } + } + if (command.restrictedGuilds?.length && message.guild) { + if (!command.restrictedGuilds.includes(message.guild.id)) { + this.emit(CommandHandlerEvents.COMMAND_BLOCKED, message, command, blockedReasons.RESTRICTED_GUILD); + return true; + } + } + if (await this.runPermissionChecks(message, command)) { + return true; + } + const reason = this.inhibitorHandler ? await this.inhibitorHandler.test('post', message, command) : null; + if (reason != null) { + this.emit(CommandHandlerEvents.COMMAND_BLOCKED, message, command, reason); + return true; + } + if (this.runCooldowns(message, command)) { + return true; + } + return false; + } + public async runCommand(message: BushMessage, command: BushCommand, args: unknown): Promise<void> { + if (command.typing) { + message.channel.startTyping(); + } + try { + this.emit(CommandHandlerEvents.COMMAND_STARTED, message, command, args); + const ret = await command.exec(message, args); + this.emit(CommandHandlerEvents.COMMAND_FINISHED, message, command, args, ret); + } finally { + if (command.typing) { + message.channel.stopTyping(); + } + } + } + public runAllTypeInhibitors(message: BushMessage): any; + public runAllTypeInhibitors(message: BushMessage | CommandInteraction): any; + public runAllTypeInhibitors(message): any { + super.runAllTypeInhibitors(message); + } } diff --git a/src/lib/extensions/BushInhibitor.ts b/src/lib/extensions/BushInhibitor.ts index d9a9b68..85d6de8 100644 --- a/src/lib/extensions/BushInhibitor.ts +++ b/src/lib/extensions/BushInhibitor.ts @@ -2,5 +2,5 @@ import { Inhibitor } from 'discord-akairo'; import { BushClient } from './BushClient'; export class BushInhibitor extends Inhibitor { - public client: BushClient; + public declare client: BushClient; } diff --git a/src/lib/extensions/BushInhinitorHandler.ts b/src/lib/extensions/BushInhinitorHandler.ts new file mode 100644 index 0000000..2a947da --- /dev/null +++ b/src/lib/extensions/BushInhinitorHandler.ts @@ -0,0 +1,6 @@ +import { InhibitorHandler } from 'discord-akairo'; +import { BushClient } from './BushClient'; + +export class BushInhibitorHandler extends InhibitorHandler { + public declare client: BushClient; +} diff --git a/src/lib/extensions/BushListener.ts b/src/lib/extensions/BushListener.ts index 6a13210..e555e89 100644 --- a/src/lib/extensions/BushListener.ts +++ b/src/lib/extensions/BushListener.ts @@ -2,5 +2,5 @@ import { Listener } from 'discord-akairo'; import { BushClient } from './BushClient'; export class BushListener extends Listener { - public client: BushClient; + public declare client: BushClient; } diff --git a/src/lib/extensions/BushTask.ts b/src/lib/extensions/BushTask.ts index 21655e9..06d0602 100644 --- a/src/lib/extensions/BushTask.ts +++ b/src/lib/extensions/BushTask.ts @@ -2,5 +2,5 @@ import { Task } from 'discord-akairo'; import { BushClient } from './BushClient'; export class BushTask extends Task { - public client: BushClient; + public declare client: BushClient; } diff --git a/src/lib/extensions/BushTaskHandler.ts b/src/lib/extensions/BushTaskHandler.ts index f783eb3..c76dbfb 100644 --- a/src/lib/extensions/BushTaskHandler.ts +++ b/src/lib/extensions/BushTaskHandler.ts @@ -1,6 +1,7 @@ import { AkairoHandlerOptions, TaskHandler } from 'discord-akairo'; import { BushClient } from './BushClient'; +// eslint-disable-next-line @typescript-eslint/no-empty-interface export interface BushTaskHandlerOptions extends AkairoHandlerOptions {} export class BushTaskHandler extends TaskHandler { diff --git a/src/lib/extensions/Util.ts b/src/lib/extensions/Util.ts deleted file mode 100644 index 3913437..0000000 --- a/src/lib/extensions/Util.ts +++ /dev/null @@ -1,598 +0,0 @@ -import chalk from 'chalk'; -import { exec } from 'child_process'; -import { ClientUtil, Command } from 'discord-akairo'; -import { - APIInteractionDataResolvedChannel, - APIInteractionDataResolvedGuildMember, - APIRole, - ApplicationCommandOptionType -} from 'discord-api-types'; -import { - ButtonInteraction, - CommandInteractionOption, - Constants, - Guild, - GuildChannel, - GuildMember, - MessageActionRow, - MessageButton, - MessageComponentInteraction, - MessageEmbed, - MessageOptions, - Role, - Snowflake, - User, - Util -} from 'discord.js'; -import got from 'got'; -import { promisify } from 'util'; -import { BushClient } from './BushClient'; -import { BushMessage } from './BushMessage'; - -interface hastebinRes { - key: string; -} - -export interface uuidRes { - uuid: string; - username: string; - username_history?: { username: string }[] | null; - textures: { - custom: boolean; - slim: boolean; - skin: { - url: string; - data: string; - }; - raw: { - value: string; - signature: string; - }; - }; - created_at: string; -} - -export interface SlashCommandOption<T> { - name: string; - type: ApplicationCommandOptionType; - value?: T; - options?: CommandInteractionOption[]; - user?: User; - member?: GuildMember | APIInteractionDataResolvedGuildMember; - channel?: GuildChannel | APIInteractionDataResolvedChannel; - role?: Role | APIRole; -} - -export class BushUtil extends ClientUtil { - /** - * The client of this ClientUtil - * @type {BushClient} - */ - public client: BushClient; - /** - * The hastebin urls used to post to hastebin, attempts to post in order - * @type {string[]} - */ - public hasteURLs = [ - 'https://hst.sh', - 'https://hasteb.in', - 'https://hastebin.com', - 'https://mystb.in', - 'https://haste.clicksminuteper.net', - 'https://paste.pythondiscord.com', - 'https://haste.unbelievaboat.com', - 'https://haste.tyman.tech' - ]; - /** - * A simple promise exec method - */ - private exec = promisify(exec); - - /** - * Creates this client util - * @param client The client to initialize with - */ - constructor(client: BushClient) { - super(client); - } - - /** - * Maps an array of user ids to user objects. - * @param ids The list of IDs to map - * @returns The list of users mapped - */ - public async mapIDs(ids: Snowflake[]): Promise<User[]> { - return await Promise.all(ids.map((id) => this.client.users.fetch(id))); - } - - /** - * Capitalizes the first letter of the given text - * @param text The text to capitalize - * @returns The capitalized text - */ - public capitalize(text: string): string { - return text.charAt(0).toUpperCase() + text.slice(1); - } - - /** - * Runs a shell command and gives the output - * @param command The shell command to run - * @returns The stdout and stderr of the shell command - */ - public async shell(command: string): Promise<{ - stdout: string; - stderr: string; - }> { - return await this.exec(command); - } - - /** - * Posts text to hastebin - * @param content The text to post - * @returns The url of the posted text - */ - public async haste(content: string): Promise<string> { - for (const url of this.hasteURLs) { - try { - const res: hastebinRes = await got.post(`${url}/documents`, { body: content }).json(); - return `${url}/${res.key}`; - } catch (e) { - // pass - } - } - throw new Error('No urls worked. (wtf)'); - } - - /** - * Resolves a user-provided string into a user object, if possible - * @param text The text to try and resolve - * @returns The user resolved or null - */ - public async resolveUserAsync(text: string): Promise<User | null> { - const idReg = /\d{17,19}/; - const idMatch = text.match(idReg); - if (idMatch) { - try { - const user = await this.client.users.fetch(text as Snowflake); - return user; - } catch { - // pass - } - } - const mentionReg = /<@!?(?<id>\d{17,19})>/; - const mentionMatch = text.match(mentionReg); - if (mentionMatch) { - try { - const user = await this.client.users.fetch(mentionMatch.groups.id as Snowflake); - return user; - } catch { - // pass - } - } - const user = this.client.users.cache.find((u) => u.username === text); - if (user) return user; - return null; - } - - /** - * Appends the correct ordinal to the given number - * @param n The number to append an ordinal to - * @returns The number with the ordinal - */ - public ordinal(n: number): string { - const s = ['th', 'st', 'nd', 'rd'], - v = n % 100; - return n + (s[(v - 20) % 10] || s[v] || s[0]); - } - - /** - * Chunks an array to the specified size - * @param arr The array to chunk - * @param perChunk The amount of items per chunk - * @returns The chunked array - */ - public chunk<T>(arr: T[], perChunk: number): T[][] { - return arr.reduce((all, one, i) => { - const ch = Math.floor(i / perChunk); - all[ch] = [].concat(all[ch] || [], one); - return all; - }, []); - } - - /** - * The colors used throught the bot - */ - public colors = { - default: '#1FD8F1', - error: '#EF4947', - warn: '#FEBA12', - success: '#3BB681', - red: '#ff0000', - orange: '#E86100', - gold: '#b59400', - yellow: '#ffff00', - green: '#00ff1e', - darkGreen: '#008f11', - aqua: '#00bbff', - blue: '#0055ff', - blurple: '#5440cd', - purple: '#8400ff', - pink: '#ff00e6', - white: '#ffffff', - gray: '#a6a6a6', - lightGray: '#cfcfcf', - darkGray: '#7a7a7a', - black: '#000000' - }; - - public emojis = { - success: '<:checkmark:837109864101707807>', - warn: '<:warn:848726900876247050> ', - error: '<:error:837123021016924261>', - successFull: '<:checkmark_full:850118767576088646>', - warnFull: '<:warn_full:850118767391539312>', - errorFull: '<:error_full:850118767295201350>', - mad: '<:mad:783046135392239626>', - join: '<:join:850198029809614858>', - leave: '<:leave:850198048205307919>' - }; - - /** - * A simple utility to create and embed with the needed style for the bot - */ - public createEmbed(color?: string, author?: User | GuildMember): MessageEmbed { - if (author instanceof GuildMember) { - author = author.user; // Convert to User if GuildMember - } - let embed = new MessageEmbed().setTimestamp(); - if (author) - embed = embed.setAuthor( - author.username, - author.displayAvatarURL({ dynamic: true }), - `https://discord.com/users/${author.id}` - ); - if (color) embed = embed.setColor(color); - return embed; - } - - public async mcUUID(username: string): Promise<string> { - const apiRes = (await got.get(`https://api.ashcon.app/mojang/v2/user/${username}`).json()) as uuidRes; - return apiRes.uuid.replace(/-/g, ''); - } - - public async syncSlashCommands(force = false, guild?: Snowflake): Promise<void> { - let fetchedGuild: Guild; - if (guild) fetchedGuild = this.client.guilds.cache.get(guild); - try { - const registered = - guild === undefined ? await this.client.application.commands.fetch() : await fetchedGuild.commands.fetch(); - for (const [, registeredCommand] of registered) { - if (!this.client.commandHandler.modules.find((cmd) => cmd.id == registeredCommand.name)?.execSlash || force) { - guild === undefined - ? await this.client.application.commands.delete(registeredCommand.id) - : await fetchedGuild.commands.delete(registeredCommand.id); - this.client.logger.verbose( - chalk`{red Deleted slash command ${registeredCommand.name}${ - guild !== undefined ? ` in guild ${fetchedGuild.name}` : '' - }}` - ); - } - } - - for (const [, botCommand] of this.client.commandHandler.modules) { - if (botCommand.execSlash) { - const found = registered.find((i) => i.name == botCommand.id); - Command; - const slashdata = { - name: botCommand.id, - description: botCommand.description.content, - options: botCommand.options.slashCommandOptions - }; - botCommand; - - if (found?.id && !force) { - if (slashdata.description !== found.description) { - guild === undefined - ? await this.client.application.commands.edit(found.id, slashdata) - : fetchedGuild.commands.edit(found.id, slashdata); - this.client.logger.verbose( - chalk`{yellow Edited slash command ${botCommand.id}${ - guild !== undefined ? ` in guild ${fetchedGuild.name}` : '' - }}` - ); - } - } else { - guild === undefined - ? await this.client.application.commands.create(slashdata) - : fetchedGuild.commands.create(slashdata); - this.client.logger.verbose( - chalk`{green Created slash command ${botCommand.id}${ - guild !== undefined ? ` in guild ${fetchedGuild.name}` : '' - }}` - ); - } - } - } - - return this.client.logger.log( - chalk.green(`Slash commands registered${guild !== undefined ? ` in guild ${fetchedGuild.name}` : ''}`) - ); - } catch (e) { - console.log(chalk.red(e.stack)); - return this.client.logger.error( - chalk`{red Slash commands not registered${ - guild !== undefined ? ` in guild ${fetchedGuild.name}` : '' - }, see above error.}` - ); - } - } - - public moulberryBushRoleMap = [ - { name: '*', id: '792453550768390194' }, - { name: 'Admin Perms', id: '746541309853958186' }, - { name: 'Sr. Moderator', id: '782803470205190164' }, - { name: 'Moderator', id: '737308259823910992' }, - { name: 'Helper', id: '737440116230062091' }, - { name: 'Trial Helper', id: '783537091946479636' }, - { name: 'Contributor', id: '694431057532944425' }, - { name: 'Giveaway Donor', id: '784212110263451649' }, - { name: 'Giveaway (200m)', id: '810267756426690601' }, - { name: 'Giveaway (100m)', id: '801444430522613802' }, - { name: 'Giveaway (50m)', id: '787497512981757982' }, - { name: 'Giveaway (25m)', id: '787497515771232267' }, - { name: 'Giveaway (10m)', id: '787497518241153025' }, - { name: 'Giveaway (5m)', id: '787497519768403989' }, - { name: 'Giveaway (1m)', id: '787497521084891166' }, - { name: 'Suggester', id: '811922322767609877' }, - { name: 'Partner', id: '767324547312779274' }, - { name: 'Level Locked', id: '784248899044769792' }, - { name: 'No Files', id: '786421005039173633' }, - { name: 'No Reactions', id: '786421270924361789' }, - { name: 'No Links', id: '786421269356740658' }, - { name: 'No Bots', id: '786804858765312030' }, - { name: 'No VC', id: '788850482554208267' }, - { name: 'No Giveaways', id: '808265422334984203' }, - { name: 'No Support', id: '790247359824396319' } - ]; - - private paginateEmojis = { - begging: '853667381335162910', - back: '853667410203770881', - stop: '853667471110570034', - forward: '853667492680564747', - end: '853667514915225640' - }; - - public async buttonPaginate( - message: BushMessage, - embeds: MessageEmbed[], - text: string | null = null, - deleteOnExit?: boolean - ): Promise<void> { - if (deleteOnExit === undefined) deleteOnExit = true; - embeds.forEach((_e, i) => { - embeds[i] = embeds[i].setFooter(`Page ${i + 1}/${embeds.length}`); - }); - - const style = Constants.MessageButtonStyles.PRIMARY; - let curPage = 0; - if (typeof embeds !== 'object') throw 'embeds must be an object'; - const msg = await message.util.reply({ content: text, embeds: [embeds[curPage]], components: [getPaginationRow()] }); - const filter = (interaction: ButtonInteraction) => - interaction.customID.startsWith('paginate_') && interaction.message == msg; - const collector = msg.createMessageComponentInteractionCollector(filter, { time: 300000 }); - collector.on('collect', async (interaction: MessageComponentInteraction) => { - if (interaction.user.id == message.author.id || message.client.config.owners.includes(interaction.user.id)) { - switch (interaction.customID) { - case 'paginate_beginning': { - curPage = 0; - await edit(interaction); - break; - } - case 'paginate_back': { - curPage--; - await edit(interaction); - break; - } - case 'paginate_stop': { - if (deleteOnExit) { - await interaction.deferUpdate(); - await msg.delete(); - } else { - await interaction?.update({ - content: `${text ? text + '\n' : ''}Command closed by user.`, - embeds: [], - components: [] - }); - } - return; - } - case 'paginate_next': { - curPage++; - await edit(interaction); - break; - } - case 'paginate_end': { - curPage = embeds.length - 1; - await edit(interaction); - break; - } - } - } else { - return await interaction?.deferUpdate(); - } - }); - - collector.on('end', async () => { - await msg.edit({ content: text, embeds: [embeds[curPage]], components: [getPaginationRow(true)] }).catch(() => {}); - }); - - async function edit(interaction: MessageComponentInteraction): Promise<void> { - return await interaction?.update({ content: text, embeds: [embeds[curPage]], components: [getPaginationRow()] }); - } - function getPaginationRow(disableAll = false): MessageActionRow { - return new MessageActionRow().addComponents( - new MessageButton({ - style, - customID: 'paginate_beginning', - emoji: this.paginateEmojis.begging, - disabled: disableAll || curPage == 0 - }), - new MessageButton({ - style, - customID: 'paginate_back', - emoji: this.paginateEmojis.back, - disabled: disableAll || curPage == 0 - }), - new MessageButton({ style, customID: 'paginate_stop', emoji: this.paginateEmojis.stop, disabled: disableAll }), - new MessageButton({ - style, - customID: 'paginate_next', - emoji: this.paginateEmojis.forward, - disabled: disableAll || curPage == embeds.length - 1 - }), - new MessageButton({ - style, - customID: 'paginate_end', - emoji: this.paginateEmojis.end, - disabled: disableAll || curPage == embeds.length - 1 - }) - ); - } - } - - public async sendWithDeleteButton(message: BushMessage, options: MessageOptions): Promise<void> { - updateOptions(); - const msg = await message.util.reply(options as MessageOptions & { split?: false }); - const filter = (interaction: ButtonInteraction) => interaction.customID == 'paginate__stop' && interaction.message == msg; - const collector = msg.createMessageComponentInteractionCollector(filter, { time: 300000 }); - collector.on('collect', async (interaction: MessageComponentInteraction) => { - if (interaction.user.id == message.author.id || message.client.config.owners.includes(interaction.user.id)) { - await interaction.deferUpdate(); - await msg.delete(); - return; - } else { - return await interaction?.deferUpdate(); - } - }); - - collector.on('end', async () => { - updateOptions(true, true); - await msg.edit(options); - }); - - function updateOptions(edit?: boolean, disable?: boolean) { - if (edit == undefined) edit = false; - if (disable == undefined) disable = false; - options.components = [ - new MessageActionRow().addComponents( - new MessageButton({ - style: Constants.MessageButtonStyles.PRIMARY, - customID: 'paginate__stop', - emoji: this.paginateEmojis.stop, - disabled: disable - }) - ) - ]; - if (edit) { - options.reply = undefined; - } - } - } - /** - * Surrounds text in a code block with the specified language and puts it in a haste bin if it too long. - * - * * Embed Description Limit = 2048 characters - * * Embed Field Limit = 1024 characters - */ - public async codeblock(code: string, length: number, language: 'ts' | 'js' | 'sh' | 'json' | '' = ''): Promise<string> { - let hasteOut = ''; - const tildes = '```'; - const formattingLength = 2 * tildes.length + language.length + 2 * '\n'.length; - if (code.length + formattingLength > length) hasteOut = 'Too large to display. Hastebin: ' + (await this.haste(code)); - - const code2 = code.length > length ? code.substring(0, length - (hasteOut.length + '\n'.length + formattingLength)) : code; - return ( - tildes + language + '\n' + Util.cleanCodeBlockContent(code2) + '\n' + tildes + (hasteOut.length ? '\n' + hasteOut : '') - ); - } -} - -// I just copy pasted this code from stackoverflow don't yell at me if there is issues for it -export class CanvasProgressBar { - private x: number; - private y: number; - private w: number; - private h: number; - private color: string; - private percentage: number; - private p: number; - private ctx: CanvasRenderingContext2D; - - constructor( - ctx: CanvasRenderingContext2D, - dimension: { x: number; y: number; width: number; height: number }, - color: string, - percentage: number - ) { - ({ x: this.x, y: this.y, width: this.w, height: this.h } = dimension); - this.color = color; - this.percentage = percentage; - this.p; - this.ctx = ctx; - } - - draw() { - // ----------------- - this.p = this.percentage * this.w; - if (this.p <= this.h) { - this.ctx.beginPath(); - this.ctx.arc( - this.h / 2 + this.x, - this.h / 2 + this.y, - this.h / 2, - Math.PI - Math.acos((this.h - this.p) / this.h), - Math.PI + Math.acos((this.h - this.p) / this.h) - ); - this.ctx.save(); - this.ctx.scale(-1, 1); - this.ctx.arc( - this.h / 2 - this.p - this.x, - this.h / 2 + this.y, - this.h / 2, - Math.PI - Math.acos((this.h - this.p) / this.h), - Math.PI + Math.acos((this.h - this.p) / this.h) - ); - this.ctx.restore(); - this.ctx.closePath(); - } else { - this.ctx.beginPath(); - this.ctx.arc(this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, Math.PI / 2, (3 / 2) * Math.PI); - this.ctx.lineTo(this.p - this.h + this.x, 0 + this.y); - this.ctx.arc(this.p - this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, (3 / 2) * Math.PI, Math.PI / 2); - this.ctx.lineTo(this.h / 2 + this.x, this.h + this.y); - this.ctx.closePath(); - } - this.ctx.fillStyle = this.color; - this.ctx.fill(); - } - - // showWholeProgressBar(){ - // this.ctx.beginPath(); - // this.ctx.arc(this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, Math.PI / 2, 3 / 2 * Math.PI); - // this.ctx.lineTo(this.w - this.h + this.x, 0 + this.y); - // this.ctx.arc(this.w - this.h / 2 + this.x, this.h / 2 + this.y, this.h / 2, 3 / 2 *Math.PI, Math.PI / 2); - // this.ctx.lineTo(this.h / 2 + this.x, this.h + this.y); - // this.ctx.strokeStyle = '#000000'; - // this.ctx.stroke(); - // this.ctx.closePath(); - // } - - get PPercentage() { - return this.percentage * 100; - } - - set PPercentage(x) { - this.percentage = x / 100; - } -} diff --git a/src/lib/utils/BushCache.ts b/src/lib/utils/BushCache.ts new file mode 100644 index 0000000..915fcb1 --- /dev/null +++ b/src/lib/utils/BushCache.ts @@ -0,0 +1,5 @@ +import { Snowflake } from 'discord.js'; + +export class BushCache { + public static superUsers = new Array<Snowflake>(); +} diff --git a/src/lib/utils/BushLogger.ts b/src/lib/utils/BushLogger.ts new file mode 100644 index 0000000..d48ec07 --- /dev/null +++ b/src/lib/utils/BushLogger.ts @@ -0,0 +1,191 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +import chalk from 'chalk'; +import { MessageEmbed } from 'discord.js'; +import { inspect } from 'util'; +import { BushClient, BushMessageType } from '../extensions/BushClient'; + +export class BushLogger { + private client: BushClient; + public constructor(client: BushClient) { + this.client = client; + } + + private parseFormatting( + content: any, + color: 'blueBright' | 'blackBright' | 'redBright' | 'yellowBright' | 'greenBright' | '', + discordFormat = false + ): string | typeof content { + if (typeof content !== 'string') return content; + const newContent: Array<string> = content.split(/<<|>>/); + const tempParsedArray: Array<string> = []; + newContent.forEach((value, index) => { + if (index % 2 !== 0) { + tempParsedArray.push(discordFormat ? `**${value}**` : chalk[color](value)); + } else { + tempParsedArray.push(value); + } + }); + return tempParsedArray.join(''); + } + + private inspectContent(content: any, depth = 2): string { + if (typeof content !== 'string') { + return inspect(content, { depth }); + } + return content; + } + + private stripColor(text: string): string { + return text.replace( + // eslint-disable-next-line no-control-regex + /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, + '' + ); + } + + private getTimeStamp(): string { + const now = new Date(); + const hours = now.getHours(); + const minute = now.getMinutes(); + let hour = hours; + let amOrPm: 'AM' | 'PM' = 'AM'; + if (hour > 12) { + amOrPm = 'PM'; + hour = hour - 12; + } + return `${hour >= 10 ? hour : `0${hour}`}:${minute >= 10 ? minute : `0${minute}`} ${amOrPm}`; + } + + /** + * Logs information. Highlight information by surrounding it in `<<>>`. + * @param header - The header displayed before the content, displayed in cyan. + * @param content - The content to log, highlights displayed in bright blue. + * @param sendChannel - Should this also be logged to discord? Defaults to true. + */ + public get log() { + return this.info; + } + + /** Sends a message to the log channel */ + public async channelLog(message: BushMessageType): Promise<void> { + const channel = await this.client.util.getConfigChannel('log'); + await channel.send(message).catch(() => {}); + } + + /** Sends a message to the error channel */ + public async channelError(message: BushMessageType): Promise<void> { + const channel = await this.client.util.getConfigChannel('error'); + await channel.send(message).catch(() => {}); + } + + /** + * Logs debug information. Only works in dev is enabled in the config. + * @param content - The content to log. + */ + public debug(...content: any): void { + if (!this.client.config.dev) return; + console.log(`${chalk.bgGrey(this.getTimeStamp())} ${chalk.grey('[Debug]')}`, ...content); + } + + /** + * Logs verbose information. Highlight information by surrounding it in `<<>>`. + * @param header - The header printed before the content, displayed in grey. + * @param content - The content to log, highlights displayed in bright black. + * @param sendChannel = false - Should this also be logged to discord? Defaults to false. + */ + public async verbose(header: string, content: any, sendChannel = false): Promise<void> { + if (!this.client.config.logging.verbose) return; + const newContent = this.inspectContent(content); + console.info( + `${chalk.bgGrey(this.getTimeStamp())} ${chalk.grey(`[${header}]`)} ` + this.parseFormatting(newContent, 'blackBright') + ); + if (!sendChannel) return; + const embed = new MessageEmbed() + .setDescription(`**[${header}]** ${this.stripColor(newContent)}`) + .setColor(this.client.util.colors.gray) + .setTimestamp(); + this.channelLog({ embeds: [embed] }); + } + + /** + * Logs information. Highlight information by surrounding it in `<<>>`. + * @param header - The header displayed before the content, displayed in cyan. + * @param content - The content to log, highlights displayed in bright blue. + * @param sendChannel - Should this also be logged to discord? Defaults to true. + */ + public async info(header: string, content: any, sendChannel = true): Promise<void> { + if (!this.client.config.logging.info) return; + const newContent = this.inspectContent(content); + console.info( + `${chalk.bgCyan(this.getTimeStamp())} ${chalk.cyan(`[${header}]`)} ` + this.parseFormatting(newContent, 'blueBright') + ); + if (!sendChannel) return; + const embed = new MessageEmbed() + .setDescription(`**[${header}]** ${this.parseFormatting(this.stripColor(newContent), '', true)}`) + .setColor(this.client.util.colors.info) + .setTimestamp(); + this.channelLog({ embeds: [embed] }); + } + + /** + * Logs warnings. Highlight information by surrounding it in `<<>>`. + * @param header - The header displayed before the content, displayed in yellow. + * @param content - The content to log, highlights displayed in bright yellow. + * @param sendChannel - Should this also be logged to discord? Defaults to true. + */ + public async warn(header: string, content: any, sendChannel = true): Promise<void> { + const newContent = this.inspectContent(content); + console.warn( + `${chalk.bgYellow(this.getTimeStamp())} ${chalk.yellow(`[${header}]`)} ` + + this.parseFormatting(newContent, 'yellowBright') + ); + + if (!sendChannel) return; + const embed = new MessageEmbed() + .setDescription(`**[${header}]** ${this.parseFormatting(this.stripColor(newContent), '', true)}`) + .setColor(this.client.util.colors.warn) + .setTimestamp(); + this.channelLog({ embeds: [embed] }); + } + + /** + * Logs errors. Highlight information by surrounding it in `<<>>`. + * @param header - The header displayed before the content, displayed in bright red. + * @param content - The content to log, highlights displayed in bright red. + * @param sendChannel - Should this also be logged to discord? Defaults to true. + */ + public async error(header: string, content: any, sendChannel = true): Promise<void> { + const newContent = this.inspectContent(content); + console.error( + `${chalk.bgRedBright(this.getTimeStamp())} ${chalk.redBright(`[${header}]`)} ` + + this.parseFormatting(newContent, 'redBright') + ); + if (!sendChannel) return; + const embed = new MessageEmbed() + .setDescription(`**[${header}]** ${this.stripColor(newContent)}`) + .setColor(this.client.util.colors.error) + .setTimestamp(); + this.channelError({ embeds: [embed] }); + } + + /** + * Logs successes. Highlight information by surrounding it in `<<>>`. + * @param header - The header displayed before the content, displayed in green. + * @param content - The content to log, highlights displayed in bright green. + * @param sendChannel - Should this also be logged to discord? Defaults to true. + */ + public async success(header: string, content: any, sendChannel = true): Promise<void> { + const newContent = this.inspectContent(content); + console.log( + `${chalk.bgGreen(this.getTimeStamp())} ${chalk.greenBright(`[${header}]`)} ` + + this.parseFormatting(newContent, 'greenBright') + ); + if (!sendChannel) return; + const embed = new MessageEmbed() + .setDescription(`**[${header}]** ${this.stripColor(newContent)}`) + .setColor(this.client.util.colors.success) + .setTimestamp(); + await this.channelLog({ embeds: [embed] }).catch(() => {}); + } +} diff --git a/src/lib/utils/Console.ts b/src/lib/utils/Console.ts deleted file mode 100644 index a3bf326..0000000 --- a/src/lib/utils/Console.ts +++ /dev/null @@ -1,115 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import chalk from 'chalk'; -import { BushClient } from '../extensions/BushClient'; - -export class Log { - client: BushClient; - - public constructor(client: BushClient) { - this.client = client; - } - - private parseColors( - content: any, - color: 'blueBright' | 'blackBright' | 'redBright' | 'yellowBright' | 'greenBright' - ): string | any { - if (typeof content === 'string') { - const newContent: Array<string> = content.split(/<<|>>/); - const tempParsedArray: Array<string> = []; - newContent.forEach((value, index) => { - if (index % 2 !== 0) { - tempParsedArray.push(chalk[color](value)); - } else { - tempParsedArray.push(value); - } - }); - return tempParsedArray.join(''); - } else { - return content; - } - } - - private timeStamp(): string { - const now = new Date(); - const hours = now.getHours(); - const minute = now.getMinutes(); - let hour = hours; - let amOrPm: 'AM' | 'PM' = 'AM'; - if (hour > 12) { - amOrPm = 'PM'; - hour = hour - 12; - } - - return `${hour >= 10 ? hour : `0${hour}`}:${minute >= 10 ? minute : `0${minute}`} ${amOrPm}`; - } - - /** - * Logs debug information. Only works in dev is enabled in the config. - * @param content - The content to log. - */ - public debug(...content: any): void { - if (this.client.config.dev) { - console.log(`${chalk.bgGrey(this.timeStamp())} ${chalk.grey('[Debug]')}`, ...content); - } - } - - /** - * Logs verbose information. Highlight information by surrounding it in `<<>>`. - * @param header - The header displayed before the content, displayed in grey. - * @param content - The content to log, highlights displayed in bright black. - */ - public verbose(header: string, content: any): void { - if (this.client.config.logging.verbose) { - return console.info( - `${chalk.bgGrey(this.timeStamp())} ${chalk.grey(`[${header}]`)} ` + this.parseColors(content, 'blackBright') - ); - } - } - - /** - * Logs information. Highlight information by surrounding it in `<<>>`. - * @param header - The header displayed before the content, displayed in cyan. - * @param content - The content to log, highlights displayed in bright blue. - */ - public info(header: string, content: any): void { - if (this.client.config.logging.info) { - return console.info( - `${chalk.bgCyan(this.timeStamp())} ${chalk.cyan(`[${header}]`)} ` + this.parseColors(content, 'blueBright') - ); - } - } - - /** - * Logs warnings. Highlight information by surrounding it in `<<>>`. - * @param header - The header displayed before the content, displayed in yellow. - * @param content - The content to log, highlights displayed in bright yellow. - */ - public warn(header: string, content: any): void { - return console.warn( - `${chalk.bgYellow(this.timeStamp())} ${chalk.yellow(`[${header}]`)} ` + this.parseColors(content, 'yellowBright') - ); - } - - /** - * Logs errors. Highlight information by surrounding it in `<<>>`. - * @param header - The header displayed before the content, displayed in bright red. - * @param content - The content to log, highlights displayed in bright red. - */ - public error(header: string, content: any): void { - return console.error( - `${chalk.bgRedBright(this.timeStamp())} ${chalk.redBright(`[${header}]`)} ` + this.parseColors(content, 'redBright') - ); - } - - /** - * Logs successes. Highlight information by surrounding it in `<<>>`. - * @param header - The header displayed before the content, displayed in green. - * @param content - The content to log, highlights displayed in bright green. - */ - public success(header: string, content: any): void { - return console.log( - `${chalk.bgGreen(this.timeStamp())} ${chalk.greenBright(`[${header}]`)} ` + this.parseColors(content, 'greenBright') - ); - } -} diff --git a/src/lib/utils/Logger.ts b/src/lib/utils/Logger.ts deleted file mode 100644 index 0675e3d..0000000 --- a/src/lib/utils/Logger.ts +++ /dev/null @@ -1,43 +0,0 @@ -import chalk from 'chalk'; -import { TextChannel } from 'discord.js'; -import { BushClient } from '../extensions/BushClient'; - -export class BushLogger { - private client: BushClient; - public constructor(client: BushClient) { - this.client = client; - } - private stripColor(text: string): string { - return text.replace( - // eslint-disable-next-line no-control-regex - /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, - '' - ); - } - public getChannel(channel: 'log' | 'error' | 'dm'): Promise<TextChannel> { - return this.client.channels.fetch(this.client.config.channels[channel]) as Promise<TextChannel>; - } - public async log(message: string, sendChannel = false): Promise<void> { - console.log(chalk`{bgCyan LOG} ` + message); - if (sendChannel) { - const channel = await this.getChannel('log'); - await channel.send('[LOG] ' + this.stripColor(message)); - } - } - - public async verbose(message: string, sendChannel = false): Promise<void> { - if (!this.client.config.logging.verbose) return; - console.log(chalk`{bgMagenta VERBOSE} ` + message); - if (sendChannel) { - const channel = await this.getChannel('log'); - await channel.send('[VERBOSE] ' + this.stripColor(message)); - } - } - public async error(message: string, sendChannel = false): Promise<void> { - console.log(chalk`{bgRed ERROR} ` + message); - if (sendChannel) { - const channel = await this.getChannel('error'); - await channel.send('[ERROR] ' + this.stripColor(message)); - } - } -} diff --git a/src/listeners/client/ready.ts b/src/listeners/client/ready.ts index d4b2808..a87d216 100644 --- a/src/listeners/client/ready.ts +++ b/src/listeners/client/ready.ts @@ -10,6 +10,25 @@ export default class ReadyListener extends BushListener { } public async exec(): Promise<void> { - await this.client.logger.log(chalk`{green Sucessfully logged in as {cyan ${this.client.user.tag}}.}`, true); + //@ts-expect-error: ik its private, this is the only time I need to access it outside of its class + const timeStamp = chalk.bgGreen(this.client.logger.getTimeStamp()), + tag = chalk.magenta(this.client.user.tag), + guildCount = chalk.magenta(this.client.guilds.cache.size.toLocaleString()), + userCount = chalk.magenta(this.client.users.cache.size.toLocaleString()); + + console.log(`${timeStamp} Logged in to ${tag} serving ${guildCount} guilds and ${userCount} users.`); + console.log( + chalk.blue(`----------------------------------------------------------------------${this.client.config.dev ? '---' : ''}`) + ); + + this.client.user.setPresence({ + activities: [ + { + name: 'Beep Boop', + type: 'WATCHING' + } + ], + status: 'online' + }); } } diff --git a/src/listeners/commands/commandBlocked.ts b/src/listeners/commands/commandBlocked.ts index 916f7cd..61433a6 100644 --- a/src/listeners/commands/commandBlocked.ts +++ b/src/listeners/commands/commandBlocked.ts @@ -1,6 +1,6 @@ -import { BushListener } from '../../lib/extensions/BushListener'; import { Command } from 'discord-akairo'; import { Message } from 'discord.js'; +import { BushListener } from '../../lib/extensions/BushListener'; export default class CommandBlockedListener extends BushListener { public constructor() { @@ -11,6 +11,12 @@ export default class CommandBlockedListener extends BushListener { } public async exec(message: Message, command: Command, reason: string): Promise<void> { + this.client.console.info( + 'CommandBlocked', + `<<${message.author.tag}>> tried to run <<${message.util.parsed.command}>> but was blocked because <<${reason}>>.`, + false + ); + switch (reason) { case 'owner': { await message.util.send(`You must be an owner to run command \`${message.util.parsed.command}\``); diff --git a/src/listeners/commands/commandError.ts b/src/listeners/commands/commandError.ts index 06aa55f..cb8c5d2 100644 --- a/src/listeners/commands/commandError.ts +++ b/src/listeners/commands/commandError.ts @@ -1,40 +1,65 @@ import { stripIndents } from 'common-tags'; -import { Message, MessageEmbed, TextChannel } from 'discord.js'; -import { BushCommand } from '../../lib/extensions/BushCommand'; +import { Command } from 'discord-akairo'; +import { MessageEmbed } from 'discord.js'; import { BushListener } from '../../lib/extensions/BushListener'; +import { BushMessage } from '../../lib/extensions/BushMessage'; export default class CommandErrorListener extends BushListener { - constructor() { - super('error', { + public constructor() { + super('commandError', { emitter: 'commandHandler', event: 'error' }); } - async exec(error: Error, message: Message, command?: BushCommand): Promise<void> { - const errorNumber = Math.floor(Math.random() * 6969696969) + 69; // hehe funy numbers - const errorDevEmbed = this.client.util - .createEmbed(this.client.util.colors.error) - .setTitle(`Error # \`${errorNumber}\`: An error occurred`) + + public async exec(error: Error, message: BushMessage, command: Command | null | undefined): Promise<void> { + const errorNo = Math.floor(Math.random() * 6969696969) + 69; // hehe funny number + const errorEmbed: MessageEmbed = new MessageEmbed() + .setTitle(`Error # \`${errorNo}\`: An error occurred`) .setDescription( stripIndents`**User:** ${message.author} (${message.author.tag}) **Command:** ${command} **Channel:** ${message.channel} (${message.channel.id}) **Message:** [link](${message.url})` ) - .addField('Error', `${await this.client.util.haste(error.stack)}`); - let errorUserEmbed: MessageEmbed; - if (command) { - errorUserEmbed = this.client.util - .createEmbed(this.client.util.colors.error) - .setTitle('An error occurred') - .setDescription( - stripIndents`Whoops! It appears like something broke. - The developers have been notified of this. If you contact them, give them code \`${errorNumber}\`. - ` - ); + .addField('Error', await this.client.util.codeblock(`${error?.stack}`, 1024, 'js')) + .setColor(this.client.util.colors.error) + .setTimestamp(); + + if (message) { + if (!this.client.config.owners.includes(message.author.id)) { + const errorUserEmbed: MessageEmbed = new MessageEmbed() + .setTitle('An error occurred') + .setColor(this.client.util.colors.error) + .setTimestamp(); + await this.client.logger.channelError({ embeds: [errorEmbed] }); + if (!command) + errorUserEmbed.setDescription(`Oh no! An error occurred. Please give the developers code \`${errorNo}\`.`); + else + errorUserEmbed.setDescription( + `Oh no! While running the command \`${command.id}\`, an error occurred. Please give the developers code \`${errorNo}\`.` + ); + await message.util.send({ embeds: [errorUserEmbed] }).catch((e) => { + const channel = message.channel.type === 'dm' ? message.channel.recipient.tag : message.channel.name; + this.client.console.warn('CommandError', `Failed to send user error embed in <<${channel}>>:\n` + e?.stack); + }); + } else { + const errorDevEmbed = new MessageEmbed() + .setTitle('An error occurred') + .setColor(this.client.util.colors.error) + .setTimestamp() + .setDescription(await this.client.util.codeblock(`${error?.stack}`, 2048, 'js')); + await message.util.send({ embeds: [errorDevEmbed] }).catch((e) => { + const channel = message.channel.type === 'dm' ? message.channel.recipient.tag : message.channel.name; + this.client.console.warn('CommandError', `Failed to send owner error stack in <<${channel}>>.` + e?.stack); + }); + } } - const channel = (await this.client.channels.fetch(this.client.config.channels.log)) as TextChannel; - await channel.send({ embeds: [errorDevEmbed] }); - if (errorUserEmbed) await message.reply({ embeds: [errorUserEmbed] }); + const channel = message.channel.type === 'dm' ? message.channel.recipient.tag : message.channel.name; + this.client.console.error( + 'CommandError', + `an error occurred with the <<${command}>> command in <<${channel}>> triggered by <<${message?.author?.tag}>>:\n` + + error?.stack + ); } } diff --git a/src/listeners/commands/commandStarted.ts b/src/listeners/commands/commandStarted.ts index 1c5b0c7..28ed0f8 100644 --- a/src/listeners/commands/commandStarted.ts +++ b/src/listeners/commands/commandStarted.ts @@ -1,5 +1,4 @@ -import chalk from 'chalk'; -import { Message, DMChannel } from 'discord.js'; +import { Message } from 'discord.js'; import { BushCommand } from '../../lib/extensions/BushCommand'; import { BushListener } from '../../lib/extensions/BushListener'; @@ -11,10 +10,12 @@ export default class CommandStartedListener extends BushListener { }); } exec(message: Message, command: BushCommand): void { - this.client.logger.verbose( - chalk`{cyan {green ${message.author.tag}} is running {green ${command.aliases[0]}} in {green ${ - message.channel instanceof DMChannel ? 'DMs' : `#${message.channel.name} (Server: ${message.guild.name})` - }}.}` + this.client.logger.info( + 'Command', + `The <<${command.id}>> command was used by <<${message.author.tag}>> in ${ + message.channel.type === 'dm' ? `their <<DMs>>` : `<<#${message.channel.name}>> in <<${message.guild?.name}>>` + }.`, + false // I don't want to spam the log channel when people use commands ); } } diff --git a/src/listeners/message/level.ts b/src/listeners/message/level.ts index 1e93055..615c013 100644 --- a/src/listeners/message/level.ts +++ b/src/listeners/message/level.ts @@ -1,4 +1,3 @@ -import chalk from 'chalk'; import { Message } from 'discord.js'; import { BushListener } from '../../lib/extensions/BushListener'; import { Level } from '../../lib/models'; @@ -30,7 +29,7 @@ export default class LevelListener extends BushListener { const xpToGive = Level.genRandomizedXp(); user.xp += xpToGive; await user.save(); - await this.client.logger.verbose(chalk`{cyan Gave XP to {green ${message.author.tag}}: {green ${xpToGive}xp}.}`); + await this.client.logger.verbose(`LevelListener`, `Gave <<${xpToGive}>> XP to <<${message.author.tag}>>.`); this.levelCooldowns.add(message.author.id); setTimeout(() => this.levelCooldowns.delete(message.author.id), 60_000); } diff --git a/src/listeners/other/consoleListener.ts b/src/listeners/other/consoleListener.ts new file mode 100644 index 0000000..50c0cf3 --- /dev/null +++ b/src/listeners/other/consoleListener.ts @@ -0,0 +1,50 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { BushListener } from '../../lib/extensions/BushListener'; + +export default class ConsoleListener extends BushListener { + public constructor() { + super('console', { + emitter: 'stdin', + event: 'line' + }); + } + + public async exec(line: string): Promise<void> { + const bot = this.client; + if (line.startsWith('eval ')) { + try { + const input = line.replace('eval ', ''); + let output = eval(input); + output = await output; + console.log(output); + } catch (e) { + console.error(e); + } + } + if (line.startsWith('ev ')) { + try { + const input = line.replace('ev ', ''); + let output = eval(input); + output = await output; + console.log(output); + } catch (e) { + console.error(e); + } + } /* else if (line.startsWith('reload')) { + exec('npx tsc', (error) => { + if (error) { + return this.client.console.error('Reload', `Error recompiling, \`${error.message}\``); + } + try { + this.client.commandHandler.reloadAll(); + this.client.listenerHandler.reloadAll(); + } catch (e) { + return this.client.console.error('Reload', e); + } + this.client.console.success('Reload', 'Reloaded successfully.'); + }); + } else if (line.startsWith('stop') || line.startsWith('exit')) { + process.exit(); + } */ + } +} diff --git a/src/listeners/other/promiseRejection.ts b/src/listeners/other/promiseRejection.ts new file mode 100644 index 0000000..2d7e316 --- /dev/null +++ b/src/listeners/other/promiseRejection.ts @@ -0,0 +1,23 @@ +import { BushListener } from '../../lib/extensions/BushListener'; + +export default class PromiseRejectionListener extends BushListener { + constructor() { + super('promiseRejection', { + emitter: 'process', + event: 'unhandledRejection' + }); + } + + public async exec(error: Error): Promise<void> { + this.client.console.error('PromiseRejection', 'An unhanded promise rejection occurred:\n' + error.stack, false); + await this.client.console.channelError({ + embeds: [ + { + title: 'Unhandled promise rejection', + fields: [{ name: 'error', value: await this.client.util.codeblock(error.stack, 1024, 'js') }], + color: this.client.util.colors.error + } + ] + }); + } +} diff --git a/src/tasks/unban.ts b/src/tasks/unban.ts index 564a2a3..6e06db8 100644 --- a/src/tasks/unban.ts +++ b/src/tasks/unban.ts @@ -1,4 +1,3 @@ -import chalk from 'chalk'; import { DiscordAPIError } from 'discord.js'; import { Op } from 'sequelize'; import { BushTask } from '../lib/extensions/BushTask'; @@ -23,7 +22,7 @@ export default class UnbanTask extends BushTask { ] } }); - this.client.logger.verbose(chalk.cyan(`Queried bans, found ${rows.length} expired bans.`)); + this.client.logger.verbose(`UnbanTask`, `Queried bans, found <<${rows.length}>> expired bans.`); for (const row of rows) { const guild = this.client.guilds.cache.get(row.guild); if (!guild) { @@ -38,7 +37,7 @@ export default class UnbanTask extends BushTask { } else throw e; } await row.destroy(); - this.client.logger.verbose(chalk.cyan('Unbanned user')); + this.client.logger.verbose(`UnbanTask`, `Unbanned ${row.user}`); } } } @@ -14,21 +14,21 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.14.0": - version: 7.14.0 - resolution: "@babel/helper-validator-identifier@npm:7.14.0" - checksum: bd67b4a1a49eba151aa0fe95508579638287fee0a3e7a3bf8c5ab480de8eaad4b4231c523d7db401eb0cecc7cf03b76ee72453fab53bab8cb8ccd154bb67feb7 +"@babel/helper-validator-identifier@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/helper-validator-identifier@npm:7.14.5" + checksum: 778312189a7c5228daac9f7767795a74f11d1eac595ca38bfea248324666459b24aaae6aef43c957ce01bbe61672039ea1c08c5623067c3701beeb1bb1f1ee33 languageName: node linkType: hard "@babel/highlight@npm:^7.10.4": - version: 7.14.0 - resolution: "@babel/highlight@npm:7.14.0" + version: 7.14.5 + resolution: "@babel/highlight@npm:7.14.5" dependencies: - "@babel/helper-validator-identifier": ^7.14.0 + "@babel/helper-validator-identifier": ^7.14.5 chalk: ^2.0.0 js-tokens: ^4.0.0 - checksum: 0122fcd3cd6e81bfa002227d6c9dfff91d388d48dc188cd13e3f60c46e5450ebad65aa133ac8f525cb3cfa3b70766484e4a93c40b2837ce16f12083ebd2b0824 + checksum: a1ed599c2655eb0b13134875ba2626b547a2634940e532c86a02896fb403f197cd56d1adaa474c7859ae4f53fabc5f1621e90770e75d235ca3350952ba78aa5c languageName: node linkType: hard @@ -63,20 +63,20 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^0.4.1": - version: 0.4.1 - resolution: "@eslint/eslintrc@npm:0.4.1" +"@eslint/eslintrc@npm:^0.4.2": + version: 0.4.2 + resolution: "@eslint/eslintrc@npm:0.4.2" dependencies: ajv: ^6.12.4 debug: ^4.1.1 espree: ^7.3.0 - globals: ^12.1.0 + globals: ^13.9.0 ignore: ^4.0.6 import-fresh: ^3.2.1 js-yaml: ^3.13.1 minimatch: ^3.0.4 strip-json-comments: ^3.1.1 - checksum: 418f5810c8dd9897d2457ceef098197d0e5f1ad345fbe4cd9256fd4223d7ea83d5e350f9091b3ab3483b6b1c367fa560df3ba1fccc7eb8ca6e1aae5a5b126d60 + checksum: 60b66ce4257bf5c36a920dea83a056102fef746e7afd7100a6fe245a126ff455f67f4948e75d28ed73090bff8f8556b6a996e74a124911ca703440bc245dbc23 languageName: node linkType: hard @@ -99,30 +99,30 @@ __metadata: languageName: node linkType: hard -"@nodelib/fs.scandir@npm:2.1.4": - version: 2.1.4 - resolution: "@nodelib/fs.scandir@npm:2.1.4" +"@nodelib/fs.scandir@npm:2.1.5": + version: 2.1.5 + resolution: "@nodelib/fs.scandir@npm:2.1.5" dependencies: - "@nodelib/fs.stat": 2.0.4 + "@nodelib/fs.stat": 2.0.5 run-parallel: ^1.1.9 - checksum: 30b3102ee37e1c1a0cb939a8e93f9a58b1637e2b4b546bb9143b3fb5efacd2abde3237a5313d5329bf1bc4231c418a77c3cb7f5434ce410e61a91ff4051cf215 + checksum: 91b3de88d9ba843b74057ebec53d97bb1ca006fcb794f1eb2becfe6faf114cb575c90b10fc20f7390358106ffa5e6bbc493506c24f2263a33aa69f90c1e77f74 languageName: node linkType: hard -"@nodelib/fs.stat@npm:2.0.4, @nodelib/fs.stat@npm:^2.0.2": - version: 2.0.4 - resolution: "@nodelib/fs.stat@npm:2.0.4" - checksum: 6454a79e945dd55102b5c2e158813804ed349f9c1cc806f8754fca4587688a5d8e4115fc3eedbdf3d8a6b343169a6b664ecd8a7a42289eed210c686a4d0897c4 +"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": + version: 2.0.5 + resolution: "@nodelib/fs.stat@npm:2.0.5" + checksum: a4fcf7408f2a1e11737856629b1259fb9ed658c464fabb17f77db1069fea5dd47abd5e92325b217617dbc116138d82ea6d33ffc07a426de940c5f6e08603da88 languageName: node linkType: hard "@nodelib/fs.walk@npm:^1.2.3": - version: 1.2.6 - resolution: "@nodelib/fs.walk@npm:1.2.6" + version: 1.2.7 + resolution: "@nodelib/fs.walk@npm:1.2.7" dependencies: - "@nodelib/fs.scandir": 2.1.4 + "@nodelib/fs.scandir": 2.1.5 fastq: ^1.6.0 - checksum: d0503ffd0bb4172d5ac5d23993b14665f5f6d42a460a719ad97743ce71e60588d134cc60df12ca76be0e5e3a93c9a3156904d9296b78a8cdf19425c3423c0b58 + checksum: ac8e2d9ca000b9f7fca2a7b005b9e476ba7b2f416d2873f64b94b207ed1854bd30f63ced4c221969c5e470ec82fbeb353c97504a86c3838cda11f98660fac284 languageName: node linkType: hard @@ -205,25 +205,25 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:^4.17.18": - version: 4.17.19 - resolution: "@types/express-serve-static-core@npm:4.17.19" + version: 4.17.21 + resolution: "@types/express-serve-static-core@npm:4.17.21" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" - checksum: b6c8c357c5d093303c681616b7a80d6a044b47c4161a3459c65e451137832b29a485a8f8708414205f427dade6b4ff5ef799d51715d12f92da3468cf41a2cf06 + checksum: 437165cc123eacb36c7602e8df738d053c2fe4d67957e2b3758bd0b7426cd0439201b411b59dc85abc74456870011b0d91abb2f7bf8e35d8b643ecbdc5d91dfd languageName: node linkType: hard "@types/express@npm:^4.17.11": - version: 4.17.11 - resolution: "@types/express@npm:4.17.11" + version: 4.17.12 + resolution: "@types/express@npm:4.17.12" dependencies: "@types/body-parser": "*" "@types/express-serve-static-core": ^4.17.18 "@types/qs": "*" "@types/serve-static": "*" - checksum: 2818120a0fd8b7982215864929cdc6cd14942dd44849f93054fe2a90b4233dff67aadc34c73b5937922a02c688b0263d00a4807aa2e59307ac859a1458d73669 + checksum: b1ab50e0373095283f5a58c8c1aa7e206182d241d24279e24d754819ae39959b35996d34633b1e4b3a9d3817559abad00ec33c94b96da945a9c3d1546f3e4f70 languageName: node linkType: hard @@ -234,7 +234,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:^7.0.3": +"@types/json-schema@npm:^7.0.7": version: 7.0.7 resolution: "@types/json-schema@npm:7.0.7" checksum: b9d2c509fa4e0b82f58e73f5e6ab76c60ff1884ba41bb82f37fb1cece226d4a3e5a62fedf78a43da0005373a6713d9abe61c1e592906402c41c08ad6ab26d52b @@ -258,16 +258,16 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 15.3.0 - resolution: "@types/node@npm:15.3.0" - checksum: 44039665ab71a6ec12e6637a9db4ec3123fdfaf52952ca8028a6f1b37c41c2d380e88d28a41e02693bf9d4815307e0ad938815bf8ffedc5f4d045855fa28db06 + version: 15.12.4 + resolution: "@types/node@npm:15.12.4" + checksum: 64b121a7e805379382aeb3eefed56c4c34f1ebf5e818ba2c732e43beebc4fbde20be438f3eaaffd8dba5062f0e0c9ae085127b7239906d170eda816885a6c508 languageName: node linkType: hard "@types/node@npm:^14.14.22": - version: 14.17.0 - resolution: "@types/node@npm:14.17.0" - checksum: f437147b39e04b23272eae604ec301b5a91956d386f96a2a796efa856d813df116c1afea511b2c23d908c0456c479bad32862aea6d6f0eaffcc1056603b98e64 + version: 14.17.3 + resolution: "@types/node@npm:14.17.3" + checksum: 0d3e3c3dbb8250166d7c8c7c6221bde20a366d2c34b27c0072c3962a32c8a74c4ae4a168bfe53d6193e7b0bba8d8bc87608a6fd2af7918cd444a9aa699b4ce18 languageName: node linkType: hard @@ -312,111 +312,111 @@ __metadata: linkType: hard "@types/ws@npm:^7.4.4": - version: 7.4.4 - resolution: "@types/ws@npm:7.4.4" + version: 7.4.5 + resolution: "@types/ws@npm:7.4.5" dependencies: "@types/node": "*" - checksum: 6a02b3164250813510c5e73998a2bbca1fb98dc23428d70c2c6d664dfbac3fde32cd8d4eb34c335a0221f49a6f02d71b09645b236b01de1aea85f80352f67e1f + checksum: b467f596cc9992dde38ea9bb824135f20d0eae92515304e3de25e4b98a3b41e71897801900563c1e72f36fa7a6277c873896b842bd6d1b9d4b9457834533903b languageName: node linkType: hard "@typescript-eslint/eslint-plugin@npm:^4.14.1": - version: 4.24.0 - resolution: "@typescript-eslint/eslint-plugin@npm:4.24.0" + version: 4.27.0 + resolution: "@typescript-eslint/eslint-plugin@npm:4.27.0" dependencies: - "@typescript-eslint/experimental-utils": 4.24.0 - "@typescript-eslint/scope-manager": 4.24.0 - debug: ^4.1.1 + "@typescript-eslint/experimental-utils": 4.27.0 + "@typescript-eslint/scope-manager": 4.27.0 + debug: ^4.3.1 functional-red-black-tree: ^1.0.1 - lodash: ^4.17.15 - regexpp: ^3.0.0 - semver: ^7.3.2 - tsutils: ^3.17.1 + lodash: ^4.17.21 + regexpp: ^3.1.0 + semver: ^7.3.5 + tsutils: ^3.21.0 peerDependencies: "@typescript-eslint/parser": ^4.0.0 eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 peerDependenciesMeta: typescript: optional: true - checksum: b3fb023320073cfbbc51d435313d63519a0c2ddb6360ace337e57be29851733edae54d2b4a893b54ee06080266021951f8a541b85084f2a00bf49c06d90e410d + checksum: 6f5e556c92cdbb25c394799c5cb442bb541717c2953a368034a06deacb158e5f4bd5f3f743a4e0a58b9446bf18387bd8fd19ded303fe1269e8c193f30fe194c4 languageName: node linkType: hard -"@typescript-eslint/experimental-utils@npm:4.24.0": - version: 4.24.0 - resolution: "@typescript-eslint/experimental-utils@npm:4.24.0" +"@typescript-eslint/experimental-utils@npm:4.27.0": + version: 4.27.0 + resolution: "@typescript-eslint/experimental-utils@npm:4.27.0" dependencies: - "@types/json-schema": ^7.0.3 - "@typescript-eslint/scope-manager": 4.24.0 - "@typescript-eslint/types": 4.24.0 - "@typescript-eslint/typescript-estree": 4.24.0 - eslint-scope: ^5.0.0 - eslint-utils: ^2.0.0 + "@types/json-schema": ^7.0.7 + "@typescript-eslint/scope-manager": 4.27.0 + "@typescript-eslint/types": 4.27.0 + "@typescript-eslint/typescript-estree": 4.27.0 + eslint-scope: ^5.1.1 + eslint-utils: ^3.0.0 peerDependencies: eslint: "*" - checksum: 09a28e2b8b39739e7543afca53910b175d0ac4d9346da25479ef179bbeea3cb6d004bd5e931f5402fb39a1af7aa49b793c573da1faa1e773ea6d18006b781a5a + checksum: b8c66eceeba674b21750eb795a91a1f20814f9be41e9d249f2ddd2bab85ad0a418322cfbbd9af845a9907921ce762df115e361467f86317f2a33330bc4461134 languageName: node linkType: hard "@typescript-eslint/parser@npm:^4.14.1": - version: 4.24.0 - resolution: "@typescript-eslint/parser@npm:4.24.0" + version: 4.27.0 + resolution: "@typescript-eslint/parser@npm:4.27.0" dependencies: - "@typescript-eslint/scope-manager": 4.24.0 - "@typescript-eslint/types": 4.24.0 - "@typescript-eslint/typescript-estree": 4.24.0 - debug: ^4.1.1 + "@typescript-eslint/scope-manager": 4.27.0 + "@typescript-eslint/types": 4.27.0 + "@typescript-eslint/typescript-estree": 4.27.0 + debug: ^4.3.1 peerDependencies: eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 30ff5e6b1e5e28a21f609576b6c504b6311ee7c26c6ffb1eaa986db16857765e7f5ad46c37c362a1fd809c3f3aead6be9c4e6b1289473be6764cf8f22e6f067e + checksum: cfe1b6b2c195e56396ffe1869af9aa660bc1427c7923cccff5b248aba95def2097eea0df40c748ee43e9796783332e7e6bbf41c2b92bebbcfe8557fa8c69ffdc languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:4.24.0": - version: 4.24.0 - resolution: "@typescript-eslint/scope-manager@npm:4.24.0" +"@typescript-eslint/scope-manager@npm:4.27.0": + version: 4.27.0 + resolution: "@typescript-eslint/scope-manager@npm:4.27.0" dependencies: - "@typescript-eslint/types": 4.24.0 - "@typescript-eslint/visitor-keys": 4.24.0 - checksum: 522d96e562bec1c717e5ec6665801ee54eaf18653044e3b385cf6967ffdfa0bdf17c0f058fff3af6ec935815abe8419969c26c6cf564e07db2487571f04c2ea4 + "@typescript-eslint/types": 4.27.0 + "@typescript-eslint/visitor-keys": 4.27.0 + checksum: 5d39a2dda0722a00e5707fddb1e83608c30c08af70e4a6f70106ecaf51359dd9ea8a64aec37cbfa23f9b286041da012a59158f7200df6007734c1d02184d0472 languageName: node linkType: hard -"@typescript-eslint/types@npm:4.24.0": - version: 4.24.0 - resolution: "@typescript-eslint/types@npm:4.24.0" - checksum: ed06724661da645419b353eefa4a81df6503a4ebd56d07113f58beb0f524414e2f3acaf82a997bb2a1cad8f99d9889cc5fc11ea0928262de65c75516eccadc59 +"@typescript-eslint/types@npm:4.27.0": + version: 4.27.0 + resolution: "@typescript-eslint/types@npm:4.27.0" + checksum: b9540fdf5cacbb36c918e3cfef07896b0c70fb49d45568ee08ea4743072925e5f89ad07549210bd362691f9a2c5b3522d97430f38cb35a25ddc1304cd5ec9823 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:4.24.0": - version: 4.24.0 - resolution: "@typescript-eslint/typescript-estree@npm:4.24.0" +"@typescript-eslint/typescript-estree@npm:4.27.0": + version: 4.27.0 + resolution: "@typescript-eslint/typescript-estree@npm:4.27.0" dependencies: - "@typescript-eslint/types": 4.24.0 - "@typescript-eslint/visitor-keys": 4.24.0 - debug: ^4.1.1 - globby: ^11.0.1 + "@typescript-eslint/types": 4.27.0 + "@typescript-eslint/visitor-keys": 4.27.0 + debug: ^4.3.1 + globby: ^11.0.3 is-glob: ^4.0.1 - semver: ^7.3.2 - tsutils: ^3.17.1 + semver: ^7.3.5 + tsutils: ^3.21.0 peerDependenciesMeta: typescript: optional: true - checksum: 7720b1f5e8c3c3bf212da3325d9beb699adb52c9cbbcf810f4a53a71e18752e299415794474fa3909671fe20fa5dc26f50c1ba476c8ae90bd2a5484f58c9b708 + checksum: dc9711dab7fc6d53bb9471e21d27e2c65f2840c52d86fc8a368dedf714297bde43b30ea4af952c1def8d063f3dbef8eda4196b85db6d7fd0062da8b304810585 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:4.24.0": - version: 4.24.0 - resolution: "@typescript-eslint/visitor-keys@npm:4.24.0" +"@typescript-eslint/visitor-keys@npm:4.27.0": + version: 4.27.0 + resolution: "@typescript-eslint/visitor-keys@npm:4.27.0" dependencies: - "@typescript-eslint/types": 4.24.0 + "@typescript-eslint/types": 4.27.0 eslint-visitor-keys: ^2.0.0 - checksum: ec25df6705f3768b415abcfeae09ef6dc4ee7a7e77e9b7b795fc461668ed4a7c5a406a23af31e1471fa920adc705c515fe56e86a7cda6cddef8521f54afadffc + checksum: d600de56ce12ee1195fbc76fd82ec56116f5301093b4f313dbf9fa1ee82a3609bbfdf48bdb722cb253256da80f46b71070fddbda47d77e8808d0a04c4f5e6a2c languageName: node linkType: hard @@ -497,14 +497,14 @@ __metadata: linkType: hard "ajv@npm:^8.0.1": - version: 8.4.0 - resolution: "ajv@npm:8.4.0" + version: 8.6.0 + resolution: "ajv@npm:8.6.0" dependencies: fast-deep-equal: ^3.1.1 json-schema-traverse: ^1.0.0 require-from-string: ^2.0.2 uri-js: ^4.2.2 - checksum: 0dcdfe0ecaafca2de60d01601c041853a1057f26bcb24de79484a3f6947486cad7b84d2779f93a9a315345451248aca14ed4996213905b42fac4ec11c7a76a6c + checksum: 4eed9ee72e752d34a99541d04a608030db17735672ec334563b7cbc5936cb879a394e8f75789174690c7cd58ec2610c8363cb7480c23c15a9ca4424911cd683d languageName: node linkType: hard @@ -681,7 +681,7 @@ __metadata: canvas: ^2.8.0 chalk: ^4.1.1 common-tags: ^1.8.0 - discord-akairo: IRONM00N-Development/discord-akairo + discord-akairo: NotEnoughUpdates/discord-akairo discord-api-types: ^0.18.1 discord.js: dev esbuild: ^0.12.1 @@ -697,6 +697,9 @@ __metadata: source-map-support: ^0.5.19 typescript: ^4.2.4 uuid: ^8.3.2 + dependenciesMeta: + prettier@2.3.1: + unplugged: true languageName: unknown linkType: soft @@ -740,17 +743,17 @@ __metadata: linkType: hard "cacheable-request@npm:^7.0.1": - version: 7.0.1 - resolution: "cacheable-request@npm:7.0.1" + version: 7.0.2 + resolution: "cacheable-request@npm:7.0.2" dependencies: clone-response: ^1.0.2 get-stream: ^5.1.0 http-cache-semantics: ^4.0.0 keyv: ^4.0.0 lowercase-keys: ^2.0.0 - normalize-url: ^4.1.0 + normalize-url: ^6.0.1 responselike: ^2.0.0 - checksum: fe0b6f3b8a145c98fecc00f0f1b13a9886cad9bf4537533c5568cba19db81c8ee09ace9c61967d5a4e72615e174d771b6b8080c3816f0b74fc6f9c69060c3ff0 + checksum: 176a1fceb987f1fee8b512ee7908445854a0c75854a11710f0d8de104cf840fd92e3c94ecd1f9144e57a25e17f5d72056591e5b33aabb8775061f906b0696a50 languageName: node linkType: hard @@ -920,7 +923,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0": +"debug@npm:4, debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1": version: 4.3.2 resolution: "debug@npm:4.3.2" dependencies: @@ -932,18 +935,6 @@ __metadata: languageName: node linkType: hard -"debug@npm:^4.0.1, debug@npm:^4.1.1": - version: 4.3.1 - resolution: "debug@npm:4.3.1" - dependencies: - ms: 2.1.2 - peerDependenciesMeta: - supports-color: - optional: true - checksum: 0d41ba5177510e8b388dfd7df143ab0f9312e4abdaba312595461511dac88e9ef8101939d33b4e6d37e10341af6a5301082e4d7d6f3deb4d57bc05fc7d296fad - languageName: node - linkType: hard - "decompress-response@npm:^4.2.0": version: 4.2.1 resolution: "decompress-response@npm:4.2.1" @@ -1015,10 +1006,10 @@ __metadata: languageName: node linkType: hard -discord-akairo@IRONM00N-Development/discord-akairo: +discord-akairo@NotEnoughUpdates/discord-akairo: version: 8.2.2 - resolution: "discord-akairo@https://github.com/IRONM00N-Development/discord-akairo.git#commit=690c219497dff280dd49360882f72ddd100fc148" - checksum: cfce18b1f676817baa19d0a63df66e0c3d6b48c1eea9e11f67ed25711f141a347fce95756b586f7bbbab92511c1a266683776faa76d699c52ff097c53f9b215e + resolution: "discord-akairo@https://github.com/NotEnoughUpdates/discord-akairo.git#commit=98309bfc2b384cb41610ab7221fcd683fe8e2f88" + checksum: f00d40033ad7b30afde775ebc602aa6f7825bfe07baf08e610185d2aa4a8d250e8b0eb01ed8365537ee6ac9fefd316a015df8332c13d9ba928e976b32d48c72b languageName: node linkType: hard @@ -1030,8 +1021,8 @@ discord-akairo@IRONM00N-Development/discord-akairo: linkType: hard "discord.js@npm:dev": - version: 13.0.0-dev.918921e8211fc16e9b12d2502f3168264246ea22 - resolution: "discord.js@npm:13.0.0-dev.918921e8211fc16e9b12d2502f3168264246ea22" + version: 13.0.0-dev.807ea2d3c197c7c6556bd1c894114932f6657d49 + resolution: "discord.js@npm:13.0.0-dev.807ea2d3c197c7c6556bd1c894114932f6657d49" dependencies: "@discordjs/collection": ^0.1.6 "@discordjs/form-data": ^3.0.1 @@ -1041,7 +1032,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: discord-api-types: ^0.18.1 node-fetch: ^2.6.1 ws: ^7.4.6 - checksum: be1707f530ce01051c43833d9eb3bf7d125f6b58a6ee790bfd0cd23327603149a4b6b142ea4ae96920af2baadc4b689b952342a2c6283db4a750dc7178723390 + checksum: 6b0cc167612d88763490c165dea3efc3483dc570f6cd56da586dba04647a413299968e03be1810b2835f9c32534a0229705d1e9a031a4e56a2a84d03acbabf3e languageName: node linkType: hard @@ -1117,11 +1108,11 @@ discord-akairo@IRONM00N-Development/discord-akairo: linkType: hard "esbuild@npm:^0.12.1": - version: 0.12.1 - resolution: "esbuild@npm:0.12.1" + version: 0.12.9 + resolution: "esbuild@npm:0.12.9" bin: esbuild: bin/esbuild - checksum: 9fad417f76b9bd8d8f62ae76572659066dfeefb11583cef73c283f7e0b75c9d1a341f9b9237b420bb1eb02234706e2563fea06ac9a1e01659705b57a3b75baa1 + checksum: e88720c29ec272c24640db25acdec841ad266bb42d8bb8930270141c82834314a05184f90ac68a74139721741c52ba343776ba4f69b2cf41a7a31c343e6fc867 languageName: node linkType: hard @@ -1132,6 +1123,13 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard +"escape-string-regexp@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: c747be8d5ff7873127e3e0cffe7d2206a37208077fa9c30a3c1bb4f26bebd081c8c24d5fba7a99449f9d20670bea3dc5e1b6098b0f074b099bd38766271a272f + languageName: node + linkType: hard + "eslint-config-prettier@npm:^8.1.0": version: 8.3.0 resolution: "eslint-config-prettier@npm:8.3.0" @@ -1143,7 +1141,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"eslint-scope@npm:^5.0.0, eslint-scope@npm:^5.1.1": +"eslint-scope@npm:^5.1.1": version: 5.1.1 resolution: "eslint-scope@npm:5.1.1" dependencies: @@ -1153,7 +1151,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"eslint-utils@npm:^2.0.0, eslint-utils@npm:^2.1.0": +"eslint-utils@npm:^2.1.0": version: 2.1.0 resolution: "eslint-utils@npm:2.1.0" dependencies: @@ -1162,6 +1160,17 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard +"eslint-utils@npm:^3.0.0": + version: 3.0.0 + resolution: "eslint-utils@npm:3.0.0" + dependencies: + eslint-visitor-keys: ^2.0.0 + peerDependencies: + eslint: ">=5" + checksum: 035451529f016e28edd26e8951f15e28a6a4e58adff67bd0cb494879f360080750b9c779e46561369aec0657ac2b89dd8b0aa38476e8cdf50e635aa872fa27b6 + languageName: node + linkType: hard + "eslint-visitor-keys@npm:^1.1.0, eslint-visitor-keys@npm:^1.3.0": version: 1.3.0 resolution: "eslint-visitor-keys@npm:1.3.0" @@ -1177,26 +1186,28 @@ discord-akairo@IRONM00N-Development/discord-akairo: linkType: hard "eslint@npm:^7.18.0": - version: 7.26.0 - resolution: "eslint@npm:7.26.0" + version: 7.29.0 + resolution: "eslint@npm:7.29.0" dependencies: "@babel/code-frame": 7.12.11 - "@eslint/eslintrc": ^0.4.1 + "@eslint/eslintrc": ^0.4.2 ajv: ^6.10.0 chalk: ^4.0.0 cross-spawn: ^7.0.2 debug: ^4.0.1 doctrine: ^3.0.0 enquirer: ^2.3.5 + escape-string-regexp: ^4.0.0 eslint-scope: ^5.1.1 eslint-utils: ^2.1.0 eslint-visitor-keys: ^2.0.0 espree: ^7.3.1 esquery: ^1.4.0 esutils: ^2.0.2 + fast-deep-equal: ^3.1.3 file-entry-cache: ^6.0.1 functional-red-black-tree: ^1.0.1 - glob-parent: ^5.0.0 + glob-parent: ^5.1.2 globals: ^13.6.0 ignore: ^4.0.6 import-fresh: ^3.0.0 @@ -1205,7 +1216,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: js-yaml: ^3.13.1 json-stable-stringify-without-jsonify: ^1.0.1 levn: ^0.4.1 - lodash: ^4.17.21 + lodash.merge: ^4.6.2 minimatch: ^3.0.4 natural-compare: ^1.4.0 optionator: ^0.9.1 @@ -1214,12 +1225,12 @@ discord-akairo@IRONM00N-Development/discord-akairo: semver: ^7.2.1 strip-ansi: ^6.0.0 strip-json-comments: ^3.1.0 - table: ^6.0.4 + table: ^6.0.9 text-table: ^0.2.0 v8-compile-cache: ^2.0.3 bin: eslint: bin/eslint.js - checksum: 08f99befd764fbd6ea811e9eec27d5c6b9dc9d1bbfe5ffa1016e4f1fe526a4f45ea127c4e30c554c423ee55eb290ce9af4fb7fedf9b7af3f84076a444c2bbdf6 + checksum: 812f8c5123860cf5bd877018ffd29abd52bbaaca55fdd616008c97da9bf47a20a7b7c7ecb7c8f753c06f77ea5d59480f3d6d76475699b2ea380237fbb7c6b3a2 languageName: node linkType: hard @@ -1290,7 +1301,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"fast-deep-equal@npm:^3.1.1": +"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" checksum: 451526766b219503131d11e823eaadd1533080b0be4860e316670b039dcaf31cd1007c2fe036a9b922abba7c040dfad5e942ed79d21f2ff849e50049f36e0fb7 @@ -1417,7 +1428,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"glob-parent@npm:^5.0.0, glob-parent@npm:^5.1.0": +"glob-parent@npm:^5.1.0, glob-parent@npm:^5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" dependencies: @@ -1440,27 +1451,18 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"globals@npm:^12.1.0": - version: 12.4.0 - resolution: "globals@npm:12.4.0" - dependencies: - type-fest: ^0.8.1 - checksum: 0b9764bdeab0bc9762dea8954a0d4c5db029420bd8bf693df9098ce7e045ccaf9b2d259185396fd048b051d42fdc8dc7ab02af62e3dbeb2324a78a05aac8d33c - languageName: node - linkType: hard - -"globals@npm:^13.6.0": - version: 13.8.0 - resolution: "globals@npm:13.8.0" +"globals@npm:^13.6.0, globals@npm:^13.9.0": + version: 13.9.0 + resolution: "globals@npm:13.9.0" dependencies: type-fest: ^0.20.2 - checksum: de85e5dc899ebd77414cc026e806d0bfd2c102ba23d08a2516c960a5e324433d3f1c124465a35b5b1d948448a7008bad85f823a9bcd8d54664d8a0cbcaab0091 + checksum: 26d71f2c286c80d806faad49c801bfb2ac5144497b5c844c5a718b2c3fad51e0d507d9069474e89f110f16a38bf212ec56e6e40936a4f24b1a645e7f21001d1d languageName: node linkType: hard -"globby@npm:^11.0.1": - version: 11.0.3 - resolution: "globby@npm:11.0.3" +"globby@npm:^11.0.3": + version: 11.0.4 + resolution: "globby@npm:11.0.4" dependencies: array-union: ^2.1.0 dir-glob: ^3.0.1 @@ -1468,7 +1470,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: ignore: ^5.1.4 merge2: ^1.3.0 slash: ^3.0.0 - checksum: f17da0f869918656ec8c16c15ad100f025fbd13e4c157286cf340811eb1355a7d06dde77be1685a7a051970ec6abeff96a9b2a1a97525f84bc94fbd518c1d1db + checksum: 9f365b35b835c0235880e272fa2a2f5d9d78428e09af8dfc67536f1047953e7b0c66aab9bb6d41e6c0f4c3ec75a22840d9acb892f102daecaadd338b2c763219 languageName: node linkType: hard @@ -1820,6 +1822,13 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard +"lodash.merge@npm:^4.6.2": + version: 4.6.2 + resolution: "lodash.merge@npm:4.6.2" + checksum: 4e2bb42a87a148991458d7c384bc197e96f7115e9536fc8e2c86ae9e99ce1c1f693ff15eb85761952535f48d72253aed8e673d9f32dde3e671cd91e3fde220a7 + languageName: node + linkType: hard + "lodash.truncate@npm:^4.4.2": version: 4.4.2 resolution: "lodash.truncate@npm:4.4.2" @@ -1827,7 +1836,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"lodash@npm:^4.17.15, lodash@npm:^4.17.20, lodash@npm:^4.17.21": +"lodash@npm:^4.17.20, lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: 4983720b9abca930a4a46f18db163d7dad8dd00dbed6db0cc7b499b33b717cce69f80928b27bbb1ff2cbd3b19d251ee90669a8b5ea466072ca81c2ebe91e7468 @@ -1906,19 +1915,19 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"mime-db@npm:1.47.0": - version: 1.47.0 - resolution: "mime-db@npm:1.47.0" - checksum: f5f9220dd53c240c9234323571f632486c663e36676ebfdca9963fb9a92d1dd28b16124bceff60868fb70743764ade8466dd5e6a1a833decde89ae6d15211503 +"mime-db@npm:1.48.0": + version: 1.48.0 + resolution: "mime-db@npm:1.48.0" + checksum: 346d5df2ff2f501bdeff07e88a28d205f9cd27bccd3b8604847d3aee6ce73d4ecf88e943bbbce46c167d404487f46cdf09d57354c51b6f08a4d5833bcaafa59f languageName: node linkType: hard "mime-types@npm:^2.1.12, mime-types@npm:~2.1.24": - version: 2.1.30 - resolution: "mime-types@npm:2.1.30" + version: 2.1.31 + resolution: "mime-types@npm:2.1.31" dependencies: - mime-db: 1.47.0 - checksum: c7ca8a9980bdae0b760820aded39ea9541a8236f4abc105df645ea5b09a9c4a5299e28667c0c9596ab8e4ca84b219fd8b94b5c68e32b59891ca1f57a7e848c02 + mime-db: 1.48.0 + checksum: 0373e58e3826802e462cf0c180ca5556fd0990acaf123d421d5f8643f0ca61d2126ea57eb6f4ba96f9ef07d3e627c06261825418a6549b0671261cc1bb4219b4 languageName: node linkType: hard @@ -2092,8 +2101,8 @@ discord-akairo@IRONM00N-Development/discord-akairo: linkType: hard "node-gyp@npm:latest": - version: 8.0.0 - resolution: "node-gyp@npm:8.0.0" + version: 8.1.0 + resolution: "node-gyp@npm:8.1.0" dependencies: env-paths: ^2.2.0 glob: ^7.1.4 @@ -2107,7 +2116,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: which: ^2.0.2 bin: node-gyp: bin/node-gyp.js - checksum: 604a48ca1ee0277a960f4d71a05cea2e9a20007a4cdf7953caec78d26acc4bba765d3a97c649953a2de505de67a1b26f0c8c7c81124c591c81de5659f359adce + checksum: 6e014ff491cc4fdd25c41e38f9f92ab665d3b2e1ef7cd18e292aff9b293ef485c6bb93194461a5538d3bfa4b678258df974800660dd7d40865866ef3188c5481 languageName: node linkType: hard @@ -2122,10 +2131,10 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"normalize-url@npm:^4.1.0": - version: 4.5.0 - resolution: "normalize-url@npm:4.5.0" - checksum: 09794941dbe5c7b91caf6f3cd1ae167c27f6d09793e4a03601a68b62de7e8ee9e5de21a246130cdbab98b01481de292f9556d492444a527648f9cf1220e4b0df +"normalize-url@npm:^6.0.1": + version: 6.0.1 + resolution: "normalize-url@npm:6.0.1" + checksum: 63fe38bbc1c1b41fcc4ba9f54411755ce75aaeb25624d3c95f6d84501ea7a0e4ddd79fbcfcf9e497de7952e3c4856cba8719e9417cfbdd8e082aea5c900f3de4 languageName: node linkType: hard @@ -2248,11 +2257,11 @@ discord-akairo@IRONM00N-Development/discord-akairo: linkType: hard "pg-hstore@npm:^2.3.3": - version: 2.3.3 - resolution: "pg-hstore@npm:2.3.3" + version: 2.3.4 + resolution: "pg-hstore@npm:2.3.4" dependencies: - underscore: ^1.7.0 - checksum: 8e496d4800f08cb8510b11afe92e25af85cecfa0434b44b267d05c9ac27b22539252351eed39b0817ae37e434604bb67c84d8e30fdcc64f8b2bd1c44297d2a6b + underscore: ^1.13.1 + checksum: 336eef36269784876769ad60dd5d674baa7e6d06c4babd33a1abba4c46877b147c12f5a486b327cfbcf7cd2d1c75d74dee5e19c37f0d90ce8b909add8935b00d languageName: node linkType: hard @@ -2322,9 +2331,9 @@ discord-akairo@IRONM00N-Development/discord-akairo: linkType: hard "picomatch@npm:^2.2.1, picomatch@npm:^2.2.3": - version: 2.2.3 - resolution: "picomatch@npm:2.2.3" - checksum: f8c9323bc3b21ff448e81dd32277135d781abae5d53a1415d69a4ce6317a2c11404d449c550110b8fa402c07d5e80ff0e2657f263a312517cc809e9010d25791 + version: 2.3.0 + resolution: "picomatch@npm:2.3.0" + checksum: 80113a0fb70cfa62730d5aa3fd3d45b76bf3985f8494080ab2de1cc1fa3ba96d77990c7553a81401e16c51c0eb19c27cf5bc94f2196155090f26c8a167968001 languageName: node linkType: hard @@ -2366,11 +2375,11 @@ discord-akairo@IRONM00N-Development/discord-akairo: linkType: hard "prettier@npm:^2.2.1": - version: 2.3.0 - resolution: "prettier@npm:2.3.0" + version: 2.3.1 + resolution: "prettier@npm:2.3.1" bin: prettier: bin-prettier.js - checksum: 652640cc8b71bc5277cfb8bf6f161783ca588efcf683c3d630837b39da8d57fef35c9e00ae5855a8e3c75136c42274046c913cc2b2d2968558315f31c6a26981 + checksum: 9b4a695b87ce5f510fc20feec01cce7371f0fa0b92ffe79d543f6be52e2004c532861629de4d7ab1c577e1f649dce3cfccd62cb2ca6526b1da8d9c63eb84bf36 languageName: node linkType: hard @@ -2502,10 +2511,10 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"regexpp@npm:^3.0.0, regexpp@npm:^3.1.0": - version: 3.1.0 - resolution: "regexpp@npm:3.1.0" - checksum: 69d0ce6b449cf35d3732d6341a1e70850360ffc619f8eef10629871c462e614853fffb80d3f00fc17cd0bb5b8f34b0cde5be4b434e72c0eb3fbba2360c8b5ac4 +"regexpp@npm:^3.1.0": + version: 3.2.0 + resolution: "regexpp@npm:3.2.0" + checksum: 91aaccadd046fc1b60477df4f44bb69d61aeca81082f2ebf879a32ff25cd7bcb7067fcd69eb9a0987ca0a3e8e2d837b2737e80961c14a504a912bed4c51c8e3e languageName: node linkType: hard @@ -2916,7 +2925,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"table@npm:^6.0.4": +"table@npm:^6.0.9": version: 6.7.1 resolution: "table@npm:6.7.1" dependencies: @@ -2988,7 +2997,7 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"tsutils@npm:^3.17.1": +"tsutils@npm:^3.21.0": version: 3.21.0 resolution: "tsutils@npm:3.21.0" dependencies: @@ -3015,13 +3024,6 @@ discord-akairo@IRONM00N-Development/discord-akairo: languageName: node linkType: hard -"type-fest@npm:^0.8.1": - version: 0.8.1 - resolution: "type-fest@npm:0.8.1" - checksum: f8c4b4249f52e8bea7a4fc55b3653c96c2d547240e4c772e001d02b7cc38b8c3eb493ab9fbe985a76a203cd1aa7044776b728a71ba12bf36e7131f989597885b - languageName: node - linkType: hard - "type-is@npm:~1.6.17": version: 1.6.18 resolution: "type-is@npm:1.6.18" @@ -3033,26 +3035,26 @@ discord-akairo@IRONM00N-Development/discord-akairo: linkType: hard typescript@^4.2.4: - version: 4.2.4 - resolution: "typescript@npm:4.2.4" + version: 4.3.4 + resolution: "typescript@npm:4.3.4" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: edaede2fa77f56b7fba80ee624a2368ab1216e75b0434d968ccb47ab0a5e2f6d94f848b3b111c1237dd71e988cd376af26370dcdad3b94355c76e759f0dd0a1e + checksum: 9791c5fe98db6cb70ec0efad8d3d2eb957b9643ee600b90bff49267de69768d0d5f59c41a8fd731cfd63df1ccfb2cb25505a2015d7b39ac10ea51f605a058e16 languageName: node linkType: hard "typescript@patch:typescript@^4.2.4#builtin<compat/typescript>": - version: 4.2.4 - resolution: "typescript@patch:typescript@npm%3A4.2.4#builtin<compat/typescript>::version=4.2.4&hash=ddfc1b" + version: 4.3.4 + resolution: "typescript@patch:typescript@npm%3A4.3.4#builtin<compat/typescript>::version=4.3.4&hash=ddfc1b" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 64658fdf27872904641dcaacf925e6b5a52fb4aa4881a5a726fc78a11b76748423ce9e996dac42313729321061c4dd38a06108014f8d07b222dcff2687037186 + checksum: c8766e84a4f71e925cc059af8286cc7f41819fe821d433b90c83e9b36729cbda7a8e4be3292d8a1433cd717d529c93217d58d173418f43862290b206bd88b284 languageName: node linkType: hard -"underscore@npm:^1.7.0": +"underscore@npm:^1.13.1": version: 1.13.1 resolution: "underscore@npm:1.13.1" checksum: 19527b2db3d34f783c3f2db9716a2c1221fef2958866925545697c46f430f59d1b384b8105cc7e7c809bdf0dc9075f2bfff90b8fb270b9d3a6c58347de2dd79d @@ -3167,8 +3169,8 @@ typescript@^4.2.4: linkType: hard "ws@npm:^7.4.4, ws@npm:^7.4.6": - version: 7.4.6 - resolution: "ws@npm:7.4.6" + version: 7.5.0 + resolution: "ws@npm:7.5.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -3177,7 +3179,7 @@ typescript@^4.2.4: optional: true utf-8-validate: optional: true - checksum: ffeb626d92f14aa3a67aa3784824c1d290131e25d225f4ca6b1b6b6d7ea754fca67694d89a5b99b144382365e1bccf1f7ec2f92df56f0d25f44939b070452f06 + checksum: f9ac36310e795995f13ac7abff9c3b104b2460864de7f0b6233d285f62c6929529e24f386ff87740c3646f818fefa014be587371aa9a5a6fffae2cd9d1e9e008 languageName: node linkType: hard |