From bf25d050d494fc542d7dc33f84a105b580d35fd0 Mon Sep 17 00:00:00 2001 From: nightlxight <89344461+nightlxight@users.noreply.github.com> Date: Sun, 19 Sep 2021 09:02:20 +0300 Subject: [PATCH 001/107] Add ".replit" file(s) --- .replit | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .replit diff --git a/.replit b/.replit new file mode 100644 index 0000000..b7a497d --- /dev/null +++ b/.replit @@ -0,0 +1,2 @@ +language = "nodejs" +run = "node ." From 728d3d52c7f15548e8834b2074034b1320b4e061 Mon Sep 17 00:00:00 2001 From: nightlxight <89344461+nightlxight@users.noreply.github.com> Date: Sun, 19 Sep 2021 09:03:23 +0300 Subject: [PATCH 002/107] Add "Procfile" file(s) for Heroku hosting --- Procfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 Procfile diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..bda5aaa --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +worker: node . From 4ff84a1bd0ee0be194e6d1b47cba7ffa0b805335 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 1 Dec 2021 23:13:49 -0500 Subject: [PATCH 003/107] npm audit fix --- package-lock.json | 2871 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 2834 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index e9cc7c8..7edc575 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,2796 @@ { "name": "reactionrolebot", "version": "1.1.2", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "reactionrolebot", + "version": "1.1.2", + "license": "AGPL-3.0", + "dependencies": { + "discord.js": "^12.5.1", + "knex": "^0.20.13", + "lodash": "^4.17.20", + "sqlite3": "^4.1.1" + }, + "devDependencies": {} + }, + "node_modules/@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "node_modules/@discordjs/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/ajv": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/colorette": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", + "integrity": "sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/discord.js": { + "version": "12.5.1", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.1.tgz", + "integrity": "sha512-VwZkVaUAIOB9mKdca0I5MefPMTQJTNg0qdgi1huF3iwsFwJ0L5s/Y69AQe+iPmjuV6j9rtKoG0Ta0n9vgEIL6w==", + "deprecated": "no longer supported", + "dependencies": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.2", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.3.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getopts": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.2.5.tgz", + "integrity": "sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA==" + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/interpret": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.0.0.tgz", + "integrity": "sha512-e0/LknJ8wpMMhTiWcjivB+ESwIuvHnBSlBbmP/pSb8CQJldoj1p2qv7xGZ/+BtbTziYRFSz8OsvdbiX45LtYQA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/knex": { + "version": "0.20.13", + "resolved": "https://registry.npmjs.org/knex/-/knex-0.20.13.tgz", + "integrity": "sha512-YVl//Te0G5suc+d9KyeI6WuhtgVlxu6HXYQB+WqrccFkSZAbHqlqZlUMogYG3UoVq69c3kiFbbxgUNkrO0PVfg==", + "dependencies": { + "colorette": "1.1.0", + "commander": "^4.1.1", + "debug": "4.1.1", + "esm": "^3.2.25", + "getopts": "2.2.5", + "inherits": "~2.0.4", + "interpret": "^2.0.0", + "liftoff": "3.1.0", + "lodash": "^4.17.15", + "mkdirp": "^0.5.1", + "pg-connection-string": "2.1.0", + "tarn": "^2.0.0", + "tildify": "2.0.0", + "uuid": "^7.0.1", + "v8flags": "^3.1.3" + }, + "bin": { + "knex": "bin/cli.js" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "mssql": "^6.1.0", + "mysql": "^2.18.1", + "mysql2": "^2.1.0", + "pg": "^7.18.2", + "sqlite3": "^4.1.1" + }, + "peerDependenciesMeta": { + "mssql": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "sqlite3": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/uuid": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz", + "integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dependencies": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "dependencies": { + "mime-db": "1.43.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/needle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.3.tgz", + "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-pre-gyp": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", + "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", + "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", + "dependencies": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "node_modules/npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dependencies": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/pg-connection-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.1.0.tgz", + "integrity": "sha512-bhlV7Eq09JrRIvo1eKngpwuqKtJnNhZdpdOlvrPrA4dxqXPjxSrbNrfnIDmTpwMyRszrcV4kU5ZA4mMsQUrjdg==" + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prism-media": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.3.tgz", + "integrity": "sha512-fSrR66n0l6roW9Rx4rSLMyTPTjRTiXy5RVqDOurACQ6si1rKHHKDU5gwBJoCsIV0R3o9gi+K50akl/qyw1C74A==", + "peerDependencies": { + "@discordjs/opus": "^0.3.3", + "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0", + "node-opus": "^0.3.3", + "opusscript": "^0.0.7" + }, + "peerDependenciesMeta": { + "@discordjs/opus": { + "optional": true + }, + "ffmpeg-static": { + "optional": true + }, + "node-opus": { + "optional": true + }, + "opusscript": { + "optional": true + } + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/psl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", + "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "node_modules/signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sqlite3": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz", + "integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==", + "hasInstallScript": true, + "dependencies": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.11.0", + "request": "^2.87.0" + } + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "dependencies": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/tar/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/tarn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-2.0.0.tgz", + "integrity": "sha512-7rNMCZd3s9bhQh47ksAQd92ADFcJUjjbyOvyFjNLwTPpGieFHMC84S+LOzw0fx1uh6hnDz/19r8CPMnIjJlMMA==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tildify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", + "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8flags": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", + "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + }, "dependencies": { "@discordjs/collection": { "version": "0.1.6", @@ -1041,9 +3829,9 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, "json-schema-traverse": { "version": "0.4.1", @@ -1056,13 +3844,13 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", - "json-schema": "0.2.3", + "json-schema": "0.4.0", "verror": "1.10.0" } }, @@ -1116,9 +3904,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "make-iterator": { "version": "1.0.1", @@ -1476,9 +4264,9 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-root": { "version": "0.1.1", @@ -1511,7 +4299,8 @@ "prism-media": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.3.tgz", - "integrity": "sha512-fSrR66n0l6roW9Rx4rSLMyTPTjRTiXy5RVqDOurACQ6si1rKHHKDU5gwBJoCsIV0R3o9gi+K50akl/qyw1C74A==" + "integrity": "sha512-fSrR66n0l6roW9Rx4rSLMyTPTjRTiXy5RVqDOurACQ6si1rKHHKDU5gwBJoCsIV0R3o9gi+K50akl/qyw1C74A==", + "requires": {} }, "process-nextick-args": { "version": "2.0.1", @@ -1922,6 +4711,14 @@ } } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -1932,14 +4729,6 @@ "strip-ansi": "^3.0.0" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -1954,17 +4743,24 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "requires": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } } }, "tarn": { @@ -2157,9 +4953,10 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.1.tgz", - "integrity": "sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ==" + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", + "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", + "requires": {} }, "yallist": { "version": "3.1.1", From 37753d57029bec2591c4cee251a18ee2976424e0 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 1 Dec 2021 23:20:39 -0500 Subject: [PATCH 004/107] Update sqlite3 --- package-lock.json | 662 +--------------------------------------------- package.json | 3 +- 2 files changed, 10 insertions(+), 655 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7edc575..70c789f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "discord.js": "^12.5.1", "knex": "^0.20.13", "lodash": "^4.17.20", - "sqlite3": "^4.1.1" + "sqlite3": "^4.2.0" }, "devDependencies": {} }, @@ -50,17 +50,6 @@ "node": ">=6.5" } }, - "node_modules/ajv": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", - "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -131,22 +120,6 @@ "node": ">=0.10.0" } }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "engines": { - "node": ">=0.8" - } - }, "node_modules/assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -171,19 +144,6 @@ "node": ">= 4.5.0" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" - }, "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -252,19 +212,6 @@ "node": ">=0.10.0" } }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -324,11 +271,6 @@ "node": ">=0.10.0" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -431,17 +373,6 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -565,15 +496,6 @@ "node": ">=12.0.0" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -756,24 +678,6 @@ "node": ">=0.10.0" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, "node_modules/fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -855,14 +759,6 @@ "node": ">=0.10.0" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "engines": { - "node": "*" - } - }, "node_modules/fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -915,14 +811,6 @@ "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.2.5.tgz", "integrity": "sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA==" }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -970,27 +858,6 @@ "node": ">=0.10.0" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -1043,20 +910,6 @@ "node": ">=0.10.0" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1267,11 +1120,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, "node_modules/is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -1309,45 +1157,6 @@ "node": ">=0.10.0" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -1717,14 +1526,6 @@ "node": ">=0.10.0" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1910,11 +1711,6 @@ "node": ">=0.10.0" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "node_modules/pg-connection-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.1.0.tgz", @@ -1958,27 +1754,6 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "node_modules/psl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", - "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -2051,50 +1826,6 @@ "node": ">=0.10" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/resolve": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", @@ -2385,45 +2116,15 @@ } }, "node_modules/sqlite3": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz", - "integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", + "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", "hasInstallScript": true, "dependencies": { "nan": "^2.12.1", - "node-pre-gyp": "^0.11.0", - "request": "^2.87.0" - } - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" + "node-pre-gyp": "^0.11.0" } }, - "node_modules/sshpk/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "node_modules/static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -2587,29 +2288,6 @@ "node": ">=0.10.0" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", @@ -2681,14 +2359,6 @@ "node": ">=0.10.0" } }, - "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -2708,15 +2378,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/v8flags": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", @@ -2728,19 +2389,6 @@ "node": ">= 0.10" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -2820,17 +2468,6 @@ "event-target-shim": "^5.0.0" } }, - "ajv": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", - "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -2880,19 +2517,6 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -2908,16 +2532,6 @@ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -2973,21 +2587,6 @@ } } }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - }, - "dependencies": { - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - } - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3040,11 +2639,6 @@ "unset-value": "^1.0.0" } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -3128,14 +2722,6 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -3226,15 +2812,6 @@ "ws": "^7.3.1" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -3381,21 +2958,6 @@ } } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -3458,11 +3020,6 @@ "for-in": "^1.0.1" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -3509,14 +3066,6 @@ "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.2.5.tgz", "integrity": "sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA==" }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -3552,20 +3101,6 @@ "which": "^1.2.14" } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -3608,16 +3143,6 @@ "parse-passwd": "^1.0.0" } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3785,11 +3310,6 @@ "is-unc-path": "^1.0.0" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -3818,42 +3338,6 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -4137,11 +3621,6 @@ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4281,11 +3760,6 @@ "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "pg-connection-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.1.0.tgz", @@ -4307,21 +3781,6 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "psl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", - "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -4381,45 +3840,6 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - } - } - }, "resolve": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", @@ -4660,36 +4080,12 @@ } }, "sqlite3": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz", - "integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", + "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", "requires": { "nan": "^2.12.1", - "node-pre-gyp": "^0.11.0", - "request": "^2.87.0" - } - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "dependencies": { - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - } + "node-pre-gyp": "^0.11.0" } }, "static-extend": { @@ -4811,23 +4207,6 @@ "repeat-string": "^1.6.1" } }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", @@ -4885,14 +4264,6 @@ } } }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "requires": { - "punycode": "^2.1.0" - } - }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -4908,11 +4279,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, "v8flags": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", @@ -4921,16 +4287,6 @@ "homedir-polyfill": "^1.0.1" } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index 4299d3c..c133cb7 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,8 @@ "discord.js": "^12.5.1", "knex": "^0.20.13", "lodash": "^4.17.20", - "sqlite3": "^4.1.1" + "sqlite3": "^4.2.0" }, - "devDependencies": {}, "scripts": { "knex": "node_modules/knex/bin/cli.js", "test": "echo \"Error: no test specified\" && exit 1" From 152e38303fc678d36d41a45f10f0bb51ee7cdfe3 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 2 Dec 2021 00:04:20 -0500 Subject: [PATCH 005/107] (broken) Update Discord.js to v13 --- package-lock.json | 431 +++++++++++++++++++++++++++++++++------------- package.json | 2 +- 2 files changed, 316 insertions(+), 117 deletions(-) diff --git a/package-lock.json b/package-lock.json index 70c789f..f243df0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,17 +9,36 @@ "version": "1.1.2", "license": "AGPL-3.0", "dependencies": { - "discord.js": "^12.5.1", + "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", "sqlite3": "^4.2.0" + } + }, + "node_modules/@discordjs/builders": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.2.tgz", + "integrity": "sha512-/YRd11SrcluqXkKppq/FAVzLIPRVlIVmc6X8ZklspzMIHDtJ+A4W37D43SHvLdH//+NnK+SHW/WeOF4Ts54PeQ==", + "dependencies": { + "@sindresorhus/is": "^4.2.0", + "discord-api-types": "^0.24.0", + "ow": "^0.27.0", + "ts-mixer": "^6.0.0", + "tslib": "^2.3.1" }, - "devDependencies": {} + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } }, "node_modules/@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.3.2.tgz", + "integrity": "sha512-dMjLl60b2DMqObbH1MQZKePgWhsNe49XkKBZ0W5Acl5uVV43SN414i2QfZwRI7dXAqIn8pEWD2+XXQFn9KWxqg==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } }, "node_modules/@discordjs/form-data": { "version": "3.0.1", @@ -34,22 +53,53 @@ "node": ">= 6" } }, + "node_modules/@sapphire/async-queue": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.9.tgz", + "integrity": "sha512-CbXaGwwlEMq+l1TRu01FJCvySJ1CEFKFclHT48nIfNeZXaAAmmwwy7scUKmYHPUa3GhoMp6Qr1B3eAJux6XgOQ==", + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", + "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@types/node": { + "version": "16.11.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", + "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==" + }, + "node_modules/@types/node-fetch": { + "version": "2.5.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", + "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/ws": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.1.tgz", + "integrity": "sha512-SqQ+LhVZaJi7c7sYVkjWALDigi/Wy7h7Iu72gkQp8Y8OWw/DddEVBrTSKu86pQftV2+Gm8lYM61hadPKqyaIeg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -271,6 +321,14 @@ "node": ">=0.10.0" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -477,23 +535,46 @@ "node": ">=0.10" } }, + "node_modules/discord-api-types": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", + "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==", + "engines": { + "node": ">=12" + } + }, "node_modules/discord.js": { - "version": "12.5.1", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.1.tgz", - "integrity": "sha512-VwZkVaUAIOB9mKdca0I5MefPMTQJTNg0qdgi1huF3iwsFwJ0L5s/Y69AQe+iPmjuV6j9rtKoG0Ta0n9vgEIL6w==", - "deprecated": "no longer supported", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.3.1.tgz", + "integrity": "sha512-zn4G8tL5+tMV00+0aSsVYNYcIfMSdT2g0nudKny+Ikd+XKv7m6bqI7n3Vji0GIRqXDr5ArPaw+iYFM2I1Iw3vg==", "dependencies": { - "@discordjs/collection": "^0.1.6", + "@discordjs/builders": "^0.8.1", + "@discordjs/collection": "^0.3.2", "@discordjs/form-data": "^3.0.1", - "abort-controller": "^3.0.0", + "@sapphire/async-queue": "^1.1.8", + "@types/node-fetch": "^2.5.12", + "@types/ws": "^8.2.0", + "discord-api-types": "^0.24.0", "node-fetch": "^2.6.1", - "prism-media": "^1.2.2", - "setimmediate": "^1.0.5", - "tweetnacl": "^1.0.3", - "ws": "^7.3.1" + "ws": "^8.2.3" + }, + "engines": { + "node": ">=16.6.0", + "npm": ">=7.0.0" + } + }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dependencies": { + "is-obj": "^2.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/esm": { @@ -504,14 +585,6 @@ "node": ">=6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -759,6 +832,19 @@ "node": ">=0.10.0" } }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -1098,6 +1184,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -1248,6 +1342,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "node_modules/make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -1650,6 +1749,25 @@ "os-tmpdir": "^1.0.0" } }, + "node_modules/ow": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", + "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", + "dependencies": { + "@sindresorhus/is": "^4.0.1", + "callsites": "^3.1.0", + "dot-prop": "^6.0.1", + "lodash.isequal": "^4.5.0", + "type-fest": "^1.2.1", + "vali-date": "^1.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -1724,31 +1842,6 @@ "node": ">=0.10.0" } }, - "node_modules/prism-media": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.3.tgz", - "integrity": "sha512-fSrR66n0l6roW9Rx4rSLMyTPTjRTiXy5RVqDOurACQ6si1rKHHKDU5gwBJoCsIV0R3o9gi+K50akl/qyw1C74A==", - "peerDependencies": { - "@discordjs/opus": "^0.3.3", - "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0", - "node-opus": "^0.3.3", - "opusscript": "^0.0.7" - }, - "peerDependenciesMeta": { - "@discordjs/opus": { - "optional": true - }, - "ffmpeg-static": { - "optional": true - }, - "node-opus": { - "optional": true - }, - "opusscript": { - "optional": true - } - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -1935,11 +2028,6 @@ "node": ">=0.10.0" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, "node_modules/signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -2288,10 +2376,26 @@ "node": ">=0.10.0" } }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + "node_modules/ts-mixer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", + "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" + }, + "node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/unc-path-regex": { "version": "0.1.2", @@ -2389,6 +2493,14 @@ "node": ">= 0.10" } }, + "node_modules/vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -2414,11 +2526,11 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/ws": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", - "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz", + "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", @@ -2440,10 +2552,22 @@ } }, "dependencies": { + "@discordjs/builders": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.2.tgz", + "integrity": "sha512-/YRd11SrcluqXkKppq/FAVzLIPRVlIVmc6X8ZklspzMIHDtJ+A4W37D43SHvLdH//+NnK+SHW/WeOF4Ts54PeQ==", + "requires": { + "@sindresorhus/is": "^4.2.0", + "discord-api-types": "^0.24.0", + "ow": "^0.27.0", + "ts-mixer": "^6.0.0", + "tslib": "^2.3.1" + } + }, "@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.3.2.tgz", + "integrity": "sha512-dMjLl60b2DMqObbH1MQZKePgWhsNe49XkKBZ0W5Acl5uVV43SN414i2QfZwRI7dXAqIn8pEWD2+XXQFn9KWxqg==" }, "@discordjs/form-data": { "version": "3.0.1", @@ -2455,19 +2579,43 @@ "mime-types": "^2.1.12" } }, + "@sapphire/async-queue": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.9.tgz", + "integrity": "sha512-CbXaGwwlEMq+l1TRu01FJCvySJ1CEFKFclHT48nIfNeZXaAAmmwwy7scUKmYHPUa3GhoMp6Qr1B3eAJux6XgOQ==" + }, + "@sindresorhus/is": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", + "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==" + }, + "@types/node": { + "version": "16.11.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", + "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==" + }, + "@types/node-fetch": { + "version": "2.5.12", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", + "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "@types/ws": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.1.tgz", + "integrity": "sha512-SqQ+LhVZaJi7c7sYVkjWALDigi/Wy7h7Iu72gkQp8Y8OWw/DddEVBrTSKu86pQftV2+Gm8lYM61hadPKqyaIeg==", + "requires": { + "@types/node": "*" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -2639,6 +2787,11 @@ "unset-value": "^1.0.0" } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -2797,19 +2950,33 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, + "discord-api-types": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", + "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==" + }, "discord.js": { - "version": "12.5.1", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.1.tgz", - "integrity": "sha512-VwZkVaUAIOB9mKdca0I5MefPMTQJTNg0qdgi1huF3iwsFwJ0L5s/Y69AQe+iPmjuV6j9rtKoG0Ta0n9vgEIL6w==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.3.1.tgz", + "integrity": "sha512-zn4G8tL5+tMV00+0aSsVYNYcIfMSdT2g0nudKny+Ikd+XKv7m6bqI7n3Vji0GIRqXDr5ArPaw+iYFM2I1Iw3vg==", "requires": { - "@discordjs/collection": "^0.1.6", + "@discordjs/builders": "^0.8.1", + "@discordjs/collection": "^0.3.2", "@discordjs/form-data": "^3.0.1", - "abort-controller": "^3.0.0", + "@sapphire/async-queue": "^1.1.8", + "@types/node-fetch": "^2.5.12", + "@types/ws": "^8.2.0", + "discord-api-types": "^0.24.0", "node-fetch": "^2.6.1", - "prism-media": "^1.2.2", - "setimmediate": "^1.0.5", - "tweetnacl": "^1.0.3", - "ws": "^7.3.1" + "ws": "^8.2.3" + } + }, + "dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "requires": { + "is-obj": "^2.0.0" } }, "esm": { @@ -2817,11 +2984,6 @@ "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -3020,6 +3182,16 @@ "for-in": "^1.0.1" } }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -3294,6 +3466,11 @@ } } }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -3392,6 +3569,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -3717,6 +3899,19 @@ "os-tmpdir": "^1.0.0" } }, + "ow": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", + "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", + "requires": { + "@sindresorhus/is": "^4.0.1", + "callsites": "^3.1.0", + "dot-prop": "^6.0.1", + "lodash.isequal": "^4.5.0", + "type-fest": "^1.2.1", + "vali-date": "^1.0.0" + } + }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -3770,12 +3965,6 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, - "prism-media": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.3.tgz", - "integrity": "sha512-fSrR66n0l6roW9Rx4rSLMyTPTjRTiXy5RVqDOurACQ6si1rKHHKDU5gwBJoCsIV0R3o9gi+K50akl/qyw1C74A==", - "requires": {} - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -3929,11 +4118,6 @@ } } }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -4207,10 +4391,20 @@ "repeat-string": "^1.6.1" } }, - "tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + "ts-mixer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", + "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==" }, "unc-path-regex": { "version": "0.1.2", @@ -4287,6 +4481,11 @@ "homedir-polyfill": "^1.0.1" } }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=" + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -4309,9 +4508,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", - "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz", + "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==", "requires": {} }, "yallist": { diff --git a/package.json b/package.json index c133cb7..d45f066 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "I'm a basic, no BS Discord bot that can assign and unassign roles using message reactions. I am completely free and open source, and always will be.", "main": "main.js", "dependencies": { - "discord.js": "^12.5.1", + "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", "sqlite3": "^4.2.0" From 74410e2d6468f514bc69c2920d5d635cf66a78bc Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 2 Dec 2021 00:04:59 -0500 Subject: [PATCH 006/107] Fix client options so bot starts with djs 13 --- main.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/main.js b/main.js index 0eed78f..321517e 100644 --- a/main.js +++ b/main.js @@ -26,11 +26,24 @@ const info = require('./package.json'); // Everything operates on IDs, so we can safely rely on partials. // This causes reaction events to fire for uncached messages. const client = new Discord.Client({ + intents: [ + Discord.Intents.FLAGS.GUILDS, + Discord.Intents.FLAGS.GUILD_MEMBERS, + Discord.Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS, + Discord.Intents.FLAGS.GUILD_MESSAGES, + Discord.Intents.FLAGS.GUILD_MESSAGE_REACTIONS, + ], partials: [ Discord.Constants.PartialTypes.MESSAGE, Discord.Constants.PartialTypes.CHANNEL, Discord.Constants.PartialTypes.REACTION - ] + ], + presence: { + activities: [{ + name: `'help' for commands. Running version ${info.version}`, + type: Discord.Constants.ActivityTypes.LISTENING, + }], + }, }); const token_file = process.argv[2] || '/etc/discord/ReactionRoleBot/token'; const token = fs.readFileSync(token_file).toString().trim(); @@ -107,16 +120,6 @@ client.login(token).catch(err => { */ function onReady() { console.log(`Logged in as ${client.user.tag}`); - - // No idea why Discord.js does stuff like this... - // https://github.com/discordjs/discord.js/blob/master/src/util/Constants.js#L431 - const LISTENING = 2; - client.user.setPresence({ - activity: { - name: `'help' for commands. Running version ${info.version}`, - type: Discord.Constants.ActivityTypes[LISTENING] - } - }).catch(logError); } /** From 9efbfcc37393ab8cce80f164315b27fb46b50218 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 2 Dec 2021 00:36:56 -0500 Subject: [PATCH 007/107] Fix permission check so bot can respond to commands again --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index 321517e..da14736 100644 --- a/main.js +++ b/main.js @@ -749,7 +749,7 @@ function onReactionRemove(reaction, user) { function userHasPermission(msg, command_name) { const everyoneCommands = ['info']; if ( - msg.member.hasPermission(Discord.Permissions.FLAGS.ADMINISTRATOR) || + msg.member.permissions.has(Discord.Permissions.FLAGS.ADMINISTRATOR) || everyoneCommands.includes(command_name) ) { return Promise.resolve(true); From 1c5a86c25bf329392b33b182d140c5cdad214b0a Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 2 Dec 2021 00:48:23 -0500 Subject: [PATCH 008/107] Fix help embed --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index da14736..6599097 100644 --- a/main.js +++ b/main.js @@ -660,7 +660,7 @@ function sayHelp(msg) { def.get('usage'), def.get('description') )); - msg.reply(embed).catch(logError); + msg.reply({ embeds: [embed] }).catch(logError); } /** From feb4df1e1a9b27ca67ca9a18a1bebb851879cd5a Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 2 Dec 2021 00:49:36 -0500 Subject: [PATCH 009/107] Update regex to match newer, longer IDs --- main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index 6599097..26a29dd 100644 --- a/main.js +++ b/main.js @@ -782,7 +782,7 @@ function extractId(str) { return null; } - let match = str.match(/(\d{17,19})/); + let match = str.match(/(\d{17,22})/); return match ? match[1] : null; } @@ -797,7 +797,7 @@ function extractEmoji(emoji) { return null; } - let match = emoji.match(/<:.+:(\d{17,19})>/); + let match = emoji.match(/<:.+:(\d{17,22})>/); return match ? match[1] : emoji; } From e58fa7105997595a59bfb23e189a67a95678931c Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 2 Dec 2021 00:52:12 -0500 Subject: [PATCH 010/107] Bump major version, since this will now break on older nodejs versions --- README.md | 8 ++++++-- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1daa57d..51eb124 100644 --- a/README.md +++ b/README.md @@ -134,10 +134,14 @@ roles, since the bot needs to make several requests to make them work. The bot is registering the actions. Give it a few seconds to catch up. ## Hosting your own instance -This bot is built on [discord.js](https://discord.js.org/#/) v12, so you'll need -Node.js 12.0.0 (or newer) installed. You will also need your own Discord bot +This bot is built on [discord.js](https://discord.js.org/#/) v13, so you'll need +Node.js 16.6.0 (or newer) installed. You will also need your own Discord bot account. +If you're upgrading from an older Discord.js v12 version of the bot, the Node.js +16.6.0 requirement might be problematic. you might consider using something like +https://github.com/nvm-sh/nvm to make the transition easier. + The `resources` directory has a service file that can be used with Linux distros with systemd. If you're installing this on some other operating system, you're on your own. diff --git a/package-lock.json b/package-lock.json index f243df0..a91d94b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "reactionrolebot", - "version": "1.1.2", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index d45f066..b33e7ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "reactionrolebot", - "version": "1.1.2", + "version": "2.0.0", "description": "I'm a basic, no BS Discord bot that can assign and unassign roles using message reactions. I am completely free and open source, and always will be.", "main": "main.js", "dependencies": { From 5ac163d2caece4599e716e85f0943c4d95acf3d4 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 3 Dec 2021 03:05:11 -0500 Subject: [PATCH 011/107] package.json script for starting dev --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index b33e7ac..d001461 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "sqlite3": "^4.2.0" }, "scripts": { + "dev": "node main.js dev-token", "knex": "node_modules/knex/bin/cli.js", "test": "echo \"Error: no test specified\" && exit 1" }, From 26e9a4ed537f3f493281560d9ad542b2fc8eb7b8 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 3 Dec 2021 03:35:18 -0500 Subject: [PATCH 012/107] Use real logger instead of console.log --- logger.js | 56 +++++++ main.js | 9 +- package-lock.json | 374 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 3 +- 4 files changed, 435 insertions(+), 7 deletions(-) create mode 100644 logger.js diff --git a/logger.js b/logger.js new file mode 100644 index 0000000..2087c77 --- /dev/null +++ b/logger.js @@ -0,0 +1,56 @@ +/******************************************************************************* + * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * Copyright (C) 2020 Mimickal (Mia Moretti). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + ******************************************************************************/ +const Winston = require('winston'); + +const LOG_FILE_NAME = 'output.log'; +const IS_PROD = process.env.NODE_ENV === 'prod'; + + +const logger = Winston.createLogger(); + +const logFormat = Winston.format.combine( + Winston.format.timestamp(), + Winston.format.printf( ({ level, message, timestamp }) => { + return `${timestamp} [${level}]: ${message}`; + }), +); + +logger.add(new Winston.transports.File({ + filename: LOG_FILE_NAME, + format: logFormat, + level: IS_PROD ? 'info' : 'debug', +})); +logger.add(new Winston.transports.Console({ + format: Winston.format.combine( + Winston.format.colorize(), + logFormat, + ), + level: IS_PROD ? 'error' : 'debug', +})); + + +// Rolling our own unhandled exception and Promise rejection handlers, because +// Winston's built-in ones kind of suck. +function errStr(err) { + return err instanceof Error ? err.stack : err; +} +process.on('uncaughtExceptionMonitor', err => logger.error(errStr(err))); +process.on('unhandledRejection', + err => logger.error(`Unhandled Promise rejection: ${errStr(err)}`)); + + +module.exports = logger; diff --git a/main.js b/main.js index 26a29dd..555413e 100644 --- a/main.js +++ b/main.js @@ -20,6 +20,7 @@ const Discord = require('discord.js'); const cache = require('./cache'); const database = require('./database'); +const logger = require('./logger'); const info = require('./package.json'); @@ -119,7 +120,7 @@ client.login(token).catch(err => { * Event handler for when the bot is logged in. */ function onReady() { - console.log(`Logged in as ${client.user.tag}`); + logger.info(`Logged in as ${client.user.tag}`); } /** @@ -707,7 +708,7 @@ function onReactionAdd(reaction, user) { ) ) .then(() => database.incrementAssignCounter()) - .then(() => console.log(`added role ${roleId} to ${user}`)); + .then(() => logger.info(`added role ${roleId} to ${user}`)); }) .catch(logError); } @@ -737,7 +738,7 @@ function onReactionRemove(reaction, user) { return reaction.message.guild.members.fetch(user.id) .then(member => member.roles.remove(roleId, 'Role bot removal')) - .then(() => console.log(`removed role ${roleId} from ${user}`)) + .then(() => logger.info(`removed role ${roleId} from ${user}`)) }) .catch(logError); } @@ -842,6 +843,6 @@ function unindent(str) { * Maybe some day we'll do something more intelligent with errors. */ function logError(err) { - console.error(err); + logger.error(err); } diff --git a/package-lock.json b/package-lock.json index a91d94b..b87e15e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,13 +6,24 @@ "packages": { "": { "name": "reactionrolebot", - "version": "1.1.2", + "version": "2.0.0", "license": "AGPL-3.0", "dependencies": { "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", - "sqlite3": "^4.2.0" + "sqlite3": "^4.2.0", + "winston": "^3.3.3" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" } }, "node_modules/@discordjs/builders": { @@ -178,6 +189,11 @@ "node": ">=0.10.0" } }, + "node_modules/async": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -379,11 +395,59 @@ "node": ">=0.10.0" } }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/color-string": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.8.2.tgz", + "integrity": "sha512-w5ZkKRdLsc5NOYsmnpS2DpyRW71npwZGwbRpLrJTuqjfTs2Bhrba7UiV59IX9siBlCPl2pne5NtiwnVWUzvYFA==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/colorette": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", "integrity": "sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==" }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -577,6 +641,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, "node_modules/esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -751,6 +820,11 @@ "node": ">=0.10.0" } }, + "node_modules/fecha": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", + "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" + }, "node_modules/fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -813,6 +887,11 @@ "node": ">= 0.10" } }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -1076,6 +1155,11 @@ "node": ">=0.10.0" } }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -1214,6 +1298,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -1319,6 +1414,11 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, "node_modules/liftoff": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", @@ -1347,6 +1447,18 @@ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, + "node_modules/logform": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz", + "integrity": "sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==", + "dependencies": { + "colors": "^1.2.1", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^1.1.0", + "triple-beam": "^1.3.0" + } + }, "node_modules/make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -1724,6 +1836,14 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -1980,6 +2100,11 @@ "ret": "~0.1.10" } }, + "node_modules/safe-stable-stringify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", + "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==" + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -2033,6 +2158,14 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -2213,6 +2346,14 @@ "node-pre-gyp": "^0.11.0" } }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "engines": { + "node": "*" + } + }, "node_modules/static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -2320,6 +2461,11 @@ "node": ">=8.0.0" } }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "node_modules/tildify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", @@ -2376,6 +2522,11 @@ "node": ">=0.10.0" } }, + "node_modules/triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, "node_modules/ts-mixer": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", @@ -2520,6 +2671,50 @@ "string-width": "^1.0.2 || 2" } }, + "node_modules/winston": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "dependencies": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "engines": { + "node": ">= 6.4.0" + } + }, + "node_modules/winston-transport": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "dependencies": { + "readable-stream": "^2.3.7", + "triple-beam": "^1.2.0" + }, + "engines": { + "node": ">= 6.4.0" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2552,6 +2747,16 @@ } }, "dependencies": { + "@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "@discordjs/builders": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.2.tgz", @@ -2670,6 +2875,11 @@ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, + "async": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2832,11 +3042,56 @@ "object-visit": "^1.0.0" } }, + "color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "requires": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.8.2.tgz", + "integrity": "sha512-w5ZkKRdLsc5NOYsmnpS2DpyRW71npwZGwbRpLrJTuqjfTs2Bhrba7UiV59IX9siBlCPl2pne5NtiwnVWUzvYFA==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "colorette": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", "integrity": "sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==" }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "requires": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2979,6 +3234,11 @@ "is-obj": "^2.0.0" } }, + "enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, "esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -3120,6 +3380,11 @@ } } }, + "fecha": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", + "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -3169,6 +3434,11 @@ "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" }, + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -3382,6 +3652,11 @@ } } }, + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -3487,6 +3762,11 @@ "is-unc-path": "^1.0.0" } }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -3549,6 +3829,11 @@ } } }, + "kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, "liftoff": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", @@ -3574,6 +3859,18 @@ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, + "logform": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz", + "integrity": "sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==", + "requires": { + "colors": "^1.2.1", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^1.1.0", + "triple-beam": "^1.3.0" + } + }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -3880,6 +4177,14 @@ "wrappy": "1" } }, + "one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "requires": { + "fn.name": "1.x.x" + } + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -4077,6 +4382,11 @@ "ret": "~0.1.10" } }, + "safe-stable-stringify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", + "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==" + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -4123,6 +4433,14 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + } + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -4272,6 +4590,11 @@ "node-pre-gyp": "^0.11.0" } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -4348,6 +4671,11 @@ "resolved": "https://registry.npmjs.org/tarn/-/tarn-2.0.0.tgz", "integrity": "sha512-7rNMCZd3s9bhQh47ksAQd92ADFcJUjjbyOvyFjNLwTPpGieFHMC84S+LOzw0fx1uh6hnDz/19r8CPMnIjJlMMA==" }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "tildify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", @@ -4391,6 +4719,11 @@ "repeat-string": "^1.6.1" } }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, "ts-mixer": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", @@ -4502,6 +4835,43 @@ "string-width": "^1.0.2 || 2" } }, + "winston": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "requires": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "winston-transport": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "requires": { + "readable-stream": "^2.3.7", + "triple-beam": "^1.2.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index d001461..80e21bf 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", - "sqlite3": "^4.2.0" + "sqlite3": "^4.2.0", + "winston": "^3.3.3" }, "scripts": { "dev": "node main.js dev-token", From 11edfbeca58435f1686a05addc94ee9a9e348bd6 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 5 Dec 2021 05:35:46 -0500 Subject: [PATCH 013/107] .gitignore output log file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 780f313..a7d8a41 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules/ todo.txt +*.log *.swp dev.sqlite3 dev-token From 3764602d77428489a37010d0c995cb89b3496d16 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 5 Dec 2021 05:33:47 -0500 Subject: [PATCH 014/107] Use config json instead of raw token file --- .gitignore | 2 +- main.js | 7 ++++--- package.json | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index a7d8a41..f47b2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ todo.txt *.log *.swp dev.sqlite3 -dev-token +dev-config.json diff --git a/main.js b/main.js index 555413e..1b4b678 100644 --- a/main.js +++ b/main.js @@ -22,6 +22,9 @@ const cache = require('./cache'); const database = require('./database'); const logger = require('./logger'); +const config = JSON.parse(fs.readFileSync( + process.argv[2] || '/etc/discord/ReactionRoleBot/config.json' +)); const info = require('./package.json'); // Everything operates on IDs, so we can safely rely on partials. @@ -46,8 +49,6 @@ const client = new Discord.Client({ }], }, }); -const token_file = process.argv[2] || '/etc/discord/ReactionRoleBot/token'; -const token = fs.readFileSync(token_file).toString().trim(); // Map of command names to handling functions. Doubles as a validator. const COMMANDS = new Map(); @@ -111,7 +112,7 @@ client.on(Events.MESSAGE_REACTION_ADD, onReactionAdd); client.on(Events.MESSAGE_REACTION_REMOVE, onReactionRemove); -client.login(token).catch(err => { +client.login(config.token).catch(err => { logError(err); process.exit(1); }); diff --git a/package.json b/package.json index 80e21bf..c9340ea 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "winston": "^3.3.3" }, "scripts": { - "dev": "node main.js dev-token", + "dev": "node main.js dev-config.json", "knex": "node_modules/knex/bin/cli.js", "test": "echo \"Error: no test specified\" && exit 1" }, From 572d5550c9167e4e4cc6dce15c262ebd2927a04a Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 5 Dec 2021 06:26:45 -0500 Subject: [PATCH 015/107] Implement info slash command --- commands.js | 51 +++++++++++ main.js | 9 ++ package-lock.json | 224 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 4 files changed, 285 insertions(+) create mode 100644 commands.js diff --git a/commands.js b/commands.js new file mode 100644 index 0000000..191dbac --- /dev/null +++ b/commands.js @@ -0,0 +1,51 @@ +/******************************************************************************* + * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * Copyright (C) 2020 Mimickal (Mia Moretti). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + ******************************************************************************/ +const { SlashCommandRegistry } = require('discord-command-registry'); + +const database = require('./database'); +const info = require('./package.json'); + +const REGISTRY = new SlashCommandRegistry() + .addCommand(command => command + .setName('info') + .setDescription( + 'Prints description, version, and link to source code for the bot' + ) + .setHandler(cmdInfo) + ) +; + +/** + * Replies with info about this bot, including a link to the source code to be + * compliant with the AGPLv3 this bot is licensed under. + */ +async function cmdInfo(interaction) { + const stats = await database.getMetaStats(); + await interaction.reply( + `${info.description}\n` + + `**Running version:** ${info.version}\n` + + `**Source code:** ${info.homepage}\n\n` + + '```Stats For Nerds:\n' + + ` - Servers bot is active in: ${stats.guilds}\n` + + ` - Reaction role mappings: ${stats.roles}\n` + + ` - Total role assignments: ${stats.assignments}\n` + + '```' + ); +} + +module.exports = REGISTRY; + diff --git a/main.js b/main.js index 1b4b678..0932a00 100644 --- a/main.js +++ b/main.js @@ -19,6 +19,7 @@ const fs = require('fs'); const Discord = require('discord.js'); const cache = require('./cache'); +const commands = require('./commands'); const database = require('./database'); const logger = require('./logger'); @@ -107,6 +108,7 @@ const Events = Discord.Constants.Events; client.on(Events.CLIENT_READY, onReady); client.on(Events.GUILD_CREATE, onGuildJoin); client.on(Events.GUILD_DELETE, onGuildLeave); +client.on(Events.INTERACTION_CREATE, onInteraction); client.on(Events.MESSAGE_CREATE, onMessage); client.on(Events.MESSAGE_REACTION_ADD, onReactionAdd); client.on(Events.MESSAGE_REACTION_REMOVE, onReactionRemove); @@ -177,6 +179,13 @@ function onGuildLeave(guild) { .catch(logError); } +/** + * Event handler for getting a new slash commands. + */ +function onInteraction(interaction) { + commands.execute(interaction); +} + /** * Event handler for getting a new message. * Parses and delegates any role bot command. diff --git a/package-lock.json b/package-lock.json index b87e15e..7608f9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "2.0.0", "license": "AGPL-3.0", "dependencies": { + "discord-command-registry": "^1.1.1", "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", @@ -64,6 +65,51 @@ "node": ">= 6" } }, + "node_modules/@discordjs/rest": { + "version": "0.1.0-canary.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-0.1.0-canary.0.tgz", + "integrity": "sha512-d+s//ISYVV+e0w/926wMEeO7vju+Pn11x1JM4tcmVMCHSDgpi6pnFCNAXF1TEdnDcy7xf9tq5cf2pQkb/7ySTQ==", + "dependencies": { + "@discordjs/collection": "^0.1.6", + "@sapphire/async-queue": "^1.1.4", + "@sapphire/snowflake": "^1.3.5", + "abort-controller": "^3.0.0", + "discord-api-types": "^0.18.1", + "form-data": "^4.0.0", + "node-fetch": "^2.6.1", + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@discordjs/rest/node_modules/@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "node_modules/@discordjs/rest/node_modules/discord-api-types": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.18.1.tgz", + "integrity": "sha512-hNC38R9ZF4uaujaZQtQfm5CdQO58uhdkoHQAVvMfIL0LgOSZeW575W8H6upngQOuoxWd8tiRII3LLJm9zuQKYg==", + "deprecated": "No longer supported. Install the latest release (0.20.2)", + "engines": { + "node": ">=12" + } + }, + "node_modules/@discordjs/rest/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@sapphire/async-queue": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.9.tgz", @@ -73,6 +119,16 @@ "npm": ">=7.0.0" } }, + "node_modules/@sapphire/snowflake": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-1.3.6.tgz", + "integrity": "sha512-QnzuLp+p9D7agynVub/zqlDVriDza9y3STArBhNiNBUgIX8+GL5FpQxstRfw1jDr5jkZUjcuKYAHxjIuXKdJAg==", + "deprecated": "This version has been automatically deprecated by @favware/npm-deprecate. Please use a newer version.", + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, "node_modules/@sindresorhus/is": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", @@ -111,6 +167,17 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -607,6 +674,51 @@ "node": ">=12" } }, + "node_modules/discord-command-registry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/discord-command-registry/-/discord-command-registry-1.1.1.tgz", + "integrity": "sha512-013woGdZBTv5bQefeuxIpmddx9cjDTD9ItOYYGKBm8+4tZg5pwM7n4QKxdbW9wiGb2UivZvXc3mTA9w1lS2eLw==", + "dependencies": { + "@discordjs/builders": "^0.9.0", + "@discordjs/rest": "^0.1.0-canary.0", + "discord-api-types": "^0.25.2" + }, + "peerDependencies": { + "discord.js": "^13.1.0" + } + }, + "node_modules/discord-command-registry/node_modules/@discordjs/builders": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.9.0.tgz", + "integrity": "sha512-XM/5yrTxMF0SDKza32YzGDQO1t+qEJTaF8Zvxu/UOjzoqzMPPGQBjC1VgZxz8/CBLygW5qI+UVygMa88z13G3g==", + "dependencies": { + "@sindresorhus/is": "^4.2.0", + "discord-api-types": "^0.24.0", + "ts-mixer": "^6.0.0", + "tslib": "^2.3.1", + "zod": "^3.11.6" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/discord-command-registry/node_modules/@discordjs/builders/node_modules/discord-api-types": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", + "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==", + "engines": { + "node": ">=12" + } + }, + "node_modules/discord-command-registry/node_modules/discord-api-types": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.25.2.tgz", + "integrity": "sha512-O243LXxb5gLLxubu5zgoppYQuolapGVWPw3ll0acN0+O8TnPUE2kFp9Bt3sTRYodw8xFIknOVxjSeyWYBpVcEQ==", + "engines": { + "node": ">=12" + } + }, "node_modules/discord.js": { "version": "13.3.1", "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.3.1.tgz", @@ -654,6 +766,14 @@ "node": ">=6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -2744,6 +2864,14 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/zod": { + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.11.6.tgz", + "integrity": "sha512-daZ80A81I3/9lIydI44motWe6n59kRBfNzTuS2bfzVh1nAXi667TOTWWtatxyG+fwgNUiagSj/CWZwRRbevJIg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } }, "dependencies": { @@ -2784,11 +2912,53 @@ "mime-types": "^2.1.12" } }, + "@discordjs/rest": { + "version": "0.1.0-canary.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-0.1.0-canary.0.tgz", + "integrity": "sha512-d+s//ISYVV+e0w/926wMEeO7vju+Pn11x1JM4tcmVMCHSDgpi6pnFCNAXF1TEdnDcy7xf9tq5cf2pQkb/7ySTQ==", + "requires": { + "@discordjs/collection": "^0.1.6", + "@sapphire/async-queue": "^1.1.4", + "@sapphire/snowflake": "^1.3.5", + "abort-controller": "^3.0.0", + "discord-api-types": "^0.18.1", + "form-data": "^4.0.0", + "node-fetch": "^2.6.1", + "tslib": "^2.3.0" + }, + "dependencies": { + "@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "discord-api-types": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.18.1.tgz", + "integrity": "sha512-hNC38R9ZF4uaujaZQtQfm5CdQO58uhdkoHQAVvMfIL0LgOSZeW575W8H6upngQOuoxWd8tiRII3LLJm9zuQKYg==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "@sapphire/async-queue": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.9.tgz", "integrity": "sha512-CbXaGwwlEMq+l1TRu01FJCvySJ1CEFKFclHT48nIfNeZXaAAmmwwy7scUKmYHPUa3GhoMp6Qr1B3eAJux6XgOQ==" }, + "@sapphire/snowflake": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-1.3.6.tgz", + "integrity": "sha512-QnzuLp+p9D7agynVub/zqlDVriDza9y3STArBhNiNBUgIX8+GL5FpQxstRfw1jDr5jkZUjcuKYAHxjIuXKdJAg==" + }, "@sindresorhus/is": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", @@ -2821,6 +2991,14 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -3210,6 +3388,42 @@ "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==" }, + "discord-command-registry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/discord-command-registry/-/discord-command-registry-1.1.1.tgz", + "integrity": "sha512-013woGdZBTv5bQefeuxIpmddx9cjDTD9ItOYYGKBm8+4tZg5pwM7n4QKxdbW9wiGb2UivZvXc3mTA9w1lS2eLw==", + "requires": { + "@discordjs/builders": "^0.9.0", + "@discordjs/rest": "^0.1.0-canary.0", + "discord-api-types": "^0.25.2" + }, + "dependencies": { + "@discordjs/builders": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.9.0.tgz", + "integrity": "sha512-XM/5yrTxMF0SDKza32YzGDQO1t+qEJTaF8Zvxu/UOjzoqzMPPGQBjC1VgZxz8/CBLygW5qI+UVygMa88z13G3g==", + "requires": { + "@sindresorhus/is": "^4.2.0", + "discord-api-types": "^0.24.0", + "ts-mixer": "^6.0.0", + "tslib": "^2.3.1", + "zod": "^3.11.6" + }, + "dependencies": { + "discord-api-types": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", + "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==" + } + } + }, + "discord-api-types": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.25.2.tgz", + "integrity": "sha512-O243LXxb5gLLxubu5zgoppYQuolapGVWPw3ll0acN0+O8TnPUE2kFp9Bt3sTRYodw8xFIknOVxjSeyWYBpVcEQ==" + } + } + }, "discord.js": { "version": "13.3.1", "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.3.1.tgz", @@ -3244,6 +3458,11 @@ "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -4887,6 +5106,11 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "zod": { + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.11.6.tgz", + "integrity": "sha512-daZ80A81I3/9lIydI44motWe6n59kRBfNzTuS2bfzVh1nAXi667TOTWWtatxyG+fwgNUiagSj/CWZwRRbevJIg==" } } } diff --git a/package.json b/package.json index c9340ea..821360e 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "I'm a basic, no BS Discord bot that can assign and unassign roles using message reactions. I am completely free and open source, and always will be.", "main": "main.js", "dependencies": { + "discord-command-registry": "^1.1.1", "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", From 6382d1b2bc0b36118d875436e8ff7c1aa9a5ba13 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 5 Dec 2021 06:27:18 -0500 Subject: [PATCH 016/107] Add script for registering slash commands --- package.json | 1 + register.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 register.js diff --git a/package.json b/package.json index 821360e..9d9c230 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "scripts": { "dev": "node main.js dev-config.json", "knex": "node_modules/knex/bin/cli.js", + "register": "node register.js", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { diff --git a/register.js b/register.js new file mode 100644 index 0000000..ee1e107 --- /dev/null +++ b/register.js @@ -0,0 +1,56 @@ +/******************************************************************************* + * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * Copyright (C) 2020 Mimickal (Mia Moretti). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + ******************************************************************************/ +const fs = require('fs'); +const path = require('path'); + +const logger = require('./logger'); +const registry = require('./commands'); + +const WHAT_AM_I = ` +Registers slash commands with Discord's API. This only needs to be done once +after commands are updated. Updating commands globally can take some time to +propagate! For testing, use guild-specific commands (set guild_id in config). +`; + +if (!process.argv[2]) { + console.log(`Usage: ${ + process.argv.slice(0, 2).map(x => path.basename(x)).join(' ') + } \n${WHAT_AM_I}`); + process.exit(); +} + +const config = JSON.parse(fs.readFileSync(process.argv[2])); + +let output = 'Registering commmands '; +if (config.guild_id) { + output += `in guild ${config.guild_id}`; +} else { + output += 'GLOBALLY'; +} +output += ` for application ${config.app_id}...`; +logger.info(output); + +registry.registerCommands({ + application_id: config.app_id, + guild: config.guild_id, + token: config.token, +}) + .then(got_back => logger.info(`Successfully registered commands! Got data: ${ + JSON.stringify(got_back) + }`)) + .catch(err => logger.error(`Error registering commands:`, err)); + From 8078d69b5ff2fabae9ef906bd3d6b37b3155b889 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 5 Dec 2021 06:35:48 -0500 Subject: [PATCH 017/107] Update README to reflect new config changes --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 51eb124..546e3db 100644 --- a/README.md +++ b/README.md @@ -161,8 +161,14 @@ npm install NODE_ENV=prod npm run knex migrate:latest ``` -Create a file `/etc/discord/ReactionRoleBot/token` and paste your bot token in, -in plain text. +Create a file `/etc/discord/ReactionRoleBot/config.json` and paste in the +following (obviously fill in the blanks with your bot's info): +```json +{ + "token": "", + "app_id": "" +} +``` Install `reactionrolebot.service` into `/etc/systemd/system/`. @@ -180,4 +186,4 @@ npm run knex migrate:latest Create a file containing your bot token in plain text. -Run this to start the bot: `node main.js path/to/your/token` +Run this to start the bot: `node main.js path/to/your/config` From 4f653324eafbff4c0c8b34335efb6ae93c9fb0a8 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 12 Dec 2021 08:46:57 -0500 Subject: [PATCH 018/107] Commands for selecting and showing selected messages --- commands.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++- package-lock.json | 25 +++++++++++++++++------- package.json | 3 ++- 3 files changed, 67 insertions(+), 9 deletions(-) diff --git a/commands.js b/commands.js index 191dbac..a25fc7e 100644 --- a/commands.js +++ b/commands.js @@ -14,11 +14,17 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const { SlashCommandRegistry } = require('discord-command-registry'); +const { + ApplicationCommandType, + SlashCommandRegistry, +} = require('discord-command-registry'); +const SELECTED_MESSAGE_CACHE = require('memory-cache'); const database = require('./database'); const info = require('./package.json'); +const ONE_HOUR_IN_MS = 60*60*1000; + const REGISTRY = new SlashCommandRegistry() .addCommand(command => command .setName('info') @@ -27,6 +33,16 @@ const REGISTRY = new SlashCommandRegistry() ) .setHandler(cmdInfo) ) + .addContextMenuCommand(command => command + .setName('select-message') + .setType(ApplicationCommandType.Message) + .setHandler(cmdSelect) + ) + .addCommand(command => command + .setName('selected') + .setDescription('Shows currently selected message') + .setHandler(cmdSelected) + ) ; /** @@ -47,5 +63,35 @@ async function cmdInfo(interaction) { ); } +/** + * Saves a user's selected message for subsequent actions. + */ +async function cmdSelect(interaction) { + const user = interaction.user; + const message = interaction.options.getMessage('message', true); + + // Always clear selected message first, just to be safe and consistent. + SELECTED_MESSAGE_CACHE.del(user.id); + SELECTED_MESSAGE_CACHE.put(user.id, message, ONE_HOUR_IN_MS); + + return interaction.reply({ + content: `Selected message: ${message.url}`, + ephemeral: true, + }); +} + +/** + * Shows a user their currently selected message. + */ +async function cmdSelected(interaction) { + const message = SELECTED_MESSAGE_CACHE.get(interaction.user.id); + return interaction.reply({ + content: message + ? `Currently selected: ${message.url}` + : 'No message currently selected', + ephemeral: true, + }); +} + module.exports = REGISTRY; diff --git a/package-lock.json b/package-lock.json index 7608f9d..df0b447 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,11 @@ "version": "2.0.0", "license": "AGPL-3.0", "dependencies": { - "discord-command-registry": "^1.1.1", + "discord-command-registry": "^1.2.0", "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", + "memory-cache": "^0.2.0", "sqlite3": "^4.2.0", "winston": "^3.3.3" } @@ -675,9 +676,9 @@ } }, "node_modules/discord-command-registry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/discord-command-registry/-/discord-command-registry-1.1.1.tgz", - "integrity": "sha512-013woGdZBTv5bQefeuxIpmddx9cjDTD9ItOYYGKBm8+4tZg5pwM7n4QKxdbW9wiGb2UivZvXc3mTA9w1lS2eLw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/discord-command-registry/-/discord-command-registry-1.2.0.tgz", + "integrity": "sha512-HqZd4owQ/prvhEDI60TbD2YqOhJ4HLFjBGUr9zPHcO0Aihvphn6RfAAc1Xqzad9rbsxGOcaTYBRFOpMtklVwgw==", "dependencies": { "@discordjs/builders": "^0.9.0", "@discordjs/rest": "^0.1.0-canary.0", @@ -1609,6 +1610,11 @@ "node": ">=0.10.0" } }, + "node_modules/memory-cache": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", + "integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo=" + }, "node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -3389,9 +3395,9 @@ "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==" }, "discord-command-registry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/discord-command-registry/-/discord-command-registry-1.1.1.tgz", - "integrity": "sha512-013woGdZBTv5bQefeuxIpmddx9cjDTD9ItOYYGKBm8+4tZg5pwM7n4QKxdbW9wiGb2UivZvXc3mTA9w1lS2eLw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/discord-command-registry/-/discord-command-registry-1.2.0.tgz", + "integrity": "sha512-HqZd4owQ/prvhEDI60TbD2YqOhJ4HLFjBGUr9zPHcO0Aihvphn6RfAAc1Xqzad9rbsxGOcaTYBRFOpMtklVwgw==", "requires": { "@discordjs/builders": "^0.9.0", "@discordjs/rest": "^0.1.0-canary.0", @@ -4111,6 +4117,11 @@ "object-visit": "^1.0.0" } }, + "memory-cache": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", + "integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo=" + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", diff --git a/package.json b/package.json index 9d9c230..3c1902a 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,11 @@ "description": "I'm a basic, no BS Discord bot that can assign and unassign roles using message reactions. I am completely free and open source, and always will be.", "main": "main.js", "dependencies": { - "discord-command-registry": "^1.1.1", + "discord-command-registry": "^1.2.0", "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", + "memory-cache": "^0.2.0", "sqlite3": "^4.2.0", "winston": "^3.3.3" }, From b3abccf87e210a30a924495518a4653bde29fe9b Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 12 Dec 2021 08:58:47 -0500 Subject: [PATCH 019/107] The problem with referencing code constants in migrations has become apparent. --- migrations/20200225015300_db.js | 15 ++++++++------- migrations/20200814190000_meta.js | 8 ++++---- migrations/20200815043000_perms.js | 11 ++++++----- migrations/20200818203000_mutex.js | 13 +++++++------ 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/migrations/20200225015300_db.js b/migrations/20200225015300_db.js index 92f9254..32ba02a 100644 --- a/migrations/20200225015300_db.js +++ b/migrations/20200225015300_db.js @@ -14,20 +14,21 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const db = require('../database'); +const DISCORD_ID_MAX = 19; +const REACTS = 'reacts'; exports.up = function(knex) { - return knex.schema.createTable(db.REACTS, table => { - table.string('guild_id', db.DISCORD_ID_LENGTH.MAX); - table.string('message_id', db.DISCORD_ID_LENGTH.MAX); - table.string('emoji_id', db.DISCORD_ID_LENGTH.MAX); - table.string('role_id', db.DISCORD_ID_LENGTH.MAX); + return knex.schema.createTable(REACTS, table => { + table.string('guild_id', DISCORD_ID_MAX); + table.string('message_id', DISCORD_ID_MAX); + table.string('emoji_id', DISCORD_ID_MAX); + table.string('role_id', DISCORD_ID_MAX); table.primary(['message_id', 'emoji_id']); }); }; exports.down = function(knex) { - return knex.schema.dropTable(db.REACTS); + return knex.schema.dropTable(REACTS); }; diff --git a/migrations/20200814190000_meta.js b/migrations/20200814190000_meta.js index 90957cb..3b72acb 100644 --- a/migrations/20200814190000_meta.js +++ b/migrations/20200814190000_meta.js @@ -14,18 +14,18 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const db = require('../database'); +const META = 'meta'; exports.up = function(knex) { - return knex.schema.createTable(db.META, table => { + return knex.schema.createTable(META, table => { table.integer('assignments'); }).then(() => { // There will only ever be one row in this table so we make it here. - return knex(db.META).insert({ assignments: 0 }); + return knex(META).insert({ assignments: 0 }); }); }; exports.down = function(knex) { - return knex.schema.dropTable(db.META); + return knex.schema.dropTable(META); }; diff --git a/migrations/20200815043000_perms.js b/migrations/20200815043000_perms.js index 381680e..01a1339 100644 --- a/migrations/20200815043000_perms.js +++ b/migrations/20200815043000_perms.js @@ -14,18 +14,19 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const db = require('../database'); +const DISCORD_ID_MAX = 19; +const PERMS = 'perms'; exports.up = function(knex) { - return knex.schema.createTable(db.PERMS, table => { - table.string('guild_id', db.DISCORD_ID_LENGTH.MAX); - table.string('role_id', db.DISCORD_ID_LENGTH.MAX); + return knex.schema.createTable(PERMS, table => { + table.string('guild_id', DISCORD_ID_MAX); + table.string('role_id', DISCORD_ID_MAX); table.primary(['guild_id', 'role_id']); }); }; exports.down = function(knex) { - return knex.schema.dropTable(db.PERMS); + return knex.schema.dropTable(PERMS); }; diff --git a/migrations/20200818203000_mutex.js b/migrations/20200818203000_mutex.js index c869b34..94a2ce5 100644 --- a/migrations/20200818203000_mutex.js +++ b/migrations/20200818203000_mutex.js @@ -14,19 +14,20 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const db = require('../database'); +const DISCORD_ID_MAX = 19; +const MUTEX = 'mutex'; exports.up = function(knex) { - return knex.schema.createTable(db.MUTEX, table => { - table.string('guild_id', db.DISCORD_ID_LENGTH.MAX); - table.string('role_id_1', db.DISCORD_ID_LENGTH.MAX); - table.string('role_id_2', db.DISCORD_ID_LENGTH.MAX); + return knex.schema.createTable(MUTEX, table => { + table.string('guild_id', DISCORD_ID_MAX); + table.string('role_id_1', DISCORD_ID_MAX); + table.string('role_id_2', DISCORD_ID_MAX); table.primary(['guild_id', 'role_id_1', 'role_id_2']); }); }; exports.down = function(knex) { - return knex.schema.dropTable(db.MUTEX); + return knex.schema.dropTable(MUTEX); }; From 64ed062d57686001705b3f97f789d1113e4fb899 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 24 Dec 2021 17:27:23 -0500 Subject: [PATCH 020/107] Slash command for adding role react --- commands.js | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++ util.js | 38 +++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 util.js diff --git a/commands.js b/commands.js index a25fc7e..9ab06b4 100644 --- a/commands.js +++ b/commands.js @@ -16,12 +16,15 @@ ******************************************************************************/ const { ApplicationCommandType, + Options, SlashCommandRegistry, } = require('discord-command-registry'); const SELECTED_MESSAGE_CACHE = require('memory-cache'); const database = require('./database'); const info = require('./package.json'); +const logger = require('./logger'); +const { emojiToKey } = require('./util'); const ONE_HOUR_IN_MS = 60*60*1000; @@ -43,6 +46,25 @@ const REGISTRY = new SlashCommandRegistry() .setDescription('Shows currently selected message') .setHandler(cmdSelected) ) + .addCommand(command => command + .setName('role') + .setDescription('Manage react roles') + .addSubcommand(subcommand => subcommand + .setName('add') + .setDescription('Add a new react-role to the selected message') + .setHandler(cmdRoleAdd) + .addStringOption(option => option + .setName('emoji') + .setDescription('The emoji to map the role to') + .setRequired(true) + ) + .addRoleOption(option => option + .setName('role') + .setDescription('The role to map the emoji to') + .setRequired(true) + ) + ) + ) ; /** @@ -93,5 +115,81 @@ async function cmdSelected(interaction) { }); } +/** + * Map an emoji reaction with a role on the currently selected message. + */ +async function cmdRoleAdd(interaction) { + const emoji = Options.getEmoji(interaction, 'emoji', true); + const role = interaction.options.getRole('role', true); + let message = SELECTED_MESSAGE_CACHE.get(interaction.user.id); + + if (!message) { + return interaction.reply({ + content: 'No message selected! Select a message first.', + ephemeral: true, + }); + } + + if (!emoji) { + return interaction.reply({ + content: 'Not a valid emoji!', + ephemeral: true, + }); + } + + message = await message.fetch(); + + // Prevent someone from modifying a server from outside the server. + if (interaction.guild !== message.guild || interaction.guild !== role.guild) { + // TODO use unindent + return interaction.reply({ + content: + 'Message and Role need to be in the same Server ' + + 'this command was issued from', + ephemeral: true, + }); + } + + // Try to add this mapping to the database. + const db_data = { + guild_id: interaction.guild.id, + message_id: message.id, + emoji_id: emojiToKey(emoji), + role_id: role.id, + }; + try { + await database.addRoleReact(db_data); + } catch (err) { + logger.error(`Database failed to create ${JSON.stringify(db_data)}`, err); + return interaction.reply({ + content: 'Something went wrong', + ephemeral: true, + }); + } + + // Try to add the emoji to the selected message. If this fails, also remove + // the created mapping from the database so this fails safe. + try { + await message.react(emoji); + } catch (err) { + logger.warn(`Could not add emoji ${emoji} to message ${message.url}`, err); + // FIXME use a transaction for this. This involves database work so + // maybe hold off until we have fully replace message commands with + // slash commands. + await database.removeRoleReact(db_data); + return interaction.reply({ + content: + 'I could not react to your selected message. Do I have the ' + + 'right permissions?', + ephemeral: true, + }); + } + + return interaction.reply({ + content: `Mapped ${emoji} to ${role} on message ${message.url}`, + ephemeral: true, + }); +} + module.exports = REGISTRY; diff --git a/util.js b/util.js new file mode 100644 index 0000000..fc0935a --- /dev/null +++ b/util.js @@ -0,0 +1,38 @@ +/******************************************************************************* + * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * Copyright (C) 2020 Mimickal (Mia Moretti). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + ******************************************************************************/ + +/** + * Converts an emoji to a string we can use as a key (e.g. in a database). + * + * - Custom emojis (animated or otherwise) return their Discord ID. + * - Built-in emojis are already strings, and so we return them as-is. + * - Non-emoji strings are considered an error and will throw accordingly. + */ +function emojiToKey(emoji) { + if (emoji?.id) { + return emoji.id; + } else if (emoji?.match(/^\p{Extended_Pictographic}$/u)) { + return emoji; + } else { + throw Error(`Not an emoji key: ${emoji}`); + } +} + +module.exports = { + emojiToKey, +}; + From e64ebdd7012fa1fe19069557a991150477d5b39c Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 24 Dec 2021 17:29:32 -0500 Subject: [PATCH 021/107] Slash command for removing react roles --- commands.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/commands.js b/commands.js index 9ab06b4..4fc5b14 100644 --- a/commands.js +++ b/commands.js @@ -64,6 +64,16 @@ const REGISTRY = new SlashCommandRegistry() .setRequired(true) ) ) + .addSubcommand(subcommand => subcommand + .setName('remove') + .setDescription('Remove a react-role from the selected message') + .setHandler(cmdRoleRemove) + .addStringOption(option => option + .setName('emoji') + .setDescription('The emoji mapping to remove') + .setRequired(true) + ) + ) ) ; @@ -191,5 +201,52 @@ async function cmdRoleAdd(interaction) { }); } +/** + * Removes an emoji mapping from the currently selected message. + */ +async function cmdRoleRemove(interaction) { + const emoji = Options.getEmoji(interaction, 'emoji', true); + let message = SELECTED_MESSAGE_CACHE.get(interaction.user.id); + + if (!message) { + return interaction.reply({ + content: 'No message selected! Select a message first.', + ephemeral: true, + }); + } + + if (!emoji) { + return interaction.reply({ + content: 'Not a valid emoji!', + ephemeral: true, + }); + } + + message = await message.fetch(); + + try { + const emoji_id = emojiToKey(emoji); + + // Intentionally NOT removing this role from users who currently have it + // FIXME need a transaction here too + await database.removeRoleReact({ + message_id: message.id, + emoji_id: emoji_id, + }); + await message.reactions.cache.get(emoji_id).remove(); + } catch (err) { + logger.error(`Could not remove emoji ${emoji} from message ${message.url}`, err); + return interaction.reply({ + content: 'I could not remove the react. Do I have the right permissions?', + ephemeral: true, + }); + } + + return interaction.reply({ + content: `Removed ${emoji} from message ${message.url}`, + ephemeral: true, + }); +} + module.exports = REGISTRY; From 74de670757f79dd7971d27f608b696334a1565d5 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 24 Dec 2021 17:30:18 -0500 Subject: [PATCH 022/107] Some guiding principles for modifying command handlers --- commands.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/commands.js b/commands.js index 4fc5b14..5b00814 100644 --- a/commands.js +++ b/commands.js @@ -14,6 +14,24 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ + +// Some notes for this file: +// +// - Always call message.fetch(). +// This ensures Discord.js' caches (e.g. for reactions) are populated and up +// to date before doing anything. +// +// - Always fail safe. +// If any part of an operation fails, every action taken during that +// operation should be rolled back. +// +// - UI updates should come last. +// Updating what the user sees (e.g. sending message, adding a reaction) +// should always be done after other actions. Discord's client already shows +// a spinner while the bot is active, so we only need to confirm success or +// failure. +// The only exception to this is committing an active database transaction. + const { ApplicationCommandType, Options, From 6b85735b88b04ef67f1f69e175eb7365ad8fa8a7 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 12 Dec 2021 08:58:47 -0500 Subject: [PATCH 023/107] The problem with referencing code constants in migrations has become apparent. --- migrations/20200225015300_db.js | 15 ++++++++------- migrations/20200814190000_meta.js | 8 ++++---- migrations/20200815043000_perms.js | 11 ++++++----- migrations/20200818203000_mutex.js | 13 +++++++------ 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/migrations/20200225015300_db.js b/migrations/20200225015300_db.js index 92f9254..32ba02a 100644 --- a/migrations/20200225015300_db.js +++ b/migrations/20200225015300_db.js @@ -14,20 +14,21 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const db = require('../database'); +const DISCORD_ID_MAX = 19; +const REACTS = 'reacts'; exports.up = function(knex) { - return knex.schema.createTable(db.REACTS, table => { - table.string('guild_id', db.DISCORD_ID_LENGTH.MAX); - table.string('message_id', db.DISCORD_ID_LENGTH.MAX); - table.string('emoji_id', db.DISCORD_ID_LENGTH.MAX); - table.string('role_id', db.DISCORD_ID_LENGTH.MAX); + return knex.schema.createTable(REACTS, table => { + table.string('guild_id', DISCORD_ID_MAX); + table.string('message_id', DISCORD_ID_MAX); + table.string('emoji_id', DISCORD_ID_MAX); + table.string('role_id', DISCORD_ID_MAX); table.primary(['message_id', 'emoji_id']); }); }; exports.down = function(knex) { - return knex.schema.dropTable(db.REACTS); + return knex.schema.dropTable(REACTS); }; diff --git a/migrations/20200814190000_meta.js b/migrations/20200814190000_meta.js index 90957cb..3b72acb 100644 --- a/migrations/20200814190000_meta.js +++ b/migrations/20200814190000_meta.js @@ -14,18 +14,18 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const db = require('../database'); +const META = 'meta'; exports.up = function(knex) { - return knex.schema.createTable(db.META, table => { + return knex.schema.createTable(META, table => { table.integer('assignments'); }).then(() => { // There will only ever be one row in this table so we make it here. - return knex(db.META).insert({ assignments: 0 }); + return knex(META).insert({ assignments: 0 }); }); }; exports.down = function(knex) { - return knex.schema.dropTable(db.META); + return knex.schema.dropTable(META); }; diff --git a/migrations/20200815043000_perms.js b/migrations/20200815043000_perms.js index 381680e..01a1339 100644 --- a/migrations/20200815043000_perms.js +++ b/migrations/20200815043000_perms.js @@ -14,18 +14,19 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const db = require('../database'); +const DISCORD_ID_MAX = 19; +const PERMS = 'perms'; exports.up = function(knex) { - return knex.schema.createTable(db.PERMS, table => { - table.string('guild_id', db.DISCORD_ID_LENGTH.MAX); - table.string('role_id', db.DISCORD_ID_LENGTH.MAX); + return knex.schema.createTable(PERMS, table => { + table.string('guild_id', DISCORD_ID_MAX); + table.string('role_id', DISCORD_ID_MAX); table.primary(['guild_id', 'role_id']); }); }; exports.down = function(knex) { - return knex.schema.dropTable(db.PERMS); + return knex.schema.dropTable(PERMS); }; diff --git a/migrations/20200818203000_mutex.js b/migrations/20200818203000_mutex.js index c869b34..94a2ce5 100644 --- a/migrations/20200818203000_mutex.js +++ b/migrations/20200818203000_mutex.js @@ -14,19 +14,20 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const db = require('../database'); +const DISCORD_ID_MAX = 19; +const MUTEX = 'mutex'; exports.up = function(knex) { - return knex.schema.createTable(db.MUTEX, table => { - table.string('guild_id', db.DISCORD_ID_LENGTH.MAX); - table.string('role_id_1', db.DISCORD_ID_LENGTH.MAX); - table.string('role_id_2', db.DISCORD_ID_LENGTH.MAX); + return knex.schema.createTable(MUTEX, table => { + table.string('guild_id', DISCORD_ID_MAX); + table.string('role_id_1', DISCORD_ID_MAX); + table.string('role_id_2', DISCORD_ID_MAX); table.primary(['guild_id', 'role_id_1', 'role_id_2']); }); }; exports.down = function(knex) { - return knex.schema.dropTable(db.MUTEX); + return knex.schema.dropTable(MUTEX); }; From ec25f83e65b5e7d5ad63bb4063e1423818775cd2 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 24 Dec 2021 17:50:38 -0500 Subject: [PATCH 024/107] ...Because we're buffing this field to 22 instead of 19 --- database.js | 2 +- main.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/database.js b/database.js index cbe12f1..117b1f1 100644 --- a/database.js +++ b/database.js @@ -24,7 +24,7 @@ const PERMS = 'perms'; const REACTS = 'reacts'; const DISCORD_ID_LENGTH = { MIN: 17, - MAX: 19 + MAX: 22, }; /** diff --git a/main.js b/main.js index 50c6de0..e36b3ed 100644 --- a/main.js +++ b/main.js @@ -808,7 +808,7 @@ function extractEmoji(emoji) { return null; } - let match = emoji.match(//); + let match = emoji.match(//); return match ? match[1] : emoji; } From 8b0503bca736a2d77f0db84102c22c33c7b7b686 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 24 Dec 2021 20:08:04 -0500 Subject: [PATCH 025/107] Use message builder utilities for info command --- commands.js | 29 ++++++++++++++++++----------- util.js | 11 +++++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/commands.js b/commands.js index 5b00814..ebc3adb 100644 --- a/commands.js +++ b/commands.js @@ -36,13 +36,18 @@ const { ApplicationCommandType, Options, SlashCommandRegistry, + bold, + codeBlock, } = require('discord-command-registry'); const SELECTED_MESSAGE_CACHE = require('memory-cache'); const database = require('./database'); const info = require('./package.json'); const logger = require('./logger'); -const { emojiToKey } = require('./util'); +const { + asLines, + emojiToKey, +} = require('./util'); const ONE_HOUR_IN_MS = 60*60*1000; @@ -101,16 +106,18 @@ const REGISTRY = new SlashCommandRegistry() */ async function cmdInfo(interaction) { const stats = await database.getMetaStats(); - await interaction.reply( - `${info.description}\n` + - `**Running version:** ${info.version}\n` + - `**Source code:** ${info.homepage}\n\n` + - '```Stats For Nerds:\n' + - ` - Servers bot is active in: ${stats.guilds}\n` + - ` - Reaction role mappings: ${stats.roles}\n` + - ` - Total role assignments: ${stats.assignments}\n` + - '```' - ); + return interaction.reply(asLines([ + info.description, + `${bold('Running version:')} ${info.version}`, + `${bold('Source code:')} ${info.homepage}`, + '', + codeBlock(asLines([ + 'Stats For Nerds:', + ` - Servers bot is active in: ${stats.guilds}`, + ` - Reaction role mappings: ${stats.roles}`, + ` - Total role assignments: ${stats.assignments}`, + ])), + ])); } /** diff --git a/util.js b/util.js index fc0935a..3a16b2d 100644 --- a/util.js +++ b/util.js @@ -15,6 +15,16 @@ * along with this program. If not, see . ******************************************************************************/ +/** + * Joins the given array of strings using newlines. + */ +function asLines(lines) { + if (!Array.isArray(lines)) { + lines = [lines]; + } + return lines.join('\n'); +} + /** * Converts an emoji to a string we can use as a key (e.g. in a database). * @@ -33,6 +43,7 @@ function emojiToKey(emoji) { } module.exports = { + asLines, emojiToKey, }; From e710117183ecdf34a669131af069d653aa390669 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 24 Dec 2021 20:43:48 -0500 Subject: [PATCH 026/107] Add utilities for stringifying Discord objects and replying ephemerally --- util.js | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/util.js b/util.js index 3a16b2d..cd43db9 100644 --- a/util.js +++ b/util.js @@ -14,6 +14,13 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ +const { + Guild, + Interaction, + User, +} = require('discord.js'); + +const logger = require('./logger'); /** * Joins the given array of strings using newlines. @@ -25,6 +32,20 @@ function asLines(lines) { return lines.join('\n'); } +/** + * Like stringify, but provides more detail. Falls back on stringify. + */ +function detail(thing) { + if (thing instanceof Interaction) { + const int = thing; + return `${stringify(int.guild)} ${stringify(int.user)} ${stringify(int)}`; + } + else { + // Fall back on standard strings + return stringify(thing); + } +} + /** * Converts an emoji to a string we can use as a key (e.g. in a database). * @@ -42,8 +63,61 @@ function emojiToKey(emoji) { } } +/** + * Shortcut for sending an ephemeral reply to an interaction, since we do it so + * much. + */ +function ephemReply(interaction, content) { + logger.info(`Reply to ${detail(interaction)}: "${content}"`); + return interaction.reply({ + content: content, + ephemeral: true, + }); +} + +/** + * Given a Discord.js object, returns a logger-friendly string describing it in + * better detail. + * + * This purposely only outputs IDs to limit the amount of user data logged. + */ +// TODO stolen from Zerda. Maybe pull this out to a module with the logger? +function stringify(thing) { + let str; + + if (!thing) { + return '[undefined]'; + } + else if (typeof thing === 'string' || thing instanceof String) { + return thing; + } + else if (thing instanceof Guild) { + const guild = thing; + return `Guild ${guild.id}`; + } + else if (thing instanceof Interaction) { + const interaction = thing; + const cmd_str = Array.of( + interaction.commandName, + interaction.options.getSubcommandGroup(false), + interaction.options.getSubcommand(false), + ).filter(x => x).join(' '); + return `Interaction "${cmd_str}"`; + } + else if (thing instanceof User) { + const user = thing; + return `User ${user.id}`; + } + else { + throw Error(`Unsupported type ${typeof(thing)}`); + } +} + module.exports = { asLines, + detail, emojiToKey, + ephemReply, + stringify, }; From 090811801a6fb69907cb2202cd500fc5ebbbe5cb Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 24 Dec 2021 20:44:55 -0500 Subject: [PATCH 027/107] Use ephemReply in commands --- commands.js | 77 ++++++++++++++++------------------------------------- 1 file changed, 23 insertions(+), 54 deletions(-) diff --git a/commands.js b/commands.js index ebc3adb..63726e6 100644 --- a/commands.js +++ b/commands.js @@ -47,6 +47,7 @@ const logger = require('./logger'); const { asLines, emojiToKey, + ephemReply, } = require('./util'); const ONE_HOUR_IN_MS = 60*60*1000; @@ -131,10 +132,7 @@ async function cmdSelect(interaction) { SELECTED_MESSAGE_CACHE.del(user.id); SELECTED_MESSAGE_CACHE.put(user.id, message, ONE_HOUR_IN_MS); - return interaction.reply({ - content: `Selected message: ${message.url}`, - ephemeral: true, - }); + return ephemReply(interaction, `Selected message: ${message.url}`); } /** @@ -142,12 +140,10 @@ async function cmdSelect(interaction) { */ async function cmdSelected(interaction) { const message = SELECTED_MESSAGE_CACHE.get(interaction.user.id); - return interaction.reply({ - content: message - ? `Currently selected: ${message.url}` - : 'No message currently selected', - ephemeral: true, - }); + return ephemReply(interaction, message + ? `Currently selected: ${message.url}` + : 'No message currently selected' + ); } /** @@ -159,17 +155,11 @@ async function cmdRoleAdd(interaction) { let message = SELECTED_MESSAGE_CACHE.get(interaction.user.id); if (!message) { - return interaction.reply({ - content: 'No message selected! Select a message first.', - ephemeral: true, - }); + return ephemReply(interaction, 'No message selected! Select a message first.'); } if (!emoji) { - return interaction.reply({ - content: 'Not a valid emoji!', - ephemeral: true, - }); + return ephemReply(interaction, 'Not a valid emoji!'); } message = await message.fetch(); @@ -177,12 +167,10 @@ async function cmdRoleAdd(interaction) { // Prevent someone from modifying a server from outside the server. if (interaction.guild !== message.guild || interaction.guild !== role.guild) { // TODO use unindent - return interaction.reply({ - content: - 'Message and Role need to be in the same Server ' + - 'this command was issued from', - ephemeral: true, - }); + return ephemReply(interaction, + 'Message and Role need to be in the same Server this command ' + + 'was issued from!' + ); } // Try to add this mapping to the database. @@ -196,10 +184,7 @@ async function cmdRoleAdd(interaction) { await database.addRoleReact(db_data); } catch (err) { logger.error(`Database failed to create ${JSON.stringify(db_data)}`, err); - return interaction.reply({ - content: 'Something went wrong', - ephemeral: true, - }); + return ephemReply(interaction, 'Something went wrong'); } // Try to add the emoji to the selected message. If this fails, also remove @@ -212,18 +197,12 @@ async function cmdRoleAdd(interaction) { // maybe hold off until we have fully replace message commands with // slash commands. await database.removeRoleReact(db_data); - return interaction.reply({ - content: - 'I could not react to your selected message. Do I have the ' + - 'right permissions?', - ephemeral: true, - }); + return ephemReply(interaction, + 'I could not react to your selected message. Do I have the right permissions?' + ); } - return interaction.reply({ - content: `Mapped ${emoji} to ${role} on message ${message.url}`, - ephemeral: true, - }); + return ephemReply(interaction, `Mapped ${emoji} to ${role} on message ${message.url}`); } /** @@ -234,17 +213,11 @@ async function cmdRoleRemove(interaction) { let message = SELECTED_MESSAGE_CACHE.get(interaction.user.id); if (!message) { - return interaction.reply({ - content: 'No message selected! Select a message first.', - ephemeral: true, - }); + return ephemReply(interaction, 'No message selected! Select a message first.'); } if (!emoji) { - return interaction.reply({ - content: 'Not a valid emoji!', - ephemeral: true, - }); + return ephemReply(interaction, 'Not a valid emoji!'); } message = await message.fetch(); @@ -261,16 +234,12 @@ async function cmdRoleRemove(interaction) { await message.reactions.cache.get(emoji_id).remove(); } catch (err) { logger.error(`Could not remove emoji ${emoji} from message ${message.url}`, err); - return interaction.reply({ - content: 'I could not remove the react. Do I have the right permissions?', - ephemeral: true, - }); + return ephemReply(interaction, + 'I could not remove the react. Do I have the right permissions?' + ); } - return interaction.reply({ - content: `Removed ${emoji} from message ${message.url}`, - ephemeral: true, - }); + return ephemReply(interaction, `Removed ${emoji} from message ${message.url}`); } module.exports = REGISTRY; From b0dbdec9f9107eb6d229b799ca4288a155c8cd10 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 24 Dec 2021 21:18:36 -0500 Subject: [PATCH 028/107] Pull unindent out to utils --- commands.js | 10 +++++----- main.js | 10 +--------- util.js | 10 ++++++++++ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/commands.js b/commands.js index 63726e6..d527e91 100644 --- a/commands.js +++ b/commands.js @@ -48,6 +48,7 @@ const { asLines, emojiToKey, ephemReply, + unindent, } = require('./util'); const ONE_HOUR_IN_MS = 60*60*1000; @@ -166,11 +167,10 @@ async function cmdRoleAdd(interaction) { // Prevent someone from modifying a server from outside the server. if (interaction.guild !== message.guild || interaction.guild !== role.guild) { - // TODO use unindent - return ephemReply(interaction, - 'Message and Role need to be in the same Server this command ' + - 'was issued from!' - ); + return ephemReply(interaction, unindent(` + Message and Role need to be in the same Server this command + was issued from! + `)); } // Try to add this mapping to the database. diff --git a/main.js b/main.js index e36b3ed..b25c251 100644 --- a/main.js +++ b/main.js @@ -22,6 +22,7 @@ const cache = require('./cache'); const commands = require('./commands'); const database = require('./database'); const logger = require('./logger'); +const { unindent } = require('./util'); const config = JSON.parse(fs.readFileSync( process.argv[2] || '/etc/discord/ReactionRoleBot/config.json' @@ -839,15 +840,6 @@ function usage(name) { return `\nUsage: ${COMMANDS.get(name).get('usage')}`; } -/** - * Allows us to treat multi-line template strings as a single continuous line. - */ -function unindent(str) { - return str - .replace(/^\s*/, '') - .replace(/\n\t*/g, ' '); -} - /** * Single function to make error redirection easier in the future. * Maybe some day we'll do something more intelligent with errors. diff --git a/util.js b/util.js index cd43db9..e2a835d 100644 --- a/util.js +++ b/util.js @@ -113,11 +113,21 @@ function stringify(thing) { } } +/** + * Allows us to treat multi-line template strings as a single continuous line. + */ +function unindent(str) { + return str + .replace(/^\s*/, '') + .replace(/\n\t*/g, ' '); +} + module.exports = { asLines, detail, emojiToKey, ephemReply, stringify, + unindent, }; From 80773d89ade2ee8f524e75d739b124c8094a701d Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Mon, 27 Dec 2021 19:57:42 -0500 Subject: [PATCH 029/107] Slash command for adding permission roles --- commands.js | 42 ++++++++++++++++++++++++++++++++++++++++++ util.js | 5 +++++ 2 files changed, 47 insertions(+) diff --git a/commands.js b/commands.js index d527e91..cf82692 100644 --- a/commands.js +++ b/commands.js @@ -48,6 +48,7 @@ const { asLines, emojiToKey, ephemReply, + stringify, unindent, } = require('./util'); @@ -100,6 +101,20 @@ const REGISTRY = new SlashCommandRegistry() ) ) ) + .addCommand(command => command + .setName('permission') + .setDescription('Manage who is allowed to configure the bot') + .addSubcommand(subcommand => subcommand + .setName('add') + .setDescription('Add a role that can configure the bot') + .setHandler(cmdPermAdd) + .addRoleOption(option => option + .setName('role') + .setDescription('The role that will be able to configure the bot') + .setRequired(true) + ) + ) + ) ; /** @@ -242,5 +257,32 @@ async function cmdRoleRemove(interaction) { return ephemReply(interaction, `Removed ${emoji} from message ${message.url}`); } +/** + * Adds a role that can configure this bot's settings for a guild. + */ +async function cmdPermAdd(interaction) { + const role = interaction.options.getRole('role', true); + + if (interaction.guild !== role.guild) { + return ephemReply(interaction, 'Role must belong to this guild!'); + } + + try { + await database.addAllowedRole({ + guild_id: interaction.guild.id, + role_id: role.id, + }); + } catch (err) { + if (err.message.includes('UNIQUE constraint failed')) { + return ephemReply(interaction, `${role} can already configure me!`); + } else { + logger.error(`Could not add permission for ${stringify(role)}`, err); + return ephemReply(interaction, 'Something went wrong. Try again?'); + } + } + + return ephemReply(interaction, `${role} can now configure me`); +} + module.exports = REGISTRY; diff --git a/util.js b/util.js index e2a835d..e3068b5 100644 --- a/util.js +++ b/util.js @@ -17,6 +17,7 @@ const { Guild, Interaction, + Role, User, } = require('discord.js'); @@ -104,6 +105,10 @@ function stringify(thing) { ).filter(x => x).join(' '); return `Interaction "${cmd_str}"`; } + else if (thing instanceof Role) { + const role = thing; + return `Role ${role.id}`; + } else if (thing instanceof User) { const user = thing; return `User ${user.id}`; From a4aef26c94c5ba359c1b845693f7f50b6f4e0c62 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Mon, 27 Dec 2021 20:23:36 -0500 Subject: [PATCH 030/107] Use stringify in more places --- commands.js | 11 +++++++---- util.js | 30 +++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/commands.js b/commands.js index cf82692..29f9cdb 100644 --- a/commands.js +++ b/commands.js @@ -207,7 +207,7 @@ async function cmdRoleAdd(interaction) { try { await message.react(emoji); } catch (err) { - logger.warn(`Could not add emoji ${emoji} to message ${message.url}`, err); + logger.warn(`Could not add ${stringify(emoji)} to ${stringify(message)}`, err); // FIXME use a transaction for this. This involves database work so // maybe hold off until we have fully replace message commands with // slash commands. @@ -217,7 +217,7 @@ async function cmdRoleAdd(interaction) { ); } - return ephemReply(interaction, `Mapped ${emoji} to ${role} on message ${message.url}`); + return ephemReply(interaction, `Mapped ${emoji} to ${role} on ${stringify(message)}`); } /** @@ -248,13 +248,16 @@ async function cmdRoleRemove(interaction) { }); await message.reactions.cache.get(emoji_id).remove(); } catch (err) { - logger.error(`Could not remove emoji ${emoji} from message ${message.url}`, err); + logger.error( + `Could not remove ${stringify(emoji)} from ${stringify(message)}`, + err + ); return ephemReply(interaction, 'I could not remove the react. Do I have the right permissions?' ); } - return ephemReply(interaction, `Removed ${emoji} from message ${message.url}`); + return ephemReply(interaction, `Removed ${emoji} from ${stringify(message)}`); } /** diff --git a/util.js b/util.js index e3068b5..9f39497 100644 --- a/util.js +++ b/util.js @@ -15,8 +15,10 @@ * along with this program. If not, see . ******************************************************************************/ const { + Emoji, Guild, Interaction, + Message, Role, User, } = require('discord.js'); @@ -55,13 +57,10 @@ function detail(thing) { * - Non-emoji strings are considered an error and will throw accordingly. */ function emojiToKey(emoji) { - if (emoji?.id) { - return emoji.id; - } else if (emoji?.match(/^\p{Extended_Pictographic}$/u)) { - return emoji; - } else { + if (!isEmoji(emoji)) { throw Error(`Not an emoji key: ${emoji}`); } + return emoji?.id ?? emoji; } /** @@ -76,6 +75,13 @@ function ephemReply(interaction, content) { }); } +/** + * Handles both custom Discord.js Emojis and standard unicode emojis. + */ +function isEmoji(thing) { + return thing?.match?.(/^\p{Extended_Pictographic}$/u) || thing instanceof Emoji; +} + /** * Given a Discord.js object, returns a logger-friendly string describing it in * better detail. @@ -84,13 +90,12 @@ function ephemReply(interaction, content) { */ // TODO stolen from Zerda. Maybe pull this out to a module with the logger? function stringify(thing) { - let str; - if (!thing) { return '[undefined]'; } - else if (typeof thing === 'string' || thing instanceof String) { - return thing; + else if (isEmoji(thing)) { + const emoji = thing; + return `Emoji ${emojiToKey(emoji)}`; } else if (thing instanceof Guild) { const guild = thing; @@ -105,6 +110,10 @@ function stringify(thing) { ).filter(x => x).join(' '); return `Interaction "${cmd_str}"`; } + else if (thing instanceof Message) { + const message = thing; + return `Message ${message.url}`; + } else if (thing instanceof Role) { const role = thing; return `Role ${role.id}`; @@ -113,6 +122,9 @@ function stringify(thing) { const user = thing; return `User ${user.id}`; } + else if (typeof thing === 'string' || thing instanceof String) { + return thing; + } else { throw Error(`Unsupported type ${typeof(thing)}`); } From 61f6e6d4f54b15c65c13adf8a4333747aba51570 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Mon, 27 Dec 2021 20:28:38 -0500 Subject: [PATCH 031/107] Actually just fall back on JSON.stringify. That makes more sense. --- commands.js | 2 +- util.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/commands.js b/commands.js index 29f9cdb..39b6e5d 100644 --- a/commands.js +++ b/commands.js @@ -198,7 +198,7 @@ async function cmdRoleAdd(interaction) { try { await database.addRoleReact(db_data); } catch (err) { - logger.error(`Database failed to create ${JSON.stringify(db_data)}`, err); + logger.error(`Database failed to create ${stringify(db_data)}`, err); return ephemReply(interaction, 'Something went wrong'); } diff --git a/util.js b/util.js index 9f39497..0d3b345 100644 --- a/util.js +++ b/util.js @@ -126,7 +126,7 @@ function stringify(thing) { return thing; } else { - throw Error(`Unsupported type ${typeof(thing)}`); + return JSON.stringify(thing); } } From 5f5449ef7fa41848f28f68ec57b7c864c634e01c Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Mon, 27 Dec 2021 20:51:26 -0500 Subject: [PATCH 032/107] Command for removing permissions --- commands.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/commands.js b/commands.js index 39b6e5d..0019d62 100644 --- a/commands.js +++ b/commands.js @@ -114,6 +114,18 @@ const REGISTRY = new SlashCommandRegistry() .setRequired(true) ) ) + .addSubcommand(subcommand => subcommand + .setName('remove') + .setDescription('Remove a role that can configure the bot') + .setHandler(cmdPermRemove) + .addRoleOption(option => option + .setName('role') + .setDescription( + 'The role that will no longer be able to configure the bot' + ) + .setRequired(true) + ) + ) ) ; @@ -287,5 +299,34 @@ async function cmdPermAdd(interaction) { return ephemReply(interaction, `${role} can now configure me`); } +/** + * Removes a role from being able to configure this bot's settings for a guild. + * A role can remove itself, which is dumb, but whatever. + */ +async function cmdPermRemove(interaction) { + const role = interaction.options.getRole('role', true); + + if (interaction.guild !== role.guild) { + return ephemReply(interaction, 'Role must belong to this guild!'); + } + + let removed; + try { + removed = await database.removeAllowedRole({ + guild_id: interaction.guild.id, + role_id: role.id, + }); + } catch (err) { + logger.error(`Could not remove permission for ${stringify(role)}`, err); + return ephemReply(interaction, 'Something went wrong. Try again?'); + } + + return ephemReply(interaction, + `${role} ${ + removed === 1 ? 'is no longer' : 'was already not' + } allowed to configure me` + ); +} + module.exports = REGISTRY; From 0a41f64a79b7f891d441ed2cc4df888dca23a1f2 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 28 Dec 2021 20:19:56 -0500 Subject: [PATCH 033/107] Slash command for adding mutex roles --- commands.js | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/commands.js b/commands.js index 0019d62..cd2af34 100644 --- a/commands.js +++ b/commands.js @@ -127,6 +127,25 @@ const REGISTRY = new SlashCommandRegistry() ) ) ) + .addCommand(command => command + .setName('mutex') + .setDescription('Manage mutually exclusive react roles') + .addSubcommand(subcommand => subcommand + .setName('add') + .setDescription('Make two react roles mutually exclusive for this server') + .setHandler(cmdMutexAdd) + .addRoleOption(option => option + .setName('role1') + .setDescription('The first mutually exclusive role') + .setRequired(true) + ) + .addRoleOption(option => option + .setName('role2') + .setDescription('The second mutually exclusive role') + .setRequired(true) + ) + ) + ) ; /** @@ -328,5 +347,48 @@ async function cmdPermRemove(interaction) { ); } +/** + * Make two roles mutually exclusive for a guild. + * This is for the whole guild, not just a single message. + */ +async function cmdMutexAdd(interaction) { + const role1 = interaction.options.getRole('role1', true); + const role2 = interaction.options.getRole('role2', true); + + if (interaction.guild !== role1.guild || interaction.guild != role2.guild) { + return ephemReply(interaction, 'Roles must belong to this guild!'); + } + + if (role1 === role2) { + return ephemReply(interaction, + 'Cannot make a role mutually exclusive with itself!' + ); + } + + try { + await database.addMutexRole({ + guild_id: interaction.guild.id, + role_id_1: role1.id, + role_id_2: role2.id, + }); + } catch (err) { + if (err.message.includes('UNIQUE constraint failed')) { + return ephemReply(interaction, + `Roles ${role1} and ${role2} are already mutually exclusive!` + ); + } else { + logger.error(unindent(` + Could not make ${stringify(role1)} and ${stringify(role2)} + mutually exclusive + `), err); + return ephemReply(interaction, 'Something went wrong. Try again?'); + } + } + + return ephemReply(interaction, + `Roles ${role1} and ${role2} are now mutually exclusive in this server` + ); +} + module.exports = REGISTRY; From 24c25a18e30964e534a5c2e038ad0c53ca86cc56 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 28 Dec 2021 20:20:22 -0500 Subject: [PATCH 034/107] Slash command for removing mutex roles --- commands.js | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/commands.js b/commands.js index cd2af34..927b5ec 100644 --- a/commands.js +++ b/commands.js @@ -145,6 +145,23 @@ const REGISTRY = new SlashCommandRegistry() .setRequired(true) ) ) + .addSubcommand(subcommand => subcommand + .setName('remove') + .setDescription( + 'Remove the mutually exclusive restriction on two react roles' + ) + .setHandler(cmdMutexRemove) + .addRoleOption(option => option + .setName('role1') + .setDescription('The first mutually exclusive role') + .setRequired(true) + ) + .addRoleOption(option => option + .setName('role2') + .setDescription('The second mutually exclusive role') + .setRequired(true) + ) + ) ) ; @@ -390,5 +407,38 @@ async function cmdMutexAdd(interaction) { ); } +/** + * Removes the mutually exclusive restriction for two roles in a guild. + */ +async function cmdMutexRemove(interaction) { + const role1 = interaction.options.getRole('role1', true); + const role2 = interaction.options.getRole('role2', true); + + if (interaction.guild !== role1.guild || interaction.guild != role2.guild) { + return ephemReply(interaction, 'Roles must belong to this guild!'); + } + + let removed; + try { + removed = await database.removeMutexRole({ + guild_id: interaction.guild.id, + role_id_1: role1.id, + role_id_2: role2.id, + }); + } catch (err) { + logger.error( + `Could not remove mutex for ${stringify(role1)} and ${stringify(role2)}`, + err + ); + return ephemReply(interaction, 'Something went wrong. Try again?'); + } + + return ephemReply(interaction, + `Roles ${role1} and ${role2} ${ + removed === 1 ? 'are no longer' : 'were already not' + } mutually exclusive` + ); +} + module.exports = REGISTRY; From f518b7473dc90f8c821933ffcec5902cc0c4d357 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 28 Dec 2021 20:29:51 -0500 Subject: [PATCH 035/107] Actually use the permissions we have set up for the server --- commands.js | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/commands.js b/commands.js index 927b5ec..dc4c3ef 100644 --- a/commands.js +++ b/commands.js @@ -39,6 +39,7 @@ const { bold, codeBlock, } = require('discord-command-registry'); +const Discord = require('discord.js'); const SELECTED_MESSAGE_CACHE = require('memory-cache'); const database = require('./database'); @@ -65,12 +66,12 @@ const REGISTRY = new SlashCommandRegistry() .addContextMenuCommand(command => command .setName('select-message') .setType(ApplicationCommandType.Message) - .setHandler(cmdSelect) + .setHandler(requireAuth(cmdSelect)) ) .addCommand(command => command .setName('selected') .setDescription('Shows currently selected message') - .setHandler(cmdSelected) + .setHandler(requireAuth(cmdSelected)) ) .addCommand(command => command .setName('role') @@ -78,7 +79,7 @@ const REGISTRY = new SlashCommandRegistry() .addSubcommand(subcommand => subcommand .setName('add') .setDescription('Add a new react-role to the selected message') - .setHandler(cmdRoleAdd) + .setHandler(requireAuth(cmdRoleAdd)) .addStringOption(option => option .setName('emoji') .setDescription('The emoji to map the role to') @@ -93,7 +94,7 @@ const REGISTRY = new SlashCommandRegistry() .addSubcommand(subcommand => subcommand .setName('remove') .setDescription('Remove a react-role from the selected message') - .setHandler(cmdRoleRemove) + .setHandler(requireAuth(cmdRoleRemove)) .addStringOption(option => option .setName('emoji') .setDescription('The emoji mapping to remove') @@ -107,7 +108,7 @@ const REGISTRY = new SlashCommandRegistry() .addSubcommand(subcommand => subcommand .setName('add') .setDescription('Add a role that can configure the bot') - .setHandler(cmdPermAdd) + .setHandler(requireAuth(cmdPermAdd)) .addRoleOption(option => option .setName('role') .setDescription('The role that will be able to configure the bot') @@ -117,7 +118,7 @@ const REGISTRY = new SlashCommandRegistry() .addSubcommand(subcommand => subcommand .setName('remove') .setDescription('Remove a role that can configure the bot') - .setHandler(cmdPermRemove) + .setHandler(requireAuth(cmdPermRemove)) .addRoleOption(option => option .setName('role') .setDescription( @@ -133,7 +134,7 @@ const REGISTRY = new SlashCommandRegistry() .addSubcommand(subcommand => subcommand .setName('add') .setDescription('Make two react roles mutually exclusive for this server') - .setHandler(cmdMutexAdd) + .setHandler(requireAuth(cmdMutexAdd)) .addRoleOption(option => option .setName('role1') .setDescription('The first mutually exclusive role') @@ -150,7 +151,7 @@ const REGISTRY = new SlashCommandRegistry() .setDescription( 'Remove the mutually exclusive restriction on two react roles' ) - .setHandler(cmdMutexRemove) + .setHandler(requireAuth(cmdMutexRemove)) .addRoleOption(option => option .setName('role1') .setDescription('The first mutually exclusive role') @@ -165,6 +166,27 @@ const REGISTRY = new SlashCommandRegistry() ) ; +/** + * Middleware for command handlers that ensures the user initiating an + * interaction has permission to do so, and short-circuits if they don't. + */ +function requireAuth(handler) { + return async function(interaction) { + const member = await interaction.member.fetch(); // Ensures cache + + if (member.permissions.has(Discord.Permissions.FLAGS.ADMINISTRATOR)) { + return handler(interaction); + } + + const allowedRoles = await database.getAllowedRoles(interaction.guild.id); + if (allowedRoles.some(role => member.roles.cache.has(role))) { + return handler(interaction); + } + + return ephemReply(interaction, "You don't have permission to use that!"); + } +} + /** * Replies with info about this bot, including a link to the source code to be * compliant with the AGPLv3 this bot is licensed under. From f30594d5d8d0f13d99c6fa30b6cf4494c47ab16e Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 28 Dec 2021 20:44:53 -0500 Subject: [PATCH 036/107] (bugfix) Don't throw error internally when removing non-existing emoji from message --- commands.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/commands.js b/commands.js index dc4c3ef..e1177f8 100644 --- a/commands.js +++ b/commands.js @@ -307,6 +307,7 @@ async function cmdRoleRemove(interaction) { message = await message.fetch(); + let removed; try { const emoji_id = emojiToKey(emoji); @@ -316,7 +317,7 @@ async function cmdRoleRemove(interaction) { message_id: message.id, emoji_id: emoji_id, }); - await message.reactions.cache.get(emoji_id).remove(); + removed = await message.reactions.cache.get(emoji_id)?.remove(); } catch (err) { logger.error( `Could not remove ${stringify(emoji)} from ${stringify(message)}`, @@ -327,7 +328,11 @@ async function cmdRoleRemove(interaction) { ); } - return ephemReply(interaction, `Removed ${emoji} from ${stringify(message)}`); + return ephemReply(interaction, + removed + ? `Removed ${emoji} from ${stringify(message)}` + : `Selected message does not have ${emoji} reaction! ${message.url}` + ); } /** From e878823db32d897fa79e08168dcad07a08781121 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 29 Dec 2021 01:12:04 -0500 Subject: [PATCH 037/107] Slash command for removing all react roles from a message --- commands.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/commands.js b/commands.js index e1177f8..1f4b94e 100644 --- a/commands.js +++ b/commands.js @@ -101,6 +101,11 @@ const REGISTRY = new SlashCommandRegistry() .setRequired(true) ) ) + .addSubcommand(subcommand => subcommand + .setName('remove-all') + .setDescription('Remove ALL react-roles from the selected message') + .setHandler(requireAuth(cmdRoleRemoveAll)) + ) ) .addCommand(command => command .setName('permission') @@ -335,6 +340,37 @@ async function cmdRoleRemove(interaction) { ); } +/** + * Removes all emoji mappings from the currently selected message. + */ +async function cmdRoleRemoveAll(interaction) { + let message = SELECTED_MESSAGE_CACHE.get(interaction.user.id); + + if (!message) { + return ephemReply(interaction, 'No message selected! Select a message first.'); + } + + message = await message.fetch(); + + let removed; + try { + // TODO Another important place for a transaction + removed = await database.removeRoleReact(message.id); + await message.reactions.removeAll(); + } catch (err) { + logger.error(`Could not remove all reacts from ${stringify(message)}`, err); + return ephemReply(interaction, + 'I could not remove the reacts. Do I have the right permissions?' + ); + } + + return ephemReply(interaction, + removed + ? `Removed all react roles from ${stringify(message)}` + : `Selected message does not have any role reactions! ${message.url}` + ); +} + /** * Adds a role that can configure this bot's settings for a guild. */ From 9054ec19909f51dc0c772ac3bf0a22c67fef1bdf Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 29 Dec 2021 01:48:32 -0500 Subject: [PATCH 038/107] Remove message commands entirely --- main.js | 610 +------------------------------------------------------- 1 file changed, 1 insertion(+), 609 deletions(-) diff --git a/main.js b/main.js index b25c251..90d2606 100644 --- a/main.js +++ b/main.js @@ -46,71 +46,17 @@ const client = new Discord.Client({ ], presence: { activities: [{ - name: `'help' for commands. Running version ${info.version}`, + name: `Running version ${info.version}`, type: Discord.Constants.ActivityTypes.LISTENING, }], }, }); -// Map of command names to handling functions. Doubles as a validator. -const COMMANDS = new Map(); -cmdDef(selectMessage, - 'select', ' ', - `Selects the message to perform actions on. This is per-user, so multiple - people can be setting up roles on different messages (or the same one).` -); -cmdDef(setupReactRole, - 'role-add', ' ', - `Creates an emoji-role on the selected message. The bot will automatically - react to the message with this emoji.` -); -cmdDef(removeReactRole, - 'role-remove', '', - `Removes the emoji-role from the message. The bot will remove all reactions - of this emoji from the message.` -); -cmdDef(removeAllReacts, - 'role-remove-all', '', - `Removes all emoji-roles and reactions from the message. This will **not** - remove existing roles from users.` -); -cmdDef(addPermissionRole, - 'perm-add', '', - `Adds a role that is allowed to configure this bot in this server. Note that - this role will be allowed to add more roles with this same permission.` -); -cmdDef(removePermissionRole, - 'perm-remove', '', - `Removes a role from being allowed to configure this bot in this server. - Note that allowed roles can remove their own ability to configure this bot, - and will then be unable to make further changes until an administrator - re-adds their permission.` -); -cmdDef(addMutexRoles, - 'mutex-add', ' ', - `Makes two roles mutually exclusive. If a user attempts to add two mutually - exclusive roles, they will lose the first one they had.` -); -cmdDef(removeMutexRoles, - 'mutex-remove', ' ', - `Removes the mutually exclusive restriction on two roles.` -); -cmdDef(sayInfo, - 'info', '', - 'Prints description, version, and link to source code for the bot' -); -cmdDef(sayHelp, - 'help', '', - 'Prints this help text' -); - - const Events = Discord.Constants.Events; client.on(Events.CLIENT_READY, onReady); client.on(Events.GUILD_CREATE, onGuildJoin); client.on(Events.GUILD_DELETE, onGuildLeave); client.on(Events.INTERACTION_CREATE, onInteraction); -client.on(Events.MESSAGE_CREATE, onMessage); client.on(Events.MESSAGE_REACTION_ADD, onReactionAdd); client.on(Events.MESSAGE_REACTION_REMOVE, onReactionRemove); @@ -187,494 +133,6 @@ function onInteraction(interaction) { commands.execute(interaction); } -/** - * Event handler for getting a new message. - * Parses and delegates any role bot command. - */ -function onMessage(msg) { - // Ignore DMs - if (msg.channel instanceof Discord.DMChannel) { - return; - } - - // Ignore anything where we're not even mentioned - if (!msg.mentions.has(client.user)) { - return; - } - - let msgParts = msg.content.split(/\s+/); - - // Only pay attention to messages where we're mentioned first. - let mentionUserId = extractId(msgParts.shift()); - if (mentionUserId !== client.user.id) { - return; - } - - let cmdName = msgParts.shift(); - - // Only pay attention to messages that are known commands. - if (!COMMANDS.has(cmdName)) { - logError('Possible unrecognized command: ' + msg.content); - return; - } - - userHasPermission(msg, cmdName) - .then(hasPerm => { - if (hasPerm) { - COMMANDS.get(cmdName).get('handler')(msg, msgParts); - } else { - msg.reply("You don't have permission to use that command"); - } - }) - .catch(logError); -} - -/** - * Selects a message to associate with any subsequent role commands. - * Previously selected message is cleared if the user gives bad input for this. - */ -function selectMessage(msg, parts) { - // TODO support selection by URL - - let maybeChannelId = parts.shift(); - let maybeMessageId = parts.shift(); - - let channelId = extractId(maybeChannelId); - let messageId = extractId(maybeMessageId); - - let issue; - if (parts.length > 0) issue = 'Too many arguments!'; - else if (!maybeChannelId) issue = 'Missing channel!'; - else if (!maybeMessageId) issue = 'Missing message_id!'; - else if (!channelId) issue = `Invalid channel_id \`${maybeChannelId}\`!`; - else if (!messageId) issue = `Invalid message_id \`${maybeMessageId}\`!`; - - if (issue) { - msg.reply(issue + usage('select')); - cache.clearSelectedMessage(msg.author.id); - return; - } - - client.channels.fetch(channelId) - .then(channel => channel.messages.fetch(messageId)) - .then(message => { - cache.selectMessage(msg.author.id, message); - - return msg.reply( - `selected message with ID \`${message.id}\` ` + - `in channel <#${channelId}>. Link: ${message.url}` - ); - }) - .catch(err => { - // The user is trying to select a new message, so at least clear - // their old selection. Principle of least surprise, and all that... - cache.clearSelectedMessage(msg.author.id); - - let errMsg; - if (err.message === 'Unknown Channel') { - errMsg = "I can't find a channel in this server with ID " - + `\`${channelId}\`.`; - } - else if (err.message === 'Unknown Message') { - errMsg = `I can't find a message with ID \`${messageId}\` ` - + `in channel <#${channelId}>.`; - } - else { - errMsg = `I got an error I don't recognize:\n\`${err.message}\``; - logError(err, 'For message', msg.content); - } - - errMsg += usage('select'); - - msg.reply(errMsg); - }); -} - -/** - * Associate an emoji reaction with a role for the currently selected message. - */ -function setupReactRole(msg, parts) { - // TODO do we want to warn when two emojis map to the same role? - - let rawEmoji = parts.shift(); // Needed to print emoji in command response - let maybeRole = parts.shift(); - - let emoji = extractEmoji(rawEmoji); - let roleId = extractId(maybeRole); - - let issue; - if (parts.length > 0) issue = 'Too many arguments!'; - else if (!emoji) issue = 'Missing emoji!'; - else if (!maybeRole) issue = 'Missing role!'; - else if (!roleId) issue = `Invalid role \`${maybeRole}\`!`; - - if (issue) { - msg.reply(issue + usage('role-add')); - return; - } - - let userId = msg.author.id; - - msg.guild.roles.fetch(roleId) - .then(role => { - if (!role) { - throw new Error('Invalid Role'); - } - - return cache.addEmojiRole(userId, emoji, roleId); - }) - .then(() => cache.getSelectedMessage(userId)) - .then(selectedMessage => selectedMessage.react(emoji)) - .then(reaction => msg.reply( - `mapped ${rawEmoji} to <@&${roleId}> on message \`${reaction.message.id}\`` - )) - .catch(err => { - if (err.message === 'No message selected!') { - msg.reply('You need to select a message first!'); - } - else if (err.message === 'Invalid Role') { - msg.reply(`I can't find a role with ID \`${roleId}\``); - } - else if (err.message === 'Unknown Emoji') { - msg.reply( - `I can't find an emoji with ID \`${emoji}\`` - + usage('role-add') - ); - } - else if (err.message === 'Missing Permissions') { - msg.reply("I don't have permission to react to the selected message"); - } - else { - msg.reply(`I got an error I don't recognize:\n\`${err.message}\``); - logError(err, 'For message', msg.content); - } - }); -} - -/** - * Removes an emoji reaction role association from the currently selected - * message. - */ -function removeReactRole(msg, parts) { - let rawEmoji = parts.shift(); - let emoji = extractEmoji(rawEmoji); - - let issue; - if (parts.length > 0) issue = 'Too many arguments!'; - else if (!emoji) issue = 'Missing emoji!'; - - if (issue) { - msg.reply(issue + usage('role-remove')); - return; - } - - let userId = msg.author.id; - - Promise.resolve() // Hack to pass error from getSelectedMessage to .catch - .then(() => cache.getSelectedMessage(userId)) - .then(selectedMessage => { - let emojiReacts = selectedMessage.reactions.cache.get(emoji); - - return Promise.all([ - emojiReacts ? emojiReacts.remove() : Promise.resolve(), - cache.removeEmojiRole(userId, emoji) - ]) - .then(() => msg.reply( - `removed ${rawEmoji} role from message \`${selectedMessage.id}\`` - )); - }) - .catch(err => { - if (err.message === 'No message selected!') { - msg.reply('You need to select a message first!'); - } - else if (err.message === 'No role mapping found') { - msg.reply( - `Selected message does not have ${rawEmoji} reaction.\n` + - 'If that displayed as a raw ID instead of an emoji, you ' + - 'might be using the wrong ID.' - ); - } - else if (err.message === 'Missing Permissions') { - msg.reply("I don't have permission to modify the selected message"); - } - else { - msg.reply(`I got an error I don't recognize:\n\`${err.message}\``); - logError(err, 'For message', msg.content); - } - }); -} - -/** - * Removes all emoji-role associations from the currently selected message. - */ -function removeAllReacts(msg, parts) { - let issue; - if (parts.length > 0) issue = 'Too many arguments!'; - - if (issue) { - msg.reply(issue + usage('role-remove-all')); - return; - } - - let userId = msg.author.id; - - Promise.resolve() // Hack to pass all errors to .catch - .then(() => cache.getSelectedMessage(userId)) - .then(selectedMessage => selectedMessage.reactions.removeAll()) - .then(() => cache.removeAllEmojiRoles(userId)) - .then(selectedMessage => msg.reply( - `removed all roles from message \`${selectedMessage.id}\`` - )) - .catch(err => { - if (err.message === 'No role mapping found') { - msg.reply('Selected message does not have any role reactions.'); - } - else if (err.message === 'No message selected!') { - msg.reply('You need to select a message first!'); - } - else if (err.message === 'Missing Permissions') { - msg.reply("I don't have permission to modify the selected message"); - } - else { - msg.reply(`I got an error I don't recognize:\n\`${err.message}\``); - logError(err, 'For message', msg.content); - } - }); -} - -/** - * Adds a role that is allowed to configure this bot's settings for a guild. - */ -function addPermissionRole(msg, parts) { - let maybeRole = parts.shift(); - let roleId = extractId(maybeRole); - - let issue; - if (parts.length > 0) issue = 'Too many arguments!'; - else if (!maybeRole) issue = 'Missing role!'; - else if (!roleId) issue = `Invalid role \`${maybeRole}\`!`; - - if (issue) { - msg.reply(issue + usage('perm-add')); - return; - } - - msg.guild.roles.fetch(roleId) - .then(role => { - if (!role) { - throw new Error('Invalid Role'); - } - - return database.addAllowedRole({ - guild_id: msg.guild.id, - role_id: role.id - }); - }) - .then(() => msg.reply(`Role <@&${roleId}> can now configure me!`)) - .catch(err => { - if (err.message === 'Invalid Role') { - msg.reply(`I can't find a role with ID \`${roleId}\``); - } - else if (err.message.includes('UNIQUE constraint failed')) { - msg.reply(`Role <@&${roleId}> was already added.`); - } - else { - msg.reply(`I got an error I don't recognize:\n\`${err.message}\``); - logError(err, 'For message', msg.content); - } - }); -} - -/** - * Removes a role from being allowed to configure this bot's settings for a - * guild. A role can remove itself, which is dumb but whatever. - */ -function removePermissionRole(msg, parts) { - let maybeRole = parts.shift(); - let roleId = extractId(maybeRole); - - let issue; - if (parts.length > 0) issue = 'Too many arguments!'; - else if (!maybeRole) issue = 'Missing role!'; - else if (!roleId) issue = `Invalid role \`${maybeRole}\`!`; - - if (issue) { - msg.reply(issue + usage('perm-remove')); - return; - } - - msg.guild.roles.fetch(roleId) - .then(role => { - if (!role) { - throw new Error('Invalid Role'); - } - - return database.removeAllowedRole({ - guild_id: msg.guild.id, - role_id: role.id - }); - }) - .then(numRemoved => msg.reply( - `Role <@&${roleId}> ${ - numRemoved === 1 ? 'is no longer' : 'was already not' - } allowed to configure me.` - )) - .catch(err => { - if (err.message === 'Invalid Role') { - msg.reply(`I can't find a role with ID \`${roleId}\``); - } - else { - msg.reply(`I got an error I don't recognize:\n\`${err.message}\``); - logError(err, 'For message', msg.content); - } - }); -} - -/** - * Makes two roles mutually exclusive for a guild. - */ -function addMutexRoles(msg, parts) { - let maybeRole1 = parts.shift(); - let maybeRole2 = parts.shift(); - - let roleId1 = extractId(maybeRole1); - let roleId2 = extractId(maybeRole2); - - let issue; - if (parts.length > 0) issue = 'Too many arguments!'; - else if (!maybeRole1) issue = 'Missing role 1!'; - else if (!maybeRole2) issue = 'Missing role 2!'; - else if (!roleId1) issue = `Invalid role \`${maybeRole1}\`!`; - else if (!roleId2) issue = `Invalid role \`${maybeRole2}\`!`; - else if (roleId1 == roleId2) - issue = 'Cannot make a role mutually exclusive with itself!'; - - if (issue) { - msg.reply(issue + usage('mutex-add')); - return; - } - - Promise.all([ - msg.guild.roles.fetch(roleId1), - msg.guild.roles.fetch(roleId2) - ]) - .then(([role1, role2]) => { - if (!role1) throw new Error('Invalid Role 1'); - if (!role2) throw new Error('Invalid Role 2'); - - return database.addMutexRole({ - guild_id: msg.guild.id, - role_id_1: role1.id, - role_id_2: role2.id - }); - }) - .then(() => msg.reply( - `Roles <@&${roleId1}> and <@&${roleId2}> are now mutually exclusive` - )) - .catch(err => { - let match; - if (match = err.message.match(/Invalid Role (\d)/)) { - let cantFind = match[1] === '1' ? roleId1 : roleId2; - msg.reply(`I can't find a role with ID \`${cantFind}\``); - } - else if (err.message.includes('UNIQUE constraint failed')) { - msg.reply(unindent( - `Roles <@&${roleId1}> and <@&${roleId2}> are - already mutually exclusive` - )); - } - else { - msg.reply(`I got an error I don't recognize:\n\`${err.message}\``); - logError(err, 'For message', msg.content); - } - }); -} - -/** - * Removes the mutually exclusive restriction for two roles in a guild. - */ -function removeMutexRoles(msg, parts) { - let maybeRole1 = parts.shift(); - let maybeRole2 = parts.shift(); - - let roleId1 = extractId(maybeRole1); - let roleId2 = extractId(maybeRole2); - - let issue; - if (parts.length > 0) issue = 'Too many arguments!'; - else if (!maybeRole1) issue = 'Missing role 1!'; - else if (!maybeRole2) issue = 'Missing role 2!'; - else if (!roleId1) issue = `Invalid role \`${maybeRole1}\`!`; - else if (!roleId2) issue = `Invalid role \`${maybeRole2}\`!`; - - if (issue) { - msg.reply(issue + usage('mutex-remove')); - return; - } - - Promise.all([ - msg.guild.roles.fetch(roleId1), - msg.guild.roles.fetch(roleId2) - ]) - .then(([role1, role2]) => { - if (!role1) throw new Error('Invalid Role 1'); - if (!role2) throw new Error('Invalid Role 2'); - - return database.removeMutexRole({ - guild_id: msg.guild.id, - role_id_1: role1.id, - role_id_2: role2.id - }); - }) - .then(numRemoved => msg.reply( - `Roles <@&${roleId1}> and <@&${roleId2}> ${ - numRemoved === 1 ? 'are no longer' : 'were already not' - } mutually exclusive` - )) - .catch(err => { - let match; - if (match = err.message.match(/Invalid Role (\d)/)) { - let cantFind = match[1] === '1' ? roleId1 : roleId2; - msg.reply(`I can't find a role with ID \`${cantFind}\``); - } - else { - msg.reply(`I got an error I don't recognize:\n\`${err.message}\``); - logError(err, 'For message', msg.content); - } - }); -} - -/** - * Replies with info about this bot, including a link to the source code to be - * compliant with the AGPLv3 this bot is licensed under. - */ -function sayInfo(msg) { - database.getMetaStats().then(stats => msg.reply( - `${info.description}\n` + - `**Running version:** ${info.version}\n` + - `**Source code:** ${info.homepage}\n\n` + - '```Stats For Nerds\n' + - ` - Servers bot is active in: ${stats.guilds}\n` + - ` - Reaction role mappings: ${stats.roles}\n` + - ` - Total role assignments: ${stats.assignments}\n` + - '```' - )); -} - -/** - * Replies with a list of commands and their usage information. - */ -function sayHelp(msg) { - let embed = new Discord.MessageEmbed() - .setTitle('Commands Help'); - - COMMANDS.forEach(def => embed.addField( - def.get('usage'), def.get('description') - )); - - msg.reply({ embeds: [embed] }).catch(logError); -} - /** * Event handler for when a reaction is added to a message. * Checks if the message has any reaction roles configured, assigning a role to @@ -754,23 +212,6 @@ function onReactionRemove(reaction, user) { .catch(logError); } -/** - * Given a message, determines if the sender has permission to use the bot. - * This may involve a database check, so it returns a Promise. - */ -function userHasPermission(msg, command_name) { - const everyoneCommands = ['info']; - if ( - msg.member.permissions.has(Discord.Permissions.FLAGS.ADMINISTRATOR) || - everyoneCommands.includes(command_name) - ) { - return Promise.resolve(true); - } - - return database.getAllowedRoles(msg.guild.id) - .then(roles => roles.some(role => msg.member.roles.cache.has(role))); -} - /** * Takes an array of items and a function that may return a promise, then runs * the promise function for each item in the array, in sequence. Returns a @@ -783,36 +224,6 @@ async function asyncForEach(arr, promiseFunc) { } } -// I'm aware Discord.MessageMentions.*_PATTERN constants exist, but they all -// have the global flag set, which screws up matching groups. For this reason we -// need to construct our own. -// -// Also, for flexibility's sake we just don't care about what type of ID this -// is. This could have collisions but it's unlikely. -function extractId(str) { - if (!str) { - return null; - } - - let match = str.match(/(\d{17,22})/); - return match ? match[1] : null; -} - -/** - * Allows us to handle custom server emojis. They are encoded in messages like - * this: <:flagtg:681985787864416286>. Discord.js can add emojis using a - * unicode string for built-in emojis, or the ID portion of the name - * (e.g. 681985787864416286) for custom server emojis. - */ -function extractEmoji(emoji) { - if (!emoji) { - return null; - } - - let match = emoji.match(//); - return match ? match[1] : emoji; -} - /** * Built-in emojis are identified by name. Custom emojis are identified by ID. * This function handles that nuance for us. @@ -821,25 +232,6 @@ function emojiIdFromEmoji(emoji) { return emoji.id || emoji.name; } -/** - * Helper for creating command definitions. We could nest these in raw objects, - * but Maps are nicer. - */ -function cmdDef(handler, name, usage, description) { - let map = new Map(); - map.set('handler', handler); - map.set('usage', `\`${name} ${usage}\``); - map.set('description', unindent(description)); - COMMANDS.set(name, map); -} - -/** - * Dress up usage string for a command. - */ -function usage(name) { - return `\nUsage: ${COMMANDS.get(name).get('usage')}`; -} - /** * Single function to make error redirection easier in the future. * Maybe some day we'll do something more intelligent with errors. From eb1d11d59a2e90ca5a6d1ca04e781d1d269151e0 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 29 Dec 2021 03:34:55 -0500 Subject: [PATCH 039/107] Update README to have slash command information instead of message command information --- README.md | 160 +++++++++++++++++++--------------------------- docs/info.png | Bin 0 -> 7750 bytes docs/mutexadd.png | Bin 0 -> 22769 bytes docs/permadd.png | Bin 0 -> 12088 bytes docs/roleadd.png | Bin 0 -> 12469 bytes docs/select.png | Bin 0 -> 69623 bytes 6 files changed, 67 insertions(+), 93 deletions(-) create mode 100644 docs/info.png create mode 100644 docs/mutexadd.png create mode 100644 docs/permadd.png create mode 100644 docs/roleadd.png create mode 100644 docs/select.png diff --git a/README.md b/README.md index 546e3db..9420625 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -## Overview -A Discord bot that can assign roles based on message reactions. +# Overview +A Discord bot that can assign roles based on message reactions.
[You can invite my live instance of the bot to your server with this link]( https://discord.com/oauth2/authorize?client_id=692585944934514738&scope=bot&permissions=335881280 -) +). -## Why this bot? +# Why this bot? Several other popular role-react bots exist, but many of them have some annoying catch. Some have uptime issues, some lock basic functionality behind premium pay walls, and some come with way too many other features that add bloat, requiring @@ -12,15 +12,22 @@ convoluted web APIs for configuration. In most cases the source code also isn't available, so we can't do anything about it. This bot attempts to address these issues. It _only_ does role reacts, and is -configured by typing to it in a Discord channel. Every feature of this bot is -completely free to use, and always will be. It's also open source, so you can -modify it to better suit your needs, or just download it and host your own -instance. Basically, there's no bullshit. +configured using slash commands. Every feature of this bot is completely free to +use, and always will be. It's also open source, so you can modify it to better +suit your needs, or just download it and host your own instance. + +Basically, there's no bullshit. # Usage -You can interact with the bot by mentioning it (denoted here as `@bot`). The bot -will currently only respond to users with the "Administrator" permissions. +You can interact with the bot using slash commands. + +The bot will always respond to users with the "Administrator" permission. +Additional roles can be whitelisted to modify the bot config for your guild. + +You write the post people can react to for their roles. The bot will not attempt +to write its own posts for this (but will add its own emojis). +## Permissions The role automatically created for the bot needs to be ordered above any role you want the bot to be able to assign. That role also needs to have access to the channel with your role-react post, and have have following permissions: @@ -30,102 +37,64 @@ the channel with your role-react post, and have have following permissions: * **Read Message History** - To see posts in the channel before it joined * **Use External Emojis** - To use your custom emojis in role reacts * **Read Text Channels & See Voice Channels** - To see the role-react post -Note that these permissions may be inherited from your `@everyone` settings. -You write the post people can react to for their roles. The bot will not attempt -to write its own posts for this. You can then tell the bot to select that post, -and tell it which roles to map to which emoji reactions on that post. +**Note:** These permissions may be inherited from your `@everyone` settings. -**Selecting a post** - The bot tracks this on a per-user basis, so multiple users can -interact with the bot at the same time. -``` -# Command: -@bot select -@bot select -@bot select # Not yet supported! - -# Examples: -@bot select #role-assginment 123456789123456789 -@bot select 123456789123456789 1234556789123456789 -@bot select https://discordapp.com/channels/123456789123456789/123456789123456789/123456789123456789 -``` +## Selecting a Message +You need to select a message to add react roles to it. Right click on a message +and use Discord's fancy context menu to select it. This is tracked per-user, so +multiple users can interact with the bot at the same time. -**Adding a role to the post** - The bot will add its own reaction to the selected -post with the given emoji. -``` -# Command: -@bot role-add -@bot role-add +Due to current Discord limitations, this is not available on mobile devices +(sorry). -# Examples: -@bot role-add 🦊 @test-role -@bot role-add 🦊 1234556789123456789 -``` +![](docs/select.png) -**Removing a react-role from a post** - The bot will remove all reactions of -this emoji from the selected post, without removing the associated role from any -user who reacted to the post. -``` -# Command -@bot role-remove +## Adding a Role to the Message +Use the `/role add` slash command to add a role to the message. -# Examples: -@bot role-remove 🦊 -``` +![](docs/roleadd.png) -**Removing all react-roles from a post** - The bot will remove all reactions -from the selected post, without removing any of the associated roles from the -members who reacted to it. This is mostly useful to work around a limitation -with Discord's API, since it treats admins removing reacts the same was as users -removing reacts. -``` -# Command -@bot role-remove-all -``` +You can also remove a role from the message using `/role remove`, or remove +all roles from the message using `/role remove-all`. This will remove all +reactions from the post, but **will not** unassign any roles. -**Adding roles that can configure the bot** - By default, the bot will only -listen to users who have the administrator permission. This command allows you -to add additional roles that are allowed to configure the bot. -``` -# Command -@bot perm-add -``` +## Making Two Roles Mutually Exclusive +Use the `/mutex add` slash command to make two (or more) roles mutually +exclusive. If a user tries to add two roles that are mutually exclusive, the bot +will automatically remove the first one they had. You can have multiple mutually +exclusive groups. -**Removing roles that can configure the bot** - Removes a role from being -allowed to configure the bot. The bot will always listen to users with the -administrator permissions. This cannot currently be disabled. -``` -# Command -@bot perm-remove -``` +This setting is **server-wide**. If roles A, B, and C are all mutually +exclusive, when a user with roles B and C tries to assign role A, the bot will +automatically remove roles B and C from them **even if those roles were not +assigned by the bot in the first place**. -**Add mutually exclusive roles** - Makes two roles mutually exclusive. If a user -tried to add two roles that are mutually exclusive, the bot will automatically -remove the first one they had. -``` -# Command -@bot mutex-add -``` +Due to current Discord limitations, you can only add two roles per-command, so +you'll need to run the command several times to make more than two roles +mutually exclusive (once again, sorry). -**Remove mutually exclusive roles** - Removes the mutually exclusive constraint -from two roles. -``` -# Command -@bot mutex-remove -``` +![](docs/mutexadd.png) -**Printing command usage info** - If you'd rather the bot tell you how to use -it, instead of looking at this page, you can use this command. -``` -# Command -@bot help -``` +Use `/mutex remove` to remove to mutually exclusive restriction on two roles. -You can also print the bot's description, version number, and link to the source -code. This command is available to all users. -``` -@bot info -``` +## Adding Roles That Can Configure The Bot +By default, the bot will only listen to users who have the "Administrator" +permission. You can use `/permission add` to add additional roles that are +allowed to configure the bot in your guild. + +![](docs/permadd.png) + +Use `/permission remove` to disallow a role from configuring the bot.
+**Note:** A user can remove their own permission to configure the bot if they +are not an administrator! + +## Printing Bot Info +You can use `/info` to print the bot's description, version number, link to the +source code, and some fun stats. This command is available to all users and +posts **non-ephemeral** replies (i.e. visible to everybody). + +![](docs/info.png) ## Rate Limits If the bot is taking a few moments to respond to reactions, it is likely hitting @@ -133,6 +102,11 @@ Discord's strict rate limit. This happens most often with mutually exclusive roles, since the bot needs to make several requests to make them work. The bot is registering the actions. Give it a few seconds to catch up. +## @everyone +Discord implements `@everyone` as a role under the hood. This means you can set +up react roles for `@everyone` like you would for any other role. It's silly, it +won't do anything, but you *could* do it... + ## Hosting your own instance This bot is built on [discord.js](https://discord.js.org/#/) v13, so you'll need Node.js 16.6.0 (or newer) installed. You will also need your own Discord bot diff --git a/docs/info.png b/docs/info.png new file mode 100644 index 0000000000000000000000000000000000000000..bfecd29924bc7e80ef7f229d9bb78e36c250c398 GIT binary patch literal 7750 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%0Aj9s<0iY%{t-A3TV=JSL!Fr<^J0BoHM;%YA?=~T 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 Tk8UrhM$%|&>T6W1J4F5mS`l&? literal 0 HcmV?d00001 diff --git a/docs/permadd.png b/docs/permadd.png new file mode 100644 index 0000000000000000000000000000000000000000..de2c3fc55f424e6053dd591e5bd592f593e72622 GIT binary patch literal 12088 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ëmS?~BbY5tUAo^4&l_o`WJT)W3E<8&4d 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 E0IxX(@&Et; literal 0 HcmV?d00001 diff --git a/docs/roleadd.png b/docs/roleadd.png new file mode 100644 index 0000000000000000000000000000000000000000..74f0be5f984cf32cfaebf7d30971d7cef2ab8470 GIT binary patch literal 12469 zcmbVzWl$VZx9yNX5zh}=GU>Y&Kd?e{ z5&hdm>=Pei8YW6SyMm`8tOD&5JNvGJhl-q*g9#q47hNllNjs z3Y{X@)nwU|h$T5lBFMOgTk+3ISLzF^Y=3M-;Yy8zYY-{Pu$=rLyo_#MkeTRo)_Y3IG3_>T{PK z2b9DVSP0OQaghER|CTX825#yx9h>o8_C1(pwH6@)3R;sFhQ>4+`W97p{`1nl)l0fOEYRR<1>< zPz{&Vsj0d+UI-rSrCPfClUF42gW%FLtP0oYk%&qOlsE8A!9n4Nc+t|RPqDOi_p&hM zG|Kt)xncj$u07}9T9sd8DFyFWA1)6U`@Y94FBOFg8ZOPTy3W3S^{U!(dzQlrSHo7v zvu!0NhesO>1~;2n8j{juCE2^ZMXvYHOczX$pph+}WX@+8az6CL%+$@qh&b9Ir%2m4 zI52c;ODp>nN#3oXwpKfB&c@5e5zMYa)?Nw=U;rZ`L93>@-iJyx@r49xBIM+t6R;ZM zpFHh;jSxQ@QotthxqN2{Ek)|=M0m1TX-!c{S)4#$&v(jotI|za*g2UNAXjFd(9%U< z=7%$QUBiq{R(v>#2Zd%%I_#+U_=xI|1w4)?_7Q=l+g;wJt1K(x47Xhm`?Z=NF&Fcvb4Q0<~7EwQE z#iRLYR_vq{6*;Z`>}qOi`spr+yxVbkcRy3olRjU!H(7v99TyrujjAFb+9>Ae7`6?c zVrR2t!4j^nTEMmpOp0*}-V1GKIJ@(uQFJU-)e~U;LBp$C;6m)~nin+3kYMzpUbsS) z^>Ch`T;o9?G<0{UyiBi(BwXkru+HJE{K=OX^mKo{o{*%s6<(lM1OI{p?C!Kd#>~#+ zEkucVtyLiU`XE%Hdq1dE`z};XuSl!0vh@b$P2%CqHZeg{J}4m?=)`jHR*w-*Sg$#f zj+be4jauh^zMleW{d|K2Bj*2!Dfk%TgdECYu@qvKnQ1$(TcB8DJ|SVwNvP|43CO%salT zc){xe7t|1Vyjl@THQU;DUsC0pUhm5h!6#_Jm-Y|N#{rU zVk%BeaYCwFvgw!yTW*PoiyPWu>;QamaPGB4o%dhvM83sHB5uQr9mYNMSNE5&zkUc$ z^VRFG9UYxQtry~5Z5FGyXII~#qEnIcr`vUCg?8y@OYO>D!j{8Fw0zsP=jcl%qG3n# zb-^}^ZlIk_=POI(p~R{$1&XZRbMh#tsG&R_wZpDh|GN5bl(yn=2oYbio3DLQtJ%utN83-aqqIBkIkDxj`R((?7aZXVO(fe0zo6 zH@jW!Wx%Cjb{Qet>L0#!+h-ymAmHvjXvA>u%-Y=C%rykKXY)4PM1z_#A0ZfnlupSM z{++hF$EFeV^(&DgGmBpv1XlfMh4W50V2vzoTSr^l{WiyeLFb&n3%=B~_gY*NHYy=1 znyp&)*?!zr3MJcOs<$9?eOl(a)sc|XQdHUEup&F#FFzm0KcKP?a=FKPS+L1cS69d5 za?in2(8tb4LxhKS@g}gpzwl_Wk@Ty@yw3yXTSCGx1~s_PRA3-tZnPf!yI zKIo=wt5s=6YdJeQZXCXsa+u+{fY!cm6@U{5VG<3l3BQySTGWQ^a9dFVj{WKV=7{;U z2y3MRJ%q-U%;oDg&t$?GgtxZesy5xWh`v8rVf6|uWpH>*@%@CiaV*7>? zOP<$}Z`PMo;_NjX-uaeBuw6|=q(PdLEP+dtsx$B%rIUZccPTT}+lw-9oHlHF$>AS3 z1Yp%OQ8OA>YgWhRPS&Jn^sgfLoaeroKCmAsm~m_=(v;MhMLrJ=-Ve+4L+1@Pnhsn{ zqdQ!?qg3O~N)k-Ets!0ZPfo3Et>uFacC#}dX7?Qa{QaBcyK`lu7^{Tv1{1aJ^2XE4 zBL`|;nFI!REiR&xl9Efym)rEQNT4+rP-FaP;YgS1?l*DV|z1RC*ii@d+4H@brYsCzr^o!$jI^Q`Q*^31>~c;XKj$2@qDO7X%texG|Zo!`!{ zzEBN0?=Pib_ZgKB78IGS!C~rzFo#plH45S3RzUG$#p{R?CfwTLm54d9Yp8}a%aEoHI_Jb&epRNgU>izwD zWo;6st}>Z`j(ndm>Q(bxWYqHQSzgWv#U|N^LB@=UPajTiW_B2t?bz9$GIM_n-RHl! zjAKZK<9fDz4^U8ev|Fc9HOb49tG2$IZGD{72Du*J$H9Frk>g0x%<0%Kn(=OD!<}y3 z*MqmVc51!vxSdaCptXXZK84d13jNCu)Ssbvl$4Y#Zm^-po1UBJdx!T8PP?R+2hccV zOd-TCo}RprqXnIP&(Yq$>o8bvlf%wB5FIV77frox)m;|rt+;`BsJ}shnMZ4XK229f zq^RHC3cuTpyxgB!oW%QphX-$jh^iF}Dh7`V3~tqz{Z%1lAwDwMDtm{rp#7d`MM^kN zVaiNXC*6ujn2j8q9ZxNdG%$%kJMUgl?`=a|AeT;ya%WNfRELK43Y)?dN&d(}f5Vez z)J)|mCEjJVYHO|Q>#*MG3H_`~92Mf)2LL=4trC?Y$#CQ#xKg{rK33Y8+##s+%nG?_)b#*2$w ztF-4=`g`}O@X*b)w6kw9SS-s|*S8BomQY?=vwN43o<4ZVzL*<3bn>+-)Tj6xkpJd* z_U3=X`jlH=ENPsIe%jd*vk)syg%r_mya%P+PGym-RUucVL>7DT5^L8Enw7^-`)r!V^J~8s4;_Wj|i}Dcvpn4fmcS{Az?RyzI z`T@m-o*!(BC{U@2iR{Yns+kna=nrI% z0xF9}v@$+96&-<47Flq#Ce@}PA^}oHzQ~V3`u*JgJy4vs|4hDwf-+eWv4|0e@WYps z!glfu6o2`P(&Jd6B79e>lD+xPz;JP{ReQxRBI4WS-Nqan8^*@oR>Vxaaoe_n@heYB zk<(|BjvqS$S8^s_AGDCge3w}57cn_6_QvC=;gN^glCf_77P_(5yvZ#m@pk(S2lNcB3eIn$nQ5} zHi||#02&M=RJHLbe%Vd6Fykg%LKH~dkEfP|sFxN| zx!2P`P_b9~6-hoa=0k+O7aq>CMg7&1+GdO4{s+<5}go_hNDuK z)>k}2Y@UC^HFb4UktO*Lkq&?yd7!c1e{)~uR+jPcyv}2ZkJpA|>Ltb)BZDi%Fp&S| zGYQkTIY5qAIcJ||x7Pi)V49lQ&N-9;`MLSG^mhOx8k-7$$yCtbyh9Xj$|x=PQ98z~ zzrAx|ZrOZcu7($(cFt;CWH?C#K*90*S#hFizt;HA%Dvrek&{+0Z{CANgoV|(aimF- zrFr7D2Rq}FBJ)*q&QL@*w+CmD=`Vxj6p}w_7WtD+ms>UuWyM##O~@_MNq(L4*K8nE zK+15EDvZ7ECp(j3d`gs4+kNr!p?qwjvG4TdLWplAmGVz#-t;uLFAA4iM~hM`&B{@k zG8A`@CLH^8-!$kxw3P4E9sf}Atq)^d{_SFPx+W|tMqI1a`}c2(K~J#LWbYQi)BROJ zQ*lV^V+%Y1U$X*NBaxVmZ#uw;bn6fDAvf+^uHwKRFewb{Y0letULAl#+XGuIGu`Ta z9$fdFd24HH>DwyG%A^WtbW(2n5u-@>RQJcQY<21dyJO!st5V(XDQFv$rU0WE9AXt4lExX4|`7lAt7&Gym&lrpQ|Qcba!{pR#kydNt2Mk5*yzu2dS2sEZsUVJbQzwgvRnF zv#6A1>V3m~d68y$1*wpwQ9g7S8%{Nolawd;&v4@xb=r@bE2(>sC0faSp-aYR&lij> zBBk}bG>g4Ei=T* z@@1UmdL5ZS?o}wAGF()^ZXD^UkF&e6!Q;L41_pyg;0s18eZmtnZt{sf93x*;1KW%_JUpB@sr9xddGFx~+X^7jw;X_BHu zBNvmIDO_h7gZTQj!&bk-HEh|;g+GnkE~+Js$iN^c{j*1GPcR0%{ujuLmoF8{rU8f$ zy|>v{F&2<92Wo9?-J5E}R*YeX>1h%%rE%A4B%NfoN+J1?rKxggVs@CF^d zz-)}f-NU060!O$$5%Qx1qml5x#l*x+&(N7`a3KP)fBRDd1n!Fnt%{bUa=KLKc(@_0 z_Q-s`r=ITY{Ni~7L!#Zn!>KlS!lVrosoNQ8DsrNU2ov$OCHbUQVLJU1NHcHDHuA7F zu9hXks&wlKlEm{2{)DW%H?>fd7`L|aS48br8+;uY9?o|?UT}B!d`pTKot8#4IyyRi zR?#zfq8gi&Wama|eQalJOsNCgkI1Ff9_Tk-zDIZM*agmtz-LAC2_>mel>&p2%?yor zd>=)d`|f4sDUh!u5n5Y@I@4s4i>0wL*CX#v$}m~1o-K{zzTdz(;}=FfFNlX3hqXij>(ac&776Vj5FmBnC8<(4ReRy*$}6)V$I%lJlY#ZR;8eBusAA7*}9 zynmQsOFDV^3WMxkor6X$^G{Dt05Xu6Zbsv2Xr4ASAdK%jm#d#~(kFx!WqQUwJz$R4 znnjuzd=7HDb`@r=9dvl*c>pbwxY&uAE>%ITh>KGph?@{~+;2HX4G*`c&v<5}Efxeg zvzqvp>)1|g8o9}Q2cuZUSg`cBY~QE*Z?U4H?w=32t*c9g&K^C6yh;c;%)b!p>GdX! z#-D8E|LyBb^Y{1WAY>Hqa?P&n=qRYieut}C2+fE|F;MBC1P>>lp@Hr^JQ(h}A5oIO zDg+PE`IsrIyW<1C3mUe=6>uOA8V^Db;dK_sSz+Mv^7lWeGw8ttZSCyD#>IsvC8;%Y z`x_b>%HtpfborHBHvN11<(`1?@gPt!r=~JJLEeOSy)g?uEp7j9*Xus}%YFsfEFPoK zt{IQty;D5_yzTXj%r{e(^?O%Tfq@)k)I0gxrYRLhUUf|(gj`!mGHF$Kzb>qtj$2Gv z@cVzqn%q&SYHLTBS#*?D_*6G`u(GmBXI|0*w9EQjjd|zu&Eo;oFkNcZc5UOp(&M9v z2jJfdc^6^FQmVZFPFC0xXt_Yen5N51;_2N>!wM7k?*2T%wV99ZjJ0nXskY?kt{^ zCuRw{q`oG>4=qbWWo0dr$9ZEh4oc9pu`pQq#+vXX!{^G8s?*|{prKmk$_OwHeyhF@ z8NdPd)6>c= zhaJ!NT91#9=8FyJj9T@^&{C-D*iA>a|Nl4=Z0uSfKe=irs|3#-5*oB+;9 z^OyPPbYIcwzFF4PFEDo6>V*(|spl6>p<;)x55Sz=9XGDp{+4q~B_wT4Q9_f#OiQlS z9qYFX!>=LFqC1pScU7;9F)p33JiWeVijzjz*x0m~Yb{L;d?Ko9o3l0MNU@*PwcDnlq0)*9 zZ)qXQ)YUaMGh22h@&cYVQK_RfG!_#RV=_~wOs}n@)8xF5)$v$6fR)yE;VdI-%LD{Q z_k<`@dk2R?;cst3Lqj>NR))`)f2(E<7>krO`&u9WO-M-zh4=~SKL_mX_#Rg2)YM~M zU(fbT#Q{+ZpxQ9^3HF;>yyl)VhiW56=TlHi@IK=b+gL;6e{LO&21Z7|i?I=+l}gY}Att1DNF z+p+237Fe5+?xT=U7PM?uADAzOhBnVil+>FY>zA9jY!pR$QLasHOBtK!)I12BOqWn7C@28D$at#;d(es-sUGCX=3lO$U{fcv z9Qo&zQn)ykfIV{^0)OZ~_u??_Z%Ys10UL^lpiAuFL(*^$GQLnM0q11!xt@=I-K1lp z7m1-{o18jHHAcz(LI1{ojfK-!N%Ae?y6wk*Vw-#xk zxc_&P;niM=TLmxYyI?@6BbNL1zfu_gZ(Y((;OX_y*bo)_CYD-wl_48}6>mBr%@BRM zv+Q)~ad28o@Ce&R@^S{fBkWW6K}8W$rL77E%v6&jJl|Jd;L+RX?BW7xZL(lU`?q(> zT-{l^0Fhcn7IX6UwrO0dcY9%veUp6xcEztz4#oX9Q+pxfpRvoB$z}D135-}Jq{2R1 zwQAZ5e7_2CxH+Y-JF*op713xI^$}Zc2qb*>PCRQx;OzXe)uQ<*{X>K8qOf)Ow{j@m znKr{;F}JZ#J5j>4Aq+la5{&k;$kR*CK~0&4ls{M%eO4=Dt_^a5!Is(d5h4;OCyjtSNvtm zdb?1pbCg));teY_qMlPrxX?aEuD8q5{be^>IJsDFH=Ee*p^*g*)b;kE}_b;3Wj#HIt%jzG%T&EjtB;=EYr9F-@_x>N%7-uku3d3l?6$g-Kxpj zahhcNgt(EbhNx(Y=y`vni;~0L-Rk>iWMhq;wwuJsma#VIJ&y{{7&KL$g1p<7E=6~$ zU55yuGe6+R_z%ro;mbqtZf!d|J9Cg1-M+ZK?w;2$b8DjnPgfiUQ-T{A3kN-S zGms)ko?`#V7 zOzN;Z$>i1%f@i=%ryJ=Su0xmm%XJG6N>48z0m&zMb|qP_B8x)(;c9mE8yJj`-PDu} zFn7BmgFjGg_~r{-3$zL$+f|cn^95X_xZ0J90ub&M!FmFYJ>M6PhZIs+mXSewdta^R zYcbkZ^y$=E8c2zGoyE#Z793g?78^3aEy)Mf_qLKpVIa_3zJIjPUR{dtb}D>D=n- zw{605%G2+LJTpc^6)1xL85AWYlWvoGiIGBIBL*|SQ22OI&K|m_YK7*={S^_&e72JD z<^9cWe@q@4u_q}IO^nS^Rf`j=cCMJfn;22?sB>Wr4$0K!Pqxm{5 z4frzDu19lSeW*f(O>^n30EbkGXfK)41WECA>U`Fkuf6>=}J0@_$YqQ`? z&di*IF62FwBn3C)sfwc>F`lcg0SFRDI>rP}tE4*DV>aLCeKNs%%c)#3uX{}V(N+)k zyQ^8!!9R{CZF%@YzVu^)+%Y_LtKx~qrhf7I0!khX(Be)9gJ=_%HDGwlCoOAu}lcV)AN1l7m69Z`TXuHU`rV)8WpNT z>v?_ZXUCF&z(&AdEMz3UItCF`fAeKi{GD_P$9FkAh?uqY2V2`p{>SkElLL3pd*w-X z_LPSz4?yz9en&EhT4$)!e_qgAfe7&TwFyRp4J5KQXZzkTWay!1o^lmy&ReBw(p zGab&)&kt;bpUAX7TGC}P>vm6<$N?&-#{FMIUYDc(6`u!?`(Xw5XWvJ}p5Ts1fMkM& zJ0){k;o5aPLAHCH?#@jb9`DOWT;93bQZJWkRWP%V`Q2Tt?zEh!*4Qj^bw2i)4Q|Gz z@a>9iY;5e$)lgJ*Jo8Q!%23eJ&6i@>+1cs(T&b9jWy*Lz@^ts~xWk`r+%G2vjE#-$ z52h_9r-n{q-=Lx8Y8ZcdK7sFm#!Fo!3S~W_{5r{)bfrztHZVUsn=|80#)gEL_mV=a zh4WktcOsHJ0HXm*vBS>*uWY?p!810_XMY-aeRfmT*P-kE+6RpMNtGej>*iTH`IPbk zZ}=noCR-#SXAjs6Hk2jchT^n4yenzSE7fry5?%s!HALUZgZuO}JDJT@uWNxkZ<><; zV==u8i{`de`qOp&VKi&$dipp4rT}vs=5^9Mf)&RWbF7 z6bCdn9d`rRC;Z4A8p|2@EqhfPTN0<$tkx5fK+;cj>Zs!4p39>Z==p`;bKCswkX<^D z6Ruxtt2dL*?`J98NwSdNE>E{>kSujW!6f-J;XPm`?KNkq_PD?W)z&!yxf#_B2B9&y z7|=XV2WVzHiu>~9$yna{sWNIQmZ>uSBMWfEasb0|!)+b9 zS*wXry9d%Dj2DdEmpYtbwq@R0Ed{eF!59rP+{@PfvTiYuxD^9Cn6|pB`>5 zHlu~uY?nUcGPw7ZM!lm5sxukF1^gYs{@VHjkPR28Rb`fI)HO&ibF*J}4KV0EBkRNZ zw5!*gR^a+1HD~Vc3l*fo!a2jq ztlt6t#_?c_HI>VvtJ=UwqsH)^VEutU$3ZBML*UjHA_mElP3XGuumTF|MgQn1<^5b& z8cCyoSL50GYdiHs8SgEyD{QITEGu=)LwTA+hM3#sO`8oB?OkUS z)XfFHv^wO80}5kQP*>OI{dD;fx?mNn~W#so0*}^Oz(TPq+ zxb?IWOQ7^jMMYY^&xd)5)N$_uYL3|QCITf*V3(K{_}%+cMMEFz0NfKB8w&v7>ZL$W z_I1Ktt(BR?5c=sxx04k%pcxh-V zjZNnn?7}I*w@`FSs=tpC&O5`i>J3LmTu3Nm;pP}VT?P7R$JWBw@KH+I)MDSFvr>6ecVJP{7p1MYClcx5M zB6rHrHm{qr`$M}GPvZAaw0wQ#Y(P=Ohg9XUgR&cBT5xQ6rKGL;z+{2mIbfp8j!*Sg zcaGa(cQ=%@pX0~J#jRJY+a1l{eh3;cCg-6;0J*uz)z($bRY;XVe_bmH01OWPq0LKMsRrb<%dol$MF8eSukEY7oygV(Pye}U84LX=E zk!fkDxHG9ce&*2vBLBB<-vZbIwsf@9&#o@E{Ug(a_V)>zemBXtsLu0ETnAaB?X8B( z3F!^y^hhvrTR&@NL6&P@cB#-`p&zoJ-IQ6m`FM=dWEO$rs8!EYOhN!;L@txY#ppD= zw6s)As+{%bPoP#M-dcIPV@1xQh91y7lE%$k$H2xG>$E#M&j0}c;7F>NCS%objoZyB zrH~Mw9|-QbclC;mZMcIw;C1BI`F41Gd~%1HOj-lwbwo3g4fvefTUA7a9|p_pr{^4? z3r&RFA$ib-`7;aw*F7(_B_N$VhR-`uW51h-@atTggdQJDkZFWUzyl zzC1fKv$j>zP3O#6z_PSX--HeF)iU`h++c3*>NU(sYhR~_MpAIoBms$1-h{cmtLx5s zaIfR-sX|(XcAM_lbw&%I-Ke*=4)^pCa-kVqU$D!URbcBlI3N>Ncw{%GrG3hih^DQ3 z?(Cv{g-N1M(7#$L#{S#w*zv2k+1crNw$6S44nS5*XL96p>y`HeV=DdB>-=RQ2UMrY zmqGuD@3XpI1tN=!j$3;QmBzXT_iE(L;9!Mje?pOLQ>Q*{unL%b|ctF7n@|$A0@SWojK@y~7 zW;lX)lxOnw@rchgCSwOqZOz|Ucm#BAjdUf`DHWie4J z@bVtLpt$(waD>zjZylS(a_LI}FZAvzTm2u=i{~b!Qx#fznaS7uHjA#Ny~9Zsiw*30 zK36d#=l_XxfU3*I6_uWzP9H5cGBDt<_p>DARNmX?u=?SmAYsLI!c33F_K5cR0=Aee zO`VHDYH*c$^}jrIECm0Ap6ch|tTTIVIa4J?#cs$7JjB6>RDW;nyEgRj&SVPr z#nYjtPoe9opeb`gFYjJX_u`w~arr%V&mn_=#TGG1$NU|Xv252NpiMhEVg>s}lQ*s@D z>c&RC7CG$i?BCcIe2a5)CnKmB=zfu0+8o|K5=YIC{EPDI>oUnK z2E4YmCPd-}1~PjyBhR9|-7f#&xS;jHO~oPty#RQytGFl8hIo6fW>Zum%icW0jlLpI zDRT65K*o3v0du0%wHAR3*EA+9gNz@welN;+d!8+7*NHYG7Vg?Hj3*h$#Ts zsK+nMADgv)DJRn>1@YtSQ1J62)0+y-3rzY?2KE1f8k5B@lTm~R~U=!id zVC~yDbGMNW$i$``DYl6Cl$N2gX&4&y`ku*_Kq~pJGZg*hGyE@6A}^`^(Ww0+P||*baj8 zuWZ12WqbDUDk0TF>n);ib(}mEIJc?kOh($ literal 0 HcmV?d00001 diff --git a/docs/select.png b/docs/select.png new file mode 100644 index 0000000000000000000000000000000000000000..2110a3ef731b944b46cfd110470b14ba0bb51a43 GIT binary patch literal 69623 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 literal 0 HcmV?d00001 From bcad64115914d636d49bef28f2d1cf4438bf607a Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 29 Dec 2021 04:24:23 -0500 Subject: [PATCH 040/107] Add command to work around Discord mobile's lack of context menus --- README.md | 16 +++++++++++++-- commands.js | 44 +++++++++++++++++++++++++++++++++++++++++ docs/mobileselect1.png | Bin 0 -> 50645 bytes docs/mobileselect2.png | Bin 0 -> 20032 bytes docs/mobileselect3.png | Bin 0 -> 37407 bytes docs/mobileselect4.png | Bin 0 -> 26092 bytes 6 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 docs/mobileselect1.png create mode 100644 docs/mobileselect2.png create mode 100644 docs/mobileselect3.png create mode 100644 docs/mobileselect4.png diff --git a/README.md b/README.md index 9420625..0e95d21 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,23 @@ You need to select a message to add react roles to it. Right click on a message and use Discord's fancy context menu to select it. This is tracked per-user, so multiple users can interact with the bot at the same time. -Due to current Discord limitations, this is not available on mobile devices -(sorry). +Due to current Discord limitations, context menus are not available on mobile +devices (sorry). See below for alternative. ![](docs/select.png) +## Selecting a Message on Mobile +If you are on mobile, you might not have access to context menus. Don't worry, +there's a workaround for you. Long-press the message, select +"Copy Message Link", then use `/select-message-mobile` with the message URL +instead. + +| This is the Message | Long press and Share | Tap Copy | +|---------------------------|---------------------------|---------------------------| +|![](docs/mobileselect1.png)|![](docs/mobileselect2.png)|![](docs/mobileselect3.png)| + +![](docs/mobileselect4.png) + ## Adding a Role to the Message Use the `/role add` slash command to add a role to the message. diff --git a/commands.js b/commands.js index 1f4b94e..614ddd0 100644 --- a/commands.js +++ b/commands.js @@ -68,6 +68,16 @@ const REGISTRY = new SlashCommandRegistry() .setType(ApplicationCommandType.Message) .setHandler(requireAuth(cmdSelect)) ) + .addCommand(command => command + .setName('select-message-mobile') + .setDescription('Workaround for selecting messages on mobile') + .setHandler(requireAuth(cmdSelectMobile)) + .addStringOption(option => option + .setName('message-url') + .setDescription('The URL for the message to select') + .setRequired(true) + ) + ) .addCommand(command => command .setName('selected') .setDescription('Shows currently selected message') @@ -226,6 +236,40 @@ async function cmdSelect(interaction) { return ephemReply(interaction, `Selected message: ${message.url}`); } +/** + * An alternative way to select messages using slash commands instead of context + * menus, since Discord mobile does not currently support context menus. + */ +async function cmdSelectMobile(interaction) { + function reportInvalid(err) { + logger.error('Failed to select message by URL', err); + return ephemReply(interaction, 'Invalid message link!'); + } + + const url = interaction.options.getString('message-url', true); + const match = url.match(/^https:\/\/discord\.com\/channels\/\d+\/(\d+)\/(\d+)$/); + + if (!match) { + return reportInvalid(); + } + + const channel_id = match[1]; + const message_id = match[2]; + + let message; + try { + const channel = await interaction.guild.channels.fetch(channel_id); + message = await channel?.messages.fetch(message_id); + } catch (err) { + return reportInvalid(err); + } + + SELECTED_MESSAGE_CACHE.del(interaction.user.id); + SELECTED_MESSAGE_CACHE.put(interaction.user.id, message, ONE_HOUR_IN_MS); + + return ephemReply(interaction, `Selected message: ${url}`); +} + /** * Shows a user their currently selected message. */ diff --git a/docs/mobileselect1.png b/docs/mobileselect1.png new file mode 100644 index 0000000000000000000000000000000000000000..ba0df431c4019a7ff30950e745cb74d8498cfc6d GIT binary patch literal 50645 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≠G>3#u2G+V`z*X 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 aigjXt?dMsypgc(12q`f+(fo%`eE$!=BOhM? literal 0 HcmV?d00001 diff --git a/docs/mobileselect3.png b/docs/mobileselect3.png new file mode 100644 index 0000000000000000000000000000000000000000..0bc917f473fd4bbeeaee5c9d1463bd517e4ca331 GIT binary patch literal 37407 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%0DZmHXq(wL z45U3M=O<0)+Aiqfkom`?nT$h#Q}F=rht^lOztuC2Wkucyd5>aGN;J&7hd|WjxQ|Da z-#nuCNx|aI(^#{Uitz`mg5RD7RtWL&p5Ex)4coGD3yjAIHKg>f`0zQ)l7AjtsI3F^ z%uIeixv`qIYT>d=tSPw8*Bei3!L!Wt+m1>ZJ+b+EN{YaA)R$-Xm(r|o^BLoPkB6rS zSUu00HK7;9Ri*j)Tf;F^!PWK7bw|IvY2N5t3&Lr<+52$;~M(1`<(-Hyb|AQqOhOVTe*rt%}MnWNGacjK?yv(q_qC9Ld(cU=*% z^4^7OVYb_DzUvt;cjxkCTs{DG;s;5^ULEmsMac~m;)4&-qIaqDrp<_k>kM|219d7<-@umUO&B8(loc#XIEcEmd%Z)2(xpJjlX09@Kehx8gfgOgt#iSeP=5F z4Sf0=5!EXCkG3V|=Wt$X`NcJ2_Z9D@*+<n@~QmK zz^AW1OE8}(N3*P(dA8k#f`0W2Mb%dQ8{!X;h~I27t?LP8ocE?E`B*jD?S@v>uPWP< z$Ooe0lfjdyn*D+`LV|tVvEV<=5GM-Jdtf3O zPc9KM{5MpSgKt6Th^IUaU(dn{9lfOH+Zwum2^!at6g7Q^|3;r~{wdu;9mKKy!&(eO z@@@drGv@F*DHJ}VSIFSVtgDYu5Ygj4XVYpP?U`hw%qseySX1bAv2_QwXx3*L}7pk3j=Tv^++`+0p&>aOK;x zU;Dp>618;eoU^fr>APs@a3o;5eSpob|^Wzsv^!^S7#+#+A|mdCkB z{0%d1c~+M#)QK}Jdu?dbW!it1b8Sx#gAEy-9fn!*i?Ll0_%udwdFbagX@L@P!Ab|A zJ$9WLo6w{8g;n&R@++ME40$x+nq>piKbMHj_+z9(aoJlOv$2<~5&43^Tv)77w;s+j z!Cc)Kzj?J(;GFxzdHj@po_venzR29uK#8N-Q{$o!CD}CWTw9WRi7Ue9hL=ZT=V)sj zISwcCSq*0q%CxWUY-sOT%KdS?Hcqc(*(89fn5mat>9!2zf7)wxs?Vg5*$J6KMJn3a z?ob^x26v=KL}z>jqQfqOs>-x+2bE?;8<75l9Y$o8WFCRNCijZ zvICsxno|~?ZeeEA>#vSYY&#nXU@}7{O$Mtx?LJOZcP+Sz>rS)Aq5mg}>+<*G>)ZEh XRWT4)Qv~4K$KFUw$ca~o>ihpMZcHtw33=DC| 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 Date: Wed, 29 Dec 2021 23:37:16 -0500 Subject: [PATCH 041/107] Move onReady event --- events.js | 29 +++++++++++++++++++++++++++++ main.js | 10 ++-------- 2 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 events.js diff --git a/events.js b/events.js new file mode 100644 index 0000000..207433c --- /dev/null +++ b/events.js @@ -0,0 +1,29 @@ +/******************************************************************************* + * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * Copyright (C) 2020 Mimickal (Mia Moretti). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + ******************************************************************************/ +const logger = require('./logger'); + +/** + * Event handler for when the bot is logged in. + */ +function onReady(client) { + logger.info(`Logged in as ${client.user.tag} (${client.user.id})`); +} + +module.exports = { + onReady, +}; + diff --git a/main.js b/main.js index 90d2606..e95b5a3 100644 --- a/main.js +++ b/main.js @@ -21,6 +21,7 @@ const Discord = require('discord.js'); const cache = require('./cache'); const commands = require('./commands'); const database = require('./database'); +const events = require('./events'); const logger = require('./logger'); const { unindent } = require('./util'); @@ -53,7 +54,7 @@ const client = new Discord.Client({ }); const Events = Discord.Constants.Events; -client.on(Events.CLIENT_READY, onReady); +client.on(Events.CLIENT_READY, events.onReady); client.on(Events.GUILD_CREATE, onGuildJoin); client.on(Events.GUILD_DELETE, onGuildLeave); client.on(Events.INTERACTION_CREATE, onInteraction); @@ -66,13 +67,6 @@ client.login(config.token).catch(err => { process.exit(1); }); -/** - * Event handler for when the bot is logged in. - */ -function onReady() { - logger.info(`Logged in as ${client.user.tag}`); -} - /** * Event handler for when the bot joins a new guild. */ From 03825f52c86598ab42116a7bdab3894f80850d0c Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 29 Dec 2021 23:42:13 -0500 Subject: [PATCH 042/107] Move onGuildLeave event --- events.js | 17 +++++++++++++++++ main.js | 9 +-------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/events.js b/events.js index 207433c..8502619 100644 --- a/events.js +++ b/events.js @@ -14,16 +14,33 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ +const database = require('./database'); const logger = require('./logger'); +const { stringify } = require('./util'); + +/** + * Event handler for when the bot leaves (or is kicked from) a guild. + * Deletes all data associated with that guild. + */ +async function onGuildLeave(guild) { + try { + await database.clearGuildInfo(guild.id) + logger.info(`Left ${stringify(guild)}, deleted all related data`); + } catch (err) { + logger.error(`Left ${stringify(guild)} but failed to delete data!`, err); + } +} /** * Event handler for when the bot is logged in. + * Just prints the bot user we logged in as. */ function onReady(client) { logger.info(`Logged in as ${client.user.tag} (${client.user.id})`); } module.exports = { + onGuildLeave, onReady, }; diff --git a/main.js b/main.js index e95b5a3..9d78411 100644 --- a/main.js +++ b/main.js @@ -56,7 +56,7 @@ const client = new Discord.Client({ const Events = Discord.Constants.Events; client.on(Events.CLIENT_READY, events.onReady); client.on(Events.GUILD_CREATE, onGuildJoin); -client.on(Events.GUILD_DELETE, onGuildLeave); +client.on(Events.GUILD_DELETE, events.onGuildLeave); client.on(Events.INTERACTION_CREATE, onInteraction); client.on(Events.MESSAGE_REACTION_ADD, onReactionAdd); client.on(Events.MESSAGE_REACTION_REMOVE, onReactionRemove); @@ -112,13 +112,6 @@ function onGuildJoin(guild) { .catch(logError); } -/** - * Event handler for when the bot leaves (or is kicked from) a guild. - */ -function onGuildLeave(guild) { - database.clearGuildInfo(guild.id) - .catch(logError); -} /** * Event handler for getting a new slash commands. From 8591693486e7c480002d4ba8fa1947c09dd893f2 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 29 Dec 2021 23:55:03 -0500 Subject: [PATCH 043/107] Move onInteraction event and log interactions --- events.js | 23 +++++++++++++++++++++-- main.js | 9 +-------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/events.js b/events.js index 8502619..8fa9b83 100644 --- a/events.js +++ b/events.js @@ -14,9 +14,13 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ +const commands = require('./commands'); const database = require('./database'); const logger = require('./logger'); -const { stringify } = require('./util'); +const { + detail, + stringify, +} = require('./util'); /** * Event handler for when the bot leaves (or is kicked from) a guild. @@ -31,9 +35,23 @@ async function onGuildLeave(guild) { } } +/** + * Event handler for receiving some kind of interaction. + * Logs the interaction and passes it on to the command handler. + */ +async function onInteraction(interaction) { + logger.info(`Received ${detail(interaction)}`); + + try { + await commands.execute(interaction); + } catch (err) { + logger.error(`${detail(interaction)} error fell through:`, err); + } +} + /** * Event handler for when the bot is logged in. - * Just prints the bot user we logged in as. + * Just logs the bot user we logged in as. */ function onReady(client) { logger.info(`Logged in as ${client.user.tag} (${client.user.id})`); @@ -41,6 +59,7 @@ function onReady(client) { module.exports = { onGuildLeave, + onInteraction, onReady, }; diff --git a/main.js b/main.js index 9d78411..4165d17 100644 --- a/main.js +++ b/main.js @@ -19,7 +19,6 @@ const fs = require('fs'); const Discord = require('discord.js'); const cache = require('./cache'); -const commands = require('./commands'); const database = require('./database'); const events = require('./events'); const logger = require('./logger'); @@ -57,7 +56,7 @@ const Events = Discord.Constants.Events; client.on(Events.CLIENT_READY, events.onReady); client.on(Events.GUILD_CREATE, onGuildJoin); client.on(Events.GUILD_DELETE, events.onGuildLeave); -client.on(Events.INTERACTION_CREATE, onInteraction); +client.on(Events.INTERACTION_CREATE, events.onInteraction); client.on(Events.MESSAGE_REACTION_ADD, onReactionAdd); client.on(Events.MESSAGE_REACTION_REMOVE, onReactionRemove); @@ -113,12 +112,6 @@ function onGuildJoin(guild) { } -/** - * Event handler for getting a new slash commands. - */ -function onInteraction(interaction) { - commands.execute(interaction); -} /** * Event handler for when a reaction is added to a message. From 95e8d04d45d94e86aa32fafba73f43ff3f8de3a6 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 29 Dec 2021 23:59:14 -0500 Subject: [PATCH 044/107] Fix some style stuff that's been bugging me --- main.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/main.js b/main.js index 4165d17..e4989f4 100644 --- a/main.js +++ b/main.js @@ -24,13 +24,13 @@ const events = require('./events'); const logger = require('./logger'); const { unindent } = require('./util'); -const config = JSON.parse(fs.readFileSync( +const CONFIG = JSON.parse(fs.readFileSync( process.argv[2] || '/etc/discord/ReactionRoleBot/config.json' )); -const info = require('./package.json'); +const PACKAGE = require('./package.json'); // Everything operates on IDs, so we can safely rely on partials. -// This causes reaction events to fire for uncached messages. +// This allows reaction events to fire for uncached messages. const client = new Discord.Client({ intents: [ Discord.Intents.FLAGS.GUILDS, @@ -46,7 +46,7 @@ const client = new Discord.Client({ ], presence: { activities: [{ - name: `Running version ${info.version}`, + name: `Running version ${PACKAGE.version}`, type: Discord.Constants.ActivityTypes.LISTENING, }], }, @@ -61,8 +61,8 @@ client.on(Events.MESSAGE_REACTION_ADD, onReactionAdd); client.on(Events.MESSAGE_REACTION_REMOVE, onReactionRemove); -client.login(config.token).catch(err => { - logError(err); +client.login(CONFIG.token).catch(err => { + logger.error('Failed to log in!', err); process.exit(1); }); From 09e731eea2346a7404de324722ea5e5d53e676de Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 30 Dec 2021 04:43:39 -0500 Subject: [PATCH 045/107] Update status to make a little more sense with slash commands --- main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index e4989f4..ac6dddb 100644 --- a/main.js +++ b/main.js @@ -46,8 +46,8 @@ const client = new Discord.Client({ ], presence: { activities: [{ - name: `Running version ${PACKAGE.version}`, - type: Discord.Constants.ActivityTypes.LISTENING, + name: `Version ${PACKAGE.version}`, + type: Discord.Constants.ActivityTypes.PLAYING, }], }, }); From 4b6aad4692088f62272ba6f98fa5595b3626d5d8 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 30 Dec 2021 06:30:00 -0500 Subject: [PATCH 046/107] Also handle Discord's class for built-in emojis --- util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.js b/util.js index 0d3b345..bc74284 100644 --- a/util.js +++ b/util.js @@ -60,7 +60,7 @@ function emojiToKey(emoji) { if (!isEmoji(emoji)) { throw Error(`Not an emoji key: ${emoji}`); } - return emoji?.id ?? emoji; + return emoji?.id ?? emoji?.name ?? emoji; } /** From 42204e6cf6a7aee06eecf626ed34486710840662 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 30 Dec 2021 06:32:01 -0500 Subject: [PATCH 047/107] Rewrite onReactionRemove to use async-await --- events.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ main.js | 32 +------------------------------- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/events.js b/events.js index 8fa9b83..56eb239 100644 --- a/events.js +++ b/events.js @@ -19,6 +19,7 @@ const database = require('./database'); const logger = require('./logger'); const { detail, + emojiToKey, stringify, } = require('./util'); @@ -49,6 +50,52 @@ async function onInteraction(interaction) { } } +/** + * Event handler for when a user removes a reaction from a message. + * Checks if the message has any reaction roles configured. If so, removes that + * role from the user whose reaction was removed. + * + * This is only fired when a user removes a reaction, either by clicking on an + * emoji or through the message's "reactions" context menu. It is NOT fired when + * a bot removes a reaction (Discord uses a seprate event for that). + * + * The user this handler receives is the user whose reaction was removed. + * Discord does not tell us who actually removed that user's reaction. We can't + * tell when an admin removes a reaction instead of the user themselves, so this + * handler will always just remove the role from the user. + */ +async function onReactionRemove(reaction, react_user) { + // TODO How do we handle two emojis mapped to the same role? + // Do we only remove the role if the user doesn't have any of the mapped + // reactions? Or do we remove when any of the emojis are un-reacted? + // TODO re-react if bot's reaction is removed + + const role_id = await database.getRoleReact({ + message_id: reaction.message.id, + emoji_id: emojiToKey(reaction.emoji), + }); + + // Ignore reactions on non-role-react posts + if (!role_id) { + return; + } + + if (react_user === react_user.client.user) { + return; + } + + try { + const member = await reaction.message.guild.members.fetch(react_user.id); + await member.roles.remove(role_id, 'Role bot removal'); + logger.info(`Removed Role ${role_id} from ${stringify(react_user)}`); + } catch (err) { + logger.error( + `Failed to remove Role ${role_id} from ${stringify(react_user)}`, + err + ); + } +} + /** * Event handler for when the bot is logged in. * Just logs the bot user we logged in as. @@ -60,6 +107,7 @@ function onReady(client) { module.exports = { onGuildLeave, onInteraction, + onReactionRemove, onReady, }; diff --git a/main.js b/main.js index ac6dddb..d4fcbb6 100644 --- a/main.js +++ b/main.js @@ -58,7 +58,7 @@ client.on(Events.GUILD_CREATE, onGuildJoin); client.on(Events.GUILD_DELETE, events.onGuildLeave); client.on(Events.INTERACTION_CREATE, events.onInteraction); client.on(Events.MESSAGE_REACTION_ADD, onReactionAdd); -client.on(Events.MESSAGE_REACTION_REMOVE, onReactionRemove); +client.on(Events.MESSAGE_REACTION_REMOVE, events.onReactionRemove); client.login(CONFIG.token).catch(err => { @@ -162,36 +162,6 @@ function onReactionAdd(reaction, user) { .catch(logError); } -/** - * Event handler for when a reaction is removed from a message. - * Checks if the message has any reaction roles configured, removing a role from - * the user who removed their reaction, if applicable. Ignored reacts removed by - * this bot, of course. - */ -function onReactionRemove(reaction, user) { - // TODO How do we handle two emojis mapped to the same role? - // Do we only remove the role if the user doesn't have any of the mapped - // reactions? Or do we remove when any of the emojis are un-reacted? - - if (user === client.user) { - return; - } - - let emoji = emojiIdFromEmoji(reaction.emoji); - - cache.getReactRole(reaction.message.id, emoji) - .then(roleId => { - if (!roleId) { - return; - } - - return reaction.message.guild.members.fetch(user.id) - .then(member => member.roles.remove(roleId, 'Role bot removal')) - .then(() => logger.info(`removed role ${roleId} from ${user}`)) - }) - .catch(logError); -} - /** * Takes an array of items and a function that may return a promise, then runs * the promise function for each item in the array, in sequence. Returns a From 7a7917d53bdd881d7dacc291210466ae0c442037 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 30 Dec 2021 06:44:50 -0500 Subject: [PATCH 048/107] Replace bot's reaction if someone removes it --- events.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/events.js b/events.js index 56eb239..0205fd7 100644 --- a/events.js +++ b/events.js @@ -53,7 +53,8 @@ async function onInteraction(interaction) { /** * Event handler for when a user removes a reaction from a message. * Checks if the message has any reaction roles configured. If so, removes that - * role from the user whose reaction was removed. + * role from the user whose reaction was removed. Also re-adds the bot's + * reaction if it is removed while a react-role is active. * * This is only fired when a user removes a reaction, either by clicking on an * emoji or through the message's "reactions" context menu. It is NOT fired when @@ -68,7 +69,6 @@ async function onReactionRemove(reaction, react_user) { // TODO How do we handle two emojis mapped to the same role? // Do we only remove the role if the user doesn't have any of the mapped // reactions? Or do we remove when any of the emojis are un-reacted? - // TODO re-react if bot's reaction is removed const role_id = await database.getRoleReact({ message_id: reaction.message.id, @@ -81,7 +81,8 @@ async function onReactionRemove(reaction, react_user) { } if (react_user === react_user.client.user) { - return; + logger.info(`Replacing removed bot reaction ${stringify(reaction.emoji)}`); + return reaction.message.react(reaction.emoji); } try { From 2ab0d1030602c0e02d4f3acf8dfd8e78b84374bc Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 30 Dec 2021 21:16:20 -0500 Subject: [PATCH 049/107] Make react remove docs a little more accurate --- events.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/events.js b/events.js index 0205fd7..e292d6a 100644 --- a/events.js +++ b/events.js @@ -51,14 +51,14 @@ async function onInteraction(interaction) { } /** - * Event handler for when a user removes a reaction from a message. + * Event handler for when a reaction is removed from a message. * Checks if the message has any reaction roles configured. If so, removes that * role from the user whose reaction was removed. Also re-adds the bot's * reaction if it is removed while a react-role is active. * - * This is only fired when a user removes a reaction, either by clicking on an - * emoji or through the message's "reactions" context menu. It is NOT fired when - * a bot removes a reaction (Discord uses a seprate event for that). + * This is only fired when a single reaction is removed, either by clicking on + * an emoji or through the message's "reactions" context menu. It is NOT fired + * when a bot removes all reactions (Discord uses a seprate event for that). * * The user this handler receives is the user whose reaction was removed. * Discord does not tell us who actually removed that user's reaction. We can't @@ -70,9 +70,11 @@ async function onReactionRemove(reaction, react_user) { // Do we only remove the role if the user doesn't have any of the mapped // reactions? Or do we remove when any of the emojis are un-reacted? + const emoji = reaction.emoji; + const role_id = await database.getRoleReact({ message_id: reaction.message.id, - emoji_id: emojiToKey(reaction.emoji), + emoji_id: emojiToKey(emoji), }); // Ignore reactions on non-role-react posts @@ -81,8 +83,8 @@ async function onReactionRemove(reaction, react_user) { } if (react_user === react_user.client.user) { - logger.info(`Replacing removed bot reaction ${stringify(reaction.emoji)}`); - return reaction.message.react(reaction.emoji); + logger.info(`Replacing removed bot reaction ${stringify(emoji)}`); + return reaction.message.react(emoji); } try { From 751228c98656cf1725d41601dc323345c35f1452 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 30 Dec 2021 21:17:07 -0500 Subject: [PATCH 050/107] Add USER partial to catch reacts on older messages --- main.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main.js b/main.js index d4fcbb6..64bc4bb 100644 --- a/main.js +++ b/main.js @@ -40,9 +40,11 @@ const client = new Discord.Client({ Discord.Intents.FLAGS.GUILD_MESSAGE_REACTIONS, ], partials: [ + // https://discordjs.guide/popular-topics/reactions.html#listening-for-reactions-on-old-messages Discord.Constants.PartialTypes.MESSAGE, Discord.Constants.PartialTypes.CHANNEL, - Discord.Constants.PartialTypes.REACTION + Discord.Constants.PartialTypes.REACTION, + Discord.Constants.PartialTypes.USER, ], presence: { activities: [{ From 59abd005ad9ca4386fe35e24ca2a690de4492f3b Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 30 Dec 2021 22:07:08 -0500 Subject: [PATCH 051/107] Debug log reaction events to help debug intermittent react failures --- events.js | 2 ++ util.js | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/events.js b/events.js index e292d6a..e6c371c 100644 --- a/events.js +++ b/events.js @@ -66,6 +66,8 @@ async function onInteraction(interaction) { * handler will always just remove the role from the user. */ async function onReactionRemove(reaction, react_user) { + logger.debug(`Removed ${detail(reaction)}`); + // TODO How do we handle two emojis mapped to the same role? // Do we only remove the role if the user doesn't have any of the mapped // reactions? Or do we remove when any of the emojis are un-reacted? diff --git a/util.js b/util.js index bc74284..f5f01e8 100644 --- a/util.js +++ b/util.js @@ -19,6 +19,7 @@ const { Guild, Interaction, Message, + MessageReaction, Role, User, } = require('discord.js'); @@ -43,6 +44,10 @@ function detail(thing) { const int = thing; return `${stringify(int.guild)} ${stringify(int.user)} ${stringify(int)}`; } + else if (thing instanceof MessageReaction) { + const reaction = thing; + return `${stringify(reaction)} on ${stringify(reaction.message)}`; + } else { // Fall back on standard strings return stringify(thing); @@ -114,6 +119,10 @@ function stringify(thing) { const message = thing; return `Message ${message.url}`; } + else if (thing instanceof MessageReaction) { + const reaction = thing; + return `Reaction ${emojiToKey(reaction.emoji)}`; + } else if (thing instanceof Role) { const role = thing; return `Role ${role.id}`; From 47dafe77642ac6c76dd84992a5f8866bbf9a6e5a Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 30 Dec 2021 22:20:55 -0500 Subject: [PATCH 052/107] Rewrite onReactionAdd to use async-await --- events.js | 53 ++++++++++++++++++++++++++++++++++++++++ main.js | 73 +------------------------------------------------------ 2 files changed, 54 insertions(+), 72 deletions(-) diff --git a/events.js b/events.js index e6c371c..07de958 100644 --- a/events.js +++ b/events.js @@ -50,6 +50,58 @@ async function onInteraction(interaction) { } } +/** + * Event handler for when a reaction is added to a message. + * Checks if the message has any reaction roles configured. If so, adds that + * role to the user who added the reaction. + */ +async function onReactionAdd(reaction, react_user) { + logger.debug(`Added ${detail(reaction)}`); + + // Ignore our own reactions + if (react_user === react_user.client.user) { + return; + } + + const role_id = await database.getRoleReact({ + message_id: reaction.message.id, + emoji_id: emojiToKey(reaction.emoji), + }); + + // Ignore reactions on non-role-react posts + if (!role_id) { + return; + } + + const member = await reaction.message.guild.members.fetch(react_user.id); + + // Remove mutually exclusive roles from user + const mutex_roles = await database.getMutexRoles({ + guild_id: reaction.message.guild.id, + role_id: role_id, + }); + try { + await member.roles.remove(mutex_roles, 'Role bot removal (mutex)'); + await member.roles.add(role_id, 'Role bot assignment'); + } catch (err) { + logger.info(`Failed to update roles on ${stringify(user)}`, err); + } + + // Remove associated mutually exclusive emoji reactions + const mutex_emojis = await database.getMutexEmojis(mutex_roles); + for await (const emoji of mutex_emojis) { + const mutex_reaction = reaction.message.reactions.resolve(emoji); + if (mutex_reaction) { + mutex_reaction.users.remove(react_user); + } + } + + // Track assignment number for fun + await database.incrementAssignCounter(); + + logger.info(`Added Role ${role_id} to ${detail(react_user)}`); +} + /** * Event handler for when a reaction is removed from a message. * Checks if the message has any reaction roles configured. If so, removes that @@ -112,6 +164,7 @@ function onReady(client) { module.exports = { onGuildLeave, onInteraction, + onReactionAdd, onReactionRemove, onReady, }; diff --git a/main.js b/main.js index 64bc4bb..aa5f9d7 100644 --- a/main.js +++ b/main.js @@ -59,7 +59,7 @@ client.on(Events.CLIENT_READY, events.onReady); client.on(Events.GUILD_CREATE, onGuildJoin); client.on(Events.GUILD_DELETE, events.onGuildLeave); client.on(Events.INTERACTION_CREATE, events.onInteraction); -client.on(Events.MESSAGE_REACTION_ADD, onReactionAdd); +client.on(Events.MESSAGE_REACTION_ADD, events.onReactionAdd); client.on(Events.MESSAGE_REACTION_REMOVE, events.onReactionRemove); @@ -113,77 +113,6 @@ function onGuildJoin(guild) { .catch(logError); } - - -/** - * Event handler for when a reaction is added to a message. - * Checks if the message has any reaction roles configured, assigning a role to - * the user who added the reaction, if applicable. Ignores reacts added by this - * bot, of course. If a user attempts to assign a role that is mutually - * exclusive with a role they already have, they will lose that first role, and - * their reaction to the message for that role will be removed. - */ -function onReactionAdd(reaction, user) { - if (user === client.user) { - return; - } - - let emoji = emojiIdFromEmoji(reaction.emoji); - - cache.getReactRole(reaction.message.id, emoji) - .then(roleId => { - if (!roleId) { - return; - } - - // TODO if ever there was a time for async-await, this is it. - // TODO Also this seems to hit Discord's rate limit almost - // immediately because of each mutex react removal being its own - // request. Might need to look into .set - return Promise.all([ - reaction.message.guild.members.fetch(user.id), - database.getMutexRoles({ - guild_id: reaction.message.guild.id, - role_id: roleId - }) - ]) - .then(([member, mutexRoles]) => - member.roles.remove(mutexRoles, 'Role bot removal (mutex)') - .then(() => member.roles.add(roleId, 'Role bot assignment')) - .then(() => database.getMutexEmojis(mutexRoles)) - .then(mutexEmojis => - asyncForEach(mutexEmojis, function(emoji) { - let mesRec = reaction.message.reactions.resolve(emoji); - if (mesRec) return mesRec.users.remove(user); - }) - ) - ) - .then(() => database.incrementAssignCounter()) - .then(() => logger.info(`added role ${roleId} to ${user}`)); - }) - .catch(logError); -} - -/** - * Takes an array of items and a function that may return a promise, then runs - * the promise function for each item in the array, in sequence. Returns a - * promise that resolves once every element has been processed. - * Does not return the results because we don't need them. - */ -async function asyncForEach(arr, promiseFunc) { - for await (let elem of arr) { - promiseFunc(elem); - } -} - -/** - * Built-in emojis are identified by name. Custom emojis are identified by ID. - * This function handles that nuance for us. - */ -function emojiIdFromEmoji(emoji) { - return emoji.id || emoji.name; -} - /** * Single function to make error redirection easier in the future. * Maybe some day we'll do something more intelligent with errors. From a6d56d7782de51a12f359cc6fdbd51bb6ca675d3 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 30 Dec 2021 22:32:38 -0500 Subject: [PATCH 053/107] Finally remove the infernal cache.js that has haunted my dreams --- cache.js | 128 ------------------------------------------------------- main.js | 2 - 2 files changed, 130 deletions(-) delete mode 100644 cache.js diff --git a/cache.js b/cache.js deleted file mode 100644 index 481814b..0000000 --- a/cache.js +++ /dev/null @@ -1,128 +0,0 @@ -/******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. - * Copyright (C) 2020 Mimickal (Mia Moretti). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - ******************************************************************************/ -const database = require('./database'); - -// The live cache of selected messages for each user. -const selectedMessages = new Map(); - -/** - * Selects a message to use for each subsequent command the user enters. - */ -function selectMessage(user_id, message) { - selectedMessages.set(user_id, message); - // TODO clear selected cache after some time -} - -/** - * Gets the message the given user currently has selected. - * - * Throws an exception if the user has no message selected. - */ -function getSelectedMessage(user_id) { - let message = selectedMessages.get(user_id); - if (!message) { - throw new Error('No message selected!'); - } - return message; -} - -/** - * Clears the selected message for the given user. - */ -function clearSelectedMessage(user_id) { - selectedMessages.delete(user_id); -} - -/** - * Add an emoji-role association to the message the user has selected. - * If the emoji was already associated with another role on this message, the - * original mapping will be overwritten. - * - * Throws an exception if the user has no message selected. - */ -async function addEmojiRole(user_id, emoji_id, role_id) { - let message = await getSelectedMessage(user_id); - - return database.addRoleReact({ - guild_id: message.guild.id, - message_id: message.id, - emoji_id: emoji_id, - role_id: role_id - }); -} - -/** - * Remove an emoji-role association from the message the user has selected. - * - * Throws an exception: - * - If the user has no message selected. - * - If the message did not have a mapping for the given emoji. - */ -async function removeEmojiRole(user_id, emoji_id) { - let message = getSelectedMessage(user_id); - - let args = { - message_id: message.id, - emoji_id: emoji_id - }; - - let role_id = await database.getRoleReact(args); - if (role_id) { - return database.removeRoleReact(args); - } else { - throw new Error('No role mapping found'); - } -} - -/** - * Removes all emoji-role associations from the message the user has selected. - * - * Throws an exception: - * - If the user has no message selected. - * - If the message did not have any emojis mappings on it. - */ -async function removeAllEmojiRoles(user_id) { - let message = getSelectedMessage(user_id); - - let rows = await database.removeAllRoleReacts(message.id); - if (rows === 0) { - throw new Error('No role mapping found'); - } - - return message; -} - -/** - * Gets the role mapped to the given emoji on the given message, or null if - * there's no role associated with it (or if the message is unknown). - */ -function getReactRole(message_id, emoji_id) { - return database.getRoleReact({ - message_id: message_id, - emoji_id: emoji_id - }); -} - -module.exports = { - selectMessage, - getSelectedMessage, - clearSelectedMessage, - addEmojiRole, - removeEmojiRole, - removeAllEmojiRoles, - getReactRole -}; diff --git a/main.js b/main.js index aa5f9d7..529cf12 100644 --- a/main.js +++ b/main.js @@ -18,8 +18,6 @@ const fs = require('fs'); const Discord = require('discord.js'); -const cache = require('./cache'); -const database = require('./database'); const events = require('./events'); const logger = require('./logger'); const { unindent } = require('./util'); From da9ae8598f5d9fea7c3af9e89cb0507e85272b13 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 31 Dec 2021 00:34:17 -0500 Subject: [PATCH 054/107] Remove extra emojis from react-role posts --- database.js | 12 ++++++++++++ events.js | 12 +++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/database.js b/database.js index 117b1f1..3bca5ff 100644 --- a/database.js +++ b/database.js @@ -101,6 +101,17 @@ function getRoleReactMap(message_id) { }); } +/** + * Returns whether the given message has any role react mappings on it. + */ +function isRoleReactMessage(message_id) { + return knex(REACTS) + .select('message_id') + .where('message_id', message_id) + .first() + .then(result => !!result); +} + /** * Deletes all the data stored for the given guild. */ @@ -262,6 +273,7 @@ module.exports = { removeAllRoleReacts, getRoleReact, getRoleReactMap, + isRoleReactMessage, clearGuildInfo, incrementAssignCounter, getMetaStats, diff --git a/events.js b/events.js index 07de958..6e19dea 100644 --- a/events.js +++ b/events.js @@ -53,7 +53,8 @@ async function onInteraction(interaction) { /** * Event handler for when a reaction is added to a message. * Checks if the message has any reaction roles configured. If so, adds that - * role to the user who added the reaction. + * role to the user who added the reaction. Removes any reaction that doesn't + * correspond to a role. */ async function onReactionAdd(reaction, react_user) { logger.debug(`Added ${detail(reaction)}`); @@ -63,14 +64,19 @@ async function onReactionAdd(reaction, react_user) { return; } + // Ignore reactions on non-role-react posts + if (!await database.isRoleReactMessage(reaction.message.id)) { + return; + } + const role_id = await database.getRoleReact({ message_id: reaction.message.id, emoji_id: emojiToKey(reaction.emoji), }); - // Ignore reactions on non-role-react posts + // Someone added an emoji that isn't mapped to a role if (!role_id) { - return; + return reaction.remove(); } const member = await reaction.message.guild.members.fetch(react_user.id); From 52dfabcfa4e9bfeea7b06255c777210e679e7c4e Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 31 Dec 2021 03:07:49 -0500 Subject: [PATCH 055/107] Remove database records for deleted messages --- events.js | 16 ++++++++++++++++ main.js | 1 + 2 files changed, 17 insertions(+) diff --git a/events.js b/events.js index 6e19dea..ab4faeb 100644 --- a/events.js +++ b/events.js @@ -50,6 +50,21 @@ async function onInteraction(interaction) { } } +/** + * Event handler for when a message is deleted. + * Removes any react-roles configured for the deleted message. + */ +async function onMessageDelete(message) { + try { + const removed = await database.removeAllRoleReacts(message.id); + if (removed) { + logger.info(`Deleted ${stringify(message)}, removed ${removed} mappings`); + } + } catch (err) { + logger.error(`Deleted ${stringify(message)} but failed to clear records`, err); + } +} + /** * Event handler for when a reaction is added to a message. * Checks if the message has any reaction roles configured. If so, adds that @@ -170,6 +185,7 @@ function onReady(client) { module.exports = { onGuildLeave, onInteraction, + onMessageDelete, onReactionAdd, onReactionRemove, onReady, diff --git a/main.js b/main.js index 529cf12..8ce6171 100644 --- a/main.js +++ b/main.js @@ -57,6 +57,7 @@ client.on(Events.CLIENT_READY, events.onReady); client.on(Events.GUILD_CREATE, onGuildJoin); client.on(Events.GUILD_DELETE, events.onGuildLeave); client.on(Events.INTERACTION_CREATE, events.onInteraction); +client.on(Events.MESSAGE_DELETE, events.onMessageDelete); client.on(Events.MESSAGE_REACTION_ADD, events.onReactionAdd); client.on(Events.MESSAGE_REACTION_REMOVE, events.onReactionRemove); From 13985ba8784ca0a8424229e42701fb7807e3f6a8 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 31 Dec 2021 03:08:12 -0500 Subject: [PATCH 056/107] Also clear database for bulk deletes --- events.js | 12 ++++++++++++ main.js | 1 + 2 files changed, 13 insertions(+) diff --git a/events.js b/events.js index ab4faeb..3e8f24c 100644 --- a/events.js +++ b/events.js @@ -50,6 +50,17 @@ async function onInteraction(interaction) { } } +/** + * Event handler for when messages are deleted in bulk. + * Removes any react roles configured for the deleted messages. + */ +async function onMessageBulkDelete(messages) { + for (const message of messages.values()) { + console.log(message.id); + onMessageDelete(message); + } +} + /** * Event handler for when a message is deleted. * Removes any react-roles configured for the deleted message. @@ -185,6 +196,7 @@ function onReady(client) { module.exports = { onGuildLeave, onInteraction, + onMessageBulkDelete, onMessageDelete, onReactionAdd, onReactionRemove, diff --git a/main.js b/main.js index 8ce6171..e55517e 100644 --- a/main.js +++ b/main.js @@ -57,6 +57,7 @@ client.on(Events.CLIENT_READY, events.onReady); client.on(Events.GUILD_CREATE, onGuildJoin); client.on(Events.GUILD_DELETE, events.onGuildLeave); client.on(Events.INTERACTION_CREATE, events.onInteraction); +client.on(Events.MESSAGE_BULK_DELETE, events.onMessageBulkDelete); client.on(Events.MESSAGE_DELETE, events.onMessageDelete); client.on(Events.MESSAGE_REACTION_ADD, events.onReactionAdd); client.on(Events.MESSAGE_REACTION_REMOVE, events.onReactionRemove); From 5af8e1aaafe3d621d9f338359cc9741781f625c0 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 31 Dec 2021 20:02:43 -0500 Subject: [PATCH 057/107] (Bugfix) rewrite onGuildJoin event handler and fix broken API between DJS v12 and v13 --- events.js | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ main.js | 56 +------------------------------------------------------ 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/events.js b/events.js index 3e8f24c..34e182f 100644 --- a/events.js +++ b/events.js @@ -14,6 +14,8 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ +const Perms = require('discord.js').Permissions.FLAGS; + const commands = require('./commands'); const database = require('./database'); const logger = require('./logger'); @@ -21,8 +23,59 @@ const { detail, emojiToKey, stringify, + unindent, } = require('./util'); +const REQUIRED_PERMISSIONS = Object.freeze({ + [Perms.ADD_REACTIONS]: 'Add Reactions', + [Perms.MANAGE_MESSAGES]: 'Manage Messages', + [Perms.MANAGE_ROLES]: 'Manage Roles', + [Perms.READ_MESSAGE_HISTORY]: 'Read Message History', + [Perms.USE_EXTERNAL_EMOJIS]: 'Use External Emojis', + [Perms.VIEW_CHANNEL]: 'Read Text Channels & See Voice Channels', +}); + +/** + * Event handler for when the bot joins a new guild. + * DMs the guild owner with some basic instructions, including any missing + * required permissions. + */ +async function onGuildJoin(guild) { + logger.info(`Joined ${stringify(guild)}`); + + let text = unindent(` + Hi there! My role needs to be ordered above any role you want me to + assign. You are getting this message because you are the server owner, + but anybody with Administrator permissions or an allowed role can + configure me. + `); + + // This bot probably shouldn't be given the admin permission, but if we have + // it then the other ones don't matter. + // These permissions can also be inherited from the server's @everyone + // permissions. + const client_member = await guild.members.fetch(guild.client.user); + const missing_perms = Object.entries(REQUIRED_PERMISSIONS) + .filter(([ perm, name ]) => !client_member.permissions.has(perm, true)) + .map(([ perm, name ]) => name); + + if (missing_perms.length > 0) { + text += '\n\n'; + text += unindent(` + Also, I am missing the following permissions. Without them, I + probably won't work right: + `); + text += '\n'; + text += missing_perms.map(name => `- ${name}`).join('\n'); + + logger.info(`${stringify(guild)} missing permissions: ${missing_perms}`); + } + + const guild_owner = await guild.fetchOwner(); + const owner_dm = await guild_owner.createDM(); + return owner_dm.send(text); +} + /** * Event handler for when the bot leaves (or is kicked from) a guild. * Deletes all data associated with that guild. @@ -194,6 +247,7 @@ function onReady(client) { } module.exports = { + onGuildJoin, onGuildLeave, onInteraction, onMessageBulkDelete, diff --git a/main.js b/main.js index e55517e..516cb33 100644 --- a/main.js +++ b/main.js @@ -20,7 +20,6 @@ const Discord = require('discord.js'); const events = require('./events'); const logger = require('./logger'); -const { unindent } = require('./util'); const CONFIG = JSON.parse(fs.readFileSync( process.argv[2] || '/etc/discord/ReactionRoleBot/config.json' @@ -54,7 +53,7 @@ const client = new Discord.Client({ const Events = Discord.Constants.Events; client.on(Events.CLIENT_READY, events.onReady); -client.on(Events.GUILD_CREATE, onGuildJoin); +client.on(Events.GUILD_CREATE, events.onGuildJoin); client.on(Events.GUILD_DELETE, events.onGuildLeave); client.on(Events.INTERACTION_CREATE, events.onInteraction); client.on(Events.MESSAGE_BULK_DELETE, events.onMessageBulkDelete); @@ -68,56 +67,3 @@ client.login(CONFIG.token).catch(err => { process.exit(1); }); -/** - * Event handler for when the bot joins a new guild. - */ -function onGuildJoin(guild) { - let info = unindent(`Hi there! My role needs to be ordered above any - role you would like me to assign. You're getting this message - because you are the server owner, but anybody with Administrator - permissions or an allowed role can configure me.`); - - guild.members.fetch(client.user.id) - .then(clientMember => { - const Perms = Discord.Permissions.FLAGS; - const requiredPermMap = { - [Perms.ADD_REACTIONS]: 'Add Reactions', - [Perms.MANAGE_MESSAGES]: 'Manage Messages', - [Perms.MANAGE_ROLES]: 'Manage Roles', - [Perms.READ_MESSAGE_HISTORY]: 'Read Message History', - [Perms.USE_EXTERNAL_EMOJIS]: 'Use External Emojis', - [Perms.VIEW_CHANNEL]: 'Read Text Channels & See Voice Channels' - }; - - // This bot probably shouldn't be given the admin permission, but if - // we have it then the other ones don't matter. - // Also, these permissions can also be inherited from the server's - // @everyone permissions. - let missingPermNames = Object.entries(requiredPermMap) - .filter(([perm, name]) => !clientMember.hasPermission( - parseInt(perm), - { checkAdmin: true } - )) - .map(([perm, name]) => name); - - if (missingPermNames.length > 0) { - info += '\n\n' + unindent(`Also, I am missing the following - permissions. Without them, I probably won't work right:`) + - '\n' + missingPermNames.join('\n'); - } - - return guild.members.fetch(guild.ownerID); - }) - .then(owner => owner.createDM()) - .then(dmChannel => dmChannel.send(info)) - .catch(logError); -} - -/** - * Single function to make error redirection easier in the future. - * Maybe some day we'll do something more intelligent with errors. - */ -function logError(err) { - logger.error(err); -} - From fdc5c2afacdc8775e8e852c157ab8f5d0330f721 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 29 Dec 2021 21:36:37 -0500 Subject: [PATCH 058/107] Add comments explaining the rationale behind each migration --- migrations/20200225015300_db.js | 6 ++++++ migrations/20200814190000_meta.js | 3 +++ migrations/20200815043000_perms.js | 4 ++++ migrations/20200818203000_mutex.js | 3 +++ migrations/20211215035000_animated.js | 10 +++++++++- 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/migrations/20200225015300_db.js b/migrations/20200225015300_db.js index 32ba02a..efb209b 100644 --- a/migrations/20200225015300_db.js +++ b/migrations/20200225015300_db.js @@ -17,6 +17,12 @@ const DISCORD_ID_MAX = 19; const REACTS = 'reacts'; +/** + * Create a table mapping a reaction emoji to a role on a message in a guild. + * + * Using a composite primary key of message_id and emoji_id doubles as a thing + * that prevents multiple database entries for the same react. + */ exports.up = function(knex) { return knex.schema.createTable(REACTS, table => { table.string('guild_id', DISCORD_ID_MAX); diff --git a/migrations/20200814190000_meta.js b/migrations/20200814190000_meta.js index 3b72acb..081be6c 100644 --- a/migrations/20200814190000_meta.js +++ b/migrations/20200814190000_meta.js @@ -16,6 +16,9 @@ ******************************************************************************/ const META = 'meta'; +/** + * Creates a table for counting how many total assignments there have been. + */ exports.up = function(knex) { return knex.schema.createTable(META, table => { table.integer('assignments'); diff --git a/migrations/20200815043000_perms.js b/migrations/20200815043000_perms.js index 01a1339..7e0d0d9 100644 --- a/migrations/20200815043000_perms.js +++ b/migrations/20200815043000_perms.js @@ -17,6 +17,10 @@ const DISCORD_ID_MAX = 19; const PERMS = 'perms'; +/** + * Creates a table that maps a role to a guild, so that role can be allowed to + * configure the bot in the guild. + */ exports.up = function(knex) { return knex.schema.createTable(PERMS, table => { table.string('guild_id', DISCORD_ID_MAX); diff --git a/migrations/20200818203000_mutex.js b/migrations/20200818203000_mutex.js index 94a2ce5..9378200 100644 --- a/migrations/20200818203000_mutex.js +++ b/migrations/20200818203000_mutex.js @@ -17,6 +17,9 @@ const DISCORD_ID_MAX = 19; const MUTEX = 'mutex'; +/** + * Creates a table mapping two roles as mutually exclusive for a guild. + */ exports.up = function(knex) { return knex.schema.createTable(MUTEX, table => { table.string('guild_id', DISCORD_ID_MAX); diff --git a/migrations/20211215035000_animated.js b/migrations/20211215035000_animated.js index 51b6173..1c0ca32 100644 --- a/migrations/20211215035000_animated.js +++ b/migrations/20211215035000_animated.js @@ -17,8 +17,16 @@ const REACTS = 'reacts'; const EMOJI_ID = 'emoji_id'; +/** + * Animated emojis did not exist when this bot was first written. When Discord + * added them, the bot did not recognize their format, so it dumped the entire + * "toString" value to the database. + * + * That logic has since been fixed. This migration correspondingly fixes any + * broken animated emoji entries already in the database. + */ exports.up = function(knex) { - console.error( + console.warn( 'Warning: this is a one-way migration. Animated emoji names cannot ' + 'be restored and will remain as IDs' ); From 1b316fcf9824002ad2612d0d49607d73903725b6 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sat, 1 Jan 2022 23:13:43 -0500 Subject: [PATCH 059/107] Remove unused exports --- database.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/database.js b/database.js index 3bca5ff..768b94d 100644 --- a/database.js +++ b/database.js @@ -22,10 +22,6 @@ const META = 'meta'; const MUTEX = 'mutex'; const PERMS = 'perms'; const REACTS = 'reacts'; -const DISCORD_ID_LENGTH = { - MIN: 17, - MAX: 22, -}; /** * Adds an emoji->role mapping for the given message. If the emoji is already @@ -263,11 +259,6 @@ function getMutexEmojis(roles) { } module.exports = { - DISCORD_ID_LENGTH, - META, - MUTEX, - PERMS, - REACTS, addRoleReact, removeRoleReact, removeAllRoleReacts, From b7e8fdbd5461068ba0a3d6e329bd58eb8571192d Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 2 Jan 2022 01:42:07 -0500 Subject: [PATCH 060/107] Actually validate the stuff we're putting into the database --- database.js | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- util.js | 32 ++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/database.js b/database.js index 768b94d..b2fbc2c 100644 --- a/database.js +++ b/database.js @@ -16,13 +16,52 @@ ******************************************************************************/ const knexfile = require('./knexfile'); const knex = require('knex')(knexfile[process.env.NODE_ENV || 'development']); -const lodash = require('lodash/object'); +const lodash = require('lodash'); + +const logger = require('./logger'); +const { + isDiscordId, + isEmojiStr, + stringify, +} = require('./util'); const META = 'meta'; const MUTEX = 'mutex'; const PERMS = 'perms'; const REACTS = 'reacts'; +/** + * Helper asserting database arguments look the way we want them to. + * + * SQLite3 has pretty lax enforcement of its constraints, so we need to do a + * little extra work to ensure we're not putting garbage in the database. + * + * Also, since we want to constrain arguments everywhere we would assert on + * them, just do the argument selection here too. + */ +function _pickAndAssertFields(args, asserts) { + lodash.toPairs(asserts).forEach(([ key, type ]) => { + const value = args[key]; + if (type === 'discord' && !isDiscordId(value)) { + throw Error(`${key} invalid Discord ID: ${value}`); + } + if (type === 'emoji' && !isDiscordId(value) && !isEmojiStr(value)) { + throw Error(`${key} invalid Emoji key: ${value}`); + } + }); + + const args_we_need = lodash.pick(args, lodash.keys(asserts)); + + // Extra arguments shouldn't happen in normal operation, but since we pick a + // subset of arguments anyway, just warn about them. + if (!lodash.isEqual(args, args_we_need)) { + const extras = lodash.omit(args, lodash.keys(asserts)); + logger.warn(`Extra database query arguments: ${stringify(extras)}`); + } + + return args_we_need; +} + /** * Adds an emoji->role mapping for the given message. If the emoji is already * mapped to a role on this message, that mapping is replaced. @@ -30,10 +69,12 @@ const REACTS = 'reacts'; * This is essentially an upsert, but "upsert" is a stupid word, so "add" it is. */ function addRoleReact(args) { - // TODO sanity check values - let fields = lodash.pick(args, [ - 'guild_id', 'message_id', 'emoji_id', 'role_id' - ]); + const fields = _pickAndAssertFields(args, { + guild_id: 'discord', + message_id: 'discord', + emoji_id: 'emoji', + role_id: 'discord', + }); return knex(REACTS) .insert(fields) diff --git a/util.js b/util.js index f5f01e8..57a21de 100644 --- a/util.js +++ b/util.js @@ -26,6 +26,14 @@ const { const logger = require('./logger'); +/** + * Most IDs are between 17 and 19 characters, but I have seen some patterns + * matching to 20 for custom emoji IDs, so let's just future-proof this and + * match up to 22. If this bot is still being used by the time we need to update + * that, well, cool. + */ +const DISCORD_ID_PATTERN = RegExp('^\\d{17,22}$'); + /** * Joins the given array of strings using newlines. */ @@ -62,7 +70,7 @@ function detail(thing) { * - Non-emoji strings are considered an error and will throw accordingly. */ function emojiToKey(emoji) { - if (!isEmoji(emoji)) { + if (!_isEmoji(emoji)) { throw Error(`Not an emoji key: ${emoji}`); } return emoji?.id ?? emoji?.name ?? emoji; @@ -83,8 +91,22 @@ function ephemReply(interaction, content) { /** * Handles both custom Discord.js Emojis and standard unicode emojis. */ -function isEmoji(thing) { - return thing?.match?.(/^\p{Extended_Pictographic}$/u) || thing instanceof Emoji; +function _isEmoji(thing) { + return isEmojiStr(thing) || thing instanceof Emoji; +} + +/** + * Matches Discord IDs. + */ +function isDiscordId(str) { + return str?.match?.(DISCORD_ID_PATTERN); +} + +/** + * Matches built-in unicode emoji literals. + */ +function isEmojiStr(str) { + return str?.match?.(/^\p{Extended_Pictographic}$/u); } /** @@ -98,7 +120,7 @@ function stringify(thing) { if (!thing) { return '[undefined]'; } - else if (isEmoji(thing)) { + else if (_isEmoji(thing)) { const emoji = thing; return `Emoji ${emojiToKey(emoji)}`; } @@ -153,6 +175,8 @@ module.exports = { detail, emojiToKey, ephemReply, + isDiscordId, + isEmojiStr, stringify, unindent, }; From f2cdebfe11c3112a4954e783045560f5a0a580bd Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 2 Jan 2022 02:13:22 -0500 Subject: [PATCH 061/107] Use field asserter for other database queries too --- database.js | 62 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/database.js b/database.js index b2fbc2c..ba9943e 100644 --- a/database.js +++ b/database.js @@ -30,6 +30,10 @@ const MUTEX = 'mutex'; const PERMS = 'perms'; const REACTS = 'reacts'; +// Poor man's enum +const DISCORD_ASSERT = 1; +const EMOJI_ASSERT = 2; + /** * Helper asserting database arguments look the way we want them to. * @@ -42,10 +46,10 @@ const REACTS = 'reacts'; function _pickAndAssertFields(args, asserts) { lodash.toPairs(asserts).forEach(([ key, type ]) => { const value = args[key]; - if (type === 'discord' && !isDiscordId(value)) { + if (type === DISCORD_ASSERT && !isDiscordId(value)) { throw Error(`${key} invalid Discord ID: ${value}`); } - if (type === 'emoji' && !isDiscordId(value) && !isEmojiStr(value)) { + if (type === EMOJI_ASSERT && !isDiscordId(value) && !isEmojiStr(value)) { throw Error(`${key} invalid Emoji key: ${value}`); } }); @@ -70,10 +74,10 @@ function _pickAndAssertFields(args, asserts) { */ function addRoleReact(args) { const fields = _pickAndAssertFields(args, { - guild_id: 'discord', - message_id: 'discord', - emoji_id: 'emoji', - role_id: 'discord', + guild_id: DISCORD_ASSERT, + message_id: DISCORD_ASSERT, + emoji_id: EMOJI_ASSERT, + role_id: DISCORD_ASSERT, }); return knex(REACTS) @@ -93,8 +97,10 @@ function addRoleReact(args) { * Removes an emoji->role mapping for the given message. */ function removeRoleReact(args) { - // TODO sanity check values - let fields = lodash.pick(args, ['message_id', 'emoji_id']); + const fields = _pickAndAssertFields(args, { + message_id: DISCORD_ASSERT, + emoji_id: EMOJI_ASSERT, + }); return knex(REACTS).where(fields).del(); } @@ -111,8 +117,10 @@ function removeAllRoleReacts(message_id) { * is no role associated with the emoji on the message. */ function getRoleReact(args) { - // TODO sanity check values - let fields = lodash.pick(args, ['message_id', 'emoji_id']); + const fields = _pickAndAssertFields(args, { + message_id: DISCORD_ASSERT, + emoji_id: EMOJI_ASSERT, + }); return knex(REACTS) .first('role_id') @@ -189,8 +197,10 @@ function getMetaStats() { * Adds a new role that's allowed to configure this bot for the given guild. */ function addAllowedRole(args) { - // TODO sanity check values - let fields = lodash.pick(args, ['guild_id', 'role_id']); + const fields = _pickAndAssertFields(args, { + guild_id: DISCORD_ASSERT, + role_id: DISCORD_ASSERT, + }); return knex(PERMS).insert(fields); } @@ -199,8 +209,10 @@ function addAllowedRole(args) { * Removes a role from being allowed to configure this bot for the given guild. */ function removeAllowedRole(args) { - // TODO sanity check values - let fields = lodash.pick(args, ['guild_id', 'role_id']); + const fields = _pickAndAssertFields(args, { + guild_id: DISCORD_ASSERT, + role_id: DISCORD_ASSERT, + }); return knex(PERMS).where(fields).del(); } @@ -222,8 +234,11 @@ function getAllowedRoles(guild_id) { * throw a unique constraint violation exception. */ function addMutexRole(args) { - // TODO sanity check values - let fields = lodash.pick(args, ['guild_id', 'role_id_1', 'role_id_2']); + const fields = _pickAndAssertFields(args, { + guild_id: DISCORD_ASSERT, + role_id_1: DISCORD_ASSERT, + role_id_2: DISCORD_ASSERT, + }); // Need to try role 1 and role 2 in reverse order too let flipped = lodash.pick(args, ['guild_id']); @@ -247,9 +262,12 @@ function addMutexRole(args) { * addMutexRole. */ function removeMutexRole(args) { - // TODO sanity check values - let fields = lodash.pick(args, ['guild_id', 'role_id_1', 'role_id_2']); - let flipped = lodash.pick(args, ['guild_id']); + const fields = _pickAndAssertFields(args, { + guild_id: DISCORD_ASSERT, + role_id_1: DISCORD_ASSERT, + role_id_2: DISCORD_ASSERT, + }); + const flipped = lodash.pick(fields, ['guild_id']); flipped.role_id_1 = fields.role_id_2; flipped.role_id_2 = fields.role_id_1; @@ -266,8 +284,10 @@ function removeMutexRole(args) { * returned. */ function getMutexRoles(args) { - // TODO sanity check values - let fields = lodash.pick(args, ['guild_id', 'role_id']) + const fields = _pickAndAssertFields(args, { + guild_id: DISCORD_ASSERT, + role_id: DISCORD_ASSERT, + }); // Roles could be added in either order, so fetch with both orders and // combine the results. From b736085a2a8231543ab3cf678f8cbd4342820ac9 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 2 Jan 2022 02:31:05 -0500 Subject: [PATCH 062/107] Also add asserts for single-argument queries --- database.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/database.js b/database.js index ba9943e..57fbc6c 100644 --- a/database.js +++ b/database.js @@ -66,6 +66,15 @@ function _pickAndAssertFields(args, asserts) { return args_we_need; } +/** + * Simple assert to ensure value is a valid Discord ID. + */ +function _assertDiscordId(value) { + if (!isDiscordId(value)) { + throw Error(`Invalid Discord ID: ${value}`); + } +} + /** * Adds an emoji->role mapping for the given message. If the emoji is already * mapped to a role on this message, that mapping is replaced. @@ -109,6 +118,7 @@ function removeRoleReact(args) { * Removes all emoji->role mappings for the given message. */ function removeAllRoleReacts(message_id) { + _assertDiscordId(message_id); return knex(REACTS).where('message_id', message_id).del(); } @@ -133,6 +143,7 @@ function getRoleReact(args) { * null if the given message has no react roles set up. */ function getRoleReactMap(message_id) { + _assertDiscordId(message_id); return knex(REACTS) .select(['emoji_id', 'role_id']) .where('message_id', message_id) @@ -150,6 +161,7 @@ function getRoleReactMap(message_id) { * Returns whether the given message has any role react mappings on it. */ function isRoleReactMessage(message_id) { + _assertDiscordId(message_id); return knex(REACTS) .select('message_id') .where('message_id', message_id) @@ -161,6 +173,7 @@ function isRoleReactMessage(message_id) { * Deletes all the data stored for the given guild. */ function clearGuildInfo(guild_id) { + _assertDiscordId(guild_id); return Promise.all([REACTS, PERMS, MUTEX].map(table => knex(table).where('guild_id', guild_id).del() )); @@ -221,6 +234,7 @@ function removeAllowedRole(args) { * Returns the list of roles that can configure this bot for the given guild. */ function getAllowedRoles(guild_id) { + _assertDiscordId(guild_id); return knex(PERMS) .select('role_id') .where({ guild_id: guild_id }) @@ -313,6 +327,11 @@ function getMutexRoles(args) { * instead of just an array. */ function getMutexEmojis(roles) { + if (!Array.isArray(roles)) { + throw Error('roles must be an Array of Discord IDs'); + } + roles.forEach(_assertDiscordId); + return knex(REACTS) .select('emoji_id') .whereIn('role_id', roles) From 865e496dd47d6f32b1270dfbc9aafaccd5151a6b Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sun, 2 Jan 2022 02:55:22 -0500 Subject: [PATCH 063/107] Some other cleanup in database queries --- database.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/database.js b/database.js index 57fbc6c..071fba9 100644 --- a/database.js +++ b/database.js @@ -147,14 +147,10 @@ function getRoleReactMap(message_id) { return knex(REACTS) .select(['emoji_id', 'role_id']) .where('message_id', message_id) - .then(pairArray => { - let mapping = pairArray.reduce( - (map, pair) => map.set(pair.emoji_id, pair.role_id), - new Map() - ); - - return mapping.size > 0 ? mapping : null; - }); + .then(rows => rows.length > 0 + ? new Map(rows.map(({ emoji_id, role_id }) => [emoji_id, role_id])) + : null + ); } /** @@ -183,7 +179,7 @@ function clearGuildInfo(guild_id) { * Increments the meta table's role assignment counter. */ function incrementAssignCounter(num) { - return knex(META).increment('assignments', num || 1); + return knex(META).increment('assignments', num ?? 1); } /** @@ -264,7 +260,8 @@ function addMutexRole(args) { .where(fields) .then(record => { // If record exists, insert it again to cause a unique constraint - // exception. If not, try to insert the fields in reverse order. + // exception. If not, try to insert the fields in reverse order + // (which will also cause a unique constraint if it exists). let version = record ? fields : flipped; return knex(MUTEX).insert(version); }); @@ -289,7 +286,7 @@ function removeMutexRole(args) { return Promise.all([ knex(MUTEX).where(fields).del(), knex(MUTEX).where(flipped).del() - ]).then(([count1, count2]) => ((count1 || 0) + (count2 || 0))); + ]).then(([count1, count2]) => ((count1 ?? 0) + (count2 ?? 0))); } /** From e40dcd8920a98f9bc1abc2daf92461b6f812a327 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 4 Jan 2022 04:24:08 -0500 Subject: [PATCH 064/107] Disable database pooling in dev --- knexfile.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/knexfile.js b/knexfile.js index 397ccd2..f2b88bc 100644 --- a/knexfile.js +++ b/knexfile.js @@ -20,7 +20,13 @@ module.exports = { useNullAsDefault: true, connection: { filename: './dev.sqlite3' - } + }, + // Helps us catch hanging transactions in dev by locking up the database + // if we forget to commit anything. + pool: { + min: 1, + max: 1, + }, }, testing: { From ed70372b1788583f70cdc40636e63c5893e00e92 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 4 Jan 2022 04:27:54 -0500 Subject: [PATCH 065/107] Use transactions for adding role reacts --- commands.js | 52 ++++++++++++++++++++++++---------------------------- database.js | 14 +++++++++++--- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/commands.js b/commands.js index 614ddd0..390c9e1 100644 --- a/commands.js +++ b/commands.js @@ -307,36 +307,32 @@ async function cmdRoleAdd(interaction) { `)); } - // Try to add this mapping to the database. - const db_data = { - guild_id: interaction.guild.id, - message_id: message.id, - emoji_id: emojiToKey(emoji), - role_id: role.id, - }; - try { - await database.addRoleReact(db_data); - } catch (err) { - logger.error(`Database failed to create ${stringify(db_data)}`, err); - return ephemReply(interaction, 'Something went wrong'); - } + return database.transaction(async trx => { + const db_data = { + guild_id: interaction.guild.id, + message_id: message.id, + emoji_id: emojiToKey(emoji), + role_id: role.id, + }; - // Try to add the emoji to the selected message. If this fails, also remove - // the created mapping from the database so this fails safe. - try { - await message.react(emoji); - } catch (err) { - logger.warn(`Could not add ${stringify(emoji)} to ${stringify(message)}`, err); - // FIXME use a transaction for this. This involves database work so - // maybe hold off until we have fully replace message commands with - // slash commands. - await database.removeRoleReact(db_data); - return ephemReply(interaction, - 'I could not react to your selected message. Do I have the right permissions?' - ); - } + try { + await database.addRoleReact(db_data, trx); + } catch (err) { + logger.error(`Database failed to create ${stringify(db_data)}`, err); + return ephemReply(interaction, 'Something went wrong'); + } + + try { + await message.react(emoji); + } catch (err) { + logger.warn(`Could not add ${stringify(emoji)} to ${stringify(message)}`, err); + return ephemReply(interaction, + 'I could not react to your selected message. Do I have the right permissions?' + ); + } - return ephemReply(interaction, `Mapped ${emoji} to ${role} on ${stringify(message)}`); + return ephemReply(interaction, `Mapped ${emoji} to ${role} on ${stringify(message)}`); + }); } /** diff --git a/database.js b/database.js index 071fba9..d732187 100644 --- a/database.js +++ b/database.js @@ -75,13 +75,20 @@ function _assertDiscordId(value) { } } +/** + * Just a pass-through for knex.transaction(...) + */ +function transaction(func) { + return knex.transaction(func); +} + /** * Adds an emoji->role mapping for the given message. If the emoji is already * mapped to a role on this message, that mapping is replaced. * * This is essentially an upsert, but "upsert" is a stupid word, so "add" it is. */ -function addRoleReact(args) { +function addRoleReact(args, trx) { const fields = _pickAndAssertFields(args, { guild_id: DISCORD_ASSERT, message_id: DISCORD_ASSERT, @@ -89,11 +96,11 @@ function addRoleReact(args) { role_id: DISCORD_ASSERT, }); - return knex(REACTS) + return (trx ? trx(REACTS) : knex(REACTS)) .insert(fields) .catch(err => { if (err.message.includes('UNIQUE constraint failed')) { - return knex(REACTS) + return (trx ? trx(REACTS) : knex(REACTS)) .where(lodash.pick(fields, ['message_id', 'emoji_id'])) .update({ role_id: fields.role_id }); } else { @@ -336,6 +343,7 @@ function getMutexEmojis(roles) { } module.exports = { + transaction, addRoleReact, removeRoleReact, removeAllRoleReacts, From 0fd014cbf62218c58e4ce84bfd1d189db058c9bc Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 4 Jan 2022 04:31:40 -0500 Subject: [PATCH 066/107] Use transactions for removing role reacts --- commands.js | 47 ++++++++++++++++++++++++----------------------- database.js | 4 ++-- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/commands.js b/commands.js index 390c9e1..1fe2a51 100644 --- a/commands.js +++ b/commands.js @@ -352,32 +352,33 @@ async function cmdRoleRemove(interaction) { message = await message.fetch(); - let removed; - try { - const emoji_id = emojiToKey(emoji); + return database.transaction(async trx => { + let removed; + try { + const emoji_id = emojiToKey(emoji); + + // Intentionally NOT removing this role from users who currently have it + await database.removeRoleReact({ + message_id: message.id, + emoji_id: emoji_id, + }, trx); + removed = await message.reactions.cache.get(emoji_id)?.remove(); + } catch (err) { + logger.error( + `Could not remove ${stringify(emoji)} from ${stringify(message)}`, + err + ); + return ephemReply(interaction, + 'I could not remove the react. Do I have the right permissions?' + ); + } - // Intentionally NOT removing this role from users who currently have it - // FIXME need a transaction here too - await database.removeRoleReact({ - message_id: message.id, - emoji_id: emoji_id, - }); - removed = await message.reactions.cache.get(emoji_id)?.remove(); - } catch (err) { - logger.error( - `Could not remove ${stringify(emoji)} from ${stringify(message)}`, - err - ); return ephemReply(interaction, - 'I could not remove the react. Do I have the right permissions?' + removed + ? `Removed ${emoji} from ${stringify(message)}` + : `Selected message does not have ${emoji} reaction! ${message.url}` ); - } - - return ephemReply(interaction, - removed - ? `Removed ${emoji} from ${stringify(message)}` - : `Selected message does not have ${emoji} reaction! ${message.url}` - ); + }); } /** diff --git a/database.js b/database.js index d732187..047698d 100644 --- a/database.js +++ b/database.js @@ -112,13 +112,13 @@ function addRoleReact(args, trx) { /** * Removes an emoji->role mapping for the given message. */ -function removeRoleReact(args) { +function removeRoleReact(args, trx) { const fields = _pickAndAssertFields(args, { message_id: DISCORD_ASSERT, emoji_id: EMOJI_ASSERT, }); - return knex(REACTS).where(fields).del(); + return (trx ? trx(REACTS) : knex(REACTS)).where(fields).del(); } /** From 749e71be78d5ea9eee496db47f6d49e0e4a5b6db Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 4 Jan 2022 04:39:17 -0500 Subject: [PATCH 067/107] (bugfix) Use transactions for removing all role reacts. Also, fix an incorrect database call --- commands.js | 31 ++++++++++++++++--------------- database.js | 4 ++-- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/commands.js b/commands.js index 1fe2a51..9ed725e 100644 --- a/commands.js +++ b/commands.js @@ -393,23 +393,24 @@ async function cmdRoleRemoveAll(interaction) { message = await message.fetch(); - let removed; - try { - // TODO Another important place for a transaction - removed = await database.removeRoleReact(message.id); - await message.reactions.removeAll(); - } catch (err) { - logger.error(`Could not remove all reacts from ${stringify(message)}`, err); + return database.transaction(async trx => { + let removed; + try { + removed = await database.removeAllRoleReacts(message.id); + await message.reactions.removeAll(); + } catch (err) { + logger.error(`Could not remove all reacts from ${stringify(message)}`, err); + return ephemReply(interaction, + 'I could not remove the reacts. Do I have the right permissions?' + ); + } + return ephemReply(interaction, - 'I could not remove the reacts. Do I have the right permissions?' + removed + ? `Removed all react roles from ${stringify(message)}` + : `Selected message does not have any role reactions! ${message.url}` ); - } - - return ephemReply(interaction, - removed - ? `Removed all react roles from ${stringify(message)}` - : `Selected message does not have any role reactions! ${message.url}` - ); + }); } /** diff --git a/database.js b/database.js index 047698d..ba51ac8 100644 --- a/database.js +++ b/database.js @@ -124,9 +124,9 @@ function removeRoleReact(args, trx) { /** * Removes all emoji->role mappings for the given message. */ -function removeAllRoleReacts(message_id) { +function removeAllRoleReacts(message_id, trx) { _assertDiscordId(message_id); - return knex(REACTS).where('message_id', message_id).del(); + return (trx ? trx(REACTS) : knex(REACTS)).where('message_id', message_id).del(); } /** From f2f5ae1456aad378e6841edde6fae3e5a758835f Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 5 Jan 2022 05:22:53 -0500 Subject: [PATCH 068/107] Command for removing all configuration in a guild --- commands.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/commands.js b/commands.js index 9ed725e..7d1b282 100644 --- a/commands.js +++ b/commands.js @@ -179,7 +179,11 @@ const REGISTRY = new SlashCommandRegistry() ) ) ) -; + .addCommand(command => command + .setName('reset-everything') + .setDescription('Deletes ALL configuration for this server') + .setHandler(requireAuth(cmdReset)) + ); /** * Middleware for command handlers that ensures the user initiating an @@ -545,5 +549,20 @@ async function cmdMutexRemove(interaction) { ); } +/** + * Removes all data for a guild. This includes role react mappings, allowed + * configuration roles, and mutually exclusive constraints on roles. + */ +async function cmdReset(interaction) { + try { + await database.clearGuildInfo(interaction.guild.id); + } catch (err) { + logger.error(`Failed to clear data for ${stringify(interaction.guild)}`, err); + return ephemReply(interaction, 'Something went wrong. Try again?'); + } + + return ephemReply(interaction, 'Deleted all configuration for this guild!'); +} + module.exports = REGISTRY; From 79d6c958961f79e39f89eaa6dbbb8b1e95ba7347 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 5 Jan 2022 05:33:00 -0500 Subject: [PATCH 069/107] Add README info for reset-everything --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 0e95d21..7a48306 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,13 @@ Use `/permission remove` to disallow a role from configuring the bot.
**Note:** A user can remove their own permission to configure the bot if they are not an administrator! +## Delete All Configuration In Server +You can use `/reset-everything` to remove *all* configuration the bot has for +the guild the command was sent from. The bot does this automatically when it is +kicked from a guild. + +This does not clear any server-side logs for to the guild. + ## Printing Bot Info You can use `/info` to print the bot's description, version number, link to the source code, and some fun stats. This command is available to all users and From 942b5f0cda28c652ad7e6fcc168d282e653bbb60 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 12 Jan 2022 20:03:55 -0500 Subject: [PATCH 070/107] Log full stack traces for errors --- logger.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/logger.js b/logger.js index 2087c77..2cbc0da 100644 --- a/logger.js +++ b/logger.js @@ -24,7 +24,14 @@ const logger = Winston.createLogger(); const logFormat = Winston.format.combine( Winston.format.timestamp(), - Winston.format.printf( ({ level, message, timestamp }) => { + Winston.format.printf( ({ level, message, timestamp, stack, ...extra }) => { + // Winston appends the error message to the log message by default, even + // when stack traces are enabled, so we need to manually unappend it. + // https://github.com/winstonjs/winston/issues/1660?ts=4#issuecomment-569413211 + if (stack) { + const err = extra[Symbol.for('splat')][0]; + message = message.replace(` ${err.message}`, '') + `\n${stack}`; + } return `${timestamp} [${level}]: ${message}`; }), ); From 45949d23a049228a6de15e592cf2bbfaf6eb647c Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 12 Jan 2022 21:35:19 -0500 Subject: [PATCH 071/107] Pre-cache known role-react messages on bot start --- database.js | 9 +++++++++ events.js | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/database.js b/database.js index ba51ac8..4847831 100644 --- a/database.js +++ b/database.js @@ -172,6 +172,14 @@ function isRoleReactMessage(message_id) { .then(result => !!result); } +function getRoleReactMessages(guild_id) { + _assertDiscordId(guild_id); + return knex(REACTS) + .distinct('message_id') + .where('guild_id', guild_id) + .then(rows => rows.map(row => row.message_id)); +} + /** * Deletes all the data stored for the given guild. */ @@ -350,6 +358,7 @@ module.exports = { getRoleReact, getRoleReactMap, isRoleReactMessage, + getRoleReactMessages, clearGuildInfo, incrementAssignCounter, getMetaStats, diff --git a/events.js b/events.js index 34e182f..49c69f2 100644 --- a/events.js +++ b/events.js @@ -240,10 +240,46 @@ async function onReactionRemove(reaction, react_user) { /** * Event handler for when the bot is logged in. - * Just logs the bot user we logged in as. + * + * Logs the bot user we logged in as. + * + * Pre-caches messages we have react role mappings on. This prevents an issue + * where the bot sometimes fails to pick up reacts when it first restarts. */ -function onReady(client) { +async function onReady(client) { logger.info(`Logged in as ${client.user.tag} (${client.user.id})`); + logger.info('Precaching messages...'); + + // Despite message IDs being unique, we can only fetch a message by ID + // through a channel object, so we need to iterate over all channels and + // search each one for the messages we expect. + await Promise.all(client.guilds.cache.map(async guild => { + const guild_message_ids = await database.getRoleReactMessages(guild.id); + let errors = {}; // Allows us to aggregate and report errors + + await Promise.all(guild.channels.cache.map(async channel => { + await Promise.all(guild_message_ids.map(async id => { + try { + await channel.messages?.fetch(id); + } catch (err) { + if (err.message.includes('Unknown Message')) { + return; // Expected when message isn't in this channel + } else { + errors[err.message] ??= 0; + errors[err.message]++; + } + } + })); + })); + + Object.entries(errors) + .filter(([msg, count]) => count) + .forEach(([msg, count]) => { + logger.warn(`Pre-cache ${stringify(guild)} - ${msg} x${count}`) + }); + })); + + logger.info('Finished pre-cache'); } module.exports = { From af23fae91f53eaf6935078108aa1f54a0abed7c4 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 13 Jan 2022 20:53:15 -0500 Subject: [PATCH 072/107] Assign mutex roles in one request to save rate limit --- events.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/events.js b/events.js index 49c69f2..4e278dd 100644 --- a/events.js +++ b/events.js @@ -166,10 +166,16 @@ async function onReactionAdd(reaction, react_user) { role_id: role_id, }); try { - await member.roles.remove(mutex_roles, 'Role bot removal (mutex)'); - await member.roles.add(role_id, 'Role bot assignment'); + // Do assignment in one request so we don't hit rate limit so quickly. + let new_roles = member.roles.cache.clone(); + const removed = mutex_roles + .map(mutex_id => new_roles.delete(mutex_id)) + .find(was_deleted => was_deleted); + new_roles = Array.from(new_roles.keys()); + new_roles.push(role_id); + await member.roles.set(new_roles, `Role bot assignment${removed && ' (mutex)'}`); } catch (err) { - logger.info(`Failed to update roles on ${stringify(user)}`, err); + logger.warn(`Failed to update roles on ${stringify(react_user)}`, err); } // Remove associated mutually exclusive emoji reactions From 78ca843de22c501ac9ef4516b56202aff8d08769 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 14 Jan 2022 19:54:43 -0500 Subject: [PATCH 073/107] Need to actually THROW errors to roll back transactions --- commands.js | 13 +++++++++---- database.js | 29 +++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/commands.js b/commands.js index 7d1b282..bc9b2d8 100644 --- a/commands.js +++ b/commands.js @@ -43,6 +43,7 @@ const Discord = require('discord.js'); const SELECTED_MESSAGE_CACHE = require('memory-cache'); const database = require('./database'); +const { rethrowHandled } = database; const info = require('./package.json'); const logger = require('./logger'); const { @@ -323,16 +324,18 @@ async function cmdRoleAdd(interaction) { await database.addRoleReact(db_data, trx); } catch (err) { logger.error(`Database failed to create ${stringify(db_data)}`, err); - return ephemReply(interaction, 'Something went wrong'); + await ephemReply(interaction, 'Something went wrong'); + rethrowHandled(err); } try { await message.react(emoji); } catch (err) { logger.warn(`Could not add ${stringify(emoji)} to ${stringify(message)}`, err); - return ephemReply(interaction, + await ephemReply(interaction, 'I could not react to your selected message. Do I have the right permissions?' ); + rethrowHandled(err); } return ephemReply(interaction, `Mapped ${emoji} to ${role} on ${stringify(message)}`); @@ -372,9 +375,10 @@ async function cmdRoleRemove(interaction) { `Could not remove ${stringify(emoji)} from ${stringify(message)}`, err ); - return ephemReply(interaction, + await ephemReply(interaction, 'I could not remove the react. Do I have the right permissions?' ); + rethrowHandled(err); } return ephemReply(interaction, @@ -404,9 +408,10 @@ async function cmdRoleRemoveAll(interaction) { await message.reactions.removeAll(); } catch (err) { logger.error(`Could not remove all reacts from ${stringify(message)}`, err); - return ephemReply(interaction, + await ephemReply(interaction, 'I could not remove the reacts. Do I have the right permissions?' ); + rethrowHandled(err); } return ephemReply(interaction, diff --git a/database.js b/database.js index 4847831..89c8465 100644 --- a/database.js +++ b/database.js @@ -76,10 +76,34 @@ function _assertDiscordId(value) { } /** - * Just a pass-through for knex.transaction(...) + * A pass-through for knex.transaction(...) that suppresses errors we have + * already handled. + * + * Knex always returns a rejected promist from a rolled back transaction, and + * rolls back transactions when Errors are thrown from the transaction + * block. + * + * We don't have a great way to differentiate between database Errors and + * Discord Errors based on their prototype. The oly way is to wrap each method + * in their own try-catch, so that makes Knex' catch-all rejection behavior + * problematic. This is our solution. */ function transaction(func) { - return knex.transaction(func); + return knex.transaction(func).catch(err => { + if (!err.handled) throw err; + logger.debug('Suppressing handled error within transaction'); + }); +} + +/** + * Marks an Error as "handled" then rethrows it. + * See {@link transaction} for why this is needed. + */ + function rethrowHandled(err) { + if (err instanceof Error) { + err.handled = true; + } + throw err; } /** @@ -352,6 +376,7 @@ function getMutexEmojis(roles) { module.exports = { transaction, + rethrowHandled, addRoleReact, removeRoleReact, removeAllRoleReacts, From 3f816e65b58b1915a043c4497b5f2e3541028dc9 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 14 Jan 2022 21:28:47 -0500 Subject: [PATCH 074/107] Go back to the old way of doing mutex assignments. The new one has issues with Discord's API --- events.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/events.js b/events.js index 4e278dd..d36b17a 100644 --- a/events.js +++ b/events.js @@ -166,14 +166,8 @@ async function onReactionAdd(reaction, react_user) { role_id: role_id, }); try { - // Do assignment in one request so we don't hit rate limit so quickly. - let new_roles = member.roles.cache.clone(); - const removed = mutex_roles - .map(mutex_id => new_roles.delete(mutex_id)) - .find(was_deleted => was_deleted); - new_roles = Array.from(new_roles.keys()); - new_roles.push(role_id); - await member.roles.set(new_roles, `Role bot assignment${removed && ' (mutex)'}`); + await member.roles.remove(mutex_roles, 'Role bot removal (mutex)'); + await member.roles.add(role_id, 'Role bot assignment'); } catch (err) { logger.warn(`Failed to update roles on ${stringify(react_user)}`, err); } From 9ca64ac32b1e1e23c8b44d6095cabd713e9317ab Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 13 Jan 2022 21:21:19 -0500 Subject: [PATCH 075/107] use node-cache instead of memory-cache We initially switched to memory-cache because it didn't serialize data, but now that we're always calling message.fetch() anyway, we can use node-cache again for the nice features it has (like instances!) --- commands.js | 14 ++++++++++---- package-lock.json | 44 +++++++++++++++++++++++++++++++++----------- package.json | 2 +- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/commands.js b/commands.js index bc9b2d8..60d1a3e 100644 --- a/commands.js +++ b/commands.js @@ -40,7 +40,7 @@ const { codeBlock, } = require('discord-command-registry'); const Discord = require('discord.js'); -const SELECTED_MESSAGE_CACHE = require('memory-cache'); +const NodeCache = require('node-cache'); const database = require('./database'); const { rethrowHandled } = database; @@ -54,7 +54,13 @@ const { unindent, } = require('./util'); -const ONE_HOUR_IN_MS = 60*60*1000; + +const ONE_HOUR_IN_SECONDS = 60*60; +const SELECTED_MESSAGE_CACHE = new NodeCache({ + stdTTL: ONE_HOUR_IN_SECONDS, + checkperiod: ONE_HOUR_IN_SECONDS, + useClones: false, +}); const REGISTRY = new SlashCommandRegistry() .addCommand(command => command @@ -236,7 +242,7 @@ async function cmdSelect(interaction) { // Always clear selected message first, just to be safe and consistent. SELECTED_MESSAGE_CACHE.del(user.id); - SELECTED_MESSAGE_CACHE.put(user.id, message, ONE_HOUR_IN_MS); + SELECTED_MESSAGE_CACHE.set(user.id, message); return ephemReply(interaction, `Selected message: ${message.url}`); } @@ -270,7 +276,7 @@ async function cmdSelectMobile(interaction) { } SELECTED_MESSAGE_CACHE.del(interaction.user.id); - SELECTED_MESSAGE_CACHE.put(interaction.user.id, message, ONE_HOUR_IN_MS); + SELECTED_MESSAGE_CACHE.set(interaction.user.id, message); return ephemReply(interaction, `Selected message: ${url}`); } diff --git a/package-lock.json b/package-lock.json index df0b447..7ce3063 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", - "memory-cache": "^0.2.0", + "node-cache": "^5.1.2", "sqlite3": "^4.2.0", "winston": "^3.3.3" } @@ -443,6 +443,14 @@ "node": ">=0.10.0" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "engines": { + "node": ">=0.8" + } + }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -1610,11 +1618,6 @@ "node": ">=0.10.0" } }, - "node_modules/memory-cache": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", - "integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo=" - }, "node_modules/micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -1780,6 +1783,17 @@ "ms": "^2.1.1" } }, + "node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/node-fetch": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", @@ -3212,6 +3226,11 @@ } } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -4117,11 +4136,6 @@ "object-visit": "^1.0.0" } }, - "memory-cache": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", - "integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo=" - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -4260,6 +4274,14 @@ } } }, + "node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "requires": { + "clone": "2.x" + } + }, "node-fetch": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", diff --git a/package.json b/package.json index 3c1902a..2aeb98e 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", - "memory-cache": "^0.2.0", + "node-cache": "^5.1.2", "sqlite3": "^4.2.0", "winston": "^3.3.3" }, From c43a34663191fd5247c63847f022f56241b497f6 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 13 Jan 2022 22:46:59 -0500 Subject: [PATCH 076/107] Commands for selecting copy target message --- commands.js | 84 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 9 deletions(-) diff --git a/commands.js b/commands.js index 60d1a3e..e1b8c46 100644 --- a/commands.js +++ b/commands.js @@ -56,11 +56,13 @@ const { const ONE_HOUR_IN_SECONDS = 60*60; -const SELECTED_MESSAGE_CACHE = new NodeCache({ +const CACHE_SETTINGS = { stdTTL: ONE_HOUR_IN_SECONDS, checkperiod: ONE_HOUR_IN_SECONDS, useClones: false, -}); +} +const SELECTED_MESSAGE_CACHE = new NodeCache(CACHE_SETTINGS); +const CLONE_MESSAGE_CACHE = new NodeCache(CACHE_SETTINGS); const REGISTRY = new SlashCommandRegistry() .addCommand(command => command @@ -90,6 +92,26 @@ const REGISTRY = new SlashCommandRegistry() .setDescription('Shows currently selected message') .setHandler(requireAuth(cmdSelected)) ) + .addContextMenuCommand(command => command + .setName('select-copy-target') + .setType(ApplicationCommandType.Message) + .setHandler(requireAuth(cmdSelectCopy)) + ) + .addCommand(command => command + .setName('select-copy-target-mobile') + .setDescription('Workaround for selecting copy target message on mobile') + .setHandler(requireAuth(cmdSelectCopyMobile)) + .addStringOption(option => option + .setName('message-url') + .setDescription('The URL for the clone target message to select') + .setRequired(true) + ) + ) + .addCommand(command => command + .setName('selected-copy-target') + .setDescription('Shows currently selected copy target message') + .setHandler(requireAuth(cmdSelectedCopy)) + ) .addCommand(command => command .setName('role') .setDescription('Manage react roles') @@ -237,14 +259,28 @@ async function cmdInfo(interaction) { * Saves a user's selected message for subsequent actions. */ async function cmdSelect(interaction) { + const message = _selectCommon(interaction, SELECTED_MESSAGE_CACHE); + return ephemReply(interaction, `Selected message: ${message.url}`); +} + +/** + * Saves a user's selected clone target message for subsequent clone. + */ +async function cmdSelectCopy(interaction) { + const message = _selectCommon(interaction, CLONE_MESSAGE_CACHE); + return ephemReply(interaction, `Selected copy target: ${message.url}`); +} + +// Common logic between cmdSelect and cmdSelectClone +function _selectCommon(interaction, cache) { const user = interaction.user; const message = interaction.options.getMessage('message', true); // Always clear selected message first, just to be safe and consistent. - SELECTED_MESSAGE_CACHE.del(user.id); - SELECTED_MESSAGE_CACHE.set(user.id, message); + cache.del(user.id); + cache.set(user.id, message); - return ephemReply(interaction, `Selected message: ${message.url}`); + return message; } /** @@ -252,8 +288,27 @@ async function cmdSelect(interaction) { * menus, since Discord mobile does not currently support context menus. */ async function cmdSelectMobile(interaction) { + const url = await _selectCloneCommon(interaction, SELECTED_MESSAGE_CACHE); + if (url) { + return ephemReply(interaction, `Selected message: ${url}`); + } +} + +/** + * An alternative way to select clone target messages using slash commands + * instead of context menus. + */ +async function cmdSelectCopyMobile(interaction) { + const url = await _selectCloneCommon(interaction, CLONE_MESSAGE_CACHE); + if (url) { + return ephemReply(interaction, `Selected copy target: ${url}`); + } +} + +// Common logic between cmdSelectMobile and cmdSelectCloneMobile +async function _selectCloneCommon(interaction, cache) { function reportInvalid(err) { - logger.error('Failed to select message by URL', err); + logger.warn('Failed to select message by URL', err); return ephemReply(interaction, 'Invalid message link!'); } @@ -275,10 +330,10 @@ async function cmdSelectMobile(interaction) { return reportInvalid(err); } - SELECTED_MESSAGE_CACHE.del(interaction.user.id); - SELECTED_MESSAGE_CACHE.set(interaction.user.id, message); + cache.del(interaction.user.id); + cache.set(interaction.user.id, message); - return ephemReply(interaction, `Selected message: ${url}`); + return url; } /** @@ -292,6 +347,17 @@ async function cmdSelected(interaction) { ); } +/** + * Shows a user their currently selected copy target message. + */ +async function cmdSelectedCopy(interaction) { + const message = CLONE_MESSAGE_CACHE.get(interaction.user.id); + return ephemReply(interaction, message + ? `Current copy target: ${message.url}` + : 'No copy target message currently selected' + ); +} + /** * Map an emoji reaction with a role on the currently selected message. */ From 559e09254b51eabae8e99104cf476bc1c7d80c19 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 13 Jan 2022 22:53:24 -0500 Subject: [PATCH 077/107] Update readme images to have select-copy-target visible --- docs/select.png | Bin 69623 -> 63627 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/select.png b/docs/select.png index 2110a3ef731b944b46cfd110470b14ba0bb51a43..b79d09b53e5cb231ced73af860dfd570738cf735 100644 GIT binary patch literal 63627 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�I0s zW`|)NLKuM9)$jcN2^{HU<>dtx9L#5Ht%m_7N!t7?4-en8iWs)ydC&O7M2b^V^s{(f zdIkW>At9j|*^kjJ{q3Sa_MP?7+HN))lqNVwgY$&cly9_C|3;tttGCIu#Bh~q)The5 zsBRsU0cjH#5$Rfz&a%fQ!beN=+@4r{h5cy*#Q|>`yFpL4r?E21&8k^7Y#4=Vi3B5sxBx;vk5C6(M^_i~?lpF#VPYz` z(@`%)I!t6@VsD$DHIvo+`BUX!n3ID_r^pOkG1tE%_H;1l?YUi1Q zpxQ2JAo4~zlYLcC_z@Aok;>(`xl<^bB}*x`l-wo5|L{XT<5S)k^Ztsdiz`lV?~v~H zXbudmc5{kYwADs1jc8;AMeM$4^}w!!8!Z+xXqJ-zt!ZEt-mG5klbubfbbmv`l^V`{ z06_*i=2}*S{10bYb<;xvT#mfHvw4-`1;SAVZQLe|IArvf3*TuQy;&crJ>pqaUqGO5QA)tMviLl))%O+A)^8jooww^0D@G8pKYoEwna_+yYDMm? zqZOSg)V++Is8l+|4=TZ#7M*&8@2kQdoJbEjF`4x^ppk{ z{vY0`*qRF8(5wbDE$TT}A>B=pCz{GemLW~8n3IpKoX-ytpLWqODSHI0l2(62$|%yf zMph3x)8VV?slJxC&I?S5Tfhtzje`H~jHTt_rtx-GmOAmaCEn$sg~5I*HCnEa4RDHS zU_$FWIQ2^igXD97rBk{yc9V>%kaL<0-)%~gzhD9&7YuQe+nbgW0?JKArM+sE3!>{a zywruEUYkoFP2aKg#xR*?TZ|rEXK8D1Pq4csovksI@bn~5uRT~E8*TxBRi*-UVx$dk zJStA8NY)3>C0M?zWs>0F5Z*%~R?0NIF3phI2=vdLogR0`#(QF7yaf<1ugNjU!_AzA z=lPcxU6;_-0K!(Y%8?pNl-ecsprb&Wo!y=5)al~$HaK@qO~r#;gYSM18Cdx2h}9~W63(+Seg6jI4ahCm8}W)o zcZP3=AE1bov;O5_+{-=K~zVmCZH< zh@QjM&Jg>NQAb5Bxn3U*tdEscO02=jgtW{|5$JqEk?`T%&G% z4jJn0)xFq@Pui1lbbM}eVyU&E%6iEuY z>euTA#=6XjCUfj))k>)JiM}{E3Nak}jSONK_c!Rj^2;JYq~bsagbEy2*N^yIzh_kP z#>Q&3`9ZP=8RQQ)i5u|4w*hTbU-B70R z?2hUQ=;gMxAy*`ByJSQeZi*R28Nze)YIXEUYsJu7M8|s26bf)v-w#A8-0jFSOI3`% z#wO~+m9ep_iYG-z)>PY+5GU8uFEP-KDk7GU*A?!^?XGqC}AQXBlkJThLby$eKyo(^1q_;CEkcdUGF-z8a+=V9xyeEmMhVzDCZ z31UlSBCz-5^)6AJvcRR_GVX5JoMnoMk39us?!3&3lOLv(Z!pL@$p&r?`@x^b3iJ^O z-OpavSUN|%oGMgCKWJEU0w(3CXoNk)w6rnreG#59?)uG0rn(WCnws7ncPC+;>Ms9* zEmHZ}gDJ!7JGQ<4bfhjdIWt*5;Gwd$b@OA>X(}64CUPG(q}MLFr9#uZgFq-f-u1*V zP~|IC3;q|%zx15^7s~Instv+) zTyxWX0SC8g!yaRyGB!uDh@c>8mZ)FW1hvYwIV_Qv%k-(b`-EbKhO-nW>;qRt#jeX* z@%=nIl|Ns6P3CY;aUIk9q}{I4ZZpeS`#g7a?cDiE|8#Gv<%aSVms^vohi;ye(*e@Z z2vSa!ZiYf6m8zbF{Y#fy9v2&8Aj0FDUh1EzhkQsoqyr5P#)_{sH#X>7XYc5ECs#lk z<*algPyuF5zC2nL9hQbKdD-ao8?OWE_>Ix5NpHQ7u1wrkeg%B3on zll=>+7t`jtSGpu_kLPgIz2S<^p?5%0<)u^oQQPNVq^F5RIV$qE?A=)4o6@W$4?YRz(W?Gg1AKCSX}@hdu1)M#SVX`eQ(Awm^C zyJQGVoMN9lg^N@oU4+?PUetVvVWV(_d>*W}>t)t|nDQ-h|UPP5`Pj#fW9 z=}^d}vTaBtK8l01$z7Z59Vs`DuhG@}H5hrhpEOi6{x>m=Bz%``7CYf?7pn|1d=L51 zL+MnmRXZ-##>x9K4@W7~ApVDezwdo{0L?~x0ubBZv22?0J$lsVz1_WBQU>Hg{lM_> z4>UB5BhW-hsLBAAjINdP$pPm0dg+skRhpoJk`a4ytp$+cB={5?69bM8DbN@Org%k~ zEkCbd?|ERATf97H>TJJOqVH+*c~F9lPVjMY2bb^q40+gA3#0;siN|%uWj_xwy|ZNw zwSYcLyyGsr%|f;Q^=iL0Pj?-SD@V)yF#;%{2DuNLo#mk$fL`r!(P=llOCy3}EP6sO zvnwYc@SX^m0&(X`TCp#4CE7dD`U$R1xR$QjaLG`I&CYUp@%;9qv$W;{88{d-2gGK* zy{$s<4yBxBkHk+6WRIJf_&f*C&GpTb>v(MfQ?ctkiAD7@EMVrM8YkmIFMZy?m2N3H z`^BieqxD&uxfRH_=e=&UTO> zA7=Mzk_xEBCKgknV@4!WP5dZ1IL%2GCH}otx%Ec#UV4Xx%i+xEOmStv#e;%9IYg^T zO->uytaQ-AA6NE@*Lk5ac3Op`@?p$xph%4weTt)mmf-b3ojHl?U4frN|LFMi*7$j#bjfK51pMkg6r7*eI3(6ar^UtNp&GQ!GEpPAJX0_S=SVzD0j z#6EwuxfZh>4Z0swD=V+@dCJlOmEFfjh|(fIR>_=IWf043cLzA{ILvW{sJ~ zl(SDaFifM(YX9twbvxbqFBibiH?e~Io?5l7Hlxzv4gH&_j|fzzmnm7&FQNC zEu_irWtxlp3nP(prdM2SYV}&nHz{cPO5-;fDp?EAP-j(<(dB|9{oXMWrE>TfF|H>n z{Npta&d{CfBX@0oXQm0yF_a)KSV3~o||0Ou3m#Pb%?zGjkvRx#bTA;9Qi_^Kxy8hMXq+sBIMrb zv{hzzi_+=9qFIL!A49TfMp8`7G;8Dbf{2)Uly}d@z~DIo8oou9*JCqWD4z4aSbBUa zcQhW<(BL^0RhatP#Xk2Z8(CuDnqF9Z?C4kl-7{%)&U5i8j+P=}W&N?zPM`HPFZ^8- zHW_ns{dC1TJLltbZ5tD&!t%Rx(lg7VBvd6Q2}74_;GTrbaj9rxLh z?)$rn-`@t>51_cp4{CpYU3~)kuzsgc*6Z$Ly5sKr#&pUagyfPtFLZD-J9pM|Nh0A@ zrzJJji}>w`EKRQ;JlXb^l!aWf(V&a63;9)$!VY4hH_0O znl+3Z6UomfDG3+p}(1RsUYJ5EtoE zppKHyNGF)FH%QZ;OOL6TH ztS;&>LToQm4QrK?qBw>eYHLVMM$WESd|FBt@(pv$d)=R;gpS*Zd5qED2oMv6RR`@@ zz1{gAS0mqe1Yo72jFHj^*!8o;`L`T&{h^#``x+IiEz2~O^B$9INnDihs-{70=n9j- z+P+Jiy{1<@t~X5mlXc9VMpoIW1PcKy*$jb$x`7%5jhYNT+JNC^Rp;0GvUG2k;&gqx zVFy`i{Z9^3Qm4K7PCVpAzUoUc#@pC>fG?%l%vGE)KUi;KKA91F-MgQzh72EHaEHt^ zdqQzO`ny#ou4_`AZQE1bUJ?oC$lK@Zj*jckSX{Kkik=+bh<>3^@%F!8uy>+11q0GS zqJ&<78`_@jkDCKo6&1m?Son#`1vwv+rQ?B`8s8A-m}q)PrKcufq7N6;ZZnw}YP`S{ zPYsuFoFJ8!|Gr+r8cX`u%%Hh`!3&d^DtPCfp5v`cVcLvCjIy28=c!h0=e z>I;49PesGmyWzOJ%Yf%@D>M$jbZ?Oh391*;N3o)%bl4VUR2jalub#oulX5_+<$7s#zKT9n+j*km@mP*tiVYB#3 zr))0rVO%s}%I5Tna?KIIQJIah-tCNi*MHK0COJ*`@2=vDVYBG|FiKUmQ}mRr4uo5# z9x_6!3-V|Bh)%Pf^~_b$lN5s!?DuNNwy6Rk%&V=k1dDDB<>gf$;woOhIFVDKf{@&e zP>o={oxT%m{M4!_5^7xS+t~9QKJ7gT{z2EW;M?}B{VFwjpZja?{>`4@J%@HJY|>u_$0aV#L9;-d26xJ(G|Cw)sj~XqZ#5Hx^n^guL&aQ(c=oM3mRNAnRp-)W<{4nEzd$r4M${aK|GWDSoEi4d11cbe<- z(#uyNrp+#My9iBFO75Zw-GtWb4Bn>iY_(MDjWx9ED@g>6yH_sR&YVTNG@z-~o_Ekx zb(==ihkO5zfUKp#=iZ+ym*;&k#%3|I30-vG{fm3hU@m5-+H%)v449l;NzG10qqz2ihd@@yv}Ve_E3;dGab&JO8siQqcd9UkU$Q?4ozTJVVAUT! z0+~Nwme^jbxJi6;9c8cY3OpeoSQg?M7(6@WCi#Xp=&6t5`L_TCsjPk!4LFA%Lh$8Y zi7*Mxt?Sw6hTDWN-2^2ko8WHA6iBxG=(^1(HhY%K}cSJJci50=7n_v<7fZJS0 zy4{r~=++B~a!QESsh^Metp*9BYL*sL3V+SFG;;{GE;yr6KwtiVIe3X^_dVRE0PR@l z8SQ)alEdVkRB9iQN~<5=d9^ykKDEC!Tc_bQx3QsOqOWQnm||*{=4YcyKZbp~DNUf` z7ha~&T_^k*(aa=$eaxnR((>%`(te@(uzTNWjZsRP|DKiabUV4rV`=H}_}!s4XwYpA zglo^xP_O5LaU7GCHr>*ut4w5-y0RAmrh4yQR2mOvX6f4ngnF-?4-TX#c3wkMS&Ww5 zR(sh}Tvp|kw91}=!q>?O?a+1jEs)@R71HUlSN^z$$>9~6l41css+N@G}?)ltkkn+>Fghb?|I_XQ$vJyZ%h?w>5foCG;imqKK5%r4&9b|5rtsUbuglci?8nT5WjoLm{nmn;Mg-T zl$l-k?pvGBGrs1V7r^n;mbM>vs+n`zc4BF1I27mY2}A9xv6QjbhK~m*nKeNZBhppX zuSteQ2lRai2h?#HX^bpiAB`?iO$Nz9iX;S`+JpKe}INPGKd~#-=xo$hRUSYVuZH*1lpH?r9 z(9sR@tSvi-?1#L~W}+W$QLmVnlB!?)Z=A%tqwZ>t4Rh<06aR2qOLW_-@Gq!Sh!XL7 zoq8!{22?PfO}rM~yL55s9!R@WO+X(O2mbSCm)lz^O4?_?oNmDA2Hn@{XcGQX(0e%voEHuV%xOG-*$v&WJSz>J@ZwICmxoE3LG=c%!dsLcu!?k1{( zIgkg=F0biXKBVNfKmR^e?VE0n?Pzv3cva_QR}y^uk)+Lywwbw)yjIpjsIh(~(8e#k zLJ?Ckp4Q*bhcPf z@DpLk8`C5=zFc{xH9=m>#A$IWV{@t~$dh@KFKXN36qWa4H!mr+7g`lBQ^4r_stq0D zFD8^ZX;O5^J^ohM6$jz_Ye89Is!7x6Xw;COYG3XZ+!?>ChrUEx7L)V}OUA^^*hRIh zKnWQxWK1-<&^h|NPnJ*qD5AA=eSm(oCCWb_b9nnY&hU6reQxZ9x7%XLJ>BDY|5t#){h+0dA;ETjvl86 zhbU+RWv+63$nDL!&tH1OUJSnYvH6}ambe!dQ_~DILjAk+XdIKE9{W|$d+8dku z;rgA_!U3a`TF@LX3k;!JUv;uYZp60f|@xE1u(<<$S@~aCO<@Ppv!V*5%^TNpR zFZc{Ym;HB*qodahF4OqDZceZAry_VKd%QioU@z~l6!>n+Q89ln;4;o~;pMjNIv!P* zrhIa$@#S^DxjOdb7EMJv+FjaTiB3=GetTGAu!g5u;(cefxUZRdtO|+TO7(6Wz+%jC%&X%X3k%Jqe%#gM8nI=%`xP$(Ynig8ro&N zMPExyTRcQax_OLT&&dk%#ee=xu{3@*U?0G}adwC~v zcY;oTNu;8+yjqUOTf5xZZ(wk+nk2WpW&hT71^t~@%`VHNn1qmaYINHD37d7}uA|fb z^M%6%&Dx5DB<23)EsHTs6jFDJuhwq6znB4SG2U0jZwx{de63}7@3t^tUjvBUUVWlP z7&Vm}SMcER%37oi`tWt_6a9HtT$$qvC_uNFGRp%{DvaG7fR-R@hT?N^+x-mBoTn4> zcqva5y0&)jb$^mrCo4d z>-Z1M9ve+#r*wb)tkkNbB71Q9V-%%706Pyi8_NC=6tnEimPLulP=<-QZt~9T4V517$%i8}X!>B?t#7JP_3bi8H&k{5Lop+xqG*z&iSZgp z86`4lil01?9qT{8vES2#(5tsW#6n!Gem}nBGeIjvMm`K>75Y@CIivDPEZ6qHyTGJQ zQ!^pOQ+4}tZ|3jqoyZ~L$@i*`?4^vF)VwEL&yB4k;%8>~h~@Iw7+-YGVV1l=3-m22 zvedLbPq4M92=~fo#RX5A`-hCT-eqK7Hr1@6E$MfdzrSW=Z2Rf;8Rl5Dv+pVn_heB| zx3TQ!eez~b#zBvr?ipgQvAH;o&p*atbn(bvWS}o~rz?~qB6|E`%fDC8+N6`!JEuvv zFs+dVPCAx47uJGADGd6YxwXvtvlb(XMI;2o!iZx=gapN6lYc7ap}KdDXzE7(Wi^qB zic^i@{Q3@V?CkVVRh|>QKNX7V?>_@t+v&%c`}Hcyo73KCGfFpVb5M=pEl8zB#9uv5 zPK}i;F_T*0Q6B!3xse|oaY&=SX_)cpkvh%CR}QEzq#e!QscbLXC5t#lwl=#Eor!b{ zyhql^|1FgxfJVY(V0WJJcjcFmCUL?K%9@j4_V&>}+c!mYcUjqfEP2uKj~_J+4Ft_Y z0vb7COczpSG_)0!o0ar?W>(8&UV>!wbPLGsZ{RF7s)FQq=KJkEJ$sz$YO{($u^Y6{ z{3vDyNB%$t4ruoUhIQp%3!Bh&;M6r4F4)nuzv1SdnHp%>RQquu6Ww9@;%N~B-4eX3 zKtsT95v^H|=IWaN`2 z?sO!d;Tf4IEjbL~h8-5i8K=sOjA(%uc~47EKJQT0R2qRc{Ysi(W^96MZ=VXSyox8X z_WP=`zubs^P5?vBM?ROF5t~f|HdEp%wN=w<+NJmVKgqA(19OH+5Y-%y|cZVHQM;fdM8xLjOMf7 zSIq`{s+uv*GC?ea1$ft|E4(r#6V)LRd$XMZcS1+U(+12vOeym5Hctfdura@!X9>L;Q6n&LO)dvhk6*Ipw+fzymjf}Pm} zd7oTtmRo_7({VXDSsNG=Od@4#=7e@$T|KDRu8N0rpw9HCox9GjiZa`Zj!i30Ow=OI zmG!3$*Tp+&T2DxC|J2kUc9}R6Llh0NG_$1|x>V#RWo*ew_#VsMd}Q9I&RIUzuvh(| z66Lh^o_sUAChlB4O{Ot{zv^98Mh>oW}vNK7UQpLkTJgAe(Y?5sZ)mnxBqim7m@)ZJ?7JontS{Xu6dN6=3@-6l41N9&DY*q!gxMwR^~2F2|HMG0 za_s>m8k&$jT?g{5r-%8yk6vkt$*<^U=LuW|4g1?B&*iPW5#o>mlj-Dg14KlkwN{fv z2dc-zI`zL?ZTg5yV2lgZcW|=h)NopH{*0Kl>X{0pJ6kI?Bq`9iQNobJ>JIU}kHIiI z`%7ar0{N4(0gK6*>8Xy!Vk^2cmy6Y&A4S{S?QnDJ$K~ezq-Ub9k~dE66fz-2Z*Z3j z!(?xY%n?W+?b4o)n&zkM{>;mVejxtj_GjViw=c1{O^V$~ZyhmE{f9(S^9&>O^j7e7 zsp0v%ofYt*!CO*T<7{1RH2hWKrs`a5mN~ZqU4@i?m3qRfH)vE;ZjCEHD3Ker1rl{y z)^sE1ojTyh?He0CGSef^uRI!N$kJOk^<(=x@rVeA;tb4sk9`E1R292tdwbi;xanDu z!`6KI7#_zN$HCe?YLc!@W9WZlkZT<03@P4C3`)kC9rPt@rta+;DU}KG+i>?7_70ud zBxo%%apK}0tOj(fSllS1q+z0K_Me>EioAQoD?+}NrGQ(@pZxtt7iUt^rKK%1&44!KQsYkz+-Tq=~G7jHBbn zrE}WK`}3VDQZN^nJz_VykZR9HXyQv_0tC67?>@*2j9!9iK>6g)rLI&l06Bum$a0gB z#SBtWQd#q=7)M32NQzBG5GF+!uFAH>(OwtS^K?a-<3(NGq7?+_2Bd$)96 zDS*+E^&@kXK3J)4bl3>M&??=>9sS)2>MxH4B82L-Tr9VYu%k|AHtdnV@#>!2fn7 z)tYa2=QK8bkx{~v`9F;2AO`x%KT}r^Bi#wFr>Diy945C5tB@BjStX>kltuVwKqfft zSzE6G%zDz&5`-m+H+MSnjNUstF=4D-8MIadp(6u1h{)N#?3(bh&y*y-4jZ6m)BAfJ zav*9u9vrZXPbfxXw7&jtVrF6OwK>{}PNa1j~D=h`xQAeZzbExRlT} zIPoTlI0CU|?fNm?*^RdDbcx)CHWK5(*r&D12{-kqTunU9$NV zB%Udn71gEL;4&RPZ`&kHQY3C^=bUMfnHQj!;KFAeiW$)U&w!WE`~4{g^(Gao2?07f zz>+^EVKM|jS-4~nqfC*e$D%85+fG7smr)eVpJN^SUEBOX3-qH0qXVz2`a?lSVif)> zZFIEI3?=x9jChm0bq<>Zdxmw4Fc; z|JHxgMqlEU-TU_gi8C$iQD=|n_F(ni)WC5AZW?^<@+Z910854B_oIBnO*=*iT!Fw9!D zm9@M{68h_75i24^>yo$CO5()+{XXC{Vg7TPD5Lk1U9EI7%VOuC zpg>#LP*I>O?&mj1U;1Y}DEj%1`7|Jnj-t(hMtaVs zcmTeLj5iZCuh#no9!+U^)t=A-DXHKGB1(kxoSfLWF=cb-J^l4Qo=M+_v-<0C35EoA z%``M8z6m?$#b@hTj@7hv2Oc%o-*w6EXFqCZOZ1M9k33dZFI5{%AMJaMxAR@!xQ+20 z6Azkxbc%~?Vb?xhSFvAwx^6ZbUIPb*%OWZI?&C77mxQA<`!#7(90RwHb#ofKd}$6u z`RiW~uI;1Scs&C`!q7nM`mrtabX-wEo1>3uV`(XN-M)3{>CIM+cXnl^v{OuiQ?3?S zNi1H;LgRj&U0WG@3?pa!dDFU-vbIapj^w|0>$I7(Z@Bp^B+qd2>7}d3no?mW2}ChA zKK5ucNkH5yRo>})WQ${2nd24>4E@qGFV&8PmQj=3{h0crx_U69${p9kCh4@_u;WSb zIH7px9kQQ*{psyp4A?G(ZaQ?!VPVyZvv_-*>iHM{9;i;fJTA;LoQ-49>fTYSlt|gP zt5bzo612CsckcKoeqxXA>FHTHPP}CQDOr11J-+0GqR6;EZ6Clk zc4&nGn4#5Hob_(BhY>1{z8-fbd!OHX#Mj@i*Bhi2A*yvOe)wXRXt=%-N{9kb9tI&{ zP}d!_s}0-wXa2&zh~ZG7X-M+BhvUHf7UVb@4NPWBFxTakW#h-UR~zj6h&gU2P106V z-SFXg1;#Q{6>BOg@>@Us`$QMa_f4}3%qi)M>CKJ-s0?`ACs*(KuAcmxwjWi zWeQEV6MsW6hw>tLu1UMfYPt7MdI>|57C-<4$cr5xfdr$10FbRtk`s#5}NdGHB^d^lo5iHl~WxH zfj|apYKA30eZtX>KrCjbFD|aCsi6|UGww+sAp0QpjtPIMr+IH6$UZ`FaMO^@{e3C`b?^D( zxKORe%XdeV+{dD&g&#sGVrx5?U82zt0Lv_8{4xfZO^XaoA5&A)WfwQ1PD_1O+_2$F z;CIIbP)&ZqE@6O9g*nO^pV+kUOg z^ZHEBn+qC+l*HK#Nab)rb@Yy4nIOT$i-9;KVfdx(K`1~K9Z+9pBIzkkg#nD9jlI2& zT{~7#BStr!S(#H8DE*4eIcLzckU5EqH!E?=`aUKflru_bNrGR6<(XLpcUWT7#}fn~57xvyqsXNKHrg zT2RpYf`uwWFae|UBjA^M9X6(8v2ilpbU~(sJBRR9i4NCSv<2Mw9)Teb=0CojlQ$jF zx!n%PElm^@$Vo_2y1e9n>mqqakfrrYXlM}SLVa*TGGbaQ=zjhBH6%P|dJNX1x|-e9 zD8IB69aaJKupd+pWOaX*mdZCZ6&8k6990;iDoffjhlPc8t@)7blElQtfcVrqn;70| zcYf=y8NXdgOXK%SN-#?~*xA`B)9`R{2AB6G$C~^p^tOn$@{^ej+FD{`W1p%IPZFfz zRq9tkAc`L%Bj)!z*+^6&VPoloCnw!u;t!iGf90^2d%MTkrf<^ZHH;Kq5dQ93V?JrX z1k|mgCK=-+6snXO&o_C}Y4bItO^D%XiGnh9R+GLqd_9a(kaL@K6@EOfQ0arUh?riO z6%CqBWmxCZ^2=VPg@>cDfdrjR?ud=+j5bRpOBal2C&`%FSM}8e8#_C*`FL>`Q{9J-gLj;Kr0CkE zfnp(wC5AM0iu);(;lH&maHORAo8}-jiv_uV<<=)pF z4Npw`Y1ncF^TL=OIyt#Av$Q1Cq<`V)SdSDz@e>5A6+V6pGUNFJgGon^C~8>n0FvzB`j)Tpj2j5yO2e)d6y*8gX^GU&2aiuJ zN*g;0OPiz=6fgn9#tU3Z1{Nv=s*ra5lhf0|xj8wo->s~y8kR}+7qX+}2sMo(s=i`k z)eZrK2RZfm!nn9GNp#J8ilge9YF7I-nbt+5jJrF--H>ATIHP3;uAmNmAcrbgSS3(3 z;rBPsuEB49qJmfxBO^C;r|B^O>oc{sCUsnR76|p3-qxFj6swjm-X?v`!1$r|!;cr8 zv^Ejs)UB=c7c>1Wr+=a5yvWsKsd2MrF%5t70`2>cSTT1A2|IPbk`ZO&(nh}On=$Zi z-zYcc6$Vn9_tiD1Z;kmE{A}54yjD$Jr{Lucft)#Mdu-w`sM?akZI69UFD{NvPQF0> z<~+75hbG6N=2KW+PD4;zHD);t3A5n}9o{qq4Wm`n)u=?@m?$WGLB;#qw{MXGp$(U7 zNoL^gd^M+{$d=dwNQw23+|<;sUtP08xxTuV2e0?{_a!WPL%W}&q0}*o0^^-$*{86v z(HC^Xe;-eha8|(!F#DjY`h;3tJ&}f%Hmk5QM3*|qEYYQ5&+xdud~FgEYsp#s<@*pz za>?(EkMy(w5UV%_H7O?i?9$SRzHqrK-^2ZZsVU*rPy#>UcURZG08O@A3bwJa^WMTO z0fj5T2jXzVI-BaEQ+{Y_WnplbDfWi?qUXC8K4Em2lsWg4{`ysaczp}%Jui+( zn@1N$V}2hvdVIAT1^%HrzkG4cD*WaYGND%_9KW2!sY+&I=&D z!1*>S?hygy%Cu;%S-71a1EEepS_@o>=v~PUy)TCTx{*wTKoFs z0CY+B1K>SSt~Ol6$#&f|U90}Wdca+v<5iL&+Nxsh8xFi)3+*YA)QAEWuIs*gN%8;- z=_PEQlHZ0z7N8~2(9;-6?1oou0#nzeac*Vc0K^j;2Gk=i`0jpw6EtPx5s>vA<8XHx zmFr#yy2)6%3=jkdJyRwwZoR`2E7y#wwUN`-^T_=PHA|#6(#1!}HPgkXl%hd_z87d62~|Y0 z>1xNbJM2D=?gvyxICnSef)U$|Dq4;>d8uyZN0-?0#jA%@W5j2_P7tpsPqbPy(uqI5 z3S-t%&W1q3RkUYaCicBoN5eWDC%(FTsvq72sH9YRKXO5(3FO2c3&f9$va=KJZ~A#@ z-ZHG+UEjCJdmUkGPuE7p(lWYfjML(V9G=$iE$!9suVo0{eghiBy7{&+*=@?KVz_PE zxRSunw9y9Tb;_-g8F)1*DO6C1U^TEqA*IwF|6VV z-ixtVqP|C!48colVIOZuTl$W5wm;v$?|sgDwjXgW+jx66?Rr|RqUN^rttXW|5EzU{ z+d8-3%It5pOAD2~;$!E)8RHonl91w9u@oC2@c6B}iZ{e@A zDcvmuteFe&;0hWV;HgJ@N=tIHv$?n}JuEDUKouQ;DwP}nAp&N499&$zM9S0C)2yc4 z+S(uu0dHh$G*(XY4h;%0_h%~;!J$i)hH-J1OG8ILiq-7$wbo)l{bH>SPumdeILY1zr#x!mZ<r9T;2U*An969W#7_Dbo}wnF(cf;NVI%~qs0xvafHAXdefbb z4iyCy1|!mbfKSN)go|ry#&Pt#-w^N5e?Kd(R6Kkn;^$H?mZd-n%BlMKn^TQoaTU5= z?5jpOD=UWZhe?E-9PE{ikZ>TGh8cTx{r{!*E{2ANzFJLx{HR>^d43L42jGIqYe-uh z)mcqf)j*vOenssnZiKgOK2L4xe~+~4Mrt2>p>CX(khZysTfU$w@a}J)@3&(>`q64 z;2-ZKDs5)ql}94~7ug%0C-b^@2ZX2>L-C)NLx<%}CM99DNAo2syz`f6pj)=#WGSR4 zl|K*%PgBUt>(PGQ)?3iGOvGs|#b6-5iURB`08X*K^{H^8%GSUR1IQuQAKaDeHfL%k zm3q(%3pfO8W8UW6fXaUEKt_*4 z^yEA2XGzIgUwu>fSfVTur``SSIn}zO^L2i4vC&$Onx%l>njc73mwN45sK$xO%QJqq z@(!urYhdN($;9YnwUQPTXTBUUGfB=vKkv1UKpc*-)&+5hT(d>VZOpVzGWJ8nF!9d3 z&5IUHpb(mNx4o`+Ybq~$dv9((dy}2Alidsi{yA{Fob30a31Vt*2jBbYGEr+8w#EF2AxFT$2oo>c!ABeR zVUa;GN=MQP4y047kX%vFC^Yq_T{=1yZVUZKVN`e+>iD#?%o_8$Pkm0|h5}jH# zlt=TDl~#fyf{Ve>c=dJP6ZSrPQ6$@+D_E%y^VZ&|$^(8J+0!SF8$pn!YOLZ%Te*E3 ztv_`0H7hG98RQi%`JVpf-xDnzNGCD97D5#*`Mr^I;L=#jPx|F|OOB(*U5mle`A4kY zwrR&n-3eO(CawIHWuXN^51G<=#jF(8|1FT73FA}Kr&7Mk)DEw{w0ld-DLl_%=Q%`5 zS3=HGm!AFN;*P$N@!QOFLVv?x>Hh7h0!!R~3->KXnxLqQP@RfBvJv5N!qD?#2fh&0 z7rKso9%kc9V%q$xlfG0GXY%LyoHD-xB( zgV&?QY#4f;H?%HIJP1_@BW@TnZx|^nW3O_Oe)YdGp>z=iCq9gdSGGBvw8V5}Xb453 zKiJfUalA9+Xa)*0$feDHwN*XW5rK}C;rf|L(pzDQ#8Y)b{u|UbR+?a{=tD+~IJ$*Y z!q4AQKjMl|gCf$SaGU%R&^pfs*w~AVEljQAr6e^K$NyVm{iU2CO!GSYd>TEEm!XCj zB5y2OhgwxwzT|w*_1E9Z8r_f|jof_eswEUQ6k}5~1;Y4$H=BN_M^3=3JZ*Ixt# zE^E#F4CD{rnzZ1nwalJQRl#wHKT{2&3DYr;fm)X-Tb#^G7OpC0B?E>Wk@NdUaK-Ca U!FmNus3E}jmiLjCZnf{vJHKxzPdBpX7{L!-P>urWdr6Hl$ z!E;5z{n&L#TR2saW^6f2BpUjD;rEFTZ;6*O;xen~oqkUE>t?$_a5#n?->GA0AEvVq z3!#5+<6w5C&3B{t=%dh&S0r||Gt-K(J}gt29z1@PG_AvK9Y0#Mw}u4IrttYvhBnCj zTm0|Cyk`+9=s)F)`1~Tu3mWD4$p5%wYC`>^GW!$WI@wx>|EtPKWL#-2<|%}uhjgP) zXIKbRZ(KG*LkHfWg*8OoMo~NOcNuR}bw9&@(X>dAj7lM;RSw%s{&Wn(maaZC|({5&hzIa^Uc-*iURnYm8A z6tWNe{acOE>`1CB5p&%S`O;Bs>$X@@Z%D2;l`CF{ZSh^)aOR|~-e*DVX6cqYT0hFB z&C-11r0>dFhf0Rkb$nw<+?Un|Dwf@redDoE3tWD^DkK#=zT{*na7${r`=nF3;`Wcx%KR71+r-KIKSyrp z)1#Tb(VGj>8=J6Yp%0^oI_+-KsRX0@Y-$bJe)?g!-rPX9 zTRMu54STrcTxT-I@~u7DvrF#8N&O*2=!b!utiEN->PN!Y#V}G(pVCU>hIlr60%QZ=B{+ zM`Zuz^EJ>ePiuv0@s+BUh#%LJ#&StcEg-^tn~t6bK9;w?F@HJY#X5)(T!yxdEj8!HWRyMQnyDrwlkm8_Hyi$a@&M#ru7 znkpk_lYW!CUI)o~wQR0E;LIc1`BB{H>eqXSU#(+tU`#>*3+#_bD~il|EEo?EROJe? z;|Y~~;iC>1^_KFPwr=z9nYzglZQrfKS!wYGl#yQ)%>~GP7;0Bk?6pvXcr?Vqa|qW4 zc`twVgL-WZ_iDcaN#MqD+KSwntPbY@(^r~)-^An!h2CFH3i|uI)36_i8D7x3huX7K z&HFBD`(vT&A=7Rdv#4`MJImUen$;f77s1fvytW^!G~iCG_bi&Fn@rA{Lu0{9cbKwS z*R7+-pVCwl4VEJirR9V94TAG!iI?F~9$;8m+4pCw(f1XI`yNOLA_5h$`E zT_Wvn&&}=G@_rMnTq_~7m;Np%W>I0nY**_l6tq;JZJu}cbD;1o%}zUGHt1?boIed? zl7qtc7i%~^p5c^ED44PII|Z$rXxBz=t;)><6%)39L?MJ__(=Zy$y>aANm*V7$If%U zMo%6X31 zM;Q*EwWe4*GwD} zGei1h`V4k!TE)9HQ1aEvQ{E>Cmng`PVCqEi5GMmL zDjix)=%#GMC!l`3q*{Iz?f%}?&snAILumMSsO_OV-RLD12$y>YFti~KQ_ z-LI1}w%)6ta87m5bK+=0k4%zAZa!@83cT)Cp6*AC)K;TERsri3(?DE0MNQQ?Xvs2A z;%tiL26oEhz;frQmlRcIZ3=j`L-E;wrM79ZS!=f`b3bc}dDYLbNFm8)!)>s%Af3y< z?ce6e#?_6ur1C|aZp;!*JQw|Tdj)?;a5g6w%tdAtWnpC7Me?>WLbQhxgHIVMMr$S| z7;hSLoNZnV?gJMTdL#5aU6+S>6xi{nAkS%#d0au$%G)WV*BCBZXoG4G&^Ut1cX?w$ zja}u$)5{Z+p>z96LXS?>8khWCK_om~I|x%9d@6~Hy88*q+P`G%j^3ZX5xmnKE_xM( z?20UMq|)UzE5Q=6)*A^;*ns5|r^xDT{90Pc?oAh3US?M}3cJJroreBSv*ocsI;X$DghokcJHXp0#MS? zOchy`3w`qobt9K@n#?F5mZ>3>K4nA96PtT;!41n=eSw-WwLq7ml6oyVOg(|*vLHV9 zx))a$3Y=GjK|^qW|0qk59un54aJ8c;z!RrV-Ga%cD&Q0O+1eu;l0wF^^5nZ8bJB43 zN3symmwOfUn*;|e*NLHMNG;_y zY9l;7F1BpW(C6M>ZAgDB7ZuMi9$W=Vcd)ZmvODQ)XhI&!xstpyO4^f@({T;l5K-6i zHA8~GjuPAKXiy@xM+HXe5|Q02q_5H(knz&p$j_88F}lM{R9=dT1woXUIYpj?alfQJ z!LeJ0h4{IdtBBQykNSxZpNa~)>FzBy4XOnY9-_t6q&mo@Y2Kl$fsS-IQQ$y*{xK%Y z3odvf~mDkF$*nGHTGb;s`qs z6?l1o3d%<|6JtZQGxPP71!++#Zg0Fi>-g*lh1($G7=#-c4(=F+mUQg=T3@`SDx+W)|A0zA0~58`&U~_FrbH78j#xi5jG@_CY9)sduH{>s}B^1Cv!^){n5c_~vb7H$q{L20p;n6GyTsdmSXMBDM6m5NQmgR1CM zi*1z0duWx5M7A7ulZ=Uw6h^2l%vEMRWP|jnDt*-6kx9K2yEAgK<#LR&g0@6EEX3Z1 zs*%My`bg9%EaT3y<1LC@X!WknB6=ZaE6p3Ub+{-vKdQ|TZzsse3}(-G(tHKNR(R=g z*)6pEiH>hit6{qJtnX-VcHTrq3_%duIGDS~T3666pXg z0voPxG8I&Lw?rtKDz*!GaoHJ|64^G^eC z`1_sCag0hnF~I{a@mh!*sn8*G5kAGqoG>Vz1+kmmSFM*nxgHP=_4__|5^CV}!w84! zXd0|GGb^#wwN%@Z4tS&+>Eq##&E}#aAa{+o4zvlqeN;LR2>S}Bi~erGE-5J*wu3?j%D%Dg7`>!t zW;zWP+UVE0nU?#sq5WH=ZNzr!a)OOi%bj9RlAuqm69W(^J@k;uan~G7y{wB zGz5EtgPO5~1=+wUVg|95Q)*{NdvY`U>|&cxfg*y9HxlpGU!A7c%J)aJDun#f{xV;d zX5M@_uV`-&N{(QKXHE>OGbx5UM0?(Q!TuGyC8T{16C64|9Ydl={8|rf&rtz9Xemc~ zEQ`4RVK_xAz?(T7ufJXOi{nV3)p@mRKp$OaQGnZf`uM>-nEfA8{F?dag7XkVa)SEX zDE$lF2@&Dafv`5n&kVyhsmS6FN*$~2*(lwNAevWO(`mh+4ZaL%DTvH*!;x`<)#AKC z{Nqu5$L;GM{<4X0xF9^gP?|90XXL+TB|rTppb0rdNNfJOy8U;(GS%irj@<|(jCmA= zIDs4$;dt7F!sD(Wi3N6Mza>^wSSVEt$-4XH+o^;!B^5?7UinOu1PTR{b?s5e?f1Q? ze#0aXD(+x{uD2cg%kPa^LfE?qi+fH~hKUaFQ(NAX?)_?~FNr8UZ9bI}(fCeS31j=YI|6tl-~ znfgdOkx(4a5agmhAMxay9*7w(z#ZA?D_%30up3p4MARg0VIhGYMp-ArFW&MsM{r*D zA+S4&6g6;+AIX71F&K?R7HxTn*)T_N{)4Eug@>+4qP?Cw569v*&_Tx`yg zQa-fXrMO7(>XycE*B8v3$&EX4q}>%TO5FRZLJP^mQ^fEomMmb;bSV|iM{; zSq9;&ybIrus29Wx^05Qo?ku+Fzkz%tikxGEU8`olRHEgENo&`MOLd#ytO}`%MGOZs zB_u}R5S~MM{kjJ?Vv&sL1W)1lqn&*6UJGaTDY?g#r2Ey2VPT2gM^FvNcAtKxK$D)rCGT zNqCm2gvTDs=7@pdR=eCX{ceg^Bm0M=D3WSI7y%t6U$daGS`1y3q<6Pt9;Xe_J5tX` zQC^*O9XXmt(#d0myY4Zp9~^3bq$>JNeCz|$g6{RE#(l8m=^OM-TUbti3ObU)Kq=A& zNcT)UownOliDM^=azzI=?!DR>O@|J?FNr&qZx!@0H*T!A_yq?PHGVHIVaU)Bl-aVs z6o++@CA{)I17;re5)WmNK7@y*l1jECbTiE9k3n9)A+F71Bol=5tUQn{IoD^wB_3&)=?-(W=(r`L!4R+8`9eo6CwOTt>Z_Vs66_ zL$oo}(L-ADU$SI6E$mND?OC4_n8nh_8(QsRjAnCqsq=62$cV+>E6&)b8q z8gaj1Ts0Z<2Lvx~pzmkb7LXOr^)4OX0`?R8^C12^JKp#6i*xbWGF zUQO*%^o4b1re>z=BKO4D4E)>|;dD6K!`3d`+lt3P!xw|=pvDoK2`)WiB8d%~)0|;} zo%WI`%#%lz{^6SRWqWP|`(WzQvtr4z86m0)Lm@AFVx0H{0tO z629rzhvGN>q>pfLEB+pbGrIh_As8bjh_MDWc9vVVHDPqbdyXn}C$4D3-8-C#SE)QK ziyxD{l2c?Fqs%2{ALAZJ@S)!>FJQ5zj*~}Lp@Ua%O}i$qo#Y>;ZCxh2S_e~`SP3Ys zJv8>sOehfXU@-jn5Bx~K&VsC5RzI0xY}O1!zUn?OCNU63(z~8QNiNEj()2ncd`ouY zOS*i7PCDf)uRgZBlL%&2bY#R)kATIe{AGYr@{ z5=A)Lu53-0NU8WAu<>NO>ekl>jApy~v^3x}#L*u>j?T_1E{T}WpRu)jJsf_-yWfzy zpMr9fO;cyNVJ(_%%~a&rKO103R>B*@Q}m)IrkIY%s}Qzt9g;${uhMvYdTtVxm15RJ zhL7mw9AUHFbloggSYB^^M{H`UMI%B-%Do@d8?UP&ErG#vRGy#o7yU`fM#sYPp%)06$9<2BCmCqK{|U#HI+;g^iS#toq*utB4#@K(Us z-j)SyVsB*1;$iCmY~X-ELZTiHU}I}j7jh$0b4xp6%F~t(N^(mRVM+~d1vUi-NmC2U z*IrJh@4XaNjlHam`AsNAMG%EN1ONoKrY>M|4_g~MX8{jk%0GAofajNHR!Z_eATHLz zl$r`k9F!u6ya`iUxVSh7u(GXfaIv(vBY(jOHnMkh z5vHUBzLWo*K3fL`g@2&8bN(9_0DiD~fE`%bS=d-@ZCU@hhqH^c8-V0*1pQxoII9Bt zT&yal&i1ZO#-`G4rgkn=|BS-K_#gcpT%BzGOvl8S)zrq+765eyMrHq(A!X$hl>X7< zg$3r8whn)K0nGjvNEb`9|6$g@(Dw4>&vgEo5TN@%@cs+*-{<}Z7=Thx5RkGrc6}jF zPD+^aWqbh>dt*xzfj^J@#=IQtU>*}@9)5myW-c}^E@rTa86PtTj}e%Y-Pnwco6Gc{ zP|4XjyMXPCOem-s!US2+4 z@IRq==VS>;CD`Vlsd_ZVT4fF!=)WM^aH;QQ14WmyD( z$pDN6zsMa+7Xe8pQ?QG@ld8SFjWFd43i6kpf5e+y=&wb2ZRrd^c)m#d-(>#1 zspDU7f2n|t<)2UFmE_jb$w%VO~x z@ffjjn(#53fsKrrxp=vZ01lfOGjo`5g1LD(ILx?B{+h-=ushqExwwO!OvTNCnF6x` z1nAFf$m##E^3}i6;%;I3!Y4Kkc4l@CW)6N;HVy$!ZUJsKW;SjCHa1GuzfG9+MXUcl zVRpSAXN#3mg9*UVmGQ|A!+0sQ)|2f5hMavg^O> z`j0s99|8YYy8g?q|A+(s5%7Pd>;E%$A^uOoV`>LPLGD00qv(bA2&6)=MsH-LfO`?> z8Hz!Z0eC`ic&+6O0wH0&{D%OgrsD&Ra4vER(r`bKN#LkBGEbfAK_GIFoRqk#$I{V? zyC&8R6zmx<0ys=qkDQ)92nid^1#u$4=rm&0*;iIEt zu(dT@pqSF`y+jVWQT2jNyMAT3yjmzj0j8Royv2;wiRT~AH9tarUYNs;i^E)4UY7JI z*eR)oh76==TwH_#xo9&3rxCFc31%2@;vxTlTdf2R_xHn&vDj6)J6QZ$qrr|`-`j?k zrK6)~WK>qxhm8%Z)0cX=W`-a?zczu2j7B0RCazpIsd}{_$k#cxN}8OEI5;$%J!|Eu z`e%uhhf#F_8pl{F92{JlX~atf0>wbGvUGfWd=eC&#nqKjGZY8%g8$4=TYnuh+IHh) z-;`LdstFw)+TjCV&uSM2jkHS9?9rO^pOJY_zKVtqkByOL>aUKn*r?HAMy~Jwv?VtA z3rEo+91EN*U8A>`IJwQ!xDGCSsKd==P;eerJmz04q2Mi-%jsQ&0Z3vlae#(|`0+!S z92=he^RP$lUnB?r_*g-|3% zb9b;BrFeK8F3wti_O$B+152A0P6xCIS^ep>HwViCOd1W16<((kL~zBzl!H!6s$Whi zhWR3_%1EfXC#0EG7|}X-4l!astV4KgS3*&L2pgnSZb2mxt=)mm(9;F4N!96yh^*rCnqhbMNNi9$O6ac^z_y79 zF=0E}wq-VG~A*IkmOj+s)0Te5%_!4{rkhF)KqXF_1&^ z)M<&=f`G$W1bA6wl^2_hrhJ{i_z(YPMxZ{&#^T4tDF`M=84iH9#_vKy)fd0&=2*-e zl8|JOV@7&V|1lVeo{Hb*!iZ@;(3Y>1kk*5^EE1yqe5u&&j_9Fb@nvWpZhIPHhbvGs z*#GmtMgAotv<{1li@f_pD9BtWy0d98`s0l) zGE}WP8e1+NnnjBO0F(RuQ4n-_w`#Ed2*9vOGHoai4^LHfwdEAAcH1*<0Bm?JtwOnx zW0Jq$Uz+Jz_5ri(D#4hH%>LHHQ(Jeg(mrIrSwFL`!uz53dzyZN+coOMAcKe0U(<1g z`rIbD1@$>To_FW**0pW^*<(krjzy>0hx-$Yj_Z4*snsqBCs>xhl-%^4?y zWA<=iD!!^;q-gJso6rBQo6gD#%aMeI1kKql1OcS?2`frTA!|yh^HmUZMjRAQX2iK@ z+a|Sl0qXiSkg@bB@X%@j5=2H;Ny|F&l?92C(&`B>A6ch&DPcY7 zY#O$i=}#{5BA6L?D}Dw2FWMx4FPl8}+E@%o9yPCqFD9tcG*FAzE-M`nwQh|_rFYn` zZKm}No(+EQ2L?X|YsV6nht0%r&wnGQ%>9H>&w%6f@$+Yia&^hdEqAE8TqRm;2`1d0 zzCIMxI7PEvNJ+fJrheX6Hr?78{WB^nQG_fc){PMncE76%5{Ai{N5V@=qQKGGYwVTN z;%aIzmS7QVC#|+IgxqDltu$<&Z)+-mVqG2*fgQC*DK>mt+s@9Qwhrr74jvmohI{Lp z(TCr05X+XU`WQlsXDwdjbEO}Q1R5HCqs8ZQFLdghQ(LZ<4+jjSD zapLp}MH%J%Ecj-&dBiF(+MOdZ!fvgqU|teUEN^F&w^`U?hETE*a^&8N-33E$dXF~L zD!D|tveJIRiooAP^+nL^wyI2T6M5J6-1za32b!OT_?0T1Ln8tYVI{(3pklRsjlrcd zNnJV{ojFwMh&oml3;78Vd-bR~QVqvVT@%u(jHN=in#E-yQa{deHjoez*^lounCF~; z>MZ3+>}Q1_W#6=?t3#qlM`KxnLVums{5fUB_(JneZBsERsRlhrP6VCS#{A_|?8Z44 zB{Z?@`FU%4PfFMdA_Uzr7T(LHpdbls>@R3Hq@=joRQMTX?tBOHyi+Cu;9a}HpHZ~T zuL1qco%07<^2CFq2ZdZ_tJC+~sB8OWW*F4+WEso8`)JC)qcxuel9}pcxuYr%VPA{^#?)I`!4j2K8fzu5fR$IuT09__ba&z zN}iqzT8VK9S9q3cFFJlLFb6I^gGR!F?TdSQ7}eBVSsEJZI8!P%1FTeq$+)G_6NeeJ zeY?Ih3=z}=B6>(}Hlo+4-qLpp(|kM@LbwYW7$&#+)#=I|Q&du-ZJSeEQeqdaBqt?R zSHP4stiWb9X-nEoxzyTpYb+V<2V&%ulIu&v&QPR_c(eP-%vz%Memi+ zDo7C45f;$&mFHF_=~v3iRev1+0l1cnAErMmn-;TtO9^S5fudq zLT)mKUwvMO+WN+#*PQ*nP_gbQ^LtWO_o@Fw;8<72=qFDP55vjLK99#M-o`AQq6$4p zie&j}!&RZAJ1W^&8}?mDW$TIU`}f(62Po<2h<3*^Y8u;XYM?>rM1tt%96Zf9?HEHT-d7F~ z0TL|1GI?Pw;TqANGM^O-B>{eO1A5$G-Ps(fun7a1bN*YUa-L`{IzAqaR`{H+89F>$ zr8q>1TEfpy1Z22ywt+9;Lci+y+qU)BLFwLXDW2EWL1@cqJKX!iw}J8n9CsvRV`B?d zV5p@A`|ya>HpjCG3Xqtg68evomGd?KXYjA>@3fUo)<5`=Nd%DH-0BzFtnofE>%g|@ z$D=-xoXt$X%kyoyPWWyT5x*9tK*T#Eu(qfbBo{9l2&{GI+(%+*viU=7JFViE6V%6C zl!R8qB+&r^VZYBmtCH0x?UH9_^-EbzEvJZ$jL`Ms6s|zIl!AH0d;t(dB)nLSC;RTT z^G+zV7m?De^ACaJBoINU!Q46)q80a4;NdcF}7@I5@ZkT>?js^=xr`VK1)syB)@n zbbhSI`>TNoa1RKCCVI&>mLVL?yXFDa@$`!k5$V@qdgbgvLQ+y}W%~oBBd3{IvC`(M z_bCiWN=n9PuL^v77L0bj+H#urE{k5ZSd}l;3)|1H{fmgNz+8o1xQ4zb3?&f;ttfX2 zoGCN7)N8MKsjyUTJeF`59%H4Kki|G*(&EK;w}j&X$zqym&P)ELtYy*x=f`xa4@guJG6U%#biPC8xX2{9yb~=tv%A?xmAi%_O zH=ZktUq3oR4wVQjdU`y6bYBy9E8uTSN`f{uEr^JX>^sqGairLV1R2g(=tUghg&r^0 z=KzA&;SYLvcyKtFd9@YMUN@>ikFD8ZC#3eSaEVe4@^W$rW9AvWDZ9tVu~SnV#tT-+ zk-Z3%iSQgL$ai;lgKY`XPf)PgMMdz4O^}7}vUpHSC=&4@Kc}S;g~j6s3WlLVfZ#(Z zu?>pBzc1oN*}>hu9#5fo*>F`piyTL*b)|E6n2}gt6})k~C^8Zg9WmqL6w!6}kCQSo zLKgz79o*gFKrSf9Q8aI!U_p&dO;qIMAkpVv7s>A^*)Fl%9mSQECvCl3V~Dw%$EuRQ zeC$n%+H*tH)lg&DR#ImmcXSI(>b?6^w?BL6lJK1&CfFNDSGmv9w!c2$HtC`Q`5rtp z>}u^tK0zpu35TS|o44{(fMJP>%3nzOXrcRcdVifMQ5PYwZ=sqBB8}IcXIWoM z>lH4GZiI9+E`@*q;rp+OeL2B!))}HFC*JFu2SFP8emL@`H2tgGxQQ6PAW%3eiG+uT zyU$Y}9z82#&$TTApUW9JD7&!{-*O;sW7)prC)ho-qeIke{0ZC9(Y{Bt^BFgk88u#9 zHBCpvD-?{~$$`CNAWc$!xYGf_t5P)p<_V;fpTH5~YN9pUxUck1U^`-M`HrSOrK27Eo@2%#+!J?2N z+uPfRgoSN3?Pl>_bGEE_czS|mbctJATiLv?3kScCHNk+RBMzo)o&+rGv_F2rmSpuH=x4i3biaz=P+%R=xgedt^V}ajj?2f?s-kvNG<#j|Mmw!GBu|=dGE;WAR{C*> zaia*@NJnR3aZ!>UTb!OlC~bR5R1$xBzZQ^_`6o-)iT&E55|wYX(Gd|vp@41&D;YLA z%v;qdsT10L{PgK#m4j7+e8Fq^x4qwEVsxHjm?^)NY0bYBELY^qHk!F5nq9g=5N>j8 zTdpUpX6RqN>iVjX=6Kc#fvd>bL&yR(=kQl?5=j4`@SyNkASG}i{v`MRt7iH4V&=c! z{}tkrgQ%NbQSWL20}l0r?1<*DpSpXL%#MDwbt#-zg+(7dMfzueqapm(h=vRH)?> zo0kVwZ>xot_}YZSzpHzV-M@?S0Sb6a z+jFM8l|6q50m6)g*5R!TRkA3u5bucdQ! zl@wHEY;IJ8q8ms86$50eafMlIVa%YtN#POvdeFM&lH-X55LV=>f1UJg+(v{^%oMPt zAa|{4^qXg)=#Msi11|IS_|j)8Y{g{`2@1`{v>bTnz`6>XPL282>j>lWWVU8*tFWoq zbA(jTt#$0DC9G#A-)U-ltqjK()J#M~3^M3@?VFB7L>uo>T5$(5E($q#dUEuYc%MI#^RmW=0>QI-waIq_ z2PY>Z02OQ*hdlUTlFNdNaADz#9g9#I5sSeXZ_0e0_evlm6B9ON;$Z#`19c-OPzxTJ z6Lv^=Y$)=CKVE{VW`}wUsn+6V8#|3CO#__1OmJM99mR2TbL+P(_=fmC%WsOW&GgW1 zdt2AA3v=bGng2EaQoSt{5JhfoVp5aw2mKuWoKsSQD0zY(BpwWFJU5bpvh=m3MX>$x zM3DI1o1S!j=aEmMS2OSNg-qbhMpHwb&BvYSY8?QV0SPkRySKTv+1}o+GK|o+T32C6 zel3~^=CN_{@ZhysZtvkcK3#)2IkBTXOdsU4bShly>Vly7G&JnEGs1tg(n4lEZ!e{$maK-TM2=4GB_{fV-Gr^# z^$<~1)L>zGQM_1n)5#A)F;gg1ujPiE-4e}3AfwN=v9S?2m+4N~>@N!KiWpKFjWlD$ z{p$kBLFf^Bvw_y|IWV}c9qtX4w3%7v09Cv~SbPI7Y1%EDk9*WnzEN>Y4bCupy0`0%VO zvZEs#WqtiXq^2f5A3lOo^-Ad+)urrjdaY*~A#TSiy8>x*l^iL4XNd!e8MgPKM#jd$ z8$BnTB$BW>Z$2A(czKACqXP~fx==Bzt71hiVy&5k0jRzNTFcjUswUOc6{c$ojBQFtScV8a?P=hEa zFy(W;X1YEWjkqmG0E$Yx22NJVn+?5GmhUJZ9+uVj!26 z4l<)VLE7cG(YVi%{8|1g#%-iu1BWFzdn9pFv0!0fHmBo7fS6jg#&lI*|Lppg#ASfr zmxpcY*2mTG*9yXOMdQQ^>>y52A3QyYAZC3gH$+6K!fde^5>7(z>!Y4h``(mt-kq^T zkH@;t8{2ypZe4`v>+t~~{}+g2+3B;ck@!(7s29|X=F8Bl2M?ps1YRXB!_pI9;s zxx3|bv^TTu_xZ+ed*kg0@K=azTcRJL8~QQC?AX%=etB~nwHX;S9;X=u_(Jq^HYqJF zL_ktEk>}0#B3|v!8+c4Q)dycm*K>08&d$qjCfoG{YfRhQMb56Sy0Qb=zwnrHhNw7Ai>gF}@i#u7Vyh=t!K7t31@+Ect+}H?2TaA`{_Vcw~6m3JF zY{B~~bOrt5G1SW*Dko3Z2zSA2B8gwFHU!Vk&Wc<+`ue4|?w*B%?RTFdxUJ_eD*5XK z3QTDR$A)Cw)Ope~G91T+Z}1^C{-n`_t-|J!oIn`~P#ZRK0YV~P8#b2ch!`o)Cgfy9 znskCjZDLtjSr-%(>0gOdX5i?Y=pt^IifwEm?mNdMPrYX79$>SJFt#5(-D*ZPgWntV zHyUw}d_hq8ab1h6u(#WQ=rcaebFUdX~ zhuz)1>VQ)BPiF>+LUVT5v575L5UF z9r`9!sbyr8GmChzq6)gxq=uFs=<4dS{hm(oxSgcSQDqn%I&ZiW&56xgb6txsFK5>G zb`_AKO#I$%E8i2o5|~2PYCJbHi)mm$_Hfz5`{m+igXY!Rl8%=OsYtrdifex?kuhdH z69W9%0IR64#v!|*lhDHAM(n)4O#I1)$8%4-{cW4hmeA3USMUb@{L9<+632K1sC#Rb ztWbD$UfOlAjlVP_!9C%|dlNYxyT=U_*of5@=SDt{SM&Jp^Ll&hr}6I#-);Op-2u|X z`CC$_u(!05Dk_*^sBJye4t>47hVN7;DSuzG7jOKs-U_G7N{`9z6w_^WL5Rj>mby+( z6F?KWC4UK_0loY2L-*mV=Z5|jOR=jTkgmwYw_^bkSEN!}?L2^5rdtgOny6RM5xSc( zaoL+7^=$GS`AGrsTs&0paV>tJ`g!p8}-Q_Ew_Azlja6|KzG~L02LJ# zR8CG#UB$qJw2L)-d0mdN<-VE1Hyc}949p*Q+7^4WJtm&=2g*gN48-qvNtW8o;~lof zkC*B~3k$S{6`+nR=mQQ-<%M7o457M zsf~?c`aJE+IygJGoivjyHAoHwGz)&0r^fujeLZ$)R~nl|c0w%Nec6eDcs@CDbAVG{ z;(Z=!K3Q*@Mk`ts90Ym3Dri5;XruQ0wz5rN#i+9*Q|-B2x?_)G4^J36I4p*%Y2y3n zFel3)@CsN|i(gBU;qhOXo{yp{EBqf~ioH7)mzTFL-kAePQhY4qiR0wrg`Ff#?aD9C z_6sws@atU!NVc6k%N3j>wW$Kd0)T1_o6{wIK1t={BnH+=T0md4|3D0ZJw>B4o0qKA z7yt0r=@d!B)&6Vxx3{;s#shI6WZt>%?(Qn{and1UY_z|h1sG&tcuBS*r6^l}4OtJ4 zwgv1@8+1?3sJ1@*Vgz=!#CO-n8jbgqe6AO5e9oS{7aHuz7;uKPccB7gO8bVA8PD8w ziE&wVBY-j#k?k`6ee=_4({6&}CiK(I(X+$R0(%T0H{o-+E(}1m+`G3ym6fb!t=v%2 zc+CAX#qTHECA~?BXUp{42<0LpUBk*#bE2Uv(N~1jOE*-CRbLBc#tlZS(q8oRv}{QA z%Xu`mq;Vh0%dvCO$SW#JOP%WX-;t7%TC7!&I9>c=(tpSt9|}{|Hc9t8Su8fg`=rKz zv%{(xa=h%G-6|25us-(Xsrwn7(5w8NQaI`{I~xySiyIyHUQPS&YaKHMP^AD6mI5hi zSnfAWma#FwE8EP~4)yiHRCWlgY#!d62nJkUVkPjsVRIQYyuH8w!gK>z*Gs&oa4j-_ z^~#&nT60z)Fq4ux&D>k2n*x5}-$ts_Km)i+p4@wxT=&XMv%||%ywKU_a!$o~QtoaW z1E|jCtF*J5Dbq%uI}V`Qa<;vN#cs9ju;rBaIwYL*OMrd*?~Ufu$Cf71uD-rSeAG36 z_pn8Q8j&Ytj+7BT-?~?;f}E>Wx2+YN=3_?V?NAekE_-XNL)#u8mCDkJeYk5~H5( zNXpZbzu5($t8>8us8A%iKHZF9A1ze3bmh@%9}3mFj8*D2Kp6N5Fk>$(4`!sqT}2BJoeqw2BiB+ff9wW!Te}qmB~d=V zr5ylL^N7euX`s%Uo0sPZ6r8YeaKveo2n>jbi6QOnS<5urF@b8vT)9s8O9hyZ5C7*+ z9KeD|dT8>Y67vPv>NG%t7;xmHFCf-CpB@2f;E|C-lB6KZ)sfz@zQe}G?G)`K>v+0n z1g)=kL49#}e&ln#M+O;+Jwx1Hr`anhE63H=a;1y7BKrQ8p}3J?LHl5}GoFP8!cD`{ zPfp4Rrg`(p@Zt76fv3uV8-qKz69)g@F$J!IjY+3{sLbt63hA&MkIi!y~dOT>H&iY%Ql@<(ClNMGM?z&B~qDQ$0Xn5aAgNzz}uw&k3f4E z3&am=em7J@j0^`pm2aN)z{osEco1toSNyqfmz-!kYtJG6p9oX$n6)41{GQHrY9?lL z`d4~e24dNl$F4&%Zf~c@W2aM6cF&)}$$I7o227rBq7U9zeydo`8d5PJ1-*oFQPI%~ zJFW-_GL4~d_Vzz&VK_ybc^U^k&-X?Y4#mFi*Z1H!ok78=KtgqgD(P!Cj7uQ6<=t)+G>#a`Lng7AD|6JMn-36 zRPouh`PeBbDH`>(0Wx{wc6KcHm&d`at-6<|WU;N$o`5^s*x5k^^mjMYpVX`EWN3|^ zXnPm$3{*_x;_2y`XIOeQ2WVJW zu077{8n)X2_0qo5%5gS=tIFoGBVrRZBK~oe^_N5nvmVs57jNKm$NY5f8@R7nQ!T#M zp16=%RWo+e>~Nk%JDtWmkOspND--;aQ9aGaa$vxo7fBbBjxGu5*U83CPK_6erfUmk z(pyLkF|lbLF(}kNrN;& zcXxM#ba%ry*?Yg=pEJh!d&WRyz*?+l&1c?m#XW)PkZvC6F3}NOIoL2@hJ1R;6M0#b z>hS81=45QX!XJWNQRm%ryoRUMZi-54<)lr22L!+1;NV%a=k7JS1QrV9V%_OOAw*)< zk^M7vGHaDH9v(Ng@%>kWPpK(CnmkBtRz`HPbB*3U2)zOxDBxa^O4~f1oZyOyjakXW zN*msywGruzX>r)kTRj?!FV$P!IPhy1MJ9kzuD|prFemTql%c|OeyrW1eO2e-cBQ+# z)Cd@$?lXpl@7&!Xt<4f~s>#isi>^Gp2Jj&It@a^U8V6P_PRpLb(tHn??fyvZeh4_n z?M}-u07;5xj2b`lgb2)ww@RAlI{vH5V!mZ@ zagdfHM}Z*WYoXG*bLeIuubX{9aCx~3KUtwt@ZX>Ng#s@UOz#*%sUkxObM~DZnY;36L5jX_IKGWjqjpC{b=2e;* z3Z{e;*|!aeFWbxphwks)=`KTWbqmck)kD|ja>so_`Q1~>dG6I zoZa!iFQM$GRfNjl1Kt8Qy4f9o#qfTv}ZwE3fy<;06|Sf4x9D%hdRM4WbR zTv+VjAl z?!N4rZoj7pNOenbOPNLkiAPAv`Jdp;rY%;q>@xRY>4RP}-&7K4h=~Q^essl*iYoe; zAE$_*P8|bp*A(v~7EQ6570&1Vl|pp4R6)Hd83piqzWxsF@ug0m$N8z{U7b2BS@!I=h zOZ{tVCN^hu44H`e!RMWF&mfGCl=2Zb=jp4ZlivjetVvsYd-E+8RI9tDTx02R)yjo? zZff6t6(}r~`H0ZRO>;FjWgMES-T%`5KsI5{?A&--sGzhIRn|CHeB!F_FoCS3dVOD1 zRD>ENge@4CGh95rgMV&qZI%{rqE`K$$%H`!u^xtr2?iByv_BjBggQeekX;Lc2Zv0| ze7OT?=Iiz0=E12#z7b?uI~?})Le)5n_eN}@15p85O<6fZd|}q8@o`T_FBKJSg{zmr zR{T>F@nSnFU@nY?CW;w){T9@(ZxZ|~K)1(e^(av8!0iNIhKp@W+Yp|Vlb((Wih*IJ zN7_KD-J+)fyI`1KWWIoaH>ioGQw1YaQ&Z-s2!c0D_oKySWp*Jj+UoozQ#S4@*Y|+w zl=ZmNUVelz?59P_j*4?CU0SXEJ=6|zEognv0AuI->Fp=L)z(1T8V$plQG+`H8-m>* zTU;l{=6Zj9#slU5>jxGV7Sb)PkiDHtO}${&WZTdXGQ1x&aJX*UyOzI*%&XdqA~c_E zfQ39+xM22A<|~&+1X?m>RIJL`Bm|)!_LWm2=m|&gG}ReulR-BIBcp`}_L?{&m$=f&qg`k{n!ID>*o6 z>`70}M!#CRyXW2cNq7{FmYt3~Pzcg89Cl6(*6%@Rmima|#vu_hkNs6~z+uo}b9tN+ z4Ck?o8HSLqXLqXh>@e_{oqm#UIfgpo_D5t^bArI|HCGO|tFSDyaEF1~2_%6w(KPok zQUnh);Qt!ro38uVU+QqCx-ULsJ|-O&m>8!~@A!_K9QLT`iXPNxIQRQr$`Z7B?a?+r z+GN+B-rnCI&Cz7fv@h`KK?%ze9j9IT*!-tTrzARBeuT2jiKtlOqZxY6q-p7GvxD=R z&3HiXkZ8UgQ7axz>$xew3%1C+m!A}{ZaO}Qt-QAZ;X zeG!>?0whRV0r{CQ>HFeSTbKqF{fF8dxS>A9C!LWN+-Mg-^j%v#N`Lt>6O>Yq9+{@~ zy{wEG7@Xg}Z6S$7Yh-etA-X=?d+Ppr&c*YBLzAuvoNbI)0ymUeq7+ZSq-?F|4 z7hp#a+}hm2(RNx(ef6}&=IKe{Q5!}g&F%tadv(khEw$E*Epk!us!}zya*us2GJu#d zfdpVB$kQXyeAN*nUqJpQ-%CWvpGrll<11%Ns#`kYhdS4LSFjw;+l*{hv;Kf9NC#mB z?FHrYs_VIt*uPRP7B-u&LgKr*7F^HE1sg2>^gOy}us%>SY5hhyEiYlznDyFeNAAAf z{sV#!Frn}69Y_AAd8v(e)4mkTHTBLFs)pxp}$I}BeL`Zc_Ma(vvOtE14D97tVU%rUqgk;W;R{z|Yx#M|3hGqR zGGGCiJ&5A~Lk9Q~bf++47m4NN-105$rDFbg9#beN(5_FbAmmP(GVMhV4~SS6g!kaH zBSb~ZOa6LK>N?4>B%ic@Hmp^GTRI9ekear+v0-w#z*K%_GD^Y$;mdDr9-rINQCQ{+ z+@0@s{!D@Tdf?U@+JCNicX)G;WOCZP8OC3g;U9l&-K?)XeA1qvuXd zl{FH5*u_zt{17AFaI(owMMc%{!OxM8hJa+~_N5~AB$Ach#-EQAD87X#wd!HjYfI%b z*}F>D_rb+B*Vt?p1^pluob*zrO>;4)kppzU?0(md1o_po_wr9-f3$oey>;(~ZNteF zH+DcdOjKm8>LP|l1tW8;In34%b1XJ|Ob2T>B|8ZZoc$-OCk z)&AJRd8Ug59P4*iw~``fX9&mOJ?h@{5ge&6)L&J?;Vb`Ept$P;*;@ZNJ~)nk{dD7= zqM7MoSp$5$l~;_Jy*fE8a0-i6EqCy4>vj^e#WH|{0C0D~4}!b!>QL4koSoO!#wYernLmF3Nq;*f3iP7hnAK`f%+sS_Tf2!Ee44JGu2Waz63x2 zGS{7zUw}jXhlgrYYHI2(iQ)z?J`Ykx!1tVQ6Nj-W6RT^;z7yQMIRk5qI#oDtTIFuookVqCh`t#>^$i#dhp#;?{$$r{Oa&kX#v|NdR zL5UO;U0IoLfqub{dCJFRVCl=)K2LmaC1gkds-t&eIA#sd=$n_0n~6sR!~1dURIKgi zkIm+ZpiM+f`W1zk-sHlM8tt5UxF2W&k{yrW1~L zBEmZV(c&sSg{Z$iR{7yWFD+`Op|9k#$vrV+tPEY>$Y_1V3kDcWh)79Y)gGK?W{#W8%n;O|P%#LC zMJf4y0Q;i~hfuZr%8$TpznS=LL#?+KbJwencSq}yqfqOI_`xkLVUmy%_(HoHWIX2A zi*+Xwd6j9y3&RtM3W|#VaCQ%K*U$cxXQKy-(GaVqF@m4K{bM&t;O;aE3FP#R=k1Nr zGiC+c_+XXGQR6z(d-@>`3xFhV5U|tLsx4`cu?^Qcg1Ypepc)z*nM@~)I~s`s7@BW? zv5L z>H_Kjs@gTPRe{@4BLUHUF%gPJw|)+-S%-&{vJqNPP=IW`m@Ge4z%*6J=7c%sk8V+_-f~u;j=QgLf z=@A*Us@T&fr>85qMhL(`=E9)jxe9?{G0DBO)V};l?nYWk1j*iGr zZD^I+7!(WPcZW$(fMS~XiFyBcM*{VIWd+sQ%}uBC^x240YPrZ2g2#>B+SDeO1BM_(Rz@-eftw15sQUe}bik0|3;7O7 z*^^9QLxPF`rZ$21rY2s%ZTvY$E@5Ci@1x<_?t7ErB?4Cz6O-;*%0e5)nVC;nN?CyZ zP-!56gL6|*qJDwv&umG5)IV2NZhO4AKq4tnl#)WHK>d-yJ`F7hV&<5(6+B#NeE^r$QIt|YQf?&e&hJEz z(Bvmeg&EI#C*RT8=&?9*(bEys!{LH1_xmTT=tLB>vLGO?g+x(WzCX&AR9B0--oCl7 zHcYX(0o&^b2#qY@emk_Zthr0AA8FE1GiK!i@vJv{8Z)Aj$K-bG^@aoJ0lmE+puWF= zxqU~$h3|OjNJU2{EYK#Uub<57B57@Hv;cYXD5)+7P;A=f(wri;_?v+`G5P}Ddw&$4 zfBnt}8j4g_ zZda+JEM zw5^N+zy-hM;UVNI#D4RJ+h+T?@}0@uWss2lS5_g?7ujQ^_gBkY!7uvS+lhw1y5Xa~ z)}g_EZ`rlye??#B^@U0ZtQHzcGm&VNJR@kcYm&8~)YQ}viFsa|O%(_mZn}I)PG)r6 zPkFtI`La-Ip@9u`n ze^PsPJ$%p4CjcI}Qo}*6pUMhg!1Z->TCy(^0lQ%FxX$s)=Wi9;PJ!m;$M<%_E9!<6 z*bI*tAQgoG!G0jE8I==<9=D&5iV<~r@Bxi90~H3Yvu(MVmrM#>fttpK=int9s1x&S z7RUSL@-LuXym-7eo`RbxvB9`J;y320y1m##2om!4ZWAz{EkgoSapkKe*(?!K)(RSX zRU&%zp4Lsec^SZl6rbI=cH0aSuW~ri1LLu9>ryK*kae6>-}nhMoR0;6t1{>GM<#;C z!NGa`wk6SF&-xu@b!#`4tb_tkEC7W`3cRS}sUEM6n(yev#l>ah)Sq3xTWM}X`@ceR znu;vus)Rp(Zt7gN(SG_ILhM25dcOZAR3vmfSGs&f&3HSJA3_Y~1AMZwFdo$!@$;37 z{j;*(*ZKRCGLu51MWTT+&~|;Y&ICwtZ2VD4GSlgd^?<2`6`%=a{~`vh8p}Ue1~37# z->5qK6!UGat(ip-NnV-Aq5)N@SUnx-ldUZ^H4Tl;ldqf2=DEs!xjkM~back}j?GQk z217_mi6sDLt$+?3t&$`F%sXQ9kk)r1u&GuB=oP4AR4{4*?nvf{^eQQlaX;yt=CC1c zcMh;_`R-|LZ{M-|G)4MO2Tnk+zHPi8W@`wK{;OyhIIxpI?fzs7eSaB(y1Kf!a zZZw?GSPkO1eR2}3nNB?f!~k%lf`hdTWE7|)epcXk+zM&8dJ6+QXyPtee`!(bbmR%{ zA69o*j?RAkXidD+8}ML27>hnVK8*a92Y^QIDhdE}aio;oSf(r;i$=qN9gwZ$EykId&qWIP?NzlEBm1 zvf94cKBc5Y9SPnBPSMLy*k(ErxiL+u7;*j7{*Ez-GOnPejLch7*DL?v;Fpl62ZqyP zR=t$-YrW@m6GbioCIxiPw?~OuQ@HU2oi5g4p;DdKn6k5f=}zu`OIr9GFjd(Wn_b zZZ!0{Q0e_2D-w`u-hRBmU07H|19lqQT0|f`A$gP?;``k9-^^5UqY-gch<-hX`m5O^ zIOK=$JV5|TwTz~0Sby9Z7;g1WD`udk)(4aSSO(+=;G&wOu{mVR^>O-dv7C zK+XUzE7Ox%zUPpRijupp{7VA10+c}Hsz6b8c7^8F*+tm8?E3&gdS&g-Ka(@fM^Mn* zuhJ#e_>;Ng-TG~nbR~=%MMOq=_4IrZ5)mQ&@ZrtI#s)5%I|p#+N2H~pXpv|EcQ`s=ZOF;VYXJFY zvol7Hi7h?~eDplmD}pms7TiNdhNK`%d3kw#nQ0<|lF`%*doc<#l5fO7$eA2cQK7fs zMW>*mf;SeHlL2}1p9?xeyCQ+F2XQfuZ={a{+v!iWU*;6PowGsdBAV zTM8QFpl@Jdaiqm4?m=N8BO?Q2NA7d}q(Ii_ z3NU_GUWV71E;qpdNd6swLlXk!5A&@8bFa<>*NMMO1IT>ZO8`5;Rm8p_qSG zBMi_)%obCDGY>xhV)^vq1eonIW?i8pp&(D?1GtaST(|9D>ZNcV9mHF@0yU^1s=zId z&+V@~U8*O#?Z5?6AIlQ?LcJ3SX!;kAAJuAi`3t_4!Z*|16Lpg3Y=f;$Ogx=<>+IsH zeRoN8y?<6rJ4K&E#LgOdV4L&mBk){;LOeD${sL-iD778OuBnS(B2H(q4rvCxdD0rE zUXlPbr8?lU*CqWN_SkT(C=l^@aC3l~Q96bi!Dc!4Y`+1>ad1gcMq8AFi$i<;*PzUA z1@Q3&_#zB9Z(P%cr@6xr;1Nna+eP#S*TF>jx{Kolg3C^sK^K00K>@9^t1E8Ya*vJh z1UfLe-=D8b8!tEUf{6*_7;!&Nt%1+Llz%)bO0w#Qqvf08)7UH7+v*dbJrrlhXwats z;CC->2`y*M(_42B51W-1Pi#koxajETAv1sVckF7vWT+Ug>W`i!m7c)Y*w~|z_VP)X z)G^}a3}{{>ry60tMD@ol4;ZLelQ`Yu=10`n*eeeTX%r^~#oscj>kgcpI4gVW_6#q7pS2ZCV9C1ytg=_SQNqu=st2oZOhMDi}BPG)F!-on*dyy=Tv*KG5$I z06csPMX*I6J!)?iEmk%)m87HI+`t0Mo>zSm0q|bDfFk6#e64O8`YMGRHbePH6W~{v z1$7N5s5P$C-1m`RR{s8d-GWwb*kn~Ukgpn8`;3Z!6J~c`(6RBK-r{1t)f#>$bZfTK zLQ_ptS??y4P+5phcp;?v>#v+K0dQ@?#zhMshk@}2=+PgWgI#mPR;>^=)y#=&Jm%TV zmksCC@7w$kBCy454i`AF-D%!vaB^0nB(j2*02xDiA`wPe5G2hY0486xwx)~%N8&5w z5HR9{Fi0P7Hnw;14YZ6ryu5(UAUK3*^MnyebOSxK@U-b18jOX(f?)-{#wi8{hHe!8 zN5m&&B2?@tq+vc5*nFkJ&fltYy%NdEpv@YO0E0Pu?B+rl3P0|;mdEusXi;ASS9zkn z7W_--`q+8?+< zH}!kms5Ddcsj+LHzZ_%V^!3=@cbXR!;w}#aa9}^K?(O-Ej1;{_Miv1T9TO)GoVtSa zqcd=|Jt8SCpir$EK&ux{;RI@1mmRw8cYs7{`4N*Z8LK$?S_&!z$ANv=B-n7Yg;OnhXctV?PADLSRZX_}_wPuql~u6^=aq*Ae{(sIYJu0n zx_(jL&lH7p@okLEY+=qeAalrN;1blnlkHE zRz_w)ULJ1#q_~VVDt2(r8hom1Aq82--RNtT+1c}>Wt<#2m(|__@{sl5P?~r6@ZsI< zYn{O~w-r+z%gbqC`XTJ$?y6k36W)a9oo|iM&kKice`Gub8`8Y--PdoBa`LwCi6Ygi zjHPnJh(=OfQLWayLi33#2TUti0{}tm4i5Ph6`1vlQs0cJuD;eMJqu)x z^+C(`aQKypfWhe7mVICQc+13d+tUuFE85NO#DaP;v0|(rW|(jhU0LywKtFgTe)uQ6 zJ2-e<0!#UoPij)v^7m2WpH?0=la%Vg*!0=phE%5*85!9f@m?{m`=HS8%F+wGerKAy zq`7Ka&%5BbM+dxm+ST*3m2OtTK$(vp#0D^^HBa`vEY(|f_HbB!`T|?c;Lf&73vTCY zttU}cRs3a7?s}!WD$|Q207*guh~1%L#Ki#rVq>$H-+-=N`VE)Qo+=}wl_SLx9RuUW zVW;fJ4w%ha^S7C10W05dw}g0kxG36>J?L`mb!WqIkp1gdxyAfV@h2i~$K+Jr`m=#? zX><~j;lxTC&9efP^4Qh(faCChN5CeLadO5S8A7x+tS={LOZ6x*tP(y=8`U#gEqVWl zBrvnR?vVvGx7K0pWe5cZIeDk~e3ef}`R!RU9V6rSg$5RsGGyd86j#v1<`3-+upvZl zMAAHuxWwVX4{*q3?wx;jx1Mxf=yio`22m2XAJ_t!zT=Ognd!xiqHyl?Xr&qsEjA0F z>({Q9r!^*+N{(7Q@r6Yq5)(yqRujmqc8dFJJQpqy31`wO&Jn?}B&~%Ql*tbJH8;!B z&5Z8XGNkVbz`#@M;{)8cYI@}I+MlVst|N_Z%Ho6AVZ_`+w@68U79Q_i5Na$3jEOzY zwK#|zr6?%MO*eK`5AHg;#o#tvO@D?Xt zdBs8}H!bbsdb{-Bj3@zh@}UP}u7{@6{M`FV7-Am%U%BG#L9gDEmWlb`VlSB%*FIHh z=I5U;8PY|spknb;{QvR{vQ_l|%QK>^ z-~1o1@xNzOel!`=2V>Ccd$#|3-5T%8qY+{)t>*rw#g!FpE)6?LAG0IN#d=+4JTnb? z-y_HcoS$BdaG)qh*Vfld4Ed-r;69#>~a7qiWpP^O+Pr~6-2 zlEG`#fcDn%VZQFNjsES4-xzdiRex)Z(u9lI88?PL*dH$7!<@hupRZsGHf+EEoBJaA=~fFRqD=7)E{*jGala< zrNJ<66ny}6!r4T$^vMDHvh7jh)fm|yF_*R-+fw6EfmD}UlctATGcY|Ns-N`*>abyt zUbV`&6|lU$!3+&8qwl-%)%QC(IwF#Pt|>OztiRHP95`^+`2H8arUo~Il<BXjj@ACOi6>Z8mBbCq#%+t3X=b|LvJy#C}R*|_$*q!2X^G| zV{$A|22;!fo2O5Q%fr>HD$pVf_*fusc=lhdqnR~2f`3d_Ar9Qxr7!9}raOO>C zMRZUQFxDG^+5m9o&UigaFyzKBDoXeAV7`0wz3BF6mis)!e70?=(d`7~b<5v%pZ*O} zj_d}oz0d!4lR!YFNB~eyiXzq6x)fZEu$-J+r(4$Om!v5RM*I+5q>U$!Oa3fb5jxDZ zGGGtJcurRrqDqd~meomMxsrLac`>s0uDR$E3!- zjnlKU*=i>S68B@T>56$u$+qF;aM8yLDkU>Ky{@nfwdupjL!gxMf%$Bm&L3EDm50K@ zejF)MnvjQ&QRp<3Nfgm2FtIq>yKuMk#m^r7FT?a ziA=&2?Aj{^7wwu#MyG(x@s1v*Hb(}mZJyEQK&m8INNL^&RzNWR0&c|x>vp7u zvmx&IuY8L1fQ7W=a@_4`F)Jo#W&H`-#M2c)lnkZ((YO8pnp;ez>-&>MmiBwWscOnO})FBnh$!2&-0MMV-yrqNL*K6&F>!G+KEBi_r+r*W`v2Zp7Q2s~9cbjbh^Cm3J(>iuh9MjzBr2=B(v(=g<=oo*kFw7fh?zOZY@wXkT+EvfRWx12&v zK{ckTM|;mcbJ)Vv!wc(Ockn^)mV+YcoG?%{t<25aEKG8_@LvPMCK zZ+@)moyEan!^PHILSwm{!bK9cbj+$oqSn?LG|m*j)~G*Umwb}Uc$%hf-(0F$?V-8% zNJ#uda&w6zpsoSIpu=`daV4HM;dZnvwn;dX#1WVX?RS*WvD|x1#=U!)TvyCde`Y*4 z2#NK<$i*nXr1{E8$za;3l2ZKMWP919!2~(9dLVz2dGk2-`WJDYW8ES@W)egnT;zf& zQO;#O2+Od%5m$_3K{tm-4SW|<#J_R#69e=x*+jxrX#jm*%F^uFNVephzs zAVCOPy4EOMyIJYjF&^-%P``C_5t#ZzQd@X8ZrYplu{&8@Lgb2|$IOn7?a5lfk>%IG zOMHu`H_a0dP?(}l0vbxqB&?=y!aC7M1)3iGP?cl;6e$$mTaeR0)OwxD4SNH91@8Um z=dp?~-jn?PQUxWRWKUY{0J)dDveTVtrgv?eB@$h6vgMv73Rsu@LMbcT%;~^Kn9M=+ zy$T`qvk6_{mpXbOg@v!W${wmG4BOY6stoxwLn3NXZkup{5x;(lRQ+~ouB1Tz>Ka_Z z7tLr$K0@Y+oN=eL$_N|5aqfAe?T4C4d}q;V6=nYB1gFm3$I!T;Sb#(FbDo7^Ut6Na z1ofcKVCgHNF~d>F49f+=kIZ`1hzfZ=MOmxpLP3mNdF-hWK@6>|18*ba`V~B6N%zne zUpkzMq6iqX(Vtiv6P~PEOzYlpV)#5UWf9-zhTPDXL*5&qH%r=;ycF#XpaBVdW}((D z8_n1F^_#dVDwujm77Hvf%8Tx*h}nZz-Y5l4c@BmS_@7r!290SuUlNB>){nm~_U$iJ zh#q^AvYkij%3;y%k?t%URZh$$E2Hb3mg*#&B8(XfnX@c%Ok!JRyj)<9uHxqr6RF<& z@Z-S0&yw7=ot=t^ZOnC9Ttx=s>+G8f^?M3cJ7OrMW^42S-cMrDVR;3HZCCV^w*5Sq z5Zx50sTC?@$7VD;A+z(F-j1Rh=;iZvtZ|llO=*#80vr5$MgwB<%d02d0f|>{btc-u zFZT|&BsCe~eMvO`b)D|4$7(k2=cAMM8G@(Y}L2X|R+jTzR<(zq>87np zJfWVZWomM@T)Zc%T7#q5jPlmau6HKm=`^LGTJ1WmjS_b;QTwj6(Cap_#W5s_E= zdVQE9WU28D4FNuvNZt}XL8G|)5W`#RR8y7K4KAj!;IwqifmXP5QI>O{qv+vBdRCGt z7TiA|B5vHEKBr{xerp8VAel?8V%&U3E$;wZ-Ss__nUUu4t-2}EjYSdpd5bEP07_9t zi3p-i(KP@o2|vi z)g-MB_Vw2X5NBwQ&+wEYJYP>+nn%ez=`C>hq*Y`vcX%!TaJ=BPJwvEbRGk}w{Frgj zidcG}V0M+N*>*^c1zXRZIc#*l8bzi?gRtqwV4rVeShm-KJMgcUyh)i0@xdmqS6xB8 zVD;DToR3PhTA1@O@7ehRz}tsLe{9h?U%!s;e#3JKXMx@LDf*g3re;x*GR^ZHVd^pS z+?c!S(>ZhGJcP8d`{kJ1vXV(tMN@V3+?^w-BfW@LywXP9&?3tBY_r^`aT{FOB*XFB zIOWeT0xUhSa)+w>9Ds4|%`~t7m`={clP2lq)v%1pAXRcvf2z6SJ#PBdJCkGHcw4E= zDvfW=xet&#-$fMn{zJH?LVJm2zb?Dz>)Mwj*F-V35zj%BMbzv(sQ1PU-jwczn44*( z)oe;}7S$gZroASL;~7I{x1|uy0+$<`{Ew@w*JIB8(9f6tqPseRYlU9?y=ux0A$JH_ z^~I;eqI+NL<|awmaZ7zC{2h-1ed64QhHfSU;;oLrr~I0n8a5k-XMkx_t6oK;ej8;@ z>i7tsD>5?~^Eaz1Mswmo66&V#F3XyWaWl0;=eRo}Eu^l%cOO~Mq`^VfMKky6ef7F^ zCffk1`xP_Pz1(Hwl$ma)D|3Cw=bf_A-MDGly8TZ#Z((vm=O$|&;vKZms;tPNKEHv; z;7sT8Xxa=N&hcn<>E2af^#yvV(pHr-V@l!Gao8@@yM|YtBstDspS0$nTG*hWo;)lf*Cz4?<(HKT~Beu}p??6pMxsAUkzLdeeWAuDv;hwmDYrzSZUsctloI((t25JF$% zz&HQhg(Ot_vUgKHSa=Pi)KhzZzz}cEp)g*(8m&{sqbG-=hWQ{U-(6peea5qx*aCA{;U-t zvJ#0z7UGip(=+-F7rJyukrvHjm$T}P*y+2UmRkwY2Y(m!&ug*rAwr#W>aB3olkw(? zl_XQ?UFmYGNw%Apf|Zq+@|R2l8BCh})4!S`=RL_>R#;Ex&nZ`Cl-jOnyD9f($U`AX zTE;Q$Qv_wwBaW@*IPL~}tj*cHikGW(GtNaP5^a_rq!;c5-k$Z`K-7CBifeKdR&ABt zk#l2&s>ngv6UVRa_N0#F@^B;j-lwD*X&%$vIB)hTS-ks4w+0$aWvJUTAZo82uB(^3 zDz7uT45I1JaTQr0mwaCT{ghig1s3yaHLJCb8OlJ-JFKSOI}TPGE+Qj-_oa(iShiNe z*)YTYWkGq@O~((pt>M0<(lY3iXw5%8uqaK$jV@5~&(c4+qz24BsL)qp=T!P4FY|9c zwASri#>Pv0oElC3+SJXJe?SG@SCj63|- zdI2PpW{8in_qT@3)Ss}e{cgW74wa-^k$rW6l@tCRtI4|teuv*R zVsHvLd%yN* zuPz^AvHrXX$rJ_DKNUPC=nqe+IN zJ4pe@R6j909ZwRcBjUcA=+FNkLrKpTgR`C+b`#!nN4)vH;wVpOXINt&H}##ofb*C7 zQ7ek6yjHk?R}n{&$UNj%`$G4L*sQ2#KVKZ}PW}wR%S9W^rIYw8V=DgJj%o| zd1fg#hP^&-?LmP2LU!Zy`S?S*>HGXMhnIxGxt%|*PNWz7=2Yc!FPdj+a0FhKbYGA+wizH>$@e!>Nq<+Uk{ig7G)tZYjn}*-W5(n;4LoOq*Thow+Q?l7O>bAc zi!W$#(mxD#XURo#Tx)XdUFNK`6ZD$#hfFk8g9~^MTX-8id2#!r$&cv&n{15x}KVG#X~Ojv@-takH4SCU(eU0dwk}KE%`QAIXM46F8~id@2$6e zvCI4FCn1nr2no(O(CXuKkxT_#hx;C?>0`U(K!<~seV!6BW+|wgEbMx9LbX8O=15m) zn~=CmP`Yk(xpcv#bEgDKgqQr5&qpfwl8f0p<2XI+jd*ZQ092id> z8aP!|FGpd%~NXD)PcSf(q8?Q@_1Xsy-a##0-q|Z>6M)jP2F$} zo&jBv{-1&z4tMX;BxoC47%^gdr!45&RX2lD6s=K0%X0ns&@3FX3Z@O23lBWhU12-2xKU?1fpHd-$5x4B;p^}KWpGJ zsh)9Qk>yIsKCjPm|8^bHUZHYLh;L>Sb2hC2cD~q1sk1E?GUX%#bj%<~7S8x-AC1K{ z%5VI1dicDo`aIRSqNlB|AtHU1o8<_`TQtXI77PzruF$Fn-*((@xd)z1 z&z;H|Gr6jwI^MB5UQB@^!GxoyEQ-co6xhlji10Aqw59_Z=+&tm>OerfdmJDcvs+g7 z?YxlANxaHiC~LUeK7i(i~Vb z1qR@}zIAJkW9Nmj_%-UjUQBRWUI+z=J(ow!cz$LBK7n8q-E-1c6nZaKCG?Ox%}$y* z>Wd&f(MS7tYXdMaWV7hXM1cBfUro;|fl8_@=-WY}_=m0ErSbV3MQ3x-WojZ8$(n48 zI5N8~*qZBF@_n**^ zIfv03EY{{5k-b;&n>hTx@2*KxC`FkE`8%^tFdvftr!YY1-$WNkux@APZ|1B2CoBYt zzfq_Riplk7?yVMr;Z&UMduk^4 zwfX&qYIvCX*kLu4<5sP$T7ACZEbxZJ-TCLhSDIH@KOp>5{`4u(HXMulOKLrP#UwvL zd1`oij6C)A_~M*%6?YhdA@gO59ACfAf%-bXw*wRY--Wp~ohh+Kj~*aPWj(t~r0ohf z6X;jsBji?9Ws(lw*D>B^su_-U>)KjjW(nS|TEXGQdPq*a&LCHtc^ z|7>gk$!zC^-upMlhKO!R_T~PNA_5PkL!w(|m`$Zw~Q`BW%xM$a~s-*6D7ii=H~2$LhzQ z>)f0oy1P#HSkhM8NvX-zQ@CIwqI3Z}D>GMdxgI?nuK3jq-;9(;AV4W!e^*0t z_Fj~jJ}w~g{ri&H1wxK*zT-Qs8>b3&_!LFzMBK0drKzRbrM8ma#6~3ln-?;d2;41j zk#hsCuhol9Xp{_(JF+ZJPUxP_3T0aOAD6t3tzmZXur)moKIM=VTA1U z97vv*@(s>`KRaoNLN1Kc1khxK=56%~~PTBwMGVTRE4I2 zYsyeQ?c28_`Lvvzz4-&itgbOP*VoQ5vj>jF%;lYHikoVkWrx)CDioCDZZRJ%33n6? z8J&-`WMyRw=QesG-zy)KD!Z&8{u@NDX0xY=v2?|*sKNYIf0Xw4SfRnxL?{Wot$H^ zFrE1wpA8S12E4BJSJX6gbQjdYK|vre`>%-e+VoFfm5Hki<#s4cNDR)u@4mu zSzS=Fb=Z=~)1_s_|IuOu0)sa>A4rK1h1)|O&T6xj!BlIA`uMw$q65-5j5ioq#DU#8 ztNONlz3TYWmQ;tNE}ii{OD)~er&zP!WBe7f+aY$9C9liq-HL7f zU-?3xsyh6+6Vu|f3X^sdH5-QyH2p2w#$-tEiUPkiE_goP@M{{>J4*l7U1o0VlOp?C zJju4UHZ{HHxLl&6moju^BqZVrQSM~3*j2=C{-B8*k3TV+j>lWiw&B(LAj_%#H`h=m zD$#Ea7GLZAqpZ#~D{||4zUZnIGz6m$iX<7IJfZhDrh$Ie1y#$cZeRA2{qD>+KD_6x zn==sN_pOjwzdmodVCribGme&p{c1oGbQRKj4+agHdF}iYetw1Fc$Gf{(jmarb+-T#2mF&!)Ko76QbP8>DxDFm=Pvlq!-!ey1QW*^1ax5|DW})=fks>AEbuizOVa=<2=saK{DHv z>^J*s_lVRcz*rp@z|gJv*yj=xA~z_kFFduCU=;eJw!5(zUfhdQrvictp58= zbB$YzJLk;<4X3#rSJ)qkxN8l=Bmv+~I^!@(_1b?$DOuf}f4#e+dau%8^`#Pug0TwSUvm} z6N#hkWOHy3toG&QA{-PVgV0V0SFpAD_bxY&VB=k(B7w zTgu%IHdeda%qDU1@x?zmUl?Mgu3OFw*C=bZydlgOCHf-9*Gy*96qTrQlTPIu5c(JV z{1WN`%UZZt-}NPouu3+mR+~1@h=0hw7TfR(J$fOU^5p|!b+5LV{Tqb~#eC0f<+KM# zfDOlMG4o^&I3=36oAjj15*I=VH4B_MfuDTp5&{49$w23LBVj%IpSvC?b7$TYs` zi>s?hVNV-{bampVtCKl+nT`5h^fa+^@}km~ECQiFlru!+QKBL)YqtCN>akqp&TFcs zmoY8DP_c-@zVPPNh)#LQo*)C3kr8WCc0W{3sxECOvB*OBK+WQiCh{DXwN(O)ZmV?K zVrqbJf5w6X_$K7CuU3zoFFg9y<|oXaL_DElX9xaYCq+rX#6M%SPOLKRJgb_Q<(3V! z6j88X#rK38hKVW5%02^*)!&98AeUo6ThU3ejC50!U#o_`ls}IMrhkL@4E^1^Wv|rc z-@DdgR-tL1O#St*%eJOsA8=RKO!R7_G3%G8&}#9M$`r!N1W1{T$p-HyM-!F%C(h@A zh&7i@%yb~+h5v+!u;uY*EAa31bH;Ec$4l$XKgDC>xzpiUePWKDsKo1S1&PGYA14S3hEl0m2pR5;?L$K1k&Y1yz5vl&_Jn7z@ zcm3XpBi~cKqdeCu|LF12Wr=GU|f7qHlJv~m6?Of{O-X)C(Np0V1j`Naa|U{v}LKN=?c$xR697)P(?#WH<&8U z*qyB)^7i&d5=cHG-C6P6@CsQUtvO*w(sJNTkaRy*BuUk zN7<;vjQjNI-{zaTe9gw%c+>GxiiN@3SW7R9)B4(XUE=a+SXLJ4-Wr&oeM8`_P9?n!nVmtbFlqRniYK&tflodVjSX+n(N$;#wAfSc>REh%Ibe|6Npp*K!(+f~QsA zk-P*wwaZYvvs2xZLqjD|w0NVP7OuQ;jOzo2bq@2c7KJ8%$>na2I=!xvtWN=*+ghcU zxo=>KUPFFu8i$vuuE#bUklD7)oepMrfD0a4%iYb2(Cy7d)ajlR1DX4UEJEzAFsi$E zFx%=*2z2`_e$!u{T{90(VASM2Sq_07!UJx*8{m=+;LZ{du_~4Tpe5&y8w%E|0SA4^ z;(AgCE-9%J74vABsFOha(KG#`rk?^0ZqJB_di{c`PR9GJs?TE8k+?kheCo32B%lJ1 zR0yg-@(qL+mrR_(s_BfU&hdczfT8T){mV}MsTt>Fxw)9BGzV#Z3`;~3?yH1d0cXDp zK}T6V2YEe*OqR>%c(6$C!!Nrg)^zqS5(-sFq{SKVU!dcWRzU?N>gG`KfZOd8qE}S zVks-VjofyrK2)E$Jl*ea3&Oov_=S+HyR!Q9DH>h{t7c9G&8$JdM(e%2ysTE3&!}&7 zdriij`s44vY3StYHKg>1SJ3jjor2LL&v%l;IIn8 zzX4~ecbrT(H@QM$(y3fxRS?aD+ieNpdw!zb#0pF0II{x0)58haL67#!`yJ0U!Y}`K zj$f=)=CCWDO21LG8WsCZg(-wURSC95!75olGgZC>=Rd4YO?+G9!GXq%NyAkXnQi|?@>l(l#y#a$Zz2l~cA<%O5zplUTC1gElJi)&=%!A9E!0M!xWty*a zCmn*{&$NYSbbn#k(*5YD>bxnRWqk7YU#WyKUm)yQ_)`RKpveB;-;~8f%3*xY;t1|j z(m-c-!zLwvP3O$W&%88EgE3iXigkBS z?KytOAw&QB8)jvA5-Vt3*UMV<_wR@F`ZVRva1yg!u7!G4Rsc=ZT>D~#9pKy5C4zKa z;y?s^_gNlSjvxmW{IuFI*@o>*g`s@KXk~%A=1M7uR8_Z10IiOqJsS(hs8tJ&bV#68 z;`QtI>3TEM4pyVJ?7F%c^jf9S3EEyCK@U5l>J715oRXmB&NmFLg$YYo_0>MFZ2q{P zpP#~M93h9r6Yyp>R%8U;($FMq=1>!3qY6;sdU~?oEq>MPORl>ff6BVCJzq$7lvH(i z!W4q`%Ak8ktR zat^|o_X!b#KN-t(JS zJTJs?#3OJs)ns%&xY?`Wk$du#=bh(hNQ>K|mqe=!nTA%!@F+pG{AD+kH}JG}mPE z_2~_**Sx$ia}r#ungrmg|DdGA0sLxj86gdme1bRE7-XJ@0@_|D3~BC{+|Y(2e6o5t z_U*0b?rcqn6wwNk+u}Q7fv!lz!f2M0pzvF;ncNbS;^~fc$Tug>u-;3I0Y3ZleOM>B z!dQQItQy+^Dzxi+HT&xN`Z3gt|9e(JU;aL?FZ-Z^UbffC)Z^; z(c&DCU}M-hNwo%JrR9Rq?94ddA>8Y*bHZ{XECFmQg0~V>RkeDxyP4%<7A6bU){{E# zHw$84zP#q9$ol8bBF^ikfm@Zxz`&r`(Q+0U$AsB@0`AUwf&n7H?mJ8=<=2c+iqxx8 z!KU?O0A|IqmwL6v6!ug&`T5hSB$1!ELpwxb`hl*!X8o_bqjXWn2 zGV0~wKv~s~;=A_%+`+AHmC%*?HfS}*g_@on7mp;URW(?6?Gto7{gm2Tg@l?qi?`N|cz?f?2*E1)g)GbzH*f-EUXX(Ju%lLU6X{sum1(DlPl8i;J~TqoLX# z8X%&%Y2{lnl38+^L#$VM=ITe2+;F9%(F3|B*B)*D#paJju6b<9IRwJOALIEudI$w)0gg>r#lZuY>|NQCKp|_~4z(q^wG=Y?Q_XH-dR^guu+=!=>>HO9U4 z=UqdfMg#SmXYk!=UmxEh{sZ^7BH^oZ@Osf%3t+Zf=ucE!+f0v>cXod4<#i}DW)}8X z$}*}@UXooBS9q+DN38l7qu;&Cgovchp=H1HIpKOlkLGuLPDm17lv0FNW~T*XX5V_t zlAMlR4s}KA_r0rbha7G#la)_DqaJ4YbSV`MZQCo`w;BO}MHP&q1xz;@@3qs8KmF0h zi|{a+E~Nn0Z4dxx$Fx9^~3RP zG49kaz2TZcrV~%%M#9F|M6%$SQ`<)U>kO-^eAE?YyWVvL@f^*!06n@-Y7ryn-^&2E znXD`k|PIa7}+40x-&*9fBpL9ygqH5 zz;Dh0woZ(Ej*7I6x9ddnfcVi7PV!MfflV}mbglIjt2Gy~BBZG}-Md5|YTPwMzG=_1 zJkbt9pfErS8~X$@$gz^eB;xo6=n}`r$L~}I#4A%hFHM2h|2MN=bs{dK_pS!Pf#-A4 zfOzcRR95NAP@&)WFYMl|J$7w+if$?GxlrzVDoh~mfkc{>^pu3{=nq)ZLj9UsL#eD=-UM^P~V%eN5zt9B4`k8Qp4` z%)b8l82v??)l6H}f;)&MTsopkP1nBjEI@c*A>CZUsRRWhWCX9GBbS$h_a37lA5Arp zt;A`2*5nxMSa2@bJbVi_*;M0BRZ0%EI3kKw`q=# zLF}xnLzu&>_c}JWIvkrD6zlMK( z@ac!N?m5b~bN#_e684eH6$WC3O)S3i zDgCxiE2H+~H80n+rnD1&n(WjdkU1xB`XS7&Y5}V41!Tmi#{WC)IDU6AAL}BHOn#pSJn%0h4|@QdWjklr`i`UIe*jUF3rCSbDUWG zO6qh*b-e)*eBD7S?ejk`zU%C|kbW2rR z3p6%@x2%+`&~&&Q0-liM%+B!0xH$Dx>zL?8yKUN$F;jVN*VQLwM*S^&jwc75WP%4A zwzhUE<<{i)cKy>+dpY?AvZ>_A$lzw3^v@x&#Dbm$zv?wRu?>t2b*rWsw-XYO5r_iK zy6>?UA4c4{1%i4fE&>_3+#D88?i+B}KS^*$T&!8=#0q9wIe9q%o*?I; zj0I5qlbhXX_6fs-d43JvO|?pk>2Gqmi{Ui#V5SkPHR`+Y2Fa6W!KAs?;+yn6$97z$ zYGNHn29$G0f{6$!-7yvBoC2iinp2fz5!b}ZvNPD5V40a=*^UcuL?2UvYxnuy0B>TX zwod-bu64cggT;u^t);FdJv6m{YA?Wl_zDwc%*-Kc)fg~oL&>~wVNMoMYSy?^v1-rj zBhf#SHBryr29$X%JaDvFkloqqPZLbrjDLBbA8OPWzr=oXGAIa6Adr>VAYA5`p1)RlHQ}}Giu*o|H_OPtp*wiY<-Z%!TcWj|sP^s+V;vd?cw+Y~M zDn67-&vcj8-gI@;~A6ZD8KoUV5x4 z%OLXqbtN<`Z|5rI+tkff&p{AF(C5R$%Fd=~G5Tou!HM&iX;b4X z8GjA9@Y{X06H07&)|Sk5-{@W!Q}GdEgTTvwr=5W3hxISN>9VMIUw3LWdCf?X+3$B_ z=sk4_N=L5SaS#4&=U}sz&Xy-!q6MR_4P5HZ-`!3+EDF-Kwsv+?)w&;VLO(~ul1Yaz z#s4MkYm$>JtpP?_)gEm#_uB zSL|<|hlvR3MJ7znbA8b&BJmXhWZU^~TKwNiqH8W76JisEy+yVpxKtv{ph&-IFRoP3 zw+OS6QF@o1DaxsLjTMH5HW3wVvEC{ZZaW$M=X96!)8M|)tN`=(BU}!>GMBrd;Tj1f z`2(|#;{}$Nf!wLqLk3)P?E+aXSL z$lQyOe?CLm_s}6?P`fxBIU)HXNlS5Lux2cUO-4E(#VK+$R_0c$s#$+D1I|n{Dy8pI z9z6P(;ON9^#$V6c${k=ZiN6xu>+EVZ3z-lsxW1A z_Ti7>uWpbUZ)(%5Zb)$?ljDV45~5B?=8v=v>g#;Jx%0l-GDPzGPM9=j6oG2NfwPf9 zApZ47>RK=QbVGh=_ZkwflR~kHEU9?*7jevAc|BqZztOzINrY7zDxYLa=luRJ3tR0O8gvI9#ZjT5$CPo|l^CmAB`HrZ*-Bl^X;6H_TjS1P71`hB2}Ft) zH$K|$6N~Gl`|!KbhO3Z1|F7Sgi^Q2NwQkMpu|o~%+6L;T4S~Um${jDM)p8C5@o)%t z%KUZDpx?SpW=%35UQH;~pNK^h9vcR&f%% za)y?^^knp#@ActF>CCDM$cmQ&Q%!Z3kj>AP>X3qhvEf~ggBjIsIw+*wV8mvjfrjr| zhgQD>VquGj@8m6YaC;^HXIEr&v0}3JYT|4<+s);!A+_&1j|qWLqO4Dmmd#iRT(c>P zV)Xy#Ay_WgVdLtaG4I$KUSXtdOYnNC>HLz>tHFtKXuCe^!DXeGi7Wqk{YNg0lcRKf zuh<8Iz9)f$qgfJ9yl(B(mzN)XMJJZVVT}9U`N*8}1?%Ol2TkT*ZI)LQPO$Eoehh{F`D@%{|0M<*$IOE;DKu@;por5ANUgz6y4zs@Y1JE zH?g8B@jh+`(t!8THSZB~ZI|ani%9e2>AK?|4~n?+dt zs^+Z1H0j-i7Dz65rtJQTdd)Z6HRg4`K5b*VJ0}mams5R|Kc5_Kp3k!AaVzCt6}a`= zlKhJru$f3o@x*)N<&{LPtkKhWePW|hIP0qV9Jz^Uy-xFv3fVsLF*4C1=N2>J8Pe1q zBpEv_SeyzwK!dG;`@iR?&9rwJeKkY7(?)+?4Mur&W+7YeseJwg9VC}nFnTrizwG0Lq56z`6<_z@#lvUp zGhAxXpm~D!F9KoN;Kta^LH0RG>rLuL8mk{|^;m@n7G-2D-yVoc$T@#(D|U zf3N<8T>9DnUgUSN8jcuwpxwSo%wGyWt`HON@04+mxDgc4@n|3ou~EQ>oTef*Wgfz=nz09M@9+iM8ES8D$)d0V%`Ro72U zLbfL$pUht1#-7$6*`MK*TREy+;p{@HVcxrUE&3aQF@K7dOlujo)U0x_#1k9Jk;M4q z=9Qx#sf{TBCAnzNV=~#upPRcka4`w1m7-V5_xEr+|Eel0CT>OxxO4#QFxu#W3R6OZbA!BThsD-7Q`jQpP*s1?^+pMofiUS zq(BMd$P$;DmcDJv;+o!0eustdCQ#;!&c*-D)ji`!66aV&;g?uyfuc>)UKQ_`_(JhfOr7;jzuDVFyA1{)86QDB|T&AV!r(8 z_Ie{p^|Y6%dTyVm>TC}d!8z}aTh-eR?$coP%?o_|9znr`o(TqZ>LRB;fzzRn<>r&& z0Aj(R9W=7zf>=|&r-OX{{5e~3ijWgRj0SK8JZHF`7rNN5UcCaLeZk}(zyJ90<8P^9 zui9$OL*H)=F$3E{c9ow-2W{x3HkI{G|J;OhIjhn zYarf(&U(rUO;msCEVOykog_yX;@GYF__(y@W0IRHYddOI&4u{XIOJ>%&27*(GG6|fv-l#23r%QTv9K_j1q&XB6|El`|P3MW`? zVLJhZSrX>o6m^Bjdt({1?z|s>u}zQPOXew1*T3JZu6A~%DL=o`!W&Wmx5{H8$r!(q z%)#wed!0`6friA@_d%9aFWyOY3I|4k2$t>meW>YEQqu5woz-g$Mx+;{5kz)6ua}kz0ju;ZOrM9I zo*uKRS1Lk_UzUf2CrcCx_wbo@VdXhNO_cv!)o5Ib@(FA&DIwE=TBJ+SS?-^>@x^X`zb4%?B$7rRG?&q+_O|n zRwB6#%^zmM$a3*Y^qBqG)Hl#}5PWI8fpe$1QS~PyL-DQ-LVfcV(&X_DkTmPhs?e%6 z=3}z}S?y@0-i6_7)z^C*Wzjl3MLPTK>(}0Uu*%UYuR9(eIzIYjFzBOFQ>DKSO%qfr z74q0+GmvrH8l)7DgIR!OWYnWdRLSWXB&Zk}J*ugRNnzZNacxK3f(3D<7qfn)GCUM* z#-?+##Mnh>LW%?F_ZKq$yTrx4(mnQ!_Gp=HP(y0Bjz>4&u~@FcYclQq#|rmFo(b`Y zr^4l5EiZB!hro<|_(xqiWZ%dgR`_sEX{%$NYIHq#a6RN^$C zAh;>GDA&^ZHrz}T0FM=v6n_Gg%_oC*K|x}mc7CCDn+W^9GOhf}20Y7~XO}2*;^raY z;d;CB`l|H?%!3hbsh}co+*dX@k#Ko+xnresTaV!5UPq(t>2+EC*@-k2U-?su-wm-p znQ4r}k(D)$rj8`k+>8WDu0K*dyanP;&*mne+Jdn+jiJH8Jv8AHrR|mNu=D`-Rggy|w*6Xr2uI#dMHYp}0cI2Q> z%wzEq02@PHmeCq7c3Hn`c=4MOjdb<%w*j*IOZWcQ^C^4@%Gxge0v?R(J#^6Pk5{Xu zy-eBl^~oElHyA)|+=xxGf>@_zd<+;a`iM#?<-YMdfT3(!(m(-RmLnwkLeezD5|#U{ zj4uk-8*=iWAMB7+RaL>5S*aGVPwFKOuEmr8ytl8Cx9;RHb^N_#+e`UwZbXpM%WD?m z)Ngm~llFElv-u`pJMB7|T(Ba1p_K}q5KG-5(qm6!+0ak;-_7;qf;J5;?P{Is!qR#5)_8vQfxw++d7ve%Qm+b@z5&S^m@Fw&zdARLASEaU6ls*fXT&c;N4MG_Rb>`iEZS3IlHzaPuzYjanUqyk z6|;7DKe}^vx@CuUm%tl$e9Qtg@D>2Ns^0uH4@gG4j=U*6P8}B5I(v!iyRa%KP+34~ z`x4-jiPDf*uB?=(F*NSXWc~j0qtfOrV_ZmRC??n;(sT`GmzDyb+hv(S_W?+(18B6) zWeSN+kE3=kleFEguEp%MbwHn-s&FG{CU16tkXdhKX?V8d)w3R1_Vo5jUox}qBQ~~X zb8!mVVexRoaciMZZ#QM`a54T+U6NOs#Xojg8 z26FXVe$9rfUN7SbuRNupJd(!kfI?SX{W1O}*y$^g1h$V)Y(&foSZd8Tq#fB=)Mu8i z%o021`Rk_ZjGcV1*eYjrtI8U*;2*sik~k5!nhGjirCCi^w^~(3VFwH9RTdC?SdyBR zkr5>z)Q1WDIky{A2HQ-K6XC0h)^Eg$sHy2JXH4q9-yep%5FsfQYPgJDiL>n;h9=rr zu7FixVbkM{TE(x|Obc*ehROgaHl>O`R8DSYwQrRaT%o8NDK;z-fEqSjX3SIxnG?7E z`rb5&gWWkieNl%tzaBT|KJZUnbXG)I_#wcy0;)4R*RCUNzL^?mgSbzl;5+WhY-EfB z1pvToW|PuC<~^`pk>UiFXXw|jU;i4Xd3Jz>AW>YNsm1N#qkaP=r)*3NoR#f-=z1_+(P4@o4Gj(A<5ioTU(qiBmWz&!2AMIg zBN1^h(eQWV%M^Awdu*b8}n zE5Lz5qz<5?>EjS4lk&j3scFInX{TyLLHjR5R&DW4dncR335IP4icB;wvNW9$YjKGho(CTAQV{F@MPta4 z*ijz#e2tfrO;2!eHflCHZN$<9POH;VIp^))Mo~(=dH+68kxn@>Ik^Q-SxYQm=@}*o z2c~ax*LN%;kDWj(A{l%87dAGQ)rJ?=9FVESBtKx_WB>gw8(1vwMCx$A!6Q*(V%X!J zsMK1#0zs{9dS!^BIz>fQRsN(5Koe_SXGp5Ksf2+|&ATE?Vr5MSyhl*Nz_jkR6sP&m zwze#{x0DtfM2uDW-D`^}bBuybKssn(tp71Krm#>6Xs#oaMOgQR_XEk~u8#7=$p&VI zux4LWP*YIW)B6RqJ*)kf?0Ma#($dm@%qJoCdoy8ezkjdrZ7r?(;s`8$BjvvsO}n)p z36E;kKL@7KZTi74GRAN!#7g2u6CR9U=%ynoORnJ%vg1{<2RqaigYYzc>kdFQ%vS?7-@2!a#0iER*`Sx??pmJurXg z<%tU<@x%Z>>2cgf>gUmWA*C<%hTk;>+sg}AKb82Sj?PomQtbDZGvz=^>Put~k%2Xr{;a>1U{;P@S5jUr#d`e)(@M`#xUjvl@^d3u z_^Iii#Kbk}?)J2c%8<=V&zq4YH5B#}UBjSB6ZPqA^sC}GUw&_4} zReo55S|)>VY`Rzuv6wGSxa+%-DHCcXe)<<+C~ZadqKb>(-=0sXO9EqQU*8R21rJqe zYwuU3$ohxhQ%vwvQ zF$6_EjEYt902}KT^2UcI>$g9Uqs~1v#HV7A=zyNw z_FF89P=oqX0|+%;erPKI7)h1$Ie%+N(Rd_uCL@2M&p+MFfnm%{vm$T8fGDhueq0YW z{XA%As`f<>S`I6lZSMLc$3n+yA0UI5is4Vo@Sf%wgUYpx_L`Y;ZG|+sQuTS zj-jANWWL7D2TxkByRd0s^q@#ClN8zwJhB2bcSwRO^QfRU21aNK;GU*%>0TdQCwABvSW} z;IxS3BP29yb5)4s&VHhvmj^{70741LThU_UL4ozY6enVsjUMglNQ*9uGZ&KYaR}xUUx)hPqfJTg80ZvGZVP z$3YU&nT^DEJY;gIWy_4Dlpo_C;(7CkIX7#0BFIh4Mh<6P@K(#@+dp>~5R)`!Ix5Ji zHol&qeauZP@;_?{d}z<3DaDnq=)xbn*3S>8Nyz$o`65-FiX{BQf6_Gtdv?~{YA5zF zfS#c;{CCNIwbP}tkGAAz25Xmj#lv(|4HfaoJoqY_kL&BNMdC1Qc#!G;cXd}46_OC@ zj3{&iv0o|vC&OQ(Z!f`c?uwk4Z5*CgLMdp6w_kQz(`;>1|L+3I{}|f7#a|{)k9zZ; z0{?&XdA3qFI4O`77?8<7vHq6G_~+|fjCSh-A2U|Pn}pd2fPFSD`WyKC@RP!Mq`Sl> z_Jb)esgJzZR^=#g0^wveNLML9{RZ&Se{VEUzGv_JwQsNA ze;1xy8YyC3Wb2)Eki3k@<9|9xlQV#(TH~?0*LfNbwgQncF)kBvVTC>4nsuUmKYdx` zA;LPHsu8JiRznuoeL~tIj!6jBi*4cZ1-X(c0(W{m{{EjCDhC8{>Vm)_NC~P+g-kD< zJ2dq4Qez~}9|Ql3ZnCZj2>!?(NFk)JQlUqR?_U=oW7TcBC@baTBgLxf_3u~mhpqhl zOYzP+MT~T~08<&8k*d7evdYY{V{`Yq8~0Pz$guQA##_>bJ!KQ@A~|WT^tDG*?1?E& z+q(tlo3CJ>{wC$oZUqNq^F1h#%U<`*u2^4}wK)AsdOb9iZGSzguh+oSAo%3WL530bP-OJ(mE5nWGWSA{oL?ZLyYWr4UL9^EGw`MSvfV^j_Bt8R>+&H#b){1 zySw9Ec>r@Q$H!{S&aAGq39Vnj2CgBSsXai^{0VG$*M9ukuu8O9*PTL9yz2Qx&<48r zw1e-63p*flz!J>7D*)dLj%sD`oK~p{q|(p8j@0i6cXK?SDuu^^l7;qLS62@1iH2ef z_1aD3iB^Qf(v7_0f|k&YjY7bI*Bk1rp{>(REEG(X24YO%hm$qGd~HW7l#tBDGRD(X z31|pp6O$fhL6xVSMipJscuyZ&wm$Ry_UEXvG+qAv+)BWo^s3I!ynF?M{cug~{-BT9 zIS-3QlCJ}E2lf;6y8{E+bLKiO}t23_KuH^pIUB)+h<1W?MBJ` zOsGi{!=-wLPbxCWs41Pahk=F-&VlL5gQ*1?6?p@e!0Pzu_51f<=HF+3(A9n5kNmkW zp4k^{`@x}8Oi1Vft5M(LAKi~z<7LJng4t=^O*|i5e3kSw@;(3Z`~;&MP2*R){|dRx z=(E58^XRCpF)WQqI@Bxn&+1vv@}&EbxnV1R3P)b<92r*}KU!Sq@e?{pK3{WtB<(p7 z%H=~8ohh_9^9OTQ;*gsaO-{@Pt(~HsYNNGV=L2IOC7 z(frc?hqU?Qagn_4_Lxlf7a3?7h(Y)c3*ANiQT@U!WAC1l&wb-mxVLuj1jCacu#qNKQV`M%=5Oh!^~wNdN%QHqoq z|CkewXU7a>9#Lty`~Q?pj8YnV%!o^xI%I*V0I@fr@BGV~C>S%Yxh}^}AfuOEW-I^8 z{<>5D9SWx_vX!pDpS^PBJ81<{rAf8@JkKJP{(g8ZZHMc1jXd|}w}3~~w?zpm@(qn9 z{rw(OTe&Asb6uzvgQpXJg7&RKXw>?$?5@2$gjUvK$i7|zDNEd`Z4wqw-QVBN!+GFx zZSw$!mNz#sgukK|TPuef@xgeFBO;-1d+j3|uM-UwvorOFrEDGTLNuWRz>4L1f^rZ|4`HfdGG4$lbq~(eG)ZDLwoMHka%>)2_)Xjhr>7Uxqkl!SCCNB-P5xkm7Dg{ z?(nOxWG1Z%e#+G7+{=7Y|(i?ujyG%T#8 z8>fZ!=73HBrSaHFV6))^`PT*~v4vQvZyAfQ;Pb4(W6=uqv9uFKbAS7+Zo}pv_o~>= zp`abYFm8Fn__cl~Bd|tkudZ!ekqYX35QMyP#04O9@bSsGvUZu_PGu(T&ZL&dPx!)J z{7w;(u{s=(^pmh+CP70V8NS2jiFIt@&Pf2ke zN5}{m?o90U7qwb&uwKXNo>njNff6UE92l=pE|i*`sV%s=oozSoz5R~+>Xnd<7!3vi zqh52%=lbhOoBO`O5ZANCa~NbTjB`Qn?zYx+x~Dp)(MoG06myK|)YvR`$sjl{^p--*Iup z%R0@Ab%x)&RH9N+`p0t9enh3n8{a&5@PO}b8Dn>@ERJd0K_3$vTbQQ(8?qqldN&ms z21ZtSIi~mjEqPZunC}CnTP`w++nzdZu<0VX4{+{ZdhS>=*6p%@IvEItxxP8@$_6K9 zfE%|yVQ9U7DPSdsHeLpUN?c@QV$0!DRpgH!AQj8l&6Vdao&^~MY5=9fY0iTaoHVja z^Mcv)m441Nk}P<^K}XcCQP+>18r#K~cuC4wdaafM)w_aJf?pB z6oTw$;5t=`opfeQZ)Wm^jy|M*q;39%n9xfZ-_bmn+qsjaqW$x;!$zZD=+zjg&}|Ei z9p;ON;+7dE(PljBOPya0mmcQQGb_he}szE zihySS%K!;>R3{o#D>KUAq2ULdorD$h32YAve|GewFV-4I-&yVA(qFGN)t{Xk2!HcM z?1T);Dk!vEo)Og_bjOpSlw z;*h|D2QTzGT+BZ@VLcvttN&GeILq9aUP(O)=5b~D79^1|AueI6U}VgvT;l`tzVhu+ z#Nfro*kE9Au)*=~rV@)SbRd0BS20BaiN07b3y$duvN zOyNC>GfvZ+y9@(+S+JBhZ(i*$rN9Mr;6?l(a5k}*aS!KjK2&D0q>~iXms#op1 z_B;tJhUhr_r>}9Tr1WmD5!X(`zjzoLC$+sE$qOX50Ex2t?)K`w_HnPJ1%`#K9d)KH zj^?HnyPO!2x?bq+H^4~+fER5R!iid1dSNpkp;DkY>vV84>%1Z*iP+3c6!#Gt)R*Ct z*7bZa3L+|g4kqXzv9Pdo4G4TllejEh+(>I!;07rWAe9SL8o!819Ti&b%FC1(_8QH5 z9q^;zkoHZL$Q+;E@k;@nNm+yW$B|W|&*;`~@Ze4rD4n|U!{@vNLD&B)UZ?#x6zu*$ zT{&>#560__J6R*p)?p)b0j)4w0LRgEb4m0u01KoZ#52qA2?4q0qStQl=&TRg{r{_{ zT*A~r7ig;6K6h|1I>0;KxlJgazIl_mDVPqT?igZE-tT_OG-A) zH0^|-lPl-dfkC--^->x{K<^h3Y{I>)EsIWd&uT@pQ2Ndz)S9DH^G81!{nVl2N(^zr zVdN?AS)k*NnOWyM#_C0FVA>7vPC!?M@~TmyUV$gEawk{aFt33vB%>QN4z%$Yu442P$wwYll7{~c$7+{P zbV^#M!NoBVBK~l{ziE5Wd)Cway#GV|I=SS@AukFF4S}cHs3xoEc5=btCc+zOf=+OK zM{;+}Y~E(@4j2_%_N6qI ztP~Vd5eJBcWeR%D%7;i`En2^&HyTWBt=yYOQvCY$i>fO3&!5kbt{W|oZ!XV|_#0)? zLR3ri6f=!~LkXRcO^G;(3PdyNzJFQ0U)y}YkD`X={9Us>N^?1( zf#xj!e}#Q@Se4zkEs7%DogzqgH;Mw%-Q6JFxj{rgKw26^y1TnUx}>{Ha?^Pi-{KtAJUdip{ngG-G3ZoCGts32-G|bEt^a!%3=brWV;q2Aup zMO=W613+?TOc|~`sQT!>)!p&C+Xq&A!q3v1S_A|t-@2Q zSqEwgRga<>5}bhU$z7@ncYJsCnS?@%%e58Eln^tH!|Q$yQS~$Y;%5Te-&c7})|eA( z2GCkE-R7-&-n_Q+cZf>ck!XMCnG(3fIc{%DEy=2O#jXdnBatOlaxskY53Ed7O=#4F zO|y~|ug*5tqHlGcN}m534Rt1+U55L9c*VCZV0FB`JM>EZE*-OSQ_ohHVvB^SU6hD} zR0)+-$=PhBzI{#KfP!2iT+DND@ae|V`n~SwNDQ7!F_m%>!H2F^?b}kaj=J#R@)I#L z+S6LgA@3UNxq!<{9&muWq(q~2bvgIwS$~*Q-a4$dx1aY}TBx;DsRZ6FU(In2kSGH0 z%D1_HkX>*bHr;R)s1~pIg!q(b%hMEB?e5+yA zSkADh*X?mmXfZ!6t8XX~H@AnDv=uTq*nz1vU%%_0c~KEBtwVeCrC0#T<^=3 z7mt=vM7Ci$W}uMICuQF_|NZA8Sn_b|t(_hG%E}5D@;g2jzPG>hLzfwcM?mPZsX1SSDr4+y@W{xgvUbZizmzFoQ%6VsSmC#q*ORwniBVa^Vxw0pUZ2FMiHwMN113q; zD@;)U>eiPpxrASQRLbJSM-sgRsX1^}Q|AGmgk}KG0=3`-XrjPZ+s+M9r{4ONmpg!F zGAh87u$Ws;5CJjK>wL%T&tg+ZW+o-6+tJ&nPoILc*jLx=NTxNSjyW2MX}b+r5Ly8H zRbO9Iwt}8kfB!)Hvk5hj<*6yB7LKIEycMFOi^|RY&@Ct&1}G{p=okdOSVrCGI5@Ob zy5vLWtsDIOxWv*)T-MW-y;`GlrQRe%9ysBEyBHnk3Ez-m`X^viKl5FWET~=@Mwww! zWW_~Ap9eZP0MFM9X1gnbP@ZH|2ZwSHGAO|4C}=u>?CQ&)>1&pw?d*@t1;z8?Yve79 zo!HjjiE`jn68ScJvF6W6j~dI_(D9bc#j*`vi9wG7ig#=@(+IySml&m)t}B>q_3a+N z6-^A|oLE4Tig}gB*BGC#RsZASncYtpQ9Zv`*j!m|lUS|BDKRTN3g!dj-v-(bYipn^ zabv7_SoehA6kO6dU865J=?}S{fL4Xu+Zm0oz7nLu=NVfsR5lt)7RH_0$ac=SHsLn( zQ?kwKRcoG~a&4@Or9}IOIz3ZPEp0OX z@wN51s>elhL<+yF5exo|79_SoD6qp_+a!~7Tr-HTeV_4<+r>;-VTM)>lfc#XSOP7niN1QEOJ**w$*u)lml;qW%D&kLiCmU(q1UTCA_ASy zb*CMSE_$ui0HOp$uS1d+{3W=5!}#JLv7%5+m|{!E?g>bSX&4x+N*Al`t&gG5we%3? z>~}e`pz!#j>ce_3f$EQ9Q&hcy!))h|hxjh5*NlI8@vbR& zZ^g^lHhsX5gWEna@O0OKEZec{8EnbQzPE;I$@`1+jHHugy^@fhvg2X9XOl}gajTo+ zgTMGxF1CadeUZKgei8eeE=7AX8ks*|B@!>DTr@)-lf9zI7fUa^*gnAi1BNdhW2#;0 zd~2OJQwO-i%XKA1JAMT+6x>mQiQe;JDf|GJf*a3y8BqK|Cr7 z>-i0h%F&F+^OSDHZ2S8MLBj@1$r4@o&CPipF;B!k#LIV5PmSTPE=`g7YT7;*sC=iNsSl0dEu>l6k?n1H;YRAD_dzRjIkaK3kz#x5iFu^to$pO8*Eu>mCS3Ol*FlRLBqSs()}NW7$Hc@` zEoSrs71NivNugk4K9&C$bWZ@p_7yuGfG>P7G%^HFUzyYr9|0_OKBw*0swo|*y-90% z$-w@V&VBn8GdBCJ6xYb)&+QpoygTn=_umw!R=KDCzeLTK?BG-g!1@1xGZmV#G2x$)BQy(|M+BT@tqJA}|&X zjD5RYGbnX{5-hT6iF-6vp(vtqaKv(#r>YueN>nnUp?zzPOZC=V zzVQ+oYvviV2TaDV;oDt^zg=u4;|41%rC&Cvh^!H#DK!h`YxU$nd$K2S+lM z7Z@97(0+W(^LtD48~4au{`8l znROkX^tb!pmXGk?fQ;!~oyE5NBYTF$TL3pi^kcn9vXpPZocq>_OWpS5UE?m=x&t7X z@67Cp0AHiWd5~A>>F}lMUvqzmnwg351xfT?zPOA|PLy=`NSByhX0T7FSD+54x-U*9TDHRh!?To6ryy;IByb!u7GuUaw_k!D8wwjg%ASUtC@70<*7*(sZ zJSUAP#T_GxXiq-sJgbvd+I9}sm&thARq*WSlj)YrMrO>3-5c6w@WxrEl;$?1s;Jo( zV&@hfeDvIS^msMP`rk}V{n$vyT};!>va+`vQbOQ4Bx6?1!Xxv}L_U_E91(KeesWIy zVgFlt?jD2cJ~(tHKgtT5or7W}KU;-HZO2^^X&I!9CRX2{?2Se%E!0oU?-d=wB^S26 zQK2CJm4@BVDcIy>L%2tNCO1eX$fCN{3d0~Wj2F+-!l!IAc6!=6sMII>lJI8a7>^NV z51|%*J=1k@3$&otQ^`EdsHNnFm-lSVIDN96?%*{21KH1ed*BgJvokBd>*3z@oqJ3< zKgrE4T&>2a8OfF*nrFhB8)v^ft*~IcCe*g!wp1;7&C8oNV=u6QgCl)8_x_+6ih59Q zNoiuTQK;Dz0Dk{n$yqD0Z?*oeRQD(u3d3O}4FtjlQMQvcGD$Tjpn+lZCmwtv0y(pA zD!^N|bL&;PveMI&YZiYD=(vWh`;J~1mMI^v-9BfqF$`#5TQKV>57Ve<-U6zU>+QON z$L2P%jC#G3)|@vk{gc+Wdj$ysJlCYa^tG3nM!)TIqQ*Svj2J$4R@Jn<38I(oeva;3 z!4CQg0Hho|%btgLAc;Hmsw%r(_@8agX?7q$N(>=G6Xr=22RX2Q-)Y5L(7k!Mt-UJF zdeFKRzGuG>4s8jaDl)pOcSeaN6L5>b({*beDtCu&J}CvQjf18w(xsD`3Nv=Ip=7wJ z_9R|M(}j!N{=v0yK~*yi2@3?*1^1l8LqLXO0g!vZ;oJ!ul}z&Vw&mq|v>c&Mv(3Kd zWRcF?FNp;fkSthGeM@}H`O^EwV)2d8{tB$pM=-x9s! zpoLSI>sKB{3}yW-ZJx#vYOC`4p`*3uS>-mAq#1RJozy3mzGb}G>sw-g5-qR1Y?S9= zbMzlSUK!nR$z-8=05tuY3xLieF{g5tT zS~k%Xg)QmcW1OyhMuT+dx2g%1rc9sj9BR)4hJUmpppe%2i%nJV!fkYMpcQQIk zga_fECfH_$xwFIc>*gD@8^H2Qwx+a75ddBA(*p?klE7UGb^!W>YN2-9{VviAq!Q4j z0(D=g=RsZENU1!S#Cd^6YB-iDu_ZnI6sV*E^TTT$qak#rnvi#9$J6=aUA8UvRQ@Ah zUx(mT7#|zb0$phf@y7wKFX%EnBn{Yz_I!~{{<>pX@*LvSqA&jreg0>H`+uAM{4a`# zeLMax8sb095jCY~)8BXdDGabE9LA({_CqR^1=M{%C)Wv_srz}bs0Y#0U;k&y82$0f z{9kmFzpNK9Y5E_c$(IN~nE!vxo{Id}Wsv_5FXeehkO}|Ki-%C{;b6G~{3kTHYAU}I z$4McI|L3KvXwR84$ihX%r!=aI`(FJ+1$ewJb6Tpb+G#7(n6A(7#xvgx8IEH{*V2s4 z|A911%jQEbX6cYzO%CGP`KbthCf3RP`*xiKYdznU6>nu=)CEb|_EEj*m^TVmF|EWg zey)ak-%_wfdh@f{)h4z0M5RV5M+>*8DicFpP!SMT_N%SkxtYWBL`6|-9%!pbibCN$ zjE#TE3cmHGVKfNMI*BKRKI|`edTBeSJRDCYIBx!sX6uzs^n^#)302jsLo%fO$+XzF zN_R9a>MiU=bN_o|<-jnKiJoq|_@q^IQ;$3eXzHp&QivG+mhKM_0@j2$zyH|g| z>pawsXTUaHp)tP?GcH>0YENBbXXScPm(8TGN)zB&eUiiW&x=2*JYV)xnTUQmr6Kzw zXT}<)7TZ7bcV!BCc#k1N>D-ke5^Xszl74YhHQGZw5xF?+UfbjOn%$* zOplS#iy41)?7*fF*Pof2OZv*OhI7&}aj-i^(6hFQxiuv;)M>_AfH=tRu=S-@6zyV} zB{ef;w0Y|tqxGMm%sOK=?!7gN`KhsB8HH?kZ90^HAZ@}O;{2~ zD62bk3A`?+eE{c+(MI;8u;ifB+MMzXY?CpIy{fZIGVuT5woqr~uM*f{5w#JeCMpGII| zg4f19C0mA|HoZO!Re+Uv%}+(eN|LH}WPh^&=!&uGFi+TBafa?Sa(Z=Y#m7&5Zhuoe zQnP32>n)_VwRNy*D!qK*`^1|hGgM+qXJ8tvr$3ll6 zH4tg=qo|4sf)+TmI_*D}&Z_U)*#*rF=2$`mJg#@ZJ#>3X47XhOJ~?FGrZ_)8edgna zKwL;eQljKtt{6cp^q8k+z*66LK{jx(n^Tv0N*V8C0%m=ig$t3{^dBA^f9o9%f^lPK z2&}a#z1b{@S6Z=6AC;?0zGR_#MJ0Xo#+h`i+|{jsQ1*epLzaUL3+hBU$Z@#JHC` z^tQ1yUmguZHFQro3&QZA=6LHwk86c1l}Ag~YE%ZFS~YR}``6J*Ys}O!?iQ^F3vsu# z!jcv?khfKP=AJJWvS6x};cY`B!jy}Cr z`(#}I3pKThgKx5^CeT}Bn$C?bLZ;Amk_`|f9xN>1DKQA}v$an>ebOFaubgUIthw!U z^ybDQYsx4!WJklAOId{?Nyg|yD!0PHC!e9KLk=_Vh}p84^`TFIlOEl3%tbrjkfVio z$mk+dlj&D|~i0{5L+a+ucv`2~Z z89pYohPVU+TXo=g1X=D>wV?~Kl7sv|Ol5e5#%h)IS=H}xT;r3Uf{DLBrhDkClxZJK zKGV2rVM|)1P1mvM=}$T3ET?xzNAM6|Zx@#fKm);z zqD{Dv1axN`sbOttDNA>%MAzjVrQ`_aG}9-UF)BOnI{M|@R=G;QyQV^ zNM&=@(UYD{6K+it47!z{fD#Vkq;QL`^RR$8Q(SaARz;Y@!SlFy_L)!pI`$$ig#`uC zF>%cyyZQMP&CG-$Wd}QEI|s4LAX`rNk{(Y!ab6kCJkmEb#EnhRPlWTlaFSXHQWEnN zS2KX&%wh?QQFIeAkmt(cP}}R|)e7ebEU2kZBr0x+&F&5`nvH9IBP{H_y!EA@Wl56_ zBXxAxY)o;D3RNjdQ}*V9V8OR^rmtBku1LGhgkEjgj%V?x3AA=ak?@x7rrjZjLRVrS zIyc6!hMF6H2!5N)*2r1qf25qWTwl)@PH#nms?)!-yDLC`Q|+{)I4ftF>e4i5 zYBW=B@_S+;rSgT8r6rL~O~a{&_tb6qfXa#!k36T!kl5oA3e#Zm@t&!!a_Hi>u*yw6 zb|EC%)u>xdIoSX?uu|QhF;^1%JDsIVTvy1Nmbj3{l0H$-yC=#jSz~JnT=>5yuUSxF z2R%+uZ?{Y5B*OF3Ys_(_J0dDRJYKpe7{f$B!gCsQ;|D6=QcTTuV<%^OQ;x%e7k1kt zX%c%t475}5V!q@0Y>&FAVSN?Jo;T&>IRb*V5u>0ZtBNhlo9@xv;(R(!#<+Zob*OuQ z5vvzxGcBx!wKYncJiH9QJ8WEj-gZ4IcK)5C1_8o9pE{A^c`(Di*nLtFD@z#4k|15~ zvabmT2d562f0?Q7C%x2Cdr`gXwazXLp(g#YeQ^|~{u#`Hu+6!%SCNueqMPxpxE(f`R(d)`!8;;q|nJp)p;Ad z0E4KnJu?li%$r1oN{n1T7!g&ydM5;+rC?}I zBRxd`=BaDqzykRA@#AzgFv&1jcBp@R?-e`4ZFg|t2ylMmaWxZ?mX`Fgfw1Eo1o*_1 zz_G!Hxw5hnN32BoWsIbw{)6{eLS^#cV=PMg(|psSN0?smZl`k%L3%tB$Pr^F z!hD1XeNKBBAk-|8mTgg4lPV@BhqmKHm^1#?Y>NO$vqx()iAy=MkE(wI+|UdQLelWS z(YIg2D^Z`9&oDH&9#SO@DuRh=aq$;r>e%C7va_j>7l7_eia*QTSn$WG?fw1dtx77Q z*4B*Rmlc_E{s^f`_P*W$@9a31`!>NUmQkyE)kRHSOR3`?_D0HA=E>)-mmK+kq+qpF zjWW(LsvH_Ngo;Yc^M-@4%cf#{bkx^o`%7TEQmpIEP7W3#+zb|KMjl~`nNw8%#@8;x z%RB#wTIV@jY-~C@x)BteA>+plgld^=2!ENFNa!U*mL~tz9|=!ZQy6gDp8CQFrG_Ua zCic!Tyz^lpm(6eGRQZrt+%nm@QDA%3j(}vF(MGFByvUA^xB{JseHu4m+OgxrMjX0g z$EPsSA-a2UgHMPUcP*HuXkpmFnqN==e$d>+fFHvdG>G-ZSV8Z*{Tp{Ccj||hm-Wd# zX%Uazh;^pQX8stn5oj~vf!+#3lQ3q`$jG#Oep{lNnz){xUY`51y!qE_cc@*Rc4l@$ z-oj34G$DJ=myR7u!XRn)8d~&i`lj=%JLH}KsVdt9s{p@1)Uo+7Hk0N2++3J(N@AwM z{ylfN7ccUPipX(8(((!G4dmlbx{cj}`E?(|m7Am2X0}{@H z5ZN|HE-vcgGV2Oh+yTnCtdS9gwY9Z+HhyRSTHbf&4DZ4|&rj7rR!obG3P(NR zAX8XJSTvJZ>y>XE!*927CbB$+lA_KaDI0I5ld_3pDDUnO9o;~3^8=>#NYtnR!M&4128?d2R+p=O zQg@1nG~Hxtr}l45ml?ePQ`l|=1sbJ4A7LJL0pjS2M<=oPi~#Xfw*s`KpWYiWYL6Vz zP>ft{MhxDshY2g|^iO=GOrIPbiRMaF5N6@>Z|_pu!g9GiU7vjTiE)>oJXt0Oh}<*MrhViaN;{`SLnhfYh(W+YfH|S_ z@IvCTb7wDka^=OK)l6K|4^cjpqr|dWtjy!UpRgL8!lQZ4G|n*tZc~CZT){-&`TiW( zoY7*hoa(f}-2l7(mob~wLcO#0@-EV8|C3jgcA*ms<6u>U^j8;^<3{C2_K^woM)y)? zTa1m(clshgMb^&*@~hBmMbgN@9RF9>PALw|wsg&-tJ_cQt#5?Eo_ODmp}2#cpTBB1 zD>Zl+Ryo9SI<}09$Wqe$q+tI@KEM7)4+nBAlZGT+%q!AxEK z+NfS^a83nW!v(azTT3L3eHzyFIWH+|$-));I+!FBEWoZ1+?6wrp!ct)|F|S3CG8xh zUi*BeprBZHP65I9sjm=nM`nF};_gRgz(elZf=0^beC@%?dYCZ{@l|^~@F&_QN%XD| zZE9}fy=^A)Rc_}JIVxfHQ?)hW}Wh$$xqqv>YBWZjUp+eE;=Pn#cI2|nTX#Vixue$Wv z@9M$Es;=e&@stGxUc7xRKx+TbA4*a=^w9Tq^~oS|u=uoj0eD-AlJGTdh(VPm(%e+x zx&!a$w&m{zNQmz`a=MWlbm6tdxse-wOaVXvZBT}>vbs8I${Fqj96q9)ph#LeO=Ghw zGvnYOgGM=a2ZuzbIM44XHN?tL6d9gm7vv7`adtm>9MVAzU{6;Erk}%kt)2j3gxD4c zujNCn%cNHQ7eEC&7(v= zILAI^TO>oySFT#ec94^}Z6p2O4%NsbEW^F<4ErOF zm{`C}RYB6y!~Mk{$elB<{^Cu?h3=<~9#!hu7lD!aUQ(63o<);hnvM72cPqm#hDdwim5}&)hjM?zVOK}|H%{lehR~kN9pLOoJ ztBVS{{MPq6TDJEIouugmjsL=eVB_ft)nlSGppRJ&# z*3*Tj*O|y^d3kVm0UeWK?!~*nox7Tq^}5#tC-99Y8usUgmg?yggLAEm0mtMzx3?De zh2Uym$c($)9{1$z3xUGovh{_~qb!|d|Mkf5cdbsjQuPQqGa=R#>E5Pjp_LuN|?>n#aY@)pU6PQw~8Me*g)Zy+>qMd^S zra>uy>VpbowGlehvEdL?jS+$Z&3JIn<+#X2$E*!QuRkZ_X*G#!-b1-@>M~^g;c-2q z)NE>5XwIRTXs!;D&-qm+K8mV1@vRt@8`T`da>>yD9+OSI#v1fvtm? z3jn5MKA(8T+1ilaJZ-lXevo>bEY!FEgb5cofyZlJ6IpEb;vIgt8ipzK+?D$?-AwXn z2}F3WjRHMj&3CdILUgswNtV^@O?r0+%b?|r+v0VJ$3DB&zFeQ}Scn4yVFCVE-_Yoex}#mw~PSBm5I-{hbX=LZY>=U{QLe8a2)GN(#M zPj@vJs}}C*vtYxmTN3AowV8!&+XQk{%-&}{Kx|#3RG*wF&T|M7U`*Gg$7Qw7OvKfP zNB1uXmyV1V-%B}HZM$|@+!zH0_w2P>7?T#nxT0TU2H9;Ugh=({fV1ubgEZ0O)m(SC zn3IlKF3;$GHy*dc{neIH&CGP8JNwMQvD{0avq0g24+294J~v6=UJMNT+@k|sr;YwN z$9?B13E%%rsKcNMUcRg;s!L%m)*V#xxyIUYN(9H4s%~}EgkB@CQ=4wRS$q%zOR^0p z)Aa>QF^g7c&Q!WPS`aZZGJ>SUN|m1M{z$mgVmw>1XbQME{HmJLm2y_W5%#%U$yj6- zRoDhRIAo;53&%Epys?Riu17fwVC%X%2yK<~;oEQ|?<7Xk&Nld|&Y&0tlKuAyrx$2; zJtTUYk2*y@kUwkcMT8JY;N?UK>FWgPh!3507jsLS9b{MVWKEldsDGA*xgVgyAZle< zJ2^Qy^r#)QvPj=oyR(CVBzX%R2HcE>h9vNvsvA8{2N8-?=^tEf_P6VYj*eKs{1>6? z{PD)v_E(W)WYA#{L9d{?7CeKWTt z+i<_^>xYbjBEwHMHI!0v98UJ&wsY2vr>nn)#QY1-G3o;)mLj}(Z8c7MvT5>nCmmGD z$I7l47z!|G*G3>QHGTqZ3n||L12Bs&(7OgN+iUz;ro<}h>385(MKx;bEx*YsvxgB_ zg7Z%uy;b6~(7Ff#xpd8`we6Y_*$uwWWe3^zVwDu4B`T7?2vD*{>0fFlzEB8z6HgOR zBu_*6oCjz8{qR;M@p}#0EnU0bZ`4C094JW(QG?xf<*rJSLT{PH8l_@`!%G7JGFK zKD`ZxI(sMtUn9Hn*R59SwXK8lk# zE=Athhwcxn{ORzg^{0}h%~LL)wzaI(n_TzSa?E;&MW+sy{`nv9`(KoDM)F`9i5G}5 z{|}J-zj(Ur+YHEk7Dfy@)=((I*4Mv~z5N&c*J`06zj$B&3#_jW)~O4OIn;$==Ntv4 z5wG!5`~}>J#gUcPQJZ<3!){j_wJ=Nm!tcq`g`AswO5+@~c=nR`u7&hbb$=iEE@%;| zmko1(7>*sz^SYK^po{%2Z=d7)uS(JL0a)NBm|`~$*fW#JQcwJj`tU7cc!NboDOe&| zK)f;ir$$ljLJUvx5UoSZGseFNeveNT0@l;t=IeaKP1wY;)GmRr%XZ6bgYDO&J*&_% z%EX|W-Ric?H7}>S$CCwiYNhA+Osmgn>)YR(Vn074^+ftPHkS1B=N0&^h{KXn*w4E- zSVO{LHm5@r#=qA;Ii4gP!SWmLEbZ#-S@nr23y&)M`*jA^>%Vt!YGCbUid9UR!zf8V zS7JrdusVG@$?%04OR~*U@e*^Dk*7ETzp~rEXjGb0NS{`GI+1wvFP)*!A&*Zpj-2S+`XdG#8p?i@R4;5JtSD3_lE;5*q(| zu16caIZmk6uadj)S&_TAEDcFM7}6kS+0d;s5{9HNUi%bx^-DLiNn*!=UD4#}Fo9Zs hmb4=(f_?t=1G)!+tnt|79t`*=Au9X6SVaHx{{nt-eDweT From fa3ddee2cb93fe6290b4fe90bc5409ef84eda238 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 13 Jan 2022 23:03:08 -0500 Subject: [PATCH 078/107] Move copy commands into subcommand group --- commands.js | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/commands.js b/commands.js index e1b8c46..0839fde 100644 --- a/commands.js +++ b/commands.js @@ -77,6 +77,11 @@ const REGISTRY = new SlashCommandRegistry() .setType(ApplicationCommandType.Message) .setHandler(requireAuth(cmdSelect)) ) + .addContextMenuCommand(command => command + .setName('select-copy-target') + .setType(ApplicationCommandType.Message) + .setHandler(requireAuth(cmdSelectCopy)) + ) .addCommand(command => command .setName('select-message-mobile') .setDescription('Workaround for selecting messages on mobile') @@ -92,25 +97,24 @@ const REGISTRY = new SlashCommandRegistry() .setDescription('Shows currently selected message') .setHandler(requireAuth(cmdSelected)) ) - .addContextMenuCommand(command => command - .setName('select-copy-target') - .setType(ApplicationCommandType.Message) - .setHandler(requireAuth(cmdSelectCopy)) - ) .addCommand(command => command - .setName('select-copy-target-mobile') - .setDescription('Workaround for selecting copy target message on mobile') - .setHandler(requireAuth(cmdSelectCopyMobile)) - .addStringOption(option => option - .setName('message-url') - .setDescription('The URL for the clone target message to select') - .setRequired(true) + .setName('copy') + .setDescription('Copy react-role mappings to another message') + .addSubcommand(subcommand => subcommand + .setName('select-target-mobile') + .setDescription('Workaround for selecting copy target message on mobile') + .setHandler(requireAuth(cmdSelectCopyMobile)) + .addStringOption(option => option + .setName('message-url') + .setDescription('The URL for the clone target message to select') + .setRequired(true) + ) + ) + .addSubcommand(subcommand => subcommand + .setName('selected-target') + .setDescription('Shows currently selected copy target message') + .setHandler(requireAuth(cmdSelectedCopy)) ) - ) - .addCommand(command => command - .setName('selected-copy-target') - .setDescription('Shows currently selected copy target message') - .setHandler(requireAuth(cmdSelectedCopy)) ) .addCommand(command => command .setName('role') From 4ef9a2a261d4e93631ee3ffbfe1d00231e1feda1 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 14 Jan 2022 19:52:58 -0500 Subject: [PATCH 079/107] Command for copying mappings from one message to another --- commands.js | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++ database.js | 4 +-- util.js | 12 ++++++++ 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/commands.js b/commands.js index 0839fde..004b7e7 100644 --- a/commands.js +++ b/commands.js @@ -49,6 +49,7 @@ const logger = require('./logger'); const { asLines, emojiToKey, + ephemEdit, ephemReply, stringify, unindent, @@ -115,6 +116,13 @@ const REGISTRY = new SlashCommandRegistry() .setDescription('Shows currently selected copy target message') .setHandler(requireAuth(cmdSelectedCopy)) ) + .addSubcommand(subcommand => subcommand + .setName('execute') + .setDescription( + 'Copy role-react mappings from selected message to target message' + ) + .setHandler(requireAuth(cmdCopyMappings)) + ) ) .addCommand(command => command .setName('role') @@ -645,5 +653,77 @@ async function cmdReset(interaction) { return ephemReply(interaction, 'Deleted all configuration for this guild!'); } +/** + * Copies role-react mappings from the selected message to the copy target + * message. This requires both a message and a copy target to be selected. + */ +async function cmdCopyMappings(interaction) { + let msg_from = SELECTED_MESSAGE_CACHE.get(interaction.user.id); + let msg_copy = CLONE_MESSAGE_CACHE.get(interaction.user.id); + + if (!msg_from) { + return ephemReply(interaction, + 'No message selected! Select a message first.' + ); + } + + if (!msg_copy) { + return ephemReply(interaction, + 'No copy target selected! Select a copy target message first.' + ); + } + + msg_from = await msg_from.fetch(); + msg_copy = await msg_copy.fetch(); + + // Prevent modifying a server from outside a server + const guild = interaction.guild; + if (guild !== msg_from.guild || guild !== msg_copy.guild) { + return ephemReply(interaction, unindent(` + Source and target messages need to be in the same Server this + command was issued from! + `)); + } + + // Need to reply to keep the interaction token alive while we copy + await ephemReply(interaction, 'Copying, this may take a moment...'); + + return database.transaction(async trx => { + const mapping = await database.getRoleReactMap(msg_from.id, trx); + for await (const [emoji_id, role_id] of mapping.entries()) { + try { + await database.addRoleReact({ + guild_id: guild.id, + message_id: msg_copy.id, + emoji_id: emoji_id, + role_id: role_id, + }, trx); + } catch (err) { + logger.error('Failed to copy roles', err); + await ephemEdit(interaction, 'Something went wrong. Try again?'); + rethrowHandled(err); + } + + try { + await msg_copy.react(emoji_id); + } catch (err) { + logger.warn(`Cannot copy roles to ${msg_copy.url}`); + await ephemEdit(interaction, unindent(` + Could not add reacts to the target message. Do I have the + right permissions? + `)); + rethrowHandled(err); + } + } + + return ephemEdit(interaction, + 'Copied react-role mappings.\n' + + `Source: ${msg_from.url}\n` + + `Target: ${msg_copy.url}\n` + + 'You can delete the original message now.' + ); + }); +} + module.exports = REGISTRY; diff --git a/database.js b/database.js index 89c8465..282fd45 100644 --- a/database.js +++ b/database.js @@ -173,9 +173,9 @@ function getRoleReact(args) { * Returns the emoji->role mapping for the given message as a Map object, or * null if the given message has no react roles set up. */ -function getRoleReactMap(message_id) { +function getRoleReactMap(message_id, trx) { _assertDiscordId(message_id); - return knex(REACTS) + return (trx ? trx(REACTS) : knex(REACTS)) .select(['emoji_id', 'role_id']) .where('message_id', message_id) .then(rows => rows.length > 0 diff --git a/util.js b/util.js index 57a21de..d65e7fd 100644 --- a/util.js +++ b/util.js @@ -76,6 +76,17 @@ function emojiToKey(emoji) { return emoji?.id ?? emoji?.name ?? emoji; } +/** + * Same as {@link ephemReply}, but to edit an existing ephemeral response. + */ +function ephemEdit(interaction, content) { + logger.info(`Edit to ${detail(interaction)}: "${content}"`); + return interaction.editReply({ + content: content, + ephemeral: true, + }); +} + /** * Shortcut for sending an ephemeral reply to an interaction, since we do it so * much. @@ -174,6 +185,7 @@ module.exports = { asLines, detail, emojiToKey, + ephemEdit, ephemReply, isDiscordId, isEmojiStr, From 451c5ac14c84f7584df6901394c181d5747b6a54 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 14 Jan 2022 21:42:52 -0500 Subject: [PATCH 080/107] Move most source files to src subdirectory --- main.js | 4 ++-- package.json | 2 +- commands.js => src/commands.js | 2 +- database.js => src/database.js | 2 +- events.js => src/events.js | 0 logger.js => src/logger.js | 0 register.js => src/register.js | 0 util.js => src/util.js | 0 8 files changed, 5 insertions(+), 5 deletions(-) rename commands.js => src/commands.js (99%) rename database.js => src/database.js (99%) rename events.js => src/events.js (100%) rename logger.js => src/logger.js (100%) rename register.js => src/register.js (100%) rename util.js => src/util.js (100%) diff --git a/main.js b/main.js index 516cb33..ed1aac0 100644 --- a/main.js +++ b/main.js @@ -18,8 +18,8 @@ const fs = require('fs'); const Discord = require('discord.js'); -const events = require('./events'); -const logger = require('./logger'); +const events = require('./src/events'); +const logger = require('./src/logger'); const CONFIG = JSON.parse(fs.readFileSync( process.argv[2] || '/etc/discord/ReactionRoleBot/config.json' diff --git a/package.json b/package.json index 2aeb98e..526e6c6 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "scripts": { "dev": "node main.js dev-config.json", "knex": "node_modules/knex/bin/cli.js", - "register": "node register.js", + "register": "node src/register.js", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { diff --git a/commands.js b/src/commands.js similarity index 99% rename from commands.js rename to src/commands.js index 004b7e7..5763e6d 100644 --- a/commands.js +++ b/src/commands.js @@ -44,7 +44,7 @@ const NodeCache = require('node-cache'); const database = require('./database'); const { rethrowHandled } = database; -const info = require('./package.json'); +const info = require('../package.json'); const logger = require('./logger'); const { asLines, diff --git a/database.js b/src/database.js similarity index 99% rename from database.js rename to src/database.js index 282fd45..99b537e 100644 --- a/database.js +++ b/src/database.js @@ -14,7 +14,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const knexfile = require('./knexfile'); +const knexfile = require('../knexfile'); const knex = require('knex')(knexfile[process.env.NODE_ENV || 'development']); const lodash = require('lodash'); diff --git a/events.js b/src/events.js similarity index 100% rename from events.js rename to src/events.js diff --git a/logger.js b/src/logger.js similarity index 100% rename from logger.js rename to src/logger.js diff --git a/register.js b/src/register.js similarity index 100% rename from register.js rename to src/register.js diff --git a/util.js b/src/util.js similarity index 100% rename from util.js rename to src/util.js From 81eb5235f519306859d7fa673bf3ab9cf8383ed9 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 14 Jan 2022 21:48:25 -0500 Subject: [PATCH 081/107] Move knexfile and migrations to src subdirectory --- package.json | 2 +- src/database.js | 2 +- knexfile.js => src/knexfile.js | 0 {migrations => src/migrations}/20200225015300_db.js | 0 {migrations => src/migrations}/20200814190000_meta.js | 0 {migrations => src/migrations}/20200815043000_perms.js | 0 {migrations => src/migrations}/20200818203000_mutex.js | 0 {migrations => src/migrations}/20211215035000_animated.js | 0 8 files changed, 2 insertions(+), 2 deletions(-) rename knexfile.js => src/knexfile.js (100%) rename {migrations => src/migrations}/20200225015300_db.js (100%) rename {migrations => src/migrations}/20200814190000_meta.js (100%) rename {migrations => src/migrations}/20200815043000_perms.js (100%) rename {migrations => src/migrations}/20200818203000_mutex.js (100%) rename {migrations => src/migrations}/20211215035000_animated.js (100%) diff --git a/package.json b/package.json index 526e6c6..363d06b 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "scripts": { "dev": "node main.js dev-config.json", - "knex": "node_modules/knex/bin/cli.js", + "knex": "npx knex --knexfile src/knexfile.js", "register": "node src/register.js", "test": "echo \"Error: no test specified\" && exit 1" }, diff --git a/src/database.js b/src/database.js index 99b537e..282fd45 100644 --- a/src/database.js +++ b/src/database.js @@ -14,7 +14,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . ******************************************************************************/ -const knexfile = require('../knexfile'); +const knexfile = require('./knexfile'); const knex = require('knex')(knexfile[process.env.NODE_ENV || 'development']); const lodash = require('lodash'); diff --git a/knexfile.js b/src/knexfile.js similarity index 100% rename from knexfile.js rename to src/knexfile.js diff --git a/migrations/20200225015300_db.js b/src/migrations/20200225015300_db.js similarity index 100% rename from migrations/20200225015300_db.js rename to src/migrations/20200225015300_db.js diff --git a/migrations/20200814190000_meta.js b/src/migrations/20200814190000_meta.js similarity index 100% rename from migrations/20200814190000_meta.js rename to src/migrations/20200814190000_meta.js diff --git a/migrations/20200815043000_perms.js b/src/migrations/20200815043000_perms.js similarity index 100% rename from migrations/20200815043000_perms.js rename to src/migrations/20200815043000_perms.js diff --git a/migrations/20200818203000_mutex.js b/src/migrations/20200818203000_mutex.js similarity index 100% rename from migrations/20200818203000_mutex.js rename to src/migrations/20200818203000_mutex.js diff --git a/migrations/20211215035000_animated.js b/src/migrations/20211215035000_animated.js similarity index 100% rename from migrations/20211215035000_animated.js rename to src/migrations/20211215035000_animated.js From 0502851c738a3a5a91d24dde57436bcbf2479356 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 14 Jan 2022 21:52:48 -0500 Subject: [PATCH 082/107] Move main.js to src subdirectory in a way that relative imports still work --- package.json | 4 ++-- main.js => src/main.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) rename main.js => src/main.js (95%) diff --git a/package.json b/package.json index 363d06b..e571741 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "reactionrolebot", "version": "2.0.0", "description": "I'm a basic, no BS Discord bot that can assign and unassign roles using message reactions. I am completely free and open source, and always will be.", - "main": "main.js", + "main": "src/main.js", "dependencies": { "discord-command-registry": "^1.2.0", "discord.js": "^13.3.1", @@ -13,7 +13,7 @@ "winston": "^3.3.3" }, "scripts": { - "dev": "node main.js dev-config.json", + "dev": "node . dev-config.json", "knex": "npx knex --knexfile src/knexfile.js", "register": "node src/register.js", "test": "echo \"Error: no test specified\" && exit 1" diff --git a/main.js b/src/main.js similarity index 95% rename from main.js rename to src/main.js index ed1aac0..7835a9f 100644 --- a/main.js +++ b/src/main.js @@ -18,13 +18,13 @@ const fs = require('fs'); const Discord = require('discord.js'); -const events = require('./src/events'); -const logger = require('./src/logger'); +const events = require('./events'); +const logger = require('./logger'); const CONFIG = JSON.parse(fs.readFileSync( process.argv[2] || '/etc/discord/ReactionRoleBot/config.json' )); -const PACKAGE = require('./package.json'); +const PACKAGE = require('../package.json'); // Everything operates on IDs, so we can safely rely on partials. // This allows reaction events to fire for uncached messages. From c33c267c4d0a54147fe8ff11fe7f69fcc0811f4c Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Fri, 14 Jan 2022 22:11:54 -0500 Subject: [PATCH 083/107] Move to short version of AGPL header, add more license info to README --- COPYING.md => LICENSE.md | 0 README.md | 13 +++++++++++++ src/commands.js | 16 ++++------------ src/database.js | 16 ++++------------ src/events.js | 16 ++++------------ src/knexfile.js | 16 ++++------------ src/logger.js | 16 ++++------------ src/main.js | 16 ++++------------ src/migrations/20200225015300_db.js | 16 ++++------------ src/migrations/20200814190000_meta.js | 16 ++++------------ src/migrations/20200815043000_perms.js | 16 ++++------------ src/migrations/20200818203000_mutex.js | 16 ++++------------ src/migrations/20211215035000_animated.js | 16 ++++------------ src/register.js | 16 ++++------------ src/util.js | 16 ++++------------ 15 files changed, 65 insertions(+), 156 deletions(-) rename COPYING.md => LICENSE.md (100%) diff --git a/COPYING.md b/LICENSE.md similarity index 100% rename from COPYING.md rename to LICENSE.md diff --git a/README.md b/README.md index 7a48306..c66f0dd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ # Overview + +
AGPL-3.0 Logo + + A Discord bot that can assign roles based on message reactions.
[You can invite my live instance of the bot to your server with this link]( https://discord.com/oauth2/authorize?client_id=692585944934514738&scope=bot&permissions=335881280 @@ -180,3 +185,11 @@ npm run knex migrate:latest Create a file containing your bot token in plain text. Run this to start the bot: `node main.js path/to/your/config` + +## License +Copyright 2020 [Mimickal](https://github.com/Mimickal) + +This code is licensed under the +[AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0-standalone.html) license. + +Basically, any modifications to this code must be made open source. diff --git a/src/commands.js b/src/commands.js index 5763e6d..2ccf072 100644 --- a/src/commands.js +++ b/src/commands.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ // Some notes for this file: diff --git a/src/database.js b/src/database.js index 282fd45..844e9bb 100644 --- a/src/database.js +++ b/src/database.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const knexfile = require('./knexfile'); const knex = require('knex')(knexfile[process.env.NODE_ENV || 'development']); diff --git a/src/events.js b/src/events.js index d36b17a..3a231d1 100644 --- a/src/events.js +++ b/src/events.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const Perms = require('discord.js').Permissions.FLAGS; diff --git a/src/knexfile.js b/src/knexfile.js index f2b88bc..5a07ec1 100644 --- a/src/knexfile.js +++ b/src/knexfile.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ module.exports = { development: { diff --git a/src/logger.js b/src/logger.js index 2cbc0da..a0adfde 100644 --- a/src/logger.js +++ b/src/logger.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const Winston = require('winston'); diff --git a/src/main.js b/src/main.js index 7835a9f..7c9bdf9 100644 --- a/src/main.js +++ b/src/main.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const fs = require('fs'); diff --git a/src/migrations/20200225015300_db.js b/src/migrations/20200225015300_db.js index efb209b..6e70003 100644 --- a/src/migrations/20200225015300_db.js +++ b/src/migrations/20200225015300_db.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const DISCORD_ID_MAX = 19; const REACTS = 'reacts'; diff --git a/src/migrations/20200814190000_meta.js b/src/migrations/20200814190000_meta.js index 081be6c..aeb1f8c 100644 --- a/src/migrations/20200814190000_meta.js +++ b/src/migrations/20200814190000_meta.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const META = 'meta'; diff --git a/src/migrations/20200815043000_perms.js b/src/migrations/20200815043000_perms.js index 7e0d0d9..9f6cf5e 100644 --- a/src/migrations/20200815043000_perms.js +++ b/src/migrations/20200815043000_perms.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const DISCORD_ID_MAX = 19; const PERMS = 'perms'; diff --git a/src/migrations/20200818203000_mutex.js b/src/migrations/20200818203000_mutex.js index 9378200..bc71ad5 100644 --- a/src/migrations/20200818203000_mutex.js +++ b/src/migrations/20200818203000_mutex.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const DISCORD_ID_MAX = 19; const MUTEX = 'mutex'; diff --git a/src/migrations/20211215035000_animated.js b/src/migrations/20211215035000_animated.js index 1c0ca32..655b586 100644 --- a/src/migrations/20211215035000_animated.js +++ b/src/migrations/20211215035000_animated.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const REACTS = 'reacts'; const EMOJI_ID = 'emoji_id'; diff --git a/src/register.js b/src/register.js index ee1e107..7e1926b 100644 --- a/src/register.js +++ b/src/register.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const fs = require('fs'); const path = require('path'); diff --git a/src/util.js b/src/util.js index d65e7fd..4139663 100644 --- a/src/util.js +++ b/src/util.js @@ -1,18 +1,10 @@ /******************************************************************************* - * This file is part of ReactionRoleBot, a role-assigning Discord bot. + * This file is part of No BS Role Reacts, a role-assigning Discord bot. * Copyright (C) 2020 Mimickal (Mia Moretti). * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. ******************************************************************************/ const { Emoji, From d084cb8e805536993e002b6f11e64fac650f5119 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 25 Jan 2022 00:53:55 -0500 Subject: [PATCH 084/107] (codecheck) fix typo --- database.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database.js b/database.js index 89c8465..3b2a9cb 100644 --- a/database.js +++ b/database.js @@ -84,7 +84,7 @@ function _assertDiscordId(value) { * block. * * We don't have a great way to differentiate between database Errors and - * Discord Errors based on their prototype. The oly way is to wrap each method + * Discord Errors based on their prototype. The only way is to wrap each method * in their own try-catch, so that makes Knex' catch-all rejection behavior * problematic. This is our solution. */ From cea438e83872a3c68dfca36648b3758cad088f38 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 2 Feb 2022 01:33:15 -0500 Subject: [PATCH 085/107] (bugfix) Fix migration creating dev database in src --- src/knexfile.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/knexfile.js b/src/knexfile.js index 5a07ec1..5556d75 100644 --- a/src/knexfile.js +++ b/src/knexfile.js @@ -6,12 +6,14 @@ * License v3.0. See LICENSE or * for more information. ******************************************************************************/ +const path = require('path'); + module.exports = { development: { client: 'sqlite3', useNullAsDefault: true, connection: { - filename: './dev.sqlite3' + filename: path.join(__dirname, '..', 'dev.sqlite3'), }, // Helps us catch hanging transactions in dev by locking up the database // if we forget to commit anything. From 8a798ea0d8a2368c98ef96cbc4a1b25d5db6f310 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 2 Feb 2022 01:41:48 -0500 Subject: [PATCH 086/107] (fix?) Do the same path trick for output.log --- src/logger.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/logger.js b/src/logger.js index a0adfde..742f4f5 100644 --- a/src/logger.js +++ b/src/logger.js @@ -6,9 +6,10 @@ * License v3.0. See LICENSE or * for more information. ******************************************************************************/ +const path = require('path'); const Winston = require('winston'); -const LOG_FILE_NAME = 'output.log'; +const LOG_FILE_NAME = path.join(__dirname, '..', 'output.log'); const IS_PROD = process.env.NODE_ENV === 'prod'; From ac63c6295858185ea76bfe3b77cf668271e18c69 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 2 Feb 2022 01:46:43 -0500 Subject: [PATCH 087/107] Migration for allowing multiple roles on a single react --- src/migrations/20220102035000_multiple.js | 110 ++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/migrations/20220102035000_multiple.js diff --git a/src/migrations/20220102035000_multiple.js b/src/migrations/20220102035000_multiple.js new file mode 100644 index 0000000..1af122e --- /dev/null +++ b/src/migrations/20220102035000_multiple.js @@ -0,0 +1,110 @@ +/******************************************************************************* + * This file is part of No BS Role Reacts, a role-assigning Discord bot. + * Copyright (C) 2020 Mimickal (Mia Moretti). + * + * No BS Role Reacts is free software under the GNU Affero General Public + * License v3.0. See LICENSE or + * for more information. + ******************************************************************************/ +const { unindent } = require('../util'); + +const REACTS = 'reacts'; +const REACTS_TMP = `${REACTS}_tmp`; + +const OLD_ID_MAX = 19; +const NEW_ID_MAX = 22; + +/** + * - Update the reacts table to use role_id in the primary key, so that we can + * support one emoji mapped to multiple roles. + * - Increase Discord ID lengths from 19 to 22. SQLite3 doesn't enforce varchar + * length, so we don't NEED to do this, but we need to remake the table to + * modify the primary key anyway, so why not... + * + * SQLite3 does not support many alter table commands, so we need to create a + * new table, copy everything over, delete the old table, then rename the new + * table back to the original name. + * https://www.sqlitetutorial.net/sqlite-alter-table/ + * + * SQLite3 does not automatically reclaim the disk space consumed by the + * duplicate table. We need the VACUUM command for this, but VACUUM also cannot + * be used in a transaction. Knex runs all migrations in a transaction by + * default, so we will need to disable this functionality and use our own in + * order to VACUUM at the end. + */ +exports.config = { transaction: false }; + +exports.up = async function(knex) { + await knex.transaction(async trx => { + await trx.schema.createTable(REACTS_TMP, table => { + table.string('guild_id', NEW_ID_MAX); + table.string('message_id', NEW_ID_MAX); + table.string('emoji_id', NEW_ID_MAX); + table.string('role_id', NEW_ID_MAX); + + table.primary(['message_id', 'emoji_id', 'role_id']); + }); + await trx.insert(trx.select().from(REACTS)).into(REACTS_TMP); + await trx.schema.dropTable(REACTS); + await trx.schema.renameTable(REACTS_TMP, REACTS); + }); + await knex.raw('VACUUM'); +}; + +exports.down = async function(knex) { + console.warn(unindent(` + Rolling back ${REACTS} primary key change. This will delete instances + where multiple rows have the same message_id and emoji_id values, but + have different role_id values. + `)); + + await knex.transaction(async trx => { + // Print and delete rows with now-duplicate primary keys. + // SQLite3 doesn't support returning so we need this workaround. + const ambiguous_query = trx + .from(REACTS) + .leftJoin(`${REACTS} as self`, join => join + .on( `${REACTS}.message_id`, '=', 'self.message_id') + .andOn(`${REACTS}.emoji_id`, '=', 'self.emoji_id') + .andOn(`${REACTS}.role_id`, '!=', 'self.role_id') + ) + .whereNotNull('self.ROWID') + + const to_delete = await ambiguous_query + .clone() + .distinct(`${REACTS}.role_id`) + .select([ + `${REACTS}.guild_id`, + `${REACTS}.message_id`, + `${REACTS}.emoji_id`, + `${REACTS}.role_id`, + ]); + if (to_delete.length > 0) { + console.warn('\nDeleting the following:'); + console.warn(to_delete.map(JSON.stringify)); + } + + await trx + .delete() + .from(REACTS) + .whereIn(`${REACTS}.ROWID`, ambiguous_query + .clone() + .distinct(`${REACTS}.ROWID`) + ); + + // Now we can remake the table + await trx.schema.createTable(REACTS_TMP, table => { + table.string('guild_id', OLD_ID_MAX); + table.string('message_id', OLD_ID_MAX); + table.string('emoji_id', OLD_ID_MAX); + table.string('role_id', OLD_ID_MAX); + + table.primary(['message_id', 'emoji_id']); + }); + await trx.insert(trx.select().from(REACTS)).into(REACTS_TMP); + await trx.schema.dropTable(REACTS); + await trx.schema.renameTable(REACTS_TMP, REACTS); + }); + await knex.raw('VACUUM'); +}; + From 195b19a1cb1f1ac84532bb830258a0087c877dab Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 2 Feb 2022 01:54:41 -0500 Subject: [PATCH 088/107] Log number of messages cached on login --- src/events.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/events.js b/src/events.js index 3a231d1..f8483f9 100644 --- a/src/events.js +++ b/src/events.js @@ -245,6 +245,7 @@ async function onReady(client) { // Despite message IDs being unique, we can only fetch a message by ID // through a channel object, so we need to iterate over all channels and // search each one for the messages we expect. + let numCached = 0; await Promise.all(client.guilds.cache.map(async guild => { const guild_message_ids = await database.getRoleReactMessages(guild.id); let errors = {}; // Allows us to aggregate and report errors @@ -252,7 +253,9 @@ async function onReady(client) { await Promise.all(guild.channels.cache.map(async channel => { await Promise.all(guild_message_ids.map(async id => { try { - await channel.messages?.fetch(id); + if (await channel.messages?.fetch(id)) { + numCached++; + } } catch (err) { if (err.message.includes('Unknown Message')) { return; // Expected when message isn't in this channel @@ -271,7 +274,7 @@ async function onReady(client) { }); })); - logger.info('Finished pre-cache'); + logger.info(`Finished pre-cache (${numCached} messages)`); } module.exports = { From 37a4dad5e35c228f1c82f4f4538df09cc32bd04f Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 2 Feb 2022 02:14:19 -0500 Subject: [PATCH 089/107] (bugfix) Actually use transaction for role remove-all --- src/commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands.js b/src/commands.js index 2ccf072..d0cfb8f 100644 --- a/src/commands.js +++ b/src/commands.js @@ -480,7 +480,7 @@ async function cmdRoleRemoveAll(interaction) { return database.transaction(async trx => { let removed; try { - removed = await database.removeAllRoleReacts(message.id); + removed = await database.removeAllRoleReacts(message.id, trx); await message.reactions.removeAll(); } catch (err) { logger.error(`Could not remove all reacts from ${stringify(message)}`, err); From 6e5feb74384ee11241054738bba4107fe29073a2 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 3 Feb 2022 01:30:16 -0500 Subject: [PATCH 090/107] Make database.removeRoleReact accept emojis and roles --- src/database.js | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/database.js b/src/database.js index 36ae5bd..5a2d2c4 100644 --- a/src/database.js +++ b/src/database.js @@ -67,6 +67,15 @@ function _assertDiscordId(value) { } } +/** + * Simple assert to ensure value is a valid Emoji string or Discord ID. + */ +function _assertEmojiKey(value) { + if (!isDiscordId(value) && !isEmojiStr(value)) { + throw Error(`Invalid Emoji key: ${value}`); + } +} + /** * A pass-through for knex.transaction(...) that suppresses errors we have * already handled. @@ -127,12 +136,33 @@ function addRoleReact(args, trx) { /** * Removes an emoji->role mapping for the given message. + * At least one of emoji_id or role_id must be provided. Mappings will be + * removed based on the data provided (e.g. if an emoji is provided, all + * mappings for that emoji are removed). */ function removeRoleReact(args, trx) { - const fields = _pickAndAssertFields(args, { - message_id: DISCORD_ASSERT, - emoji_id: EMOJI_ASSERT, - }); + const fields = {}; + + const message_id = args.message_id; + const emoji_id = args.emoji_id; + const role_id = args.role_id; + + _assertDiscordId(message_id); + fields.message_id = message_id; + + if (!emoji_id && !role_id) { + throw new Error('Need one of emoji_id or role_id'); + } + + if (emoji_id) { + _assertEmojiKey(emoji_id); + fields.emoji_id = emoji_id; + } + + if (role_id) { + _assertDiscordId(role_id); + fields.role_id = role_id; + } return (trx ? trx(REACTS) : knex(REACTS)).where(fields).del(); } From 63b993e4c388bd03bb2fd69e2f1a0168759c51eb Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sat, 5 Feb 2022 04:20:17 -0500 Subject: [PATCH 091/107] Adjust database.getRoleReactMap to use a MultiMap --- package-lock.json | 11 +++++++++++ package.json | 1 + src/commands.js | 3 ++- src/database.js | 11 +++++------ src/util.js | 11 +++++++++++ 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7ce3063..0ab1f5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", + "multimap": "^1.1.0", "node-cache": "^5.1.2", "sqlite3": "^4.2.0", "winston": "^3.3.3" @@ -1732,6 +1733,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/multimap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz", + "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==" + }, "node_modules/nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", @@ -4231,6 +4237,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "multimap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz", + "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==" + }, "nan": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", diff --git a/package.json b/package.json index e571741..43d5c84 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "discord.js": "^13.3.1", "knex": "^0.20.13", "lodash": "^4.17.20", + "multimap": "^1.1.0", "node-cache": "^5.1.2", "sqlite3": "^4.2.0", "winston": "^3.3.3" diff --git a/src/commands.js b/src/commands.js index d0cfb8f..8d295b4 100644 --- a/src/commands.js +++ b/src/commands.js @@ -41,6 +41,7 @@ const logger = require('./logger'); const { asLines, emojiToKey, + entries, ephemEdit, ephemReply, stringify, @@ -682,7 +683,7 @@ async function cmdCopyMappings(interaction) { return database.transaction(async trx => { const mapping = await database.getRoleReactMap(msg_from.id, trx); - for await (const [emoji_id, role_id] of mapping.entries()) { + for await (const [emoji_id, role_id] of entries(mapping)) { try { await database.addRoleReact({ guild_id: guild.id, diff --git a/src/database.js b/src/database.js index 5a2d2c4..2fa4e95 100644 --- a/src/database.js +++ b/src/database.js @@ -9,6 +9,7 @@ const knexfile = require('./knexfile'); const knex = require('knex')(knexfile[process.env.NODE_ENV || 'development']); const lodash = require('lodash'); +const MultiMap = require('multimap'); const logger = require('./logger'); const { @@ -192,18 +193,16 @@ function getRoleReact(args) { } /** - * Returns the emoji->role mapping for the given message as a Map object, or - * null if the given message has no react roles set up. + * Returns the emoji->role mapping for the given message as a MultiMap. */ function getRoleReactMap(message_id, trx) { _assertDiscordId(message_id); return (trx ? trx(REACTS) : knex(REACTS)) .select(['emoji_id', 'role_id']) .where('message_id', message_id) - .then(rows => rows.length > 0 - ? new Map(rows.map(({ emoji_id, role_id }) => [emoji_id, role_id])) - : null - ); + .then(rows => new MultiMap( + rows.map(({emoji_id, role_id}) => [emoji_id, role_id]) + )); } /** diff --git a/src/util.js b/src/util.js index 4139663..47e666c 100644 --- a/src/util.js +++ b/src/util.js @@ -68,6 +68,16 @@ function emojiToKey(emoji) { return emoji?.id ?? emoji?.name ?? emoji; } +/** + * Flattens a MultiMap to an array of emoji-role pairs. + */ + function entries(mmap) { + return Array.from(mmap.keys()).reduce((arr, emoji_key) => { + arr.push(...mmap.get(emoji_key).map(role_id => [emoji_key, role_id])); + return arr; + }, new Array()); +} + /** * Same as {@link ephemReply}, but to edit an existing ephemeral response. */ @@ -177,6 +187,7 @@ module.exports = { asLines, detail, emojiToKey, + entries, ephemEdit, ephemReply, isDiscordId, From 725a6a43df3eafdbd65abcd9ce93310843e81ee9 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sat, 5 Feb 2022 06:02:14 -0500 Subject: [PATCH 092/107] role remove can now take emojis and roles --- src/commands.js | 75 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/src/commands.js b/src/commands.js index 8d295b4..2e57c65 100644 --- a/src/commands.js +++ b/src/commands.js @@ -30,6 +30,7 @@ const { SlashCommandRegistry, bold, codeBlock, + roleMention, } = require('discord-command-registry'); const Discord = require('discord.js'); const NodeCache = require('node-cache'); @@ -142,7 +143,12 @@ const REGISTRY = new SlashCommandRegistry() .addStringOption(option => option .setName('emoji') .setDescription('The emoji mapping to remove') - .setRequired(true) + .setRequired(false) + ) + .addRoleOption(option => option + .setName('role') + .setDescription('The role mapping to remove') + .setRequired(false) ) ) .addSubcommand(subcommand => subcommand @@ -423,51 +429,74 @@ async function cmdRoleAdd(interaction) { * Removes an emoji mapping from the currently selected message. */ async function cmdRoleRemove(interaction) { - const emoji = Options.getEmoji(interaction, 'emoji', true); + const emoji = Options.getEmoji(interaction, 'emoji', false); + const role = interaction.options.getRole('role', false); let message = SELECTED_MESSAGE_CACHE.get(interaction.user.id); if (!message) { return ephemReply(interaction, 'No message selected! Select a message first.'); } - if (!emoji) { - return ephemReply(interaction, 'Not a valid emoji!'); + if (!emoji && !role) { + return ephemReply(interaction, 'You must specify an emoji or a role (or both)!'); } message = await message.fetch(); return database.transaction(async trx => { - let removed; + // Need to reply to keep the interaction token alive while we delete + await ephemReply(interaction, 'Removing, this may take a moment...'); + + let map_before; + const db_data = { + message_id: message.id, + emoji_id: emoji ? emojiToKey(emoji) : undefined, + role_id: role?.id, + }; try { - const emoji_id = emojiToKey(emoji); - - // Intentionally NOT removing this role from users who currently have it - await database.removeRoleReact({ - message_id: message.id, - emoji_id: emoji_id, - }, trx); - removed = await message.reactions.cache.get(emoji_id)?.remove(); + map_before = await database.getRoleReactMap(message.id, trx); + // Intentionally NOT removing roles from users who currently have them + await database.removeRoleReact(db_data, trx); } catch (err) { - logger.error( - `Could not remove ${stringify(emoji)} from ${stringify(message)}`, - err - ); - await ephemReply(interaction, - 'I could not remove the react. Do I have the right permissions?' + logger.error(`Database failed to remove mappings ${stringify(db_data)}`, err); + await ephemEdit(interaction, 'Something went wrong. Try again?'); + rethrowHandled(err); + } + + let map_after; + try { + map_after = await database.getRoleReactMap(message.id, trx); + await Promise.all(message.reactions.cache + .filter((_, msg_emoji) => !map_after.has(msg_emoji)) + .map(react => react.remove())); + } catch (err) { + logger.error(`Could not remove reacts from ${stringify(message)}`, err); + await ephemEdit(interaction, + 'I could not remove the react(s). Do I have the right permissions?' ); rethrowHandled(err); } - return ephemReply(interaction, - removed - ? `Removed ${emoji} from ${stringify(message)}` - : `Selected message does not have ${emoji} reaction! ${message.url}` + entries(map_after).forEach( + ([emoji_key, role_id]) => map_before.delete(emoji_key, role_id) + ); + const removed_pairs = entries(map_before); + + return ephemEdit(interaction, removed_pairs + ? 'Selected message has no mappings for the given emoji and/or role!' + : `Removed mappings:\n${ + removed_pairs.map(([emoji_id, role_id]) => { + const emoji_str = interaction.client.emojis.resolve(emoji_id) ?? emoji_id; + return `${emoji_str} -> ${roleMention(role_id)}` + }).join('\n') + }\nFrom ${stringify(message)}` ); }); } /** * Removes all emoji mappings from the currently selected message. + * This remains a separate function to avoid accidentally nuking a message. */ async function cmdRoleRemoveAll(interaction) { let message = SELECTED_MESSAGE_CACHE.get(interaction.user.id); From 4671aad569d7a825c066cc8331f92e38fe789e09 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sat, 5 Feb 2022 06:10:01 -0500 Subject: [PATCH 093/107] Custom reports for copying a message to itself and copying nothing --- src/commands.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/commands.js b/src/commands.js index 2e57c65..712c239 100644 --- a/src/commands.js +++ b/src/commands.js @@ -695,6 +695,10 @@ async function cmdCopyMappings(interaction) { ); } + if (msg_from === msg_copy) { + return ephemReply(interaction, 'Cannot copy a message to itself!'); + } + msg_from = await msg_from.fetch(); msg_copy = await msg_copy.fetch(); @@ -738,11 +742,12 @@ async function cmdCopyMappings(interaction) { } } - return ephemEdit(interaction, - 'Copied react-role mappings.\n' + - `Source: ${msg_from.url}\n` + - `Target: ${msg_copy.url}\n` + - 'You can delete the original message now.' + return ephemEdit(interaction, mapping.size === 0 + ? 'Selected message has no mappings!' + : 'Copied react-role mappings.\n' + + `Source: ${msg_from.url}\n` + + `Target: ${msg_copy.url}\n` + + 'You can delete the original message now.' ); }); } From 3151c48d1af9ad34662d929569e42ca4274812b5 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Sat, 5 Feb 2022 06:10:40 -0500 Subject: [PATCH 094/107] npm audit fix --- package-lock.json | 64 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0ab1f5e..5865ee6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1801,11 +1801,22 @@ } }, "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/node-pre-gyp": { @@ -2668,6 +2679,11 @@ "node": ">=0.10.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, "node_modules/triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", @@ -2798,6 +2814,20 @@ "node": ">=0.10.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -4294,9 +4324,12 @@ } }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } }, "node-pre-gyp": { "version": "0.11.0", @@ -4982,6 +5015,11 @@ "repeat-string": "^1.6.1" } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, "triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", @@ -5082,6 +5120,20 @@ "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=" }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", From d82ccb286d08388290fcea81ff7099ae3a927691 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Mon, 21 Feb 2022 17:13:58 -0500 Subject: [PATCH 095/107] Prevent adding mutex-conflicting role mappings --- src/commands.js | 23 +++++++++++++++++++++-- src/database.js | 7 ++++--- src/util.js | 2 +- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/commands.js b/src/commands.js index 712c239..186e194 100644 --- a/src/commands.js +++ b/src/commands.js @@ -396,10 +396,29 @@ async function cmdRoleAdd(interaction) { } return database.transaction(async trx => { + const emoji_key = emojiToKey(emoji); + + const mapping = await database.getRoleReactMap(message.id, trx); + const mutex_roles = await database.getMutexRoles({ + guild_id: interaction.guild.id, + role_id: role.id, + }, trx); + if (mutex_roles.find(mrole_id => mapping.has(emoji_key, mrole_id))) { + const conflicting = mutex_roles.filter( + mrole_id => mapping.has(emoji_key, mrole_id) + ); + return await ephemReply(interaction, unindent( + `Cannot add emoji-role mapping because it conflicts with + mutually exclusive roles mapped to this emoji.\n + Conflicting roles: + ${conflicting.map(mrole_id => roleMention(mrole_id)).join(', ')}` + )); + } + const db_data = { guild_id: interaction.guild.id, message_id: message.id, - emoji_id: emojiToKey(emoji), + emoji_id: emoji_key, role_id: role.id, }; @@ -407,7 +426,7 @@ async function cmdRoleAdd(interaction) { await database.addRoleReact(db_data, trx); } catch (err) { logger.error(`Database failed to create ${stringify(db_data)}`, err); - await ephemReply(interaction, 'Something went wrong'); + await ephemReply(interaction, 'Something went wrong. Try again?'); rethrowHandled(err); } diff --git a/src/database.js b/src/database.js index 2fa4e95..0cc9e5c 100644 --- a/src/database.js +++ b/src/database.js @@ -354,7 +354,7 @@ function removeMutexRole(args) { * for the given guild. If no roles are mutually exclusive, an empty array is * returned. */ -function getMutexRoles(args) { +function getMutexRoles(args, trx) { const fields = _pickAndAssertFields(args, { guild_id: DISCORD_ASSERT, role_id: DISCORD_ASSERT, @@ -362,12 +362,13 @@ function getMutexRoles(args) { // Roles could be added in either order, so fetch with both orders and // combine the results. + const builder = trx ? trx : knex; return Promise.all([ - knex(MUTEX).select('role_id_1').where({ + builder(MUTEX).select('role_id_1').where({ guild_id: fields.guild_id, role_id_2: fields.role_id }), - knex(MUTEX).select('role_id_2').where({ + builder(MUTEX).select('role_id_2').where({ guild_id: fields.guild_id, role_id_1: fields.role_id }) diff --git a/src/util.js b/src/util.js index 47e666c..9762032 100644 --- a/src/util.js +++ b/src/util.js @@ -69,7 +69,7 @@ function emojiToKey(emoji) { } /** - * Flattens a MultiMap to an array of emoji-role pairs. + * Flattens a MultiMap to an array of emoji-role pairs. */ function entries(mmap) { return Array.from(mmap.keys()).reduce((arr, emoji_key) => { From dbb10718b8aea6afcda3d94a09e3fbb44f687164 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 23 Feb 2022 19:55:29 -0500 Subject: [PATCH 096/107] Some proofreading fixes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c66f0dd..c527147 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ and use Discord's fancy context menu to select it. This is tracked per-user, so multiple users can interact with the bot at the same time. Due to current Discord limitations, context menus are not available on mobile -devices (sorry). See below for alternative. +devices (sorry). See below for an alternative. ![](docs/select.png) @@ -111,7 +111,7 @@ You can use `/reset-everything` to remove *all* configuration the bot has for the guild the command was sent from. The bot does this automatically when it is kicked from a guild. -This does not clear any server-side logs for to the guild. +This does not clear any server-side logs for the guild. ## Printing Bot Info You can use `/info` to print the bot's description, version number, link to the From d622bfd32114b19e912bb4dabde5b47852b22db5 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 23 Feb 2022 21:29:01 -0500 Subject: [PATCH 097/107] Fix inaccurate reporting for adding and removing role mappings --- src/commands.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/commands.js b/src/commands.js index 186e194..caf9b27 100644 --- a/src/commands.js +++ b/src/commands.js @@ -407,12 +407,11 @@ async function cmdRoleAdd(interaction) { const conflicting = mutex_roles.filter( mrole_id => mapping.has(emoji_key, mrole_id) ); - return await ephemReply(interaction, unindent( - `Cannot add emoji-role mapping because it conflicts with - mutually exclusive roles mapped to this emoji.\n - Conflicting roles: - ${conflicting.map(mrole_id => roleMention(mrole_id)).join(', ')}` - )); + return await ephemReply(interaction, unindent(` + Cannot add emoji-role mapping because it conflicts with mutually + exclusive roles mapped to this emoji! Conflicting roles: + ${conflicting.map(mrole_id => roleMention(mrole_id)).join(', ')} + `)); } const db_data = { @@ -501,7 +500,7 @@ async function cmdRoleRemove(interaction) { ); const removed_pairs = entries(map_before); - return ephemEdit(interaction, removed_pairs + return ephemEdit(interaction, removed_pairs.length === 0 ? 'Selected message has no mappings for the given emoji and/or role!' : `Removed mappings:\n${ removed_pairs.map(([emoji_id, role_id]) => { From c27d307be41da6fb8ccffe718e45352b69cfb2ee Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 23 Feb 2022 22:14:32 -0500 Subject: [PATCH 098/107] Warn when mapping multiple emojis to the same role --- src/commands.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/commands.js b/src/commands.js index caf9b27..2cee92c 100644 --- a/src/commands.js +++ b/src/commands.js @@ -439,7 +439,14 @@ async function cmdRoleAdd(interaction) { rethrowHandled(err); } - return ephemReply(interaction, `Mapped ${emoji} to ${role} on ${stringify(message)}`); + let response = `Mapped ${emoji} to ${role} on ${stringify(message)}`; + const also_mapped = entries(mapping) + .filter(([eid, rid]) => eid !== emoji_key && rid === role.id) + .map(([eid, _]) => message.reactions.resolve(eid).emoji); + if (also_mapped.length > 0) { + response += `\nNote: also mapped to ${also_mapped.join(' ')}`; + } + return ephemReply(interaction, response); }); } From 1de07d35418543e8a4526805c3916e35f1b52630 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 23 Feb 2022 22:23:09 -0500 Subject: [PATCH 099/107] Fix 'UNIQUE constraint failed' error on addRoleReact update --- src/database.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database.js b/src/database.js index 0cc9e5c..45ee7fc 100644 --- a/src/database.js +++ b/src/database.js @@ -127,7 +127,7 @@ function addRoleReact(args, trx) { .catch(err => { if (err.message.includes('UNIQUE constraint failed')) { return (trx ? trx(REACTS) : knex(REACTS)) - .where(lodash.pick(fields, ['message_id', 'emoji_id'])) + .where(lodash.pick(fields, ['message_id', 'emoji_id', 'role_id'])) .update({ role_id: fields.role_id }); } else { throw err; From 202bb36989c40e098e47683f04d598a8ed0c3e67 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Mon, 18 Apr 2022 22:36:57 -0400 Subject: [PATCH 100/107] Update SQLite3 dependency --- package-lock.json | 1985 +++++++++++++++++++++++++++++++++------------ package.json | 2 +- 2 files changed, 1456 insertions(+), 531 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5865ee6..9dcb6c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "lodash": "^4.17.20", "multimap": "^1.1.0", "node-cache": "^5.1.2", - "sqlite3": "^4.2.0", + "sqlite3": "^5.0.4", "winston": "^3.3.3" } }, @@ -112,6 +112,66 @@ "node": ">= 6" } }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "optional": true + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", + "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@sapphire/async-queue": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.9.tgz", @@ -142,6 +202,15 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "optional": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/@types/node": { "version": "16.11.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", @@ -180,26 +249,80 @@ "node": ">=6.5" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", + "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "optional": true, + "dependencies": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "node_modules/are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "dependencies": { "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/arr-diff": { @@ -280,9 +403,9 @@ } }, "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base": { "version": "0.11.2", @@ -387,6 +510,47 @@ "node": ">=0.10.0" } }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -415,9 +579,12 @@ } }, "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } }, "node_modules/class-utils": { "version": "0.3.6", @@ -444,6 +611,15 @@ "node": ">=0.10.0" } }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", @@ -452,14 +628,6 @@ "node": ">=0.8" } }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -503,6 +671,14 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colorette": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", @@ -589,14 +765,6 @@ "node": ">=0.10" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -657,6 +825,15 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", @@ -666,14 +843,11 @@ } }, "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", "engines": { - "node": ">=0.10" + "node": ">=8" } }, "node_modules/discord-api-types": { @@ -763,11 +937,40 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/enabled": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "optional": true + }, "node_modules/esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -1066,11 +1269,14 @@ } }, "node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dependencies": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, "node_modules/fs.realpath": { @@ -1079,18 +1285,22 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", "dependencies": { - "aproba": "^1.0.3", + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" } }, "node_modules/get-value": { @@ -1107,9 +1317,9 @@ "integrity": "sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA==" }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1153,6 +1363,12 @@ "node": ">=0.10.0" } }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "optional": true + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -1205,25 +1421,83 @@ "node": ">=0.10.0" } }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "optional": true + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "dependencies": { - "minimatch": "^3.0.4" + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "optional": true, + "engines": { + "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "optional": true + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1251,6 +1525,12 @@ "node": ">= 0.10" } }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "optional": true + }, "node_modules/is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", @@ -1355,14 +1635,11 @@ } }, "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dependencies": { - "number-is-nan": "^1.0.0" - }, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/is-glob": { @@ -1376,6 +1653,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", + "optional": true + }, "node_modules/is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -1589,6 +1872,66 @@ "triple-beam": "^1.3.0" } }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -1662,9 +2005,9 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1678,20 +2021,91 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "optional": true, "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dependencies": { - "minipass": "^2.9.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" } }, "node_modules/mixin-deep": { @@ -1738,11 +2152,6 @@ "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz", "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==" }, - "node_modules/nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" - }, "node_modules/nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -1764,30 +2173,19 @@ "node": ">=0.10.0" } }, - "node_modules/needle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.3.tgz", - "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==", - "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "optional": true, "engines": { - "node": ">= 4.4.x" + "node": ">= 0.6" } }, - "node_modules/needle/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dependencies": { - "ms": "^2.1.1" - } + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" }, "node_modules/node-cache": { "version": "5.1.2", @@ -1819,79 +2217,129 @@ } } }, - "node_modules/node-pre-gyp": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", - "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", - "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "optional": true, "dependencies": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" }, "bin": { - "node-pre-gyp": "bin/node-pre-gyp" + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" } }, - "node_modules/nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", + "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", + "optional": true, "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" }, - "bin": { - "nopt": "bin/nopt.js" + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" } }, - "node_modules/npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "optional": true, "dependencies": { - "npm-normalize-package-bin": "^1.0.1" + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.1.tgz", + "integrity": "sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg==", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.0", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } }, - "node_modules/npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "node_modules/node-gyp/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, "dependencies": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "node_modules/node-gyp/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "optional": true, "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" } }, "node_modules/object-assign": { @@ -2001,31 +2449,6 @@ "fn.name": "1.x.x" } }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "node_modules/ow": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", @@ -2045,6 +2468,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -2124,25 +2562,25 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "optional": true, "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "err-code": "^2.0.2", + "retry": "^0.12.0" }, - "bin": { - "rc": "cli.js" + "engines": { + "node": ">=10" } }, - "node_modules/rc/node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, "node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -2233,15 +2671,27 @@ "node": ">=0.12" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "optional": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/safe-buffer": { @@ -2265,19 +2715,21 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/set-blocking": { @@ -2311,9 +2763,9 @@ } }, "node_modules/signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/simple-swizzle": { "version": "0.2.2", @@ -2323,6 +2775,16 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -2457,6 +2919,51 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/socks": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "optional": true, + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.0.tgz", + "integrity": "sha512-wWqJhjb32Q6GsrUqzuFkukxb/zzide5quXYcMVpIjxalDBBYy2nqKCFQ/9+Ie4dvOYSQdOk3hUlZSdzZOd3zMQ==", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -2494,13 +3001,37 @@ } }, "node_modules/sqlite3": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", - "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.4.tgz", + "integrity": "sha512-ATvAe7JutFv/d+KTbLS58KsKn/t1raL/WGn2qZfZxwsrL/oGSP+0OlbQ2tX5jISvyu6/7JuKze3WkaiP1JAH6A==", "hasInstallScript": true, "dependencies": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.11.0" + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^4.2.0", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" } }, "node_modules/stack-trace": { @@ -2543,73 +3074,56 @@ } }, "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" } }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "dependencies": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - }, - "engines": { - "node": ">=4.5" - } - }, - "node_modules/tar/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/tarn": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tarn/-/tarn-2.0.0.tgz", @@ -2732,6 +3246,24 @@ "node": ">=0.10.0" } }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, "node_modules/unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -2840,11 +3372,11 @@ } }, "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dependencies": { - "string-width": "^1.0.2 || 2" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, "node_modules/winston": { @@ -2917,9 +3449,9 @@ } }, "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/zod": { "version": "3.11.6", @@ -3005,6 +3537,56 @@ } } }, + "@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "optional": true + }, + "@mapbox/node-pre-gyp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", + "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + } + }, + "@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "optional": true, + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "optional": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true + } + } + }, "@sapphire/async-queue": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.9.tgz", @@ -3020,6 +3602,12 @@ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==" }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "optional": true + }, "@types/node": { "version": "16.11.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", @@ -3055,23 +3643,64 @@ "event-target-shim": "^5.0.0" } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", + "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "optional": true, + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "optional": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "requires": { "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "arr-diff": { @@ -3125,9 +3754,9 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base": { "version": "0.11.2", @@ -3215,6 +3844,40 @@ } } }, + "cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "optional": true, + "requires": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3237,9 +3900,9 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, "class-utils": { "version": "0.3.6", @@ -3262,16 +3925,17 @@ } } }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "optional": true + }, "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -3312,6 +3976,11 @@ "simple-swizzle": "^0.2.2" } }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "colorette": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", @@ -3382,11 +4051,6 @@ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -3434,15 +4098,21 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "optional": true + }, "detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" }, "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" }, "discord-api-types": { "version": "0.24.0", @@ -3509,11 +4179,37 @@ "is-obj": "^2.0.0" } }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "enabled": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "optional": true + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "optional": true + }, "esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -3751,11 +4447,11 @@ } }, "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "requires": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" } }, "fs.realpath": { @@ -3764,18 +4460,19 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", "requires": { - "aproba": "^1.0.3", + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" } }, "get-value": { @@ -3789,9 +4486,9 @@ "integrity": "sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA==" }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3823,6 +4520,12 @@ "which": "^1.2.14" } }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "optional": true + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -3865,22 +4568,68 @@ "parse-passwd": "^1.0.0" } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "optional": true + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "optional": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" } }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "optional": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, "requires": { - "minimatch": "^3.0.4" + "safer-buffer": ">= 2.1.2 < 3.0.0" } }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "optional": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "optional": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "optional": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3905,6 +4654,12 @@ "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.0.0.tgz", "integrity": "sha512-e0/LknJ8wpMMhTiWcjivB+ESwIuvHnBSlBbmP/pSb8CQJldoj1p2qv7xGZ/+BtbTziYRFSz8OsvdbiX45LtYQA==" }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "optional": true + }, "is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", @@ -3988,12 +4743,9 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { "version": "4.0.1", @@ -4003,6 +4755,12 @@ "is-extglob": "^2.1.1" } }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", + "optional": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -4151,6 +4909,53 @@ "triple-beam": "^1.3.0" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "optional": true, + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + } + }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -4206,9 +5011,9 @@ } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } @@ -4219,20 +5024,68 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "optional": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "optional": true, + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "optional": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "optional": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "optional": true, "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "minipass": "^3.0.0" } }, "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "requires": { - "minipass": "^2.9.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" } }, "mixin-deep": { @@ -4272,11 +5125,6 @@ "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz", "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==" }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -4295,25 +5143,16 @@ "to-regex": "^3.0.1" } }, - "needle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.3.tgz", - "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==", - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "optional": true + }, + "node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" }, "node-cache": { "version": "5.1.2", @@ -4331,71 +5170,103 @@ "whatwg-url": "^5.0.0" } }, - "node-pre-gyp": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", - "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", + "node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "optional": true, "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "dependencies": { + "are-we-there-yet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", + "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "optional": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "npmlog": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.1.tgz", + "integrity": "sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg==", + "optional": true, + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.0", + "set-blocking": "^2.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "optional": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" - }, - "npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" + "abbrev": "1" } }, "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4481,25 +5352,6 @@ "fn.name": "1.x.x" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "ow": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", @@ -4513,6 +5365,15 @@ "vali-date": "^1.0.0" } }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "optional": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -4571,22 +5432,20 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "optional": true + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "optional": true, "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - } + "err-code": "^2.0.2", + "retry": "^0.12.0" } }, "readable-stream": { @@ -4657,10 +5516,16 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "optional": true + }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { "glob": "^7.1.3" } @@ -4686,17 +5551,16 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } }, "set-blocking": { "version": "2.0.0", @@ -4725,9 +5589,9 @@ } }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "simple-swizzle": { "version": "0.2.2", @@ -4737,6 +5601,12 @@ "is-arrayish": "^0.3.1" } }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -4847,6 +5717,38 @@ } } }, + "socks": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "optional": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.0.tgz", + "integrity": "sha512-wWqJhjb32Q6GsrUqzuFkukxb/zzide5quXYcMVpIjxalDBBYy2nqKCFQ/9+Ie4dvOYSQdOk3hUlZSdzZOd3zMQ==", + "optional": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, + "requires": { + "ms": "2.1.2" + } + } + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -4878,12 +5780,23 @@ } }, "sqlite3": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", - "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.4.tgz", + "integrity": "sha512-ATvAe7JutFv/d+KTbLS58KsKn/t1raL/WGn2qZfZxwsrL/oGSP+0OlbQ2tX5jISvyu6/7JuKze3WkaiP1JAH6A==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^4.2.0", + "node-gyp": "8.x", + "tar": "^6.1.11" + } + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "optional": true, "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.11.0" + "minipass": "^3.1.1" } }, "stack-trace": { @@ -4919,46 +5832,40 @@ } }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.1" } }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, "tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", - "requires": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" } } }, @@ -5056,6 +5963,24 @@ "set-value": "^2.0.1" } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "optional": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "optional": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -5143,11 +6068,11 @@ } }, "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "requires": { - "string-width": "^1.0.2 || 2" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, "winston": { @@ -5199,9 +6124,9 @@ "requires": {} }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "zod": { "version": "3.11.6", diff --git a/package.json b/package.json index 43d5c84..c2802ac 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lodash": "^4.17.20", "multimap": "^1.1.0", "node-cache": "^5.1.2", - "sqlite3": "^4.2.0", + "sqlite3": "^5.0.4", "winston": "^3.3.3" }, "scripts": { From 45d66691774011ca282b965bc84be9f67de80e75 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Mon, 18 Apr 2022 22:52:19 -0400 Subject: [PATCH 101/107] Add multiple roles on react. NOTE: onReactionRemove is broken with this change --- src/database.js | 11 +++++------ src/events.js | 27 +++++++++++++++------------ src/util.js | 3 +++ 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/database.js b/src/database.js index 45ee7fc..8806b50 100644 --- a/src/database.js +++ b/src/database.js @@ -177,19 +177,18 @@ function removeAllRoleReacts(message_id, trx) { } /** - * Returns the role for the given emoji on the given message, or null if there - * is no role associated with the emoji on the message. + * Returns the roles as an Array for the given emoji on the given message. */ -function getRoleReact(args) { +function getRoleReacts(args) { const fields = _pickAndAssertFields(args, { message_id: DISCORD_ASSERT, emoji_id: EMOJI_ASSERT, }); return knex(REACTS) - .first('role_id') + .select('role_id') .where(fields) - .then(result => result ? result.role_id : null); + .then(results => results.map(row => row.role_id)); } /** @@ -402,7 +401,7 @@ module.exports = { addRoleReact, removeRoleReact, removeAllRoleReacts, - getRoleReact, + getRoleReacts, getRoleReactMap, isRoleReactMessage, getRoleReactMessages, diff --git a/src/events.js b/src/events.js index f8483f9..c0b3fe5 100644 --- a/src/events.js +++ b/src/events.js @@ -6,6 +6,7 @@ * License v3.0. See LICENSE or * for more information. ******************************************************************************/ +const lodash = require('lodash'); const Perms = require('discord.js').Permissions.FLAGS; const commands = require('./commands'); @@ -123,9 +124,9 @@ async function onMessageDelete(message) { /** * Event handler for when a reaction is added to a message. - * Checks if the message has any reaction roles configured. If so, adds that - * role to the user who added the reaction. Removes any reaction that doesn't - * correspond to a role. + * Checks if the message has any reaction roles configured for the given emoji. + * If so, adds that role (or roles) to the user who added the reaction. + * Removes any reaction that doesn't correspond to a role. */ async function onReactionAdd(reaction, react_user) { logger.debug(`Added ${detail(reaction)}`); @@ -140,26 +141,28 @@ async function onReactionAdd(reaction, react_user) { return; } - const role_id = await database.getRoleReact({ + const role_ids = await database.getRoleReacts({ message_id: reaction.message.id, emoji_id: emojiToKey(reaction.emoji), }); // Someone added an emoji that isn't mapped to a role - if (!role_id) { + if (role_ids.length === 0) { return reaction.remove(); } const member = await reaction.message.guild.members.fetch(react_user.id); // Remove mutually exclusive roles from user - const mutex_roles = await database.getMutexRoles({ - guild_id: reaction.message.guild.id, - role_id: role_id, - }); + const mutex_roles = lodash.flatMap( + await Promise.all(role_ids.map(role_id => database.getMutexRoles({ + guild_id: reaction.message.guild.id, + role_id: role_id, + }))) + ); try { await member.roles.remove(mutex_roles, 'Role bot removal (mutex)'); - await member.roles.add(role_id, 'Role bot assignment'); + await member.roles.add(role_ids, 'Role bot assignment'); } catch (err) { logger.warn(`Failed to update roles on ${stringify(react_user)}`, err); } @@ -174,9 +177,9 @@ async function onReactionAdd(reaction, react_user) { } // Track assignment number for fun - await database.incrementAssignCounter(); + await database.incrementAssignCounter(role_ids.length); - logger.info(`Added Role ${role_id} to ${detail(react_user)}`); + logger.info(`Added Roles ${stringify(role_ids)} to ${stringify(react_user)}`); } /** diff --git a/src/util.js b/src/util.js index 9762032..4ac3850 100644 --- a/src/util.js +++ b/src/util.js @@ -166,6 +166,9 @@ function stringify(thing) { const user = thing; return `User ${user.id}`; } + else if (Array.isArray(thing)) { + return thing.map(t => stringify(t)).join(', '); + } else if (typeof thing === 'string' || thing instanceof String) { return thing; } From 16cd4086411a52e0bf3ffc3a2030fa33483df304 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Mon, 18 Apr 2022 23:20:28 -0400 Subject: [PATCH 102/107] Remove multiple roles on react. This fixes onReactionRemove. --- src/events.js | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/events.js b/src/events.js index c0b3fe5..e70ad6d 100644 --- a/src/events.js +++ b/src/events.js @@ -184,10 +184,11 @@ async function onReactionAdd(reaction, react_user) { /** * Event handler for when a reaction is removed from a message. - * Checks if the message has any reaction roles configured. If so, removes that - * role from the user whose reaction was removed. Also re-adds the bot's - * reaction if it is removed while a react-role is active. + * Checks if the message has any reaction roles configured for the given emoji. + * If so, removes that role (or roles) from the user whose reaction was removed. + * Also re-adds the bot's reaction if it is removed while a react-role is active. * + * NOTE: * This is only fired when a single reaction is removed, either by clicking on * an emoji or through the message's "reactions" context menu. It is NOT fired * when a bot removes all reactions (Discord uses a seprate event for that). @@ -200,19 +201,20 @@ async function onReactionAdd(reaction, react_user) { async function onReactionRemove(reaction, react_user) { logger.debug(`Removed ${detail(reaction)}`); - // TODO How do we handle two emojis mapped to the same role? - // Do we only remove the role if the user doesn't have any of the mapped - // reactions? Or do we remove when any of the emojis are un-reacted? + // TODO Maybe be a little smarter about how we remove roles when multiple + // emojis map to that role. Currently we remove the roll when a single emoji + // mapped to it is removed. Maybe we should wait until all emojis mapped to + // it are removed? const emoji = reaction.emoji; - const role_id = await database.getRoleReact({ + const role_ids = await database.getRoleReacts({ message_id: reaction.message.id, emoji_id: emojiToKey(emoji), }); // Ignore reactions on non-role-react posts - if (!role_id) { + if (role_ids.length === 0) { return; } @@ -223,11 +225,11 @@ async function onReactionRemove(reaction, react_user) { try { const member = await reaction.message.guild.members.fetch(react_user.id); - await member.roles.remove(role_id, 'Role bot removal'); - logger.info(`Removed Role ${role_id} from ${stringify(react_user)}`); + await member.roles.remove(role_ids, 'Role bot removal'); + logger.info(`Removed Roles ${stringify(role_ids)} from ${stringify(react_user)}`); } catch (err) { logger.error( - `Failed to remove Role ${role_id} from ${stringify(react_user)}`, + `Failed to remove Roles ${stringify(role_ids)} from ${stringify(react_user)}`, err ); } From 6ffcf8a4efd1296e9cbf69c48d4ef2dedfc6d292 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 19 Apr 2022 01:13:03 -0400 Subject: [PATCH 103/107] Update packages --- package-lock.json | 3872 +++++++++++++++++++-------------------------- package.json | 3 +- 2 files changed, 1604 insertions(+), 2271 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9dcb6c6..c39735c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,14 +15,23 @@ "lodash": "^4.17.20", "multimap": "^1.1.0", "node-cache": "^5.1.2", - "sqlite3": "^5.0.4", + "sqlite": "^4.0.25", + "sqlite3": "^4.2.0", "winston": "^3.3.3" } }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/@dabh/diagnostics": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", - "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "dependencies": { "colorspace": "1.1.x", "enabled": "2.0.x", @@ -30,42 +39,34 @@ } }, "node_modules/@discordjs/builders": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.2.tgz", - "integrity": "sha512-/YRd11SrcluqXkKppq/FAVzLIPRVlIVmc6X8ZklspzMIHDtJ+A4W37D43SHvLdH//+NnK+SHW/WeOF4Ts54PeQ==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.9.0.tgz", + "integrity": "sha512-XM/5yrTxMF0SDKza32YzGDQO1t+qEJTaF8Zvxu/UOjzoqzMPPGQBjC1VgZxz8/CBLygW5qI+UVygMa88z13G3g==", "dependencies": { "@sindresorhus/is": "^4.2.0", "discord-api-types": "^0.24.0", - "ow": "^0.27.0", "ts-mixer": "^6.0.0", - "tslib": "^2.3.1" + "tslib": "^2.3.1", + "zod": "^3.11.6" }, "engines": { "node": ">=16.0.0", "npm": ">=7.0.0" } }, - "node_modules/@discordjs/collection": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.3.2.tgz", - "integrity": "sha512-dMjLl60b2DMqObbH1MQZKePgWhsNe49XkKBZ0W5Acl5uVV43SN414i2QfZwRI7dXAqIn8pEWD2+XXQFn9KWxqg==", + "node_modules/@discordjs/builders/node_modules/discord-api-types": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", + "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==", + "deprecated": "No longer supported. Install the latest release!", "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" + "node": ">=12" } }, - "node_modules/@discordjs/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } + "node_modules/@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" }, "node_modules/@discordjs/rest": { "version": "0.1.0-canary.0", @@ -85,11 +86,6 @@ "node": ">=16.0.0" } }, - "node_modules/@discordjs/rest/node_modules/@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" - }, "node_modules/@discordjs/rest/node_modules/discord-api-types": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.18.1.tgz", @@ -99,83 +95,10 @@ "node": ">=12" } }, - "node_modules/@discordjs/rest/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "optional": true - }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", - "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "optional": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "optional": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@sapphire/async-queue": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.9.tgz", - "integrity": "sha512-CbXaGwwlEMq+l1TRu01FJCvySJ1CEFKFclHT48nIfNeZXaAAmmwwy7scUKmYHPUa3GhoMp6Qr1B3eAJux6XgOQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.3.1.tgz", + "integrity": "sha512-FFTlPOWZX1kDj9xCAsRzH5xEJfawg1lNoYAA+ecOWJMHOfiZYb1uXOI3ne9U4UILSEPwfE68p3T9wUHwIQfR0g==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" @@ -192,9 +115,9 @@ } }, "node_modules/@sindresorhus/is": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", - "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", "engines": { "node": ">=10" }, @@ -202,33 +125,37 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "optional": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/@types/node": { - "version": "16.11.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", - "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==" + "version": "17.0.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz", + "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w==" }, "node_modules/@types/node-fetch": { - "version": "2.5.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", - "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==", "dependencies": { "@types/node": "*", "form-data": "^3.0.0" } }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@types/ws": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.1.tgz", - "integrity": "sha512-SqQ+LhVZaJi7c7sYVkjWALDigi/Wy7h7Iu72gkQp8Y8OWw/DddEVBrTSKu86pQftV2+Gm8lYM61hadPKqyaIeg==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", "dependencies": { "@types/node": "*" } @@ -249,80 +176,26 @@ "node": ">=6.5" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", - "optional": true, - "dependencies": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "optional": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "dependencies": { "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "readable-stream": "^2.0.6" } }, "node_modules/arr-diff": { @@ -382,9 +255,9 @@ } }, "node_modules/async": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", - "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" }, "node_modules/asynckit": { "version": "0.4.0", @@ -435,41 +308,6 @@ "node": ">=0.10.0" } }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -510,45 +348,12 @@ "node": ">=0.10.0" } }, - "node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "optional": true, - "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cacache/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, + "node_modules/braces/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, "node_modules/cache-base": { @@ -570,21 +375,10 @@ "node": ">=0.10.0" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "node_modules/class-utils": { "version": "0.3.6", @@ -611,13 +405,69 @@ "node": ">=0.10.0" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "optional": true, + "node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dependencies": { + "kind-of": "^3.0.2" + }, "engines": { - "node": ">=6" + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" } }, "node_modules/clone": { @@ -628,6 +478,14 @@ "node": ">=0.8" } }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -663,35 +521,19 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "node_modules/color-string": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.8.2.tgz", - "integrity": "sha512-w5ZkKRdLsc5NOYsmnpS2DpyRW71npwZGwbRpLrJTuqjfTs2Bhrba7UiV59IX9siBlCPl2pne5NtiwnVWUzvYFA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", + "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colorette": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", "integrity": "sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==" }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/colorspace": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", @@ -744,9 +586,9 @@ } }, "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "node_modules/debug": { "version": "4.1.1", @@ -765,6 +607,14 @@ "node": ">=0.10" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -777,41 +627,6 @@ "node": ">=0.10.0" } }, - "node_modules/define-property/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -825,15 +640,6 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "optional": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", @@ -843,17 +649,21 @@ } }, "node_modules/detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, "engines": { - "node": ">=8" + "node": ">=0.10" } }, "node_modules/discord-api-types": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", - "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.25.2.tgz", + "integrity": "sha512-O243LXxb5gLLxubu5zgoppYQuolapGVWPw3ll0acN0+O8TnPUE2kFp9Bt3sTRYodw8xFIknOVxjSeyWYBpVcEQ==", + "deprecated": "No longer supported. Install the latest release!", "engines": { "node": ">=12" } @@ -871,13 +681,33 @@ "discord.js": "^13.1.0" } }, - "node_modules/discord-command-registry/node_modules/@discordjs/builders": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.9.0.tgz", - "integrity": "sha512-XM/5yrTxMF0SDKza32YzGDQO1t+qEJTaF8Zvxu/UOjzoqzMPPGQBjC1VgZxz8/CBLygW5qI+UVygMa88z13G3g==", + "node_modules/discord.js": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.6.0.tgz", + "integrity": "sha512-tXNR8zgsEPxPBvGk3AQjJ9ljIIC6/LOPjzKwpwz8Y1Q2X66Vi3ZqFgRHYwnHKC0jC0F+l4LzxlhmOJsBZDNg9g==", + "dependencies": { + "@discordjs/builders": "^0.11.0", + "@discordjs/collection": "^0.4.0", + "@sapphire/async-queue": "^1.1.9", + "@types/node-fetch": "^2.5.12", + "@types/ws": "^8.2.2", + "discord-api-types": "^0.26.0", + "form-data": "^4.0.0", + "node-fetch": "^2.6.1", + "ws": "^8.4.0" + }, + "engines": { + "node": ">=16.6.0", + "npm": ">=7.0.0" + } + }, + "node_modules/discord.js/node_modules/@discordjs/builders": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.11.0.tgz", + "integrity": "sha512-ZTB8yJdJKrKlq44dpWkNUrAtEJEq0gqpb7ASdv4vmq6/mZal5kOv312hQ56I/vxwMre+VIkoHquNUAfnTbiYtg==", "dependencies": { "@sindresorhus/is": "^4.2.0", - "discord-api-types": "^0.24.0", + "discord-api-types": "^0.26.0", "ts-mixer": "^6.0.0", "tslib": "^2.3.1", "zod": "^3.11.6" @@ -887,90 +717,28 @@ "npm": ">=7.0.0" } }, - "node_modules/discord-command-registry/node_modules/@discordjs/builders/node_modules/discord-api-types": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", - "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==", - "engines": { - "node": ">=12" - } - }, - "node_modules/discord-command-registry/node_modules/discord-api-types": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.25.2.tgz", - "integrity": "sha512-O243LXxb5gLLxubu5zgoppYQuolapGVWPw3ll0acN0+O8TnPUE2kFp9Bt3sTRYodw8xFIknOVxjSeyWYBpVcEQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/discord.js": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.3.1.tgz", - "integrity": "sha512-zn4G8tL5+tMV00+0aSsVYNYcIfMSdT2g0nudKny+Ikd+XKv7m6bqI7n3Vji0GIRqXDr5ArPaw+iYFM2I1Iw3vg==", - "dependencies": { - "@discordjs/builders": "^0.8.1", - "@discordjs/collection": "^0.3.2", - "@discordjs/form-data": "^3.0.1", - "@sapphire/async-queue": "^1.1.8", - "@types/node-fetch": "^2.5.12", - "@types/ws": "^8.2.0", - "discord-api-types": "^0.24.0", - "node-fetch": "^2.6.1", - "ws": "^8.2.3" - }, + "node_modules/discord.js/node_modules/@discordjs/collection": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.4.0.tgz", + "integrity": "sha512-zmjq+l/rV35kE6zRrwe8BHqV78JvIh2ybJeZavBi5NySjWXqN3hmmAKg7kYMMXSeiWtSsMoZ/+MQi0DiQWy2lw==", "engines": { - "node": ">=16.6.0", + "node": ">=16.0.0", "npm": ">=7.0.0" } }, - "node_modules/dot-prop": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", - "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", - "dependencies": { - "is-obj": "^2.0.0" - }, + "node_modules/discord.js/node_modules/discord-api-types": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz", + "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, "node_modules/enabled": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "optional": true - }, "node_modules/esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -1034,6 +802,79 @@ "node": ">=0.10.0" } }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/expand-brackets/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1067,17 +908,6 @@ "node": ">=0.10.0" } }, - "node_modules/extend-shallow/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -1118,45 +948,18 @@ "node": ">=0.10.0" } }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, + "node_modules/extglob/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "engines": { "node": ">=0.10.0" } }, "node_modules/fecha": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", - "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, "node_modules/fill-range": { "version": "4.0.0", @@ -1183,6 +986,14 @@ "node": ">=0.10.0" } }, + "node_modules/fill-range/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/findup-sync": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", @@ -1245,9 +1056,9 @@ } }, "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -1269,14 +1080,11 @@ } }, "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" + "minipass": "^2.6.0" } }, "node_modules/fs.realpath": { @@ -1284,23 +1092,24 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", + "aproba": "^1.0.3", "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, "node_modules/get-value": { @@ -1363,11 +1172,16 @@ "node": ">=0.10.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "optional": true + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } }, "node_modules/has-unicode": { "version": "2.0.1", @@ -1421,83 +1235,25 @@ "node": ">=0.10.0" } }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "optional": true - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "optional": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "optional": true, - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "optional": true, + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "optional": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "optional": true, - "engines": { - "node": ">=8" + "node_modules/ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "dependencies": { + "minimatch": "^3.0.4" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "optional": true - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1518,19 +1274,13 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/interpret": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.0.0.tgz", - "integrity": "sha512-e0/LknJ8wpMMhTiWcjivB+ESwIuvHnBSlBbmP/pSb8CQJldoj1p2qv7xGZ/+BtbTziYRFSz8OsvdbiX45LtYQA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "engines": { "node": ">= 0.10" } }, - "node_modules/ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "optional": true - }, "node_modules/is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", @@ -1544,22 +1294,11 @@ } }, "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dependencies": { - "is-buffer": "^1.1.5" + "kind-of": "^6.0.0" }, "engines": { "node": ">=0.10.0" @@ -1575,53 +1314,48 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "node_modules/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "dependencies": { - "kind-of": "^3.0.2" + "has": "^1.0.3" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dependencies": { - "is-buffer": "^1.1.5" + "kind-of": "^6.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, "engines": { "node": ">=0.10.0" } @@ -1635,17 +1369,20 @@ } }, "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dependencies": { "is-extglob": "^2.1.1" }, @@ -1653,12 +1390,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", - "optional": true - }, "node_modules/is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -1681,14 +1412,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -1768,9 +1491,9 @@ } }, "node_modules/knex": { - "version": "0.20.13", - "resolved": "https://registry.npmjs.org/knex/-/knex-0.20.13.tgz", - "integrity": "sha512-YVl//Te0G5suc+d9KyeI6WuhtgVlxu6HXYQB+WqrccFkSZAbHqlqZlUMogYG3UoVq69c3kiFbbxgUNkrO0PVfg==", + "version": "0.20.15", + "resolved": "https://registry.npmjs.org/knex/-/knex-0.20.15.tgz", + "integrity": "sha512-WHmvgfQfxA5v8pyb9zbskxCS1L1WmYgUbwBhHojlkmdouUOazvroUWlCr6KIKMQ8anXZh1NXOOtIUMnxENZG5Q==", "dependencies": { "colorette": "1.1.0", "commander": "^4.1.1", @@ -1819,14 +1542,6 @@ } } }, - "node_modules/knex/node_modules/uuid": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz", - "integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -1855,83 +1570,18 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, "node_modules/logform": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz", - "integrity": "sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.4.0.tgz", + "integrity": "sha512-CPSJw4ftjf517EhXZGGvTHHkYobo7ZCc0kvwUoOYcjfR2UVrI66RHj8MCrfAdEitdmFqbu2BYdYs8FHHZSb6iw==", "dependencies": { - "colors": "^1.2.1", + "@colors/colors": "1.5.0", "fecha": "^4.2.0", "ms": "^2.1.1", - "safe-stable-stringify": "^1.1.0", + "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "optional": true, - "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -1986,19 +1636,19 @@ } }, "node_modules/mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.43.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -2016,96 +1666,25 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "node_modules/minipass": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", - "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "optional": true, - "dependencies": { - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "optionalDependencies": { - "encoding": "^0.1.12" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "optional": true, + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" } }, "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" + "minipass": "^2.9.0" } }, "node_modules/mixin-deep": { @@ -2120,38 +1699,32 @@ "node": ">=0.10.0" } }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dependencies": { - "minimist": "^1.2.5" + "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/multimap": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz", "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==" }, + "node_modules/nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + }, "node_modules/nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -2173,19 +1746,29 @@ "node": ">=0.10.0" } }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "optional": true, + "node_modules/needle": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", + "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, "engines": { - "node": ">= 0.6" + "node": ">= 4.4.x" } }, - "node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } }, "node_modules/node-cache": { "version": "5.1.2", @@ -2217,129 +1800,79 @@ } } }, - "node_modules/node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "optional": true, + "node_modules/node-pre-gyp": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", + "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", + "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" }, "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/node-gyp/node_modules/are-we-there-yet": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", - "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/node-gyp/node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "optional": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/npmlog": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.1.tgz", - "integrity": "sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg==", - "optional": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.0", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node-pre-gyp": "bin/node-pre-gyp" } }, - "node_modules/node-gyp/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "optional": true, + "node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "abbrev": "1", + "osenv": "^0.1.4" }, - "engines": { - "node": ">= 6" + "bin": { + "nopt": "bin/nopt.js" } }, - "node_modules/node-gyp/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "optional": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" + "node_modules/npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" } }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "node_modules/npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" } }, "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" } }, "node_modules/object-assign": { @@ -2374,6 +1907,49 @@ "node": ">=0.10.0" } }, + "node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-copy/node_modules/kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -2449,38 +2025,29 @@ "fn.name": "1.x.x" } }, - "node_modules/ow": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", - "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", - "dependencies": { - "@sindresorhus/is": "^4.0.1", - "callsites": "^3.1.0", - "dot-prop": "^6.0.1", - "lodash.isequal": "^4.5.0", - "type-fest": "^1.2.1", - "vali-date": "^1.0.0" - }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "optional": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "node_modules/parse-filepath": { @@ -2562,23 +2129,18 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "optional": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "optional": true, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, - "engines": { - "node": ">=10" + "bin": { + "rc": "cli.js" } }, "node_modules/readable-stream": { @@ -2619,9 +2181,9 @@ } }, "node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", "engines": { "node": ">=0.10.0" } @@ -2635,11 +2197,16 @@ } }, "node_modules/resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dependencies": { - "path-parse": "^1.0.6" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2671,27 +2238,15 @@ "node": ">=0.12" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", - "optional": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, "node_modules/safe-buffer": { @@ -2708,28 +2263,29 @@ } }, "node_modules/safe-stable-stringify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", - "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", + "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==", + "engines": { + "node": ">=10" + } }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "optional": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "semver": "bin/semver" } }, "node_modules/set-blocking": { @@ -2762,6 +2318,14 @@ "node": ">=0.10.0" } }, + "node_modules/set-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -2775,16 +2339,6 @@ "is-arrayish": "^0.3.1" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -2827,41 +2381,6 @@ "node": ">=0.10.0" } }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", @@ -2914,56 +2433,84 @@ "node": ">=0.10.0" } }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/socks": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", - "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", - "optional": true, + "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dependencies": { - "ip": "^1.1.5", - "smart-buffer": "^4.2.0" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" + "node": ">=0.10.0" } }, - "node_modules/socks-proxy-agent": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.0.tgz", - "integrity": "sha512-wWqJhjb32Q6GsrUqzuFkukxb/zzide5quXYcMVpIjxalDBBYy2nqKCFQ/9+Ie4dvOYSQdOk3hUlZSdzZOd3zMQ==", - "optional": true, + "node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "kind-of": "^3.0.2" }, "engines": { - "node": ">= 10" + "node": ">=0.10.0" } }, - "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "optional": true, + "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dependencies": { - "ms": "2.1.2" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">=6.0" + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" } }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -2976,6 +2523,7 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", "dependencies": { "atob": "^2.1.2", "decode-uri-component": "^0.2.0", @@ -2985,9 +2533,10 @@ } }, "node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated" }, "node_modules/split-string": { "version": "3.1.0", @@ -3000,71 +2549,117 @@ "node": ">=0.10.0" } }, + "node_modules/sqlite": { + "version": "4.0.25", + "resolved": "https://registry.npmjs.org/sqlite/-/sqlite-4.0.25.tgz", + "integrity": "sha512-gqCEcLF8FOTeW/na3SRYWLQkw2jZXgVj1DdgRJbm0jvrhnUgBIuNDUUm649AnBNDNHhI5XskwT8dvc8vearRLQ==" + }, "node_modules/sqlite3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.4.tgz", - "integrity": "sha512-ATvAe7JutFv/d+KTbLS58KsKn/t1raL/WGn2qZfZxwsrL/oGSP+0OlbQ2tX5jISvyu6/7JuKze3WkaiP1JAH6A==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", + "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", "hasInstallScript": true, "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "node-addon-api": "^4.2.0", - "tar": "^6.1.11" + "nan": "^2.12.1", + "node-pre-gyp": "^0.11.0" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "engines": { + "node": "*" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, - "optionalDependencies": { - "node-gyp": "8.x" + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" }, - "peerDependencies": { - "node-gyp": "8.x" + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dependencies": { + "kind-of": "^3.0.2" }, - "peerDependenciesMeta": { - "node-gyp": { - "optional": true - } + "engines": { + "node": ">=0.10.0" } }, - "node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "optional": true, + "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dependencies": { - "minipass": "^3.1.1" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dependencies": { + "kind-of": "^3.0.2" + }, "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "is-buffer": "^1.1.5" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dependencies": { - "is-descriptor": "^0.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "engines": { "node": ">=0.10.0" } }, + "node_modules/static-extend/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -3074,56 +2669,84 @@ } }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "engines": { - "node": ">= 10" + "node": ">=0.10.0" } }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "dependencies": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/tar/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/tarn": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tarn/-/tarn-2.0.0.tgz", @@ -3204,26 +2827,15 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "node_modules/ts-mixer": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", - "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", + "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" }, "node_modules/tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, - "node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -3246,22 +2858,12 @@ "node": ">=0.10.0" } }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "optional": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "optional": true, - "dependencies": { - "imurmurhash": "^0.1.4" + "node_modules/union-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "engines": { + "node": ">=0.10.0" } }, "node_modules/unset-value": { @@ -3327,10 +2929,18 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8flags": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", "dependencies": { "homedir-polyfill": "^1.0.1" }, @@ -3338,14 +2948,6 @@ "node": ">= 0.10" } }, - "node_modules/vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -3380,36 +2982,51 @@ } }, "node_modules/winston": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", - "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.7.2.tgz", + "integrity": "sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng==", "dependencies": { "@dabh/diagnostics": "^2.0.2", - "async": "^3.1.0", + "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.2.0", + "logform": "^2.4.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" + "winston-transport": "^4.5.0" }, "engines": { - "node": ">= 6.4.0" + "node": ">= 12.0.0" } }, "node_modules/winston-transport": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", - "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", + "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", "dependencies": { - "readable-stream": "^2.3.7", - "triple-beam": "^1.2.0" + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" }, "engines": { "node": ">= 6.4.0" } }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/winston/node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -3429,9 +3046,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/ws": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz", - "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", "engines": { "node": ">=10.0.0" }, @@ -3449,24 +3066,29 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/zod": { - "version": "3.11.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.11.6.tgz", - "integrity": "sha512-daZ80A81I3/9lIydI44motWe6n59kRBfNzTuS2bfzVh1nAXi667TOTWWtatxyG+fwgNUiagSj/CWZwRRbevJIg==", + "version": "3.14.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.14.4.tgz", + "integrity": "sha512-U9BFLb2GO34Sfo9IUYp0w3wJLlmcyGoMd75qU9yf+DrdGA4kEx6e+l9KOkAlyUO0PSQzZCa3TR4qVlcmwqSDuw==", "funding": { "url": "https://github.com/sponsors/colinhacks" } } }, "dependencies": { + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" + }, "@dabh/diagnostics": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", - "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "requires": { "colorspace": "1.1.x", "enabled": "2.0.x", @@ -3474,31 +3096,28 @@ } }, "@discordjs/builders": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.2.tgz", - "integrity": "sha512-/YRd11SrcluqXkKppq/FAVzLIPRVlIVmc6X8ZklspzMIHDtJ+A4W37D43SHvLdH//+NnK+SHW/WeOF4Ts54PeQ==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.9.0.tgz", + "integrity": "sha512-XM/5yrTxMF0SDKza32YzGDQO1t+qEJTaF8Zvxu/UOjzoqzMPPGQBjC1VgZxz8/CBLygW5qI+UVygMa88z13G3g==", "requires": { "@sindresorhus/is": "^4.2.0", "discord-api-types": "^0.24.0", - "ow": "^0.27.0", "ts-mixer": "^6.0.0", - "tslib": "^2.3.1" + "tslib": "^2.3.1", + "zod": "^3.11.6" + }, + "dependencies": { + "discord-api-types": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", + "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==" + } } }, "@discordjs/collection": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.3.2.tgz", - "integrity": "sha512-dMjLl60b2DMqObbH1MQZKePgWhsNe49XkKBZ0W5Acl5uVV43SN414i2QfZwRI7dXAqIn8pEWD2+XXQFn9KWxqg==" - }, - "@discordjs/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" }, "@discordjs/rest": { "version": "0.1.0-canary.0", @@ -3515,82 +3134,17 @@ "tslib": "^2.3.0" }, "dependencies": { - "@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" - }, "discord-api-types": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.18.1.tgz", "integrity": "sha512-hNC38R9ZF4uaujaZQtQfm5CdQO58uhdkoHQAVvMfIL0LgOSZeW575W8H6upngQOuoxWd8tiRII3LLJm9zuQKYg==" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - } - } - }, - "@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "optional": true - }, - "@mapbox/node-pre-gyp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", - "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", - "requires": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - } - }, - "@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "optional": true, - "requires": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "optional": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true } } }, "@sapphire/async-queue": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.9.tgz", - "integrity": "sha512-CbXaGwwlEMq+l1TRu01FJCvySJ1CEFKFclHT48nIfNeZXaAAmmwwy7scUKmYHPUa3GhoMp6Qr1B3eAJux6XgOQ==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.3.1.tgz", + "integrity": "sha512-FFTlPOWZX1kDj9xCAsRzH5xEJfawg1lNoYAA+ecOWJMHOfiZYb1uXOI3ne9U4UILSEPwfE68p3T9wUHwIQfR0g==" }, "@sapphire/snowflake": { "version": "1.3.6", @@ -3598,34 +3152,40 @@ "integrity": "sha512-QnzuLp+p9D7agynVub/zqlDVriDza9y3STArBhNiNBUgIX8+GL5FpQxstRfw1jDr5jkZUjcuKYAHxjIuXKdJAg==" }, "@sindresorhus/is": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", - "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==" - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "optional": true + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==" }, "@types/node": { - "version": "16.11.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", - "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==" + "version": "17.0.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz", + "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w==" }, "@types/node-fetch": { - "version": "2.5.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", - "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==", "requires": { "@types/node": "*", "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } } }, "@types/ws": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.1.tgz", - "integrity": "sha512-SqQ+LhVZaJi7c7sYVkjWALDigi/Wy7h7Iu72gkQp8Y8OWw/DddEVBrTSKu86pQftV2+Gm8lYM61hadPKqyaIeg==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", "requires": { "@types/node": "*" } @@ -3643,64 +3203,23 @@ "event-target-shim": "^5.0.0" } }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", - "optional": true, - "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "optional": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "requires": { "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "readable-stream": "^2.0.6" } }, "arr-diff": { @@ -3739,9 +3258,9 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, "async": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", - "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" }, "asynckit": { "version": "0.4.0", @@ -3779,32 +3298,6 @@ "requires": { "is-descriptor": "^1.0.0" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } } } }, @@ -3841,40 +3334,11 @@ "requires": { "is-extendable": "^0.1.0" } - } - } - }, - "cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "optional": true, - "requires": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" } } }, @@ -3894,15 +3358,10 @@ "unset-value": "^1.0.0" } }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" - }, "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "class-utils": { "version": "0.3.6", @@ -3920,22 +3379,72 @@ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "optional": true - }, "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -3968,29 +3477,19 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.8.2.tgz", - "integrity": "sha512-w5ZkKRdLsc5NOYsmnpS2DpyRW71npwZGwbRpLrJTuqjfTs2Bhrba7UiV59IX9siBlCPl2pne5NtiwnVWUzvYFA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", + "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, "colorette": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", "integrity": "sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==" }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, "colorspace": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", @@ -4034,9 +3533,9 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "debug": { "version": "4.1.1", @@ -4051,6 +3550,11 @@ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -4058,34 +3562,6 @@ "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } } }, "delayed-stream": { @@ -4098,26 +3574,20 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "optional": true - }, "detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" }, "detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, "discord-api-types": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", - "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==" + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.25.2.tgz", + "integrity": "sha512-O243LXxb5gLLxubu5zgoppYQuolapGVWPw3ll0acN0+O8TnPUE2kFp9Bt3sTRYodw8xFIknOVxjSeyWYBpVcEQ==" }, "discord-command-registry": { "version": "1.2.0", @@ -4127,89 +3597,53 @@ "@discordjs/builders": "^0.9.0", "@discordjs/rest": "^0.1.0-canary.0", "discord-api-types": "^0.25.2" + } + }, + "discord.js": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.6.0.tgz", + "integrity": "sha512-tXNR8zgsEPxPBvGk3AQjJ9ljIIC6/LOPjzKwpwz8Y1Q2X66Vi3ZqFgRHYwnHKC0jC0F+l4LzxlhmOJsBZDNg9g==", + "requires": { + "@discordjs/builders": "^0.11.0", + "@discordjs/collection": "^0.4.0", + "@sapphire/async-queue": "^1.1.9", + "@types/node-fetch": "^2.5.12", + "@types/ws": "^8.2.2", + "discord-api-types": "^0.26.0", + "form-data": "^4.0.0", + "node-fetch": "^2.6.1", + "ws": "^8.4.0" }, "dependencies": { "@discordjs/builders": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.9.0.tgz", - "integrity": "sha512-XM/5yrTxMF0SDKza32YzGDQO1t+qEJTaF8Zvxu/UOjzoqzMPPGQBjC1VgZxz8/CBLygW5qI+UVygMa88z13G3g==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.11.0.tgz", + "integrity": "sha512-ZTB8yJdJKrKlq44dpWkNUrAtEJEq0gqpb7ASdv4vmq6/mZal5kOv312hQ56I/vxwMre+VIkoHquNUAfnTbiYtg==", "requires": { "@sindresorhus/is": "^4.2.0", - "discord-api-types": "^0.24.0", + "discord-api-types": "^0.26.0", "ts-mixer": "^6.0.0", "tslib": "^2.3.1", "zod": "^3.11.6" - }, - "dependencies": { - "discord-api-types": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.24.0.tgz", - "integrity": "sha512-X0uA2a92cRjowUEXpLZIHWl4jiX1NsUpDhcEOpa1/hpO1vkaokgZ8kkPtPih9hHth5UVQ3mHBu/PpB4qjyfJ4A==" - } } }, + "@discordjs/collection": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.4.0.tgz", + "integrity": "sha512-zmjq+l/rV35kE6zRrwe8BHqV78JvIh2ybJeZavBi5NySjWXqN3hmmAKg7kYMMXSeiWtSsMoZ/+MQi0DiQWy2lw==" + }, "discord-api-types": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.25.2.tgz", - "integrity": "sha512-O243LXxb5gLLxubu5zgoppYQuolapGVWPw3ll0acN0+O8TnPUE2kFp9Bt3sTRYodw8xFIknOVxjSeyWYBpVcEQ==" + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz", + "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==" } } }, - "discord.js": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.3.1.tgz", - "integrity": "sha512-zn4G8tL5+tMV00+0aSsVYNYcIfMSdT2g0nudKny+Ikd+XKv7m6bqI7n3Vji0GIRqXDr5ArPaw+iYFM2I1Iw3vg==", - "requires": { - "@discordjs/builders": "^0.8.1", - "@discordjs/collection": "^0.3.2", - "@discordjs/form-data": "^3.0.1", - "@sapphire/async-queue": "^1.1.8", - "@types/node-fetch": "^2.5.12", - "@types/ws": "^8.2.0", - "discord-api-types": "^0.24.0", - "node-fetch": "^2.6.1", - "ws": "^8.2.3" - } - }, - "dot-prop": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", - "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", - "requires": { - "is-obj": "^2.0.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, "enabled": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - } - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "optional": true - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "optional": true - }, "esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -4258,6 +3692,62 @@ "is-extendable": "^0.1.0" } }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -4285,16 +3775,6 @@ "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } } }, "extglob": { @@ -4328,38 +3808,17 @@ "is-extendable": "^0.1.0" } }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" } } }, "fecha": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", - "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, "fill-range": { "version": "4.0.0", @@ -4379,6 +3838,11 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" } } }, @@ -4429,9 +3893,9 @@ } }, "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -4447,11 +3911,11 @@ } }, "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "requires": { - "minipass": "^3.0.0" + "minipass": "^2.6.0" } }, "fs.realpath": { @@ -4459,20 +3923,24 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", + "aproba": "^1.0.3", "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, "get-value": { @@ -4520,11 +3988,13 @@ "which": "^1.2.14" } }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "optional": true + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } }, "has-unicode": { "version": "2.0.1", @@ -4568,68 +4038,22 @@ "parse-passwd": "^1.0.0" } }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "optional": true - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "optional": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "optional": true, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "requires": { - "ms": "^2.0.0" + "safer-buffer": ">= 2.1.2 < 3" } }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "optional": true, + "ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "minimatch": "^3.0.4" } }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "optional": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "optional": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "optional": true - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -4650,15 +4074,9 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "interpret": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.0.0.tgz", - "integrity": "sha512-e0/LknJ8wpMMhTiWcjivB+ESwIuvHnBSlBbmP/pSb8CQJldoj1p2qv7xGZ/+BtbTziYRFSz8OsvdbiX45LtYQA==" - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "optional": true + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==" }, "is-absolute": { "version": "1.0.0", @@ -4670,21 +4088,11 @@ } }, "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "kind-of": "^6.0.0" } }, "is-arrayish": { @@ -4697,45 +4105,39 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "requires": { + "has": "^1.0.3" + } + }, "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "kind-of": "^6.0.0" } }, "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } }, "is-extglob": { "version": "2.1.1", @@ -4743,24 +4145,21 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "requires": { "is-extglob": "^2.1.1" } }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", - "optional": true - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -4779,11 +4178,6 @@ } } }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" - }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -4839,9 +4233,9 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "knex": { - "version": "0.20.13", - "resolved": "https://registry.npmjs.org/knex/-/knex-0.20.13.tgz", - "integrity": "sha512-YVl//Te0G5suc+d9KyeI6WuhtgVlxu6HXYQB+WqrccFkSZAbHqlqZlUMogYG3UoVq69c3kiFbbxgUNkrO0PVfg==", + "version": "0.20.15", + "resolved": "https://registry.npmjs.org/knex/-/knex-0.20.15.tgz", + "integrity": "sha512-WHmvgfQfxA5v8pyb9zbskxCS1L1WmYgUbwBhHojlkmdouUOazvroUWlCr6KIKMQ8anXZh1NXOOtIUMnxENZG5Q==", "requires": { "colorette": "1.1.0", "commander": "^4.1.1", @@ -4858,13 +4252,6 @@ "tildify": "2.0.0", "uuid": "^7.0.1", "v8flags": "^3.1.3" - }, - "dependencies": { - "uuid": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz", - "integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==" - } } }, "kuler": { @@ -4889,71 +4276,19 @@ }, "lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "logform": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz", - "integrity": "sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==", - "requires": { - "colors": "^1.2.1", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^1.1.0", - "triple-beam": "^1.3.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "optional": true, + "logform": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.4.0.tgz", + "integrity": "sha512-CPSJw4ftjf517EhXZGGvTHHkYobo7ZCc0kvwUoOYcjfR2UVrI66RHj8MCrfAdEitdmFqbu2BYdYs8FHHZSb6iw==", "requires": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" + "@colors/colors": "1.5.0", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" } }, "make-iterator": { @@ -4998,16 +4333,16 @@ } }, "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.43.0" + "mime-db": "1.52.0" } }, "minimatch": { @@ -5019,73 +4354,25 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "minipass": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", - "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "optional": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "optional": true, - "requires": { - "encoding": "^0.1.12", - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "optional": true, + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "optional": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "optional": true, - "requires": { - "minipass": "^3.0.0" + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" } }, "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^2.9.0" } }, "mixin-deep": { @@ -5095,36 +4382,31 @@ "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } } }, "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "requires": { - "minimist": "^1.2.5" + "minimist": "^1.2.6" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "multimap": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz", "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==" }, + "nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -5143,16 +4425,25 @@ "to-regex": "^3.0.1" } }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "optional": true - }, - "node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + "needle": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", + "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } }, "node-cache": { "version": "5.1.2", @@ -5170,103 +4461,71 @@ "whatwg-url": "^5.0.0" } }, - "node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "optional": true, + "node-pre-gyp": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", + "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "are-we-there-yet": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", - "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "optional": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "npmlog": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.1.tgz", - "integrity": "sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg==", - "optional": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.0", - "set-blocking": "^2.0.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "optional": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "optional": true, - "requires": { - "isexe": "^2.0.0" - } - } + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" } }, "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", "requires": { - "abbrev": "1" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" } }, "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5290,6 +4549,39 @@ "is-descriptor": "^0.1.0" } }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -5352,26 +4644,23 @@ "fn.name": "1.x.x" } }, - "ow": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", - "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", - "requires": { - "@sindresorhus/is": "^4.0.1", - "callsites": "^3.1.0", - "dot-prop": "^6.0.1", - "lodash.isequal": "^4.5.0", - "type-fest": "^1.2.1", - "vali-date": "^1.0.0" - } + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "optional": true, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "requires": { - "aggregate-error": "^3.0.0" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "parse-filepath": { @@ -5432,20 +4721,15 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "optional": true - }, - "promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "optional": true, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" } }, "readable-stream": { @@ -5480,9 +4764,9 @@ } }, "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" }, "repeat-string": { "version": "1.6.1", @@ -5490,11 +4774,13 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "requires": { - "path-parse": "^1.0.6" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-dir": { @@ -5516,16 +4802,10 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", - "optional": true - }, "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "requires": { "glob": "^7.1.3" } @@ -5544,23 +4824,24 @@ } }, "safe-stable-stringify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", - "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", + "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "optional": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "requires": { - "lru-cache": "^6.0.0" - } + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, "set-blocking": { "version": "2.0.0", @@ -5585,6 +4866,11 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" } } }, @@ -5601,12 +4887,6 @@ "is-arrayish": "^0.3.1" } }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -5646,6 +4926,62 @@ "is-extendable": "^0.1.0" } }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -5670,32 +5006,6 @@ "requires": { "is-descriptor": "^1.0.0" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } } } }, @@ -5717,38 +5027,6 @@ } } }, - "socks": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", - "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", - "optional": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.0.tgz", - "integrity": "sha512-wWqJhjb32Q6GsrUqzuFkukxb/zzide5quXYcMVpIjxalDBBYy2nqKCFQ/9+Ie4dvOYSQdOk3hUlZSdzZOd3zMQ==", - "optional": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "optional": true, - "requires": { - "ms": "2.1.2" - } - } - } - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -5767,9 +5045,9 @@ } }, "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" }, "split-string": { "version": "3.1.0", @@ -5779,24 +5057,18 @@ "extend-shallow": "^3.0.0" } }, - "sqlite3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.4.tgz", - "integrity": "sha512-ATvAe7JutFv/d+KTbLS58KsKn/t1raL/WGn2qZfZxwsrL/oGSP+0OlbQ2tX5jISvyu6/7JuKze3WkaiP1JAH6A==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.0", - "node-addon-api": "^4.2.0", - "node-gyp": "8.x", - "tar": "^6.1.11" - } + "sqlite": { + "version": "4.0.25", + "resolved": "https://registry.npmjs.org/sqlite/-/sqlite-4.0.25.tgz", + "integrity": "sha512-gqCEcLF8FOTeW/na3SRYWLQkw2jZXgVj1DdgRJbm0jvrhnUgBIuNDUUm649AnBNDNHhI5XskwT8dvc8vearRLQ==" }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "optional": true, + "sqlite3": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", + "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", "requires": { - "minipass": "^3.1.1" + "nan": "^2.12.1", + "node-pre-gyp": "^0.11.0" } }, "stack-trace": { @@ -5820,6 +5092,57 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -5832,40 +5155,51 @@ } }, "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^2.0.0" } }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "requires": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" } } }, @@ -5933,20 +5267,15 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "ts-mixer": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", - "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", + "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==" }, "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, - "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==" - }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -5961,24 +5290,13 @@ "get-value": "^2.0.6", "is-extendable": "^0.1.1", "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "optional": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "optional": true, - "requires": { - "imurmurhash": "^0.1.4" + }, + "dependencies": { + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + } } }, "unset-value": { @@ -6032,19 +5350,19 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" + }, "v8flags": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", "requires": { "homedir-polyfill": "^1.0.1" } }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=" - }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -6076,19 +5394,20 @@ } }, "winston": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", - "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.7.2.tgz", + "integrity": "sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng==", "requires": { "@dabh/diagnostics": "^2.0.2", - "async": "^3.1.0", + "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.2.0", + "logform": "^2.4.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" + "winston-transport": "^4.5.0" }, "dependencies": { "readable-stream": { @@ -6104,12 +5423,25 @@ } }, "winston-transport": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", - "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", + "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", "requires": { - "readable-stream": "^2.3.7", - "triple-beam": "^1.2.0" + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "wrappy": { @@ -6118,20 +5450,20 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz", - "integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", "requires": {} }, "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "zod": { - "version": "3.11.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.11.6.tgz", - "integrity": "sha512-daZ80A81I3/9lIydI44motWe6n59kRBfNzTuS2bfzVh1nAXi667TOTWWtatxyG+fwgNUiagSj/CWZwRRbevJIg==" + "version": "3.14.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.14.4.tgz", + "integrity": "sha512-U9BFLb2GO34Sfo9IUYp0w3wJLlmcyGoMd75qU9yf+DrdGA4kEx6e+l9KOkAlyUO0PSQzZCa3TR4qVlcmwqSDuw==" } } } diff --git a/package.json b/package.json index c2802ac..e9674ee 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "lodash": "^4.17.20", "multimap": "^1.1.0", "node-cache": "^5.1.2", - "sqlite3": "^5.0.4", + "sqlite": "^4.0.25", + "sqlite3": "^4.2.0", "winston": "^3.3.3" }, "scripts": { From 8a8300a1b84686f5939459f0737d866f2fb60c82 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Tue, 19 Apr 2022 01:15:27 -0400 Subject: [PATCH 104/107] And also don't add sqlite --- package-lock.json | 11 ----------- package.json | 1 - 2 files changed, 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index c39735c..8046a39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ "lodash": "^4.17.20", "multimap": "^1.1.0", "node-cache": "^5.1.2", - "sqlite": "^4.0.25", "sqlite3": "^4.2.0", "winston": "^3.3.3" } @@ -2549,11 +2548,6 @@ "node": ">=0.10.0" } }, - "node_modules/sqlite": { - "version": "4.0.25", - "resolved": "https://registry.npmjs.org/sqlite/-/sqlite-4.0.25.tgz", - "integrity": "sha512-gqCEcLF8FOTeW/na3SRYWLQkw2jZXgVj1DdgRJbm0jvrhnUgBIuNDUUm649AnBNDNHhI5XskwT8dvc8vearRLQ==" - }, "node_modules/sqlite3": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", @@ -5057,11 +5051,6 @@ "extend-shallow": "^3.0.0" } }, - "sqlite": { - "version": "4.0.25", - "resolved": "https://registry.npmjs.org/sqlite/-/sqlite-4.0.25.tgz", - "integrity": "sha512-gqCEcLF8FOTeW/na3SRYWLQkw2jZXgVj1DdgRJbm0jvrhnUgBIuNDUUm649AnBNDNHhI5XskwT8dvc8vearRLQ==" - }, "sqlite3": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", diff --git a/package.json b/package.json index e9674ee..43d5c84 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "lodash": "^4.17.20", "multimap": "^1.1.0", "node-cache": "^5.1.2", - "sqlite": "^4.0.25", "sqlite3": "^4.2.0", "winston": "^3.3.3" }, From b614cc28ec4fd2eeba1780d755e99e68d7c6c3c8 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 20 Apr 2022 01:21:50 -0400 Subject: [PATCH 105/107] Update resources to use new project config --- package.json | 1 + resources/post-receive | 2 +- resources/reactionrolebot.service | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 43d5c84..d028b90 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "winston": "^3.3.3" }, "scripts": { + "start": "node .", "dev": "node . dev-config.json", "knex": "npx knex --knexfile src/knexfile.js", "register": "node src/register.js", diff --git a/resources/post-receive b/resources/post-receive index 29a18a1..d046252 100755 --- a/resources/post-receive +++ b/resources/post-receive @@ -11,7 +11,7 @@ NODE_ENV="prod" mkdir -p $TEMP /usr/bin/env git --work-tree=$TEMP --git-dir=$REPO checkout -f cd $TEMP -/usr/bin/env npm install +/usr/bin/env npm ci NODE_ENV=$NODE_ENV /usr/bin/env npm run knex migrate:latest # Now install the code diff --git a/resources/reactionrolebot.service b/resources/reactionrolebot.service index 0fae6d1..bad310d 100644 --- a/resources/reactionrolebot.service +++ b/resources/reactionrolebot.service @@ -11,7 +11,7 @@ Restart=on-failure RestartSec=10 User= Environment="NODE_ENV=prod" -ExecStart=/usr/bin/env nodejs /srv/discord/ReactionRoleBot/main.js +ExecStart=/usr/bin/env npm start --prefix /srv/discord/ReactionRoleBot/ [Install] WantedBy=multi-user.target From d37653c220369471d74ada4471c483a9764399b7 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Wed, 20 Apr 2022 01:22:29 -0400 Subject: [PATCH 106/107] Improve hosting docs and add instructions on migrating instances --- README.md | 57 +++----------------------------------- docs/hosting.md | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/migrate.md | 31 +++++++++++++++++++++ 3 files changed, 108 insertions(+), 53 deletions(-) create mode 100644 docs/hosting.md create mode 100644 docs/migrate.md diff --git a/README.md b/README.md index c527147..81d2fee 100644 --- a/README.md +++ b/README.md @@ -132,59 +132,10 @@ up react roles for `@everyone` like you would for any other role. It's silly, it won't do anything, but you *could* do it... ## Hosting your own instance -This bot is built on [discord.js](https://discord.js.org/#/) v13, so you'll need -Node.js 16.6.0 (or newer) installed. You will also need your own Discord bot -account. - -If you're upgrading from an older Discord.js v12 version of the bot, the Node.js -16.6.0 requirement might be problematic. you might consider using something like -https://github.com/nvm-sh/nvm to make the transition easier. - -The `resources` directory has a service file that can be used with Linux distros -with systemd. If you're installing this on some other operating system, you're -on your own. - -### Running as a service -The provided service file expects to find the bot code at -`/srv/discord/ReactionRoleBot/`, and will want to create the sqlite database at -`/srv/discord/rolebot.sqlite`. The easiest way to do this is to create a -`/srv/discord` directory, and `chown` it so it belongs to the user running the -bot. - -The following will prepare the bot to run. Run this from `/srv/discord`: -``` -git clone https://github.com/Mimickal/ReactionRoleBot.git -cd ReactionRoleBot -npm install -NODE_ENV=prod npm run knex migrate:latest -``` - -Create a file `/etc/discord/ReactionRoleBot/config.json` and paste in the -following (obviously fill in the blanks with your bot's info): -```json -{ - "token": "", - "app_id": "" -} -``` - -Install `reactionrolebot.service` into `/etc/systemd/system/`. - -Now you should be able to run `systemctl restart reactionrolebot.service` to -start your bot. - -### Running locally (in dev-mode) -Run this wherever you want: -``` -git clone https://github.com/Mimickal/ReactionRoleBot.git -cd ReactionRoleBot -npm install -npm run knex migrate:latest -``` - -Create a file containing your bot token in plain text. - -Run this to start the bot: `node main.js path/to/your/config` +[See the guide here](docs/hosting.md). + +If you are upgrading from version 1.x, [see the migration guide]( +docs/migrate.md). ## License Copyright 2020 [Mimickal](https://github.com/Mimickal) diff --git a/docs/hosting.md b/docs/hosting.md new file mode 100644 index 0000000..3aa3046 --- /dev/null +++ b/docs/hosting.md @@ -0,0 +1,73 @@ +# Hosting your own instance + +This bot is built on [discord.js](https://discord.js.org/#/) v13, so you'll need +Node.js 16.6.0 (or newer) installed. You will also need your own Discord bot +account. If your platform does not have Node.js 16.6.0, consider using something +like https://github.com/nvm-sh/nvm. + +This guide assumes you're hosting on a Linux distro with `systemd`. The bot will +work on other platforms, but you're on your own figuring that out. + +## Running as a user (in dev-mode) +Quick and easy. Also (mostly) platform-independent! + +Create a file `config.json` and paste in the following (obviously fill in the +blanks with your bot's info): +```json +{ + "token": "", + "app_id": "" +} +``` + +Install dependencies, register Discord slash commands, and set up the database +for your bot: +``` +git clone https://github.com/Mimickal/ReactionRoleBot.git +cd ReactionRoleBot +npm ci +npm run register path/to/your/config.json +npm run knex migrate:latest +``` + +Start the bot: +``` +npm start path/to/your/config.json +``` + +## Running as a service +A little more effort to set up, but better for long-term use. + +The provided service file expects to find the bot code at +`/srv/discord/ReactionRoleBot/`, and will want to create the sqlite database at +`/srv/discord/rolebot.sqlite`. The easiest way to do this is to create a +`/srv/discord` directory, and `chown` it so it belongs to the user running the +bot. + +Create a file `/etc/discord/ReactionRoleBot/config.json` and paste in the +following (obviously fill in the blanks with your bot's info): +```json +{ + "token": "", + "app_id": "" +} +``` + +The following will prepare the bot to run by installing dependencies, +registering slash commands for your Discord bot account, and setting up the +bot's database. Run this from `/srv/discord`: +``` +git clone https://github.com/Mimickal/ReactionRoleBot.git +cd ReactionRoleBot +npm ci +npm run register /etc/discord/ReactionRoleBot/config.json +NODE_ENV=prod npm run knex migrate:latest +``` + +Install `reactionrolebot.service` into `/etc/systemd/system/`. This service file +depends on the above directories, so if you want to change them, you'll also +need to edit this file. + +Now you should be able to run `systemctl restart reactionrolebot.service` to +start your bot. + diff --git a/docs/migrate.md b/docs/migrate.md new file mode 100644 index 0000000..fa1495a --- /dev/null +++ b/docs/migrate.md @@ -0,0 +1,31 @@ +# Migrating your instance to 2.x + +This guide is for people who were running their own 1.x instance of the bot. + +This bot now runs Discord.js v13, which requires Node.js 16.6.0. On some +platforms (older distros, cloud hosting, etc...) this may be problematic. +Something like https://github.com/nvm-sh/nvm can make the transition easier. + +1. Get the updated bot code (either `git pull origin master` if you cloned with + git (which you should) or download `master` as a zip). +1. Make a copy of your old database + - **Running as a service**: probably `/srv/discord/rolebot.sqlite3` + - **Running in dev-mode**: `dev.sqlite3` +1. Replace bot token file with a `config.json` file that looks like this: + ```json + { + "token": "", + "app_id": "" + } + ``` + - **Running as a service**: Replace `/etc/discord/ReactionRoleBot/token` + with `/etc/discord/ReactionRoleBot/config.json` + - **Running in dev-mode**: Some local token file +1. Install updated dependencies: `npm ci` +1. Register slash commands: `npm run register path/to/your/config.json` +1. Update your database: `npm run knex migrate:latest` +1. Start the bot + - **Running as a service**: update `reactionrolebot.service` ([see reference + implementation](../resources/reactionrolebot.service)). Restart service + `systemctl restart reactionrolebot.service`. + - **Running in dev-mode**: `npm start path/to/your/config.json` From 59b437f07853ea01e6e6919c79344daab89fe8e8 Mon Sep 17 00:00:00 2001 From: Mia Moretti Date: Thu, 21 Apr 2022 23:55:00 -0400 Subject: [PATCH 107/107] Add some info for running as a service with nvm --- docs/hosting.md | 9 +++++---- resources/reactionrolebot.service | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/hosting.md b/docs/hosting.md index 3aa3046..42ca24a 100644 --- a/docs/hosting.md +++ b/docs/hosting.md @@ -64,10 +64,11 @@ npm run register /etc/discord/ReactionRoleBot/config.json NODE_ENV=prod npm run knex migrate:latest ``` -Install `reactionrolebot.service` into `/etc/systemd/system/`. This service file -depends on the above directories, so if you want to change them, you'll also -need to edit this file. +Add your user to `reactionrolebot.service`, then install it into +`/etc/systemd/system/` (just copy the file into that directory). This service +file depends on the above directories, so if you want to change them, you'll +also need to edit those fields. If you are using `nvm`, you may need to tweak +the service file a bit (see comments in provided service file). Now you should be able to run `systemctl restart reactionrolebot.service` to start your bot. - diff --git a/resources/reactionrolebot.service b/resources/reactionrolebot.service index bad310d..4e5968c 100644 --- a/resources/reactionrolebot.service +++ b/resources/reactionrolebot.service @@ -12,6 +12,9 @@ RestartSec=10 User= Environment="NODE_ENV=prod" ExecStart=/usr/bin/env npm start --prefix /srv/discord/ReactionRoleBot/ +# If using nvm, you may need to do something like this instead: +#Environment="NODE_ENV=prod" "NODE_VERSION=" +#ExecStart= npm start --prefix /srv/discord/ReactionRoleBot [Install] WantedBy=multi-user.target