diff options
| -rw-r--r-- | .eslintrc.json | 161 | ||||
| -rw-r--r-- | .gitignore | 7 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | UNLICENSE | 24 | ||||
| -rw-r--r-- | config.def.toml | 22 | ||||
| -rw-r--r-- | index.js | 25 | ||||
| -rw-r--r-- | install_lavalink.sh | 7 | ||||
| -rw-r--r-- | package-lock.json | 1013 | ||||
| -rw-r--r-- | package.json | 23 | ||||
| -rw-r--r-- | src/CommandLoader.js | 12 | ||||
| -rw-r--r-- | src/Events.js | 57 | ||||
| -rw-r--r-- | src/Hastebin.js | 6 | ||||
| -rw-r--r-- | src/RegexFramework.js | 31 | ||||
| -rw-r--r-- | src/Time.js | 5 | ||||
| -rw-r--r-- | src/Troffman.js | 35 | ||||
| -rw-r--r-- | src/TroffmanDatabase.js | 25 | ||||
| -rw-r--r-- | src/Wait.js | 7 | ||||
| -rw-r--r-- | src/cmd/debug.js | 5 | ||||
| -rw-r--r-- | src/cmd/info.js | 19 | ||||
| -rw-r--r-- | src/cmd/sudo.js | 139 | ||||
| -rw-r--r-- | src/cmd/troff.js | 59 | ||||
| -rw-r--r-- | src/cmd/voice.js | 356 |
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); + } + }); +}; |
