Switch to knub-command-manager instead of Eris's command client. Update sqlite3 for Node.js 12 support.
parent
68ec9748a1
commit
38c7bd83ff
|
@ -45,7 +45,6 @@
|
||||||
"version": "6.10.0",
|
"version": "6.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
|
||||||
"integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
|
"integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"fast-deep-equal": "^2.0.1",
|
"fast-deep-equal": "^2.0.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
@ -445,9 +444,9 @@
|
||||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||||
},
|
},
|
||||||
"combined-stream": {
|
"combined-stream": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"delayed-stream": "~1.0.0"
|
"delayed-stream": "~1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -1155,9 +1154,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fs-minipass": {
|
"fs-minipass": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz",
|
||||||
"integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
|
"integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"minipass": "^2.2.1"
|
"minipass": "^2.2.1"
|
||||||
}
|
}
|
||||||
|
@ -1227,6 +1226,7 @@
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs.realpath": "^1.0.0",
|
"fs.realpath": "^1.0.0",
|
||||||
"inflight": "^1.0.4",
|
"inflight": "^1.0.4",
|
||||||
|
@ -1299,19 +1299,6 @@
|
||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "^6.5.5",
|
"ajv": "^6.5.5",
|
||||||
"har-schema": "^2.0.0"
|
"har-schema": "^2.0.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ajv": {
|
|
||||||
"version": "6.9.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.2.tgz",
|
|
||||||
"integrity": "sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg==",
|
|
||||||
"requires": {
|
|
||||||
"fast-deep-equal": "^2.0.1",
|
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
|
||||||
"json-schema-traverse": "^0.4.1",
|
|
||||||
"uri-js": "^4.2.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"has-flag": {
|
"has-flag": {
|
||||||
|
@ -1850,6 +1837,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"knub-command-manager": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/knub-command-manager/-/knub-command-manager-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-ylSRl84FcRjanvE1cMXhgrHIMOEgYmUEFHDutbiUr5aAg/C1coHE/HrPIwiovhDfRLU2++Y79yJoV99Jmwy4mA==",
|
||||||
|
"requires": {
|
||||||
|
"escape-string-regexp": "^2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"escape-string-regexp": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"lcid": {
|
"lcid": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
|
||||||
|
@ -1978,16 +1980,16 @@
|
||||||
"integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg=="
|
"integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg=="
|
||||||
},
|
},
|
||||||
"mime-db": {
|
"mime-db": {
|
||||||
"version": "1.38.0",
|
"version": "1.40.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
|
||||||
"integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg=="
|
"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
|
||||||
},
|
},
|
||||||
"mime-types": {
|
"mime-types": {
|
||||||
"version": "2.1.22",
|
"version": "2.1.24",
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz",
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
|
||||||
"integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==",
|
"integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-db": "~1.38.0"
|
"mime-db": "1.40.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mimic-fn": {
|
"mimic-fn": {
|
||||||
|
@ -2081,9 +2083,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"nan": {
|
"nan": {
|
||||||
"version": "2.10.0",
|
"version": "2.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
|
||||||
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA=="
|
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
|
||||||
},
|
},
|
||||||
"nanomatch": {
|
"nanomatch": {
|
||||||
"version": "1.2.13",
|
"version": "1.2.13",
|
||||||
|
@ -2110,13 +2112,28 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"needle": {
|
"needle": {
|
||||||
"version": "2.2.4",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz",
|
||||||
"integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==",
|
"integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^2.1.2",
|
"debug": "^3.2.6",
|
||||||
"iconv-lite": "^0.4.4",
|
"iconv-lite": "^0.4.4",
|
||||||
"sax": "^1.2.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"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nice-try": {
|
"nice-try": {
|
||||||
|
@ -2490,9 +2507,9 @@
|
||||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||||
},
|
},
|
||||||
"psl": {
|
"psl": {
|
||||||
"version": "1.1.31",
|
"version": "1.1.32",
|
||||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz",
|
||||||
"integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw=="
|
"integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g=="
|
||||||
},
|
},
|
||||||
"public-ip": {
|
"public-ip": {
|
||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
|
@ -2709,11 +2726,26 @@
|
||||||
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
|
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
|
||||||
},
|
},
|
||||||
"rimraf": {
|
"rimraf": {
|
||||||
"version": "2.6.1",
|
"version": "2.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
|
||||||
"integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
|
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"glob": "^7.0.5"
|
"glob": "^7.1.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"glob": {
|
||||||
|
"version": "7.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
|
||||||
|
"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"run-async": {
|
"run-async": {
|
||||||
|
@ -2977,11 +3009,11 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"sqlite3": {
|
"sqlite3": {
|
||||||
"version": "4.0.6",
|
"version": "4.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.9.tgz",
|
||||||
"integrity": "sha512-EqBXxHdKiwvNMRCgml86VTL5TK1i0IKiumnfxykX0gh6H6jaKijAXvE9O1N7+omfNSawR2fOmIyJZcfe8HYWpw==",
|
"integrity": "sha512-IkvzjmsWQl9BuBiM4xKpl5X8WCR4w0AeJHRdobCdXZ8dT/lNc1XS6WqvY35N6+YzIIgzSBeY5prdFObID9F9tA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"nan": "~2.10.0",
|
"nan": "^2.12.1",
|
||||||
"node-pre-gyp": "^0.11.0",
|
"node-pre-gyp": "^0.11.0",
|
||||||
"request": "^2.87.0"
|
"request": "^2.87.0"
|
||||||
}
|
}
|
||||||
|
@ -3151,17 +3183,17 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tar": {
|
"tar": {
|
||||||
"version": "4.4.8",
|
"version": "4.4.10",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz",
|
||||||
"integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
|
"integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chownr": "^1.1.1",
|
"chownr": "^1.1.1",
|
||||||
"fs-minipass": "^1.2.5",
|
"fs-minipass": "^1.2.5",
|
||||||
"minipass": "^2.3.4",
|
"minipass": "^2.3.5",
|
||||||
"minizlib": "^1.1.1",
|
"minizlib": "^1.2.1",
|
||||||
"mkdirp": "^0.5.0",
|
"mkdirp": "^0.5.0",
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.2"
|
"yallist": "^3.0.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
|
|
|
@ -19,10 +19,11 @@
|
||||||
"humanize-duration": "^3.12.1",
|
"humanize-duration": "^3.12.1",
|
||||||
"json5": "^1.0.1",
|
"json5": "^1.0.1",
|
||||||
"knex": "^0.15.2",
|
"knex": "^0.15.2",
|
||||||
|
"knub-command-manager": "^3.1.2",
|
||||||
"mime": "^2.3.1",
|
"mime": "^2.3.1",
|
||||||
"moment": "^2.21.0",
|
"moment": "^2.21.0",
|
||||||
"public-ip": "^2.0.1",
|
"public-ip": "^2.0.1",
|
||||||
"sqlite3": "^4.0.6",
|
"sqlite3": "^4.0.9",
|
||||||
"tmp": "0.0.33",
|
"tmp": "0.0.33",
|
||||||
"transliteration": "^1.6.2",
|
"transliteration": "^1.6.2",
|
||||||
"uuid": "^3.1.0"
|
"uuid": "^3.1.0"
|
||||||
|
|
10
src/bot.js
10
src/bot.js
|
@ -1,17 +1,9 @@
|
||||||
const Eris = require('eris');
|
const Eris = require('eris');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
|
|
||||||
const bot = new Eris.CommandClient(config.token, {
|
const bot = new Eris.Client(config.token, {
|
||||||
getAllUsers: true,
|
getAllUsers: true,
|
||||||
restMode: true,
|
restMode: true,
|
||||||
}, {
|
|
||||||
prefix: config.prefix,
|
|
||||||
ignoreSelf: true,
|
|
||||||
ignoreBots: true,
|
|
||||||
defaultHelpCommand: false,
|
|
||||||
defaultCommandOptions: {
|
|
||||||
caseInsensitive: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = bot;
|
module.exports = bot;
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
const { CommandManager, defaultParameterTypes, TypeConversionError } = require('knub-command-manager');
|
||||||
|
const config = require('./config');
|
||||||
|
const utils = require('./utils');
|
||||||
|
const threads = require('./data/threads');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createCommandManager(bot) {
|
||||||
|
const manager = new CommandManager({
|
||||||
|
prefix: config.prefix,
|
||||||
|
types: Object.assign({}, defaultParameterTypes, {
|
||||||
|
userId(value) {
|
||||||
|
const userId = utils.getUserMention(value);
|
||||||
|
if (! userId) throw new TypeConversionError();
|
||||||
|
return userId;
|
||||||
|
},
|
||||||
|
|
||||||
|
delay(value) {
|
||||||
|
const ms = utils.convertDelayStringToMS(value);
|
||||||
|
if (ms === null) throw new TypeConversionError();
|
||||||
|
return ms;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const handlers = {};
|
||||||
|
const aliasMap = new Map();
|
||||||
|
|
||||||
|
bot.on('messageCreate', async msg => {
|
||||||
|
if (msg.author.bot) return;
|
||||||
|
if (msg.author.id === bot.user.id) return;
|
||||||
|
if (! msg.content) return;
|
||||||
|
|
||||||
|
const matchedCommand = await manager.findMatchingCommand(msg.content, { msg });
|
||||||
|
if (matchedCommand === null) return;
|
||||||
|
if (matchedCommand.error !== undefined) {
|
||||||
|
utils.postError(msg.channel, matchedCommand.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allArgs = {};
|
||||||
|
for (const [name, arg] of Object.entries(matchedCommand.args)) {
|
||||||
|
allArgs[name] = arg.value;
|
||||||
|
}
|
||||||
|
for (const [name, opt] of Object.entries(matchedCommand.opts)) {
|
||||||
|
allArgs[name] = opt.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
handlers[matchedCommand.id](msg, allArgs);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a command that can be invoked anywhere
|
||||||
|
*/
|
||||||
|
const addGlobalCommand = (trigger, parameters, handler, commandConfig = {}) => {
|
||||||
|
let aliases = aliasMap.has(trigger) ? [...aliasMap.get(trigger)] : [];
|
||||||
|
if (commandConfig.aliases) aliases.push(...commandConfig.aliases);
|
||||||
|
|
||||||
|
const cmd = manager.add(trigger, parameters, { ...commandConfig, aliases });
|
||||||
|
handlers[cmd.id] = handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a command that can only be invoked on the inbox server
|
||||||
|
*/
|
||||||
|
const addInboxServerCommand = (trigger, parameters, handler, commandConfig = {}) => {
|
||||||
|
const aliases = aliasMap.has(trigger) ? [...aliasMap.get(trigger)] : [];
|
||||||
|
if (commandConfig.aliases) aliases.push(...commandConfig.aliases);
|
||||||
|
|
||||||
|
const cmd = manager.add(trigger, parameters, {
|
||||||
|
...commandConfig,
|
||||||
|
aliases,
|
||||||
|
preFilters: [
|
||||||
|
(_, context) => {
|
||||||
|
if (! utils.messageIsOnInboxServer(context.msg)) return false;
|
||||||
|
if (! utils.isStaff(context.msg.member)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
handlers[cmd.id] = async (msg, args) => {
|
||||||
|
const thread = await threads.findOpenThreadByChannelId(msg.channel.id);
|
||||||
|
handler(msg, args, thread);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a command that can only be invoked in a thread on the inbox server
|
||||||
|
*/
|
||||||
|
const addInboxThreadCommand = (trigger, parameters, handler, commandConfig = {}) => {
|
||||||
|
const aliases = aliasMap.has(trigger) ? [...aliasMap.get(trigger)] : [];
|
||||||
|
if (commandConfig.aliases) aliases.push(...commandConfig.aliases);
|
||||||
|
|
||||||
|
let thread;
|
||||||
|
const cmd = manager.add(trigger, parameters, {
|
||||||
|
...commandConfig,
|
||||||
|
aliases,
|
||||||
|
preFilters: [
|
||||||
|
async (_, context) => {
|
||||||
|
if (! utils.messageIsOnInboxServer(context.msg)) return false;
|
||||||
|
if (! utils.isStaff(context.msg.member)) return false;
|
||||||
|
thread = await threads.findOpenThreadByChannelId(context.msg.channel.id);
|
||||||
|
if (! thread) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
handlers[cmd.id] = async (msg, args) => {
|
||||||
|
handler(msg, args, thread);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const addAlias = (originalCmd, alias) => {
|
||||||
|
if (! aliasMap.has(originalCmd)) {
|
||||||
|
aliasMap.set(originalCmd, new Set());
|
||||||
|
}
|
||||||
|
|
||||||
|
aliasMap.get(originalCmd).add(alias);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
manager,
|
||||||
|
addGlobalCommand,
|
||||||
|
addInboxServerCommand,
|
||||||
|
addInboxThreadCommand,
|
||||||
|
addAlias,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
74
src/main.js
74
src/main.js
|
@ -6,6 +6,8 @@ const bot = require('./bot');
|
||||||
const knex = require('./knex');
|
const knex = require('./knex');
|
||||||
const {messageQueue} = require('./queue');
|
const {messageQueue} = require('./queue');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
|
const { createCommandManager } = require('./commands');
|
||||||
|
|
||||||
const blocked = require('./data/blocked');
|
const blocked = require('./data/blocked');
|
||||||
const threads = require('./data/threads');
|
const threads = require('./data/threads');
|
||||||
const updates = require('./data/updates');
|
const updates = require('./data/updates');
|
||||||
|
@ -182,44 +184,54 @@ bot.on('messageCreate', async msg => {
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
async start() {
|
async start() {
|
||||||
// Load modules
|
// Initialize command manager
|
||||||
console.log('Loading modules...');
|
const commands = createCommandManager(bot);
|
||||||
await reply(bot);
|
|
||||||
await close(bot);
|
|
||||||
await logs(bot);
|
|
||||||
await block(bot);
|
|
||||||
await move(bot);
|
|
||||||
await snippets(bot);
|
|
||||||
await suspend(bot);
|
|
||||||
await greeting(bot);
|
|
||||||
await webserver(bot);
|
|
||||||
await typingProxy(bot);
|
|
||||||
await version(bot);
|
|
||||||
await newthread(bot);
|
|
||||||
await idModule(bot);
|
|
||||||
await alert(bot);
|
|
||||||
|
|
||||||
// Load plugins
|
|
||||||
if (config.plugins && config.plugins.length) {
|
|
||||||
console.log('Loading plugins...');
|
|
||||||
for (const plugin of config.plugins) {
|
|
||||||
const pluginFn = require(`../${plugin}`);
|
|
||||||
pluginFn(bot, knex, config);
|
|
||||||
}
|
|
||||||
console.log(`Loaded ${config.plugins.length} plugin(s)`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.updateNotifications) {
|
|
||||||
updates.startVersionRefreshLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register command aliases
|
// Register command aliases
|
||||||
if (config.commandAliases) {
|
if (config.commandAliases) {
|
||||||
for (const alias in config.commandAliases) {
|
for (const alias in config.commandAliases) {
|
||||||
bot.registerCommandAlias(alias, config.commandAliases[alias]);
|
commands.addAlias(config.commandAliases[alias], alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load modules
|
||||||
|
console.log('Loading plugins...');
|
||||||
|
const builtInPlugins = [
|
||||||
|
reply,
|
||||||
|
close,
|
||||||
|
logs,
|
||||||
|
block,
|
||||||
|
move,
|
||||||
|
snippets,
|
||||||
|
suspend,
|
||||||
|
greeting,
|
||||||
|
webserver,
|
||||||
|
typingProxy,
|
||||||
|
version,
|
||||||
|
newthread,
|
||||||
|
idModule,
|
||||||
|
alert
|
||||||
|
];
|
||||||
|
|
||||||
|
const plugins = [...builtInPlugins];
|
||||||
|
|
||||||
|
if (config.plugins && config.plugins.length) {
|
||||||
|
for (const plugin of config.plugins) {
|
||||||
|
const pluginFn = require(`../${plugin}`);
|
||||||
|
plugins.push(pluginFn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.forEach(pluginFn => {
|
||||||
|
pluginFn(bot, knex, config, commands);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Loaded ${plugins.length} plugins (${builtInPlugins.length} built-in plugins, ${plugins.length - builtInPlugins.length} external plugins)`);
|
||||||
|
|
||||||
|
if (config.updateNotifications) {
|
||||||
|
updates.startVersionRefreshLoop();
|
||||||
|
}
|
||||||
|
|
||||||
// Connect to Discord
|
// Connect to Discord
|
||||||
console.log('Connecting to Discord...');
|
console.log('Connecting to Discord...');
|
||||||
await bot.connect();
|
await bot.connect();
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
const threadUtils = require('../threadUtils');
|
module.exports = (bot, knex, config, commands) => {
|
||||||
|
commands.addInboxThreadCommand('alert', '[opt:string]', async (msg, args, thread) => {
|
||||||
module.exports = bot => {
|
if (args.opt && args.opt.startsWith('c')) {
|
||||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
|
||||||
|
|
||||||
addInboxServerCommand('alert', async (msg, args, thread) => {
|
|
||||||
if (! thread) return;
|
|
||||||
|
|
||||||
if (args[0] && args[0].startsWith('c')) {
|
|
||||||
await thread.setAlert(null);
|
await thread.setAlert(null);
|
||||||
await thread.postSystemMessage(`Cancelled new message alert`);
|
await thread.postSystemMessage(`Cancelled new message alert`);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
const humanizeDuration = require('humanize-duration');
|
const humanizeDuration = require('humanize-duration');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const threadUtils = require('../threadUtils');
|
|
||||||
const blocked = require("../data/blocked");
|
const blocked = require("../data/blocked");
|
||||||
const utils = require("../utils");
|
const utils = require("../utils");
|
||||||
|
|
||||||
module.exports = bot => {
|
module.exports = (bot, knex, config, commands) => {
|
||||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
|
||||||
|
|
||||||
async function removeExpiredBlocks() {
|
async function removeExpiredBlocks() {
|
||||||
const expiredBlocks = await blocked.getExpiredBlocks();
|
const expiredBlocks = await blocked.getExpiredBlocks();
|
||||||
const logChannel = utils.getLogChannel();
|
const logChannel = utils.getLogChannel();
|
||||||
|
@ -28,12 +25,8 @@ module.exports = bot => {
|
||||||
|
|
||||||
bot.on('ready', expiredBlockLoop);
|
bot.on('ready', expiredBlockLoop);
|
||||||
|
|
||||||
addInboxServerCommand('block', async (msg, args, thread) => {
|
const blockCmd = async (msg, args, thread) => {
|
||||||
const firstArgUserId = utils.getUserMention(args[0]);
|
const userIdToBlock = args.userId || (thread && thread.user_id);
|
||||||
const userIdToBlock = firstArgUserId
|
|
||||||
? firstArgUserId
|
|
||||||
: thread && thread.user_id;
|
|
||||||
|
|
||||||
if (! userIdToBlock) return;
|
if (! userIdToBlock) return;
|
||||||
|
|
||||||
const isBlocked = await blocked.isBlocked(userIdToBlock);
|
const isBlocked = await blocked.isBlocked(userIdToBlock);
|
||||||
|
@ -42,29 +35,26 @@ module.exports = bot => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputExpiryTime = firstArgUserId ? args[1] : args[0];
|
const expiresAt = args.blockTime
|
||||||
const expiryTime = inputExpiryTime ? utils.convertDelayStringToMS(inputExpiryTime) : null;
|
? moment.utc().add(args.blockTime, 'ms').format('YYYY-MM-DD HH:mm:ss')
|
||||||
const expiresAt = expiryTime
|
|
||||||
? moment.utc().add(expiryTime, 'ms').format('YYYY-MM-DD HH:mm:ss')
|
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const user = bot.users.get(userIdToBlock);
|
const user = bot.users.get(userIdToBlock);
|
||||||
await blocked.block(userIdToBlock, (user ? `${user.username}#${user.discriminator}` : ''), msg.author.id, expiresAt);
|
await blocked.block(userIdToBlock, (user ? `${user.username}#${user.discriminator}` : ''), msg.author.id, expiresAt);
|
||||||
|
|
||||||
if (expiresAt) {
|
if (expiresAt) {
|
||||||
const humanized = humanizeDuration(expiryTime, { largest: 2, round: true });
|
const humanized = humanizeDuration(args.blockTime, { largest: 2, round: true });
|
||||||
msg.channel.createMessage(`Blocked <@${userIdToBlock}> (id \`${userIdToBlock}\`) from modmail for ${humanized}`);
|
msg.channel.createMessage(`Blocked <@${userIdToBlock}> (id \`${userIdToBlock}\`) from modmail for ${humanized}`);
|
||||||
} else {
|
} else {
|
||||||
msg.channel.createMessage(`Blocked <@${userIdToBlock}> (id \`${userIdToBlock}\`) from modmail indefinitely`);
|
msg.channel.createMessage(`Blocked <@${userIdToBlock}> (id \`${userIdToBlock}\`) from modmail indefinitely`);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
addInboxServerCommand('unblock', async (msg, args, thread) => {
|
commands.addInboxServerCommand('block', '<userId:userId> [blockTime:delay]', blockCmd);
|
||||||
const firstArgUserId = utils.getUserMention(args[0]);
|
commands.addInboxServerCommand('block', '[blockTime:delay]', blockCmd);
|
||||||
const userIdToUnblock = firstArgUserId
|
|
||||||
? firstArgUserId
|
|
||||||
: thread && thread.user_id;
|
|
||||||
|
|
||||||
|
const unblockCmd = async (msg, args, thread) => {
|
||||||
|
const userIdToUnblock = args.userId || (thread && thread.user_id);
|
||||||
if (! userIdToUnblock) return;
|
if (! userIdToUnblock) return;
|
||||||
|
|
||||||
const isBlocked = await blocked.isBlocked(userIdToUnblock);
|
const isBlocked = await blocked.isBlocked(userIdToUnblock);
|
||||||
|
@ -73,28 +63,26 @@ module.exports = bot => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputUnblockDelay = firstArgUserId ? args[1] : args[0];
|
const unblockAt = args.unblockDelay
|
||||||
const unblockDelay = inputUnblockDelay ? utils.convertDelayStringToMS(inputUnblockDelay) : null;
|
? moment.utc().add(args.unblockDelay, 'ms').format('YYYY-MM-DD HH:mm:ss')
|
||||||
const unblockAt = unblockDelay
|
|
||||||
? moment.utc().add(unblockDelay, 'ms').format('YYYY-MM-DD HH:mm:ss')
|
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const user = bot.users.get(userIdToUnblock);
|
const user = bot.users.get(userIdToUnblock);
|
||||||
if (unblockAt) {
|
if (unblockAt) {
|
||||||
const humanized = humanizeDuration(unblockDelay, { largest: 2, round: true });
|
const humanized = humanizeDuration(args.unblockDelay, { largest: 2, round: true });
|
||||||
await blocked.updateExpiryTime(userIdToUnblock, unblockAt);
|
await blocked.updateExpiryTime(userIdToUnblock, unblockAt);
|
||||||
msg.channel.createMessage(`Scheduled <@${userIdToUnblock}> (id \`${userIdToUnblock}\`) to be unblocked in ${humanized}`);
|
msg.channel.createMessage(`Scheduled <@${userIdToUnblock}> (id \`${userIdToUnblock}\`) to be unblocked in ${humanized}`);
|
||||||
} else {
|
} else {
|
||||||
await blocked.unblock(userIdToUnblock);
|
await blocked.unblock(userIdToUnblock);
|
||||||
msg.channel.createMessage(`Unblocked <@${userIdToUnblock}> (id ${userIdToUnblock}) from modmail`);
|
msg.channel.createMessage(`Unblocked <@${userIdToUnblock}> (id ${userIdToUnblock}) from modmail`);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
addInboxServerCommand('is_blocked', async (msg, args, thread) => {
|
commands.addInboxServerCommand('unblock', '<userId:userId> [unblockDelay:delay]', unblockCmd);
|
||||||
const userIdToCheck = args[0]
|
commands.addInboxServerCommand('unblock', '[unblockDelay:delay]', unblockCmd);
|
||||||
? utils.getUserMention(args[0])
|
|
||||||
: thread && thread.user_id;
|
|
||||||
|
|
||||||
|
commands.addInboxServerCommand('is_blocked', '[userId:userId]',async (msg, args, thread) => {
|
||||||
|
const userIdToCheck = args.userId || (thread && thread.user_id);
|
||||||
if (! userIdToCheck) return;
|
if (! userIdToCheck) return;
|
||||||
|
|
||||||
const blockStatus = await blocked.getBlockStatus(userIdToCheck);
|
const blockStatus = await blocked.getBlockStatus(userIdToCheck);
|
||||||
|
|
|
@ -6,7 +6,7 @@ const threads = require('../data/threads');
|
||||||
const blocked = require('../data/blocked');
|
const blocked = require('../data/blocked');
|
||||||
const {messageQueue} = require('../queue');
|
const {messageQueue} = require('../queue');
|
||||||
|
|
||||||
module.exports = bot => {
|
module.exports = (bot, knex, config, commands) => {
|
||||||
// Check for threads that are scheduled to be closed and close them
|
// Check for threads that are scheduled to be closed and close them
|
||||||
async function applyScheduledCloses() {
|
async function applyScheduledCloses() {
|
||||||
const threadsToBeClosed = await threads.getThreadsThatShouldBeClosed();
|
const threadsToBeClosed = await threads.getThreadsThatShouldBeClosed();
|
||||||
|
@ -38,7 +38,7 @@ module.exports = bot => {
|
||||||
scheduledCloseLoop();
|
scheduledCloseLoop();
|
||||||
|
|
||||||
// Close a thread. Closing a thread saves a log of the channel's contents and then deletes the channel.
|
// Close a thread. Closing a thread saves a log of the channel's contents and then deletes the channel.
|
||||||
bot.registerCommand('close', async (msg, args) => {
|
commands.addGlobalCommand('close', '[opts...]', async (msg, args) => {
|
||||||
let thread, closedBy;
|
let thread, closedBy;
|
||||||
|
|
||||||
let hasCloseMessage = !! config.closeMessage;
|
let hasCloseMessage = !! config.closeMessage;
|
||||||
|
@ -68,8 +68,8 @@ module.exports = bot => {
|
||||||
thread = await threads.findOpenThreadByChannelId(msg.channel.id);
|
thread = await threads.findOpenThreadByChannelId(msg.channel.id);
|
||||||
if (! thread) return;
|
if (! thread) return;
|
||||||
|
|
||||||
if (args.length) {
|
if (args.opts && args.opts.length) {
|
||||||
if (args.includes('cancel') || args.includes('c')) {
|
if (args.opts.includes('cancel') || args.opts.includes('c')) {
|
||||||
// Cancel timed close
|
// Cancel timed close
|
||||||
if (thread.scheduled_close_at) {
|
if (thread.scheduled_close_at) {
|
||||||
await thread.cancelScheduledClose();
|
await thread.cancelScheduledClose();
|
||||||
|
@ -80,12 +80,12 @@ module.exports = bot => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Silent close (= no close message)
|
// Silent close (= no close message)
|
||||||
if (args.includes('silent') || args.includes('s')) {
|
if (args.opts.includes('silent') || args.opts.includes('s')) {
|
||||||
silentClose = true;
|
silentClose = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timed close
|
// Timed close
|
||||||
const delayStringArg = args.find(arg => utils.delayStringRegex.test(arg));
|
const delayStringArg = args.opts.find(arg => utils.delayStringRegex.test(arg));
|
||||||
if (delayStringArg) {
|
if (delayStringArg) {
|
||||||
const delay = utils.convertDelayStringToMS(delayStringArg);
|
const delay = utils.convertDelayStringToMS(delayStringArg);
|
||||||
if (delay === 0 || delay === null) {
|
if (delay === 0 || delay === null) {
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
const threadUtils = require("../threadUtils");
|
module.exports = (bot, knex, config, commands) => {
|
||||||
|
commands.addInboxThreadCommand('id', [], async (msg, args, thread) => {
|
||||||
module.exports = bot => {
|
|
||||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
|
||||||
|
|
||||||
addInboxServerCommand('id', async (msg, args, thread) => {
|
|
||||||
if (! thread) return;
|
|
||||||
thread.postSystemMessage(thread.user_id);
|
thread.postSystemMessage(thread.user_id);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,19 +1,12 @@
|
||||||
const threadUtils = require('../threadUtils');
|
|
||||||
const threads = require("../data/threads");
|
const threads = require("../data/threads");
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const utils = require("../utils");
|
const utils = require("../utils");
|
||||||
|
|
||||||
const LOG_LINES_PER_PAGE = 10;
|
const LOG_LINES_PER_PAGE = 10;
|
||||||
|
|
||||||
module.exports = bot => {
|
module.exports = (bot, knex, config, commands) => {
|
||||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
const logsCmd = async (msg, args, thread) => {
|
||||||
|
let userId = args.userId || (thread && thread.user_id);
|
||||||
addInboxServerCommand('logs', async (msg, args, thread) => {
|
|
||||||
const firstArgUserId = utils.getUserMention(args[0]);
|
|
||||||
let userId = firstArgUserId
|
|
||||||
? firstArgUserId
|
|
||||||
: thread && thread.user_id;
|
|
||||||
|
|
||||||
if (! userId) return;
|
if (! userId) return;
|
||||||
|
|
||||||
let userThreads = await threads.getClosedThreadsByUserId(userId);
|
let userThreads = await threads.getClosedThreadsByUserId(userId);
|
||||||
|
@ -28,7 +21,7 @@ module.exports = bot => {
|
||||||
// Pagination
|
// Pagination
|
||||||
const totalUserThreads = userThreads.length;
|
const totalUserThreads = userThreads.length;
|
||||||
const maxPage = Math.ceil(totalUserThreads / LOG_LINES_PER_PAGE);
|
const maxPage = Math.ceil(totalUserThreads / LOG_LINES_PER_PAGE);
|
||||||
const inputPage = firstArgUserId ? args[1] : args[0];
|
const inputPage = args.page;
|
||||||
const page = Math.max(Math.min(inputPage ? parseInt(inputPage, 10) : 1, maxPage), 1); // Clamp page to 1-<max page>
|
const page = Math.max(Math.min(inputPage ? parseInt(inputPage, 10) : 1, maxPage), 1); // Clamp page to 1-<max page>
|
||||||
const isPaginated = totalUserThreads > LOG_LINES_PER_PAGE;
|
const isPaginated = totalUserThreads > LOG_LINES_PER_PAGE;
|
||||||
const start = (page - 1) * LOG_LINES_PER_PAGE;
|
const start = (page - 1) * LOG_LINES_PER_PAGE;
|
||||||
|
@ -59,9 +52,12 @@ module.exports = bot => {
|
||||||
chunks.forEach(lines => {
|
chunks.forEach(lines => {
|
||||||
root = root.then(() => msg.channel.createMessage(lines.join('\n')));
|
root = root.then(() => msg.channel.createMessage(lines.join('\n')));
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
addInboxServerCommand('loglink', async (msg, args, thread) => {
|
commands.addInboxServerCommand('logs', '<userId:userId> [page:number]', logsCmd);
|
||||||
|
commands.addInboxServerCommand('logs', '[page:number]', logsCmd);
|
||||||
|
|
||||||
|
commands.addInboxServerCommand('loglink', [], async (msg, args, thread) => {
|
||||||
if (! thread) {
|
if (! thread) {
|
||||||
thread = await threads.findSuspendedThreadByChannelId(msg.channel.id);
|
thread = await threads.findSuspendedThreadByChannelId(msg.channel.id);
|
||||||
if (! thread) return;
|
if (! thread) return;
|
||||||
|
|
|
@ -1,20 +1,13 @@
|
||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
const Eris = require('eris');
|
const Eris = require('eris');
|
||||||
const threadUtils = require('../threadUtils');
|
|
||||||
const transliterate = require("transliteration");
|
const transliterate = require("transliteration");
|
||||||
const erisEndpoints = require('eris/lib/rest/Endpoints');
|
const erisEndpoints = require('eris/lib/rest/Endpoints');
|
||||||
|
|
||||||
module.exports = bot => {
|
module.exports = (bot, knex, config, commands) => {
|
||||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
|
||||||
|
|
||||||
addInboxServerCommand('move', async (msg, args, thread) => {
|
|
||||||
if (! config.allowMove) return;
|
if (! config.allowMove) return;
|
||||||
|
|
||||||
if (! thread) return;
|
commands.addInboxThreadCommand('move', '<category:string$>', async (msg, args, thread) => {
|
||||||
|
const searchStr = args.category;
|
||||||
const searchStr = args[0];
|
|
||||||
if (! searchStr || searchStr.trim() === '') return;
|
|
||||||
|
|
||||||
const normalizedSearchStr = transliterate.slugify(searchStr);
|
const normalizedSearchStr = transliterate.slugify(searchStr);
|
||||||
|
|
||||||
const categories = msg.channel.guild.channels.filter(c => {
|
const categories = msg.channel.guild.channels.filter(c => {
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
const utils = require("../utils");
|
const utils = require("../utils");
|
||||||
const threadUtils = require("../threadUtils");
|
|
||||||
const threads = require("../data/threads");
|
const threads = require("../data/threads");
|
||||||
|
|
||||||
module.exports = bot => {
|
module.exports = (bot, knex, config, commands) => {
|
||||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
commands.addInboxServerCommand('newthread', '<userId:userId>', async (msg, args, thread) => {
|
||||||
|
const user = bot.users.get(args.userId);
|
||||||
addInboxServerCommand('newthread', async (msg, args, thread) => {
|
|
||||||
if (args.length === 0) return;
|
|
||||||
|
|
||||||
const userId = utils.getUserMention(args[0]);
|
|
||||||
if (! userId) return;
|
|
||||||
|
|
||||||
const user = bot.users.get(userId);
|
|
||||||
if (! user) {
|
if (! user) {
|
||||||
utils.postSystemMessageWithFallback(msg.channel, thread, 'User not found!');
|
utils.postSystemMessageWithFallback(msg.channel, thread, 'User not found!');
|
||||||
return;
|
return;
|
||||||
|
@ -26,8 +18,6 @@ module.exports = bot => {
|
||||||
const createdThread = await threads.createNewThreadForUser(user, true, true);
|
const createdThread = await threads.createNewThreadForUser(user, true, true);
|
||||||
createdThread.postSystemMessage(`Thread was opened by ${msg.author.username}#${msg.author.discriminator}`);
|
createdThread.postSystemMessage(`Thread was opened by ${msg.author.username}#${msg.author.discriminator}`);
|
||||||
|
|
||||||
if (thread) {
|
msg.channel.createMessage(`Thread opened: <#${createdThread.channel_id}>`);
|
||||||
msg.delete();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,29 +1,21 @@
|
||||||
const attachments = require("../data/attachments");
|
const attachments = require("../data/attachments");
|
||||||
const threadUtils = require("../threadUtils");
|
|
||||||
|
|
||||||
module.exports = bot => {
|
|
||||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
|
||||||
|
|
||||||
|
module.exports = (bot, knex, config, commands) => {
|
||||||
// Mods can reply to modmail threads using !r or !reply
|
// Mods can reply to modmail threads using !r or !reply
|
||||||
// These messages get relayed back to the DM thread between the bot and the user
|
// These messages get relayed back to the DM thread between the bot and the user
|
||||||
addInboxServerCommand('reply', async (msg, args, thread) => {
|
commands.addInboxThreadCommand('reply', '<text$>', async (msg, args, thread) => {
|
||||||
if (! thread) return;
|
const replied = await thread.replyToUser(msg.member, args.text, msg.attachments, false);
|
||||||
|
|
||||||
const text = args.join(' ').trim();
|
|
||||||
const replied = await thread.replyToUser(msg.member, text, msg.attachments, false);
|
|
||||||
if (replied) msg.delete();
|
if (replied) msg.delete();
|
||||||
|
}, {
|
||||||
|
aliases: ['r']
|
||||||
});
|
});
|
||||||
|
|
||||||
bot.registerCommandAlias('r', 'reply');
|
|
||||||
|
|
||||||
// Anonymous replies only show the role, not the username
|
// Anonymous replies only show the role, not the username
|
||||||
addInboxServerCommand('anonreply', async (msg, args, thread) => {
|
commands.addInboxThreadCommand('anonreply', '<text$>', async (msg, args, thread) => {
|
||||||
if (! thread) return;
|
const replied = await thread.replyToUser(msg.member, args.text, msg.attachments, true);
|
||||||
|
|
||||||
const text = args.join(' ').trim();
|
|
||||||
const replied = await thread.replyToUser(msg.member, text, msg.attachments, true);
|
|
||||||
if (replied) msg.delete();
|
if (replied) msg.delete();
|
||||||
|
}, {
|
||||||
|
aliases: ['ar']
|
||||||
});
|
});
|
||||||
|
|
||||||
bot.registerCommandAlias('ar', 'anonreply');
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,50 +2,12 @@ const threads = require('../data/threads');
|
||||||
const snippets = require('../data/snippets');
|
const snippets = require('../data/snippets');
|
||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
const utils = require('../utils');
|
const utils = require('../utils');
|
||||||
const threadUtils = require('../threadUtils');
|
const { parseArguments } = require('knub-command-manager');
|
||||||
|
|
||||||
const whitespaceRegex = /\s/;
|
const whitespaceRegex = /\s/;
|
||||||
const quoteChars = ["'", '"'];
|
const quoteChars = ["'", '"'];
|
||||||
|
|
||||||
module.exports = bot => {
|
module.exports = (bot, knex, config, commands) => {
|
||||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a string of arguments, e.g.
|
|
||||||
* arg "quoted arg" with\ some\ escapes
|
|
||||||
* ...to an array of said arguments
|
|
||||||
* @param {String} str
|
|
||||||
* @returns {String[]}
|
|
||||||
*/
|
|
||||||
function parseArgs(str) {
|
|
||||||
const args = [];
|
|
||||||
let current = '';
|
|
||||||
let inQuote = false;
|
|
||||||
let escapeNext = false;
|
|
||||||
|
|
||||||
for (const char of [...str]) {
|
|
||||||
if (escapeNext) {
|
|
||||||
current += char;
|
|
||||||
escapeNext = false;
|
|
||||||
} else if (char === '\\') {
|
|
||||||
escapeNext = true;
|
|
||||||
} else if (! inQuote && whitespaceRegex.test(char)) {
|
|
||||||
args.push(current);
|
|
||||||
current = '';
|
|
||||||
} else if (! inQuote && quoteChars.includes(char)) {
|
|
||||||
inQuote = char;
|
|
||||||
} else if (inQuote && inQuote === char) {
|
|
||||||
inQuote = false;
|
|
||||||
} else {
|
|
||||||
current += char;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current !== '') args.push(current);
|
|
||||||
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Renders" a snippet by replacing all argument placeholders e.g. {1} {2} with their corresponding arguments.
|
* "Renders" a snippet by replacing all argument placeholders e.g. {1} {2} with their corresponding arguments.
|
||||||
* The number in the placeholder is the argument's order in the argument list, i.e. {1} is the first argument (= index 0)
|
* The number in the placeholder is the argument's order in the argument list, i.e. {1} is the first argument (= index 0)
|
||||||
|
@ -104,7 +66,8 @@ module.exports = bot => {
|
||||||
const snippet = await snippets.get(trigger);
|
const snippet = await snippets.get(trigger);
|
||||||
if (! snippet) return;
|
if (! snippet) return;
|
||||||
|
|
||||||
const args = rawArgs ? parseArgs(rawArgs) : [];
|
let args = rawArgs ? parseArguments(rawArgs) : [];
|
||||||
|
args = args.map(arg => arg.value);
|
||||||
const rendered = renderSnippet(snippet.body, args);
|
const rendered = renderSnippet(snippet.body, args);
|
||||||
|
|
||||||
const replied = await thread.replyToUser(msg.member, rendered, [], isAnonymous);
|
const replied = await thread.replyToUser(msg.member, rendered, [], isAnonymous);
|
||||||
|
@ -112,73 +75,60 @@ module.exports = bot => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show or add a snippet
|
// Show or add a snippet
|
||||||
addInboxServerCommand('snippet', async (msg, args, thread) => {
|
commands.addInboxServerCommand('snippet', '<trigger> [text$]', async (msg, args, thread) => {
|
||||||
const trigger = args[0];
|
const snippet = await snippets.get(args.trigger);
|
||||||
if (! trigger) return
|
|
||||||
|
|
||||||
const text = args.slice(1).join(' ').trim();
|
|
||||||
const snippet = await snippets.get(trigger);
|
|
||||||
|
|
||||||
if (snippet) {
|
if (snippet) {
|
||||||
if (text) {
|
if (args.text) {
|
||||||
// If the snippet exists and we're trying to create a new one, inform the user the snippet already exists
|
// If the snippet exists and we're trying to create a new one, inform the user the snippet already exists
|
||||||
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${trigger}" already exists! You can edit or delete it with ${config.prefix}edit_snippet and ${config.prefix}delete_snippet respectively.`);
|
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${args.trigger}" already exists! You can edit or delete it with ${config.prefix}edit_snippet and ${config.prefix}delete_snippet respectively.`);
|
||||||
} else {
|
} else {
|
||||||
// If the snippet exists and we're NOT trying to create a new one, show info about the existing snippet
|
// If the snippet exists and we're NOT trying to create a new one, show info about the existing snippet
|
||||||
utils.postSystemMessageWithFallback(msg.channel, thread, `\`${config.snippetPrefix}${trigger}\` replies with:\n${snippet.body}`);
|
utils.postSystemMessageWithFallback(msg.channel, thread, `\`${config.snippetPrefix}${args.trigger}\` replies with: \`\`\`${utils.disableCodeBlocks(snippet.body)}\`\`\``);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (text) {
|
if (args.text) {
|
||||||
// If the snippet doesn't exist and the user wants to create it, create it
|
// If the snippet doesn't exist and the user wants to create it, create it
|
||||||
await snippets.add(trigger, text, msg.author.id);
|
await snippets.add(args.trigger, args.text, msg.author.id);
|
||||||
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${trigger}" created!`);
|
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${args.trigger}" created!`);
|
||||||
} else {
|
} else {
|
||||||
// If the snippet doesn't exist and the user isn't trying to create it, inform them how to create it
|
// If the snippet doesn't exist and the user isn't trying to create it, inform them how to create it
|
||||||
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${trigger}" doesn't exist! You can create it with \`${config.prefix}snippet ${trigger} text\``);
|
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${args.trigger}" doesn't exist! You can create it with \`${config.prefix}snippet ${args.trigger} text\``);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
aliases: ['s']
|
||||||
});
|
});
|
||||||
|
|
||||||
bot.registerCommandAlias('s', 'snippet');
|
commands.addInboxServerCommand('delete_snippet', '<trigger>', async (msg, args, thread) => {
|
||||||
|
const snippet = await snippets.get(args.trigger);
|
||||||
addInboxServerCommand('delete_snippet', async (msg, args, thread) => {
|
|
||||||
const trigger = args[0];
|
|
||||||
if (! trigger) return;
|
|
||||||
|
|
||||||
const snippet = await snippets.get(trigger);
|
|
||||||
if (! snippet) {
|
if (! snippet) {
|
||||||
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${trigger}" doesn't exist!`);
|
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${args.trigger}" doesn't exist!`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await snippets.del(trigger);
|
await snippets.del(args.trigger);
|
||||||
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${trigger}" deleted!`);
|
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${args.trigger}" deleted!`);
|
||||||
|
}, {
|
||||||
|
aliases: ['ds']
|
||||||
});
|
});
|
||||||
|
|
||||||
bot.registerCommandAlias('ds', 'delete_snippet');
|
commands.addInboxServerCommand('edit_snippet', '<trigger> [text$]', async (msg, args, thread) => {
|
||||||
|
const snippet = await snippets.get(args.trigger);
|
||||||
addInboxServerCommand('edit_snippet', async (msg, args, thread) => {
|
|
||||||
const trigger = args[0];
|
|
||||||
if (! trigger) return;
|
|
||||||
|
|
||||||
const text = args.slice(1).join(' ').trim();
|
|
||||||
if (! text) return;
|
|
||||||
|
|
||||||
const snippet = await snippets.get(trigger);
|
|
||||||
if (! snippet) {
|
if (! snippet) {
|
||||||
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${trigger}" doesn't exist!`);
|
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${args.trigger}" doesn't exist!`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await snippets.del(trigger);
|
await snippets.del(args.trigger);
|
||||||
await snippets.add(trigger, text, msg.author.id);
|
await snippets.add(args.trigger, args.text, msg.author.id);
|
||||||
|
|
||||||
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${trigger}" edited!`);
|
utils.postSystemMessageWithFallback(msg.channel, thread, `Snippet "${args.trigger}" edited!`);
|
||||||
|
}, {
|
||||||
|
aliases: ['es']
|
||||||
});
|
});
|
||||||
|
|
||||||
bot.registerCommandAlias('es', 'edit_snippet');
|
commands.addInboxServerCommand('snippets', [], async (msg, args, thread) => {
|
||||||
|
|
||||||
addInboxServerCommand('snippets', async (msg, args, thread) => {
|
|
||||||
const allSnippets = await snippets.all();
|
const allSnippets = await snippets.all();
|
||||||
const triggers = allSnippets.map(s => s.trigger);
|
const triggers = allSnippets.map(s => s.trigger);
|
||||||
triggers.sort();
|
triggers.sort();
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const threadUtils = require('../threadUtils');
|
|
||||||
const threads = require("../data/threads");
|
const threads = require("../data/threads");
|
||||||
const utils = require('../utils');
|
const utils = require('../utils');
|
||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
|
|
||||||
const {THREAD_STATUS} = require('../data/constants');
|
const {THREAD_STATUS} = require('../data/constants');
|
||||||
|
|
||||||
module.exports = bot => {
|
module.exports = (bot, knex, config, commands) => {
|
||||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
|
||||||
|
|
||||||
// Check for threads that are scheduled to be suspended and suspend them
|
// Check for threads that are scheduled to be suspended and suspend them
|
||||||
async function applyScheduledSuspensions() {
|
async function applyScheduledSuspensions() {
|
||||||
const threadsToBeSuspended = await threads.getThreadsThatShouldBeSuspended();
|
const threadsToBeSuspended = await threads.getThreadsThatShouldBeSuspended();
|
||||||
|
@ -32,46 +29,41 @@ module.exports = bot => {
|
||||||
|
|
||||||
scheduledSuspendLoop();
|
scheduledSuspendLoop();
|
||||||
|
|
||||||
addInboxServerCommand('suspend', async (msg, args, thread) => {
|
commands.addInboxThreadCommand('suspend cancel', [], async (msg, args, thread) => {
|
||||||
if (! thread) return;
|
|
||||||
|
|
||||||
if (args.length) {
|
|
||||||
// Cancel timed suspend
|
|
||||||
if (args.includes('cancel') || args.includes('c')) {
|
|
||||||
// Cancel timed suspend
|
// Cancel timed suspend
|
||||||
if (thread.scheduled_suspend_at) {
|
if (thread.scheduled_suspend_at) {
|
||||||
await thread.cancelScheduledSuspend();
|
await thread.cancelScheduledSuspend();
|
||||||
thread.postSystemMessage(`Cancelled scheduled suspension`);
|
thread.postSystemMessage(`Cancelled scheduled suspension`);
|
||||||
|
} else {
|
||||||
|
thread.postSystemMessage(`Thread is not scheduled to be suspended`);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return;
|
commands.addInboxThreadCommand('suspend', '[delay:delay]', async (msg, args, thread) => {
|
||||||
}
|
if (args.delay) {
|
||||||
|
const suspendAt = moment.utc().add(args.delay, 'ms');
|
||||||
// Timed suspend
|
|
||||||
const delayStringArg = args.find(arg => utils.delayStringRegex.test(arg));
|
|
||||||
if (delayStringArg) {
|
|
||||||
const delay = utils.convertDelayStringToMS(delayStringArg);
|
|
||||||
if (delay === 0 || delay === null) {
|
|
||||||
thread.postSystemMessage(`Invalid delay specified. Format: "1h30m"`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const suspendAt = moment.utc().add(delay, 'ms');
|
|
||||||
await thread.scheduleSuspend(suspendAt.format('YYYY-MM-DD HH:mm:ss'), msg.author);
|
await thread.scheduleSuspend(suspendAt.format('YYYY-MM-DD HH:mm:ss'), msg.author);
|
||||||
|
|
||||||
thread.postSystemMessage(`Thread will be suspended in ${utils.humanizeDelay(delay)}. Use \`${config.prefix}suspend cancel\` to cancel.`);
|
thread.postSystemMessage(`Thread will be suspended in ${utils.humanizeDelay(args.delay)}. Use \`${config.prefix}suspend cancel\` to cancel.`);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
await thread.suspend();
|
await thread.suspend();
|
||||||
thread.postSystemMessage(`**Thread suspended!** This thread will act as closed until unsuspended with \`!unsuspend\``);
|
thread.postSystemMessage(`**Thread suspended!** This thread will act as closed until unsuspended with \`!unsuspend\``);
|
||||||
});
|
});
|
||||||
|
|
||||||
addInboxServerCommand('unsuspend', async msg => {
|
commands.addInboxServerCommand('unsuspend', [], async (msg, args, thread) => {
|
||||||
const thread = await threads.findSuspendedThreadByChannelId(msg.channel.id);
|
if (thread) {
|
||||||
if (! thread) return;
|
thread.postSystemMessage(`Thread is not suspended`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread = await threads.findSuspendedThreadByChannelId(msg.channel.id);
|
||||||
|
if (! thread) {
|
||||||
|
thread.postSystemMessage(`Not in a thread`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const otherOpenThread = await threads.findOpenThreadByUserId(thread.user_id);
|
const otherOpenThread = await threads.findOpenThreadByUserId(thread.user_id);
|
||||||
if (otherOpenThread) {
|
if (otherOpenThread) {
|
||||||
|
|
|
@ -2,7 +2,6 @@ const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const {promisify} = require('util');
|
const {promisify} = require('util');
|
||||||
const utils = require("../utils");
|
const utils = require("../utils");
|
||||||
const threadUtils = require("../threadUtils");
|
|
||||||
const updates = require('../data/updates');
|
const updates = require('../data/updates');
|
||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
|
|
||||||
|
@ -11,10 +10,8 @@ const readFile = promisify(fs.readFile);
|
||||||
|
|
||||||
const GIT_DIR = path.join(__dirname, '..', '..', '.git');
|
const GIT_DIR = path.join(__dirname, '..', '..', '.git');
|
||||||
|
|
||||||
module.exports = bot => {
|
module.exports = (bot, knex, config, commands) => {
|
||||||
const addInboxServerCommand = (...args) => threadUtils.addInboxServerCommand(bot, ...args);
|
commands.addInboxServerCommand('version', [], async (msg, args, thread) => {
|
||||||
|
|
||||||
addInboxServerCommand('version', async (msg, args, thread) => {
|
|
||||||
const packageJson = require('../../package.json');
|
const packageJson = require('../../package.json');
|
||||||
const packageVersion = packageJson.version;
|
const packageVersion = packageJson.version;
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
const threads = require('./data/threads');
|
|
||||||
const utils = require("./utils");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a command that can only be triggered on the inbox server.
|
|
||||||
* Command handlers added with this function also get the thread the message was posted in as a third argument, if any.
|
|
||||||
* @param {Eris~CommandClient} bot
|
|
||||||
* @param {String} cmd
|
|
||||||
* @param {Function} commandHandler
|
|
||||||
* @param {Eris~CommandOptions} opts
|
|
||||||
*/
|
|
||||||
function addInboxServerCommand(bot, cmd, commandHandler, opts) {
|
|
||||||
bot.registerCommand(cmd, async (msg, args) => {
|
|
||||||
if (! utils.messageIsOnInboxServer(msg)) return;
|
|
||||||
if (! utils.isStaff(msg.member)) return;
|
|
||||||
|
|
||||||
const thread = await threads.findOpenThreadByChannelId(msg.channel.id);
|
|
||||||
commandHandler(msg, args, thread);
|
|
||||||
}, opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
addInboxServerCommand
|
|
||||||
};
|
|
13
src/utils.js
13
src/utils.js
|
@ -65,10 +65,10 @@ function postLog(...args) {
|
||||||
getLogChannel().createMessage(...args);
|
getLogChannel().createMessage(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
function postError(str) {
|
function postError(channel, str, opts = {}) {
|
||||||
getLogChannel().createMessage({
|
return channel.createMessage({
|
||||||
content: `${getInboxMention()}**Error:** ${str.trim()}`,
|
...opts,
|
||||||
disableEveryone: false
|
content: `⚠ ${str}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,6 +306,10 @@ function escapeMarkdown(str) {
|
||||||
return str.replace(markdownCharsRegex, '\\$1');
|
return str.replace(markdownCharsRegex, '\\$1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function disableCodeBlocks(str) {
|
||||||
|
return str.replace(/`/g, "`\u200b");
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
BotError,
|
BotError,
|
||||||
|
|
||||||
|
@ -341,4 +345,5 @@ module.exports = {
|
||||||
humanizeDelay,
|
humanizeDelay,
|
||||||
|
|
||||||
escapeMarkdown,
|
escapeMarkdown,
|
||||||
|
disableCodeBlocks,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue