Fix user nicknames. Don't require manageRoles permission by default anymore (moved to config).

master
Miikka Virtanen 2017-08-03 21:50:41 +03:00
parent 3b33cde517
commit 4963ba6a39
3 changed files with 94 additions and 85 deletions

101
package-lock.json generated
View File

@ -37,12 +37,6 @@
"json-stable-stringify": "1.0.1" "json-stable-stringify": "1.0.1"
} }
}, },
"ajv-keywords": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz",
"integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=",
"dev": true
},
"ansi-escapes": { "ansi-escapes": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
@ -161,9 +155,9 @@
} }
}, },
"circular-json": { "circular-json": {
"version": "0.3.2", "version": "0.3.3",
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.2.tgz", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
"integrity": "sha512-KXNXs9gb8kzOqiEdneVsH0YO4cy1bBs7iCHSoKRx6gCtNkNTyLW6pGeCySCdcITqMkFVY0vV0A2s8o/X6rz7zQ==", "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
"dev": true "dev": true
}, },
"cli-cursor": { "cli-cursor": {
@ -252,7 +246,7 @@
"requires": { "requires": {
"lru-cache": "4.1.1", "lru-cache": "4.1.1",
"shebang-command": "1.2.0", "shebang-command": "1.2.0",
"which": "1.2.14" "which": "1.3.0"
} }
}, },
"d": { "d": {
@ -261,7 +255,7 @@
"integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
"dev": true, "dev": true,
"requires": { "requires": {
"es5-ext": "0.10.24" "es5-ext": "0.10.26"
} }
}, },
"debug": { "debug": {
@ -332,11 +326,13 @@
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
}, },
"eris": { "eris": {
"version": "github:abalabahaha/eris#39733fc6fadd8bf648bf713e5e5f990809e03849", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/eris/-/eris-0.7.0.tgz",
"integrity": "sha1-dMorOxhBhWHXWQqEnMsuWKiBsnk=",
"requires": { "requires": {
"opusscript": "0.0.3", "opusscript": "0.0.3",
"tweetnacl": "1.0.0", "tweetnacl": "1.0.0",
"ws": "3.0.0" "ws": "2.3.1"
} }
}, },
"error-ex": { "error-ex": {
@ -348,9 +344,9 @@
} }
}, },
"es5-ext": { "es5-ext": {
"version": "0.10.24", "version": "0.10.26",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.26.tgz",
"integrity": "sha1-pVh3yZJLwMjZvTwsvhdJWsFwmxQ=", "integrity": "sha1-UbISilMbcMT2dkCTpzy+u4IYY3I=",
"dev": true, "dev": true,
"requires": { "requires": {
"es6-iterator": "2.0.1", "es6-iterator": "2.0.1",
@ -364,7 +360,7 @@
"dev": true, "dev": true,
"requires": { "requires": {
"d": "1.0.0", "d": "1.0.0",
"es5-ext": "0.10.24", "es5-ext": "0.10.26",
"es6-symbol": "3.1.1" "es6-symbol": "3.1.1"
} }
}, },
@ -375,7 +371,7 @@
"dev": true, "dev": true,
"requires": { "requires": {
"d": "1.0.0", "d": "1.0.0",
"es5-ext": "0.10.24", "es5-ext": "0.10.26",
"es6-iterator": "2.0.1", "es6-iterator": "2.0.1",
"es6-set": "0.1.5", "es6-set": "0.1.5",
"es6-symbol": "3.1.1", "es6-symbol": "3.1.1",
@ -389,7 +385,7 @@
"dev": true, "dev": true,
"requires": { "requires": {
"d": "1.0.0", "d": "1.0.0",
"es5-ext": "0.10.24", "es5-ext": "0.10.26",
"es6-iterator": "2.0.1", "es6-iterator": "2.0.1",
"es6-symbol": "3.1.1", "es6-symbol": "3.1.1",
"event-emitter": "0.3.5" "event-emitter": "0.3.5"
@ -402,7 +398,7 @@
"dev": true, "dev": true,
"requires": { "requires": {
"d": "1.0.0", "d": "1.0.0",
"es5-ext": "0.10.24" "es5-ext": "0.10.26"
} }
}, },
"es6-weak-map": { "es6-weak-map": {
@ -412,7 +408,7 @@
"dev": true, "dev": true,
"requires": { "requires": {
"d": "1.0.0", "d": "1.0.0",
"es5-ext": "0.10.24", "es5-ext": "0.10.26",
"es6-iterator": "2.0.1", "es6-iterator": "2.0.1",
"es6-symbol": "3.1.1" "es6-symbol": "3.1.1"
} }
@ -459,7 +455,7 @@
"inquirer": "0.12.0", "inquirer": "0.12.0",
"is-my-json-valid": "2.16.0", "is-my-json-valid": "2.16.0",
"is-resolvable": "1.0.0", "is-resolvable": "1.0.0",
"js-yaml": "3.9.0", "js-yaml": "3.9.1",
"json-stable-stringify": "1.0.1", "json-stable-stringify": "1.0.1",
"levn": "0.3.0", "levn": "0.3.0",
"lodash": "4.17.4", "lodash": "4.17.4",
@ -532,7 +528,7 @@
"dev": true, "dev": true,
"requires": { "requires": {
"d": "1.0.0", "d": "1.0.0",
"es5-ext": "0.10.24" "es5-ext": "0.10.26"
} }
}, },
"execa": { "execa": {
@ -595,7 +591,7 @@
"integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=",
"dev": true, "dev": true,
"requires": { "requires": {
"circular-json": "0.3.2", "circular-json": "0.3.3",
"del": "2.2.2", "del": "2.2.2",
"graceful-fs": "4.1.11", "graceful-fs": "4.1.11",
"write": "0.2.1" "write": "0.2.1"
@ -752,9 +748,22 @@
"readline2": "1.0.1", "readline2": "1.0.1",
"run-async": "0.1.0", "run-async": "0.1.0",
"rx-lite": "3.1.2", "rx-lite": "3.1.2",
"string-width": "2.1.1", "string-width": "1.0.2",
"strip-ansi": "3.0.1", "strip-ansi": "3.0.1",
"through": "2.3.8" "through": "2.3.8"
},
"dependencies": {
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
}
} }
}, },
"interpret": { "interpret": {
@ -891,9 +900,9 @@
"dev": true "dev": true
}, },
"js-yaml": { "js-yaml": {
"version": "3.9.0", "version": "3.9.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.0.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz",
"integrity": "sha512-0LoUNELX4S+iofCT8f4uEHIiRBR+c2AINyC8qRWfC6QNruLtxVZRJaPcu/xwMgFIgDxF25tGHaDjvxzJCNE9yw==", "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==",
"dev": true, "dev": true,
"requires": { "requires": {
"argparse": "1.0.9", "argparse": "1.0.9",
@ -1051,7 +1060,7 @@
"requires": { "requires": {
"hosted-git-info": "2.5.0", "hosted-git-info": "2.5.0",
"is-builtin-module": "1.0.0", "is-builtin-module": "1.0.0",
"semver": "5.3.0", "semver": "5.4.1",
"validate-npm-package-license": "3.0.1" "validate-npm-package-license": "3.0.1"
} }
}, },
@ -1311,7 +1320,7 @@
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
"dev": true, "dev": true,
"requires": { "requires": {
"resolve": "1.3.3" "resolve": "1.4.0"
} }
}, },
"require-directory": { "require-directory": {
@ -1335,9 +1344,9 @@
} }
}, },
"resolve": { "resolve": {
"version": "1.3.3", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz",
"integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"path-parse": "1.0.5" "path-parse": "1.0.5"
@ -1389,9 +1398,9 @@
"integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c="
}, },
"semver": { "semver": {
"version": "5.3.0", "version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg=="
}, },
"set-blocking": { "set-blocking": {
"version": "2.0.0", "version": "2.0.0",
@ -1545,6 +1554,14 @@
"lodash": "4.17.4", "lodash": "4.17.4",
"slice-ansi": "0.0.4", "slice-ansi": "0.0.4",
"string-width": "2.1.1" "string-width": "2.1.1"
},
"dependencies": {
"ajv-keywords": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz",
"integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=",
"dev": true
}
} }
}, },
"text-table": { "text-table": {
@ -1642,9 +1659,9 @@
} }
}, },
"which": { "which": {
"version": "1.2.14", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
"integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
"requires": { "requires": {
"isexe": "2.0.0" "isexe": "2.0.0"
} }
@ -1697,9 +1714,9 @@
} }
}, },
"ws": { "ws": {
"version": "3.0.0", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.0.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-2.3.1.tgz",
"integrity": "sha1-mN2wAFbIOQy3Ued4h4hJf5kQO2w=", "integrity": "sha1-a5Sz5EfLajY/eF6vlK9jWejoHIA=",
"requires": { "requires": {
"safe-buffer": "5.0.1", "safe-buffer": "5.0.1",
"ultron": "1.1.0" "ultron": "1.1.0"

View File

@ -10,7 +10,7 @@
}, },
"author": "", "author": "",
"dependencies": { "dependencies": {
"eris": "github:abalabahaha/eris#dev", "eris": "^0.7.0",
"humanize-duration": "^3.10.0", "humanize-duration": "^3.10.0",
"mime": "^1.3.4", "mime": "^1.3.4",
"moment": "^2.17.1", "moment": "^2.17.1",

View File

@ -27,10 +27,6 @@ const bot = new Eris.CommandClient(config.token, {}, {
}, },
}); });
const restBot = new Eris.Client(`Bot ${config.token}`, {
restMode: true,
});
const messageQueue = new Queue(); const messageQueue = new Queue();
bot.on('ready', () => { bot.on('ready', () => {
@ -38,9 +34,10 @@ bot.on('ready', () => {
console.log('Bot started, listening to DMs'); console.log('Bot started, listening to DMs');
}); });
restBot.on('ready', () => { function isStaff(member) {
console.log('Rest client ready'); if (! config.inboxServerPermission) return true;
}); return member.permission.has(config.inboxServerPermission);
}
function formatAttachment(attachment) { function formatAttachment(attachment) {
let filesize = attachment.size || 0; let filesize = attachment.size || 0;
@ -56,7 +53,7 @@ if (config.alwaysReply) {
bot.on('messageCreate', msg => { bot.on('messageCreate', msg => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
if (msg.author.bot) return; if (msg.author.bot) return;
if (msg.content[0] == bot.commandOptions.prefix) return; if (msg.content[0] == bot.commandOptions.prefix) return;
@ -138,14 +135,12 @@ Here's what their message contained:
// If the thread was just created, do some extra stuff // If the thread was just created, do some extra stuff
if (thread._wasCreated) { if (thread._wasCreated) {
const mainGuild = utils.getMainGuild(restBot); const mainGuild = utils.getMainGuild(restBot);
const memberPromise = (mainGuild ? mainGuild.getRESTMember(msg.author.id) : Promise.resolve()); const member = utils.getMainGuild(bot).members.get(msg.author.id);
threadInitDonePromise = memberPromise if (! member) {
.catch(err => {
console.log(`Member ${msg.author.id} not found in main guild ${config.mainGuildId}`); console.log(`Member ${msg.author.id} not found in main guild ${config.mainGuildId}`);
console.error(String(err)); }
})
.then(member => {
let mainGuildNickname = null; let mainGuildNickname = null;
if (member && member.nick) mainGuildNickname = member.nick; if (member && member.nick) mainGuildNickname = member.nick;
else if (member && member.user) mainGuildNickname = member.user.username; else if (member && member.user) mainGuildNickname = member.user.username;
@ -156,9 +151,7 @@ Here's what their message contained:
const accountAge = humanizeDuration(Date.now() - msg.author.createdAt, {largest: 2}); const accountAge = humanizeDuration(Date.now() - msg.author.createdAt, {largest: 2});
const infoHeader = `ACCOUNT AGE **${accountAge}**, ID **${msg.author.id}**, NICKNAME **${mainGuildNickname}**, LOGS **${userLogs.length}**\n-------------------------------`; const infoHeader = `ACCOUNT AGE **${accountAge}**, ID **${msg.author.id}**, NICKNAME **${mainGuildNickname}**, LOGS **${userLogs.length}**\n-------------------------------`;
return bot.createMessage(thread.channelId, infoHeader); return bot.createMessage(thread.channelId, infoHeader).then(() => {
})
.then(() => {
// Ping mods of the new thread // Ping mods of the new thread
bot.createMessage(thread.channelId, { bot.createMessage(thread.channelId, {
content: `@here New modmail thread (${msg.author.username}#${msg.author.discriminator})`, content: `@here New modmail thread (${msg.author.username}#${msg.author.discriminator})`,
@ -294,7 +287,7 @@ function reply(msg, text, anonymous = false) {
bot.registerCommand('reply', (msg, args) => { bot.registerCommand('reply', (msg, args) => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
const text = args.join(' ').trim(); const text = args.join(' ').trim();
reply(msg, text, false); reply(msg, text, false);
@ -306,7 +299,7 @@ bot.registerCommandAlias('r', 'reply');
bot.registerCommand('anonreply', (msg, args) => { bot.registerCommand('anonreply', (msg, args) => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
const text = args.join(' ').trim(); const text = args.join(' ').trim();
reply(msg, text, true); reply(msg, text, true);
@ -317,7 +310,7 @@ bot.registerCommandAlias('ar', 'anonreply');
bot.registerCommand('close', (msg, args) => { bot.registerCommand('close', (msg, args) => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
threads.getByChannelId(msg.channel.id).then(thread => { threads.getByChannelId(msg.channel.id).then(thread => {
if (! thread) return; if (! thread) return;
@ -347,7 +340,7 @@ Logs: <${url}>`;
bot.registerCommand('block', (msg, args) => { bot.registerCommand('block', (msg, args) => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
function block(userId) { function block(userId) {
blocked.block(userId).then(() => { blocked.block(userId).then(() => {
@ -371,7 +364,7 @@ bot.registerCommand('block', (msg, args) => {
bot.registerCommand('unblock', (msg, args) => { bot.registerCommand('unblock', (msg, args) => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
function unblock(userId) { function unblock(userId) {
blocked.unblock(userId).then(() => { blocked.unblock(userId).then(() => {
@ -395,7 +388,7 @@ bot.registerCommand('unblock', (msg, args) => {
bot.registerCommand('logs', (msg, args) => { bot.registerCommand('logs', (msg, args) => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
function getLogs(userId) { function getLogs(userId) {
logs.getLogsWithUrlByUserId(userId).then(infos => { logs.getLogsWithUrlByUserId(userId).then(infos => {
@ -434,7 +427,7 @@ bot.registerCommand('logs', (msg, args) => {
bot.on('messageCreate', async msg => { bot.on('messageCreate', async msg => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
if (msg.author.bot) return; if (msg.author.bot) return;
if (! msg.content) return; if (! msg.content) return;
if (! msg.content.startsWith(snippetPrefix)) return; if (! msg.content.startsWith(snippetPrefix)) return;
@ -450,7 +443,7 @@ bot.on('messageCreate', async msg => {
bot.registerCommand('snippet', async (msg, args) => { bot.registerCommand('snippet', async (msg, args) => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
const shortcut = args[0]; const shortcut = args[0];
const text = args.slice(1).join(' ').trim(); const text = args.slice(1).join(' ').trim();
@ -483,7 +476,7 @@ bot.registerCommandAlias('s', 'snippet');
bot.registerCommand('delete_snippet', async (msg, args) => { bot.registerCommand('delete_snippet', async (msg, args) => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
const shortcut = args[0]; const shortcut = args[0];
if (! shortcut) return; if (! shortcut) return;
@ -502,7 +495,7 @@ bot.registerCommandAlias('ds', 'delete_snippet');
bot.registerCommand('edit_snippet', async (msg, args) => { bot.registerCommand('edit_snippet', async (msg, args) => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
const shortcut = args[0]; const shortcut = args[0];
const text = args.slice(1).join(' ').trim(); const text = args.slice(1).join(' ').trim();
@ -526,7 +519,7 @@ bot.registerCommandAlias('es', 'edit_snippet');
bot.registerCommand('snippets', async msg => { bot.registerCommand('snippets', async msg => {
if (! msg.channel.guild) return; if (! msg.channel.guild) return;
if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return; if (msg.channel.guild.id !== utils.getModmailGuild(bot).id) return;
if (! msg.member.permission.has('manageRoles')) return; if (! isStaff(msg.member)) return;
const allSnippets = await snippets.all(); const allSnippets = await snippets.all();
const shortcuts = Object.keys(allSnippets); const shortcuts = Object.keys(allSnippets);
@ -536,6 +529,5 @@ bot.registerCommand('snippets', async msg => {
}); });
bot.connect(); bot.connect();
restBot.connect();
webserver.run(); webserver.run();
greeting.init(bot); greeting.init(bot);