summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc.json161
-rw-r--r--.gitignore7
-rw-r--r--README.md2
-rw-r--r--UNLICENSE24
-rw-r--r--config.def.toml22
-rw-r--r--index.js25
-rw-r--r--install_lavalink.sh7
-rw-r--r--package-lock.json1013
-rw-r--r--package.json23
-rw-r--r--src/CommandLoader.js12
-rw-r--r--src/Events.js57
-rw-r--r--src/Hastebin.js6
-rw-r--r--src/RegexFramework.js31
-rw-r--r--src/Time.js5
-rw-r--r--src/Troffman.js35
-rw-r--r--src/TroffmanDatabase.js25
-rw-r--r--src/Wait.js7
-rw-r--r--src/cmd/debug.js5
-rw-r--r--src/cmd/info.js19
-rw-r--r--src/cmd/sudo.js139
-rw-r--r--src/cmd/troff.js59
-rw-r--r--src/cmd/voice.js356
22 files changed, 2040 insertions, 0 deletions
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..cdc72aa
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,161 @@
+{
+ "extends": "eslint:recommended",
+ "parserOptions": {
+ "ecmaVersion": 2017
+ },
+ "env": {
+ "es6": true,
+ "node": true
+ },
+ "globals": {
+ "Exception": true,
+ "Logger": true
+ },
+ "overrides": [
+ { "files": ["*.browser.js"], "env": { "browser": true } }
+ ],
+ "rules": {
+ "no-console": "warn",
+ "no-await-in-loop": "warn",
+ "no-compare-neg-zero": "error",
+ "no-extra-parens": ["warn", "all", {
+ "nestedBinaryExpressions": false
+ }],
+ "no-template-curly-in-string": "error",
+ "no-unsafe-negation": "error",
+ "valid-jsdoc": ["error", {
+ "requireReturn": false,
+ "requireReturnDescription": false,
+ "prefer": {
+ "return": "returns",
+ "arg": "param"
+ },
+ "preferType": {
+ "String": "string",
+ "Number": "number",
+ "Boolean": "boolean",
+ "Symbol": "symbol",
+ "object": "Object",
+ "function": "Function",
+ "array": "Array",
+ "date": "Date",
+ "error": "Error",
+ "null": "void"
+ }
+ }],
+
+ "accessor-pairs": "warn",
+ "array-callback-return": "error",
+ "complexity": "warn",
+ "consistent-return": "error",
+ "curly": ["error", "multi-line", "consistent"],
+ "dot-location": ["error", "property"],
+ "dot-notation": "error",
+ "eqeqeq": "error",
+ "no-empty-function": "error",
+ "no-floating-decimal": "error",
+ "no-implied-eval": "error",
+ "no-invalid-this": "error",
+ "no-lone-blocks": "error",
+ "no-multi-spaces": "error",
+ "no-new-func": "error",
+ "no-new-wrappers": "error",
+ "no-new": "error",
+ "no-octal-escape": "error",
+ "no-return-assign": "error",
+ "no-return-await": "error",
+ "no-self-compare": "error",
+ "no-sequences": "error",
+ "no-throw-literal": "error",
+ "no-unmodified-loop-condition": "error",
+ "no-unused-expressions": "error",
+ "no-useless-call": "error",
+ "no-useless-concat": "error",
+ "no-useless-escape": "error",
+ "no-useless-return": "error",
+ "no-void": "error",
+ "no-warning-comments": "warn",
+ "prefer-promise-reject-errors": "error",
+ "require-await": "warn",
+ "wrap-iife": "error",
+ "yoda": "error",
+
+ "no-label-var": "error",
+ "no-shadow": "error",
+ "no-undef-init": "error",
+
+ "callback-return": "error",
+ "handle-callback-err": "error",
+ "no-mixed-requires": "error",
+ "no-new-require": "error",
+ "no-path-concat": "error",
+
+ "array-bracket-spacing": "error",
+ "block-spacing": "error",
+ "brace-style": ["error", "stroustrup", { "allowSingleLine": true }],
+ "comma-dangle": ["error", "always-multiline"],
+ "comma-spacing": "error",
+ "comma-style": "error",
+ "computed-property-spacing": "error",
+ "consistent-this": ["error", "$this"],
+ "eol-last": "error",
+ "func-names": "error",
+ "func-name-matching": "error",
+ "func-style": ["error", "declaration", { "allowArrowFunctions": true }],
+ "indent": ["error", 4, { "SwitchCase": 1 }],
+ "key-spacing": "error",
+ "keyword-spacing": "error",
+ "max-depth": "error",
+ "max-len": ["off", 120, 2],
+ "max-nested-callbacks": ["error", { "max": 4 }],
+ "max-statements-per-line": ["error", { "max": 2 }],
+ "new-cap": "off",
+ "newline-per-chained-call": ["error", { "ignoreChainWithDepth": 3 }],
+ "no-array-constructor": "error",
+ "no-inline-comments": "error",
+ "no-lonely-if": "error",
+ "no-mixed-operators": "error",
+ "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }],
+ "no-new-object": "error",
+ "no-spaced-func": "error",
+ "no-trailing-spaces": "error",
+ "no-unneeded-ternary": "error",
+ "no-whitespace-before-property": "error",
+ "nonblock-statement-body-position": "error",
+ "object-curly-spacing": ["error", "always"],
+ "operator-assignment": "error",
+ "operator-linebreak": ["error", "after"],
+ "padded-blocks": ["error", "never"],
+ "quote-props": ["error", "as-needed"],
+ "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }],
+ "semi-spacing": "error",
+ "semi": "error",
+ "space-before-blocks": "error",
+ "space-before-function-paren": ["error", {
+ "anonymous": "never",
+ "named": "never",
+ "asyncArrow": "always"
+ }],
+ "space-in-parens": "error",
+ "space-infix-ops": "error",
+ "space-unary-ops": "error",
+ "spaced-comment": "error",
+ "template-tag-spacing": "error",
+ "unicode-bom": "error",
+
+ "arrow-body-style": "error",
+ "arrow-parens": ["error", "as-needed"],
+ "arrow-spacing": "error",
+ "no-duplicate-imports": "error",
+ "no-useless-computed-key": "error",
+ "no-useless-constructor": "error",
+ "prefer-arrow-callback": "error",
+ "prefer-numeric-literals": "error",
+ "prefer-rest-params": "error",
+ "prefer-spread": "error",
+ "prefer-template": "error",
+ "rest-spread-spacing": "error",
+ "template-curly-spacing": "error",
+ "yield-star-spacing": "error"
+ }
+ } \ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..128b1cf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+/node_modules/
+/genki.log
+/config.toml
+/database.sqlite
+/Lavalink.jar
+/logs
+/*.core
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a5168ef
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# genki
+Private music bot \ No newline at end of file
diff --git a/UNLICENSE b/UNLICENSE
new file mode 100644
index 0000000..68a49da
--- /dev/null
+++ b/UNLICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
diff --git a/config.def.toml b/config.def.toml
new file mode 100644
index 0000000..0789501
--- /dev/null
+++ b/config.def.toml
@@ -0,0 +1,22 @@
+token = ""
+sudoers = [""]
+
+# NPM Logging levels :
+#
+# error: 0,
+# warn: 1,
+# info: 2,
+# verbose: 3,
+# debug: 4,
+# silly: 5
+
+database = "database.sqlite"
+
+[logging.console]
+enabled = true
+minimal = "verbose"
+
+[logging.file]
+enabled = false
+path = "genki.log"
+minimal = "info"
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..8247028
--- /dev/null
+++ b/index.js
@@ -0,0 +1,25 @@
+const Troffman = require('./src/Troffman');
+const winston = require('winston');
+
+global.Logger = winston.createLogger({
+ levels: winston.config.npm.levels,
+ format: winston.format.printf(info => {
+ let date = new Date();
+ return `[${date.getDate()}/${(date.getMonth() + 1)}/${date.getFullYear()}-${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}][${info.level.toUpperCase()}] ${info.message}`;
+ }),
+});
+
+const bot = new Troffman('./config.toml');
+
+if (bot.config.logging.console.enabled) {
+ Logger.add(new winston.transports.Console({ level: bot.config.logging.console.minimal }));
+}
+
+if (bot.config.logging.file.enabled && bot.config.logging.file.path) {
+ Logger.add(new winston.transports.File({ filename: bot.config.logging.file.path, level: bot.config.logging.file.minimal }));
+ Logger.verbose(`Now logging to file ${bot.config.logging.file.path} with minimal level ${bot.config.logging.file.minimal}`);
+}
+
+Logger.verbose('Connecting the bot');
+
+bot.connect();
diff --git a/install_lavalink.sh b/install_lavalink.sh
new file mode 100644
index 0000000..b9c4901
--- /dev/null
+++ b/install_lavalink.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+cd "$(dirname $0)"
+
+curl https://github.com/Frederikam/Lavalink/releases/download/3.3.1/Lavalink.jar > Lavalink.jar
+
+echo "WARNING: please install a Java 13 runtime and make sure Lavalink is launched with it." \ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..387e81a
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1013 @@
+{
+ "name": "troffman",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@types/node": {
+ "version": "13.13.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.5.tgz",
+ "integrity": "sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g=="
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+ "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
+ "async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+ },
+ "chunk-text": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/chunk-text/-/chunk-text-1.0.5.tgz",
+ "integrity": "sha512-rgSZNj6nZLkXgUWwcoMyXCm6sTn6B1QhaZyXK/lF2t8TF/lIgLtz5cHpNJBpDXx5x/gvnlqp8l9B7s9fXZG2/w==",
+ "requires": {
+ "runes": "^0.4.1"
+ }
+ },
+ "cls-bluebird": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz",
+ "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=",
+ "requires": {
+ "is-bluebird": "^1.0.2",
+ "shimmer": "^1.1.0"
+ }
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+ },
+ "color": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz",
+ "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==",
+ "requires": {
+ "color-convert": "^1.9.1",
+ "color-string": "^1.5.2"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+ },
+ "color-string": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
+ "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
+ "requires": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "colornames": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz",
+ "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y="
+ },
+ "colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
+ },
+ "colorspace": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz",
+ "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==",
+ "requires": {
+ "color": "3.0.x",
+ "text-hex": "1.0.x"
+ }
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+ },
+ "cookiejar": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
+ "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "dbot-regex-handler": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dbot-regex-handler/-/dbot-regex-handler-1.0.0.tgz",
+ "integrity": "sha512-e9WAoIQrFOHrvoEU5RVTX8vZrze0w/YR1stDuMF3pRkZ1xyHyhJxrLfFxoU6zmPD4ZIlpuXg0VX1SqGgkBNMlw=="
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+ "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
+ },
+ "diagnostics": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz",
+ "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==",
+ "requires": {
+ "colorspace": "1.1.x",
+ "enabled": "1.0.x",
+ "kuler": "1.0.x"
+ }
+ },
+ "dottie": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz",
+ "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg=="
+ },
+ "enabled": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz",
+ "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=",
+ "requires": {
+ "env-variable": "0.0.x"
+ }
+ },
+ "env-variable": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz",
+ "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg=="
+ },
+ "eris": {
+ "version": "github:abalabahaha/eris#983008230f20532dbedbb75ab6cb79a8ab066d5a",
+ "from": "github:abalabahaha/eris#dev",
+ "requires": {
+ "opusscript": "^0.0.7",
+ "tweetnacl": "^1.0.1",
+ "ws": "^7.2.1"
+ }
+ },
+ "eris-lavalink": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/eris-lavalink/-/eris-lavalink-1.0.2.tgz",
+ "integrity": "sha512-bDkxvfv6iLnTm/Vpg/Hb8v21bv8zDCrdNLmnux6wVypiiGp0kx3yiXeiSBuLJegUbCvpxC6XJByqPwTaLRYnmw==",
+ "requires": {
+ "eris": "eris@github:abalabahaha/eris#fd4366699f506b8b8efb347ac418f856c86d24a7",
+ "ws": "^3.1.0"
+ },
+ "dependencies": {
+ "eris": {
+ "version": "github:abalabahaha/eris#fd4366699f506b8b8efb347ac418f856c86d24a7",
+ "from": "eris@github:abalabahaha/eris#fd4366699f506b8b8efb347ac418f856c86d24a7",
+ "requires": {
+ "opusscript": "^0.0.7",
+ "tweetnacl": "^1.0.1",
+ "ws": "^7.2.1"
+ },
+ "dependencies": {
+ "ws": {
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz",
+ "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA=="
+ }
+ }
+ },
+ "ws": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
+ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
+ "requires": {
+ "async-limiter": "~1.0.0",
+ "safe-buffer": "~5.1.0",
+ "ultron": "~1.1.0"
+ }
+ }
+ }
+ },
+ "fast-safe-stringify": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
+ "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
+ },
+ "fecha": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
+ "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
+ },
+ "form-data": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
+ "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "formidable": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
+ "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q=="
+ },
+ "fs-minipass": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
+ "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
+ "requires": {
+ "minipass": "^2.6.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
+ "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflection": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz",
+ "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+ },
+ "is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+ },
+ "is-bluebird": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz",
+ "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI="
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "kuler": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz",
+ "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==",
+ "requires": {
+ "colornames": "^1.1.1"
+ }
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ },
+ "logform": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz",
+ "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==",
+ "requires": {
+ "colors": "^1.2.1",
+ "fast-safe-stringify": "^2.0.4",
+ "fecha": "^2.3.3",
+ "ms": "^2.1.1",
+ "triple-beam": "^1.3.0"
+ }
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.5.tgz",
+ "integrity": "sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w=="
+ },
+ "mime-db": {
+ "version": "1.44.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+ "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
+ },
+ "mime-types": {
+ "version": "2.1.27",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
+ "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+ "requires": {
+ "mime-db": "1.44.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ },
+ "minipass": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
+ "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
+ "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
+ "requires": {
+ "minipass": "^2.9.0"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "moment": {
+ "version": "2.25.3",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz",
+ "integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg=="
+ },
+ "moment-timezone": {
+ "version": "0.5.28",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.28.tgz",
+ "integrity": "sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw==",
+ "requires": {
+ "moment": ">= 2.9.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "nan": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
+ "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
+ },
+ "needle": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.1.tgz",
+ "integrity": "sha512-x/gi6ijr4B7fwl6WYL9FwlCvRQKGlUNvnceho8wxkwXqN8jvVmmmATTmZPRRG7b/yC1eode26C2HO9jl78Du9g==",
+ "requires": {
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz",
+ "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==",
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ }
+ }
+ },
+ "nopt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
+ "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
+ "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
+ "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
+ },
+ "npm-packlist": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
+ "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1",
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "one-time": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz",
+ "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4="
+ },
+ "opusscript": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/opusscript/-/opusscript-0.0.7.tgz",
+ "integrity": "sha512-DcBadTdYTUuH9zQtepsLjQn4Ll6rs3dmeFvN+SD0ThPnxRBRm/WC1zXWPg+wgAJimB784gdZvUMA57gDP7FdVg==",
+ "optional": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+ "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "qs": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz",
+ "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ=="
+ },
+ "rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "retry-as-promised": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz",
+ "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==",
+ "requires": {
+ "any-promise": "^1.3.0"
+ }
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "runes": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/runes/-/runes-0.4.3.tgz",
+ "integrity": "sha512-K6p9y4ZyL9wPzA+PMDloNQPfoDGTiFYDvdlXznyGKgD10BJpcAosvATKrExRKOrNLgD8E7Um7WGW0lxsnOuNLg=="
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ },
+ "sequelize": {
+ "version": "5.21.7",
+ "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.21.7.tgz",
+ "integrity": "sha512-+JrS5Co7CN53cOFFFaUb+xqQP00wD1Ag9xGLBLoUko2KhRZxjm+UDkqAVPHTUp87McLwJaCPkKv61GPhBVloRQ==",
+ "requires": {
+ "bluebird": "^3.5.0",
+ "cls-bluebird": "^2.1.0",
+ "debug": "^4.1.1",
+ "dottie": "^2.0.0",
+ "inflection": "1.12.0",
+ "lodash": "^4.17.15",
+ "moment": "^2.24.0",
+ "moment-timezone": "^0.5.21",
+ "retry-as-promised": "^3.2.0",
+ "semver": "^6.3.0",
+ "sequelize-pool": "^2.3.0",
+ "toposort-class": "^1.0.1",
+ "uuid": "^3.3.3",
+ "validator": "^10.11.0",
+ "wkx": "^0.4.8"
+ }
+ },
+ "sequelize-pool": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz",
+ "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA=="
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "shimmer": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",
+ "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="
+ },
+ "signal-exit": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
+ },
+ "simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
+ "requires": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "sqlite3": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz",
+ "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==",
+ "requires": {
+ "nan": "^2.12.1",
+ "node-pre-gyp": "^0.11.0"
+ }
+ },
+ "stack-trace": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
+ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
+ },
+ "superagent": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.2.2.tgz",
+ "integrity": "sha512-pMWBUnIllK4ZTw7p/UaobiQPwAO5w/1NRRTDpV0FTVNmECztsxKspj3ZWEordVEaqpZtmOQJJna4yTLyC/q7PQ==",
+ "requires": {
+ "component-emitter": "^1.3.0",
+ "cookiejar": "^2.1.2",
+ "debug": "^4.1.1",
+ "fast-safe-stringify": "^2.0.7",
+ "form-data": "^3.0.0",
+ "formidable": "^1.2.1",
+ "methods": "^1.1.2",
+ "mime": "^2.4.4",
+ "qs": "^6.9.1",
+ "readable-stream": "^3.4.0",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "tar": {
+ "version": "4.4.13",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
+ "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
+ },
+ "text-hex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
+ "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
+ },
+ "toml": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
+ "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
+ },
+ "toposort-class": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
+ "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg="
+ },
+ "triple-beam": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
+ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
+ },
+ "tweetnacl": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
+ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==",
+ "optional": true
+ },
+ "ultron": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
+ "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+ },
+ "validator": {
+ "version": "10.11.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
+ "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "winston": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz",
+ "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==",
+ "requires": {
+ "async": "^2.6.1",
+ "diagnostics": "^1.1.1",
+ "is-stream": "^1.1.0",
+ "logform": "^2.1.1",
+ "one-time": "0.0.4",
+ "readable-stream": "^3.1.1",
+ "stack-trace": "0.0.x",
+ "triple-beam": "^1.3.0",
+ "winston-transport": "^4.3.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "winston-transport": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz",
+ "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==",
+ "requires": {
+ "readable-stream": "^2.3.6",
+ "triple-beam": "^1.2.0"
+ }
+ },
+ "wkx": {
+ "version": "0.4.8",
+ "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz",
+ "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "ws": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz",
+ "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA=="
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..a0a5f7a
--- /dev/null
+++ b/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "troffman",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "MIT",
+ "dependencies": {
+ "chunk-text": "^1.0.5",
+ "dbot-regex-handler": "^1.0.0",
+ "eris": "github:abalabahaha/eris#dev",
+ "eris-lavalink": "^1.0.2",
+ "sequelize": "^5.21.6",
+ "sqlite3": "^4.1.1",
+ "superagent": "^5.2.2",
+ "toml": "^3.0.0",
+ "winston": "^3.2.1"
+ }
+}
diff --git a/src/CommandLoader.js b/src/CommandLoader.js
new file mode 100644
index 0000000..d38250b
--- /dev/null
+++ b/src/CommandLoader.js
@@ -0,0 +1,12 @@
+const fs = require('fs');
+
+module.exports = function CommandLoader(bot) {
+ fs.readdirSync('./src/cmd/').forEach(file => {
+ if (file.endsWith('.js')) {
+ let plugin = require(`./cmd/${file}`);
+ if (plugin.loadModule) {
+ plugin.loadModule(bot);
+ }
+ }
+ });
+};
diff --git a/src/Events.js b/src/Events.js
new file mode 100644
index 0000000..d3ea15f
--- /dev/null
+++ b/src/Events.js
@@ -0,0 +1,57 @@
+const { PlayerManager } = require('eris-lavalink');
+const { Op } = require('sequelize');
+
+module.exports = function Events(bot) {
+ let r;
+
+ bot.on('ready', async () => {
+ Logger.info(`Successfully connected as user ${bot.user.username}#${bot.user.discriminator}`);
+ r = new RegExp(`^(?:<@!?${bot.user.id}> +|-)\\b`);
+
+ bot.editStatus('online', {
+ name: `watching LaTeX.`,
+ type: 3,
+ });
+ });
+
+ bot.on('error', (err, id) => {
+ Logger.error(`Error encountered on shard ${id}`);
+ Logger.error(err);
+ });
+
+ bot.on('messageCreate', async (msg) => {
+ if (!r) {
+ Logger.error('Some real shit hapened : message matching regex hasn\'t been defined for some reason.');
+ process.exit();
+ }
+
+ let content = msg.content.replace(r, '');
+
+ if (content === msg.content) return;
+ if (msg.author.bot) return;
+ if (msg.author === bot.user) return;
+ if (msg.channel.type !== 0) return;
+
+ /*
+ let important = msg.channel.guild.members.filter(m => m.permission.has('administrator')).map(m => m.id);
+
+ important.push(msg.author.id);
+
+ let user = await bot.db.Auser.findOne({
+ where: {
+ userId: important,
+ },
+ });
+ let guild = await bot.db.Aguild.findOne({ where: { guildId: msg.channel.guild.id } });
+
+ if ((bot.config.sudoers && bot.config.sudoers.indexOf(msg.author.id) <= -1) && !user && !guild) return; */
+
+ Logger.debug(`Command '${msg.content}' issued`);
+
+ let trimmedContent = content.trim();
+ let result = bot.handler.apply(trimmedContent, msg);
+ if (Array.isArray(result)) {
+ bot.createMessage(msg.channel.id, `Missing permissions : ${result.join(', ')}`).catch(Logger.error);
+ }
+ });
+};
diff --git a/src/Hastebin.js b/src/Hastebin.js
new file mode 100644
index 0000000..1d7bae0
--- /dev/null
+++ b/src/Hastebin.js
@@ -0,0 +1,6 @@
+const superagent = require('superagent');
+
+module.exports = async function hastebin(text) {
+ let res = await superagent.post('https://hasteb.in/documents').send(text);
+ return JSON.parse(res.text).key;
+}; \ No newline at end of file
diff --git a/src/RegexFramework.js b/src/RegexFramework.js
new file mode 100644
index 0000000..fb915aa
--- /dev/null
+++ b/src/RegexFramework.js
@@ -0,0 +1,31 @@
+const CommandHandler = require('dbot-regex-handler');
+
+
+module.exports = class RegexFramework extends CommandHandler {
+ endpoint(r, perms, cb) {
+ super.endpoint(r, cb);
+ this.commands[this.commands.length - 1].p = perms;
+ }
+
+ apply(str, context) {
+ for (let i = 0; i < this.commands.length; i++) {
+ let match = str.match(this.commands[i].regex);
+ if (match) {
+ let missingPerms = [];
+ this.commands[i].p.forEach(name => {
+ if (!context.member.permission.has(name)) {
+ missingPerms.push(name);
+ }
+ });
+ if (missingPerms.length === 0) {
+ this.commands[i].callback(match, context);
+ return true;
+ }
+ else {
+ return missingPerms;
+ }
+ }
+ }
+ return false;
+ }
+};
diff --git a/src/Time.js b/src/Time.js
new file mode 100644
index 0000000..1bbd7eb
--- /dev/null
+++ b/src/Time.js
@@ -0,0 +1,5 @@
+module.exports.msToMinutes = function msToMinutes(ms) {
+ let d = new Date();
+ d.setTime(ms);
+ return `${d.getMinutes()}min ${d.getSeconds()}s`;
+}; \ No newline at end of file
diff --git a/src/Troffman.js b/src/Troffman.js
new file mode 100644
index 0000000..2b8860c
--- /dev/null
+++ b/src/Troffman.js
@@ -0,0 +1,35 @@
+const Eris = require('eris');
+const toml = require('toml');
+const fs = require('fs');
+
+const RegexFramework = require('./RegexFramework');
+const Events = require('./Events');
+const CommandLoader = require('./CommandLoader');
+const TroffmanDatabase = require('./TroffmanDatabase');
+
+module.exports = class Troffman extends Eris {
+ constructor(configPath, options) {
+ if (!fs.existsSync(configPath)) {
+ fs.copyFileSync("./config.def.toml", configPath);
+ process.exit(0);
+ }
+ let c = toml.parse(fs.readFileSync(configPath));
+ super(c.token, options);
+ this.config = c;
+ if (!this.config.sudoers) {
+ this.config.sudoers = [''];
+ }
+ else if (!Array.isArray(this.config.sudoers)) {
+ this.config.sudoers = [''];
+ }
+ else if (this.config.sudoers.length <= 0) {
+ this.config.sudoers = [''];
+ }
+ this._ds = Array.from(this.config.sudoers);
+ this.db = new TroffmanDatabase(c.database);
+ this.handler = new RegexFramework();
+ Events(this);
+ CommandLoader(this);
+ this.db.sync();
+ }
+};
diff --git a/src/TroffmanDatabase.js b/src/TroffmanDatabase.js
new file mode 100644
index 0000000..58e7608
--- /dev/null
+++ b/src/TroffmanDatabase.js
@@ -0,0 +1,25 @@
+const Sequelize = require('sequelize');
+
+module.exports = class TroffmanDatabase extends Sequelize {
+ constructor(path) {
+ super('database', 'user', 'password', {
+ host: 'localhost',
+ dialect: 'sqlite',
+ logging: false,
+ storage: path,
+ });
+
+ this.Auser = this.define('ausers', {
+ userId: {
+ type: Sequelize.STRING,
+ unique: true,
+ },
+ });
+ this.Aguild = this.define('aguilds', {
+ guildId: {
+ type: Sequelize.STRING,
+ unique: true,
+ },
+ });
+ }
+};
diff --git a/src/Wait.js b/src/Wait.js
new file mode 100644
index 0000000..0f0bdfd
--- /dev/null
+++ b/src/Wait.js
@@ -0,0 +1,7 @@
+module.exports = function wait(ms) {
+ return new Promise(resolve => {
+ setTimeout(() => {
+ resolve();
+ }, ms);
+ });
+};
diff --git a/src/cmd/debug.js b/src/cmd/debug.js
new file mode 100644
index 0000000..ecb475c
--- /dev/null
+++ b/src/cmd/debug.js
@@ -0,0 +1,5 @@
+module.exports.loadModule = function loadModule(bot) {
+ bot.handler.endpoint('^ping$', [], (match, message) => {
+ bot.createMessage(message.channel.id, 'Pong').catch(Logger.error);
+ });
+};
diff --git a/src/cmd/info.js b/src/cmd/info.js
new file mode 100644
index 0000000..899dac6
--- /dev/null
+++ b/src/cmd/info.js
@@ -0,0 +1,19 @@
+const exec = require('child_process').exec;
+
+module.exports.loadModule = function loadModule(bot) {
+ bot.handler.endpoint('^v(?:ersion)?$', [], (match, message) => {
+ exec('git rev-list --count HEAD', (error, stdout) => {
+ if (error) {
+ bot.createMessage(message.channel.id, 'An error has occured').catch(Logger.error);
+ return;
+ }
+ exec('git log -1 --pretty=%B', (error2, stdout2) => {
+ let msg = `Commit number ${stdout}`;
+ if (!error2) {
+ msg += `\n\`\`\`\n${stdout2}\`\`\``;
+ }
+ bot.createMessage(message.channel.id, msg).catch(Logger.error);
+ });
+ });
+ });
+};
diff --git a/src/cmd/sudo.js b/src/cmd/sudo.js
new file mode 100644
index 0000000..cc590bf
--- /dev/null
+++ b/src/cmd/sudo.js
@@ -0,0 +1,139 @@
+const { inspect } = require('util');
+const vm = require('vm');
+
+module.exports.loadModule = function loadModule(bot) {
+ bot.handler.endpoint('^guilds$', [], (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ bot.createMessage(message.channel.id, `\`${bot.guilds.size}\``).catch(Logger.error);
+ });
+ bot.handler.endpoint('^is-sudoer$', [], (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ bot.createMessage(message.channel.id, 'true').catch(Logger.error);
+ });
+ bot.handler.endpoint('^sudoers$', [], (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ bot.createMessage(message.channel.id, `\`\`\`\n[ ${bot.config.sudoers.join(',\n ')} ]\n\`\`\``).catch(Logger.error);
+ });
+ bot.handler.endpoint('^addsudo (.+)$', [], (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ bot.config.sudoers.push(match[1]);
+ bot.createMessage(message.channel.id, `${match[1]} temporarily added to the sudoers list`).catch(Logger.error);
+ });
+ bot.handler.endpoint('^resetsudo$', [], (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ bot.config.sudoers = Array.from(bot._ds);
+ bot.createMessage(message.channel.id, `Sudoers list reset`).catch(Logger.error);
+ });
+ bot.handler.endpoint('^removesudo (.+)$', [], (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ let i = bot.config.sudoers.indexOf(match[1]);
+ if (i >= 0) {
+ bot.config.sudoers.splice(i, 1);
+ bot.createMessage(message.channel.id, `${match[1]} removed from sudoers list`).catch(Logger.error);
+ }
+ else {
+ bot.createMessage(message.channel.id, `${match[1]} was not sudoer`).catch(Logger.error);
+ }
+ });
+ bot.handler.endpoint('^e ?```(?:.*\n)?(.*)\n?```$', [], (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ try {
+ let evaled = vm.runInNewContext(match[1], {
+ ctx: {
+ bot: bot,
+ message: message,
+ match: match,
+ },
+ require: require,
+ });
+
+ if (typeof evaled !== 'string') {
+ evaled = inspect(evaled);
+ }
+ evaled = evaled.replace(bot.config.token, 'ツ');
+ bot.createMessage(message.channel.id, `\`\`\`${evaled}\`\`\``).catch(Logger.error);
+ }
+ catch (e) {
+ bot.createMessage(message.channel.id, `Error:\n\`\`\`\n${e}\`\`\``).catch(Logger.error);
+ }
+ });
+ bot.handler.endpoint('^aguilds$', [], async (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ let aguilds = await bot.db.Aguild.findAll({ attributes: ['guildId'] });
+ let buff = '```\nAuthorized guilds:\n\n';
+ aguilds.forEach(g => {
+ buff += `- ${g.guildId}\n`;
+ });
+ buff += '```';
+ bot.createMessage(message.channel.id, buff).catch(Logger.error);
+ });
+ bot.handler.endpoint('^ausers$', [], async (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ let ausers = await bot.db.Auser.findAll({ attributes: ['userId'] });
+ let buff = '```\nAuthorized users:\n\n';
+ ausers.forEach(u => {
+ buff += `- ${u.userId}\n`;
+ });
+ buff += '```';
+ bot.createMessage(message.channel.id, buff).catch(Logger.error);
+ });
+ bot.handler.endpoint('^aguild ([0-9]+)$', [], async (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ if (!match[1]) return;
+ try {
+ await bot.db.Aguild.create({
+ guildId: match[1],
+ });
+ bot.createMessage(message.channel.id, `Guild \`${match[1]}\` successfully authorized!`).catch(Logger.error);
+ }
+ catch (e) {
+ bot.createMessage(message.channel.id, 'Guild was already authorized.').catch(Logger.error);
+ }
+ });
+ bot.handler.endpoint('^auser ([0-9]+)$', [], async (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ if (!match[1]) return;
+ try {
+ await bot.db.Auser.create({
+ userId: match[1],
+ });
+ bot.createMessage(message.channel.id, `User \`${match[1]}\` successfully authorized!`).catch(Logger.error);
+ }
+ catch (e) {
+ bot.createMessage(message.channel.id, 'User was already authorized.').catch(Logger.error);
+ }
+ });
+ bot.handler.endpoint('^rguild ([0-9]+)$', [], async (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ if (!match[1]) return;
+ await bot.db.Aguild.destroy({
+ where: {
+ guildId: match[1],
+ }
+ });
+ bot.createMessage(message.channel.id, `Guild \`${match[1]}\` successfully removed!`).catch(Logger.error);
+ });
+ bot.handler.endpoint('^ruser ([0-9]+)$', [], async (match, message) => {
+ if (!bot.config.sudoers) return;
+ if (bot.config.sudoers.indexOf(message.author.id) <= -1) return;
+ if (!match[1]) return;
+ await bot.db.Auser.destroy({
+ where: {
+ userId: match[1],
+ }
+ });
+ bot.createMessage(message.channel.id, `User \`${match[1]}\` successfully removed!`).catch(Logger.error);
+ });
+};
diff --git a/src/cmd/troff.js b/src/cmd/troff.js
new file mode 100644
index 0000000..91090a5
--- /dev/null
+++ b/src/cmd/troff.js
@@ -0,0 +1,59 @@
+const spawn = require('child_process').spawn;
+const fs = require('fs');
+const { ConsoleTransportOptions } = require('winston/lib/winston/transports');
+
+/*
+\\"".fp - R cmunrm
+\\"".fp - I cmunti
+\\"".fp - B cmunrb
+\\"".fp - BI cmunbi
+*/
+
+const prelude = `
+.fp - CMEX CMEX10
+.fp - CMSY CMSY10
+.fp - CMMI CMMI10
+.fp - CB CB
+.fspecial R CMEX CMSY
+.fspecial I CMMI
+
+.EQ
+define <=> %{vcenter roman " \\\\N'arrowdblboth' "}%
+define appr %{vcenter roman "≈"}%
+define intd %{vcenter roman "\\\\N'integraldisplay'"}%
+delim $$
+.EN
+
+.LP
+.ps +20
+\\m[white]
+`;
+
+module.exports.loadModule = function loadModule(bot) {
+ bot.handler.endpoint(/^tr(?:off)?!?(?: |\n)([\s\S]*)$/m, [], (match, message) => {
+ ma = match[1].replace(/^\.sy\s.*$/gm, '');
+ ma = ma.replace(/^sh\s.*$/gm, '');
+ ma = ma.replace(/^\.?co\s.*$/gm, '');
+ ma = ma.replace(/^\\X.*$/gm, '');
+ if (ma !== match[1]) console.log('had to sanitize');
+ const subprocess0 = spawn('pic');
+ console.log(ma);
+ subprocess0.stdin.write(prelude + '\n' + ma + '\n');
+ subprocess0.stdin.end();
+ const subprocess1 = spawn('eqn');
+ subprocess0.stdout.pipe(subprocess1.stdin);
+ const subprocess2 = spawn('roff', ['-ms']);
+ subprocess1.stdout.pipe(subprocess2.stdin);
+ const subprocess3 = spawn('pdf', ['-p', '10000x10000']);
+ subprocess2.stdout.pipe(subprocess3.stdin);
+ const subprocess4 = spawn('convert', ['-', '-trim', 'png:-']);
+ subprocess3.stdout.pipe(subprocess4.stdin);
+ let ch = Buffer.from("");
+ subprocess4.stdout.on('data', (data) => {
+ ch = Buffer.concat([ch, data]);
+ });
+ subprocess4.stdout.on('end', () => {
+ message.channel.createMessage('', {name: 'troff.png', file: ch});
+ });
+ });
+};
diff --git a/src/cmd/voice.js b/src/cmd/voice.js
new file mode 100644
index 0000000..7f12603
--- /dev/null
+++ b/src/cmd/voice.js
@@ -0,0 +1,356 @@
+const superagent = require('superagent');
+const wait = require('../Wait');
+const time = require('../Time');
+const hastebin = require('../Hastebin');
+
+const querystring = require('querystring');
+const chunk = require('chunk-text');
+
+async function resolveTracks(node, search) {
+ let result;
+ try {
+ result = await superagent.get(`http://${node.host}:${node.port}/loadtracks?identifier=${search}`)
+ .set('Authorization', node.password)
+ .set('Accept', 'application/json');
+ } catch (err) {
+ throw err;
+ }
+
+ if (!result) {
+ throw 'Unable play that video.';
+ }
+
+ return result.body; // array of tracks resolved from lavalink
+}
+
+function getLavalinkPlayer(channel, bot) {
+ if (!channel || !channel.guild) {
+ return Promise.reject('Not a guild channel.');
+ }
+
+ let player = bot.voiceConnections.get(channel.guild.id);
+ if (player) {
+ return Promise.resolve(player);
+ }
+
+ let options = {};
+ if (channel.guild.region) {
+ options.region = channel.guild.region;
+ }
+
+ return bot.joinVoiceChannel(channel.id, options);
+}
+
+function getRandomColor() {
+ var letters = '0123456789ABCDEF';
+ var color = '';
+ for (var i = 0; i < 6; i++) {
+ color += letters[Math.floor(Math.random() * 16)];
+ }
+ return parseInt(color);
+}
+
+async function crawl(player, bot, message) {
+ if (bot.voices[message.channel.guild.id].queue.length === 0) {
+ bot.voices[message.channel.guild.id].crawling = false;
+ delete bot.voices[message.channel.guild.id].current;
+ bot.leaveVoiceChannel(player.channelId);
+ return;
+ };
+
+ bot.voices[message.channel.guild.id].crawling = true;
+ let next = bot.voices[message.channel.guild.id].queue.shift();
+ bot.voices[message.channel.guild.id].current = next;
+ player.play(next.track);
+
+ player.removeAllListeners('disconnect');
+ player.once('disconnect', (err) => {
+ if (err) {
+ Logger.error(err);
+ }
+ bot.voices[message.channel.guild.id].crawling = false;
+ delete bot.voices[message.channel.guild.id].current; //Attempt to fix disconnect bug, implement `come' command to recrawl is still to do. Refer to previous commit for previous implementation
+ bot.leaveVoiceChannel(player.channelId);
+ });
+
+ player.removeAllListeners('error');
+ player.once('error', (err) => {
+ Logger.error(`Player error: ${err}`);
+ // I do not know how it behaves after there's an error so I just put these in comment for now
+ // bot.voices[message.channel.guild.id].crawling = false;
+ // delete bot.voices[message.channel.guild.id].current;
+ // bot.leaveVoiceChannel(player.channelId);
+
+ // Just in case, continue crawling
+ crawl(player, bot, message);
+ });
+
+ player.removeAllListeners('end');
+ player.once('end', async (data) => {
+ // REPLACED reason is emitted when playing without stopping, I ignore these to prevent skip loops
+ if (data.reason && data.reason === 'REPLACED') return;
+ await wait(750);
+ crawl(player, bot, message);
+ });
+}
+
+module.exports.loadModule = function loadModule(bot) {
+ bot.handler.endpoint('^(?:add|meme|play|p|a)([;:-][0-9,-]+)? (.+)$', [], async (match, message) => {
+ let ones = [];
+ // The following messy loop parses playlist selection.
+ // A hacky limitation has been used here to prevent abuse. A new system HAS to be used.
+ if (match[1]) {
+ let param = match[1].substring(1);
+ let selectors = param.split(',');
+ selectors.forEach(s => {
+ let r = s.split('-');
+ if (r.length === 2) {
+ let indS = parseInt(r[0]);
+ let indE = parseInt(r[1]);
+ if (indE <= indS) return;
+ if (indE - indS > 100) return;
+ for (let i = indS; i <= indE; i++) {
+ if (ones.indexOf(i) <= -1) {
+ ones.push(i);
+ }
+ }
+ }
+ else if (r.length === 1) {
+ let ind = parseInt(r[0]);
+ if (ones.indexOf(ind) <= -1) {
+ ones.push(ind);
+ }
+ }
+ });
+ }
+
+ if (!bot.voices[message.channel.guild.id]) bot.voices[message.channel.guild.id] = { queue: [] };
+
+ let m = match[2];
+
+ if (!m.match(/^<?https?:\/\//)) {
+ m = 'ytsearch:' + m;
+ }
+ else if (m.charAt(0) === '<' && m.charAt(m.length - 1) === '>') {
+ m = m.slice(1);
+ m = m.slice(0, -1);
+ }
+
+ let t = await resolveTracks(bot._main, `${m}`);
+ if (t.loadType === 'TRACK_LOADED' || t.loadType === 'SEARCH_RESULT') {
+ let tr = t.tracks[0];
+ if (tr.info.isStream) {
+ bot.createMessage(message.channel.id, `I do not yet support streams, I'm sorry :(`).catch(Logger.error);
+ return;
+ }
+ tr.adder = `${message.author.username}#${message.author.discriminator}`;
+ bot.voices[message.channel.guild.id].queue.push(tr);
+ let ign = !match[1] ? '' : ' Playlist selectors parameters have been ignored as it is a sole song.';
+ bot.createMessage(message.channel.id, `\`${tr.info.title}\` has been added by \`${tr.adder}\`.${ign}`).catch(Logger.error);
+ }
+ else if (t.loadType === 'PLAYLIST_LOADED') {
+ let co = 0;
+ for (let i = 0; i < t.tracks.length; i++) {
+ if (ones.indexOf(i + 1) > -1 || ones.length === 0) {
+ let tr = t.tracks[i];
+ tr.adder = `${message.author.username}#${message.author.discriminator}`;
+ bot.voices[message.channel.guild.id].queue.push(tr);
+ co++;
+ }
+ }
+ bot.createMessage(message.channel.id, `${co} songs have been added to the queue by \`${message.author.username}#${message.author.discriminator}\``).catch(Logger.error);
+ }
+ else if (t.loadType === 'NO_MATCHES' || t.loadType === 'LOAD_FAILED') {
+ bot.createMessage(message.channel.id, `No results, sorry.`).catch(Logger.error);
+ return;
+ }
+
+ if (!message.member.voiceState.channelID) return;
+ let channel = message.channel.guild.channels.find(m => m.id === message.member.voiceState.channelID);
+ if (!bot.voices[message.channel.guild.id].crawling) {
+ let player = await getLavalinkPlayer(channel, bot);
+ player.switchChannel(message.member.voiceState.channelID, true);
+ bot.createMessage(message.channel.id, 'Joined voice channel.').catch(Logger.error); // TEMPORARY
+ crawl(player, bot, message);
+ }
+ });
+
+ bot.handler.endpoint('^skip$', [], async (match, message) => {
+ let player = bot.voiceConnections.get(message.channel.guild.id);
+ if (player) {
+ player.stop();
+ bot.createMessage(message.channel.id, 'Current song skipped').catch(Logger.error);
+ }
+ else {
+ bot.createMessage(message.channel.id, 'The bot wasn\'t playing.').catch(Logger.error);
+ }
+ });
+
+ bot.handler.endpoint('^clear$', [], async (match, message) => {
+ bot.voices[message.channel.guild.id].queue = [];
+ bot.createMessage(message.channel.id, 'The current queue has been cleared!').catch(Logger.error);
+ });
+
+ bot.handler.endpoint('^(?:stop|quit|halt)!?$', [], async (match, message) => {
+ let player = bot.voiceConnections.get(message.channel.guild.id);
+ bot.voices[message.channel.guild.id].queue = [];
+ if (player) {
+ player.stop();
+ bot.createMessage(message.channel.id, 'Successfully stopped!').catch(Logger.error);
+ }
+ else {
+ bot.createMessage(message.channel.id, 'The bot wasn\'t playing but the queue still has been cleared.').catch(Logger.error);
+ }
+ });
+
+ bot.handler.endpoint('^(?:come|resume)!?$', [], async (match, message) => {
+ if (!message.member.voiceState.channelID) return;
+ let channel = message.channel.guild.channels.find(m => m.id === message.member.voiceState.channelID);
+ let player = bot.voiceConnections.get(message.channel.guild.id);
+ if (player) {
+ player.switchChannel(message.member.voiceState.channelID, true);
+ if (player.paused) {
+ player.resume();
+ bot.createMessage(message.channel.id, 'Resumed the song.').catch(Logger.error);
+ }
+ }
+ else {
+ if (!message.member.voiceState.channelID) return;
+ if (!bot.voices[message.channel.guild.id]) bot.voices[message.channel.guild.id] = { queue: [] };
+ if (bot.voices[message.channel.guild.id].queue.length >= 1) {
+ let channel = message.channel.guild.channels.find(m => m.id === message.member.voiceState.channelID);
+ //if (!bot.voices[message.channel.guild.id].crawling) {
+ let player = await getLavalinkPlayer(channel, bot);
+ player.switchChannel(message.member.voiceState.channelID, true);
+ bot.createMessage(message.channel.id, 'Joined voice channel.').catch(Logger.error); // TEMPORARY
+ crawl(player, bot, message);
+ //}
+ }
+ else {
+ bot.createMessage(message.channel.id, 'The bot wasn\'t in any voice channel.').catch(Logger.error);
+ }
+ }
+ });
+
+ bot.handler.endpoint('^pause!?$', [], async (match, message) => {
+ let player = bot.voiceConnections.get(message.channel.guild.id);
+ if (player) {
+ player.pause();
+ bot.createMessage(message.channel.id, 'Song paused.').catch(Logger.error);
+ }
+ else {
+ bot.createMessage(message.channel.id, 'The bot isn\'t in any voice channel.').catch(Logger.error);
+ }
+ });
+
+ bot.handler.endpoint('^skip-to!? ([0-9]+)$', [], async (match, message) => {
+ let player = bot.voiceConnections.get(message.channel.guild.id);
+ if (!bot.voices[message.channel.guild.id]) bot.voices[message.channel.guild.id] = { queue: [] };
+ let arg = parseInt(match[1]);
+ if (arg <= 0) {
+ bot.createMessage(message.channel.id, `The argument should be greater than 0 (the queue is one-indexed), but 0 was provided.`).catch(Logger.error);
+ return;
+ }
+ if (arg > bot.voices[message.channel.guild.id].queue.length) {
+ bot.createMessage(message.channel.id, `Can't skip that far, the queue is currently only ${bot.voices[message.channel.guild.id].queue.length} titles long :')`).catch(Logger.error);
+ return;
+ }
+ bot.voices[message.channel.guild.id].queue = bot.voices[message.channel.guild.id].queue.splice(arg - 1);
+ if (player) {
+ player.stop();
+ bot.createMessage(message.channel.id, `Current song and ${arg - 1} following where skipped.`).catch(Logger.error);
+ }
+ else {
+ bot.createMessage(message.channel.id, `The bot wasn\'t playing but the ${arg - 1} next songs were successfully removed.`).catch(Logger.error);
+ }
+ });
+
+ bot.handler.endpoint('^remove-to!? ([0-9]+)$', [], async (match, message) => {
+ if (!bot.voices[message.channel.guild.id]) bot.voices[message.channel.guild.id] = { queue: [] };
+ let arg = parseInt(match[1]);
+ if (arg <= 0) {
+ bot.createMessage(message.channel.id, `The argument should be greater than 0 (the queue is one-indexed), but 0 was provided.`).catch(Logger.error);
+ return;
+ }
+ if (arg > bot.voices[message.channel.guild.id].queue.length) {
+ bot.createMessage(message.channel.id, `Can't remove that far, the queue is currently only ${bot.voices[message.channel.guild.id].queue.length} titles long :')`).catch(Logger.error);
+ return;
+ }
+ bot.voices[message.channel.guild.id].queue = bot.voices[message.channel.guild.id].queue.splice(arg);
+ bot.createMessage(message.channel.id, `${arg} next songs in the queue were removed.`).catch(Logger.error);
+ });
+
+ bot.handler.endpoint('^remove!? ([0-9]+)$', [], async (match, message) => {
+ if (!bot.voices[message.channel.guild.id]) bot.voices[message.channel.guild.id] = { queue: [] };
+ let arg = parseInt(match[1]);
+ if (arg <= 0) {
+ bot.createMessage(message.channel.id, `The argument should be greater than 0 (the queue is one-indexed), but 0 was provided.`).catch(Logger.error);
+ return;
+ }
+ if (arg > bot.voices[message.channel.guild.id].queue.length) {
+ bot.createMessage(message.channel.id, `Can't remove that far, the queue is currently only ${bot.voices[message.channel.guild.id].queue.length} titles long :')`).catch(Logger.error);
+ return;
+ }
+ bot.voices[message.channel.guild.id].queue.splice(arg - 1, 1);
+ bot.createMessage(message.channel.id, `The ${arg}e song in the queue was removed.`).catch(Logger.error);
+ });
+
+ bot.handler.endpoint('^now\\??$', [], async (match, message) => {
+ let player = bot.voiceConnections.get(message.channel.guild.id);
+ if (player && bot.voices[message.channel.guild.id].current) {
+ bot.createMessage(message.channel.id, `Now playing \`${bot.voices[message.channel.guild.id].current.info.title}\` at position ${time.msToMinutes(player.state.position)} added by \`${bot.voices[message.channel.guild.id].current.adder}\`. Total duration: ${time.msToMinutes(bot.voices[message.channel.guild.id].current.info.length)}`).catch(Logger.error);
+ }
+ else {
+ bot.createMessage(message.channel.id, 'The bot is not playing anything ¯\\_(ツ)_/¯').catch(Logger.error);
+ }
+ });
+
+ bot.handler.endpoint('^(?:queue|playlist|q|list)\\??$', [], async (match, message) => {
+ if (!bot.voices[message.channel.guild.id].queue || bot.voices[message.channel.guild.id].queue.length === 0) {
+ bot.createMessage(message.channel.id, 'The queue is empty!').catch(Logger.error);
+ return;
+ }
+ let buff = "";
+ let count = 1;
+ bot.voices[message.channel.guild.id].queue.forEach(t => {
+ buff += `${count}. ${t.info.title}, added by \`${t.adder}\` and lasts ${time.msToMinutes(t.info.length)}\n`;
+ count++;
+ });
+ bot.createMessage(message.channel.id, buff).catch(Logger.error);
+ });
+
+ bot.handler.endpoint('^(?:lyrics|text)\\??(?: (.+))?$', [], async (match, message) => {
+ let s = match[1] ? match[1] : null;
+ if (!s && (bot.voices[message.channel.guild.id] && bot.voices[message.channel.guild.id].current)) s = bot.voices[message.channel.guild.id].current.info.title;
+ if (!s) {
+ bot.createMessage(message.channel.id, 'No request mentionned and no song currently playing ¯\\_(ツ)_/¯').catch(Logger.error);
+ return;
+ }
+ let result;
+ try {
+ result = await superagent.get(`https://lyrics.tsu.sh/v1/?q=${s}`);
+ }
+ catch (e) {
+ return;
+ }
+ let res = JSON.parse(result.text);
+ let chunks = chunk(res.content, 2048);
+ if (chunks.length <= 4) {
+ let col = getRandomColor();
+ for (let i = 0; i < chunks.length; i++) {
+ let data = {
+ embed: {
+ description: chunks[i],
+ color: col,
+ }
+ }
+ if (i === 0) data.embed.title = res.song.full_title;
+ await bot.createMessage(message.channel.id, data).catch(Logger.error);
+ }
+ }
+ else {
+ let key = await hastebin(res.content);
+ bot.createMessage(message.channel.id, `https://hasteb.in/${key}.txt`).catch(Logger.error);
+ }
+ });
+};