diff --git a/index.js b/index.js index b76f5cfd2..6d7155d62 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ const Sentry = require('@sentry/node') Sentry.init({ dsn: process.env.SENTRY_DSN }) +const { Intents } = require('discord.js') const { readFileSync } = require('fs') require('moment') @@ -16,9 +17,9 @@ try { // Initialize client const CLIENT_OPTIONS = { - fetchAllMembers: false, enableEveryone: false, - canvasLoaded + canvasLoaded, + intents: [Intents.FLAGS.GUILDS] } console.log(readFileSync('bigtitle.txt', 'utf8').toString()) diff --git a/package-lock.json b/package-lock.json index b6c4bda25..6bc084209 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "abort-controller": "^3.0.0", "adm-zip": "^0.5.6", "ascii-table": "0.0.9", + "ast-parser": "^0.1.1", "axios": "^0.21.4", "brainfuck-node": "^1.0.2", "bunyan": "^1.8.15", @@ -23,7 +24,7 @@ "cors": "^2.8.5", "cows": "^2.1.1", "cowsay": "^1.5.0", - "discord.js": "^12.5.1", + "discord.js": "^13.6.0", "express": "^4.17.1", "figlet": "^1.5.2", "fuse.js": "^6.4.6", @@ -62,7 +63,6 @@ "steamladder": "^1.0.7", "transform-props": "^1.0.1", "turndown": "^7.1.1", - "uws": "^200.0.0", "wikijs": "^6.3.2", "xml2json": "^0.12.0", "zlib-sync": "^0.1.7" @@ -84,10 +84,9 @@ "node": "> 14.0.0" }, "optionalDependencies": { - "@discordjs/uws": "^11.149.1", - "canvas": "^2.8.0", - "erlpack": "github:discord/erlpack", - "node-opus": "^0.3.3" + "bufferutil": "^4.0.6", + "canvas": "^2.9.0", + "utf-8-validate": "^5.0.8" } }, "node_modules/@babel/code-frame": { @@ -98,19 +97,95 @@ "@babel/highlight": "^7.10.4" } }, + "node_modules/@babel/generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz", + "integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==", + "dependencies": { + "@babel/types": "^7.16.8", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", + "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "dependencies": { + "@babel/helper-get-function-arity": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", + "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "engines": { + "node": ">=6.9.0" + } }, "node_modules/@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.12.11", + "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/highlight/node_modules/ansi-styles": { @@ -169,6 +244,17 @@ "node": ">=4" } }, + "node_modules/@babel/parser": { + "version": "7.16.12", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", + "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/runtime": { "version": "7.15.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", @@ -180,32 +266,106 @@ "node": ">=6.9.0" } }, - "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/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } }, - "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==", + "node_modules/@babel/template/node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "@babel/highlight": "^7.16.7" }, "engines": { - "node": ">= 6" + "node": ">=6.9.0" } }, - "node_modules/@discordjs/uws": { - "version": "11.149.1", - "resolved": "https://registry.npmjs.org/@discordjs/uws/-/uws-11.149.1.tgz", - "integrity": "sha512-TmbwZaeXDSCq0ckmf2q10Fkt1220gu9AZJ/UvtQjsi2jyJDjy0i0OwL4/eb3vc9Cwr0mpC9EbfzltQ2si0qUiQ==", - "hasInstallScript": true, - "optional": true, + "node_modules/@babel/traverse": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz", + "integrity": "sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.16.8", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.16.10", + "@babel/types": "^7.16.8", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz", + "integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@daybrush/utils": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@daybrush/utils/-/utils-0.11.0.tgz", + "integrity": "sha512-PnrY1NDjXqXKASoREcjHokQt0WWHiUBClMJ0l9APx42QkeOCQ5nXB7k4VdmkaU23BndeSmNNYJDNL6eEsRitaA==" + }, + "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.26.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/@discordjs/builders/node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "node_modules/@discordjs/collection": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.4.0.tgz", + "integrity": "sha512-zmjq+l/rV35kE6zRrwe8BHqV78JvIh2ybJeZavBi5NySjWXqN3hmmAKg7kYMMXSeiWtSsMoZ/+MQi0DiQWy2lw==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" } }, "node_modules/@eslint/eslintrc": { @@ -368,6 +528,15 @@ "node": ">=10" } }, + "node_modules/@sapphire/async-queue": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.2.0.tgz", + "integrity": "sha512-O5ND5Ljpef86X5oy8zXorQ754TMjWALcPSAgPBu4+76HLtDTrNoDyzU2uGE2G4A8Wv51u0MXHzGQ0WZ4GMtpIw==", + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@sentry/core": { "version": "6.13.2", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.13.2.tgz", @@ -486,6 +655,17 @@ "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" }, + "node_modules/@sindresorhus/is": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", + "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -509,6 +689,28 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.2.tgz", "integrity": "sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ==" }, + "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/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/webidl-conversions": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", @@ -523,6 +725,14 @@ "@types/webidl-conversions": "*" } }, + "node_modules/@types/ws": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz", + "integrity": "sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -557,18 +767,6 @@ "node": ">= 0.6" } }, - "node_modules/acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/adm-zip": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.6.tgz", @@ -869,6 +1067,16 @@ "node": ">=0.10.0" } }, + "node_modules/ast-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ast-parser/-/ast-parser-0.1.1.tgz", + "integrity": "sha512-IFkSxogYovWJivO7cnjaCQatLRPV7i3tzCbGFi9QGHczxJzkxKFuJYdwBGdRLg0f1nAqaHS2k9k1GO0INZ+gKQ==", + "dependencies": { + "@babel/traverse": "^7.2.3", + "@babel/types": "^7.3.0", + "@daybrush/utils": "^0.11.0" + } + }, "node_modules/astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -1310,6 +1518,19 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "node_modules/bufferutil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", + "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -1449,13 +1670,13 @@ } }, "node_modules/canvas": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz", - "integrity": "sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.0.tgz", + "integrity": "sha512-0l93g7uxp7rMyr7H+XRQ28A3ud0dKIUTIEkUe1Dxh4rjUYN7B93+SjC3r1PDKA18xcQN87OFGgUnyw7LSgNLSQ==", "hasInstallScript": true, "dependencies": { "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.14.0", + "nan": "^2.15.0", "simple-get": "^3.0.3" }, "engines": { @@ -2506,6 +2727,18 @@ "node-source-walk": "^3.0.0" } }, + "node_modules/detective/node_modules/acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/diacritics": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/diacritics/-/diacritics-1.3.0.tgz", @@ -2520,23 +2753,65 @@ "node": ">=0.3.1" } }, + "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": ">=12" + } + }, "node_modules/discord.js": { - "version": "12.5.3", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", - "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", - "deprecated": "no longer supported", - "dependencies": { - "@discordjs/collection": "^0.1.6", - "@discordjs/form-data": "^3.0.1", - "abort-controller": "^3.0.0", + "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", - "prism-media": "^1.2.9", - "setimmediate": "^1.0.5", - "tweetnacl": "^1.0.3", - "ws": "^7.4.4" + "ws": "^8.4.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=16.6.0", + "npm": ">=7.0.0" + } + }, + "node_modules/discord.js/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/discord.js/node_modules/ws": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz", + "integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/docopt": { @@ -2728,17 +3003,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/erlpack": { - "version": "0.1.3", - "resolved": "git+ssh://git@github.com/discord/erlpack.git#f7d730debe32c416d1b55b4217f8aef2ade05874", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.15.0" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -6504,6 +6768,17 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/json-bigint": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", @@ -8316,44 +8591,17 @@ "node": ">= 6.0.0" } }, - "node_modules/node-opus": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/node-opus/-/node-opus-0.3.3.tgz", - "integrity": "sha512-ZQniA8iJ6y/qOTmW6eyzM9m8odt4CIGV0NM9/U03/pYLhGyxy18QXO25WfrWd8XsUYx57tnxll2xxj54CN08uQ==", - "cpu": [ - "x64", - "arm", - "arm64", - "ia32" - ], - "deprecated": "This project is unmaintained. See @discordjs/opus for an alternative.", - "hasInstallScript": true, + "node_modules/node-gyp-build": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", "optional": true, - "os": [ - "linux", - "darwin", - "win32", - "freebsd", - "android" - ], - "dependencies": { - "bindings": "~1.2.1", - "commander": "^2.9.0", - "nan": "^2.14.0" - }, - "engines": { - "node": ">=5.10.0" - }, - "optionalDependencies": { - "ogg-packet": "^1.0.0" + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" } }, - "node_modules/node-opus/node_modules/bindings": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", - "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=", - "optional": true - }, "node_modules/node-source-walk": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-3.3.0.tgz", @@ -9712,31 +9960,6 @@ "node": ">=0.10.0" } }, - "node_modules/prism-media": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.2.tgz", - "integrity": "sha512-L6UsGHcT6i4wrQhFF1aPK+MNYgjRqR2tUoIqEY+CG1NqVkMjPRKzS37j9f8GiYPlD6wG9ruBj+q5Ax+bH8Ik1g==", - "peerDependencies": { - "@discordjs/opus": "^0.5.0", - "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0", - "node-opus": "^0.3.3", - "opusscript": "^0.0.8" - }, - "peerDependenciesMeta": { - "@discordjs/opus": { - "optional": true - }, - "ffmpeg-static": { - "optional": true - }, - "node-opus": { - "optional": true - }, - "opusscript": { - "optional": true - } - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -10902,11 +11125,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/setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", @@ -11372,7 +11590,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -12451,6 +12668,14 @@ "node": ">=0.6.0" } }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "engines": { + "node": ">=4" + } + }, "node_modules/to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -12590,6 +12815,11 @@ "resolved": "https://registry.npmjs.org/transform-props/-/transform-props-1.0.1.tgz", "integrity": "sha1-yY6jLXYDH5uDVhsVdd/7WLOaexw=" }, + "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/tsconfig-paths": { "version": "3.11.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", @@ -12635,11 +12865,6 @@ "domino": "^2.1.6" } }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, "node_modules/type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -12944,6 +13169,19 @@ "lodash.clonedeep": "^4.5.0" } }, + "node_modules/utf-8-validate": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.8.tgz", + "integrity": "sha512-k4dW/Qja1BYDl2qD4tOMB9PFVha/UJtxTc1cXYOe3WwA/2m0Yn4qB7wLMpJyLJ/7DR0XnTut3HsCSzDT4ZvKgA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -12965,11 +13203,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/uws": { - "version": "200.0.0", - "resolved": "https://registry.npmjs.org/uws/-/uws-200.0.0.tgz", - "integrity": "sha512-A2j/p+tJBHZ2MtRoMjVqXMzstpyiZkHcV+XzLQ021h63aqHt5P6l0QkR87L0OASvesjMG42Qo97uyEmPB98+3g==" - }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -13633,6 +13866,14 @@ "dependencies": { "nan": "^2.14.0" } + }, + "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": { @@ -13644,17 +13885,69 @@ "@babel/highlight": "^7.10.4" } }, + "@babel/generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz", + "integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==", + "requires": { + "@babel/types": "^7.16.8", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", + "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "requires": { + "@babel/helper-get-function-arity": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", + "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "requires": { + "@babel/types": "^7.16.7" + } + }, "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" }, "@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", "requires": { - "@babel/helper-validator-identifier": "^7.12.11", + "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -13705,6 +13998,11 @@ } } }, + "@babel/parser": { + "version": "7.16.12", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", + "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==" + }, "@babel/runtime": { "version": "7.15.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", @@ -13713,26 +14011,90 @@ "regenerator-runtime": "^0.13.4" } }, - "@discordjs/collection": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", - "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "requires": { + "@babel/highlight": "^7.16.7" + } + } + } }, - "@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==", + "@babel/traverse": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz", + "integrity": "sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==", "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.16.8", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.16.10", + "@babel/types": "^7.16.8", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "requires": { + "@babel/highlight": "^7.16.7" + } + } } }, - "@discordjs/uws": { - "version": "11.149.1", - "resolved": "https://registry.npmjs.org/@discordjs/uws/-/uws-11.149.1.tgz", - "integrity": "sha512-TmbwZaeXDSCq0ckmf2q10Fkt1220gu9AZJ/UvtQjsi2jyJDjy0i0OwL4/eb3vc9Cwr0mpC9EbfzltQ2si0qUiQ==", - "optional": true + "@babel/types": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz", + "integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==", + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + }, + "@daybrush/utils": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@daybrush/utils/-/utils-0.11.0.tgz", + "integrity": "sha512-PnrY1NDjXqXKASoREcjHokQt0WWHiUBClMJ0l9APx42QkeOCQ5nXB7k4VdmkaU23BndeSmNNYJDNL6eEsRitaA==" + }, + "@discordjs/builders": { + "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.26.0", + "ts-mixer": "^6.0.0", + "tslib": "^2.3.1", + "zod": "^3.11.6" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "@discordjs/collection": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.4.0.tgz", + "integrity": "sha512-zmjq+l/rV35kE6zRrwe8BHqV78JvIh2ybJeZavBi5NySjWXqN3hmmAKg7kYMMXSeiWtSsMoZ/+MQi0DiQWy2lw==" }, "@eslint/eslintrc": { "version": "0.4.3", @@ -13846,6 +14208,11 @@ } } }, + "@sapphire/async-queue": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.2.0.tgz", + "integrity": "sha512-O5ND5Ljpef86X5oy8zXorQ754TMjWALcPSAgPBu4+76HLtDTrNoDyzU2uGE2G4A8Wv51u0MXHzGQ0WZ4GMtpIw==" + }, "@sentry/core": { "version": "6.13.2", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.13.2.tgz", @@ -13945,6 +14312,11 @@ "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" }, + "@sindresorhus/is": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", + "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==" + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -13965,6 +14337,27 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.2.tgz", "integrity": "sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ==" }, + "@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" + }, + "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/webidl-conversions": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", @@ -13979,6 +14372,14 @@ "@types/webidl-conversions": "*" } }, + "@types/ws": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz", + "integrity": "sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==", + "requires": { + "@types/node": "*" + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -14007,12 +14408,6 @@ "negotiator": "0.6.2" } }, - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - }, "adm-zip": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.6.tgz", @@ -14239,6 +14634,16 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "ast-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ast-parser/-/ast-parser-0.1.1.tgz", + "integrity": "sha512-IFkSxogYovWJivO7cnjaCQatLRPV7i3tzCbGFi9QGHczxJzkxKFuJYdwBGdRLg0f1nAqaHS2k9k1GO0INZ+gKQ==", + "requires": { + "@babel/traverse": "^7.2.3", + "@babel/types": "^7.3.0", + "@daybrush/utils": "^0.11.0" + } + }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -14578,6 +14983,15 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "bufferutil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", + "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "optional": true, + "requires": { + "node-gyp-build": "^4.3.0" + } + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -14679,12 +15093,12 @@ "dev": true }, "canvas": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz", - "integrity": "sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.9.0.tgz", + "integrity": "sha512-0l93g7uxp7rMyr7H+XRQ28A3ud0dKIUTIEkUe1Dxh4rjUYN7B93+SjC3r1PDKA18xcQN87OFGgUnyw7LSgNLSQ==", "requires": { "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.14.0", + "nan": "^2.15.0", "simple-get": "^3.0.3" } }, @@ -15490,6 +15904,14 @@ "requires": { "acorn": "^3.1.0", "defined": "^1.0.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } } }, "detective-es6": { @@ -15512,19 +15934,43 @@ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, + "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==" + }, "discord.js": { - "version": "12.5.3", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz", - "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==", - "requires": { - "@discordjs/collection": "^0.1.6", - "@discordjs/form-data": "^3.0.1", - "abort-controller": "^3.0.0", + "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", - "prism-media": "^1.2.9", - "setimmediate": "^1.0.5", - "tweetnacl": "^1.0.3", - "ws": "^7.4.4" + "ws": "^8.4.0" + }, + "dependencies": { + "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" + } + }, + "ws": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz", + "integrity": "sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==", + "requires": {} + } } }, "docopt": { @@ -15673,15 +16119,6 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" }, - "erlpack": { - "version": "git+ssh://git@github.com/discord/erlpack.git#f7d730debe32c416d1b55b4217f8aef2ade05874", - "from": "erlpack@github:discord/erlpack", - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.15.0" - } - }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -18548,6 +18985,11 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, "json-bigint": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", @@ -19977,25 +20419,11 @@ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" }, - "node-opus": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/node-opus/-/node-opus-0.3.3.tgz", - "integrity": "sha512-ZQniA8iJ6y/qOTmW6eyzM9m8odt4CIGV0NM9/U03/pYLhGyxy18QXO25WfrWd8XsUYx57tnxll2xxj54CN08uQ==", - "optional": true, - "requires": { - "bindings": "~1.2.1", - "commander": "^2.9.0", - "nan": "^2.14.0", - "ogg-packet": "^1.0.0" - }, - "dependencies": { - "bindings": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", - "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=", - "optional": true - } - } + "node-gyp-build": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "optional": true }, "node-source-walk": { "version": "3.3.0", @@ -21015,12 +21443,6 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, - "prism-media": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.2.tgz", - "integrity": "sha512-L6UsGHcT6i4wrQhFF1aPK+MNYgjRqR2tUoIqEY+CG1NqVkMjPRKzS37j9f8GiYPlD6wG9ruBj+q5Ax+bH8Ik1g==", - "requires": {} - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -21990,11 +22412,6 @@ } } }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", @@ -22361,8 +22778,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-resolve": { "version": "0.5.3", @@ -23178,6 +23594,11 @@ "os-tmpdir": "~1.0.2" } }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -23290,6 +23711,11 @@ "resolved": "https://registry.npmjs.org/transform-props/-/transform-props-1.0.1.tgz", "integrity": "sha1-yY6jLXYDH5uDVhsVdd/7WLOaexw=" }, + "ts-mixer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", + "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==" + }, "tsconfig-paths": { "version": "3.11.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", @@ -23331,11 +23757,6 @@ "domino": "^2.1.6" } }, - "tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -23589,6 +24010,15 @@ "lodash.clonedeep": "^4.5.0" } }, + "utf-8-validate": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.8.tgz", + "integrity": "sha512-k4dW/Qja1BYDl2qD4tOMB9PFVha/UJtxTc1cXYOe3WwA/2m0Yn4qB7wLMpJyLJ/7DR0XnTut3HsCSzDT4ZvKgA==", + "optional": true, + "requires": { + "node-gyp-build": "^4.3.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -23604,11 +24034,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, - "uws": { - "version": "200.0.0", - "resolved": "https://registry.npmjs.org/uws/-/uws-200.0.0.tgz", - "integrity": "sha512-A2j/p+tJBHZ2MtRoMjVqXMzstpyiZkHcV+XzLQ021h63aqHt5P6l0QkR87L0OASvesjMG42Qo97uyEmPB98+3g==" - }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -24117,6 +24542,11 @@ "requires": { "nan": "^2.14.0" } + }, + "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 306bcb2c6..207b270a7 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "abort-controller": "^3.0.0", "adm-zip": "^0.5.6", "ascii-table": "0.0.9", + "ast-parser": "^0.1.1", "axios": "^0.21.4", "brainfuck-node": "^1.0.2", "bunyan": "^1.8.15", @@ -46,7 +47,7 @@ "cors": "^2.8.5", "cows": "^2.1.1", "cowsay": "^1.5.0", - "discord.js": "^12.5.1", + "discord.js": "^13.6.0", "express": "^4.17.1", "figlet": "^1.5.2", "fuse.js": "^6.4.6", @@ -85,7 +86,6 @@ "steamladder": "^1.0.7", "transform-props": "^1.0.1", "turndown": "^7.1.1", - "uws": "^200.0.0", "wikijs": "^6.3.2", "xml2json": "^0.12.0", "zlib-sync": "^0.1.7" @@ -110,9 +110,8 @@ "delay": "5000" }, "optionalDependencies": { - "@discordjs/uws": "^11.149.1", - "canvas": "^2.8.0", - "erlpack": "github:discord/erlpack", - "node-opus": "^0.3.3" + "bufferutil": "^4.0.6", + "canvas": "^2.9.0", + "utf-8-validate": "^5.0.8" } } diff --git a/src/Switchblade.js b/src/Switchblade.js index d7bd66817..529e562cf 100644 --- a/src/Switchblade.js +++ b/src/Switchblade.js @@ -80,8 +80,8 @@ module.exports = class Switchblade extends Client { : null return cmd ? deepSubcmd(cmd, a.slice(1)) : c } - const verify = await this.modules.commandRules.verifyCommand(deepSubcmd(command, args), context) - if (!verify) return + /*const verify = await this.modules.commandRules.verifyCommand(deepSubcmd(command, args), context) + if (!verify) return */ } context.setFixedT(this.i18next.getFixedT(language)) diff --git a/src/commands/bot/help.js b/src/commands/bot/help.js deleted file mode 100644 index 4b7997c1a..000000000 --- a/src/commands/bot/help.js +++ /dev/null @@ -1,59 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class Help extends Command { - constructor (client) { - super({ - name: 'help', - aliases: ['commands', 'ajuda', 'halp'], - category: 'bot', - parameters: [{ - type: 'command', full: true, required: false - }] - }, client) - } - - async run ({ t, author, channel, guild, prefix }, command) { - const embed = new SwitchbladeEmbed(author) - - if (command) { - const description = [ - t([`commands:${command.tPath}.commandDescription`, 'commands:help.noDescriptionProvided']), - '', - command.usage(t, prefix, false) - ] - - if (command.aliases && command.aliases.length > 0) description.push(`**${t('commands:help.aliases')}:** ${command.aliases.map(a => `\`${a}\``).join(', ')}`) - if (command.subcommands.length > 0) description.push(`**${t('commands:help.subcommands')}:** ${command.subcommands.map(a => `\`${a.name}\``).join(', ')}`) - if (command.requirements && command.requirements.permissions && command.requirements.permissions.length > 0) description.push(`**${t('commands:help.permissions')}:** ${command.requirements.permissions.map(p => `\`${t(`permissions:${p}`)}\``).join(', ')}`) - if (command.requirements && command.requirements.botPermissions && command.requirements.botPermissions.length > 0) description.push(`**${t('commands:help.botPermissions')}:** ${command.requirements.botPermissions.map(p => `\`${t(`permissions:${p}`)}\``).join(', ')}`) - - embed.setTitle(command.fullName) - .setDescription(description.join('\n')) - } else { - const botMention = `<@!${this.client.user.id}>` - embed - .setAuthor(t('commands:help.listTitle'), this.client.user.displayAvatarURL({ format: 'png' })) - .setDescription([ - `**${t('commands:help.prefix')}:** \`${prefix}\` (${t('commands:help.youCanUse', { botMention })})`, - `**${t('commands:help.specificInformation', { helpString: `\`${prefix}${this.name} ${t('commands:help.commandUsage')}\`` })}**` - ].join('\n')) - - const validCommands = this.client.commands.filter(c => !c.hidden && (channel.nsfw || c.category !== 'nsfw')) - const categories = validCommands.map(c => c.category).filter((v, i, a) => a.indexOf(v) === i) - categories - .sort((a, b) => t(`categories:${a}`).localeCompare(t(`categories:${b}`))) - .forEach(category => { - const commands = validCommands - .filter(c => c.category === category) - .sort((a, b) => a.name.localeCompare(b.name)) - .map(c => `\`${c.name}\``).join('**, **') - - const length = validCommands - .filter(c => c.category === category).length - - embed.addField(`${t(`categories:${category}`)} [**${length}**]`, commands, false) - }) - } - channel.send(embed) - } -} diff --git a/src/commands/bot/shards.js b/src/commands/bot/shards.js deleted file mode 100644 index 2668fed04..000000000 --- a/src/commands/bot/shards.js +++ /dev/null @@ -1,28 +0,0 @@ -const { Command, MiscUtils } = require('../../') -const AsciiTable = require('ascii-table') - -module.exports = class Shards extends Command { - constructor (client) { - super({ - name: 'shards', - category: 'bot' - }, client) - } - - async run ({ channel }) { - const table = new AsciiTable() - .setHeading('Shard', 'Servers', 'Cached Users', 'Ping') - .setAlign(0, AsciiTable.CENTER) - .setAlign(1, AsciiTable.CENTER) - .setAlign(2, AsciiTable.CENTER) - .setAlign(3, AsciiTable.CENTER) - .removeBorder() - const guildCount = await this.client.shard.fetchClientValues('guilds.cache.size') - const users = await this.client.shard.fetchClientValues('users.cache.size') - const ping = await this.client.shard.fetchClientValues('ws.ping') - guildCount.forEach((count, shardId) => { - table.addRow(shardId, MiscUtils.formatNumber(count), MiscUtils.formatNumber(users[shardId]), `${MiscUtils.formatNumber(ping[shardId])}ms`) - }) - channel.send(`\`\`\`${table.toString()}\`\`\``) - } -} diff --git a/src/commands/configuration/prefix.js b/src/commands/configuration/prefix.js deleted file mode 100644 index 6981e5273..000000000 --- a/src/commands/configuration/prefix.js +++ /dev/null @@ -1,31 +0,0 @@ -const { Command, SwitchbladeEmbed, Constants } = require('../../') - -module.exports = class ConfigPrefix extends Command { - constructor (client) { - super({ - name: 'prefix', - parent: 'config', - parameters: [{ - type: 'string', - full: true, - required: false, - maxLength: 50, - missingError: 'commands:config.subcommands.prefix.noPrefix' - }] - }, client) - } - - async run ({ t, author, channel, guild }, prefix = process.env.PREFIX) { - const embed = new SwitchbladeEmbed(author) - - try { - await this.client.modules.prefix.updateValues(guild.id, { prefix }) - embed.setTitle(t('commands:config.subcommands.prefix.changedSuccessfully', { prefix })) - } catch (e) { - embed.setColor(Constants.ERROR_COLOR) - .setTitle(t('errors:generic')) - } - - channel.send(embed) - } -} diff --git a/src/commands/developers/eval.js b/src/commands/developers/eval.js index bed1bfbff..b9f25fc62 100644 --- a/src/commands/developers/eval.js +++ b/src/commands/developers/eval.js @@ -17,13 +17,13 @@ module.exports = class Eval extends Command { }, client) } - async run ({ channel, message }, expr) { + async run ({ channel, message, t }, expr) { try { const evaled = await eval(expr.replace(/(^`{3}(\w+)?|`{3}$)/g, '')) const cleanEvaled = this.clean(util.inspect(evaled, { depth: 0 })).replace(this.client.token, '*'.repeat(this.client.token.length)) await channel.send(cleanEvaled, { code: 'xl' }) } catch (err) { - channel.send('`ERROR` ```xl\n' + this.clean(err) + '\n```') + channel.send('`ERROR` ```xl\n' + this.clean(err.stack) + '\n```') } } diff --git a/src/commands/developers/reloadlocales.js b/src/commands/developers/reloadlocales.js deleted file mode 100644 index b647ca6de..000000000 --- a/src/commands/developers/reloadlocales.js +++ /dev/null @@ -1,29 +0,0 @@ -const { Command, SwitchbladeEmbed, Constants } = require('../../') - -module.exports = class reloadlocales extends Command { - constructor (client) { - super({ - name: 'reloadlocales', - category: 'developers', - hidden: true, - requirements: { managersOnly: true } - }, client) - } - - async run ({ t, channel, author }) { - channel.startTyping() - const embed = new SwitchbladeEmbed(author) - try { - this.client.downloadAndInitializeLocales('src/locales').then(() => { - embed - .setTitle(t('commands:reloadlocales:reloaded')) - channel.send(embed).then(() => channel.stopTyping()) - }) - } catch (e) { - embed - .setColor(Constants.ERROR_COLOR) - .setTitle(t('errors:generic')) - channel.send(embed).then(() => channel.stopTyping()) - } - } -} diff --git a/src/commands/games/beatsaver.js b/src/commands/games/beatsaver.js deleted file mode 100644 index 46d793735..000000000 --- a/src/commands/games/beatsaver.js +++ /dev/null @@ -1,38 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed } = require('../../') - -module.exports = class BeatSaver extends SearchCommand { - constructor (client) { - super({ - name: 'beatsaver', - aliases: ['beatsaber', 'bsaver'], - category: 'games', - embedColor: 0x3C347B, - embedLogoURL: 'https://i.imgur.com/yK8SmyX.png' - }, client) - } - - search (context, query) { - return this.client.apis.beatsaver.searchMaps(query) - } - - searchResultFormatter ({ metadata, key, uploader }) { - return `[${metadata.songName}](${'https://beatsaver.com/beatmap/' + key}) - [${metadata.levelAuthorName}](${'https://beatsaver.com/uploader/' + uploader._id})` - } - - async handleResult ({ t, channel, author }, map) { - const embed = new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor('Beat Saver', 'https://i.imgur.com/yK8SmyX.png') - .setTitle(map.metadata.songName) - .setThumbnail('https://beatsaver.com' + map.coverURL) - .setDescription([ - map.description, - '', - `**[${t('commands:beatsaver.download')}](${'https://beatsaver.com' + map.directDownload})** - [${t('commands:beatsaver.details')}](${'https://beatsaver.com/beatmap/' + map.key})` - ]) - .setTimestamp(new Date(map.uploaded)) - .setFooter(map.metadata.levelAuthorName) - - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/games/chorus.js b/src/commands/games/chorus.js deleted file mode 100644 index 6b567725e..000000000 --- a/src/commands/games/chorus.js +++ /dev/null @@ -1,115 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, MiscUtils, Constants } = require('../../') - -const icon = 'https://chorus.fightthe.pw/assets/images/favicon_128.png' -const instruments = ['drums', 'guitarghl', 'keys', 'guitar', 'bassghl', 'bass'] -const warningLinks = { - driveFolderExampleLink: 'https://i.imgur.com/DsTwJsv.png' -} - -module.exports = class Chorus extends SearchCommand { - constructor (client) { - super({ - name: 'chorus', - aliases: ['clonehero', 'chart'], - requirements: { - apis: ['chorus'] - }, - embedColor: Constants.CHORUS_COLOR, - embedLogoURL: icon - }, client) - } - - async search (context, query) { - const results = await this.client.apis.chorus.search(query) - return results - } - - searchResultFormatter (chart) { - return `${chart.artist} - **[${chart.name}](${chart.link})**${chart.noteCounts && chart.noteCounts.guitar ? ` **[${this.getDifficultyString(chart.noteCounts.guitar)}]**` : ''}${chart.charter ? ` \`(${chart.charter})\`` : ''}` - } - - async handleResult ({ t, channel, author, language }, chart) { - const features = { - hasOpen: chart.hasOpen && Object.keys(chart.hasOpen).length > 0, - hasForced: chart.hasForced, - hasTap: chart.hasTap, - hasSections: chart.hasSections, - hasSoloSections: chart.hasSoloSections, - hasStarPower: chart.hasStarPower, - hasStems: chart.hasStems, - hasVideo: chart.hasVideo, - hasLyrics: chart.hasLyrics - } - - const warnings = { - driveFolder: chart.isFolder && chart.link, - needsRenaming: chart.needsRenaming, - is120: chart.is120, - hasNoAudio: chart.hasNoAudio, - no5FretLead: !chart.noteCounts || !chart.noteCounts.guitar, - hasBrokenNotes: chart.hasBrokenNotes, - notesAfterEnd: chart.length && chart.effectiveLength && chart.effectiveLength > chart.length - } - - const nps = this.getNotePerSecondAverage(chart.effectiveLength, chart.noteCounts) - - channel.send( - new SwitchbladeEmbed(author) - .setColor(Constants.CHORUS_COLOR) - .setAuthor('chorus', icon, 'https://chorus.fightthe.pw/') - .setTitle(`${chart.artist} - ${chart.name}`) - .setDescriptionFromBlockArray([ - [ - chart.album ? `**${chart.album}${chart.year ? ` (${chart.year})` : ''}**` : (chart.year ? `**${chart.year}**` : null), // Album name (album year) - chart.genre, - chart.length && chart.effectiveLength ? `${MiscUtils.formatDuration(chart.length * 1000)} (${MiscUtils.formatDuration(chart.effectiveLength * 1000)})` : null // Chart length (effective length) - ], - [ - Object.keys(features).filter(k => features[k]).map(k => `\`${t(`commands:chorus.features.${k}`)}\``).join(', ') // Chart features - ], - [ - Object.keys(warnings).filter(k => warnings[k]).map(k => `**>** _${t(`commands:chorus.warnings.${k}`, warningLinks)}_`).join('\n') // Chart warnings - ], - [ - `**${this.getNotePerSecondRating(t, nps)}**`, // NPS Rating - t('commands:chorus.notesPerSecond', { nps }) // NPS average - ], - [ - chart.noteCounts && Object.keys(chart.noteCounts).filter(i => instruments.includes(i)).length > 0 ? `${Object.keys(chart.noteCounts).filter(i => instruments.includes(i)).map(i => `${this.getEmoji(i)} ${this.getDifficultyString(chart.noteCounts[i])}`).join(' ')}` : null // Difficulties per instrument - ], - [ - `[${this.getDownloadLinkText(chart, t)}](${chart.link})`, // Download link - chart.sources[0] ? (chart.sources[0].isSetlist && chart.sources[0].name && chart.sources[0].link ? `[${t('commands:chorus.downloadFullSetlist', { setlistName: chart.sources[0].name })}](${chart.sources[0].link})` : null) : null // Download full setlist link - ] - ]) - .addField(t('commands:chorus.source', { count: chart.sources.length }), chart.sources.map(s => `${s.parent ? `[${s.parent.name}](${s.parent.link}) in ` : ''}${`[${s.name}](${s.link})`}`).join('\n')) - ) - } - - getDownloadLinkText (chart, t) { - if (!chart.charter) return t('commands:chorus.downloadHere', { charterName: chart.charter }) - if (chart.isPack) return t('commands:chorus.downloadPack', { charterName: chart.charter }) - return t('commands:chorus.downloadChart', { charterName: chart.charter }) - } - - getDifficultyString (instrument) { - let string = '' - if (instrument.e) string += 'E' - if (instrument.m) string += 'M' - if (instrument.h) string += 'H' - if (instrument.x) string += 'X' - return string - } - - getNotePerSecondAverage (length, noteCounts) { - if (!noteCounts) return 0 - const instrument = noteCounts.guitar ? 'guitar' : Object.keys(noteCounts)[0] - if (!instrument || !noteCounts[instrument]) return 0 - const difficulty = ['x', 'h', 'm', 'e'].find(d => noteCounts[instrument][d]) - return (noteCounts[instrument][difficulty] / length).toFixed(2) - } - - getNotePerSecondRating (t, average) { - return average > 15 ? t('commands:chorus.noteDensityRatings.15') : t(`commands:chorus.noteDensityRatings.${average >> 0}`) - } -} diff --git a/src/commands/games/freefire.js b/src/commands/games/freefire.js deleted file mode 100644 index 497963f5b..000000000 --- a/src/commands/games/freefire.js +++ /dev/null @@ -1,12 +0,0 @@ -const { SubcommandListCommand } = require('../../') - -module.exports = class FreeFire extends SubcommandListCommand { - constructor (client) { - super({ - name: 'freefire', - aliases: ['ff'], - category: 'games', - authorString: 'commands:freefire.gameName' - }, client) - } -} diff --git a/src/commands/games/freefire/weapon.js b/src/commands/games/freefire/weapon.js deleted file mode 100644 index 43f341369..000000000 --- a/src/commands/games/freefire/weapon.js +++ /dev/null @@ -1,76 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed } = require('../../../') - -const Fuse = require('fuse.js') - -module.exports = class FreeFireWeapon extends Command { - constructor (client) { - super({ - name: 'weapon', - aliases: ['w'], - parent: 'freefire', - parameters: [{ - type: 'string', full: true, missingError: 'commands:freefire.subcommands.weapon.missingWeapon' - }] - }, client) - } - - async run ({ t, channel, language }, query) { - const { - weapons, - commons: { attribute_names: attributeNames, attachment_names: attachmentNames } - } = await this.client.apis.freefire.getWeaponData(language) - - const fuse = new Fuse(weapons, { - shouldSort: true, - maxPatternLength: 32, - minMatchCharLength: 1, - keys: [ - 'name' - ] - }) - - const weapon = fuse.search(query)[0] - - if (!weapon) { - throw new CommandError(t('commands:freefire.subcommands.weapon.unknownWeapon', { - weapon: query - })) - } - - const embed = new SwitchbladeEmbed() - .setTitle(weapon.name) - .setDescriptionFromBlockArray([ - [ - weapon.description - ], - [ - weapon.ammunition ? `**${t('commands:freefire.subcommands.weapon.ammunition')}:** ${weapon.ammunition}` : null - ], - [ - weapon.labels.map(l => `\`${l}\``).join(', ') - ] - ]) - .addFields([ - { - name: t('commands:freefire.subcommands.weapon.attributes'), - value: this.getInfo({ weapon, data: 'attributes', names: attributeNames }), - inline: true - }, - { - name: t('commands:freefire.subcommands.weapon.attachments'), - value: this.getInfo({ weapon, data: 'attachments', names: attachmentNames }), - inline: true - } - ]) - .setImage(weapon.skins[0].image_url) - - await channel.send(embed) - } - - getInfo ({ weapon, data, names }) { - return Object.entries(weapon[data]) - .filter(([key, value]) => value.avaliable || value >= 1) - .map(([key, value]) => ` - **${names[key]}**${data !== 'attachments' ? `: ${value}` : ''}`) - .join('\n') - } -} diff --git a/src/commands/games/howlongtobeat.js b/src/commands/games/howlongtobeat.js deleted file mode 100644 index fbdb67960..000000000 --- a/src/commands/games/howlongtobeat.js +++ /dev/null @@ -1,44 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed, Constants } = require('../../') -const hltb = require('howlongtobeat') -const hltbService = new hltb.HowLongToBeatService() - -module.exports = class HowLongToBeat extends Command { - constructor (client) { - super( - { - name: 'howlongtobeat', - aliases: ['hltb'], - category: 'games', - parameters: [ - { - type: 'string', - missingError: 'commands:howlongtobeat.missingGame' - } - ] - }, - client - ) - } - - async run ({ t, author, channel, guild }, game) { - try { - const gameData = await hltbService.search(game) - - if (gameData.length === 0) { - throw new Error() - } else { - const gameResult = gameData[0] - const description = gameResult.timeLabels.map(timeLabel => `${timeLabel[1]} : ${gameResult[timeLabel[0]]} hrs`).join('\n') - channel.send( - new SwitchbladeEmbed(author) - .setTitle(t('commands:howlongtobeat.title', { game: gameResult.name })) - .setDescription(description) - .setImage(`https://howlongtobeat.com${gameResult.imageUrl}`) - .setColor(Constants.HOW_LONG_TO_BEAT_COLOR) - ) - } - } catch { - throw new CommandError(t('commands:howlongtobeat.invalidGame'), true) - } - } -} diff --git a/src/commands/games/igdb.js b/src/commands/games/igdb.js deleted file mode 100644 index 4fbde87b0..000000000 --- a/src/commands/games/igdb.js +++ /dev/null @@ -1,147 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, PaginatedEmbed, Constants } = require('../../') -const moment = require('moment') -const { CommandError } = require('../../structures/command') - -const RATINGS = { - 1: '3+', - 2: '7+', - 3: '12+', - 4: '16+', - 5: '18+', - 6: 'RP', - 7: 'EC', - 8: 'E', - 9: 'E10', - 10: 'T', - 11: 'M', - 12: 'AO' -} - -const REGIONS = { - 1: ':flag_eu:', - 2: ':flag_us:', - 3: ':flag_au:', - 4: ':flag_nz:', - 5: ':flag_jp:', - 6: ':flag_cn:', - 7: ':earth_asia:', - 8: ':globe_with_meridians:' -} - -module.exports = class IGDB extends SearchCommand { - constructor (client) { - super({ - name: 'igdb', - aliases: ['game'], - requirements: { apis: ['igdb'] }, - parameters: [{ - type: 'string', full: true, missingError: 'commands:igdb.noGame' - }], - embedColor: '#9345FA', - embedLogoURL: 'https://i.imgur.com/T0iuwzs.jpg' - }, client) - } - - async search (context, query) { - return this.client.apis.igdb.searchGame(query) - } - - searchResultFormatter (obj) { - return `[${obj.name}](${obj.url})` - } - - async handleResult ({ t, channel, author, language }, { id }) { - channel.startTyping() - moment.locale(language) - - try { - const gameData = await this.client.apis.igdb.getGameById(id) - - let alternativeNames - // Updating data outside of the embed, so it doesn't get cluttered - if (gameData.alternative_names) { - alternativeNames = gameData.alternative_names.length > 5 ? gameData.alternative_names.slice(0, 5) : gameData.alternative_names - } - - const paginatedEmbed = new PaginatedEmbed(t, author) - - const firstEmbed = new SwitchbladeEmbed(author) - .setTitle(`${gameData.name} ${gameData.alternative_names ? t('commands:igdb.aka', { aliases: alternativeNames.map(n => `${n.name}`).join(', ') }) : ''}`) - .setURL(gameData.url) - .setThumbnail(`https:${gameData.cover.url}`) - .setDescription(gameData.summary ? gameData.summary : '') - - if (gameData.age_ratings) { - firstEmbed.addField(t('commands:igdb.ageRating'), gameData.age_ratings.map(r => { - return `**${r.category === 1 ? 'ESRB' : 'PEGI'}**: ${RATINGS[r.rating]}` - }).join('\n')) - } - - firstEmbed.addField(t('commands:igdb.genres'), gameData.genres.map(g => g.name).join(', ')) - .addField(t('commands:igdb.platforms'), gameData.platforms.map(p => p.name).join(', ')) - .addField(t('commands:igdb.popularity'), `${Number(gameData.popularity).toFixed(2)}%`) - .addField(t('commands:igdb.ratingTitle'), t('commands:igdb.ratingDescription', { value: `${Number(gameData.total_rating).toFixed(2)}%`, total: gameData.total_rating_count })) - - paginatedEmbed.addPage(firstEmbed) - - if (gameData.release_dates) { - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setAuthor(`${gameData.name} - ${t('commands:igdb.releaseDates')}`) - .setURL(gameData.url) - .setThumbnail(`https:${gameData.cover.url}`) - .setDescription(gameData.release_dates.map(r => { - return `${REGIONS[r.region]} **${r.platform.name}:** ${moment(r.date, 'X').format('LL')}` - }).join('\n')) - ) - } - - if (gameData.dlcs) { - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setAuthor(`${gameData.name} - ${t('commands:igdb.dlcs')}`) - .setURL(gameData.url) - .setThumbnail(`https:${gameData.cover.url}`) - .setDescription(gameData.dlcs.map(d => { - return `**${d.name}**: ${moment(d.first_release_date, 'X').format('LL')}` - }).join('\n')) - ) - } - - if (gameData.expansions) { - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setAuthor(`${gameData.name} - ${t('commands:igdb.expansions')}`) - .setURL(gameData.url) - .setThumbnail(`https:${gameData.cover.url}`) - .setDescription(gameData.expansions.map(e => { - return `**${e.name}**: ${moment(e.first_release_date, 'X').format('LL')}` - }).join('\n')) - ) - } - - if (gameData.involved_companies) { - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setAuthor(`${gameData.name} - ${t('commands:igdb.companies')}`) - .setURL(gameData.url) - .setThumbnail(`https:${gameData.cover.url}`) - .setDescription(gameData.involved_companies.map(c => c.company.name).join('\n')) - ) - } - - if (gameData.similar_games) { - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setAuthor(`${gameData.name} - ${t('commands:igdb.similarGames')}`) - .setURL(gameData.url) - .setThumbnail(`https:${gameData.cover.url}`) - .setDescription(gameData.similar_games.map(g => { - return `**${g.name}**: ${moment(g.first_release_date, 'X').format('LL')}` - }).join('\n')) - ) - } - - paginatedEmbed.run(await channel.send(Constants.EMPTY_SPACE)) - } catch (err) { - throw new CommandError(t('commands:igdb.error', { err })) - } - - channel.stopTyping() - } -} diff --git a/src/commands/games/osu.js b/src/commands/games/osu.js deleted file mode 100644 index 69e98c19f..000000000 --- a/src/commands/games/osu.js +++ /dev/null @@ -1,22 +0,0 @@ -const { SubcommandListCommand } = require('../../') - -module.exports = class Osu extends SubcommandListCommand { - constructor (client) { - super({ - name: 'osu', - category: 'games', - requirements: { apis: ['osu'] }, - authorString: 'commands:osu.gameName', - authorImage: 'https://i.imgur.com/Ek0hnam.png', - authorURL: 'https://osu.ppy.sh', - embedColor: '#E7669F' - }, client) - - this.modes = { - osu: ['0', 'osu!'], - taiko: ['1', 'osu!taiko'], - catchthebeat: ['2', 'osu!catch'], - mania: ['3', 'osu!mania'] - } - } -} diff --git a/src/commands/games/osu/beatmap.js b/src/commands/games/osu/beatmap.js deleted file mode 100644 index 34f9fe9d0..000000000 --- a/src/commands/games/osu/beatmap.js +++ /dev/null @@ -1,106 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, PaginatedEmbed, MiscUtils, Constants } = require('../../../') -const moment = require('moment') - -module.exports = class OsuBeatmap extends SearchCommand { - constructor (client) { - super({ - name: 'beatmap', - aliases: ['b'], - parent: 'osu', - parameters: [{ - type: 'string', full: true, missingError: 'commands:osu.subcommands.beatmap.noBeatmap' - }, [{ - type: 'booleanFlag', name: 'taiko' - }, { - type: 'booleanFlag', name: 'catchthebeat', aliases: ['ctb', 'catch'] - }, { - type: 'booleanFlag', name: 'mania' - }]], - embedColor: '#E7669F', - embedLogoURL: 'https://i.imgur.com/Ek0hnam.png' - }, client) - } - - async search (context, query) { - return this.client.apis.osu.getBeatmap(query, 0, 10) - } - - searchResultFormatter (obj) { - return `[${obj.artist} - ${obj.title} (${obj.version})](${this.parentCommand.authorURL}/b/${obj.beatmap_id})` - } - - async handleResult ({ t, channel, author, language, flags }, data) { - channel.startTyping() - const paginatedEmbed = new PaginatedEmbed(t, author) - - const mode = this.parentCommand.modes[Object.keys(flags).filter(key => flags[key])[0] || 'osu'] - const scores = await this.client.apis.osu.getBeatmapScores(data.beatmap_id, mode[0], 5) - - const connections = await this.client.controllers.connection.getConnectionsFiltered(author.id) - const osu = connections.find(c => c.name === 'osu') - - moment.locale(language) - - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setAuthor(mode[1], this.parentCommand.authorImage, `${this.parentCommand.authorURL}/b/${data.beatmap_id}`) - .setTitle(`${data.artist} - ${data.title} (${data.version})`) - .setColor(this.parentCommand.embedColor) - .setImage(`https://assets.ppy.sh/beatmaps/${data.beatmapset_id}/covers/cover.jpg?${Date.now()}`) - .setDescriptionFromBlockArray([ - [ - `${this.client.officialEmojis.get('length')} ${moment.duration(data.total_length * 1000).format('m:ss')} ${this.client.officialEmojis.get('bpm')} ${data.bpm}`, - t('commands:osu.subcommands.beatmap.starDifficulty', { difficulty: Number(data.difficultyrating).toFixed(2) }), - t('commands:osu.subcommands.beatmap.successRate', { rate: ((parseInt(data.passcount) / parseInt(data.playcount)) * 100 || 0).toFixed(1), successfulPlays: MiscUtils.formatNumber(data.passcount, language), totalPlays: MiscUtils.formatNumber(data.playcount, language) }) - ], - [ - t('commands:osu.subcommands.beatmap.mappedBy', { mapper: `[${data.creator}](${this.parentCommand.authorURL}/u/${data.creator_id})` }), - t('commands:osu.subcommands.beatmap.lastUpdate', { date: moment(data.last_update).format('LLL'), timeAgo: moment(data.last_update).fromNow() }), - Number(data.approved) > 0 ? t('commands:osu.subcommands.beatmap.approved', { date: moment(data.approved_date).format('LLL'), timeAgo: moment(data.approved_date).fromNow() }) : null, - data.tags ? t('commands:osu.subcommands.beatmap.tags', { tags: data.tags.split(' ').map(t => `\`${t}\``).join(', ') }) : null - ], - [ - t('commands:osu.subcommands.beatmap.download', { link: `${this.parentCommand.authorURL}/beatmapsets/${data.beatmapset_id}/download` }), - Number(data.video) > 0 ? t('commands:osu.subcommands.beatmap.downloadNoVideo', { link: `${this.parentCommand.authorURL}/beatmapsets/${data.beatmapset_id}/download?noVideo=1` }) : null - ] - ])) - - if (scores.length > 0) { - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setAuthor(mode[1], this.parentCommand.authorImage, `${this.parentCommand.authorURL}/b/${data.beatmap_id}`) - .setTitle(`${data.artist} - ${data.title} (${data.version})`) - .setColor(this.parentCommand.embedColor) - .setDescriptionFromBlockArray([ - [ - t('commands:osu.subcommands.beatmap.topScores') - ], - [ - scores.map((score, i) => { - return `#${i + 1} - **[${score.username}](${this.parentCommand.authorURL}/u/${score.user_id})** ${this.client.officialEmojis.get(score.rank.length === 1 ? `${score.rank.toLowerCase()}_` : score.rank.toLowerCase())} - ${score.count300} ${this.client.officialEmojis.get('300')} (${score.countgeki} ${this.client.officialEmojis.get('geki')}), ${score.count100} ${this.client.officialEmojis.get('100')} (${score.countkatu} ${this.client.officialEmojis.get('katu')}), ${score.countmiss} ${this.client.officialEmojis.get('miss')} - **${MiscUtils.formatNumber(parseInt(score.pp), language)}pp**` - }).join('\n') - ] - ])) - } - - if (osu.account) { - const [topPlayerScore] = await this.client.apis.osu.getBeatmapScoreFromPlayer(data.beatmap_id, osu.account.id) - - if (topPlayerScore) { - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setAuthor(mode[1], this.parentCommand.authorImage, `${this.parentCommand.authorURL}/b/${data.beatmap_id}`) - .setTitle(`${data.artist} - ${data.title} (${data.version})`) - .setColor(this.parentCommand.embedColor) - .setDescriptionFromBlockArray([ - [ - t('commands:osu.subcommands.beatmap.topScoreSelf', { date: moment(topPlayerScore.date).format('LLL') }) - ], - [ - `${this.client.officialEmojis.get(topPlayerScore.rank.length === 1 ? `${topPlayerScore.rank.toLowerCase()}_` : topPlayerScore.rank.toLowerCase())} - ${topPlayerScore.count300} ${this.client.officialEmojis.get('300')} (${topPlayerScore.countgeki} ${this.client.officialEmojis.get('geki')}), ${topPlayerScore.count100} ${this.client.officialEmojis.get('100')} (${topPlayerScore.countkatu} ${this.client.officialEmojis.get('katu')}), ${topPlayerScore.countmiss} ${this.client.officialEmojis.get('miss')} - **${MiscUtils.formatNumber(parseInt(topPlayerScore.pp), language)}pp**` - ] - ])) - } - } - - paginatedEmbed.run(await channel.send(Constants.EMPTY_SPACE)) - channel.stopTyping() - } -} diff --git a/src/commands/games/osu/player.js b/src/commands/games/osu/player.js deleted file mode 100644 index a808340e4..000000000 --- a/src/commands/games/osu/player.js +++ /dev/null @@ -1,115 +0,0 @@ -const { Command, SwitchbladeEmbed, PaginatedEmbed, CommandError, MiscUtils, Constants } = require('../../../') -const moment = require('moment') - -module.exports = class OsuPlayer extends Command { - constructor (client) { - super({ - name: 'player', - aliases: ['p'], - parent: 'osu', - parameters: [{ - type: 'string', full: true, required: false - }, [{ - type: 'booleanFlag', name: 'taiko' - }, { - type: 'booleanFlag', name: 'catchthebeat', aliases: ['ctb', 'catch'] - }, { - type: 'booleanFlag', name: 'mania' - }]] - }, client) - } - - async run ({ t, author, flags, channel, language }, user) { - const connections = await this.client.controllers.connection.getConnectionsFiltered(author.id) - const osu = connections.find(c => c.name === 'osu') - if (!user && !osu.account) throw new CommandError(t('commands:osu.subcommands.player.noPlayer')) - if (!user && osu.account) user = osu.account.id - - const mode = this.parentCommand.modes[Object.keys(flags).filter(key => flags[key])[0] || 'osu'] - const paginatedEmbed = new PaginatedEmbed(t, author) - - try { - channel.startTyping() - moment.locale(language) - const userData = await this.client.apis.osu.getUser(user, mode[0]) - - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setAuthor(mode[1], this.parentCommand.authorImage) - .setColor(this.parentCommand.embedColor) - .setThumbnail(`https://a.ppy.sh/${userData.user_id}?${Date.now()}.png`) - .setDescriptionFromBlockArray([ - [ - `:flag_${userData.country.toLowerCase()}: **[${userData.username}](${this.parentCommand.authorURL}/u/${userData.user_id})** (${t('commands:osu.subcommands.player.level', { number: MiscUtils.formatNumber(Math.floor(userData.level), language) })})` - ], - [ - t('commands:osu.subcommands.player.joinedAt', { date: moment(userData.join_date).format('LLL'), timeAgo: moment(userData.join_date).fromNow() }), - t('commands:osu.subcommands.player.playTime', { time: moment.duration(userData.total_seconds_played * 1000).format('d[d] h[h] m[m] s[s]'), pp: MiscUtils.formatNumber(Math.floor(userData.pp_raw), language) }) - ], - [ - `**${MiscUtils.formatNumber(userData.count_rank_ssh, language)}** ${this.client.officialEmojis.get('xh')}, **${MiscUtils.formatNumber(userData.count_rank_ss, language)}** ${this.client.officialEmojis.get('x_')}, **${MiscUtils.formatNumber(userData.count_rank_sh, language)}** ${this.client.officialEmojis.get('sh')}, **${MiscUtils.formatNumber(userData.count_rank_s, language)}** ${this.client.officialEmojis.get('s_')}, **${MiscUtils.formatNumber(userData.count_rank_a, language)}** ${this.client.officialEmojis.get('a_')}` - ], - [ - t('commands:osu.subcommands.player.globalRanking', { rank: MiscUtils.formatNumber(userData.pp_rank, language) }), - t('commands:osu.subcommands.player.countryRanking', { rank: MiscUtils.formatNumber(userData.pp_country_rank, language) }), - t('commands:osu.subcommands.player.rankedScore', { rankedScore: MiscUtils.formatNumber(userData.ranked_score, language) }), - t('commands:osu.subcommands.player.totalScore', { totalScore: MiscUtils.formatNumber(userData.total_score, language) }) - ], - [ - t('commands:osu.subcommands.player.hitAccuracy', { accuracy: Math.floor(userData.accuracy) }), - t('commands:osu.subcommands.player.playCount', { playCount: MiscUtils.formatNumber(userData.playcount, language) }), - t('commands:osu.subcommands.player.totalHits', { totalHits: MiscUtils.formatNumber((parseInt(userData.count300) + parseInt(userData.count100) + parseInt(userData.count50)), language), 300: MiscUtils.formatNumber(userData.count300, language), 100: MiscUtils.formatNumber(userData.count100, language), 50: MiscUtils.formatNumber(userData.count50, language), emoji300: this.client.officialEmojis.get('300'), emoji100: this.client.officialEmojis.get('100'), emoji50: this.client.officialEmojis.get('50') }) - ] - ])) - - const topScores = await this.client.apis.osu.getUserTopScores(user, mode[0], 5) - if (topScores.length > 0) { - const description = [] - - for (const i in topScores) { - const [firstBeatmap] = await this.client.apis.osu.getBeatmap(topScores[i].beatmap_id, mode[0]) - if (firstBeatmap) description.push(`#${parseInt(i) + 1} - **[${firstBeatmap.artist} - ${firstBeatmap.title} (${firstBeatmap.version})](${this.parentCommand.authorURL}/b/${topScores[i].beatmap_id})** ${this.client.officialEmojis.get(topScores[i].rank.length === 1 ? `${topScores[i].rank.toLowerCase()}_` : topScores[i].rank.toLowerCase())} - **${MiscUtils.formatNumber(parseInt(topScores[i].pp), language)}pp**`) - } - - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setColor(this.parentCommand.embedColor) - .setAuthor(mode[1], this.parentCommand.authorImage) - .setDescriptionFromBlockArray([ - [ - t('commands:osu.subcommands.player.topScores', { user: userData.username }) - ], - [ - description.join('\n') - ] - ])) - } - - const recentPlays = await this.client.apis.osu.getUserRecentPlays(user, mode[0], 5) - - if (recentPlays.length > 0) { - const description = [] - - for (const int in recentPlays) { - const [firstBeatmap] = await this.client.apis.osu.getBeatmap(recentPlays[int].beatmap_id, mode[0]) - if (firstBeatmap) description.push(`#${parseInt(int) + 1} - **[${firstBeatmap.artist} - ${firstBeatmap.title} (${firstBeatmap.version})](${this.parentCommand.authorURL}/b/${recentPlays[int].beatmap_id})** ${this.client.officialEmojis.get(recentPlays[int].rank.length === 1 ? `${recentPlays[int].rank.toLowerCase()}_` : recentPlays[int].rank.toLowerCase())} (${moment(recentPlays[int].date).fromNow()})`) - } - - paginatedEmbed.addPage(new SwitchbladeEmbed(author) - .setColor(this.parentCommand.embedColor) - .setAuthor(mode[1], this.parentCommand.authorImage) - .setDescriptionFromBlockArray([ - [ - t('commands:osu.subcommands.player.recentPlays', { user: userData.username }) - ], - [ - description.join('\n') - ] - ])) - } - - paginatedEmbed.run(await channel.send(Constants.EMPTY_SPACE)) - channel.stopTyping() - } catch (e) { - throw new CommandError(t('commands:osu.subcommands.player.playerNotFound')) - } - } -} diff --git a/src/commands/games/samp.js b/src/commands/games/samp.js deleted file mode 100644 index 0f1b6bcf7..000000000 --- a/src/commands/games/samp.js +++ /dev/null @@ -1,51 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed } = require('../../') -const query = require('samp-query') - -module.exports = class SAMP extends Command { - constructor (client) { - super({ - name: 'samp', - category: 'games', - parameters: [{ - type: 'string', missingError: 'commands:samp.noIP' - }] - }, client) - } - - async run ({ t, author, channel }, address) { - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - const [host, port = 7777] = address.split(':') - try { - const response = await this.queryPromise({ host, port }) - embed.setAuthor('San Andreas: Multiplayer', 'https://i.imgur.com/QYeGxrV.png') - .setColor(0xF07B0F) - .setTitle(response.hostname) - .setURL(this.cleanURL(response.rules.weburl)) - .addField(t('commands:samp.address'), `\`${host}:${port}\``, true) - .addField(t('commands:samp.version'), response.rules.version, true) - .addField(t('commands:samp.players'), `${response.online}/${response.maxplayers}`, true) - .addField(t('commands:samp.map'), response.mapname, true) - .addField(t('commands:samp.gameMode'), response.gamemode, true) - .addField(t('commands:samp.time'), response.rules.worldtime, true) - } catch (err) { - throw new CommandError(new SwitchbladeEmbed(author) - .setTitle(t('commands:samp.serverUnreachableTitle')) - .setDescription(t('commands:samp.serverUnreachableDescription'))) - } - channel.send(embed).then(channel.stopTyping()) - } - - async queryPromise (options) { - return new Promise((resolve, reject) => { - query(options, function (error, response) { - if (error) return reject(error) - resolve(response) - }) - }) - } - - cleanURL (url) { - return /^https?:\/\//i.test(url) ? url : `http://${url}` - } -} diff --git a/src/commands/gifs/handshake.js b/src/commands/gifs/handshake.js deleted file mode 100644 index 8267318bc..000000000 --- a/src/commands/gifs/handshake.js +++ /dev/null @@ -1,29 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -const handshakeArray = [ - 'https://i.gifer.com/C9M7.gif', - 'https://media1.tenor.com/images/314a2f7c3647ec0b9ba4100f8e35dc2e/tenor.gif?itemid=12270042', - 'https://i.giphy.com/media/lNjOEfoKIplcc/200_d.gif' -] - -module.exports = class Handshake extends Command { - constructor (client) { - super({ - name: 'handshake', - aliases: ['hs', 'hands'], - category: 'images', - parameters: [{ - type: 'user', acceptBot: true, acceptSelf: false, missingError: 'commands:handshake.noMention' - }] - }, client) - } - - run ({ t, channel, author }, user) { - const handshakeImg = handshakeArray[Math.floor(Math.random() * handshakeArray.length)] - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - embed.setImage(handshakeImg) - .setDescription(t('commands:handshake.success', { handshaker: author.toString(), handshaked: user.toString() })) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/gifs/hug.js b/src/commands/gifs/hug.js deleted file mode 100644 index 066b110ab..000000000 --- a/src/commands/gifs/hug.js +++ /dev/null @@ -1,24 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -const fetch = require('node-fetch') - -module.exports = class Hug extends Command { - constructor (client) { - super({ - name: 'hug', - category: 'images', - parameters: [{ - type: 'user', acceptBot: true, acceptSelf: false, missingError: 'commands:hug.noMention' - }] - }, client) - } - - async run ({ t, channel, author }, user) { - const body = await fetch('https://nekos.life/api/v2/img/hug').then(res => res.json()) - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - embed.setImage(body.url) - .setDescription(t('commands:hug.success', { hugger: author.toString(), hugged: user.toString() })) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/gifs/kiss.js b/src/commands/gifs/kiss.js deleted file mode 100644 index f562b57f3..000000000 --- a/src/commands/gifs/kiss.js +++ /dev/null @@ -1,25 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -const fetch = require('node-fetch') - -module.exports = class Kiss extends Command { - constructor (client) { - super({ - name: 'kiss', - aliases: ['beijo', 'beijar'], - category: 'images', - parameters: [{ - type: 'user', acceptBot: true, acceptSelf: false, missingError: 'commands:kiss.noMention' - }] - }, client) - } - - async run ({ t, channel, author }, user) { - const body = await fetch('https://nekos.life/api/v2/img/kiss').then(res => res.json()) - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - embed.setImage(body.url) - .setDescription(t('commands:kiss.success', { kisser: author.toString(), kissed: user.toString() })) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/gifs/pat.js b/src/commands/gifs/pat.js deleted file mode 100644 index 50c89404a..000000000 --- a/src/commands/gifs/pat.js +++ /dev/null @@ -1,24 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -const fetch = require('node-fetch') - -module.exports = class Pat extends Command { - constructor (client) { - super({ - name: 'pat', - category: 'images', - parameters: [{ - type: 'user', acceptBot: true, acceptSelf: false, missingError: 'commands:pat.noMention' - }] - }, client) - } - - async run ({ t, channel, author }, user) { - const body = await fetch('https://nekos.life/api/v2/img/pat').then(res => res.json()) - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - embed.setImage(body.url) - .setDescription(t('commands:pat.success', { _author: author.toString(), pat: user.toString() })) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/gifs/slap.js b/src/commands/gifs/slap.js deleted file mode 100644 index 210adc515..000000000 --- a/src/commands/gifs/slap.js +++ /dev/null @@ -1,24 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -const fetch = require('node-fetch') - -module.exports = class Slap extends Command { - constructor (client) { - super({ - name: 'slap', - category: 'images', - parameters: [{ - type: 'user', acceptBot: true, acceptSelf: false, missingError: 'commands:slap.noMention' - }] - }, client) - } - - async run ({ t, channel, author }, user) { - const body = await fetch('https://nekos.life/api/v2/img/slap').then(res => res.json()) - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - embed.setImage(body.url) - .setDescription(t('commands:slap.success', { _author: author.toString(), slapped: user.toString() })) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/government/auxilioemergencial.js b/src/commands/government/auxilioemergencial.js deleted file mode 100644 index 8beaa18ca..000000000 --- a/src/commands/government/auxilioemergencial.js +++ /dev/null @@ -1,36 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed, Constants } = require('../../') -const moment = require('moment') - -module.exports = class AuxilioEmergencial extends Command { - constructor (client) { - super({ - name: 'auxilioemergencial', - alias: ['aemergencial', 'ae'], - category: 'government', - requirements: { - apis: ['portaldatransparencia'] - }, - parameters: [{ - type: 'string', - full: true, - missingError: 'commands:auxilioemergencial.notFound' - }] - }, client) - } - - async run ({ t, author, channel, language }, cpf) { - const auxilio = await this.client.apis.portaldatransparencia.searchAuxilioCPF(cpf) - moment.locale(language) - try { - channel.send( - new SwitchbladeEmbed(author) - .setAuthor('Portal da Transparência', 'https://logodownload.org/wp-content/uploads/2017/03/brasao-do-brasil-republica-1.png', 'http://portaltransparencia.gov.br/') - .setColor(Constants.PORTALTRANSPARENCIA_COLOR) - .setDescription(`**${t('commands:auxilioemergencial.name')}**: ${auxilio[0].beneficiario.nome}\n**${t('commands:auxilioemergencial.cpf')}**:` + auxilio[0].beneficiario.cpfFormatado + `\n**${t('commands:auxilioemergencial.nis')}**: ${auxilio[0].beneficiario.nis}\n**${t('commands:auxilioemergencial.amount')}**: R$ ${auxilio[0].valor}.00\n**${t('commands:auxilioemergencial.city')}**: ${auxilio[0].municipio.nomeIBGE} - ${auxilio[0].municipio.uf.sigla}`) - ) - } catch (e) { - channel.stopTyping(true) - throw new CommandError(t('commands:correios.notFound')) - } - } -} diff --git a/src/commands/government/correios.js b/src/commands/government/correios.js deleted file mode 100644 index fd4d739d5..000000000 --- a/src/commands/government/correios.js +++ /dev/null @@ -1,40 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed, Constants } = require('../../') -const moment = require('moment') - -module.exports = class Correios extends Command { - constructor (client) { - super({ - name: 'correios', - alias: ['trackCorreios'], - category: 'government', - requirements: { - apis: ['correios'] - }, - parameters: [{ - type: 'string', - full: true, - missingError: 'commands:correios.notFound' - }] - }, client) - } - - async run ({ t, author, channel, language }, tCode) { - const tracked = await this.client.apis.correios.trackCode(tCode) - moment.locale(language) - try { - const laststate = tracked[0].tracks[tracked[0].tracks.length - 1] - channel.send( - new SwitchbladeEmbed() - .setAuthor(`${tracked[0].code}`, 'https://i.imgur.com/QRBKPwm.png') - .setTitle(laststate.locale.toUpperCase()) - .setDescription(`${laststate.status.toUpperCase()} ${laststate.observation ? laststate.observation.toUpperCase() : ''}`) - .setColor(tracked[0].isDelivered ? Constants.SPOTIFY_COLOR : '#0f75bc') - .setFooter(t('commands:correios.lastUpdated')) - .setTimestamp(laststate.trackedAt) - ) - } catch (e) { - channel.stopTyping(true) - throw new CommandError(t('commands:correios.notFound')) - } - } -} diff --git a/src/commands/image-manipulation/presidentialalert.js b/src/commands/image-manipulation/presidentialalert.js deleted file mode 100644 index d7ee582b9..000000000 --- a/src/commands/image-manipulation/presidentialalert.js +++ /dev/null @@ -1,24 +0,0 @@ -const { CanvasTemplates, Command } = require('../../') - -const { MessageAttachment } = require('discord.js') - -module.exports = class PresidentialAlert extends Command { - constructor (client) { - super({ - name: 'presidentialalert', - aliases: ['pa'], - category: 'images', - requirements: { canvasOnly: true }, - parameters: [{ - type: 'string', full: true, required: true, missingError: 'commands:presidentialalert.missingText' - }] - }, client) - } - - async run ({ t, author, channel }, text) { - channel.startTyping() - const presidential = await CanvasTemplates.presidentialAlert(text) - channel.send(new MessageAttachment(presidential, 'president.jpg')) - channel.stopTyping() - } -} diff --git a/src/commands/memes/ashwga.js b/src/commands/memes/ashwga.js deleted file mode 100644 index 92c1da8d2..000000000 --- a/src/commands/memes/ashwga.js +++ /dev/null @@ -1,24 +0,0 @@ -const { CanvasTemplates, Command } = require('../../') - -const { MessageAttachment } = require('discord.js') - -module.exports = class HereWeGoAgain extends Command { - constructor (client) { - super({ - name: 'herewegoagain', - aliases: ['ahshit', 'ahshitherewegoagain', 'ashwga', 'hwga'], - category: 'images', - requirements: { canvasOnly: true }, - parameters: [{ - type: 'image', - missingError: 'commands:herewegoagain.missingImage' - }] - }, client) - } - - async run ({ t, author, channel }, image) { - channel.startTyping() - const hwga = await CanvasTemplates.herewegoagain(image) - channel.send(new MessageAttachment(hwga, 'ashwga.png')).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/memes/bolinadegorfe.js b/src/commands/memes/bolinadegorfe.js deleted file mode 100644 index fa162536b..000000000 --- a/src/commands/memes/bolinadegorfe.js +++ /dev/null @@ -1,20 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class BolinaDeGorfe extends Command { - constructor (client) { - super({ - name: 'bolinadegorfe', - aliases: ['bolinhadegolfe', 'bolinhadegorfe', 'bolinadegolfe'], - category: 'memes' - }, client) - } - - run ({ author, channel }) { - // TODO: make this command only works in pt-BR - const embed = new SwitchbladeEmbed(author) - embed - .setTitle('ooo, boliña de gorfe') - .setImage('https://j.gifs.com/9QVDRP.gif') - channel.send(embed) - } -} diff --git a/src/commands/memes/clapify.js b/src/commands/memes/clapify.js deleted file mode 100644 index 36d6f01fe..000000000 --- a/src/commands/memes/clapify.js +++ /dev/null @@ -1,28 +0,0 @@ -const { Command, SwitchbladeEmbed, Constants } = require('../../index') - -const emoji = '\uD83D\uDC4F' -const CLAPIFY_LIMIT = 128 - -module.exports = class Clapify extends Command { - constructor (client) { - super({ - name: 'clapify', - category: 'memes', - parameters: [{ - type: 'string', full: true, missingError: 'commands:clapify.missingSentence' - }] - }, client) - } - - async run ({ t, author, channel }, text) { - const embed = new SwitchbladeEmbed(author) - if (text.length >= CLAPIFY_LIMIT) { - embed - .setTitle(t('commands:clapify.tooLongText', { limit: CLAPIFY_LIMIT })) - .setColor(Constants.ERROR_COLOR) - } else { - embed.setTitle(`${emoji} ${text.toUpperCase().split(' ').join(` ${emoji} `)} ${emoji}`) - } - channel.send(embed) - } -} diff --git a/src/commands/memes/piratespeak.js b/src/commands/memes/piratespeak.js deleted file mode 100644 index 187c935bb..000000000 --- a/src/commands/memes/piratespeak.js +++ /dev/null @@ -1,21 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') -const pirateSpeak = require('pirate-speak') - -module.exports = class PirateSpeak extends Command { - constructor (client) { - super({ - name: 'piratespeak', - aliases: ['ps', 'yarrspeak'], - category: 'memes', - parameters: [{ - type: 'string', full: true, clean: true, missingError: 'commands:piratespeak.missingSentence' - }] - }, client) - } - - async run ({ author, channel }, text) { - const embed = new SwitchbladeEmbed(author) - embed.setDescription(pirateSpeak.translate(text)) - channel.send(embed) - } -} diff --git a/src/commands/memes/quieres.js b/src/commands/memes/quieres.js deleted file mode 100644 index 37d19b0eb..000000000 --- a/src/commands/memes/quieres.js +++ /dev/null @@ -1,27 +0,0 @@ -const { CanvasTemplates, Command } = require('../../') - -const { MessageAttachment } = require('discord.js') - -module.exports = class Quieres extends Command { - constructor (client) { - super({ - name: 'quieres', - aliases: ['bufa'], - category: 'images', - requirements: { canvasOnly: true }, - parameters: [{ - type: 'image', - missingError: 'commands:quieres.missingImage', - userOptions: { - acceptSelf: true - } - }] - }, client) - } - - async run ({ t, author, channel }, image) { - channel.startTyping() - const quieres = await CanvasTemplates.quieres(image) - channel.send(new MessageAttachment(quieres, 'quieres.jpg')).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/memes/reversetext.js b/src/commands/memes/reversetext.js deleted file mode 100644 index e4c685a66..000000000 --- a/src/commands/memes/reversetext.js +++ /dev/null @@ -1,20 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../index') - -module.exports = class ReverseText extends Command { - constructor (client) { - super({ - name: 'reversetext', - category: 'memes', - parameters: [{ - type: 'string', full: true, missingError: 'commands:reversetext.missingSentence' - }] - }, client) - } - - async run ({ t, author, channel }, text) { - channel.send( - new SwitchbladeEmbed(author) - .setDescription(text.split('').reverse().join('')) - ) - } -} diff --git a/src/commands/memes/smart.js b/src/commands/memes/smart.js deleted file mode 100644 index a81e136c3..000000000 --- a/src/commands/memes/smart.js +++ /dev/null @@ -1,17 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class Smart extends Command { - constructor (client) { - super({ - name: 'smart', - aliases: ['wesmart'], - category: 'memes' - }, client) - } - - run ({ author, channel }) { - const embed = new SwitchbladeEmbed(author) - embed.setImage('https://media0.giphy.com/media/d3mlE7uhX8KFgEmY/source.gif') - channel.send(embed) - } -} diff --git a/src/commands/memes/tipsfedora.js b/src/commands/memes/tipsfedora.js deleted file mode 100644 index 0e5b0ff01..000000000 --- a/src/commands/memes/tipsfedora.js +++ /dev/null @@ -1,16 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class TipsFedora extends Command { - constructor (client) { - super({ - name: 'tipsfedora', - category: 'memes' - }, client) - } - - run ({ author, channel }) { - const embed = new SwitchbladeEmbed(author) - embed.setImage('https://i.kym-cdn.com/photos/images/masonry/000/747/485/3a1.gif') - channel.send(embed) - } -} diff --git a/src/commands/misc/asciify.js b/src/commands/misc/asciify.js deleted file mode 100644 index 51695f457..000000000 --- a/src/commands/misc/asciify.js +++ /dev/null @@ -1,23 +0,0 @@ -const { Command } = require('../../') -const figlet = require('figlet') - -module.exports = class Asciify extends Command { - constructor (client) { - super({ - name: 'asciify', - aliases: ['bigtext'], - parameters: [{ - type: 'string', full: true, clean: true, missingError: 'commands:asciify.noText' - }] - }, client) - } - - run ({ channel, message }, text) { - const bigtext = figlet.textSync(text, { - font: 'Big', - horizontalLayout: 'universal smushing', - verticalLayout: 'universal smushing' - }) - channel.send(`\`\`\`${bigtext}\`\`\``) - } -} diff --git a/src/commands/misc/bmi.js b/src/commands/misc/bmi.js deleted file mode 100644 index 2fda62f67..000000000 --- a/src/commands/misc/bmi.js +++ /dev/null @@ -1,93 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -// Reference: https://en.wikipedia.org/wiki/Body_mass_index#Categories -const BMICategories = { - verySeverelyUnderweight: { - displayName: 'commands:bmi.categoryVerySeverelyUnderweight', - color: '#2196F3', - min: 0, - max: 15 - }, - severelyUnderweight: { - displayName: 'commands:bmi.categorySeverelyUnderweight', - color: '#03A9F4', - min: 15, - max: 16 - }, - underweight: { - displayName: 'commands:bmi.categoryUnderweight', - color: '#00BCD4', - min: 16, - max: 18.5 - }, - normal: { - displayName: 'commands:bmi.categoryNormal', - color: '#4CAF50', - min: 18.5, - max: 25 - }, - overweight: { - displayName: 'commands:bmi.categoryOverweight', - color: '#FFEB3B', - min: 25, - max: 30 - }, - obese1: { - displayName: 'commands:bmi.categoryObese1', - color: '#FFC107', - min: 30, - max: 35 - }, - obese2: { - displayName: 'commands:bmi.categoryObese2', - color: '#FF9800', - min: 35, - max: 40 - }, - obese3: { - displayName: 'commands:bmi.categoryObese3', - color: '#FF5722', - min: 40, - max: Infinity - } -} - -module.exports = class BMI extends Command { - constructor (client) { - super({ - name: 'bmi', - aliases: ['bodymassindex'], - parameters: [ - { - type: 'number', - min: 0, - required: true, - missingError: 'commands:bmi.missingWeight' - }, - { - type: 'number', - min: 0, - required: true, - missingError: 'commands:bmi.missingHeight' - } - ] - }, client) - } - - async run ({ t, channel }, weight, height) { - const BMIValue = weight / Math.pow(height, 2) - const { displayName, color } = Object.values(BMICategories).find(category => - BMIValue > category.min && BMIValue < category.max - ) - // Format number to 2 nearest integers - // https://stackoverflow.com/a/11832950 - const formattedBMIValue = Math.round((BMIValue + Number.EPSILON) * 100) / 100 - const embed = new SwitchbladeEmbed() - embed - .setTitle(t('commands:bmi.title', { value: formattedBMIValue })) - .setDescription(t('commands:bmi.description', { category: t(displayName) })) - .setColor(color) - .setFooter(t('commands:bmi.footer')) - channel.send(embed) - } -} diff --git a/src/commands/misc/brewsearch.js b/src/commands/misc/brewsearch.js deleted file mode 100644 index 349f976a4..000000000 --- a/src/commands/misc/brewsearch.js +++ /dev/null @@ -1,48 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed, Constants } = require('../../') - -module.exports = class BrewSearch extends Command { - constructor (client) { - super({ - name: 'brew', - parameters: [ - { - type: 'string', - missingError: 'commands:brew.missingFormulae' - } - ], - requirements: { - apis: ['brew'] - } - }, client) - } - - async run ({ t, author, channel }, formulae) { - try { - const formulaeData = await this.client.apis.brew.search(formulae) - channel.send( - new SwitchbladeEmbed(author) - .setTitle(t('commands:brew.title', { name: formulaeData.full_name })) - .setDescriptionFromBlockArray([ - [ - `**${t('commands:brew.description')}**: ${formulaeData.desc}`, - `**${t('commands:brew.analytics')}**:\n${t('commands:brew.30d')}: \`${ - formulaeData.analytics.install['30d'][formulaeData.name] - }\`\n${t('commands:brew.90d')}: \`${ - formulaeData.analytics.install['90d'][formulaeData.name] - }\`\n${t('commands:brew.365d')}: ${ - formulaeData.analytics.install['365d'][formulaeData.name] - }`, - `**${t('commands:brew.links')}**:\n[${t( - 'commands:brew.homebrewLink' - )}](https://formulae.brew.sh/formula/${formulaeData.name}) [${t( - 'commands:brew.homePage' - )}](${formulaeData.homepage})` - ] - ]) - .setColor(Constants.HOMEBREW_COLOR) - ) - } catch { - throw new CommandError(t('commands:brew.invalidFormulae')) - } - } -} diff --git a/src/commands/misc/chocolatey.js b/src/commands/misc/chocolatey.js deleted file mode 100644 index 848d65859..000000000 --- a/src/commands/misc/chocolatey.js +++ /dev/null @@ -1,53 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants } = require('../..') - -module.exports = class Chocolatey extends SearchCommand { - constructor (client) { - super({ - name: 'chocolatey', - aliases: ['choco'], - requirements: { apis: ['chocolatey'] }, - embedColor: Constants.CHOCOLATEY_COLOR, - embedLogoURL: 'https://i.imgur.com/CRddVay.png' - }, client) - } - - async search (_, query) { - const res = await this.client.apis.chocolatey.search(query) - if ('d' in res.data) return res.data.d.results - } - - searchResultFormatter (i) { - return `[${i.Title} - ${i.Authors}](${i.GalleryDetailsUrl})` - } - - async handleResult ({ t, author, channel, language }, { __metadata, Authors, Description, DownloadCount, GalleryDetailsUrl, LicenseUrl, IconUrl, Tags, Title, Summary, Version }) { - channel.send( - new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor('Chocolatey', this.embedLogoURL, 'https://chocolatey.org/packages') - .setURL(GalleryDetailsUrl) - .setThumbnail(IconUrl) - .setTitle(`${Title} v${Version}`) - .setDescriptionFromBlockArray([ - [ - Summary || (Description && Description.split('\n')[0].replace(/#/g, '')) - ], - [ - t('commands:chocolatey.by', { authors: Authors.split(', ').map((a) => `**${a}**`).join(', ') }) - ], - [ - t('commands:chocolatey.installs', { count: DownloadCount.toLocaleString(language) }) - ], - [ - Tags.trim().split(' ').map((t) => `\`${t}\``).join(', ') - ], - [ - `[${t('commands:chocolatey.license')}](${LicenseUrl})` - ], - [ - `\`\`\`\nchoco install ${__metadata.uri.match(/Id='([.\w\d_-]+)'/)[1].toLowerCase()}\n\`\`\`` - ] - ]) - ) - } -} diff --git a/src/commands/misc/cow.js b/src/commands/misc/cow.js deleted file mode 100644 index 16259a5d9..000000000 --- a/src/commands/misc/cow.js +++ /dev/null @@ -1,16 +0,0 @@ -const { Command } = require('../../') -const cows = require('cows') - -module.exports = class Cow extends Command { - constructor (client) { - super({ - name: 'cow' - }, client) - } - - run ({ channel }) { - const cowNumber = Math.round((Math.random() * cows().length)) - const cow = cows()[cowNumber] - channel.send(`\`\`\`${cow}\`\`\``) - } -} diff --git a/src/commands/misc/cowsay.js b/src/commands/misc/cowsay.js deleted file mode 100644 index 5e19d0e85..000000000 --- a/src/commands/misc/cowsay.js +++ /dev/null @@ -1,19 +0,0 @@ -const { Command } = require('../../') -const cowsay = require('cowsay') - -module.exports = class Cowsay extends Command { - constructor (client) { - super({ - name: 'cowsay', - aliases: ['cs'], - category: 'general', - parameters: [{ - type: 'string', full: true, clean: true, missingError: 'commands:cowsay.noText' - }] - }, client) - } - - run ({ channel, message }, text) { - channel.send(`\`\`\`${cowsay.say({ text })}\`\`\``) - } -} diff --git a/src/commands/misc/deezer.js b/src/commands/misc/deezer.js deleted file mode 100644 index 18935f6c0..000000000 --- a/src/commands/misc/deezer.js +++ /dev/null @@ -1,14 +0,0 @@ -const { SubcommandListCommand } = require('../../') - -module.exports = class Deezer extends SubcommandListCommand { - constructor (client) { - super({ - name: 'deezer', - aliases: ['dz'], - requirements: { apis: ['deezer'] }, - authorString: 'commands:deezer.serviceName', - authorImage: 'https://lh3.googleusercontent.com/r55K1eQcji3QMHRKERq6zE1-csoh_MTOHiKyHTuTOblhFi_rIz06_8GN5-DHUGJOpn79', - authorURL: 'https://deezer.com' - }, client) - } -} diff --git a/src/commands/misc/deezer/album.js b/src/commands/misc/deezer/album.js deleted file mode 100644 index 9499495f8..000000000 --- a/src/commands/misc/deezer/album.js +++ /dev/null @@ -1,61 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants, MiscUtils } = require('../../../') - -module.exports = class DeezerAlbum extends SearchCommand { - constructor (client) { - super({ - name: 'album', - aliases: ['al'], - parent: 'deezer', - embedColor: Constants.DEEZER_COLOR, - embedLogoURL: 'https://i.imgur.com/lKlFtbs.png', - parameters: [{ - type: 'string', full: true, missingError: 'commons:search.noParams' - }, [{ - type: 'booleanFlag', name: 'tracks', aliases: ['songs', 's', 't'] - }]] - }, client) - } - - async search (context, query) { - const results = await this.client.apis.deezer.findAlbums(query) - return results.data - } - - searchResultFormatter (item) { - return `[${item.title}](${item.link}) - [${item.artist.name}](${item.artist.link})` - } - - async handleResult ({ t, channel, author, language, flags }, album) { - channel.startTyping() - album = await this.client.apis.deezer.getAlbum(album.id) - const { link, title, cover_big: cover, artist, nb_tracks: trackNumber, tracks, genres, release_date: date, explicit_lyrics: explicitLyric, fans } = album - let trackList = tracks.data.slice(0, 10).map((track, i) => { - const explicit = track.explicit_lyrics ? this.getEmoji('explicit') : '' - return `\`${this.formatIndex(i, tracks)}\`. ${explicit} [${track.title_short}](${track.link}) \`(${MiscUtils.formatDuration(track.duration * 1000)})\`` - }) - const embed = new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor(t('commands:deezer.subcommands.album.albumInfo'), this.embedLogoURL, link) - .setThumbnail(cover) - .setURL(link) - - if (flags.tracks) { - if (tracks.data.length > 10) trackList.push(t('music:moreTracks', { tracks: tracks.data.length - 10 })) - embed.setAuthor(t('commands:deezer.subcommands.album.albumTracks'), this.embedLogoURL, link) - .setTitle(title) - .setDescription(trackList) - channel.send(embed).then(() => channel.stopTyping()) - return - } - - const explicit = explicitLyric ? this.getEmoji('explicit') : '' - trackList = trackList.slice(0, 5) - if (trackList.length > 5) trackList.push(t('music:moreTracks', { tracks: trackNumber - 5 })) - embed.setDescription(`${explicit} [${title}](${link}) \`(${date.split('-')[0]})\``) - .addField(t('music:artist'), `[${artist.name}](https://www.deezer.com/artist/${artist.id})`, true) - .addField(t('commands:deezer.fans'), MiscUtils.formatNumber(fans, language), true) - .addField(t('music:genres'), genres.data.map(g => g.name).join(', '), true) - .addField(t('music:tracksCountParentheses', { tracks: trackNumber }), trackList) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/deezer/artist.js b/src/commands/misc/deezer/artist.js deleted file mode 100644 index 3c5bd9703..000000000 --- a/src/commands/misc/deezer/artist.js +++ /dev/null @@ -1,71 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants, MiscUtils } = require('../../../') - -module.exports = class DeezerArtist extends SearchCommand { - constructor (client) { - super({ - name: 'artist', - aliases: ['ar'], - parent: 'deezer', - embedColor: Constants.DEEZER_COLOR, - embedLogoURL: 'https://i.imgur.com/lKlFtbs.png', - parameters: [{ - type: 'string', full: true, missingError: 'commons:search.noParams' - }, [{ - type: 'booleanFlag', name: 'albums', aliases: ['a'] - }, { - type: 'booleanFlag', name: 'related', aliases: ['r'] - }]] - }, client) - } - - async search (context, query) { - const results = await this.client.apis.deezer.findArtists(query) - return results.data - } - - searchResultFormatter (item, { t, language }) { - return `[${item.name}](${item.link}) - ${t('commands:deezer.fansCount', { fans: MiscUtils.formatNumber(item.nb_fan, language) })}` - } - - async handleResult ({ t, channel, author, language, flags }, artist) { - channel.startTyping() - const { id, name, link, nb_album: albums, picture_big: cover, nb_fan: fans } = artist - const embed = new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor(t('commands:deezer.subcommands.artist.artistInfo'), this.embedLogoURL, link) - .setThumbnail(cover) - if (flags.albums) { - const { data } = await this.client.apis.deezer.getArtistAlbums(id) - const albumList = data.map((album, i) => { - const explicit = album.explicit_lyrics ? this.getEmoji('explicit') : '' - return `\`${this.formatIndex(i, data)}\`. ${explicit} [${album.title}](${album.link}) \`(${album.release_date.split('-')[0]})\`` - }) - if (albums > 10) albumList.push(t('music:moreAlbums', { albums: albums - 10 })) - return channel.send(embed - .setDescription(albumList) - .setTitle(name) - .setURL(link) - .setAuthor(t('commands:deezer.subcommands.artist.artistAlbums'), this.embedLogoURL, link) - ).then(() => channel.stopTyping()) - } - - if (flags.related) { - const { data } = await this.client.apis.deezer.getArtistRelated(id) - const artistList = data.slice(0, 10).map((artist, i) => { - return `\`${this.formatIndex(i, data)}\`. [${artist.name}](${artist.link}) - ${t('commands:deezer.fansCount', { fans: MiscUtils.formatNumber(artist.nb_fan, language) })}` - }) - if (albums.length > 10) artistList.push(t('music:moreArtists', { artists: data.length - 10 })) - return channel.send(embed - .setDescription(artistList) - .setTitle(name) - .setURL(link) - .setAuthor(t('commands:deezer.subcommands.artist.artistRelated'), this.embedLogoURL, link) - ).then(() => channel.stopTyping()) - } - - embed.setDescription(`[${name}](${link})`) - .addField(t('music:albumPlural'), MiscUtils.formatNumber(albums, language), true) - .addField(t('commands:deezer.fans'), MiscUtils.formatNumber(fans, language), true) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/deezer/playlist.js b/src/commands/misc/deezer/playlist.js deleted file mode 100644 index 1a60353cf..000000000 --- a/src/commands/misc/deezer/playlist.js +++ /dev/null @@ -1,59 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants, MiscUtils } = require('../../../') - -const moment = require('moment') - -module.exports = class DeezerPlaylist extends SearchCommand { - constructor (client) { - super({ - name: 'playlist', - aliases: ['p'], - parent: 'deezer', - embedColor: Constants.DEEZER_COLOR, - embedLogoURL: 'https://i.imgur.com/lKlFtbs.png', - parameters: [{ - type: 'string', full: true, missingError: 'commons:search.noParams' - }, [{ - type: 'booleanFlag', name: 'tracks', aliases: ['songs', 's', 't'] - }]] - }, client) - } - - async search (context, query) { - const results = await this.client.apis.deezer.findPlaylists(query) - return results.data - } - - searchResultFormatter (item, { t, language }) { - return `[${item.title}](${item.link}) - ${t('music:tracksCount', { tracks: MiscUtils.formatNumber(item.nb_tracks, language) })}` - } - - async handleResult ({ t, channel, author, language, flags }, { id }) { - channel.startTyping() - const playlist = await this.client.apis.deezer.getPlaylist(id) - const { title, link, description, nb_tracks: trackNumber, fans, creation_date: date, picture_big: cover, creator, tracks } = playlist - let trackList = tracks.data.slice(0, 10).map((track, i) => { - const explicit = track.explicit_lyrics ? this.getEmoji('explicit') : '' - return `\`${this.formatIndex(i, tracks)}\`. ${explicit} [${track.title_short}](${track.link}) \`(${MiscUtils.formatDuration(track.duration * 1000)})\`` - }) - const embed = new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor(t('commands:deezer.subcommands.playlist.playlistInfo'), this.embedLogoURL, link) - .setThumbnail(cover) - .setTitle(title) - .setURL(link) - if (flags.tracks) { - if (tracks.data.length > 10) trackList.push(t('music:moreTracks', { tracks: tracks.data.length - 10 })) - embed.setAuthor(t('commands:deezer.subcommands.playlist.playlistTracks'), this.embedLogoURL, link) - .setDescription(trackList) - return channel.send(embed).then(() => channel.stopTyping()) - } - trackList = trackList.slice(0, 5) - if (tracks.data.length > 5) trackList.push(t('music:moreTracks', { tracks: tracks.data.length - 5 })) - embed.setDescription(description) - .addField(t('commands:deezer.createdAt'), moment(date).format('LLL'), true) - .addField(t('commands:deezer.createdBy'), `[${creator.name}](https://www.deezer.com/profile/${creator.id})`, true) - .addField(t('commands:deezer.fans'), MiscUtils.formatNumber(fans, language), true) - .addField(t('music:tracksCountParentheses', { tracks: trackNumber }), trackList) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/deezer/podcast.js b/src/commands/misc/deezer/podcast.js deleted file mode 100644 index 9805b27f5..000000000 --- a/src/commands/misc/deezer/podcast.js +++ /dev/null @@ -1,50 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants, MiscUtils } = require('../../../') - -module.exports = class DeezerPodcast extends SearchCommand { - constructor (client) { - super({ - name: 'podcast', - aliases: ['pod'], - parent: 'deezer', - embedColor: Constants.DEEZER_COLOR, - embedLogoURL: 'https://i.imgur.com/lKlFtbs.png', - parameters: [{ - type: 'string', full: true, missingError: 'commons:search.noParams' - }, [{ - type: 'booleanFlag', name: 'episodes', aliases: ['e', 'eps', 'ep'] - }]] - }, client) - } - - async search (context, query) { - const results = await this.client.apis.deezer.findPodcasts(query) - return results.data - } - - searchResultFormatter (item, { t, language }) { - return `[${item.title}](${item.link}) - ${t('commands:deezer.fansCount', { fans: MiscUtils.formatNumber(item.fans, language) })}` - } - - async handleResult ({ t, channel, author, language, flags }, podcast) { - channel.startTyping() - const { id, title, description, link, fans, picture_big: cover } = podcast - const embed = new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor(t('commands:deezer.subcommands.podcast.podcastInfo'), this.embedLogoURL, link) - .setThumbnail(cover) - .setTitle(title) - .setURL(link) - - if (flags.episodes) { - const { data } = await this.client.apis.deezer.getPodcastEpisodes(id) - const episodesList = data.slice(0, 10).map((ep, i) => `\`${this.formatIndex(i, data)}\`. [${ep.title}](https://www.deezer.com/episode/${ep.id}) \`(${MiscUtils.formatDuration(ep.duration * 1000)})\``) - if (data.length > 10) episodesList.push(t('commands:deezer.subcommands.podcast.moreEpisodes', { episodes: data.length - 10 })) - embed.setDescription(episodesList) - .setAuthor(t('commands:deezer.subcommands.podcast.podcastEpisodes'), this.embedLogoURL, link) - return channel.send(embed).then(() => channel.stopTyping()) - } - embed.setDescription(description.length < 2040 ? description : description.substring(0, 2040) + '...') - .addField(t('commands:deezer.fans'), MiscUtils.formatNumber(fans, language), true) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/deezer/track.js b/src/commands/misc/deezer/track.js deleted file mode 100644 index 18800ec34..000000000 --- a/src/commands/misc/deezer/track.js +++ /dev/null @@ -1,36 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants, MiscUtils } = require('../../../') - -module.exports = class DeezerTrack extends SearchCommand { - constructor (client) { - super({ - name: 'track', - aliases: ['song', 't', 's'], - parent: 'deezer', - embedColor: Constants.DEEZER_COLOR, - embedLogoURL: 'https://i.imgur.com/lKlFtbs.png' - }, client) - } - - async search (context, query) { - const results = await this.client.apis.deezer.findTracks(query) - return results.data - } - - searchResultFormatter (item) { - return `[${item.title_short}](${item.link}) - [${item.artist.name}](${item.artist.link})` - } - - handleResult ({ t, channel, author }, track) { - channel.startTyping() - const { link, title, duration, explicit_lyrics: explicitLyric, artist, album } = track - const explicit = explicitLyric ? this.getEmoji('explicit') : '' - const embed = new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor(t('commands:deezer.subcommands.track.trackInfo'), this.embedLogoURL, link) - .setThumbnail(album.cover_big) - .setDescription(`${explicit} [${title}](${link}) \`(${MiscUtils.formatDuration(duration * 1000)})\``) - .addField(t('music:artist'), `[${artist.name}](${artist.link})`, true) - .addField(t('music:album'), `[${album.title}](https://www.deezer.com/album/${album.id})`, true) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/deezer/user.js b/src/commands/misc/deezer/user.js deleted file mode 100644 index c0119da56..000000000 --- a/src/commands/misc/deezer/user.js +++ /dev/null @@ -1,39 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants, MiscUtils } = require('../../../') - -module.exports = class DeezerUser extends SearchCommand { - constructor (client) { - super({ - name: 'user', - aliases: ['u'], - parent: 'deezer', - embedColor: Constants.DEEZER_COLOR, - embedLogoURL: 'https://i.imgur.com/lKlFtbs.png' - }, client) - } - - async search (context, query) { - const results = await this.client.apis.deezer.findUser(query) - return results.data - } - - searchResultFormatter (item) { - return `[${item.name}](https://www.deezer.com/profile/${item.id})` - } - - async handleResult ({ t, channel, author, language }, user) { - channel.startTyping() - const { name, picture_big: cover, id } = user - const link = `https://www.deezer.com/profile/${id}` - const followers = await this.client.apis.deezer.getUserFollowers(id) - const followings = await this.client.apis.deezer.getUserFollowings(id) - const embed = new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor(t('commands:deezer.subcommands.user.userInfo'), this.embedLogoURL, link) - .setThumbnail(cover) - .setTitle(name) - .setURL(link) - .addField(t('commands:deezer.followers'), MiscUtils.formatNumber(followers.total, language), true) - .addField(t('commands:deezer.following'), MiscUtils.formatNumber(followings.total, language), true) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/eclipseplugin.js b/src/commands/misc/eclipseplugin.js deleted file mode 100644 index 0ca70e077..000000000 --- a/src/commands/misc/eclipseplugin.js +++ /dev/null @@ -1,58 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants } = require('../..') -const moment = require('moment') - -module.exports = class EclipsePlugin extends SearchCommand { - constructor (client) { - super({ - name: 'eclipseplugin', - aliases: ['eclipseplugins', 'eclipse', 'eclipsemarketplace'], - requirements: { apis: ['eclipseplugins'] }, - embedColor: Constants.ECLIPSE_PLUGINS_COLOR, - embedLogoURL: 'https://i.imgur.com/h72SGPd.png' - }, client) - } - - async search (_, query) { - const res = await this.client.apis.eclipseplugins.search(query) - const node = res.marketplace.search.node - return Array.isArray(node) ? node : [node] - } - - searchResultFormatter (i) { - return `[${i.name} - ${i.owner}](${i.url})` - } - - async handleResult ({ t, author, channel, language }, { categories, changed, id, image, installstotal, homepageurl, license, name, owner, shortdescription, url, version }) { - moment.locale(language) - - channel.send( - new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor(t('commands:eclipseplugin.marketplace'), this.embedLogoURL, 'https://marketplace.eclipse.org/') - .setURL(url) - .setThumbnail(image) - .setTitle(name) - .setDescriptionFromBlockArray([ - [ - shortdescription.replace(/(<([^>]+)>)/gi, '') - ], - [ - t('commands:eclipseplugin.by', { name: owner, homepage: homepageurl }) - ], - [ - t('commands:eclipseplugin.installs', { count: Number(installstotal).toLocaleString(language) }) - ], - [ - categories.category.map((c) => `\`${c.name}\``).join(', ') - ], - [ - t('commands:eclipseplugin.lastUpdate', { ago: moment(Number(changed) * 1e3).fromNow(), version }) - ], - [ - `**${t('commands:eclipseplugin.license')}**: ${license}`, - `[${t('commands:eclipseplugin.install')}](http://marketplace.eclipse.org/marketplace-client-intro?mpc_install=${id})` - ] - ]) - ) - } -} diff --git a/src/commands/misc/fliptext.js b/src/commands/misc/fliptext.js deleted file mode 100644 index d454adfd0..000000000 --- a/src/commands/misc/fliptext.js +++ /dev/null @@ -1,25 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class FlipText extends Command { - constructor (client) { - super({ - name: 'fliptext', - parameters: [{ - type: 'string', full: true, missingError: 'commands:fliptext.noSentence' - }] - }, client) - } - - run ({ author, channel }, text) { - const embed = new SwitchbladeEmbed(author) - const mapping = '¡"#$%⅋,)(*+\'-˙/0ƖᄅƐㄣϛ9ㄥ86:;<=>¿@∀qƆpƎℲפHIſʞ˥WNOԀQɹS┴∩ΛMX⅄Z[/]^_`ɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz{|}~' - const offset = '!'.charCodeAt(0) - embed.setTitle( - text.split('') - .map(c => c.charCodeAt(0) - offset) - .map(c => mapping[c] || ' ') - .reverse().join('') - ) - channel.send(embed) - } -} diff --git a/src/commands/misc/fox.js b/src/commands/misc/fox.js deleted file mode 100644 index 4c7975438..000000000 --- a/src/commands/misc/fox.js +++ /dev/null @@ -1,19 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') -const fetch = require('node-fetch') - -module.exports = class Fox extends Command { - constructor (client) { - super({ - name: 'fox' - }, client) - } - - async run ({ t, author, channel }) { - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - const { image } = await fetch('https://randomfox.ca/floof/').then(res => res.json()) - embed.setImage(image) - .setDescription(t('commands:fox.hereIsYourFox')) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/geekjokes.js b/src/commands/misc/geekjokes.js deleted file mode 100644 index 4dc0629ac..000000000 --- a/src/commands/misc/geekjokes.js +++ /dev/null @@ -1,19 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') -const fetch = require('node-fetch') - -module.exports = class GeekJokes extends Command { - constructor (client) { - super({ - name: 'geekjokes', - aliases: ['geek', 'geekjoke', 'geekj'] - }, client) - } - - async run ({ author, channel }, number) { - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - const body = await fetch('https://geek-jokes.sameerkumar.website/api').then(res => res.json()) - embed.setTitle(body) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/goat.js b/src/commands/misc/goat.js deleted file mode 100644 index 39f31e5ab..000000000 --- a/src/commands/misc/goat.js +++ /dev/null @@ -1,25 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class Goat extends Command { - constructor (client) { - super({ - name: 'goat', - aliases: ['placegoat'], - category: 'general', - parameters: [{ - type: 'number', - required: false - }, { - type: 'number', - required: false - }] - }, client) - } - - async run ({ t, author, channel }, width = 500, height = 0) { - channel.send( - new SwitchbladeEmbed(author) - .setImage(`http://placegoat.com/${Math.round(width)}/${Math.round(height)}`).setDescription(t(`commands:goat.hereIsYourGoat${height !== 0 ? '_resolution' : ''}`, { width, height })) - ) - } -} diff --git a/src/commands/misc/googleplay.js b/src/commands/misc/googleplay.js deleted file mode 100644 index bd3454692..000000000 --- a/src/commands/misc/googleplay.js +++ /dev/null @@ -1,15 +0,0 @@ -const { SubcommandListCommand, Constants } = require('../../') - -module.exports = class GooglePlay extends SubcommandListCommand { - constructor (client) { - super({ - name: 'googleplay', - aliases: ['gplay', 'androidmarket'], - requirements: { apis: ['gplaystore'] }, - authorString: 'commands:googleplay.serviceName', - authorImage: 'https://i.imgur.com/kLdJwcj.png', - authorURL: 'https://play.google.com', - embedColor: Constants.GOOGLEPLAY_COLOR - }, client) - } -} diff --git a/src/commands/misc/googleplay/app.js b/src/commands/misc/googleplay/app.js deleted file mode 100644 index c3cdcf82f..000000000 --- a/src/commands/misc/googleplay/app.js +++ /dev/null @@ -1,38 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants } = require('../../../') - -module.exports = class GooglePlayApp extends SearchCommand { - constructor (client) { - super({ - name: 'app', - aliases: ['application', 'a'], - parent: 'googleplay', - embedColor: Constants.GOOGLEPLAY_COLOR, - embedLogoURL: 'https://i.imgur.com/kLdJwcj.png' - }, client) - } - - async search (_, query) { - return this.client.apis.gplaystore.searchApp(query) - } - - searchResultFormatter (items) { - return `[${items.title} - ${items.developer}](${items.url})` - } - - async handleResult ({ t, channel, author, language }, { title, screenshots, installs, released, contentRating, genre, url, priceText, price, icon, summary, appId, developer, developerId, currency }) { - channel.send( - new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setThumbnail(icon) - .setAuthor(title, icon, url) - .setDescription(summary.replace(/&/g, '&')) - .addField(t('commands:googleplay.developer'), `${developer} (${developerId})`, true) - .addField(t('commands:googleplay.price'), priceText, true) - .addField(t('commands:googleplay.genre'), genre, true) - .addField(t('commands:googleplay.rating'), contentRating, true) - .addField(t('commands:googleplay.installs'), installs, true) - .addField(t('commands:googleplay.released'), released, true) - .setImage(screenshots[Math.floor(Math.random() * screenshots.length)]) - ) - } -} diff --git a/src/commands/misc/googleplay/developer.js b/src/commands/misc/googleplay/developer.js deleted file mode 100644 index b83477434..000000000 --- a/src/commands/misc/googleplay/developer.js +++ /dev/null @@ -1,38 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants } = require('../../../') - -module.exports = class GooglePlayDev extends SearchCommand { - constructor (client) { - super({ - name: 'developer', - aliases: ['dev', 'd'], - parent: 'googleplay', - embedColor: Constants.GOOGLEPLAY_COLOR, - embedLogoURL: 'https://i.imgur.com/kLdJwcj.png' - }, client) - } - - async search (_, query) { - return this.client.apis.gplaystore.searchDev(query) - } - - searchResultFormatter (items) { - return `[${items.title} - ${items.developer}](${items.url})` - } - - async handleResult ({ t, channel, author, language }, { title, screenshots, installs, released, contentRating, genre, url, priceText, price, icon, summary, appId, developer, developerId, currency }) { - channel.send( - new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setThumbnail(icon) - .setAuthor(title, icon, url) - .setDescription(summary.replace(/&/g, '&')) - .addField(t('commands:googleplay.developer'), `${developer} (${developerId})`, true) - .addField(t('commands:googleplay.price'), priceText, true) - .addField(t('commands:googleplay.genre'), genre, true) - .addField(t('commands:googleplay.rating'), contentRating, true) - .addField(t('commands:googleplay.installs'), installs, true) - .addField(t('commands:googleplay.released'), released, true) - .setImage(screenshots[Math.floor(Math.random() * screenshots.length)]) - ) - } -} diff --git a/src/commands/misc/hibp.js b/src/commands/misc/hibp.js deleted file mode 100644 index 2ccb1bdb2..000000000 --- a/src/commands/misc/hibp.js +++ /dev/null @@ -1,29 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -const types = ['breach', 'paste', 'b', 'p'] - -module.exports = class HIBP extends Command { - constructor (client) { - super({ - name: 'hibp', - aliases: ['haveibeenpwned'], - requirements: { apis: ['hibp'] }, - parameters: [{ - type: 'string', - full: false, - whitelist: types, - missingError: ({ t, prefix }) => { - return new SwitchbladeEmbed().setTitle(t('commons:search.noType')) - .setDescription([ - this.usage(t, prefix), - '', - `__**${t('commons:search.types')}:**__`, - `\`${['breach', 'paste'].join('`, `')}\`` - ].join('\n')) - } - }] - }, client) - - this.HIBP_LOGO = 'https://haveibeenpwned.com/Content/Images/SocialLogo.png' - } -} diff --git a/src/commands/misc/hibp/breach.js b/src/commands/misc/hibp/breach.js deleted file mode 100644 index f110ed574..000000000 --- a/src/commands/misc/hibp/breach.js +++ /dev/null @@ -1,34 +0,0 @@ -const { Command, SwitchbladeEmbed, Constants, MiscUtils } = require('../../../') -const moment = require('moment') - -module.exports = class HIBPBreach extends Command { - constructor (client) { - super({ - name: 'breach', - aliases: ['b'], - parent: 'hibp', - parameters: [{ - type: 'string', missingError: 'commands:hibp.noEmail' - }] - }, client) - } - - async run ({ t, author, channel, language }, query) { - channel.startTyping() - try { - moment.locale(language) - const data = await this.client.apis.hibp.getBreaches(query) - const embed = new SwitchbladeEmbed(author) - .setColor(Constants.PWNED_COLOR) - .setAuthor(t('commands:hibp.breached'), this.parentCommand.HIBP_LOGO) - .setDescription(`${data.length > 1 ? t('commands:hibp.subcommands.breach.pwnedInPlural', { count: MiscUtils.formatNumber(data.length, language) }) : t('commands:hibp.subcommands.breach.pwnedInSingular')}:\n\n${data.slice(0, 5).map(breach => `**${breach.Title}** - ${moment(breach.BreachDate).format('LLL')}`).join('\n')}${data.length > 5 ? `\n${t('commands:hibp.andMore', { count: data.length - 5 })}` : ''}`) - channel.send(embed).then(() => channel.stopTyping()) - } catch (e) { - channel.send(new SwitchbladeEmbed(author) - .setColor(Constants.NOT_PWNED_COLOR) - .setAuthor(t('commands:hibp.notBreached'), this.parentCommand.HIBP_LOGO) - .setDescription(t('commands:hibp.subcommands.breach.notFoundBreach')) - ).then(() => channel.stopTyping()) - } - } -} diff --git a/src/commands/misc/hibp/paste.js b/src/commands/misc/hibp/paste.js deleted file mode 100644 index 6d267407c..000000000 --- a/src/commands/misc/hibp/paste.js +++ /dev/null @@ -1,34 +0,0 @@ -const { Command, SwitchbladeEmbed, Constants, MiscUtils } = require('../../../') -const moment = require('moment') - -module.exports = class HIBPPaste extends Command { - constructor (client) { - super({ - name: 'paste', - aliases: ['p'], - parent: 'hibp', - parameters: [{ - type: 'string', missingError: 'commands:hibp.noEmail' - }] - }, client) - } - - async run ({ t, author, channel, language }, query) { - channel.startTyping() - try { - moment.locale(language) - const data = await this.client.apis.hibp.getPastes(query) - const embed = new SwitchbladeEmbed(author) - .setColor(Constants.PWNED_COLOR) - .setAuthor(t('commands:hibp.breached'), this.parentCommand.HIBP_LOGO) - .setDescription(`${data.length > 1 ? t('commands:hibp.subcommands.paste.pwnedInPlural', { count: MiscUtils.formatNumber(data.length, language) }) : t('commands:hibp.subcommands.paste.pwnedInSingular')}:\n\n${data.slice(0, 5).map(paste => `**${paste.Source}** - ${encodeURI(paste.Id)} ${paste.Date !== null ? `- ${moment(paste.Date).format('LLL')}` : ''}`).join('\n')}${data.length > 5 ? `\n${t('commands:hibp.andMore', { count: data.length - 5 })}` : ''}`) - channel.send(embed).then(() => channel.stopTyping()) - } catch (e) { - channel.send(new SwitchbladeEmbed(author) - .setColor(Constants.NOT_PWNED_COLOR) - .setAuthor(t('commands:hibp.notBreached'), this.parentCommand.HIBP_LOGO) - .setDescription(t('commands:hibp.subcommands.paste.notFoundPaste')) - ).then(() => channel.stopTyping()) - } - } -} diff --git a/src/commands/misc/httpdog.js b/src/commands/misc/httpdog.js deleted file mode 100644 index 5b1eb3c16..000000000 --- a/src/commands/misc/httpdog.js +++ /dev/null @@ -1,21 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class HttpDog extends Command { - constructor (client) { - super({ - name: 'httpdog', - category: 'general', - parameters: [{ - type: 'number', - required: false - }] - }, client) - } - - async run ({ t, author, channel }, statusCode = 200) { - channel.send( - new SwitchbladeEmbed(author) - .setImage(`https://httpstatusdogs.com/img/${Math.round(statusCode)}.jpg`) - ) - } -} diff --git a/src/commands/misc/imageoftheday.js b/src/commands/misc/imageoftheday.js deleted file mode 100644 index 99c73b540..000000000 --- a/src/commands/misc/imageoftheday.js +++ /dev/null @@ -1,28 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -const Parser = require('rss-parser') -const parser = new Parser() - -module.exports = class ImageOfTheDay extends Command { - constructor (client) { - super({ - name: 'imageoftheday', - aliases: ['iotd'] - }, client) - } - - async run ({ t, author, channel }) { - channel.startTyping() - const embed = new SwitchbladeEmbed(author) - const feed = await parser.parseURL('https://www.nasa.gov/rss/dyn/lg_image_of_the_day.rss') - const item = feed.items[0] - embed - .setAuthor(t('commands:imageoftheday.embedAuthor'), 'https://i.imgur.com/bHmqqHL.jpg') - .setTitle(item.title) - .setURL(item.link) - .setImage(item.enclosure.url) - .setDescription(item.content) - .setColor(0x0b3d91) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/inspirobot.js b/src/commands/misc/inspirobot.js deleted file mode 100644 index 349a70a72..000000000 --- a/src/commands/misc/inspirobot.js +++ /dev/null @@ -1,22 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -const fetch = require('node-fetch') - -module.exports = class InspiroBot extends Command { - constructor (client) { - super({ - name: 'inspirobot', - aliases: ['inspiro', 'ibot'] - }, client) - } - - async run ({ t, author, channel }) { - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - const body = await fetch('http://inspirobot.me/api?generate=true').then(res => res.text()) - embed - .setImage(body.toString('utf8')) - .setDescription(t('commands:inspirobot.quote')) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/jetbrainsplugin.js b/src/commands/misc/jetbrainsplugin.js deleted file mode 100644 index 6a20afcb0..000000000 --- a/src/commands/misc/jetbrainsplugin.js +++ /dev/null @@ -1,71 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants } = require('../..') -const moment = require('moment') - -const BASE_URL = 'https://plugins.jetbrains.com' - -module.exports = class JetBrainsPlugin extends SearchCommand { - constructor (client) { - super({ - name: 'jetbrainsplugin', - aliases: ['jetbrains', 'jetbrainsplugins'], - requirements: { apis: ['jetbrainsplugins'] }, - embedColor: Constants.JETBRAINS_PLUGIN, - embedLogoURL: 'https://i.imgur.com/2djoFWM.png' - }, client) - } - - async search (_, query) { - const res = await this.client.apis.jetbrainsplugins.search(query) - return res.data.plugins - } - - searchResultFormatter (i) { - return `[${i.name} - ${i.downloads.toLocaleString()} downloads](${BASE_URL}${i.link})` - } - - getRatingEmojis (rating) { - return (this.getEmoji('ratingstar', '⭐').repeat(Math.floor(rating))) + (this.getEmoji('ratinghalfstar').repeat(Math.ceil(rating - Math.floor(rating)))) - } - - async handleResult ({ t, author, channel, language }, { id, rating }) { - moment.locale(language) - - const { cdate, name, downloads, urls, preview, vendor, link, tags, icon } = await this.client.apis.jetbrainsplugins.getPluginInfo(id) - const [{ version }] = await this.client.apis.jetbrainsplugins.getPluginVersion(id) - - const stars = this.getRatingEmojis(rating) - - const embed = new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor(t('commands:jetbrainsplugin.plugins'), this.embedLogoURL, BASE_URL) - .setURL(`${BASE_URL}${link}`) - .setTitle(name) - .setDescriptionFromBlockArray([ - [ - preview - ], - [ - t('commands:jetbrainsplugin.by', { name: vendor.name, url: vendor.url }) - ], - [ - t('commands:jetbrainsplugin.installs', { count: downloads.toLocaleString(language) }), - stars - ], - [ - tags.map((t) => `\`${t.name}\``).join(', ') - ], - [ - t('commands:jetbrainsplugin.lastUpdate', { ago: moment(cdate).fromNow(), version }) - ], - [ - `[${t('commands:jetbrainsplugin.license')}](${urls.licenseUrl})`, - urls.docUrl ? `[${t('commands:jetbrainsplugin.documentation')}](${urls.docUrl})` : '', - `[${t('commands:jetbrainsplugin.download')}](${BASE_URL}${link})` - ] - ]) - - if (icon) embed.setThumbnail(`${BASE_URL}${icon.replace(/svg$/, 'png')}`) - - channel.send(embed) - } -} diff --git a/src/commands/misc/numberfacts.js b/src/commands/misc/numberfacts.js deleted file mode 100644 index d47bb887a..000000000 --- a/src/commands/misc/numberfacts.js +++ /dev/null @@ -1,29 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed } = require('../../') - -const fetch = require('node-fetch') - -module.exports = class NumberFacts extends Command { - constructor (client) { - super({ - name: 'numberfacts', - aliases: ['number', 'numfacts', 'numf'], - parameters: [{ - type: 'number', min: 0, missingError: 'commands:numberfacts.validNumber' - }] - }, client) - } - - async run ({ t, author, channel }, number) { - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - try { - const body = await fetch(`http://numbersapi.com/${number}/trivia`).then(res => res.text()) - embed.setTitle(body) - channel.send(embed).then(() => channel.stopTyping()) - } catch (e) { - channel.stopTyping() - console.error(e) - throw new CommandError(t('commands:numberfacts.anErrorOcurred')) - } - } -} diff --git a/src/commands/misc/owlbot.js b/src/commands/misc/owlbot.js deleted file mode 100644 index 9499ce1d2..000000000 --- a/src/commands/misc/owlbot.js +++ /dev/null @@ -1,51 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed, Constants } = require('../../') - -module.exports = class Owlbot extends Command { - constructor (client) { - super({ - name: 'owlbot', - aliases: ['owl'], - requirements: { - apis: ['owlbot'] - }, - parameters: [{ - type: 'string', - full: true, - missingError: 'commands:owlbot.noWord' - }] - }, client) - } - - async run ({ t, channel }, word) { - channel.startTyping() - try { - const { data } = await this.client.apis.owlbot.request(word) - const embed = new SwitchbladeEmbed() - .setTitle(data.word) - .addFields( - data.definitions.map(d => - ({ - name: d.type, - value: `${d.definition}${d.example ? `\n"_${d.example}_"` : ''}` - }) - ) - ) - .setColor(Constants.OWLBOT_COLOR) - .setFooter( - t('commands:owlbot.footer'), - 'https://media.owlbot.info/dictionary/images/owlbot.png.400x400_q85_box-0,0,287,288_crop_detail.png' - ) - if (data.pronunciation) embed.setDescription(`/${data.pronunciation}/`) - const definitionWithImage = data.definitions.find(d => d.image_url) - if (definitionWithImage) embed.setThumbnail(definitionWithImage.image_url) - channel.send(embed).then(() => channel.stopTyping()) - } catch (err) { - channel.stopTyping() - if (err.response && err.response.status === 404) { - throw new CommandError(t('commands:owlbot.notFound')) - } else { - throw new CommandError(t('commands:owlbot.error')) - } - } - } -} diff --git a/src/commands/misc/qrcode.js b/src/commands/misc/qrcode.js deleted file mode 100644 index 31d93f475..000000000 --- a/src/commands/misc/qrcode.js +++ /dev/null @@ -1,11 +0,0 @@ -const { SubcommandListCommand } = require('../../') - -module.exports = class QRCode extends SubcommandListCommand { - constructor (client) { - super({ - name: 'qrcode', - aliases: ['qr'], - authorString: 'commands:qrcode.title' - }, client) - } -} diff --git a/src/commands/misc/qrcode/generate.js b/src/commands/misc/qrcode/generate.js deleted file mode 100644 index 12a3b6a25..000000000 --- a/src/commands/misc/qrcode/generate.js +++ /dev/null @@ -1,21 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../../') - -module.exports = class QRCodeGenerate extends Command { - constructor (client) { - super({ - name: 'generate', - aliases: ['create', 'g'], - parent: 'qrcode', - parameters: [{ - type: 'string', full: true, missingError: 'commands:qrcode.subcommands.generate.noText' - }] - }, client) - } - - async run ({ t, author, channel, language }, text) { - channel.send( - new SwitchbladeEmbed(author) - .setImage(`https://api.qrserver.com/v1/create-qr-code/?data=${encodeURIComponent(text)}`) - ) - } -} diff --git a/src/commands/misc/qrcode/read.js b/src/commands/misc/qrcode/read.js deleted file mode 100644 index afacc0402..000000000 --- a/src/commands/misc/qrcode/read.js +++ /dev/null @@ -1,30 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed } = require('../../../') -const fetch = require('node-fetch') - -module.exports = class QRCodeRead extends Command { - constructor (client) { - super({ - name: 'read', - aliases: ['r'], - parent: 'qrcode', - parameters: [{ - type: 'image', - authorAvatar: false, - url: true, - missingError: 'commands:qrcode.subcommands.read.noImage' - }] - }, client) - } - - async run ({ t, channel, author, message }, image) { - const body = await fetch(`http://api.qrserver.com/v1/read-qr-code/?fileurl=${encodeURIComponent(image)}`).then(res => res.json()) - if (body[0].symbol[0].data !== null) { - channel.send( - new SwitchbladeEmbed(author) - .setDescription(body[0].symbol[0].data) - ) - } else { - throw new CommandError(t('commands:qrcode.subcommands.read.unknownImage')) - } - } -} diff --git a/src/commands/misc/shiba.js b/src/commands/misc/shiba.js deleted file mode 100644 index 662ceabbd..000000000 --- a/src/commands/misc/shiba.js +++ /dev/null @@ -1,21 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -const fetch = require('node-fetch') - -module.exports = class Shiba extends Command { - constructor (client) { - super({ - name: 'shiba', - aliases: ['shibainu', 'doge'] - }, client) - } - - async run ({ t, author, channel }) { - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - const body = await fetch('http://shibe.online/api/shibes').then(res => res.json()) - embed.setDescription(`${t('commands:shiba.hereIsYourShiba')} <:DoggoF:445701839564963840>`) - embed.setImage(body[0]) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/tcdne.js b/src/commands/misc/tcdne.js deleted file mode 100644 index 4fb6f3408..000000000 --- a/src/commands/misc/tcdne.js +++ /dev/null @@ -1,18 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class TCDNE extends Command { - constructor (client) { - super({ - name: 'tcdne', - aliases: ['thiscatdoesnotexist'] - }, client) - } - - run ({ t, channel, author }) { - channel.send( - new SwitchbladeEmbed(author) - .setDescription(t('commands:tcdne.cat')) - .setImage(`https://thiscatdoesnotexist.com/?q=${new Date().getTime()}`) - ) - } -} diff --git a/src/commands/misc/tpdne.js b/src/commands/misc/tpdne.js deleted file mode 100644 index 24b0022b5..000000000 --- a/src/commands/misc/tpdne.js +++ /dev/null @@ -1,18 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class TPDNE extends Command { - constructor (client) { - super({ - name: 'tpdne', - aliases: ['thispersondoesnotexist'] - }, client) - } - - run ({ t, channel, author }) { - channel.send( - new SwitchbladeEmbed(author) - .setDescription(t('commands:tpdne.person')) - .setImage(`https://thispersondoesnotexist.com/image?q=${new Date().getTime()}`) - ) - } -} diff --git a/src/commands/misc/vscodeextension.js b/src/commands/misc/vscodeextension.js deleted file mode 100644 index a7422ec32..000000000 --- a/src/commands/misc/vscodeextension.js +++ /dev/null @@ -1,72 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants } = require('../..') -const moment = require('moment') - -const EXTENSION_URL = 'https://marketplace.visualstudio.com/items/' - -module.exports = class VSCodeExtensions extends SearchCommand { - constructor (client) { - super({ - name: 'vscodeextension', - aliases: ['vscodeextensions', 'codeextensions', 'codeext', 'vscmarketplace', 'vscode'], - requirements: { apis: ['vscodeextensions'] }, - embedColor: Constants.VSCODE_EXTENSIONS_COLOR, - embedLogoURL: 'https://i.imgur.com/Ihot5Zi.png' - }, client) - } - - async search (_, query) { - const res = await this.client.apis.vscodeextensions.search(query) - return res.data.results[0].extensions - } - - searchResultFormatter (i) { - return `[${i.displayName} - ${i.publisher.displayName}](${EXTENSION_URL}${i.publisher.publisherName}.${i.extensionName})` - } - - getRatingEmojis (rating) { - return (this.getEmoji('ratingstar', '⭐').repeat(Math.floor(rating))) + (this.getEmoji('ratinghalfstar').repeat(Math.ceil(rating - Math.floor(rating)))) - } - - async handleResult ({ t, author, channel, language }, { displayName, shortDescription, publisher, versions, extensionName, statistics, categories, tags }) { - moment.locale(language) - const { assetUri, lastUpdated, version } = versions[0] - - const [{ value: installs }, { value: averageRating }, { value: ratingCount }] = statistics - const stars = this.getRatingEmojis(averageRating) - - const url = `${EXTENSION_URL}${publisher.publisherName}.${extensionName}` - - channel.send( - new SwitchbladeEmbed(author) - .setColor(this.embedColor) - .setAuthor(t('commands:vscodeextension.marketplace'), this.embedLogoURL, 'https://marketplace.visualstudio.com/vscode') - .setURL(url) - .setThumbnail(`${assetUri}/Microsoft.VisualStudio.Services.Icons.Default`) - .setTitle(displayName) - .setDescriptionFromBlockArray([ - [ - shortDescription - ], - [ - t('commands:vscodeextension.by', { displayName: publisher.displayName, name: publisher.publisherName }) - ], - [ - t('commands:vscodeextension.installs', { count: installs.toLocaleString(language) }), - `${stars} (${Math.round(ratingCount)})` - ], - [ - categories.join(', '), - tags.map((t) => `\`${t}\``).join(', ') - ], - [ - t('commands:vscodeextension.lastUpdate', { ago: moment(lastUpdated).fromNow(), version }) - ], - [ - `[${t('commands:vscodeextension.license')}](${url}/license)`, - `[${t('commands:vscodeextension.changelog')}](${url}/changelog)`, - `[${t('commands:vscodeextension.install')}](https://vscoderedirect.switchblade.xyz/${publisher.publisherName}.${extensionName})` - ] - ]) - ) - } -} diff --git a/src/commands/misc/whatlanguage.js b/src/commands/misc/whatlanguage.js deleted file mode 100644 index dddefa951..000000000 --- a/src/commands/misc/whatlanguage.js +++ /dev/null @@ -1,25 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class WhatLanguage extends Command { - constructor (client) { - super({ - name: 'whatlanguage', - requirements: { apis: ['languagelayer'] }, - parameters: [{ - type: 'string', full: true, missingError: 'commands:whatlanguage.noText' - }] - }, client) - } - - async run ({ t, author, channel }, query) { - channel.startTyping() - const { data } = await this.client.apis.languagelayer.detectText(query) - const embed = new SwitchbladeEmbed(author) - .setTitle(t('commands:whatlanguage.embedTitle')) - .setDescription(t('commands:whatlanguage.embedDes')) - .addField(t('commands:whatlanguage.fieldLanguage'), `:flag_${data.results[0].language_code}: ${data.results[0].language_name}`, true) - .addField(t('commands:whatlanguage.fieldProbability'), `${Math.round(data.results[0].probability)}%`, true) - .addField(t('commands:whatlanguage.fieldPercentage'), `${data.results[0].percentage}%`, true) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/misc/xkcd.js b/src/commands/misc/xkcd.js deleted file mode 100644 index b572ba032..000000000 --- a/src/commands/misc/xkcd.js +++ /dev/null @@ -1,53 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed, Constants } = require('../../') - -const fetch = require('node-fetch') - -const baseUrl = 'https://xkcd.com' - -module.exports = class XKCD extends Command { - constructor (client) { - super({ - name: 'xkcd', - parameters: [{ - type: 'string', full: true, required: false - }] - }, client) - } - - async run ({ t, author, channel }, arg) { - channel.startTyping() - const embed = new SwitchbladeEmbed() - let response - try { - if (arg) { - if (arg === 'latest') { - response = await fetch(baseUrl + '/info.0.json').then(res => res.json()) - } else if (arg.match(/^\d+$/)) { - response = await fetch(baseUrl + `/${arg}/info.0.json`).then(res => res.json()) - } else { - throw new CommandError(t('commands:xkcd.invalidArgument'), true) - } - } else { - const latestResp = await fetch(`${baseUrl}/info.0.json`).then(res => res.json()) - const latestNumber = latestResp.num - const randomNumber = Math.floor(Math.random() * latestNumber + 1) - response = await fetch(`${baseUrl}/${randomNumber}/info.0.json`).then(res => res.json()) - } - } catch (e) { - if (e.statusCode === 404) { - throw new CommandError(t('commands:xkcd.notFound')) - } - throw new CommandError(new SwitchbladeEmbed(author).setTitle(t('errors:generic')) - .setDescription(`\`${e.message}\`\n\n[${t('commons:reportThis')}](https://github.com/SwitchbladeBot/switchblade/issues)`)) - } - - if (response) { - embed.setColor(Constants.XKCD_COLOR) - .setTitle(`#${response.num} - "${response.title}"`) - .setURL(`http://xkcd.com/${response.num}`) - .setDescription(response.alt) - .setImage(response.img) - channel.send(embed).then(() => { channel.stopTyping() }) - } - } -} diff --git a/src/commands/misc/xkcd37.js b/src/commands/misc/xkcd37.js deleted file mode 100644 index 79bdb22f3..000000000 --- a/src/commands/misc/xkcd37.js +++ /dev/null @@ -1,20 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class XKCD37 extends Command { - constructor (client) { - super({ - name: 'xkcd37', - parameters: [{ - type: 'string', full: true - }] - }, client) - } - - // Context: https://xkcd.com/37/ - - async run ({ author, channel }, text) { - const embed = new SwitchbladeEmbed(author) - embed.setTitle(text.replace(/(\w+?)(?!\\)+(-ass)(\s+)(\S+?)/g, '$1$3ass-$4').replace(/\\-/g, '-')) - channel.send(embed) - } -} diff --git a/src/commands/moderation/createrole.js b/src/commands/moderation/createrole.js deleted file mode 100644 index 01f87aef9..000000000 --- a/src/commands/moderation/createrole.js +++ /dev/null @@ -1,32 +0,0 @@ -const { Command, SwitchbladeEmbed, Color, CommandError } = require('../../') - -module.exports = class CreateRole extends Command { - constructor (client) { - super({ - name: 'createrole', - category: 'moderation', - requirements: { guildOnly: true, botPermissions: ['MANAGE_ROLES'], permissions: ['MANAGE_ROLES'] }, - parameters: [ - { type: 'color', required: false }, - { type: 'string', full: true, missingError: 'commands:createrole.noParams', required: true } - ] - }, client) - } - - async run ({ channel, guild, author, t }, color = new Color('#ffffff'), name) { - const hexcode = color.rgb(true) - const embed = new SwitchbladeEmbed(author) - - try { - await guild.roles.create({ data: { name, color: hexcode } }) - embed - .setTitle(t('commands:createrole.successTitle')) - .setDescription(t('commands:createrole.successMessage', { name })) - .setColor(hexcode) - } catch (err) { - throw new CommandError(t('commands:createrole.errorTitle')) - } - - channel.send(embed) - } -} diff --git a/src/commands/moderation/giverole.js b/src/commands/moderation/giverole.js deleted file mode 100644 index 8fde4cd9c..000000000 --- a/src/commands/moderation/giverole.js +++ /dev/null @@ -1,32 +0,0 @@ -const { Command, SwitchbladeEmbed, CommandError } = require('../../') - -module.exports = class GiveRole extends Command { - constructor (client) { - super({ - name: 'giverole', - aliases: ['gr'], - category: 'moderation', - requirements: { guildOnly: true, botPermissions: ['MANAGE_ROLES'], permissions: ['MANAGE_ROLES'] }, - parameters: [{ - type: 'member', acceptBot: true, missingError: 'errors:invalidUser', acceptSelf: true - }, - { - type: 'role', full: true, missingError: 'errors:invalidRole' - }] - }, client) - } - - async run ({ channel, guild, member: author, t }, member, role) { - const embed = new SwitchbladeEmbed(author) - if (member.roles.highest.position < role.position && author.roles.highest.position < role.position) { - await member.roles.add(role).then(() => { - embed - .setTitle(t('commands:giverole.roleAdded')) - }).catch(() => { - throw new CommandError(t('commands:giverole.error')) - }) - } else { - throw new CommandError(t('commands:giverole.higherError')) - } - } -} diff --git a/src/commands/moderation/move.js b/src/commands/moderation/move.js deleted file mode 100644 index 95bf5cfae..000000000 --- a/src/commands/moderation/move.js +++ /dev/null @@ -1,57 +0,0 @@ -const { Command, CommandError } = require('../../') - -module.exports = class Move extends Command { - constructor (client) { - super({ - name: 'move', - aliases: ['mover'], - category: 'moderation', - requirements: { guildOnly: true, botPermissions: ['MANAGE_MESSAGES'], permissions: ['MANAGE_MESSAGES'] }, - parameters: [{ - type: 'messageLink', - sameGuildOnly: true, - forceExists: true, - linkChannelUserPermission: ['VIEW_MESSAGES'], - linkChannelBotPermission: ['MANAGE_MESSAGES'], - missingError: 'commands:move.missingMessageLink' - }, { - type: 'channel', - onlySameGuild: true, - acceptText: true, - channelUserPermission: ['SEND_MESSAGES'], - channelBotPermission: ['SEND_MESSAGES', 'EMBED_LINKS'], - missingError: 'commands:move.missingChannelMention' - }] - }, client) - } - - async run ({ channel, guild, author, t, message }, link, destinationChannel) { - if (link.channel.nsfw && !destinationChannel.nsfw) throw new CommandError(t('commands:move.channelsHaveDifferentType')) - - const messageObj = {} - const content = link.content - - if (link.attachments.size >= 1) { - messageObj.files = [link.attachments.array()] - } - - if (link.embeds.length >= 1) { - messageObj.embed = {}; - ['fields', 'title', 'description', 'url', 'timestamp', 'color', 'image', 'thumbnail', 'author'].forEach(p => { - messageObj.embed[p] = link.embeds[0][p] - }) - } - - if (Object.keys(messageObj).length === 0 && (!content || content === '')) { - throw new CommandError(t('errors:messageContainsNothing')) - } - - try { - await destinationChannel.send(content, messageObj) - await destinationChannel.send(t('commands:move.messageMoved', { authorName: link.author.username, movedFrom: link.channel.name, movedBy: author.username })) - link.delete() - } catch (e) { - throw new CommandError(t('commands:move.couldntSendMessage')) - } - } -} diff --git a/src/commands/music/lyrics.js b/src/commands/music/lyrics.js deleted file mode 100644 index d68d43fa1..000000000 --- a/src/commands/music/lyrics.js +++ /dev/null @@ -1,55 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed, Constants } = require('../../') - -module.exports = class Lyrics extends Command { - constructor (client) { - super({ - name: 'lyrics', - aliases: ['lyric', 'genius'], - category: 'music', - requirements: { apis: ['genius'] }, - parameters: [{ - type: 'string', full: true, required: false - }] - }, client) - } - - async run ({ t, author, channel, guild }, song) { - channel.startTyping() - - const playingSong = !song - if (playingSong) { - const guildPlayer = (guild && this.client.playerManager && this.client.playerManager.players.get(guild.id)) - if (!guildPlayer || !guildPlayer.playing) { - throw new CommandError(t('commands:lyrics.noTrackName'), true) - } - - song = guildPlayer.playingSong.title - } - - const embed = new SwitchbladeEmbed(author) - const { response: { hits: [hit] } } = await this.client.apis.genius.findTrack(song) - if (hit) { - const { - result: { - song_art_image_thumbnail_url: thumbnailUrl, - title_with_featured: title, - primary_artist: { name: artist }, - url, - path - } - } = hit - const body = await this.client.apis.genius.loadLyrics(url) - - embed.setAuthor('Genius', 'https://i.imgur.com/NmCTsoF.png') - .setDescription(body.length >= 1900 ? `${body.substr(0, 1900)}\n\n[${t('commands:lyrics.fullLyrics')}](http://genius.com${path})` : body) - .setThumbnail(thumbnailUrl) - .setColor(Constants.GENIUS_COLOR) - .setTitle(`${title} - ${artist}`) - .setURL(`http://genius.com${path}`) - return channel.send(embed).then(() => channel.stopTyping()) - } else { - const error = playingSong ? 'noLyricsFoundPlaying' : 'noLyricsFound' - throw new CommandError(t(`commands:lyrics.${error}`)) - } - } -} diff --git a/src/commands/nsfw/porngifs.js b/src/commands/nsfw/porngifs.js deleted file mode 100644 index 5e3830aa6..000000000 --- a/src/commands/nsfw/porngifs.js +++ /dev/null @@ -1,12 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class PornGifs extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'porngifs', - subreddit: 'porngifs', - category: 'nsfw', - requirements: { nsfwOnly: true } - }, client) - } -} diff --git a/src/commands/reddit/aww.js b/src/commands/reddit/aww.js deleted file mode 100644 index 5cd3a9805..000000000 --- a/src/commands/reddit/aww.js +++ /dev/null @@ -1,13 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Aww extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'aww', - aliases: ['aw', 'cute', 'eyebleach'], - category: 'memes', - subreddit: 'aww', - titleString: 'commands:aww.title' - }, client) - } -} diff --git a/src/commands/reddit/birb.js b/src/commands/reddit/birb.js deleted file mode 100644 index 7f64ae39c..000000000 --- a/src/commands/reddit/birb.js +++ /dev/null @@ -1,13 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Birb extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'birb', - aliases: ['bird', 'borb'], - category: 'memes', - subreddit: 'birbs', - titleString: 'commands:birb.hereIsYourBirb' - }, client) - } -} diff --git a/src/commands/reddit/cat.js b/src/commands/reddit/cat.js deleted file mode 100644 index fae41e9ec..000000000 --- a/src/commands/reddit/cat.js +++ /dev/null @@ -1,13 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Cat extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'cat', - aliases: ['catto', 'kitty'], - category: 'general', - titleString: 'commands:cat.hereIsYourCat', - subreddit: 'catpictures' - }, client) - } -} diff --git a/src/commands/reddit/copypasta.js b/src/commands/reddit/copypasta.js deleted file mode 100644 index 82884e076..000000000 --- a/src/commands/reddit/copypasta.js +++ /dev/null @@ -1,11 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Copypasta extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'copypasta', - category: 'memes', - subreddit: 'copypasta' - }, client) - } -} diff --git a/src/commands/reddit/crappydesign.js b/src/commands/reddit/crappydesign.js deleted file mode 100644 index ff68e5342..000000000 --- a/src/commands/reddit/crappydesign.js +++ /dev/null @@ -1,12 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class CrappyDesign extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'crappydesign', - aliases: ['cd'], - category: 'memes', - subreddit: 'CrappyDesign' - }, client) - } -} diff --git a/src/commands/reddit/fursuit.js b/src/commands/reddit/fursuit.js deleted file mode 100644 index 7b244094f..000000000 --- a/src/commands/reddit/fursuit.js +++ /dev/null @@ -1,11 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Fursuit extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'fursuit', - aliases: ['expensiveaf', 'furrysuit'], - subreddit: 'fursuit' - }, client) - } -} diff --git a/src/commands/reddit/hmmm.js b/src/commands/reddit/hmmm.js deleted file mode 100644 index 2434a5fca..000000000 --- a/src/commands/reddit/hmmm.js +++ /dev/null @@ -1,14 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Hmmm extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'hmmm', - aliases: ['hm', 'hmm', 'hmmmm'], - category: 'memes', - subreddit: 'hmmm', - titleString: 'hmmm', - requirements: { nsfwOnly: true } - }, client) - } -} diff --git a/src/commands/reddit/keanu.js b/src/commands/reddit/keanu.js deleted file mode 100644 index a26b033e9..000000000 --- a/src/commands/reddit/keanu.js +++ /dev/null @@ -1,10 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Keanu extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'keanu', - subreddit: 'KeanuBeingAwesome' - }, client) - } -} diff --git a/src/commands/reddit/oddlysatisfying.js b/src/commands/reddit/oddlysatisfying.js deleted file mode 100644 index 008bdc424..000000000 --- a/src/commands/reddit/oddlysatisfying.js +++ /dev/null @@ -1,12 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class OddlySatisfying extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'oddlysatisfying', - aliases: ['odds'], - category: 'memes', - subreddit: 'oddlysatisfying' - }, client) - } -} diff --git a/src/commands/reddit/parrot.js b/src/commands/reddit/parrot.js deleted file mode 100644 index 934773cc6..000000000 --- a/src/commands/reddit/parrot.js +++ /dev/null @@ -1,10 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Parrot extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'parrot', - subreddit: 'partyparrot' - }, client) - } -} diff --git a/src/commands/reddit/showerthoughts.js b/src/commands/reddit/showerthoughts.js deleted file mode 100644 index ec8ab07e1..000000000 --- a/src/commands/reddit/showerthoughts.js +++ /dev/null @@ -1,10 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Showerthoughts extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'showerthoughts', - subreddit: 'showerthoughts' - }, client) - } -} diff --git a/src/commands/reddit/softwaregore.js b/src/commands/reddit/softwaregore.js deleted file mode 100644 index 828c000b9..000000000 --- a/src/commands/reddit/softwaregore.js +++ /dev/null @@ -1,12 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class SoftwareGore extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'softwaregore', - aliases: ['sg'], - category: 'memes', - subreddit: 'softwaregore' - }, client) - } -} diff --git a/src/commands/reddit/tesla.js b/src/commands/reddit/tesla.js deleted file mode 100644 index d726f28fc..000000000 --- a/src/commands/reddit/tesla.js +++ /dev/null @@ -1,11 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Tesla extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'tesla', - aliases: ['weebmusk', 'teslaporn'], - subreddit: 'TeslaPorn' - }, client) - } -} diff --git a/src/commands/reddit/thinking.js b/src/commands/reddit/thinking.js deleted file mode 100644 index 0f7f33fcf..000000000 --- a/src/commands/reddit/thinking.js +++ /dev/null @@ -1,13 +0,0 @@ -const { RandomRedditPostCommand } = require('../../') - -module.exports = class Thinking extends RandomRedditPostCommand { - constructor (client) { - super({ - name: 'thinking', - aliases: ['thonk', 'thonking', 'thonkang'], - category: 'memes', - subreddit: 'thinking', - addTitle: false - }, client) - } -} diff --git a/src/commands/social/leaderboard/leaderboard.js b/src/commands/social/leaderboard/leaderboard.js deleted file mode 100644 index dccd59b20..000000000 --- a/src/commands/social/leaderboard/leaderboard.js +++ /dev/null @@ -1,13 +0,0 @@ -const { SubcommandListCommand } = require('../../../') - -module.exports = class Leaderboard extends SubcommandListCommand { - constructor (client) { - super({ - name: 'leaderboard', - aliases: ['top', 'ranking'], - category: 'social', - authorString: 'commands:leaderboard.title', - requirements: { databaseOnly: true, canvasOnly: true } - }, client) - } -} diff --git a/src/commands/social/leaderboard/money.js b/src/commands/social/leaderboard/money.js deleted file mode 100644 index a867c6170..000000000 --- a/src/commands/social/leaderboard/money.js +++ /dev/null @@ -1,27 +0,0 @@ -const { CanvasTemplates, Command, Constants } = require('../../../') -const { MessageAttachment } = require('discord.js') - -module.exports = class MoneyLeaderboard extends Command { - constructor (client) { - super({ - name: 'money', - aliases: ['balance', 'switchcoins'], - parent: 'leaderboard' - }, client) - } - - async run ({ t, author, channel }) { - channel.startTyping() - - const top = await this.client.controllers.social.leaderboard('money') - const leaderboard = await CanvasTemplates.leaderboard({ t }, top, { - icon: Constants.COINS_SVG, - iconWidth: 48, - iconHeight: 48, - title: t(`commands:${this.tPath}.title`).toUpperCase(), - valueFunction: (u) => t('commons:currencyWithCount_plural', { count: Math.round(u.money) }) - }) - - channel.send(new MessageAttachment(leaderboard, 'leaderboard.jpg')).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/social/leaderboard/reputation.js b/src/commands/social/leaderboard/reputation.js deleted file mode 100644 index 34b7e6463..000000000 --- a/src/commands/social/leaderboard/reputation.js +++ /dev/null @@ -1,27 +0,0 @@ -const { CanvasTemplates, Command, Constants } = require('../../../') -const { MessageAttachment } = require('discord.js') - -module.exports = class ReputationLeaderboard extends Command { - constructor (client) { - super({ - name: 'reputation', - aliases: ['rep'], - parent: 'leaderboard' - }, client) - } - - async run ({ t, author, channel }) { - channel.startTyping() - - const top = await this.client.controllers.social.leaderboard('rep') - const leaderboard = await CanvasTemplates.leaderboard({ t }, top, { - icon: Constants.REPUTATION_SVG, - iconWidth: 48, - iconHeight: 48, - title: t(`commands:${this.tPath}.title`).toUpperCase(), - valueFunction: (u) => t('commons:reputationWithCount', { count: Math.round(u.rep) }) - }) - - channel.send(new MessageAttachment(leaderboard, 'leaderboard.jpg')).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/text/leet.js b/src/commands/text/leet.js deleted file mode 100644 index e1fc7ea3f..000000000 --- a/src/commands/text/leet.js +++ /dev/null @@ -1,70 +0,0 @@ -const { Command } = require('../../') -const { cleanContent } = require('discord.js').Util - -const leetMap = { - a: { soft: '4', hard: '4' }, - b: { soft: 'B', hard: 'I3' }, - c: { soft: 'C', hard: '[' }, - d: { soft: 'D', hard: '|)' }, - e: { soft: '3', hard: '3' }, - f: { soft: 'F', hard: '|=' }, - g: { soft: 'G', hard: '6' }, - h: { soft: 'H', hard: '#' }, - i: { soft: '1', hard: '1' }, - j: { soft: 'J', hard: ']' }, - k: { soft: 'K', hard: '|<' }, - l: { soft: 'L', hard: '1' }, - m: { soft: 'M', hard: '/\\/\\' }, - n: { soft: 'N', hard: '|\\|' }, - o: { soft: '0', hard: '0' }, - p: { soft: 'P', hard: '|>' }, - q: { soft: 'Q', hard: '0_' }, - r: { soft: 'R', hard: 'I2' }, - s: { soft: 'S', hard: '5' }, - t: { soft: 'T', hard: '7' }, - u: { soft: 'U', hard: '(_)' }, - v: { soft: 'V', hard: '\\/' }, - w: { soft: 'W', hard: '\\/\\/' }, - x: { soft: 'X', hard: '><' }, - y: { soft: 'Y', hard: '`/' }, - z: { soft: 'Z', hard: '2' } -} - -module.exports = class Leet extends Command { - constructor (client) { - super({ - name: 'leet', - category: 'memes', - parameters: [ - { - type: 'string', - full: true, - clean: true, - missingError: 'commands:leet.missingSentence' - }, - [{ - type: 'booleanFlag', - name: 'hard', - aliases: ['hc', '#4I2|D', 'hardcore'] - }] - ] - }, client) - } - - async run ({ channel, flags, message }, text) { - const leetTranslation = cleanContent( - text - .split('') - .map(char => { - const normalizedChar = char.toLowerCase() - const mappedChar = leetMap[normalizedChar] - return mappedChar // if char has leet translation - ? mappedChar[flags.hard ? 'hard' : 'soft'] - : char - }) - .join(''), - message - ) - channel.send(leetTranslation) - } -} diff --git a/src/commands/text/vaporwave.js b/src/commands/text/vaporwave.js deleted file mode 100644 index 87d81462f..000000000 --- a/src/commands/text/vaporwave.js +++ /dev/null @@ -1,23 +0,0 @@ -const { Command } = require('../../') - -module.exports = class Vaporwave extends Command { - constructor (client) { - super({ - name: 'vaporwave', - category: 'memes', - parameters: [{ - type: 'string', - full: true, - missingError: 'commands:vaporwave.missingSentence' - }] - }, client) - } - - async run ({ t, author, channel }, text) { - const vaporwavefied = text.split('').map(char => { - const code = char.charCodeAt(0) - return code >= 33 && code <= 126 ? String.fromCharCode((code - 33) + 65281) : char - }).join('') - channel.send(vaporwavefied) - } -} diff --git a/src/commands/utility/brainfuck.js b/src/commands/utility/brainfuck.js deleted file mode 100644 index 96c54db49..000000000 --- a/src/commands/utility/brainfuck.js +++ /dev/null @@ -1,45 +0,0 @@ -const { Command } = require('../../') -const Brainfuck = require('brainfuck-node') -const brainfuck = new Brainfuck() - -module.exports = class BrainfuckCommand extends Command { - constructor (client) { - super({ - name: 'brainfuck', - category: 'utility', - aliases: ['brainf', 'brf'], - parameters: [ - { - type: 'string', - required: true, - missingError: 'commands:brainfuck.noCode' - }, - { - type: 'string', - full: true, - required: false - } - ] - }, client) - } - - constructOutputMsg (input, t) { - const output = `\`\`\`${input.output}\`\`\`` - return `**${t('commands:brainfuck.steps')}:** ${input.steps}\n**${t('commands:brainfuck.time')}:** ${input.time}ms\n**${t('commands:brainfuck.output')}:** ${output}` - } - - run ({ t, channel }, code, input) { - try { - const result = brainfuck.execute(code, input) - const outputMsg = this.constructOutputMsg(result, t) - channel.send(outputMsg) - } catch (err) { - if (err.name === 'BrainfuckError') { - const outputMsg = this.constructOutputMsg(err.result, t) - channel.send(`**${t('commands:brainfuck.error')}:** ${err.message}\n${outputMsg}`) - } else { - throw err - } - } - } -} diff --git a/src/commands/utility/cep.js b/src/commands/utility/cep.js deleted file mode 100644 index c3ddb0d4e..000000000 --- a/src/commands/utility/cep.js +++ /dev/null @@ -1,35 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed } = require('../../') - -module.exports = class CEP extends Command { - constructor (client) { - super({ - name: 'cep', - alias: ['searchCEP'], - category: 'utility', - requirements: { - apis: ['viacep'] - }, - parameters: [{ - type: 'string', - full: true, - missingError: 'commands:cep.nocep' - }] - }, client) - } - - async run ({ t, author, channel }, cep) { - channel.startTyping() - try { - const rcep = await this.client.apis.viacep.searchCEP(cep) - channel.send( - new SwitchbladeEmbed() - .setDescription(`**${t('commands:cep.cep')}**: ${rcep.cep}\n**${t('commands:cep.fullAddress')}**: ${rcep.logradouro} ${rcep.complemento}\n**${t('commands:cep.neighborhood')}**: ${rcep.bairro}\n**${t('commands:cep.city')}**: ${rcep.localidade} - ${rcep.uf}\n**${t('commands:cep.ibge')}**: ${rcep.ibge}`) - .setThumbnail(`https://cdn.jsdelivr.net/gh/bgeneto/bandeiras-br/imagens/${rcep.uf}.png`) - ) - channel.stopTyping(true) - } catch (e) { - channel.stopTyping(true) - throw new CommandError(`${t('commands:cep.notFound')}`) - } - } -} diff --git a/src/commands/utility/channelinfo.js b/src/commands/utility/channelinfo.js new file mode 100644 index 000000000..3d6a942e6 --- /dev/null +++ b/src/commands/utility/channelinfo.js @@ -0,0 +1,35 @@ +const { Command, SwitchbladeEmbed } = require('../../') +const moment = require('moment') + +module.exports = class ChannelInfo extends Command { + constructor (client) { + super({ + name: 'channelinfo', + requirements: { guildOnly: true }, + parameters: [{ + type: 'channel', + required: false, + acceptText: true, + acceptNews: true, + acceptStore: true, + onlySameGuild: true, + missingError: 'commands:info.subcommands.category.missingCategoryMention' + }] + }, client) + } + + async run ({ t, author, channel, language }, givenChannel) { + moment.locale(language) + givenChannel = givenChannel ?? channel + const embed = new SwitchbladeEmbed(author) + .setTitle(`${givenChannel.nsfw ? `${t('commands:info.subcommands.channel.nsfwTag')} ` : ''}${givenChannel.name}`) + .setDescription( + `${givenChannel.parent ? `**${t('commands:info.subcommands.channel.category')}**: ${givenChannel.parent.name}` : ''} + **${t('commands:guildinfo.createdAt')}**: ${moment(givenChannel.createdAt).format('LLL')}\n(${moment(givenChannel.createdAt).fromNow()}) + **ID**: \`${givenChannel.id}\` <#${givenChannel.id}> + **${t(`commands:info.subcommands.channel.canViewThisChannel${givenChannel.members.size > 1 ? 'Plural' : ''}`, { userCount: givenChannel.members.size })}** + ${givenChannel.topic?.length > 1 ? `\n${givenChannel.topic}` : ''}`) + + channel.send(embed) + } +} diff --git a/src/commands/utility/country.js b/src/commands/utility/country.js deleted file mode 100644 index 9233f8107..000000000 --- a/src/commands/utility/country.js +++ /dev/null @@ -1,53 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed, MiscUtils } = require('../../') -const fetch = require('node-fetch') - -module.exports = class Country extends Command { - constructor (client) { - super({ - name: 'country', - category: 'utility', - parameters: [{ - type: 'string', - missingError: 'commands:country.noCountry', - full: true - }] - }, client) - } - - async run ({ t, author, channel, language }, country) { - channel.startTyping() - const embed = new SwitchbladeEmbed(author) - const endpoint = country.split('').length <= 3 ? 'alpha' : 'name' - try { - const data = await fetch(`https://restcountries.eu/rest/v2/${endpoint}/${encodeURIComponent(country)}`) - .then(res => res.json()) - .then(body => body[0] || body) - .catch(err => err) - - embed - .setTitle(`:flag_${data.alpha2Code.toLowerCase()}: ${data.name}`) - .setDescriptionFromBlockArray([ - [ - t('commands:country.aka', { alts: data.altSpellings.join(', ') }) - ], - [ - t('commands:country.languages', { languages: data.languages.map(l => `**${l.name}** (${l.nativeName})`).join(', ') }), - t('commands:country.capital', { capital: data.capital }), - t('commands:country.region', { region: data.region, subregion: data.subregion }), - t('commands:country.population', { population: MiscUtils.formatNumber(data.population, language) }), - t('commands:country.area', { area: MiscUtils.formatNumber(data.area, language) }), - t('commands:country.timezones', { timezones: data.timezones.join(', ') }) - ], - [ - t('commands:country.currencies', { currencies: data.currencies.map(c => `**${c.name}** (${c.symbol})`).join(', ') }), - data.regionalBlocs.length > 0 ? t('commands:country.treaties', { treaties: data.regionalBlocs.map(b => `**${b.acronym}** - ${b.name}`).join(', ') }) : null - ] - ]) - - channel.send(embed).then(() => channel.stopTyping()) - } catch (e) { - channel.stopTyping() - throw new CommandError(`${t('errors:generic')}`) - } - } -} diff --git a/src/commands/utility/deleteemoji.js b/src/commands/utility/deleteemoji.js deleted file mode 100644 index c41ee83e4..000000000 --- a/src/commands/utility/deleteemoji.js +++ /dev/null @@ -1,34 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed } = require('../../') - -module.exports = class DeleteEmoji extends Command { - constructor (client) { - super({ - name: 'deleteemoji', - aliases: ['delemoji'], - category: 'utility', - requirements: { guildOnly: true, permissions: ['MANAGE_EMOJIS'], botPermissions: ['MANAGE_EMOJIS'] }, - parameters: [{ - type: 'emoji', - sameGuildOnly: true, - missingError: 'commands:deleteemoji.noEmoji' - }] - }, client) - } - - async run ({ t, channel, author, guild }, emoji) { - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - - try { - await emoji.delete() - - embed.setDescription(t('commands:deleteemoji.deleted', { emoji })) - .setThumbnail(emoji.url) - - channel.send(embed).then(() => channel.stopTyping()) - } catch (e) { - channel.stopTyping() - throw new CommandError(`${t('commands:deleteemoji.error')}\n${e.toString()}`) - } - } -} diff --git a/src/commands/utility/hastebin.js b/src/commands/utility/hastebin.js deleted file mode 100644 index 19f4f11ba..000000000 --- a/src/commands/utility/hastebin.js +++ /dev/null @@ -1,36 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -const fetch = require('node-fetch') - -const EscapeMarkdown = (text) => text.replace(/(\*|~+|`)/g, '') - -const baseURL = 'https://hastebin.com' - -module.exports = class Hastebin extends Command { - constructor (client) { - super({ - name: 'hastebin', - aliases: ['haste'], - category: 'utility', - parameters: [{ - type: 'string', - full: true, - missingError: 'commands:hastebin.missingCode' - }] - }, client) - } - - async run ({ t, author, channel, message }, code) { - const embed = new SwitchbladeEmbed() - const { key } = await fetch(`${baseURL}/documents`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: EscapeMarkdown(code) - }).then(res => res.json()) - - embed - .setAuthor(t('commands:hastebin.hereIsYourURL')) - .setDescription(`${baseURL}/${key}`) - channel.send(embed) - } -} diff --git a/src/commands/utility/holidays.js b/src/commands/utility/holidays.js deleted file mode 100644 index 60f29ba53..000000000 --- a/src/commands/utility/holidays.js +++ /dev/null @@ -1,72 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed } = require('../../') -const moment = require('moment') -const fetch = require('node-fetch') - -const supportedCountries = [ - 'AD', 'AL', 'AR', 'AT', 'AU', 'AX', 'BB', 'BE', 'BG', 'BJ', 'BO', 'BR', - 'BS', 'BW', 'BY', 'BZ', 'CA', 'CH', 'CL', 'CN', 'CO', 'CR', 'CU', 'CY', - 'CZ', 'DE', 'DK', 'DO', 'EC', 'EE', 'EG', 'ES', 'FI', 'FO', 'FR', 'GA', - 'GB', 'GD', 'GL', 'GM', 'GR', 'GT', 'GY', 'HN', 'HR', 'HT', 'HU', 'ID', - 'IE', 'IM', 'IS', 'IT', 'JE', 'JM', 'JP', 'LI', 'LS', 'LT', 'LU', 'LV', - 'MA', 'MC', 'MD', 'MG', 'MK', 'MN', 'MT', 'MX', 'MZ', 'NA', 'NE', 'NI', - 'NL', 'NO', 'NZ', 'PA', 'PE', 'PL', 'PR', 'PT', 'PY', 'RO', 'RS', 'RU', - 'SE', 'SI', 'SJ', 'SK', 'SM', 'SR', 'SV', 'TN', 'TR', 'UA', 'US', 'UY', - 'VA', 'VE', 'VN', 'ZA', 'ZW' -] - -module.exports = class Holidays extends Command { - constructor (client) { - super({ - name: 'holidays', - category: 'utility', - parameters: [{ - type: 'string', - whitelist: supportedCountries, - toUpperCase: true, - missingError: ({ t }) => { - return new SwitchbladeEmbed() - .setTitle(t('commands:holidays.invalidCountry')) - .setDescription(supportedCountries - .map(countryCode => { - return `\`${countryCode}\`` - } - ).join(', ') - ) - } - }, { - type: 'number', - required: false, - min: 0 - }] - }, client) - } - - async run ({ t, author, channel }, countryCode = '', year = moment().year()) { - try { - channel.startTyping() - const embed = new SwitchbladeEmbed(author) - const countryName = t(`countries:${countryCode.toUpperCase()}`) - const url = `https://date.nager.at/api/v2/publicholidays/${year}/${countryCode}` - const holidays = await fetch(url) - .then(res => res.json()) - .catch(e => { - throw new CommandError(t('commands:holidays.noInformation'), true) - }) - - if (holidays) { - channel.send(embed - .setTitle(t('commands:holidays.title', { countryName, year })) - .setDescription(holidays - .map(({ date, localName }) => - `**${moment(date).format('Do MMMM')}** ${localName}` - ).join('\n') - ) - ) - } - } catch (e) { - throw new CommandError(t('commons:error'), true) - } finally { - channel.stopTyping() - } - } -} diff --git a/src/commands/utility/isitup.js b/src/commands/utility/isitup.js deleted file mode 100644 index 5f807622d..000000000 --- a/src/commands/utility/isitup.js +++ /dev/null @@ -1,34 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed } = require('../../') -const fetch = require('node-fetch') - -const PROTOCOL_REGEX = /^[a-zA-Z]+:\/\// -const PATH_REGEX = /(\/(.+)?)/g - -module.exports = class IsItUp extends Command { - constructor (client) { - super({ - name: 'isitup', - category: 'utility', - parameters: [{ - type: 'string', - full: true, - missingError: 'commands:isitup.noWebsite' - }] - }, client) - } - - async run ({ t, author, channel }, url) { - url = url.replace(PROTOCOL_REGEX, '').replace(PATH_REGEX, '') - const embed = new SwitchbladeEmbed(author) - channel.startTyping() - const body = await fetch(`https://isitup.org/${url}.json`).then(res => res.json()) - if (body.response_code) { - body.response_time *= 1000 - embed.setTitle(t('commands:isitup.isUp')) - .setDescription(t('commands:isitup.details', { body })) - } else { - throw new CommandError(t('commands:isitup.isDown')) - } - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/utility/mostplayed.js b/src/commands/utility/mostplayed.js deleted file mode 100644 index 930509513..000000000 --- a/src/commands/utility/mostplayed.js +++ /dev/null @@ -1,39 +0,0 @@ -const { Command, SwitchbladeEmbed, MiscUtils } = require('../../') - -module.exports = class MostPlayed extends Command { - constructor (client) { - super({ - name: 'mostplayed', - aliases: ['topgames'], - category: 'utility', - requirements: { guildOnly: true } - }, client) - } - - run ({ message, t, channel, language }) { - channel.startTyping() - const games = {} - - message.guild.members.cache.filter(member => !member.user.bot && member.presence.activities.length).each(member => { - member.presence.activities.filter(activity => activity.type === 'PLAYING').forEach(activity => { - games[activity.name] = games[activity.name] + 1 || 1 - }) - }) - - const gamesList = Object.keys(games) - const mostPlayed = gamesList.sort((a, b) => games[b] - games[a]).slice(0, 20) - const totalPlayers = gamesList.length - ? Object.values(games).reduce((acc, val) => acc + val) - : 0 - - channel.send( - new SwitchbladeEmbed() - .setThumbnail(message.guild.iconURL({ dynamic: true })) - .setTitle(t('commands:mostplayed.mostPlayedTitle', { name: message.guild.name })) - .setDescription(mostPlayed.length - ? mostPlayed.map((game, i) => t('commands:mostplayed.hasPlayers', { rank: i + 1, game, count: MiscUtils.formatNumber(games[game], language) })) - : t('commands:mostplayed.noPlayers')) - .setFooter(t('commands:mostplayed.totalPlayers', { count: MiscUtils.formatNumber(totalPlayers, language) })) - ).then(() => channel.stopTyping(true)) - } -} diff --git a/src/commands/utility/packagist.js b/src/commands/utility/packagist.js deleted file mode 100644 index a124b0d42..000000000 --- a/src/commands/utility/packagist.js +++ /dev/null @@ -1,48 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants } = require('../../') -const moment = require('moment') - -module.exports = class Packagist extends SearchCommand { - constructor (client) { - super({ - name: 'packagist', - category: 'utility', - parameters: [{ - type: 'string', - full: true, - fullJoin: '-', - missingError: 'commands:packagist.noNameProvided' - }], - requirements: { apis: ['packagist'] }, - embedColor: Constants.PACKAGIST_COLOR, - embedLogoURL: 'https://i.imgur.com/MLTCgKN.png' - }, client) - } - - async search (_, query) { - const { data } = await this.client.apis.packagist.search(query) - return Object.values(data.results) - } - - searchResultFormatter (item) { - return `[${item.name}](${item.repository})` - } - - async handleResult ({ channel, author, language }, item) { - const embed = new SwitchbladeEmbed(author) - moment.locale(language) - channel.startTyping() - embed - .setColor(Constants.PACKAGIST_COLOR) - .setAuthor('Packagist', this.embedLogoURL, 'https://packagist.org/') - .setDescriptionFromBlockArray([ - [ - `[${item.name}](${item.url})`, - item.description ? item.description : null - ], - [ - `\`\`\`composer require ${item.name}\`\`\`` - ] - ]) - channel.send(embed).then(() => channel.stopTyping()) - } -} diff --git a/src/commands/utility/render.js b/src/commands/utility/render.js deleted file mode 100644 index 2de6487c0..000000000 --- a/src/commands/utility/render.js +++ /dev/null @@ -1,58 +0,0 @@ -const { Command, CommandError, SwitchbladeEmbed } = require('../../') -module.exports = class Render extends Command { - constructor (client) { - super({ - name: 'render', - aliases: ['show'], - category: 'utility', - requirements: { guildOnly: true, botPermissions: ['EMBED_LINKS'] }, - parameters: [{ - type: 'messageLink', - sameGuildOnly: true, - forceExists: true, - linkChannelUserPermission: ['VIEW_CHANNEL'], - linkChannelBotPermission: ['VIEW_CHANNEL'], - missingError: 'commands:move.missingMessageLink' - }] - }, client) - } - - async run ({ author, t, message }, link) { - const render = {} - const { content } = link - let messageHasNoEmbed = true - - if (link.attachments.size >= 1) { - render.files = link.attachments.array() - } - - if (link.embeds.length >= 1) { - messageHasNoEmbed = false - render.embed = link.embeds[0].toJSON() - } - - if (Object.keys(render).length === 0 && !content) { - throw new CommandError(t('errors:messageContainsNothing')) - } - - try { - if (messageHasNoEmbed) { - const embed = new SwitchbladeEmbed(author) - .setAuthor(link.author.username, link.author.displayAvatarURL({ dynamic: true })) - if (link.guild.member(author.id)) { - embed.setColor(link.guild.member(author.id).displayHexColor) - } - - if (content) { - embed.setDescription(content) - } - - render.embed = embed - } - - message.channel.send(render) - } catch (e) { - throw new CommandError(t('commands:move.couldntSendMessage')) - } - } -} diff --git a/src/commands/utility/rubygems.js b/src/commands/utility/rubygems.js deleted file mode 100644 index 663307d22..000000000 --- a/src/commands/utility/rubygems.js +++ /dev/null @@ -1,66 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, MiscUtils } = require('../../') - -const RUBYGEMS_COLOR = '#fb5e2b' -const RUBYGEMS_ICON = 'https://avatars1.githubusercontent.com/u/208761' - -module.exports = class RubyGems extends SearchCommand { - constructor (client) { - super({ - name: 'rubygems', - aliases: ['gem', 'rubygem'], - category: 'utility', - parameters: [{ - type: 'string', - full: true, - missingError: 'commands:rubygems.noNameProvided' - }], - embedColor: RUBYGEMS_COLOR, - embedLogoURL: RUBYGEMS_ICON - }, client) - } - - async search (context, query) { - return this.client.apis.rubygems.search(query) - } - - searchResultFormatter (gem) { - return `[${gem.name}](${gem.project_uri}) \`${gem.version}\`` - } - - async handleResult ({ t, channel, author, language }, partialGem) { - channel.startTyping() - const gem = await this.client.apis.rubygems.getGem(partialGem.name) - channel.send( - new SwitchbladeEmbed(author) - .setAuthor('RubyGems.org', RUBYGEMS_ICON) - .setColor(RUBYGEMS_COLOR) - .setDescriptionFromBlockArray([ - [ - `[**${gem.name}**](${gem.project_uri}) _${gem.version}_`, - gem.info - ], - [ - `_${t('commands:rubygems.downloadCount', { count: MiscUtils.formatNumber(gem.downloads, language) })}_` - ], - [ - [ - 'gem', - 'homepage', - 'wiki', - 'documentation', - 'mailing_list', - 'source_code', - 'bug_tracker', - 'changelog' - ].filter(u => !!gem[`${u}_uri`]).map(u => `[${t(`commands:rubygems.uris.${u}`)}](${gem[`${u}_uri`]})`).join(' • ') - ], - [ - '**Gemfile**', - `\`\`\`gem '${gem.name}', '~> ${gem.version}'\`\`\``, - `**${t('commands:rubygems.install')}**`, - `\`\`\`gem install ${gem.name}\`\`\`` - ] - ]) - ).then(() => { channel.stopTyping() }) - } -} diff --git a/src/commands/utility/snapcraft.js b/src/commands/utility/snapcraft.js deleted file mode 100644 index b7fe2e9ac..000000000 --- a/src/commands/utility/snapcraft.js +++ /dev/null @@ -1,48 +0,0 @@ -const { SearchCommand, SwitchbladeEmbed, Constants } = require('../../') - -module.exports = class SnapCraft extends SearchCommand { - constructor (client) { - super({ - name: 'snapcraft', - category: 'utility', - aliases: ['snap', 'snapd', 'snappy'], - parameters: [{ - type: 'string', - full: true, - missingError: 'commands:snapcraft.noQueryProvided' - }], - embedLogoURL: 'https://dashboard.snapcraft.io/site_media/appmedia/2018/04/Snapcraft-logo-bird.png', - embedColor: Constants.SNAPCRAFT_COLOR - }, client) - } - - async search (context, query) { - return this.client.apis.snapcraft.searchApp(query) - } - - searchResultFormatter (app) { - return `[${app.title}](${app.storeURL}) - \`${app.version}\`` - } - - handleResult ({ channel, author, t }, { storeURL, title, description, icon, version, branch, publisher }) { - const embed = new SwitchbladeEmbed(author) - .setAuthor('Snapcraft', this.embedLogoURL, 'https://snapcraft.io/') - .setColor(this.embedColor) - .setURL(storeURL) - .setTitle(title) - .setDescription(description) - .setThumbnail(icon) - .addFields([ - { - name: t('commands:snapcraft.version'), - value: `${branch} - \`${version}\`` - }, - { - name: t('commands:snapcraft.publisher'), - value: `${publisher.displayName} - \`${publisher.username}\` - ${t('commands:snapcraft.verified')} - \`${publisher.verified ? t('commands:snapcraft.yes') : t('commands:snapcraft.no')}\`` - } - ]) - channel.send(embed) - } -} diff --git a/src/commands/utility/stoptyping.js b/src/commands/utility/stoptyping.js deleted file mode 100644 index 99ed8e5a5..000000000 --- a/src/commands/utility/stoptyping.js +++ /dev/null @@ -1,18 +0,0 @@ -const { Command, SwitchbladeEmbed } = require('../../') - -module.exports = class StopTyping extends Command { - constructor (client) { - super({ - name: 'stoptyping', - aliases: ['st'], - category: 'utility' - }, client) - } - - run ({ t, author, channel }) { - channel.stopTyping(true) - channel.send( - new SwitchbladeEmbed(author).setDescription(t('commands:stoptyping.tryingToStop')) - ) - } -} diff --git a/src/commands/utility/translate.js b/src/commands/utility/translate.js deleted file mode 100644 index 7bb7ebe87..000000000 --- a/src/commands/utility/translate.js +++ /dev/null @@ -1,46 +0,0 @@ -const { SwitchbladeEmbed, Command } = require('../../') - -module.exports = class TranslateCommand extends Command { - constructor (client) { - super({ - name: 'translate', - aliases: ['translator'], - parameters: [ - { - type: 'string' - }, - { - type: 'string' - }, - { - type: 'string', - full: true, - clean: true - } - ] - }, client) - } - - async run ({ t, author, channel, language }, from, to, text) { - channel.startTyping() - const embed = new SwitchbladeEmbed(author) - - const languages = require(`../../locales/${language}/languages.json`) - const languageCodes = Object.keys(languages) - - const wasFallback = !languageCodes.slice(1).includes(to) - - if (!languageCodes.includes(from)) from = 'auto' - if (wasFallback) to = 'en' - - const { translated, from: fromT, to: toT } = await this.client.apis.gtranslate.translateText(from, to, text) - - const auto = from === 'auto' ? ' ' + t('commands:translate.automatic') : '' - embed.setDescription(translated.length > 2000 ? translated.slice(0, 2000) + '...' : translated) - .addField(t('commands:translate.translatedFrom'), languages[fromT] + auto, true) - .addField(t('commands:translate.translatedTo'), languages[toT], true) - .setAuthor(t('commands:translate.title'), 'https://i.imgur.com/FQuOtF5.jpg') - channel.send(embed) - .then(() => channel.stopTyping()) - } -} diff --git a/src/listeners/MainListener.js b/src/listeners/MainListener.js index 46f339b09..c3f526998 100644 --- a/src/listeners/MainListener.js +++ b/src/listeners/MainListener.js @@ -9,7 +9,7 @@ const PRESENCE_INTERVAL = 60 * 1000 // 1 minute module.exports = class MainListener extends EventListener { constructor (client) { super({ - events: ['ready', 'message'] + events: ['ready', 'interactionCreate'] }, client) } @@ -116,43 +116,27 @@ module.exports = class MainListener extends EventListener { emojiLoader.load() } - async onMessage (message) { - if (message.author.bot || !this.loaded) return - - const guildId = message.guild && message.guild.id - - const { prefix, spacePrefix } = await this.modules.prefix.retrieveValues(guildId, ['prefix', 'spacePrefix']) - const language = await this.modules.language.retrieveValue(guildId, 'language') - - const botMention = this.user.toString() - - const sw = (...s) => s.some(st => message.content.startsWith(st)) - const usedPrefix = sw(botMention, `<@!${this.user.id}>`) ? `${botMention} ` : sw(prefix) ? prefix : null - - if (usedPrefix) { - const fullCmd = message.content.substring(usedPrefix.length).split(/[ \t]+/).filter(a => !spacePrefix || a) - const args = fullCmd.slice(1) - if (!fullCmd.length) return - - const cmd = fullCmd[0].toLowerCase().trim() - const command = this.commands.find(c => c.name.toLowerCase() === cmd || (c.aliases && c.aliases.includes(cmd))) - if (command) { - const userDocument = this.database && await this.database.users.findOne(message.author.id, 'blacklisted') - if (userDocument && userDocument.blacklisted) return - - const context = new CommandContext({ - defaultPrefix: usedPrefix, - aliase: cmd, - client: this, - prefix, - message, - command, - language - }) - - this.logger.info({ tag: 'Commands' }, `"${message.content}" (${command.constructor.name}) ran by "${message.author.tag}" (${message.author.id}) on guild "${message.guild.name}" (${message.guild.id}) channel "#${message.channel.name}" (${message.channel.id})`) - this.runCommand(command, context, args, language) - } + async onInteractionCreate (interaction) { + if (!interaction.isCommand() || !interaction.member) return + const cmd = interaction.commandName + const command = this.commands.find(c => c.name.toLowerCase() === cmd || (c.aliases && c.aliases.includes(cmd))) + if (command) { + const userDocument = this.database && await this.database.users.findOne(interaction.user.id, 'blacklisted') + if (userDocument && userDocument.blacklisted) return + let args = interaction.options._hoistedOptions.map(z => z.value) + if (interaction.options._subcommand) args = [interaction.options._subcommand, ...args] + args = args.map(z => z.toString?.() ?? z) + + const context = new CommandContext({ + client: this, + interaction, + command, + language: interaction.locale, + args + }) + + this.logger.info({ tag: 'Commands' }, `"(${command.constructor.name}) ran by "${interaction.user.tag}" (${interaction.user.id})`) + this.runCommand(command, context, args, interaction.locale) } } } diff --git a/src/locales/en-US/commands.json b/src/locales/en-US/commands.json index b2f1e50f2..48667ead6 100644 --- a/src/locales/en-US/commands.json +++ b/src/locales/en-US/commands.json @@ -1906,23 +1906,23 @@ "source": "Data provided by [disease-sh](https://github.com/disease-sh). Check the [sources](https://github.com/disease-sh/API/blob/master/README.md#sources)", "subcommands": { "countries": { - "commandDescription": "Shows data from multiple sources from a country about Covid-19 (deaths, cases, tests, one case per people).", + "commandDescription": "Shows data from multiple sources from a country about Covid-19.", "commandUsage": "", "noCountry": "You have to give me a country.", "notFound": "Country not found." }, "worldwide": { - "commandDescription": "Shows worldwide data from multiple sources about Covid-19 (deaths, cases, tests, cases per one million).", + "commandDescription": "Shows worldwide data from multiple sources about Covid-19.", "affectedCountries": "Affected countries" }, "continents": { - "commandDescription": "Shows a continent data from multiple sources about Covid-19 (deaths, cases, tests, countries, cases per one million).", + "commandDescription": "Shows a continent data from multiple sources about Covid-19.", "countries": "countries", "notFound": "Continent not found.", "noContinent": "You have to give me a continent." }, "states": { - "commandDescription": "Shows an US state data from multiple sources about Covid-19 (deaths, cases, tests, cases per one million).", + "commandDescription": "Shows an US state data from multiple sources about Covid-19.", "noState": "You have to give me a state.", "notFound": "US State not found." } diff --git a/src/modules/CommandsModule.js b/src/modules/CommandsModule.js index e9b2c4810..bf526775c 100644 --- a/src/modules/CommandsModule.js +++ b/src/modules/CommandsModule.js @@ -119,7 +119,8 @@ module.exports = class CommandsModule extends Module { } async verifyCommand (command, { guild, channel, member }) { - if (member.hasPermission('ADMINISTRATOR')) return true + console.log(member) + if (member.permissions.has('ADMINISTRATOR')) return true const allCommands = recPaths(command) const { commands, categories, all } = await this.retrieveValues(guild.id, [ diff --git a/src/structures/SwitchbladeEmbed.js b/src/structures/SwitchbladeEmbed.js index e1faba0c9..24601ce07 100644 --- a/src/structures/SwitchbladeEmbed.js +++ b/src/structures/SwitchbladeEmbed.js @@ -11,6 +11,7 @@ module.exports = class SwitchbladeEmbed extends MessageEmbed { super(data) this.setColor(process.env.EMBED_COLOR).setTimestamp() if (user) this.setFooter(user.tag) + this._files = [] } /** @@ -22,4 +23,15 @@ module.exports = class SwitchbladeEmbed extends MessageEmbed { this.description = blocks.map(lines => lines.filter(l => !!l).join('\n')).filter(b => !!b.length).join('\n\n') return this } + + setDescription (description) { + if (description instanceof Array) return super.setDescription(description.join('\n')) + else return super.setDescription(description.toString?.() ?? description) + } + + attachFiles (t) { + if (t instanceof Array) this._files = [...this._files, ...t] + else this._files.push(t) + return this + } } diff --git a/src/structures/command/Command.js b/src/structures/command/Command.js index 59ebeba0b..ce8971628 100644 --- a/src/structures/command/Command.js +++ b/src/structures/command/Command.js @@ -119,7 +119,7 @@ module.exports = class Command { const embed = error.embed || new SwitchbladeEmbed(author) .setTitle(error.message) .setDescription(error.showUsage ? usage : '') - return channel.send(embed.setColor(Constants.ERROR_COLOR)).then(() => channel.stopTyping()) + return channel.send(embed.setColor(Constants.ERROR_COLOR)) } console.error(error) } diff --git a/src/structures/command/CommandContext.js b/src/structures/command/CommandContext.js index 9f4241536..b16605462 100644 --- a/src/structures/command/CommandContext.js +++ b/src/structures/command/CommandContext.js @@ -1,3 +1,5 @@ +const { MessageEmbed, MessageAttachment } = require('discord.js') + module.exports = class CommandContext { /** * @param {Object} options The context options @@ -17,20 +19,54 @@ module.exports = class CommandContext { constructor (options = {}) { this.client = options.client - this.message = options.message - this.author = options.message.author - this.member = options.message.member - this.channel = options.message.channel + this.interaction = options.interaction + this.author = options.interaction.user + this.member = options.interaction.member + this.channel = options.interaction.channel this.voiceState = this.member ? this.member.voice : null - this.guild = options.message.guild + this.guild = options.interaction.guild this.language = options.language this.command = options.command - this.aliase = options.aliase - this.prefix = options.prefix - this.defaultPrefix = options.defaultPrefix + this.prefix = '/' this.t = () => { throw new Error('Invalid FixedT') } this.flags = {} + this.patchChannel() + this.__replied = false + this.__deferred = false + + setTimeout(async () => { + if (!this.__replied) { + await this.interaction.deferReply() + this.__deferred = true + } + }, 1500) + } + + reply (content, data = {}) { + let request + if (data.code) { + request = { content: `\`\`\`${data.code}\n${content}\n\`\`\`` } + } else if (typeof (content) === 'string') { + request = { content, ...data } + } else if (content instanceof MessageEmbed) { + request = { embeds: [content], files: content._files } + } else if (content instanceof MessageAttachment) { + request = { files: [content] } + } else { + request = data + } + + this.__replied = true + return (this.__deferred + ? this.interaction.editReply(request) + : this.interaction.reply(request)) + } + + patchChannel () { + this.channel.send = (content, data = {}) => this.reply(content, data) + this.channel.stopTyping = function () {} + this.channel.startTyping = function () {} } setFixedT (translate) { diff --git a/src/utils/DiscordUtils.js b/src/utils/DiscordUtils.js index 01ea94a78..9b782427f 100644 --- a/src/utils/DiscordUtils.js +++ b/src/utils/DiscordUtils.js @@ -1,3 +1,5 @@ +// const { Parser } = require('acorn') + module.exports = class DiscordUtils { /** * @param {String} userID - The id of the user who should have permission checked. @@ -17,4 +19,65 @@ module.exports = class DiscordUtils { return null } + + static convertCommandsToDiscordPayload (t, commands) { + return commands.map((cmd) => DiscordUtils.convertCommandToDiscordPayload(t, cmd)) + } + + static convertCommandToDiscordPayload (t, command) { + const data = { options: [] } + if (command.parameters?.[0]) { + data.options = DiscordUtils.convertParameterListToDiscordPayload(command) + } + + if (command.subcommands?.[0]) { + command.subcommands.forEach((sub) => { + const opts = sub.parameters?.[0] + ? { options: DiscordUtils.convertParameterListToDiscordPayload(sub) } + : {} + + data.options.push({ + type: 1, + name: sub.name, + description: t([`commands:${command.tPath}.subcommands.${sub.name}.commandDescription`, 'commands:help.noDescriptionProvided']) || 'No description provided.', + ...opts + }) + }) + } + + return { + name: command.name, + description: t([`commands:${command.tPath}.commandDescription`, 'commands:help.noDescriptionProvided']) || 'No description provided.', + ...data + } + } + + static convertParameterListToDiscordPayload (command, params = command.parameters) { + const typeList = { string: 3, integer: 4, boolean: 5, user: 6, member: 6, channel: 7, role: 8, mentionable: 9, number: 10 } + let argList = (command.search || command.run).toString().split('\n')[0].replace(/(async )?([a-z]+ )\((_|context|\{[\s\S]*?\})?(, )?/g, '').replace(') {', '').trim() + if (argList) argList = argList.split(',').map(z => z.split(' = ')[0].trim()) + + const options = [] + params.forEach((a, i) => { + if (a instanceof Array) { + // flag parsing + a.forEach((flag) => { + options.push({ + name: flag.name.toLowerCase(), + type: typeList[flag.type.replace('Flag')] ?? typeList.boolean, + required: false, + description: 'aaaa' + }) + }) + } else { + options.push({ + name: (argList?.[i] ?? `${command.name.split('')[0]}${i}`).toLowerCase(), + type: typeList[a.type] ?? typeList.string, + required: a.isRequired ?? (a.full || false), + description: 'PAJUBA' + }) + } + }) + return options.sort(x => x.required ? -1 : 1) + } }