From 9e7c34ae62e06a4603acda7ec6d3d0b2f1ae0c1d Mon Sep 17 00:00:00 2001 From: vzwGrey Date: Mon, 24 Oct 2016 18:44:56 +0200 Subject: [PATCH 01/51] Added padding to help command --- commands/System/help.js | 8 +++++++- functions/pad.js | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 functions/pad.js diff --git a/commands/System/help.js b/commands/System/help.js index ad4dcdbc..5517a2f0 100644 --- a/commands/System/help.js +++ b/commands/System/help.js @@ -1,3 +1,5 @@ +const pad = require("../../functions/pad.js"); + exports.run = (client, msg, [cmd]) => { if (!cmd) { let helpMessage = []; @@ -7,9 +9,13 @@ exports.run = (client, msg, [cmd]) => { for(let [subCategory, commands] of subCategories) { helpMessage.push(`= ${subCategory} =`); client.funcs.log(`There are ${commands.size} commands in ${subCategory}`); + + let commandNames = Array.from(commands.keys()); + let longest = commandNames.reduce((longest, name) => Math.max(longest, name.length), 0); + for(let [command, description] of commands) { client.funcs.log(`Help command for ${command} :: ${description}`); - helpMessage.push(`${command} :: ${description}`); + helpMessage.push(`${pad(command + "::", longest + 2)} ${description}`); } helpMessage.push(" "); } diff --git a/functions/pad.js b/functions/pad.js new file mode 100644 index 00000000..fe92c4f6 --- /dev/null +++ b/functions/pad.js @@ -0,0 +1,3 @@ +module.exports = (str, length) => { + return str + " ".repeat(length - str.length); +}; \ No newline at end of file From dd2a5f9e892b4abdb38cdb375de39a450d579390 Mon Sep 17 00:00:00 2001 From: vzwGrey Date: Wed, 26 Oct 2016 15:15:04 +0200 Subject: [PATCH 02/51] Removed one line function --- commands/System/help.js | 4 +--- functions/pad.js | 3 --- 2 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 functions/pad.js diff --git a/commands/System/help.js b/commands/System/help.js index 5517a2f0..026c5c1a 100644 --- a/commands/System/help.js +++ b/commands/System/help.js @@ -1,5 +1,3 @@ -const pad = require("../../functions/pad.js"); - exports.run = (client, msg, [cmd]) => { if (!cmd) { let helpMessage = []; @@ -15,7 +13,7 @@ exports.run = (client, msg, [cmd]) => { for(let [command, description] of commands) { client.funcs.log(`Help command for ${command} :: ${description}`); - helpMessage.push(`${pad(command + "::", longest + 2)} ${description}`); + helpMessage.push(`${command}::${" ".repeat(longest - command.length)} ${description}`); } helpMessage.push(" "); } diff --git a/functions/pad.js b/functions/pad.js deleted file mode 100644 index fe92c4f6..00000000 --- a/functions/pad.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (str, length) => { - return str + " ".repeat(length - str.length); -}; \ No newline at end of file From ca34bf869eb621721da6d33247e9df0819a90165 Mon Sep 17 00:00:00 2001 From: vzwGrey Date: Sat, 29 Oct 2016 13:35:06 +0200 Subject: [PATCH 03/51] Added padding to help command --- commands/System/help.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/commands/System/help.js b/commands/System/help.js index d66066e9..a12d56a1 100644 --- a/commands/System/help.js +++ b/commands/System/help.js @@ -43,6 +43,11 @@ const buildHelp = (client, msg) => { let help = {}; let mps = []; + let commandNames = Array.from(client.commands.keys()); + let longest = commandNames.reduce((longest, str) => { + return Math.max(longest, str.length); + }, 0); + client.commands.forEach(command => { mps.push(new Promise(res => { client.funcs.runCommandInhibitors(client, msg, command, true) @@ -51,7 +56,7 @@ const buildHelp = (client, msg) => { let subcat = command.help.subCategory; if (!help.hasOwnProperty(cat)) help[cat] = {}; if (!help[cat].hasOwnProperty(subcat)) help[cat][subcat] = []; - help[cat][subcat].push(`${msg.guildConf.prefix}${command.help.name} :: ${command.help.description}`); + help[cat][subcat].push(`${msg.guildConf.prefix}${command.help.name}::${" ".repeat(longest - command.help.name.length)} ${command.help.description}`); res(); }) .catch(() => { From ad48002c691ef0c091f74988076e8ea9bdfa2d18 Mon Sep 17 00:00:00 2001 From: Faith Date: Sat, 29 Oct 2016 09:16:58 -0400 Subject: [PATCH 04/51] Custom Permission Roles Support --- functions/confs.js | 5 ++++- functions/permissionLevel.js | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/functions/confs.js b/functions/confs.js index ded95b4d..583a0478 100644 --- a/functions/confs.js +++ b/functions/confs.js @@ -11,7 +11,9 @@ exports.init = (client) => { // Load default configuration, create if not exist. defaultConf = { prefix: {type: "String", data: client.config.prefix}, - disabledCommands: {type: "Array", data: "[]"} + disabledCommands: {type: "Array", data: []}, + mod_role: {type: "String", data: "Mods"}, + admin_role: {type: "String", data: "Devs"} }; fs.ensureFileSync(dataDir + path.sep + defaultFile); @@ -140,6 +142,7 @@ exports.set = (guild, key, value) => { } thisConf[key] = {data : value , type : defaultConf[key].type}; + guildConfs.set(guild.id, thisConf); fs.outputJSONSync(path.resolve(dataDir + path.sep + guild.id + ".json"), thisConf); diff --git a/functions/permissionLevel.js b/functions/permissionLevel.js index f01a0421..e08ae418 100644 --- a/functions/permissionLevel.js +++ b/functions/permissionLevel.js @@ -1,13 +1,14 @@ module.exports = (client, user, guild = null) => { return new Promise((resolve, reject) => { + let guildConf = client.funcs.confs.get(guild); let permlvl = 0; if(guild) { - try{ + try { let member = guild.member(user); - let mod_role = guild.roles.find("name", "Mods"); + let mod_role = guild.roles.find("name", guildConf.mod_role); if (mod_role && member.roles.has(mod_role.id)) permlvl = 2; - let admin_role = guild.roles.find("name", "Devs"); + let admin_role = guild.roles.find("name", guildConf.admin_role); if (admin_role && member.roles.has(admin_role.id)) permlvl = 3; if(member === guild.owner) From e227e5a10e900b5796b77fad8af6336c239a9d03 Mon Sep 17 00:00:00 2001 From: Faith Date: Sat, 29 Oct 2016 16:43:20 -0400 Subject: [PATCH 05/51] Adds member usage type. --- inhibitors/usage.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/inhibitors/usage.js b/inhibitors/usage.js index f81fdbab..4b53bcaa 100644 --- a/inhibitors/usage.js +++ b/inhibitors/usage.js @@ -99,6 +99,17 @@ exports.run = (client, msg, cmd) => { reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); } break; + case "member": + if (/^<@!?\d+>$/.test(args[i]) && msg.guild.members.has(/\d+/.exec(args[i])[0]) && args[i].length > 5) { + args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); + validateArgs(++i); + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); + } + break; case "channel": if (/^<#\d+>$/.test(args[i]) || client.channels.has(args[i])) { args[i] = client.channels.get(/\d+/.exec(args[i])[0]); @@ -363,6 +374,15 @@ exports.run = (client, msg, cmd) => { multiPossibles(++p); } break; + case "member": + if (result && args[i].length > 5 && msg.guild.members.has(result[0])) { + args[i] = msg.members.get(/\d+/.exec(args[i])[0]); + validated = true; + multiPossibles(++p); + } else { + multiPossibles(++p); + } + break; case "channel": if (/^<#\d+>$/.test(args[i]) || client.channels.has(args[i])) { args[i] = client.channels.get(/\d+/.exec(args[i])[0]); From e881ad21c3ffd2dd48c4ce8f04d5d5c7be6bd7b2 Mon Sep 17 00:00:00 2001 From: Faith Date: Sat, 29 Oct 2016 17:43:35 -0400 Subject: [PATCH 06/51] parseUsage fix and member usage type --- functions/parseUsage.js | 2 +- inhibitors/usage.js | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/functions/parseUsage.js b/functions/parseUsage.js index 03c41302..947533c0 100644 --- a/functions/parseUsage.js +++ b/functions/parseUsage.js @@ -10,7 +10,7 @@ const parseTag = (tag, count) => { const members = tag.split("|"); members.forEach((e, i) => { // i is the current bound if required for errors. - const result = /^([a-z09]+)(?::([a-z09]+)(?:{(?:(\d+(?:\.\d+)?))?(?:,(\d+(?:\.\d+)?))?})?)?$/i.exec(e); + const result = /^([a-z0-9]+)(?::([a-z0-9]+)(?:{(?:(\d+(?:\.\d+)?))?(?:,(\d+(?:\.\d+)?))?})?)?$/i.exec(e); // I require to modify the regex if we wan't to handle invalid types instead of defaulting them if (!result) diff --git a/inhibitors/usage.js b/inhibitors/usage.js index 4b53bcaa..a74e2b8d 100644 --- a/inhibitors/usage.js +++ b/inhibitors/usage.js @@ -99,17 +99,17 @@ exports.run = (client, msg, cmd) => { reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); } break; - case "member": - if (/^<@!?\d+>$/.test(args[i]) && msg.guild.members.has(/\d+/.exec(args[i])[0]) && args[i].length > 5) { - args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); - validateArgs(++i); - } else if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); - } - break; + case "member": + if (/^<@!?\d+>$/.test(args[i]) && msg.guild.members.has(/\d+/.exec(args[i])[0]) && args[i].length > 5) { + args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); + validateArgs(++i); + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); + } + break; case "channel": if (/^<#\d+>$/.test(args[i]) || client.channels.has(args[i])) { args[i] = client.channels.get(/\d+/.exec(args[i])[0]); @@ -376,7 +376,7 @@ exports.run = (client, msg, cmd) => { break; case "member": if (result && args[i].length > 5 && msg.guild.members.has(result[0])) { - args[i] = msg.members.get(/\d+/.exec(args[i])[0]); + args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); validated = true; multiPossibles(++p); } else { From 12524f652ea9d8017e59d61986826562c6025221 Mon Sep 17 00:00:00 2001 From: CyberiumShadow Date: Sun, 30 Oct 2016 15:30:46 +1100 Subject: [PATCH 07/51] Allows multi word values to be used --- commands/System/conf.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/commands/System/conf.js b/commands/System/conf.js index 2ffbe209..9121a3f9 100644 --- a/commands/System/conf.js +++ b/commands/System/conf.js @@ -1,4 +1,5 @@ -exports.run = (client, msg, [action, key, value]) => { +exports.run = (client, msg, [action, key, ... value]) => { + value = value.join(" "); if(action === "list") { msg.channel.sendCode("json", require("util").inspect(msg.guildConf)); return; From 1e083ecf6bb6f54f4ea9d723557b64b668e23c7d Mon Sep 17 00:00:00 2001 From: Kelvin Wu Date: Sun, 30 Oct 2016 16:33:24 +0000 Subject: [PATCH 08/51] Fix random missing periods, spelling, etc. --- README.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 485e9c6b..08383121 100644 --- a/README.md +++ b/README.md @@ -44,18 +44,18 @@ npm install node app.js ``` -> Requires Node 6 or higher (because discord.js requires that), also requires Discord.js v10 (currently #indev), installed automatically with `npm install`. +> Requires Node 6 or higher (because Discord.js requires that), also requires Discord.js v10, installed automatically with `npm install`. ## Quick & Dirty Reference Guide > For creating your own pieces -Essentially, the way Komada works is that we have *core* pieces (functions, events, commands, etc) loaded automatically. -But you can add your own pieces easily by adding files to your *local* folders (which are created on first load) +Essentially, the way Komada works is that we have *core* pieces (functions, events, commands, etc.) loaded automatically. +But you can add your own pieces easily by adding files to your *local* folders (which are created on first load). These pieces are: -- **Commands** which add in-chat functionality to your bot +- **commands** which add in-chat functionality to your bot. - **functions** which can be used by other pieces or anywhere in the bot. -- **dataHandlers** which are database connectors (in progress at the moment) +- **dataHandlers** which are database connectors (in progress at the moment). ### Creating a new command @@ -69,7 +69,7 @@ your command will override the core one. This can let you modify the core behaviour. Note also that you cannot have more than one command with the same name. ```js -exports.run = (client, msg. [...args]) => { +exports.run = (client, msg, [...args]) => { // Place Code Here }; @@ -97,10 +97,10 @@ by the `usage` property and its given arguments. **Non-obvious options**: - **enabled**: Set to false to completely disable this command, it cannot be forecefully enabled. - **aliases**: Array of aliases for the command, which will *also* trigger it. -- **permLevel**: Permission level, controlled via `./functions/permissionLevel.js` +- **permLevel**: Permission level, controlled via `./functions/permissionLevel.js`. - **botPerms**: An array of permission strings (such as `"MANAGE_MESSAGES"`) required for the command to run. -- **requiredFuncs**: An array of function names required for this command to execute (dependency) -- **usage**: The usage string as determined by the Argument Usage (see below) +- **requiredFuncs**: An array of function names required for this command to execute (dependency). +- **usage**: The usage string as determined by the Argument Usage (see below). #### Command Arguments @@ -110,21 +110,21 @@ by the `usage` property and its given arguments. `` - **Name** Mostly used for debugging message, unless the type is Litteral in which it compares the argument to the name. -- **Type** The type of variable you are expecting +- **Type** The type of variable you are expecting. - **Min, Max** Minimum or Maximum for a giving variable (works on strings in terms of length, and on all types of numbers in terms of value) You are allowed to define any combination of min and max. Omit for none, `{min}` for min, `{,max}` for max. -- **Special Repeat Tag** `[...]` will repeat the last usage optionally until you run out of arguments. Useful for doing something like ` [...]` which will allow you to take as many search terms as you want, per your Usage Deliminator. +- **Special Repeat Tag** `[...]` will repeat the last usage optionally until you run out of arguments. Useful for doing something like ` [...]` which will allow you to take as many search terms as you want, per your Usage Delimiter. **Usage Types** - `literal` : Literally equal to the Name. This is the default type if none is defined. -- `str`, `string` : Strings -- `int`, `integer` : Integers -- `num`, `number`, `Float` : Floating point numbers -- `url` : a url -- `msg`, `message` : A message object returned from the message id (now using fetchMessage as of d3d498c99d5eca98b5cbcefb9838fa7d96f17c93) -- `channel` : A channel object returned from the channel id or channel tag -- `guild` : A guild object returned from the guild id -- `user`, `mention` : A user object returned from the user id or mention +- `str`, `string` : Strings. +- `int`, `integer` : Integers. +- `num`, `number`, `Float` : Floating point numbers. +- `url` : A URL. +- `msg`, `message` : A message object returned from the message ID (now using fetchMessage as of d3d498c99d5eca98b5cbcefb9838fa7d96f17c93). +- `channel` : A channel object returned from the channel ID or channel tag. +- `guild` : A guild object returned from the guild ID. +- `user`, `mention` : A user object returned from the user ID or mention. ### Creating an event @@ -140,7 +140,7 @@ exports.run = (client, [...args]) => { }; ``` -Where `[...args]` is arguments you would *normally* get from those events. +Where `[...args]` are arguments you would *normally* get from those events. For example, while the `ready` event would only have `(client)`, the `guildMemberAdd` event would be `(guild, member)`. From a58b39540752ad40beea7e30478d10bf4a01e541 Mon Sep 17 00:00:00 2001 From: Evelyne Lachance Date: Sun, 30 Oct 2016 19:45:07 -0400 Subject: [PATCH 09/51] bot owner commands only... --- commands/System/disable.js | 2 +- commands/System/enable.js | 2 +- commands/System/reload.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/commands/System/disable.js b/commands/System/disable.js index 329f59a5..58ad238b 100644 --- a/commands/System/disable.js +++ b/commands/System/disable.js @@ -17,7 +17,7 @@ exports.conf = { enabled: true, guildOnly: false, aliases: [], - permLevel: 4, + permLevel: 10, botPerms: [], requiredFuncs: [] }; diff --git a/commands/System/enable.js b/commands/System/enable.js index 102e34b6..a05ff7ed 100644 --- a/commands/System/enable.js +++ b/commands/System/enable.js @@ -17,7 +17,7 @@ exports.conf = { enabled: true, guildOnly: false, aliases: [], - permLevel: 4, + permLevel: 10, botPerms: [], requiredFuncs: [] }; diff --git a/commands/System/reload.js b/commands/System/reload.js index a291dac9..a2faf2f5 100644 --- a/commands/System/reload.js +++ b/commands/System/reload.js @@ -44,7 +44,7 @@ exports.conf = { enabled: true, guildOnly: false, aliases: ["r", "load"], - permLevel: 4, + permLevel: 10, botPerms: [], requiredFuncs: [] }; From b66a126c56521613007c00f0b9ac83a63b2492a6 Mon Sep 17 00:00:00 2001 From: Faith Date: Mon, 31 Oct 2016 00:46:51 -0400 Subject: [PATCH 10/51] Fix for Core 'conf' command --- commands/System/conf.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/commands/System/conf.js b/commands/System/conf.js index 9121a3f9..adb0aace 100644 --- a/commands/System/conf.js +++ b/commands/System/conf.js @@ -13,6 +13,10 @@ exports.run = (client, msg, [action, key, ... value]) => { if(action === "set") { if(!key || !value) return msg.reply("Please provide both a key and value!"); + if (value === "true") + value = true; + if (value === "false") + value = false; client.funcs.confs.set(msg.guild, key, value); return msg.reply(`The value for ${key} has been set to: ${value}`); } else @@ -36,6 +40,6 @@ exports.conf = { exports.help = { name: "conf", description: "Define per-server configuration.", - usage: " [key:str] [channel:channel|user:user|role:role|int:int|str:str]", + usage: " [key:str] [true|false|channel:channel|user:user|role:role|int:int|str:str]", usageDelim: " " }; From ca28d66f0e7ac9b99123183acc108ea0dd09a6ae Mon Sep 17 00:00:00 2001 From: Faith Date: Mon, 31 Oct 2016 05:04:11 -0400 Subject: [PATCH 11/51] Adds Boolean Usage type and reverts old boolean fix --- commands/System/conf.js | 12 +++++------- inhibitors/usage.js | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/commands/System/conf.js b/commands/System/conf.js index adb0aace..a1512d45 100644 --- a/commands/System/conf.js +++ b/commands/System/conf.js @@ -1,5 +1,7 @@ exports.run = (client, msg, [action, key, ... value]) => { - value = value.join(" "); + if (value[1] != undefined) { + value = value.join(' '); + } if(action === "list") { msg.channel.sendCode("json", require("util").inspect(msg.guildConf)); return; @@ -13,11 +15,7 @@ exports.run = (client, msg, [action, key, ... value]) => { if(action === "set") { if(!key || !value) return msg.reply("Please provide both a key and value!"); - if (value === "true") - value = true; - if (value === "false") - value = false; - client.funcs.confs.set(msg.guild, key, value); + client.funcs.confs.set(msg.guild, key, value[1] === undefined ? value[0] : value); return msg.reply(`The value for ${key} has been set to: ${value}`); } else @@ -40,6 +38,6 @@ exports.conf = { exports.help = { name: "conf", description: "Define per-server configuration.", - usage: " [key:str] [true|false|channel:channel|user:user|role:role|int:int|str:str]", + usage: " [key:str] [boolean:boolean|channel:channel|user:user|role:role|int:int|str:str]", usageDelim: " " }; diff --git a/inhibitors/usage.js b/inhibitors/usage.js index a74e2b8d..f79364c4 100644 --- a/inhibitors/usage.js +++ b/inhibitors/usage.js @@ -99,6 +99,19 @@ exports.run = (client, msg, cmd) => { reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); } break; + case "boolean": + if (/^true|false$/.test(args[i])) { + if (args[i] === "true") + args[i] = true; + else args[i] = false; + validateArgs(++i); + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + reject(`${currentUsage.possibles[0].name} must be true or false.`) + } + break; case "member": if (/^<@!?\d+>$/.test(args[i]) && msg.guild.members.has(/\d+/.exec(args[i])[0]) && args[i].length > 5) { args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); @@ -374,6 +387,16 @@ exports.run = (client, msg, cmd) => { multiPossibles(++p); } break; + case "boolean": + if (/^true|false$/.test(args[i])) { + if (args[i] === "true") args[i] = true; + else args[i] = false; + validated = true; + multiPossibles(++p); + } else { + multiPossibles(++p); + } + break; case "member": if (result && args[i].length > 5 && msg.guild.members.has(result[0])) { args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); From 60e33cd544932dbe1c8c928423de930d388d7f43 Mon Sep 17 00:00:00 2001 From: Faith Date: Mon, 31 Oct 2016 20:46:27 -0400 Subject: [PATCH 12/51] Reverted again and made value checking better. Will now correctly change depending on the type of the key. Set can now set a boolean key as 'false' --- commands/System/conf.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/commands/System/conf.js b/commands/System/conf.js index a1512d45..4e9760cb 100644 --- a/commands/System/conf.js +++ b/commands/System/conf.js @@ -1,7 +1,14 @@ exports.run = (client, msg, [action, key, ... value]) => { - if (value[1] != undefined) { + + if (msg.guildConf[key].constructor.name === "String") { value = value.join(' '); + } else + if (msg.guildConf[key].constructor.name === "Boolean") { + value = value[0]; + } else { + value = value; } + if(action === "list") { msg.channel.sendCode("json", require("util").inspect(msg.guildConf)); return; @@ -14,8 +21,8 @@ exports.run = (client, msg, [action, key, ... value]) => { } else if(action === "set") { - if(!key || !value) return msg.reply("Please provide both a key and value!"); - client.funcs.confs.set(msg.guild, key, value[1] === undefined ? value[0] : value); + if(!key || value === undefined) return msg.reply("Please provide both a key and value!"); + client.funcs.confs.set(msg.guild, key, value); return msg.reply(`The value for ${key} has been set to: ${value}`); } else From f32faecb9cfde8ffedc4eb16e5d96a7576cce919 Mon Sep 17 00:00:00 2001 From: Faith Date: Mon, 31 Oct 2016 20:47:37 -0400 Subject: [PATCH 13/51] Quick fix for disable.js not disabling commands in disabledCommands array --- inhibitors/disable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inhibitors/disable.js b/inhibitors/disable.js index 3c36c5d2..73f7ae95 100644 --- a/inhibitors/disable.js +++ b/inhibitors/disable.js @@ -5,7 +5,7 @@ exports.conf = { exports.run = (client, msg, cmd) => { return new Promise((resolve, reject) => { - if (cmd.conf.enabled && !msg.guildConf.disabledCommands.includes(cmd)) { + if (cmd.conf.enabled && !msg.guildConf.disabledCommands.includes(cmd.help.name)) { resolve(); } else { reject("This command is currently disabled"); From 760aaca32e146ebbd7988cb5498bcdb62c0ab96f Mon Sep 17 00:00:00 2001 From: Faith Date: Wed, 2 Nov 2016 23:44:07 -0400 Subject: [PATCH 14/51] Fix for default config being 'out of sync' on updates --- functions/confs.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/functions/confs.js b/functions/confs.js index 583a0478..7a4ad275 100644 --- a/functions/confs.js +++ b/functions/confs.js @@ -18,11 +18,17 @@ exports.init = (client) => { fs.ensureFileSync(dataDir + path.sep + defaultFile); try { - defaultConf = fs.readJSONSync(path.resolve(dataDir + path.sep + defaultFile)); + let currentDefaultConf = fs.readJSONSync(path.resolve(dataDir + path.sep + defaultFile)); + if (JSON.stringify(defaultConf) !== JSON.stringify(currentDefaultConf)) { + client.funcs.log("Default Configuration out of date. Fixing that now."); + fs.outputJSONSync(dataDir + path.set + defaultFile, defaultConf); + let defaultConf = fs.readJSONSync(path.resolve(dataDir + path.sep + defaultFile)); + } else { + defaultConf = currentDefaultConf; + } } catch(e) { fs.outputJSONSync(dataDir + path.sep + defaultFile, defaultConf); } - fs.walk(dataDir) .on("data", (item) => { let fileinfo = path.parse(item.path); From 042ac9e9df94807e4326bdbc1c2e98fd1322de3f Mon Sep 17 00:00:00 2001 From: Faith Date: Thu, 3 Nov 2016 01:39:02 -0400 Subject: [PATCH 15/51] Better 'Fix', which allow you to use setKey, and not have your default options overwritten, but still add missing keys if you don't have them --- functions/confs.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/functions/confs.js b/functions/confs.js index 7a4ad275..d948a0c1 100644 --- a/functions/confs.js +++ b/functions/confs.js @@ -8,7 +8,6 @@ let defaultConf = {}; exports.init = (client) => { dataDir = path.resolve(`${client.clientBaseDir}${path.sep}bwd${path.sep}conf`); - // Load default configuration, create if not exist. defaultConf = { prefix: {type: "String", data: client.config.prefix}, disabledCommands: {type: "Array", data: []}, @@ -19,13 +18,15 @@ exports.init = (client) => { fs.ensureFileSync(dataDir + path.sep + defaultFile); try { let currentDefaultConf = fs.readJSONSync(path.resolve(dataDir + path.sep + defaultFile)); - if (JSON.stringify(defaultConf) !== JSON.stringify(currentDefaultConf)) { - client.funcs.log("Default Configuration out of date. Fixing that now."); - fs.outputJSONSync(dataDir + path.set + defaultFile, defaultConf); - let defaultConf = fs.readJSONSync(path.resolve(dataDir + path.sep + defaultFile)); - } else { + Object.keys(defaultConf).forEach(key => { + if (currentDefaultConf[key] === undefined) { + currentDefaultConf[key] = defaultConf[key]; + } else { + return; + } + }); + fs.outputJSONSync(dataDir + path.sep + defaultFile, currentDefaultConf); defaultConf = currentDefaultConf; - } } catch(e) { fs.outputJSONSync(dataDir + path.sep + defaultFile, defaultConf); } From 0624db445ec20e3a356c1b84f8e773321f1d1d06 Mon Sep 17 00:00:00 2001 From: Faith Date: Thu, 3 Nov 2016 02:04:56 -0400 Subject: [PATCH 16/51] Updated forEach per Ao's recommendation --- functions/confs.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/functions/confs.js b/functions/confs.js index d948a0c1..817732ff 100644 --- a/functions/confs.js +++ b/functions/confs.js @@ -19,11 +19,7 @@ exports.init = (client) => { try { let currentDefaultConf = fs.readJSONSync(path.resolve(dataDir + path.sep + defaultFile)); Object.keys(defaultConf).forEach(key => { - if (currentDefaultConf[key] === undefined) { - currentDefaultConf[key] = defaultConf[key]; - } else { - return; - } + if(!currentDefaultConf.hasOwnProperty(key)) currentDefaultConf[key] = defaultConf[key]; }); fs.outputJSONSync(dataDir + path.sep + defaultFile, currentDefaultConf); defaultConf = currentDefaultConf; From f4d2a156249b4509fe00ebc644aacdfe27090ea2 Mon Sep 17 00:00:00 2001 From: Faith Date: Thu, 3 Nov 2016 02:15:48 -0400 Subject: [PATCH 17/51] Download.js VM "Cannot Find Module" Fix --- commands/System/download.js | 72 +++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/commands/System/download.js b/commands/System/download.js index 5dbcfae6..0029a05f 100644 --- a/commands/System/download.js +++ b/commands/System/download.js @@ -1,7 +1,9 @@ const request = require("superagent"); const vm = require("vm"); +const exec = require("child_process").exec; var fs = require("fs-extra"); + exports.run = (client, msg, [url, folder = "Downloaded"]) => { request.get(url, (err, res) => { if (err) console.log(err); @@ -10,20 +12,51 @@ exports.run = (client, msg, [url, folder = "Downloaded"]) => { var mod = { exports: {} }; + + let code = + `(function(require) { + ${res.text}; + })`; + try { - vm.runInNewContext(res.text, { module: mod, exports: mod.exports }, {timeout: 500}); + vm.runInNewContext(code, { module: mod, exports: mod.exports}, {timeout: 500})(require); } catch (e) { + if (e.message.startsWith("Cannot find module ")) { + msg.channel.sendMessage("Couldn't find module... Attempting to download.").then(m => { + let moduleName = e.message.substring(19).replace(/'/g, ""); + client.funcs.installNPM(moduleName).then((resolved) => { + m.edit(`Downloaded **${moduleName}!** I will make an attempt to load the command now.`); + if (client.tempmodules === undefined) client.tempmodules = []; + client.tempmodules.push(moduleName) + client.commands.get('download').run(client, msg, [url, folder]); + }).catch(e => { + console.log(e); + }) + return; + }); + } else if (e.message.startsWith("ENOENT: no such file or directory, open ")) { + msg.channel.sendMessage("Couldn't find module... Attempting to download."); + let string = e.message.substring(e.message.indexOf("node_modules"), e.message.lastIndexOf("\\")); + let moduleName = string.substring(string.indexOf("\\")+1, string.length); + client.funcs.installNPM(moduleName).then((resolved) => { + m.edit(`Downloaded **${moduleName}!** I will make an attempt to load the command now.`) + if (client.tempmodules === undefined) client.tempmodules = []; + client.tempmodules.push(moduleName); + client.commands.get('download').run(client, msg, [url, folder]); + }).catch(e => { + console.log(e); + }) + return; + } else { msg.reply(`URL command not valid: ${e}`); return; } + return; + } let name = mod.exports.help.name; let description = mod.exports.help.description; - if (mod.exports.conf.selfbot && client.config.selfbot) { - msg.reply(`The command \`${name}\` is only usable in selfbots!`); - return; - } if (client.commands.has(name)) { msg.reply(`The command \`${name}\` already exists in the bot!`); return; @@ -48,8 +81,31 @@ ${description} }); collector.on("end", (collected, reason) => { - if (reason === "time") return msg.channel.sendMessage(":timer: 5s timeout. Can you read a bit faster?"); - if (reason === "aborted") return msg.channel.sendMessage(":no_mobile_phones: Load Aborted. Command not installed."); + if (reason === "aborted" || reason === "time") { + if (client.tempmodules !== undefined) { + msg.channel.sendMessage(":no_mobile_phones: Load Aborted. Command not installed. Lemme remove those useless modules for you :smile:").then(m => { + exec(`npm uninstall ${client.tempmodules.join(' ')}`, (e, stdout, stderr) => { + if (e) { + msg.channel.sendMessage(`Failed uninstalling the modules.. Sorry about that.`); + console.log(e); + return; + } else { + console.log(stdout); + console.log(stderr); + m.edit(`Succesfully uninstalled : **${client.tempmodules.join(', ')}**`); + client.tempmodules.forEach(module => { + delete require.cache[require.resolve(module)]; + }); + delete client.tempmodules; + return; + } + }); + }); + } else { + msg.channel.sendMessage(":no_mobile_phones: Load Aborted. Command not installed."); + return; + } + } if (reason === "success") { msg.channel.sendMessage(":inbox_tray: `Loading Command...`").then(m => { let category = mod.exports.help.category ? mod.exports.help.category : client.funcs.toTitleCase(folder); @@ -63,10 +119,12 @@ ${description} client.funcs.loadSingleCommand(client, name, false, `${dir}/${name}.js`) .then((cmd) => { m.edit(`:inbox_tray: Successfully Loaded: ${cmd.help.name}`); + delete client.tempmodules; }) .catch(e => { m.edit(`:no_mobile_phones: Command load failed: ${name}\n\`\`\`${e.stack}\`\`\``); fs.unlink(`${dir}/${name}.js`); + delete client.tempmodules; }); }); }); From d6f1ac7a77838f635c025b589f147fb7dc1fdfea Mon Sep 17 00:00:00 2001 From: Faith Date: Thu, 3 Nov 2016 02:26:39 -0400 Subject: [PATCH 18/51] Readded Cybers selfbot option && fix for it --- commands/System/download.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/commands/System/download.js b/commands/System/download.js index 0029a05f..ef771aac 100644 --- a/commands/System/download.js +++ b/commands/System/download.js @@ -62,6 +62,11 @@ exports.run = (client, msg, [url, folder = "Downloaded"]) => { return; } + if (mod.exports.conf.selfbot && !client.config.selfbot) { + msg.reply(`The command \`${name}\` is only usable in selfbots!`); + return; + } + msg.channel.sendMessage(`Are you sure you want to load the following command into your bot? \`\`\`asciidoc === NAME === From e1942cf423646ed9de84dde51bbc5cb6003b878f Mon Sep 17 00:00:00 2001 From: Faith Date: Thu, 3 Nov 2016 03:14:15 -0400 Subject: [PATCH 19/51] If command is now selfbot only and bot is not a selfbot, The bot will now uninstall the modules it previously installed. --- commands/System/download.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/commands/System/download.js b/commands/System/download.js index ef771aac..a5f4919a 100644 --- a/commands/System/download.js +++ b/commands/System/download.js @@ -59,11 +59,29 @@ exports.run = (client, msg, [url, folder = "Downloaded"]) => { if (client.commands.has(name)) { msg.reply(`The command \`${name}\` already exists in the bot!`); + delete client.tempmodules; return; } if (mod.exports.conf.selfbot && !client.config.selfbot) { - msg.reply(`The command \`${name}\` is only usable in selfbots!`); + msg.channel.sendMessage(`The command \`${name}\` is only usable in selfbots! I'll uninstall the modules for you.`).then(m => { + exec(`npm uninstall ${client.tempmodules.join(' ')}`, (e, stdout, stderr) => { + if (e) { + msg.channel.sendMessage(`Failed uninstalling the modules.. Sorry about that.`); + console.log(e); + return; + } else { + console.log(stdout); + console.log(stderr); + m.edit(`Succesfully uninstalled : **${client.tempmodules.join(', ')}**`); + client.tempmodules.forEach(module => { + delete require.cache[require.resolve(module)]; + }); + delete client.tempmodules; + return; + } + }); + }) return; } @@ -77,7 +95,7 @@ ${description} \`\`\``); const collector = msg.channel.createCollector(m => m.author === msg.author, { - time: 5000 + time: 8000 }); collector.on("message", m => { @@ -91,7 +109,7 @@ ${description} msg.channel.sendMessage(":no_mobile_phones: Load Aborted. Command not installed. Lemme remove those useless modules for you :smile:").then(m => { exec(`npm uninstall ${client.tempmodules.join(' ')}`, (e, stdout, stderr) => { if (e) { - msg.channel.sendMessage(`Failed uninstalling the modules.. Sorry about that.`); + msg.channel.sendMessage(`Failed uninstalling the modules.. Sorry about that, the modules you need to uninstall are in \`client.tempmodules\``); console.log(e); return; } else { From 10e8e7a124424023522ce884f5b29fcf9eee2967 Mon Sep 17 00:00:00 2001 From: Faith Date: Thu, 3 Nov 2016 03:46:12 -0400 Subject: [PATCH 20/51] Selfbot commands now correctly load or not if selfbot --- functions/loadSingleCommand.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/loadSingleCommand.js b/functions/loadSingleCommand.js index f82c80ed..670eebd1 100644 --- a/functions/loadSingleCommand.js +++ b/functions/loadSingleCommand.js @@ -25,7 +25,7 @@ module.exports = function(client, command, reload = false, loadPath = null) { } else { try { cmd = require(loadPath); - if (cmd.conf.selfbot && client.config.selfbot) { + if (cmd.conf.selfbot && !client.config.selfbot) { return reject(`The command \`${cmd.help.name}\` is only usable in selfbots!`); } let pathParts = loadPath.split(path.sep); From 1d868b8d1103c78f699e804159d70212998b861b Mon Sep 17 00:00:00 2001 From: CyberiumShadow Date: Tue, 8 Nov 2016 21:58:13 +1100 Subject: [PATCH 21/51] Bumping Komada Core to use D.JS Indev --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2cc49530..5352504f 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "license": "ISC", "dependencies": { "chalk": "^1.1.3", - "discord.js": "^10.0.0", + "discord.js": "hydrabolt/discord.js#indev", "fs-extra": "^0.30.0", "moment": "^2.15.1", "moment-duration-format": "^1.3.0" From cea31569806b3be8cb80716784a1f3793f1c48a5 Mon Sep 17 00:00:00 2001 From: CyberiumShadow Date: Tue, 8 Nov 2016 23:00:41 +1100 Subject: [PATCH 22/51] Eslint/Beautify everything~ --- README.md | 14 ++--- commands/System/download.js | 95 +++++++++++++++--------------- commands/System/eval.js | 3 +- commands/System/help.js | 44 +++++++------- commands/System/reload.js | 16 ++--- events/guildDelete.js | 2 +- functions/clean.js | 14 ++--- functions/confs.js | 84 +++++++++++++------------- functions/getFileListing.js | 58 +++++++++--------- functions/loadCommandInhibitors.js | 22 +++---- functions/loadDataProviders.js | 20 +++---- functions/loadEvents.js | 8 +-- functions/loadFunctions.js | 26 ++++---- functions/loadSingleCommand.js | 31 +++++----- functions/parseTags.js | 10 ++-- functions/permissionLevel.js | 4 +- functions/runCommandInhibitors.js | 12 ++-- functions/validateData.js | 1 - inhibitors/permissions.js | 12 ++-- inhibitors/selfBot.js | 2 +- inhibitors/usage.js | 6 +- 21 files changed, 240 insertions(+), 244 deletions(-) diff --git a/README.md b/README.md index 08383121..063af198 100644 --- a/README.md +++ b/README.md @@ -49,10 +49,10 @@ node app.js ## Quick & Dirty Reference Guide > For creating your own pieces -Essentially, the way Komada works is that we have *core* pieces (functions, events, commands, etc.) loaded automatically. +Essentially, the way Komada works is that we have *core* pieces (functions, events, commands, etc.) loaded automatically. But you can add your own pieces easily by adding files to your *local* folders (which are created on first load). -These pieces are: +These pieces are: - **commands** which add in-chat functionality to your bot. - **functions** which can be used by other pieces or anywhere in the bot. - **dataHandlers** which are database connectors (in progress at the moment). @@ -64,7 +64,7 @@ the categories offered in the help command. For instance adding `./commands/Misc will create a command named `test` in the `Misc` category. Subcategories can also be created by adding a second folder level. -> If a command is present both in the *core* folders and your client folders, +> If a command is present both in the *core* folders and your client folders, your command will override the core one. This can let you modify the core behaviour. Note also that you cannot have more than one command with the same name. @@ -94,7 +94,7 @@ exports.help = { run. The name of the arguments in the array (and their count) is determined by the `usage` property and its given arguments. -**Non-obvious options**: +**Non-obvious options**: - **enabled**: Set to false to completely disable this command, it cannot be forecefully enabled. - **aliases**: Array of aliases for the command, which will *also* trigger it. - **permLevel**: Permission level, controlled via `./functions/permissionLevel.js`. @@ -125,7 +125,7 @@ by the `usage` property and its given arguments. - `channel` : A channel object returned from the channel ID or channel tag. - `guild` : A guild object returned from the guild ID. - `user`, `mention` : A user object returned from the user ID or mention. - + ### Creating an event Events are placed in `./events/` and their filename must be `eventName.js`. @@ -141,7 +141,7 @@ exports.run = (client, [...args]) => { ``` Where `[...args]` are arguments you would *normally* get from those events. -For example, while the `ready` event would only have `(client)`, the +For example, while the `ready` event would only have `(client)`, the `guildMemberAdd` event would be `(guild, member)`. ### Creating a function @@ -164,4 +164,4 @@ module.exports = (str) => { ``` The arguments are arbitrary - just like a regular function. It may, or may not, -return anything. Basically any functions. You know what I mean. \ No newline at end of file +return anything. Basically any functions. You know what I mean. diff --git a/commands/System/download.js b/commands/System/download.js index a5f4919a..c53719f2 100644 --- a/commands/System/download.js +++ b/commands/System/download.js @@ -3,7 +3,6 @@ const vm = require("vm"); const exec = require("child_process").exec; var fs = require("fs-extra"); - exports.run = (client, msg, [url, folder = "Downloaded"]) => { request.get(url, (err, res) => { if (err) console.log(err); @@ -14,45 +13,45 @@ exports.run = (client, msg, [url, folder = "Downloaded"]) => { }; let code = - `(function(require) { + `(function(require) { ${res.text}; })`; try { - vm.runInNewContext(code, { module: mod, exports: mod.exports}, {timeout: 500})(require); + vm.runInNewContext(code, { module: mod, exports: mod.exports }, { timeout: 500 })(require); } catch (e) { if (e.message.startsWith("Cannot find module ")) { msg.channel.sendMessage("Couldn't find module... Attempting to download.").then(m => { - let moduleName = e.message.substring(19).replace(/'/g, ""); - client.funcs.installNPM(moduleName).then((resolved) => { - m.edit(`Downloaded **${moduleName}!** I will make an attempt to load the command now.`); - if (client.tempmodules === undefined) client.tempmodules = []; - client.tempmodules.push(moduleName) - client.commands.get('download').run(client, msg, [url, folder]); - }).catch(e => { - console.log(e); - }) - return; - }); + let moduleName = e.message.substring(19).replace(/'/g, ""); + client.funcs.installNPM(moduleName).then((resolved) => { + m.edit(`Downloaded **${moduleName}!** I will make an attempt to load the command now.`); + if (client.tempmodules === undefined) client.tempmodules = []; + client.tempmodules.push(moduleName); + client.commands.get("download").run(client, msg, [url, folder]); + }).catch(e => { + console.log(e); + }); + return; + }); } else if (e.message.startsWith("ENOENT: no such file or directory, open ")) { msg.channel.sendMessage("Couldn't find module... Attempting to download."); let string = e.message.substring(e.message.indexOf("node_modules"), e.message.lastIndexOf("\\")); - let moduleName = string.substring(string.indexOf("\\")+1, string.length); + let moduleName = string.substring(string.indexOf("\\") + 1, string.length); client.funcs.installNPM(moduleName).then((resolved) => { - m.edit(`Downloaded **${moduleName}!** I will make an attempt to load the command now.`) + m.edit(`Downloaded **${moduleName}!** I will make an attempt to load the command now.`); if (client.tempmodules === undefined) client.tempmodules = []; client.tempmodules.push(moduleName); - client.commands.get('download').run(client, msg, [url, folder]); + client.commands.get("download").run(client, msg, [url, folder]); }).catch(e => { console.log(e); - }) + }); return; } else { - msg.reply(`URL command not valid: ${e}`); + msg.reply(`URL command not valid: ${e}`); + return; + } return; } - return; - } let name = mod.exports.help.name; let description = mod.exports.help.description; @@ -65,23 +64,23 @@ exports.run = (client, msg, [url, folder = "Downloaded"]) => { if (mod.exports.conf.selfbot && !client.config.selfbot) { msg.channel.sendMessage(`The command \`${name}\` is only usable in selfbots! I'll uninstall the modules for you.`).then(m => { - exec(`npm uninstall ${client.tempmodules.join(' ')}`, (e, stdout, stderr) => { + exec(`npm uninstall ${client.tempmodules.join(" ")}`, (e, stdout, stderr) => { if (e) { - msg.channel.sendMessage(`Failed uninstalling the modules.. Sorry about that.`); + msg.channel.sendMessage("Failed uninstalling the modules.. Sorry about that."); console.log(e); return; } else { console.log(stdout); console.log(stderr); - m.edit(`Succesfully uninstalled : **${client.tempmodules.join(', ')}**`); + m.edit(`Succesfully uninstalled : **${client.tempmodules.join(", ")}**`); client.tempmodules.forEach(module => { delete require.cache[require.resolve(module)]; }); delete client.tempmodules; return; } + }); }); - }) return; } @@ -106,29 +105,29 @@ ${description} collector.on("end", (collected, reason) => { if (reason === "aborted" || reason === "time") { if (client.tempmodules !== undefined) { - msg.channel.sendMessage(":no_mobile_phones: Load Aborted. Command not installed. Lemme remove those useless modules for you :smile:").then(m => { - exec(`npm uninstall ${client.tempmodules.join(' ')}`, (e, stdout, stderr) => { - if (e) { - msg.channel.sendMessage(`Failed uninstalling the modules.. Sorry about that, the modules you need to uninstall are in \`client.tempmodules\``); - console.log(e); - return; - } else { - console.log(stdout); - console.log(stderr); - m.edit(`Succesfully uninstalled : **${client.tempmodules.join(', ')}**`); - client.tempmodules.forEach(module => { - delete require.cache[require.resolve(module)]; - }); - delete client.tempmodules; - return; - } - }); - }); - } else { - msg.channel.sendMessage(":no_mobile_phones: Load Aborted. Command not installed."); - return; + msg.channel.sendMessage(":no_mobile_phones: Load Aborted. Command not installed. Lemme remove those useless modules for you :smile:").then(m => { + exec(`npm uninstall ${client.tempmodules.join(" ")}`, (e, stdout, stderr) => { + if (e) { + msg.channel.sendMessage(`Failed uninstalling the modules.. Sorry about that, the modules you need to uninstall are in \`client.tempmodules\``); + console.log(e); + return; + } else { + console.log(stdout); + console.log(stderr); + m.edit(`Succesfully uninstalled : **${client.tempmodules.join(", ")}**`); + client.tempmodules.forEach(module => { + delete require.cache[require.resolve(module)]; + }); + delete client.tempmodules; + return; + } + }); + }); + } else { + msg.channel.sendMessage(":no_mobile_phones: Load Aborted. Command not installed."); + return; + } } - } if (reason === "success") { msg.channel.sendMessage(":inbox_tray: `Loading Command...`").then(m => { let category = mod.exports.help.category ? mod.exports.help.category : client.funcs.toTitleCase(folder); @@ -138,7 +137,7 @@ ${description} fs.ensureDir(dir, err => { if (err) console.error(err); fs.writeFile(`${dir}/${name}.js`, res.text, (err) => { - if(err) console.error(err); + if (err) console.error(err); client.funcs.loadSingleCommand(client, name, false, `${dir}/${name}.js`) .then((cmd) => { m.edit(`:inbox_tray: Successfully Loaded: ${cmd.help.name}`); diff --git a/commands/System/eval.js b/commands/System/eval.js index ab715269..b53215c1 100644 --- a/commands/System/eval.js +++ b/commands/System/eval.js @@ -4,8 +4,7 @@ exports.run = (client, msg, [code]) => { if (typeof evaled !== "string") evaled = require("util").inspect(evaled); msg.channel.sendCode("xl", client.funcs.clean(client, evaled)); - } - catch (err) { + } catch (err) { msg.channel.sendMessage("`ERROR` ```xl\n" + client.funcs.clean(err) + "\n```"); diff --git a/commands/System/help.js b/commands/System/help.js index a12d56a1..d602bbad 100644 --- a/commands/System/help.js +++ b/commands/System/help.js @@ -1,18 +1,18 @@ exports.run = (client, msg, [cmd]) => { if (!cmd) { buildHelp(client, msg) - .then(help => { - let helpMessage = []; - for (let key in help) { - helpMessage.push(`**${key} Commands**: \`\`\`asciidoc`); - for (let key2 in help[key]) { - helpMessage.push(`= ${key2} =`); - helpMessage.push(help[key][key2].join("\n") + "\n"); + .then(help => { + let helpMessage = []; + for (let key in help) { + helpMessage.push(`**${key} Commands**: \`\`\`asciidoc`); + for (let key2 in help[key]) { + helpMessage.push(`= ${key2} =`); + helpMessage.push(help[key][key2].join("\n") + "\n"); + } + helpMessage.push("```\n\u200b"); } - helpMessage.push("```\n\u200b"); - } - msg.channel.sendMessage(helpMessage, { split: { char: "\u200b" } }).catch(e => { console.error(e); }); - }); + msg.channel.sendMessage(helpMessage, { split: { char: "\u200b" } }).catch(e => { console.error(e); }); + }); } else { if (client.commands.has(cmd)) { @@ -51,17 +51,17 @@ const buildHelp = (client, msg) => { client.commands.forEach(command => { mps.push(new Promise(res => { client.funcs.runCommandInhibitors(client, msg, command, true) - .then(() => { - let cat = command.help.category; - let subcat = command.help.subCategory; - if (!help.hasOwnProperty(cat)) help[cat] = {}; - if (!help[cat].hasOwnProperty(subcat)) help[cat][subcat] = []; - help[cat][subcat].push(`${msg.guildConf.prefix}${command.help.name}::${" ".repeat(longest - command.help.name.length)} ${command.help.description}`); - res(); - }) - .catch(() => { - res(); - }); + .then(() => { + let cat = command.help.category; + let subcat = command.help.subCategory; + if (!help.hasOwnProperty(cat)) help[cat] = {}; + if (!help[cat].hasOwnProperty(subcat)) help[cat][subcat] = []; + help[cat][subcat].push(`${msg.guildConf.prefix}${command.help.name}::${" ".repeat(longest - command.help.name.length)} ${command.help.description}`); + res(); + }) + .catch(() => { + res(); + }); })); }); Promise.all(mps).then(() => { diff --git a/commands/System/reload.js b/commands/System/reload.js index a2faf2f5..16d6fe1f 100644 --- a/commands/System/reload.js +++ b/commands/System/reload.js @@ -13,17 +13,17 @@ exports.run = (client, msg, [commandname]) => { if (!command) { client.funcs.getFileListing(client, client.coreBaseDir, "commands") .then(files => { - let newCommands = files.filter(f=>f.name == command); + let newCommands = files.filter(f => f.name == command); newCommands.forEach(file => { msg.channel.sendMessage(`Loading New Command: ${commandname}`) - .then(m => { - client.funcs.loadSingleCommand(client, command, false, `${file.path}${require("path").sep}${file.base}`).then(cmd => { - m.edit(`Successfully Loaded: ${cmd.help.name}`); - }) - .catch(e => { - m.edit(`Command load failed for ${command}: \n\`\`\`${e.stack}\`\`\``); + .then(m => { + client.funcs.loadSingleCommand(client, command, false, `${file.path}${require("path").sep}${file.base}`).then(cmd => { + m.edit(`Successfully Loaded: ${cmd.help.name}`); + }) + .catch(e => { + m.edit(`Command load failed for ${command}: \n\`\`\`${e.stack}\`\`\``); + }); }); - }); }); }); } else { diff --git a/events/guildDelete.js b/events/guildDelete.js index d25b5a50..2aa3b509 100644 --- a/events/guildDelete.js +++ b/events/guildDelete.js @@ -1,4 +1,4 @@ exports.run = (client, guild) => { - if(!guild.available) return; + if (!guild.available) return; client.funcs.confs.remove(client, guild); }; diff --git a/functions/clean.js b/functions/clean.js index ee67c330..bc448eaf 100644 --- a/functions/clean.js +++ b/functions/clean.js @@ -1,6 +1,6 @@ module.exports = (client, text) => { if (typeof(text) === "string") { - return text.replace(sensitivePattern(client), "「redacted」").replace(client.user.email, '「redacted」').replace(/`/g, "`" + String.fromCharCode(8203)).replace(/@/g, "@" + String.fromCharCode(8203)); + return text.replace(sensitivePattern(client), "「redacted」").replace(client.user.email, "「redacted」").replace(/`/g, "`" + String.fromCharCode(8203)).replace(/@/g, "@" + String.fromCharCode(8203)); } else { return text; } @@ -8,12 +8,12 @@ module.exports = (client, text) => { function sensitivePattern(client) { if (!this._sensitivePattern) { - let pattern = ''; + let pattern = ""; if (client.token) pattern += client.token; - if (client.token) pattern += (pattern.length > 0 ? '|' : '') + client.token; - if (client.email) pattern += (pattern.length > 0 ? '|' : '') + client.email; - if (client.password) pattern += (pattern.length > 0 ? '|' : '') + client.password; - this._sensitivePattern = new RegExp(pattern, 'gi'); + if (client.token) pattern += (pattern.length > 0 ? "|" : "") + client.token; + if (client.email) pattern += (pattern.length > 0 ? "|" : "") + client.email; + if (client.password) pattern += (pattern.length > 0 ? "|" : "") + client.password; + this._sensitivePattern = new RegExp(pattern, "gi"); } return this._sensitivePattern; -}; +} diff --git a/functions/confs.js b/functions/confs.js index 817732ff..641d28e4 100644 --- a/functions/confs.js +++ b/functions/confs.js @@ -9,39 +9,39 @@ exports.init = (client) => { dataDir = path.resolve(`${client.clientBaseDir}${path.sep}bwd${path.sep}conf`); defaultConf = { - prefix: {type: "String", data: client.config.prefix}, - disabledCommands: {type: "Array", data: []}, - mod_role: {type: "String", data: "Mods"}, - admin_role: {type: "String", data: "Devs"} + prefix: { type: "String", data: client.config.prefix }, + disabledCommands: { type: "Array", data: [] }, + mod_role: { type: "String", data: "Mods" }, + admin_role: { type: "String", data: "Devs" } }; fs.ensureFileSync(dataDir + path.sep + defaultFile); try { let currentDefaultConf = fs.readJSONSync(path.resolve(dataDir + path.sep + defaultFile)); - Object.keys(defaultConf).forEach(key => { - if(!currentDefaultConf.hasOwnProperty(key)) currentDefaultConf[key] = defaultConf[key]; - }); - fs.outputJSONSync(dataDir + path.sep + defaultFile, currentDefaultConf); - defaultConf = currentDefaultConf; - } catch(e) { + Object.keys(defaultConf).forEach(key => { + if (!currentDefaultConf.hasOwnProperty(key)) currentDefaultConf[key] = defaultConf[key]; + }); + fs.outputJSONSync(dataDir + path.sep + defaultFile, currentDefaultConf); + defaultConf = currentDefaultConf; + } catch (e) { fs.outputJSONSync(dataDir + path.sep + defaultFile, defaultConf); } fs.walk(dataDir) - .on("data", (item) => { - let fileinfo = path.parse(item.path); - if(!fileinfo.ext) return; - if(fileinfo.name == "default") return; - const guildID = fileinfo.name; - const thisConf = fs.readJSONSync(path.resolve(dataDir + path.sep + fileinfo.base)); - guildConfs.set(guildID, thisConf); - }) - .on("end", () => { - client.emit("confsRead"); - }); + .on("data", (item) => { + let fileinfo = path.parse(item.path); + if (!fileinfo.ext) return; + if (fileinfo.name == "default") return; + const guildID = fileinfo.name; + const thisConf = fs.readJSONSync(path.resolve(dataDir + path.sep + fileinfo.base)); + guildConfs.set(guildID, thisConf); + }) + .on("end", () => { + client.emit("confsRead"); + }); }; exports.remove = (guild) => { - if(!guildConfs.has(guild.id)) { + if (!guildConfs.has(guild.id)) { return console.log(`Attempting to remove ${guild.name} but it's not there.`); } @@ -56,36 +56,36 @@ exports.has = (guild) => { exports.get = (guild) => { let conf = {}; - if(!!guild && guildConfs.has(guild.id)) { + if (!!guild && guildConfs.has(guild.id)) { let guildConf = guildConfs.get(guild.id); - for(let key in guildConf) { - if(guildConf[key]) conf[key] = guildConf[key].data; + for (let key in guildConf) { + if (guildConf[key]) conf[key] = guildConf[key].data; else conf[key] = defaultConf[key].data; } } - for(let key in defaultConf) { - if(!conf[key]) conf[key] = defaultConf[key].data; + for (let key in defaultConf) { + if (!conf[key]) conf[key] = defaultConf[key].data; } return conf; }; exports.addKey = (key, defaultValue) => { let type = defaultValue.constructor.name; - if(["TextChannel", "GuildChannel", "Message", "User", "GuildMember", "Guild", "Role", "VoiceChannel", "Emoji", "Invite"].includes(type)) { + if (["TextChannel", "GuildChannel", "Message", "User", "GuildMember", "Guild", "Role", "VoiceChannel", "Emoji", "Invite"].includes(type)) { defaultValue = defaultValue.id; } - if(defaultValue.constructor.name !== type && defaultValue.constructor.name !== null) { + if (defaultValue.constructor.name !== type && defaultValue.constructor.name !== null) { return false; } - defaultConf[key] = {type: defaultValue.constructor.name, data: defaultValue}; + defaultConf[key] = { type: defaultValue.constructor.name, data: defaultValue }; fs.outputJSONSync(path.resolve(dataDir + path.sep + "default.json"), defaultConf); }; exports.setKey = (key, defaultValue) => { - if(!(key in defaultConf)) { + if (!(key in defaultConf)) { throw new Error(`:x: The key \`${key}\` does not seem to be present in the default configuration.`); } - if(defaultValue.constructor.name !== defaultConf[key].type) { + if (defaultValue.constructor.name !== defaultConf[key].type) { throw new Error(`:x: The key \`${key}\` does not correspond to the type: ${defaultConf[key].type}.`); } defaultConf[key].data = defaultValue; @@ -93,11 +93,11 @@ exports.setKey = (key, defaultValue) => { }; exports.resetKey = (guild, key) => { - if(!guildConfs.has(guild.id)) { + if (!guildConfs.has(guild.id)) { throw new Error(`:x: The guild ${guild.id} not found while trying to reset ${key}`); } let thisConf = this.get(guild); - if(!(key in thisConf)) { + if (!(key in thisConf)) { throw new Error(`:x: The key \`${key}\` does not seem to be present in the server configuration.`); } delete thisConf[key]; @@ -106,14 +106,14 @@ exports.resetKey = (guild, key) => { }; exports.delKey = (key, delFromAll) => { - if(!(key in defaultConf)) { + if (!(key in defaultConf)) { throw new Error(`:x: The key \`${key}\` does not seem to be present in the default configuration.`); } - if(["serverID", "serverName", "prefix"].includes(key)) { + if (["serverID", "serverName", "prefix"].includes(key)) { throw new Error(`:x: The key \`${key}\` is core and cannot be deleted.`); } delete defaultConf[key]; - if(delFromAll) { + if (delFromAll) { guildConfs.forEach(conf => { delete conf[key]; fs.outputJSONSync(path.resolve(dataDir + path.sep + conf.guildID + ".json"), conf); @@ -127,24 +127,24 @@ exports.hasKey = (key) => { exports.set = (guild, key, value) => { let thisConf = {}; - if(guildConfs.has(guild.id)) { + if (guildConfs.has(guild.id)) { thisConf = guildConfs.get(guild.id); } - if(!(key in defaultConf)) { + if (!(key in defaultConf)) { throw new Error(`:x: The key \`${key}\` is not valid according to the Default Configuration.`); } - if(value.constructor.name !== defaultConf[key].type) { + if (value.constructor.name !== defaultConf[key].type) { throw new Error(`:x: The key \`${key}\` does not correspond to the type: ${defaultConf[key].type}.`); } let type = value.constructor.name; - if(["TextChannel", "GuildChannel", "Message", "User", "GuildMember", "Guild", "Role", "VoiceChannel", "Emoji", "Invite"].includes(type)) { + if (["TextChannel", "GuildChannel", "Message", "User", "GuildMember", "Guild", "Role", "VoiceChannel", "Emoji", "Invite"].includes(type)) { value = value.id; } - thisConf[key] = {data : value , type : defaultConf[key].type}; + thisConf[key] = { data: value, type: defaultConf[key].type }; guildConfs.set(guild.id, thisConf); fs.outputJSONSync(path.resolve(dataDir + path.sep + guild.id + ".json"), thisConf); diff --git a/functions/getFileListing.js b/functions/getFileListing.js index c5ea33c1..7a34b2b6 100644 --- a/functions/getFileListing.js +++ b/functions/getFileListing.js @@ -2,43 +2,43 @@ const path = require("path"); const fs = require("fs-extra"); module.exports = (client, baseDir, type) => { - return new Promise( (resolve, reject) => { + return new Promise((resolve, reject) => { let dir = path.resolve(`${baseDir}/${type}/`); let files = []; try { fs.walk(dir) - .on("data", (item) => { - let fileinfo = path.parse(item.path); - if(!fileinfo.ext) return; - files.push({ - path: fileinfo.dir, - name: fileinfo.name, - base: fileinfo.base, - ext: fileinfo.ext - }); - }) - .on("end", () => { - //client.funcs.log(`Modules: ${categories.join(",")}`); - resolve(files); - }) - .on("errors", (root, nodeStatsArray, next) => { - nodeStatsArray.forEach(function (n) { - client.funcs.log("[ERROR] " + n.name, "error"); - client.funcs.log(n.error.message || (n.error.code + ": " + n.error.path), "error"); + .on("data", (item) => { + let fileinfo = path.parse(item.path); + if (!fileinfo.ext) return; + files.push({ + path: fileinfo.dir, + name: fileinfo.name, + base: fileinfo.base, + ext: fileinfo.ext + }); + }) + .on("end", () => { + //client.funcs.log(`Modules: ${categories.join(",")}`); + resolve(files); + }) + .on("errors", (root, nodeStatsArray, next) => { + nodeStatsArray.forEach(function(n) { + client.funcs.log("[ERROR] " + n.name, "error"); + client.funcs.log(n.error.message || (n.error.code + ": " + n.error.path), "error"); + }); + next(); }); - next(); - }); } catch (e) { if (e.code === "MODULE_NOT_FOUND") { let module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1,-1)) - .then(() => { - client.funcs.loadCommands(client); - }) - .catch(e => { - console.error(e); - process.exit(); - }); + client.funcs.installNPM(module[0].slice(1, -1)) + .then(() => { + client.funcs.loadCommands(client); + }) + .catch(e => { + console.error(e); + process.exit(); + }); } else { reject(e); } diff --git a/functions/loadCommandInhibitors.js b/functions/loadCommandInhibitors.js index 95016e6d..e654778f 100644 --- a/functions/loadCommandInhibitors.js +++ b/functions/loadCommandInhibitors.js @@ -3,7 +3,7 @@ const path = require("path"); module.exports = client => { client.commandInhibitors.clear(); - let counts = [0,0]; + let counts = [0, 0]; loadCommandInhibitors(client, client.coreBaseDir, counts).then(counts => { loadCommandInhibitors(client, client.clientBaseDir, counts).then(counts => { let [p, o] = counts; @@ -14,14 +14,14 @@ module.exports = client => { }; const loadCommandInhibitors = (client, baseDir, counts) => { - return new Promise( (resolve, reject) => { + return new Promise((resolve, reject) => { let dir = path.resolve(baseDir + "./inhibitors/"); fs.ensureDir(dir, err => { if (err) console.error(err); fs.readdir(dir, (err, files) => { if (err) console.error(err); let [p, o] = counts; - try{ + try { files = files.filter(f => { return f.slice(-3) === ".js"; }); files.forEach(f => { let file = f.split("."); @@ -40,14 +40,14 @@ const loadCommandInhibitors = (client, baseDir, counts) => { } catch (e) { if (e.code === "MODULE_NOT_FOUND") { let module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1,-1)) - .then(() => { - client.funcs.loadCommandInhibitors(client); - }) - .catch(e => { - console.error(e); - process.exit(); - }); + client.funcs.installNPM(module[0].slice(1, -1)) + .then(() => { + client.funcs.loadCommandInhibitors(client); + }) + .catch(e => { + console.error(e); + process.exit(); + }); } else { console.error(e); } diff --git a/functions/loadDataProviders.js b/functions/loadDataProviders.js index 3996b708..43222710 100644 --- a/functions/loadDataProviders.js +++ b/functions/loadDataProviders.js @@ -4,7 +4,7 @@ const path = require("path"); module.exports = client => { client.dataProviders.clear(); let counts = [0, 0]; - loadDataProviders(client, client.coreBaseDir, counts).then(counts=>{ + loadDataProviders(client, client.coreBaseDir, counts).then(counts => { loadDataProviders(client, client.clientBaseDir, counts).then(counts => { let [d, o] = counts; client.funcs.log(`Loaded ${d} database handlers, with ${o} optional.`); @@ -20,7 +20,7 @@ const loadDataProviders = (client, baseDir, counts) => { fs.readdir(dir, (err, files) => { if (err) console.error(err); let [d, o] = counts; - try{ + try { files = files.filter(f => { return f.slice(-3) === ".js"; }); files.forEach(f => { let file = f.split("."); @@ -40,14 +40,14 @@ const loadDataProviders = (client, baseDir, counts) => { } catch (e) { if (e.code === "MODULE_NOT_FOUND") { let module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1,-1)) - .then(() => { - client.funcs.loadDataProviders(client, baseDir, counts); - }) - .catch(e => { - console.error(e); - process.exit(); - }); + client.funcs.installNPM(module[0].slice(1, -1)) + .then(() => { + client.funcs.loadDataProviders(client, baseDir, counts); + }) + .catch(e => { + console.error(e); + process.exit(); + }); } else { reject(e); } diff --git a/functions/loadEvents.js b/functions/loadEvents.js index 723df0a5..29386f66 100644 --- a/functions/loadEvents.js +++ b/functions/loadEvents.js @@ -13,18 +13,18 @@ module.exports = client => { }; const loadEvents = (client, baseDir, count) => { - return new Promise( (resolve, reject) => { + return new Promise((resolve, reject) => { let dir = path.resolve(baseDir + "./events/"); fs.ensureDir(dir, err => { - if(err) reject(err); + if (err) reject(err); fs.readdir(dir, (err, files) => { - if(err) reject(err); + if (err) reject(err); let e = count; files = files.filter(f => { let name = f.split(".")[0]; return events.includes(name); }); - files.forEach(f=> { + files.forEach(f => { let name = f.split(".")[0]; client.on(name, (...args) => require(`${dir}/${f}`).run(client, ...args)); e++; diff --git a/functions/loadFunctions.js b/functions/loadFunctions.js index 5ee6b40a..012e6f15 100644 --- a/functions/loadFunctions.js +++ b/functions/loadFunctions.js @@ -2,7 +2,7 @@ const fs = require("fs-extra"); const path = require("path"); module.exports = client => { - return new Promise( (resolve, reject) => { + return new Promise((resolve, reject) => { let counts = [0, 0]; loadFunctions(client, client.coreBaseDir, counts).then(counts => { loadFunctions(client, client.clientBaseDir, counts).then(counts => { @@ -15,17 +15,17 @@ module.exports = client => { }; const loadFunctions = (client, baseDir, counts) => { - return new Promise( (resolve, reject) => { + return new Promise((resolve, reject) => { let dir = path.resolve(baseDir + "./functions/"); fs.ensureDirSync(dir); fs.readdir(dir, (err, files) => { if (err) reject(err); files = files.filter(f => { return f.slice(-3) === ".js"; }); - let [d,o] = counts; + let [d, o] = counts; try { - files.forEach(f=> { + files.forEach(f => { let file = f.split("."); - if(file[0] === "loadFunctions") return; + if (file[0] === "loadFunctions") return; if (file[1] !== "opt") { client.funcs[file[0]] = require(`${dir}/${f}`); d++; @@ -38,14 +38,14 @@ const loadFunctions = (client, baseDir, counts) => { } catch (e) { if (e.code === "MODULE_NOT_FOUND") { let module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1,-1)) - .then(() => { - client.funcs.loadDatabaseHandlers(client); - }) - .catch(e => { - console.error(e); - process.exit(); - }); + client.funcs.installNPM(module[0].slice(1, -1)) + .then(() => { + client.funcs.loadDatabaseHandlers(client); + }) + .catch(e => { + console.error(e); + process.exit(); + }); } else { reject(e); } diff --git a/functions/loadSingleCommand.js b/functions/loadSingleCommand.js index 670eebd1..a46d89d4 100644 --- a/functions/loadSingleCommand.js +++ b/functions/loadSingleCommand.js @@ -3,12 +3,12 @@ const path = require("path"); module.exports = function(client, command, reload = false, loadPath = null) { return new Promise((resolve, reject) => { let category, subCategory, cmd; - if(!loadPath && !reload) return reject("Path must be provided when loading a new command."); - if(reload) { - if(!client.commands.has(command)) { + if (!loadPath && !reload) return reject("Path must be provided when loading a new command."); + if (reload) { + if (!client.commands.has(command)) { reject("Reload requested, but command does not exist."); } - try{ + try { cmd = client.commands.get(command); category = cmd.help.category; subCategory = cmd.help.subCategory; @@ -29,20 +29,20 @@ module.exports = function(client, command, reload = false, loadPath = null) { return reject(`The command \`${cmd.help.name}\` is only usable in selfbots!`); } let pathParts = loadPath.split(path.sep); - pathParts = pathParts.slice(pathParts.indexOf("commands")+1); + pathParts = pathParts.slice(pathParts.indexOf("commands") + 1); category = client.funcs.toTitleCase(cmd.help.category ? cmd.help.category : (pathParts[0] && pathParts[0].length > 0 ? pathParts[0] : "General")); subCategory = client.funcs.toTitleCase(cmd.help.subCategory ? cmd.help.subCategory : (pathParts[1] && pathParts[1].length > 0 && !~pathParts[1].indexOf(".") ? pathParts[1] : "General")); } catch (e) { if (e.code === "MODULE_NOT_FOUND") { let module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1,-1)) - .then(() => { - client.funcs.loadSingleCommand(client, command, false, loadPath); - }) - .catch(e => { - console.error(e); - process.exit(); - }); + client.funcs.installNPM(module[0].slice(1, -1)) + .then(() => { + client.funcs.loadSingleCommand(client, command, false, loadPath); + }) + .catch(e => { + console.error(e); + process.exit(); + }); } else { reject(`Could not load new command data: ${e.stack}`); } @@ -59,13 +59,12 @@ module.exports = function(client, command, reload = false, loadPath = null) { client.aliases.set(alias, cmd.help.name); }); - // update help structure - if(!client.helpStructure.has(category)) { + if (!client.helpStructure.has(category)) { client.helpStructure.set(category, new Map()); } let catMap = client.helpStructure.get(category); - if(!catMap.has(subCategory)) { + if (!catMap.has(subCategory)) { catMap.set(subCategory, new Map()); } let subCatMap = catMap.get(subCategory); diff --git a/functions/parseTags.js b/functions/parseTags.js index 94cfcc24..2f5991aa 100644 --- a/functions/parseTags.js +++ b/functions/parseTags.js @@ -184,14 +184,14 @@ module.exports = (command, disallowCharacters) => { type: "loop" }); - //tags[tags.length -1].loop = true; + //tags[tags.length -1].loop = true; closed = true; } else - tags.push({ - type: c === ">" ? "required" : "optional", - possibles: parseTagData(current, disallowCharacters, tags.length + 1) - }); + tags.push({ + type: c === ">" ? "required" : "optional", + possibles: parseTagData(current, disallowCharacters, tags.length + 1) + }); current = ""; opened = null; diff --git a/functions/permissionLevel.js b/functions/permissionLevel.js index e08ae418..be24db91 100644 --- a/functions/permissionLevel.js +++ b/functions/permissionLevel.js @@ -2,7 +2,7 @@ module.exports = (client, user, guild = null) => { return new Promise((resolve, reject) => { let guildConf = client.funcs.confs.get(guild); let permlvl = 0; - if(guild) { + if (guild) { try { let member = guild.member(user); let mod_role = guild.roles.find("name", guildConf.mod_role); @@ -11,7 +11,7 @@ module.exports = (client, user, guild = null) => { let admin_role = guild.roles.find("name", guildConf.admin_role); if (admin_role && member.roles.has(admin_role.id)) permlvl = 3; - if(member === guild.owner) + if (member === guild.owner) permlvl = 4; } catch (e) { reject(e); diff --git a/functions/runCommandInhibitors.js b/functions/runCommandInhibitors.js index 96026657..4e6fb2db 100644 --- a/functions/runCommandInhibitors.js +++ b/functions/runCommandInhibitors.js @@ -1,5 +1,5 @@ module.exports = (client, msg, cmd, selective = false) => { - return new Promise ((resolve, reject) => { + return new Promise((resolve, reject) => { let mps = [true]; let i = 1; let usage; @@ -11,10 +11,10 @@ module.exports = (client, msg, cmd, selective = false) => { i++; }); Promise.all(mps) - .then(value => { - resolve(value[usage]); - }, reason => { - reject(reason); - }); + .then(value => { + resolve(value[usage]); + }, reason => { + reject(reason); + }); }); }; diff --git a/functions/validateData.js b/functions/validateData.js index 68236428..2c602f93 100644 --- a/functions/validateData.js +++ b/functions/validateData.js @@ -27,7 +27,6 @@ module.exports = (data, properties, values) => { throw `at value #${i +1}: Can't be null`; } - switch (bound.type) { case "autots": case "autoid": diff --git a/inhibitors/permissions.js b/inhibitors/permissions.js index 49fa6b3d..6e99fb4a 100644 --- a/inhibitors/permissions.js +++ b/inhibitors/permissions.js @@ -6,11 +6,11 @@ exports.conf = { exports.run = (client, msg, cmd) => { return new Promise((resolve, reject) => { client.funcs.permissionLevel(client, msg.author, msg.guild) - .then(permlvl => { - if (permlvl >= cmd.conf.permLevel) - resolve(); - else - reject("You do not have permission to use this command."); - }); + .then(permlvl => { + if (permlvl >= cmd.conf.permLevel) + resolve(); + else + reject("You do not have permission to use this command."); + }); }); }; diff --git a/inhibitors/selfBot.js b/inhibitors/selfBot.js index 20ec76f9..a60746c7 100644 --- a/inhibitors/selfBot.js +++ b/inhibitors/selfBot.js @@ -5,7 +5,7 @@ exports.conf = { exports.run = (client, msg, cmd) => { return new Promise((resolve, reject) => { - if(client.config.selfbot) { + if (client.config.selfbot) { if (msg.author === client.user) { resolve(); } else { diff --git a/inhibitors/usage.js b/inhibitors/usage.js index f79364c4..b35db7e3 100644 --- a/inhibitors/usage.js +++ b/inhibitors/usage.js @@ -109,7 +109,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be true or false.`) + reject(`${currentUsage.possibles[0].name} must be true or false.`); } break; case "member": @@ -379,7 +379,7 @@ exports.run = (client, msg, cmd) => { case "user": case "mention": const result = /\d+/.exec(args[i]); - if (result && args[i].length > 5 && client.users.has(result[0])) { + if (result && args[i].length > 5 && client.users.has(result[0])) { args[i] = client.users.get(/\d+/.exec(args[i])[0]); validated = true; multiPossibles(++p); @@ -398,7 +398,7 @@ exports.run = (client, msg, cmd) => { } break; case "member": - if (result && args[i].length > 5 && msg.guild.members.has(result[0])) { + if (result && args[i].length > 5 && msg.guild.members.has(result[0])) { args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); validated = true; multiPossibles(++p); From 9ccdbffbf89712b33c0e14c621ec947134b3b4a8 Mon Sep 17 00:00:00 2001 From: CyberiumShadow Date: Tue, 8 Nov 2016 23:46:06 +1100 Subject: [PATCH 23/51] Updated ESLint to allow Template Literals --- .eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 6e07f9bc..4613a956 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,7 +9,7 @@ "no-console": "off", "indent": ["error", 2, { "SwitchCase": 1 } ], "linebreak-style": "off", - "quotes": [ "warn", "double" ], + "quotes": [ "warn", "double", { "allowTemplateLiterals": true }], "semi": [ "warn", "always" ] } } From 5c05aa74b54d2952f3f08a1f7329fb052cc8d321 Mon Sep 17 00:00:00 2001 From: bdistin Date: Thu, 10 Nov 2016 15:05:04 -0600 Subject: [PATCH 24/51] Fix Resolves/Rejects to stop executing further code --- inhibitors/usage.js | 64 ++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/inhibitors/usage.js b/inhibitors/usage.js index b35db7e3..8c799f42 100644 --- a/inhibitors/usage.js +++ b/inhibitors/usage.js @@ -12,11 +12,11 @@ exports.run = (client, msg, cmd) => { if (args[0] === "") args = []; let currentUsage; let repeat = false; - if (usage.length === 0) resolve(); + if (usage.length === 0) return resolve(); (function validateArgs(i) { if (i >= usage.length && i >= args.length) { - resolve(args); + return resolve(args); } else if (usage[i]) { if (usage[i].type !== "repeat") { //Handle if args length > usage length currentUsage = usage[i]; @@ -25,16 +25,16 @@ exports.run = (client, msg, cmd) => { repeat = true; } } else if (!repeat) { //Handle if usage does not end in a repeat - resolve(args); + return resolve(args); } if (currentUsage.type === "optional" && (args[i] === undefined || args[i] === "")) { //Handle if args length < required usage length if (usage.slice(i).some(u => { return u.type === "required"; })) { - reject("Missing one or more required arguments after end of input."); + return reject("Missing one or more required arguments after end of input."); } else { - resolve(args); + return resolve(args); } } else if (currentUsage.type === "required" && args[i] === undefined) { - reject(currentUsage.possibles.length === 1 ? `${currentUsage.possibles[0].name} is a required argument.` : `Missing a required option: (${currentUsage.possibles.map(p => {return p.name;}).join(", ")})`); + return reject(currentUsage.possibles.length === 1 ? `${currentUsage.possibles[0].name} is a required argument.` : `Missing a required option: (${currentUsage.possibles.map(p => {return p.name;}).join(", ")})`); } else if (currentUsage.possibles.length === 1) { switch (currentUsage.possibles[0].type) { case "literal": @@ -45,7 +45,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`Your option did not litterally match the only possibility: (${currentUsage.possibles.map(p => {return p.name;}).join(", ")})\nThis is likely caused by a mistake in the usage string.`); + return reject(`Your option did not litterally match the only possibility: (${currentUsage.possibles.map(p => {return p.name;}).join(", ")})\nThis is likely caused by a mistake in the usage string.`); } break; case "msg": @@ -62,7 +62,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be a valid message id.`); + return reject(`${currentUsage.possibles[0].name} must be a valid message id.`); } }); } else { @@ -76,7 +76,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be a valid message id.`); + return reject(`${currentUsage.possibles[0].name} must be a valid message id.`); } }); } @@ -84,7 +84,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be a valid message id.`); + return reject(`${currentUsage.possibles[0].name} must be a valid message id.`); } break; case "user": @@ -96,7 +96,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); + return reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); } break; case "boolean": @@ -109,7 +109,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be true or false.`); + return reject(`${currentUsage.possibles[0].name} must be true or false.`); } break; case "member": @@ -120,7 +120,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); + return reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); } break; case "channel": @@ -131,7 +131,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be a channel tag or valid channel id.`); + return reject(`${currentUsage.possibles[0].name} must be a channel tag or valid channel id.`); } break; case "guild": @@ -142,7 +142,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be a valid guild id.`); + return reject(`${currentUsage.possibles[0].name} must be a valid guild id.`); } break; case "role": @@ -153,7 +153,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be a role mention or role id.`); + return reject(`${currentUsage.possibles[0].name} must be a role mention or role id.`); } break; case "str": @@ -165,9 +165,9 @@ exports.run = (client, msg, cmd) => { validateArgs(++i); } else { if (currentUsage.possibles[0].min === currentUsage.possibles[0].max) { - reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min} characters.`); + return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min} characters.`); } else { - reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max} characters.`); + return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max} characters.`); } } } else { @@ -179,7 +179,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be longer than ${currentUsage.possibles[0].min} characters.`); + return reject(`${currentUsage.possibles[0].name} must be longer than ${currentUsage.possibles[0].min} characters.`); } } else { validateArgs(++i); @@ -190,7 +190,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be shorter than ${currentUsage.possibles[0].max} characters.`); + return reject(`${currentUsage.possibles[0].name} must be shorter than ${currentUsage.possibles[0].max} characters.`); } } else { validateArgs(++i); @@ -206,7 +206,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be an integer.`); + return reject(`${currentUsage.possibles[0].name} must be an integer.`); } } else if (currentUsage.possibles[0].min && currentUsage.possibles[0].max) { args[i] = parseInt(args[i]); @@ -216,14 +216,14 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min}\nSo why didn't the dev use a literal?`); + return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min}\nSo why didn't the dev use a literal?`); } } else { if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); + return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); } } } else { @@ -236,7 +236,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be greater than ${currentUsage.possibles[0].min}.`); + return reject(`${currentUsage.possibles[0].name} must be greater than ${currentUsage.possibles[0].min}.`); } } else { validateArgs(++i); @@ -248,7 +248,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be less than ${currentUsage.possibles[0].max}.`); + return reject(`${currentUsage.possibles[0].name} must be less than ${currentUsage.possibles[0].max}.`); } } else { validateArgs(++i); @@ -266,7 +266,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be a valid number.`); + return reject(`${currentUsage.possibles[0].name} must be a valid number.`); } } else if (currentUsage.possibles[0].min && currentUsage.possibles[0].max) { args[i] = parseFloat(args[i]); @@ -276,14 +276,14 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min}\nSo why didn't the dev use a literal?`); + return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min}\nSo why didn't the dev use a literal?`); } } else { if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); + return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); } } } else { @@ -296,7 +296,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be greater than ${currentUsage.possibles[0].min}.`); + return reject(`${currentUsage.possibles[0].name} must be greater than ${currentUsage.possibles[0].min}.`); } } else { validateArgs(++i); @@ -308,7 +308,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be less than ${currentUsage.possibles[0].max}.`); + return reject(`${currentUsage.possibles[0].name} must be less than ${currentUsage.possibles[0].max}.`); } } else { validateArgs(++i); @@ -324,7 +324,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`${currentUsage.possibles[0].name} must be a valid url.`); + return reject(`${currentUsage.possibles[0].name} must be a valid url.`); } } else { validateArgs(++i); @@ -346,7 +346,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - reject(`Your option didn't match any of the possibilities: (${currentUsage.possibles.map(p => {return p.name;}).join(", ")})`); + return reject(`Your option didn't match any of the possibilities: (${currentUsage.possibles.map(p => {return p.name;}).join(", ")})`); } return; } From 48f29662f397a72be8adbbf92a7f1b259e40ae31 Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Fri, 18 Nov 2016 14:36:37 +1100 Subject: [PATCH 25/51] Delete .jsbeautifyrc --- .jsbeautifyrc | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 .jsbeautifyrc diff --git a/.jsbeautifyrc b/.jsbeautifyrc deleted file mode 100644 index 05f9a2eb..00000000 --- a/.jsbeautifyrc +++ /dev/null @@ -1,30 +0,0 @@ -{ - "allowed_file_extensions": ["js", "json", "jshintrc", "jsbeautifyrc"], - - // Set brace_style - // collapse: (old default) Put braces on the same line as control statements - // collapse-preserve-inline: (new default) Same as collapse but better support for ES6 destructuring and other features. https://github.com/victorporof/Sublime-HTMLPrettify/issues/231 - // expand: Put braces on own line (Allman / ANSI style) - // end-expand: Put end braces on own line - // none: Keep them where they are - "brace_style": "collapse-preserve-inline", - - "break_chained_methods": false, // Break chained method calls across subsequent lines - "e4x": false, // Pass E4X xml literals through untouched - "end_with_newline": false, // End output with newline - "indent_char": " ", // Indentation character - "indent_level": 0, // Initial indentation level - "indent_size": 2, // Indentation size - "indent_with_tabs": false, // Indent with tabs, overrides `indent_size` and `indent_char` - "jslint_happy": false, // If true, then jslint-stricter mode is enforced - "keep_array_indentation": false, // Preserve array indentation - "keep_function_indentation": false, // Preserve function indentation - "max_preserve_newlines": 2, // Maximum number of line breaks to be preserved in one chunk (0 disables) - "preserve_newlines": true, // Whether existing line breaks should be preserved - "space_after_anon_function": false, // Should the space before an anonymous function's parens be added, "function()" vs "function ()" - "space_before_conditional": true, // Should the space before conditional statement be added, "if(true)" vs "if (true)" - "space_in_empty_paren": false, // Add padding spaces within empty paren, "f()" vs "f( )" - "space_in_paren": false, // Add padding spaces within paren, ie. f( a, b ) - "unescape_strings": false, // Should printable characters in strings encoded in \xNN notation be unescaped, "example" vs "\x65\x78\x61\x6d\x70\x6c\x65" - "wrap_line_length": 0 // Lines should wrap at next opportunity after this number of characters (0 disables) -} From 17d767e7dc16a37938e892008ef1eb681039b29d Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Fri, 18 Nov 2016 14:39:21 +1100 Subject: [PATCH 26/51] Update .eslintrc.json --- .eslintrc.json | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 4613a956..6e8dea04 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,13 +3,20 @@ "es6": true, "node": true }, - "extends": "eslint:recommended", + "extends": "airbnb-base", "parserOptions": { "sourceType": "module" }, "rules": { "no-console": "off", - "indent": ["error", 2, { "SwitchCase": 1 } ], + "indent": ["error", 2, { "SwitchCase": 1 }], "linebreak-style": "off", - "quotes": [ "warn", "double", { "allowTemplateLiterals": true }], - "semi": [ "warn", "always" ] + "quotes": ["warn", "double", { "allowTemplateLiterals": true }], + "semi": ["warn", "always"], + "no-param-reassign": "off", + "no-shadow": "warn", + "no-plusplus": "off", + "radix": ["error", "as-needed"], + "max-len": "warn", + "import/no-extraneous-dependencies": "off", + "import/no-unresolved": "off" } } From 7c1bcd899b1837150eb4141d410a35e3e5ad776e Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Fri, 18 Nov 2016 14:41:10 +1100 Subject: [PATCH 27/51] Update package.json --- package.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 5352504f..0bc2c517 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "main": "app.js", "scripts": { "start": "node app.js", - "lint": "eslint commands functions inhibitors", - "test": "echo \"Error: no test specified\" && exit 1" + "lint": "eslint commands functions inhibitors, events", + "lint:fix": "npm run lint -- --fix" }, "repository": { "type": "git", @@ -28,6 +28,8 @@ "node": ">=6.0.0" }, "devDependencies": { - "eslint": "^3.8.1" + "eslint": "^3.10.2", + "eslint-config-airbnb-base": "^10.0.1", + "eslint-plugin-import": "^2.2.0" } } From 7fbb90b3bd606c765d638b78e42099dbb00a2ea8 Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Fri, 18 Nov 2016 14:41:54 +1100 Subject: [PATCH 28/51] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0bc2c517..283d0567 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "chalk": "^1.1.3", "discord.js": "hydrabolt/discord.js#indev", "fs-extra": "^0.30.0", - "moment": "^2.15.1", + "moment": "^2.16.0", "moment-duration-format": "^1.3.0" }, "engines": { From c0fca36c0039e5cd9b190544adabe0b3968d5f3d Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Fri, 18 Nov 2016 14:42:18 +1100 Subject: [PATCH 29/51] Various Changes. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 283d0567..7fbc90a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "komada", - "version": "0.8.5", + "version": "0.8.7", "author": "Evelyne Lachance", "description": "Komada: Croatian for 'pieces', is a modular bot system including reloading modules and easy to use custom commands.", "main": "app.js", From 1f7aa4d975d0cf94b857812e4e44bdef3baa05f2 Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Fri, 18 Nov 2016 14:48:17 +1100 Subject: [PATCH 30/51] Update .eslintrc.json --- .eslintrc.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 6e8dea04..3801676c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,12 +4,11 @@ "node": true }, "extends": "airbnb-base", - "parserOptions": { "sourceType": "module" }, "rules": { "no-console": "off", "indent": ["error", 2, { "SwitchCase": 1 }], "linebreak-style": "off", - "quotes": ["warn", "double", { "allowTemplateLiterals": true }], + "quotes": ["warn", "double"], "semi": ["warn", "always"], "no-param-reassign": "off", "no-shadow": "warn", @@ -17,6 +16,11 @@ "radix": ["error", "as-needed"], "max-len": "warn", "import/no-extraneous-dependencies": "off", - "import/no-unresolved": "off" + "import/no-unresolved": "off", + "no-prototype-builtins": "warn", + "no-restricted-syntax": "warn", + "guard-for-in": "warn", + "consistent-return": ["warn", { "treatUndefinedAsUnspecified": true }], + "no-use-before-define": ["warn", { "functions": true, "classes": true }] } } From a496543bf5d70c0f92ed286de8aeca213c66bf9c Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Fri, 18 Nov 2016 14:54:37 +1100 Subject: [PATCH 31/51] Fixed --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7fbc90a3..b088251b 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "app.js", "scripts": { "start": "node app.js", - "lint": "eslint commands functions inhibitors, events", + "lint": "eslint commands functions inhibitors events", "lint:fix": "npm run lint -- --fix" }, "repository": { @@ -20,7 +20,7 @@ "dependencies": { "chalk": "^1.1.3", "discord.js": "hydrabolt/discord.js#indev", - "fs-extra": "^0.30.0", + "fs-extra": "^1.0.0", "moment": "^2.16.0", "moment-duration-format": "^1.3.0" }, From 3aeb37e15b17f6ce89854eee1612330ca28e5dba Mon Sep 17 00:00:00 2001 From: Faith Date: Sat, 19 Nov 2016 00:19:04 -0500 Subject: [PATCH 32/51] Conf.js Fix && Eslint --- commands/System/conf.js | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/commands/System/conf.js b/commands/System/conf.js index 4e9760cb..c4bcfdbd 100644 --- a/commands/System/conf.js +++ b/commands/System/conf.js @@ -1,33 +1,28 @@ -exports.run = (client, msg, [action, key, ... value]) => { +exports.run = (client, msg, [action, key, ...value]) => { - if (msg.guildConf[key].constructor.name === "String") { - value = value.join(' '); - } else - if (msg.guildConf[key].constructor.name === "Boolean") { - value = value[0]; - } else { - value = value; - } - - if(action === "list") { + if (action === "list") { msg.channel.sendCode("json", require("util").inspect(msg.guildConf)); - return; } else - if(action === "get") { - if(!key) return msg.reply("Please provide a key you wish to view"); + if (action === "get") { + if (!key) return msg.reply("Please provide a key you wish to view"); msg.reply(`The value for ${key} is currently: ${msg.guildConf[key]}`); - return; } else - if(action === "set") { - if(!key || value === undefined) return msg.reply("Please provide both a key and value!"); + if (action === "set") { + if (!key || value === undefined) return msg.reply("Please provide both a key and value!"); + if (msg.guildConf[key].constructor.name === "String") { + value = value.join(" "); + } else + if (msg.guildConf[key].constructor.name === "Boolean") { + value = value[0]; + } client.funcs.confs.set(msg.guild, key, value); return msg.reply(`The value for ${key} has been set to: ${value}`); } else - if(action === "reset") { - if(!key) return msg.reply("Please provide a key you wish to reset"); + if (action === "reset") { + if (!key) return msg.reply("Please provide a key you wish to reset"); client.funcs.confs.resetKey(msg.guild, key); return msg.reply("The key has been reset."); } @@ -39,12 +34,12 @@ exports.conf = { aliases: [], permLevel: 3, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "conf", description: "Define per-server configuration.", usage: " [key:str] [boolean:boolean|channel:channel|user:user|role:role|int:int|str:str]", - usageDelim: " " + usageDelim: " ", }; From 4dffe89ebdd5c89b4a53ea567c36f4ba241fe0d9 Mon Sep 17 00:00:00 2001 From: Faith Date: Sat, 19 Nov 2016 02:21:35 -0500 Subject: [PATCH 33/51] The Great Conf Fix --- functions/confs.js | 65 +++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/functions/confs.js b/functions/confs.js index 641d28e4..7182d55e 100644 --- a/functions/confs.js +++ b/functions/confs.js @@ -1,8 +1,9 @@ const fs = require("fs-extra"); const path = require("path"); + const guildConfs = new Map(); let dataDir = ""; -let defaultFile = "default.json"; +const defaultFile = "default.json"; let defaultConf = {}; exports.init = (client) => { @@ -12,27 +13,26 @@ exports.init = (client) => { prefix: { type: "String", data: client.config.prefix }, disabledCommands: { type: "Array", data: [] }, mod_role: { type: "String", data: "Mods" }, - admin_role: { type: "String", data: "Devs" } + admin_role: { type: "String", data: "Devs" }, }; - - fs.ensureFileSync(dataDir + path.sep + defaultFile); + fs.ensureFileSync(`${dataDir}${path.sep}${defaultFile}`); try { - let currentDefaultConf = fs.readJSONSync(path.resolve(dataDir + path.sep + defaultFile)); - Object.keys(defaultConf).forEach(key => { + const currentDefaultConf = fs.readJSONSync(path.resolve(`${dataDir}${path.sep}${defaultFile}`)); + Object.keys(defaultConf).forEach((key) => { if (!currentDefaultConf.hasOwnProperty(key)) currentDefaultConf[key] = defaultConf[key]; }); - fs.outputJSONSync(dataDir + path.sep + defaultFile, currentDefaultConf); + fs.outputJSONSync(path.resolve(`${dataDir}${path.sep}${defaultFile}`), currentDefaultConf); defaultConf = currentDefaultConf; } catch (e) { - fs.outputJSONSync(dataDir + path.sep + defaultFile, defaultConf); + fs.outputJSONSync(`${dataDir}${path.sep}${defaultFile}`, defaultConf); } fs.walk(dataDir) .on("data", (item) => { - let fileinfo = path.parse(item.path); + const fileinfo = path.parse(item.path); if (!fileinfo.ext) return; - if (fileinfo.name == "default") return; + if (fileinfo.name === "default") return; const guildID = fileinfo.name; - const thisConf = fs.readJSONSync(path.resolve(dataDir + path.sep + fileinfo.base)); + const thisConf = fs.readJSONSync(path.resolve(`${dataDir}${path.sep}${fileinfo.base}`)); guildConfs.set(guildID, thisConf); }) .on("end", () => { @@ -45,7 +45,7 @@ exports.remove = (guild) => { return console.log(`Attempting to remove ${guild.name} but it's not there.`); } - fs.unlinkSync(path.resolve(dataDir + path.sep + guild.id + ".json")); + fs.unlinkSync(path.resolve(`${dataDir}${path.sep}${guild.id}.json`)); return true; }; @@ -55,22 +55,22 @@ exports.has = (guild) => { }; exports.get = (guild) => { - let conf = {}; + const conf = {}; if (!!guild && guildConfs.has(guild.id)) { - let guildConf = guildConfs.get(guild.id); - for (let key in guildConf) { + const guildConf = guildConfs.get(guild.id); + for (const key in guildConf) { if (guildConf[key]) conf[key] = guildConf[key].data; else conf[key] = defaultConf[key].data; } } - for (let key in defaultConf) { + for (const key in defaultConf) { if (!conf[key]) conf[key] = defaultConf[key].data; } return conf; }; exports.addKey = (key, defaultValue) => { - let type = defaultValue.constructor.name; + const type = defaultValue.constructor.name; if (["TextChannel", "GuildChannel", "Message", "User", "GuildMember", "Guild", "Role", "VoiceChannel", "Emoji", "Invite"].includes(type)) { defaultValue = defaultValue.id; } @@ -78,7 +78,8 @@ exports.addKey = (key, defaultValue) => { return false; } defaultConf[key] = { type: defaultValue.constructor.name, data: defaultValue }; - fs.outputJSONSync(path.resolve(dataDir + path.sep + "default.json"), defaultConf); + fs.outputJSONSync(path.resolve(`${dataDir}${path.sep}${defaultFile}`), defaultConf); + return true; }; exports.setKey = (key, defaultValue) => { @@ -89,34 +90,44 @@ exports.setKey = (key, defaultValue) => { throw new Error(`:x: The key \`${key}\` does not correspond to the type: ${defaultConf[key].type}.`); } defaultConf[key].data = defaultValue; - fs.outputJSONSync(path.resolve(dataDir + path.sep + "default.json"), defaultConf); + fs.outputJSONSync(path.resolve(`${dataDir}${path.sep}${defaultFile}`), defaultConf); }; exports.resetKey = (guild, key) => { if (!guildConfs.has(guild.id)) { throw new Error(`:x: The guild ${guild.id} not found while trying to reset ${key}`); } - let thisConf = this.get(guild); + const thisConf = fs.readJSONSync(path.resolve(`${dataDir}${path.sep}${guild.id}.json`)); if (!(key in thisConf)) { throw new Error(`:x: The key \`${key}\` does not seem to be present in the server configuration.`); } delete thisConf[key]; - guildConfs.set(guild.id, thisConf); - fs.outputJSONSync(path.resolve(dataDir + path.sep + guild.id + ".json"), thisConf); + if (Object.keys(thisConf).length > 0) { + guildConfs.set(guild.id, thisConf); + fs.outputJSONSync(path.resolve(`${dataDir}${path.sep}${guild.id}.json`), thisConf); + } else { + fs.unlinkSync(path.resolve(`${dataDir}${path.sep}${guild.id}.json`)); + } }; exports.delKey = (key, delFromAll) => { if (!(key in defaultConf)) { throw new Error(`:x: The key \`${key}\` does not seem to be present in the default configuration.`); } - if (["serverID", "serverName", "prefix"].includes(key)) { + if (["mod_role", "admin_role", "disabledCommands", "prefix"].includes(key)) { throw new Error(`:x: The key \`${key}\` is core and cannot be deleted.`); } delete defaultConf[key]; + fs.outputJSONSync(path.resolve(`${dataDir}${path.sep}${defaultFile}`), defaultConf); if (delFromAll) { - guildConfs.forEach(conf => { + const MapIter = guildConfs.keys(); + guildConfs.forEach((conf) => { delete conf[key]; - fs.outputJSONSync(path.resolve(dataDir + path.sep + conf.guildID + ".json"), conf); + if (Object.keys(conf).length > 0) { + fs.outputJSONSync(path.resolve(`${dataDir}${path.sep}${MapIter.next().value}.json`), conf); + } else { + fs.unlinkSync(path.resolve(`${dataDir}${path.sep}${MapIter.next().value}.json`)); + } }); } }; @@ -139,7 +150,7 @@ exports.set = (guild, key, value) => { throw new Error(`:x: The key \`${key}\` does not correspond to the type: ${defaultConf[key].type}.`); } - let type = value.constructor.name; + const type = value.constructor.name; if (["TextChannel", "GuildChannel", "Message", "User", "GuildMember", "Guild", "Role", "VoiceChannel", "Emoji", "Invite"].includes(type)) { value = value.id; } @@ -147,7 +158,7 @@ exports.set = (guild, key, value) => { thisConf[key] = { data: value, type: defaultConf[key].type }; guildConfs.set(guild.id, thisConf); - fs.outputJSONSync(path.resolve(dataDir + path.sep + guild.id + ".json"), thisConf); + fs.outputJSONSync(path.resolve(`${dataDir}${path.sep}${guild.id}.json`), thisConf); return thisConf; }; From e891614ab3540d86d03f7e899486bcd678db5089 Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Sat, 19 Nov 2016 18:30:11 +1100 Subject: [PATCH 34/51] Update confs.js --- functions/confs.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/functions/confs.js b/functions/confs.js index 7182d55e..ad54dce4 100644 --- a/functions/confs.js +++ b/functions/confs.js @@ -50,9 +50,7 @@ exports.remove = (guild) => { return true; }; -exports.has = (guild) => { - return guildConfs.has(guild.id); -}; +exports.has = guild => guildConfs.has(guild.id); exports.get = (guild) => { const conf = {}; @@ -132,9 +130,7 @@ exports.delKey = (key, delFromAll) => { } }; -exports.hasKey = (key) => { - return (key in defaultConf); -}; +exports.hasKey = key => (key in defaultConf); exports.set = (guild, key, value) => { let thisConf = {}; From b2299fb0ee506a66895d76f75a6496c5dbb9fc78 Mon Sep 17 00:00:00 2001 From: Faith Date: Sat, 19 Nov 2016 04:40:25 -0500 Subject: [PATCH 35/51] Eslinting Patch --- app.js | 45 +++++----- commands/System/conf.js | 2 +- commands/System/disable.js | 9 +- commands/System/enable.js | 9 +- commands/System/eval.js | 9 +- commands/System/info.js | 4 +- commands/System/invite.js | 4 +- commands/System/ping.js | 6 +- commands/System/reboot.js | 10 +-- commands/System/reload.js | 22 ++--- commands/System/stats.js | 6 +- functions/addCommas.js | 4 +- functions/botPermissions.js | 13 ++- functions/clean.js | 21 +++-- functions/createDBSchema.js | 27 +++--- functions/fullUsage.js | 4 +- functions/getFileListing.js | 20 ++--- functions/impliedPermissions.js | 4 +- functions/loadCommandInhibitors.js | 26 +++--- functions/loadCommands.js | 53 ++++++----- functions/loadDataProviders.js | 36 ++++---- functions/loadEvents.js | 31 +++---- functions/loadFunctions.js | 38 ++++---- functions/loadSingleCommand.js | 18 ++-- functions/log.js | 7 +- functions/parseTags.js | 131 +++++++++++++++------------- functions/permissionLevel.js | 20 +++-- functions/runCommandInhibitors.js | 6 +- functions/toTitleCase.js | 2 +- inhibitors/disable.js | 2 +- inhibitors/guildOnly.js | 2 +- inhibitors/missingBotPermissions.js | 7 +- inhibitors/permissions.js | 9 +- inhibitors/requiredFuncs.js | 4 +- inhibitors/selfBot.js | 2 +- inhibitors/usage.js | 85 +++++++++--------- 36 files changed, 355 insertions(+), 343 deletions(-) diff --git a/app.js b/app.js index b87c7893..e5de3992 100644 --- a/app.js +++ b/app.js @@ -1,15 +1,15 @@ const Discord = require("discord.js"); const chalk = require("chalk"); + const clk = new chalk.constructor({ enabled: true }); exports.start = (config) => { - const client = new Discord.Client(config.clientOptions); client.config = config; // Extend client - client.config["init"] = []; + client.config.init = []; client.funcs = {}; client.helpStructure = new Map(); client.commands = new Discord.Collection(); @@ -17,8 +17,8 @@ exports.start = (config) => { client.commandInhibitors = new Discord.Collection(); client.dataProviders = new Discord.Collection(); - client.coreBaseDir = __dirname + "/"; - client.clientBaseDir = process.cwd() + "/"; + client.coreBaseDir = `${__dirname}/`; + client.clientBaseDir = `${__dirname}/`; // Load core functions, then everything else require("./functions/loadFunctions.js")(client).then(() => { @@ -34,32 +34,31 @@ exports.start = (config) => { }); client.once("confsRead", () => { - client.commands.forEach(command => { - if(command.init) { + client.commands.forEach((command) => { + if (command.init) { command.init(client); } }); }); - client.on("message", msg => { - let conf = client.funcs.confs.get(msg.guild); + client.on("message", (msg) => { + const conf = client.funcs.confs.get(msg.guild); msg.guildConf = conf; if (!msg.content.startsWith(conf.prefix) && !client.config.prefixMention.test(msg.content)) return; let prefixLength = conf.prefix.length; - if(client.config.prefixMention.test(msg.content)) prefixLength = client.config.prefixMention.exec(msg.content)[0].length +1; - let command = msg.content.slice(prefixLength).split(" ")[0].toLowerCase(); - let suffix = msg.content.slice(prefixLength).split(" ").slice(1).join(" "); + if (client.config.prefixMention.test(msg.content)) prefixLength = client.config.prefixMention.exec(msg.content)[0].length + 1; + const command = msg.content.slice(prefixLength).split(" ")[0].toLowerCase(); + const suffix = msg.content.slice(prefixLength).split(" ").slice(1).join(" "); let commandLog; switch (msg.channel.type) { - case "text": - commandLog = `${clk.black.bgYellow(`${msg.author.username}<@${msg.author.id}>`)} : ${clk.bold(command)}('${suffix ? suffix : ""}') => ${clk.bgGreen(`${msg.guild.name}[${msg.guild.id}]`)}`; - break; case "dm": - commandLog = `${clk.black.bgYellow(`${msg.author.username}<@${msg.author.id}>`)} : ${clk.bold(command)}('${suffix ? suffix : ""}') => ${clk.bgMagenta("[Direct Messages]")}`; + commandLog = `${clk.black.bgYellow(`${msg.author.username}<@${msg.author.id}>`)} : ${clk.bold(command)}('${suffix}') => ${clk.bgMagenta("[Direct Messages]")}`; break; - case "group": //works for selfbots only - commandLog = `${clk.black.bgYellow(`${msg.author.username}<@${msg.author.id}>`)} : ${clk.bold(command)}('${suffix ? suffix : ""}') => ${clk.bgCyan(`${msg.channel.owner.username}[${msg.channel.owner.id}] in [GroupDM]`)}`; + case "group": // works for selfbots only + commandLog = `${clk.black.bgYellow(`${msg.author.username}<@${msg.author.id}>`)} : ${clk.bold(command)}('${suffix}') => ${clk.bgCyan(`${msg.channel.owner.username}[${msg.channel.owner.id}] in [GroupDM]`)}`; break; + default: // text channels + commandLog = `${clk.black.bgYellow(`${msg.author.username}<@${msg.author.id}>`)} : ${clk.bold(command)}('${suffix}') => ${clk.bgGreen(`${msg.guild.name}[${msg.guild.id}]`)}`; } let cmd; if (client.commands.has(command)) { @@ -67,14 +66,14 @@ exports.start = (config) => { } else if (client.aliases.has(command)) { cmd = client.commands.get(client.aliases.get(command)); } - if(!cmd) return; + if (!cmd) return; client.funcs.runCommandInhibitors(client, msg, cmd) - .then(params => { + .then((params) => { client.funcs.log(commandLog); cmd.run(client, msg, params); }) - .catch(reason => { - if(reason) { + .catch((reason) => { + if (reason) { msg.channel.sendMessage(reason).catch(console.error); } }); @@ -84,6 +83,6 @@ exports.start = (config) => { return client; }; -process.on("unhandledRejection", err => { - console.error("Uncaught Promise Error: \n" + err.stack); +process.on("unhandledRejection", (err) => { + console.error(`Uncaught Promise Error: \n${err.stack}`); }); diff --git a/commands/System/conf.js b/commands/System/conf.js index c4bcfdbd..62b81586 100644 --- a/commands/System/conf.js +++ b/commands/System/conf.js @@ -1,5 +1,4 @@ exports.run = (client, msg, [action, key, ...value]) => { - if (action === "list") { msg.channel.sendCode("json", require("util").inspect(msg.guildConf)); } else @@ -26,6 +25,7 @@ exports.run = (client, msg, [action, key, ...value]) => { client.funcs.confs.resetKey(msg.guild, key); return msg.reply("The key has been reset."); } + return false; }; exports.conf = { diff --git a/commands/System/disable.js b/commands/System/disable.js index 58ad238b..c6bb1995 100644 --- a/commands/System/disable.js +++ b/commands/System/disable.js @@ -7,10 +7,9 @@ exports.run = (client, msg, [commandname]) => { } if (!command) { return msg.channel.sendMessage(`I cannot find the command: ${commandname}`); - } else { - client.commands.get(command).conf.enabled = false; - return msg.channel.sendMessage(`Successfully disabled: ${commandname}`); } + client.commands.get(command).conf.enabled = false; + return msg.channel.sendMessage(`Successfully disabled: ${commandname}`); }; exports.conf = { @@ -19,12 +18,12 @@ exports.conf = { aliases: [], permLevel: 10, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "disable", description: "Temporarily disables the command. Resets upon reboot.", usage: "", - usageDelim: "" + usageDelim: "", }; diff --git a/commands/System/enable.js b/commands/System/enable.js index a05ff7ed..59dd4b0e 100644 --- a/commands/System/enable.js +++ b/commands/System/enable.js @@ -7,10 +7,9 @@ exports.run = (client, msg, [commandname]) => { } if (!command) { return msg.channel.sendMessage(`I cannot find the command: ${commandname}`); - } else { - client.commands.get(command).conf.enabled = true; - return msg.channel.sendMessage(`Successfully enabled: ${commandname}`); } + client.commands.get(command).conf.enabled = true; + return msg.channel.sendMessage(`Successfully enabled: ${commandname}`); }; exports.conf = { @@ -19,12 +18,12 @@ exports.conf = { aliases: [], permLevel: 10, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "enable", description: "Re-enables or temporarily enables a command. Default state restored on reboot.", usage: "", - usageDelim: "" + usageDelim: "", }; diff --git a/commands/System/eval.js b/commands/System/eval.js index b53215c1..90ac11cc 100644 --- a/commands/System/eval.js +++ b/commands/System/eval.js @@ -1,8 +1,9 @@ exports.run = (client, msg, [code]) => { try { - var evaled = eval(code); - if (typeof evaled !== "string") + let evaled = eval(code); + if (typeof evaled !== "string") { evaled = require("util").inspect(evaled); + } msg.channel.sendCode("xl", client.funcs.clean(client, evaled)); } catch (err) { msg.channel.sendMessage("`ERROR` ```xl\n" + @@ -17,12 +18,12 @@ exports.conf = { aliases: ["ev"], permLevel: 10, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "eval", description: "Evaluates arbitrary Javascript. Reserved for bot owner.", usage: "", - usageDelim: "" + usageDelim: "", }; diff --git a/commands/System/info.js b/commands/System/info.js index 1526927a..96f88439 100644 --- a/commands/System/info.js +++ b/commands/System/info.js @@ -9,12 +9,12 @@ exports.conf = { aliases: ["details", "what"], permLevel: 0, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "info", description: "Provides some information about this bot.", usage: "", - usageDelim: "" + usageDelim: "", }; diff --git a/commands/System/invite.js b/commands/System/invite.js index 8d3642cb..f4d2c92f 100644 --- a/commands/System/invite.js +++ b/commands/System/invite.js @@ -7,7 +7,7 @@ exports.help = { name: "invite", description: "Displays the join server link of the bot.", usage: "", - usageDelim: "" + usageDelim: "", }; exports.conf = { @@ -16,5 +16,5 @@ exports.conf = { aliases: [], permLevel: 0, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; diff --git a/commands/System/ping.js b/commands/System/ping.js index b657f179..5afd7285 100644 --- a/commands/System/ping.js +++ b/commands/System/ping.js @@ -1,6 +1,6 @@ exports.run = (client, msg) => { msg.channel.sendMessage("Ping?") - .then(message => { + .then((message) => { message.edit(`Pong! (took: ${message.createdTimestamp - msg.createdTimestamp}ms)`); }); }; @@ -11,12 +11,12 @@ exports.conf = { aliases: [], permLevel: 0, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "ping", description: "Ping/Pong command. I wonder what this does? /sarcasm", usage: "", - usageDelim: "" + usageDelim: "", }; diff --git a/commands/System/reboot.js b/commands/System/reboot.js index c7947bdf..c1d2ab65 100644 --- a/commands/System/reboot.js +++ b/commands/System/reboot.js @@ -1,9 +1,9 @@ exports.run = (client, msg) => { const collector = msg.channel.createCollector(m => m.author === msg.author, { - time: 10000 + time: 10000, }); msg.channel.sendMessage("are you sure?"); - collector.on("message", m => { + collector.on("message", (m) => { if (m.content === "no") collector.stop("aborted"); if (m.content === "yes") collector.stop("success"); }); @@ -15,7 +15,7 @@ exports.run = (client, msg) => { .then(() => { process.exit(); }) - .catch(e => { + .catch((e) => { console.error(e); }); } @@ -28,12 +28,12 @@ exports.conf = { aliases: [], permLevel: 10, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "reboot", description: "reboots the bot.", usage: "", - usageDelim: "" + usageDelim: "", }; diff --git a/commands/System/reload.js b/commands/System/reload.js index 16d6fe1f..eeca7e73 100644 --- a/commands/System/reload.js +++ b/commands/System/reload.js @@ -12,15 +12,15 @@ exports.run = (client, msg, [commandname]) => { } if (!command) { client.funcs.getFileListing(client, client.coreBaseDir, "commands") - .then(files => { - let newCommands = files.filter(f => f.name == command); - newCommands.forEach(file => { + .then((files) => { + const newCommands = files.filter(f => f.name === command); + newCommands.forEach((file) => { msg.channel.sendMessage(`Loading New Command: ${commandname}`) - .then(m => { - client.funcs.loadSingleCommand(client, command, false, `${file.path}${require("path").sep}${file.base}`).then(cmd => { + .then((m) => { + client.funcs.loadSingleCommand(client, command, false, `${file.path}${require("path").sep}${file.base}`).then((cmd) => { m.edit(`Successfully Loaded: ${cmd.help.name}`); }) - .catch(e => { + .catch((e) => { m.edit(`Command load failed for ${command}: \n\`\`\`${e.stack}\`\`\``); }); }); @@ -28,12 +28,12 @@ exports.run = (client, msg, [commandname]) => { }); } else { msg.channel.sendMessage(`Reloading: ${command}`) - .then(m => { + .then((m) => { client.funcs.loadSingleCommand(client, command, true) - .then(cmd => { + .then((cmd) => { m.edit(`Successfully reloaded: ${cmd.help.name}`); }) - .catch(e => { + .catch((e) => { m.edit(`Command reload failed for ${command}: \n\`\`\`${e}\`\`\``); }); }); @@ -46,11 +46,11 @@ exports.conf = { aliases: ["r", "load"], permLevel: 10, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "reload", description: "Reloads the command file, if it's been updated or modified.", - usage: "" + usage: "", }; diff --git a/commands/System/stats.js b/commands/System/stats.js index 1b9cbaf3..c285260e 100644 --- a/commands/System/stats.js +++ b/commands/System/stats.js @@ -3,7 +3,7 @@ const moment = require("moment"); require("moment-duration-format"); exports.run = (client, msg) => { - let duration = moment.duration(client.uptime).format(" D [days], H [hrs], m [mins], s [secs]"); + const duration = moment.duration(client.uptime).format(" D [days], H [hrs], m [mins], s [secs]"); msg.channel.sendCode("asciidoc", `= STATISTICS = • Mem Usage :: ${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB @@ -20,12 +20,12 @@ exports.conf = { aliases: ["details", "what"], permLevel: 0, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "stats", description: "Provides some details about the bot and stats.", usage: "", - usageDelim: "" + usageDelim: "", }; diff --git a/functions/addCommas.js b/functions/addCommas.js index fe2b7e37..432d56fc 100644 --- a/functions/addCommas.js +++ b/functions/addCommas.js @@ -1,8 +1,8 @@ module.exports = (nStr) => { nStr += ""; - let x = nStr.split("."); + const x = nStr.split("."); let x1 = x[0]; - let x2 = x.length > 1 ? "." + x[1] : ""; + const x2 = x.length > 1 ? `.${x[1]}` : ""; const rgx = /(\d+)(\d{3})/; while (rgx.test(x1)) { x1 = x1.replace(rgx, "$1" + "," + "$2"); diff --git a/functions/botPermissions.js b/functions/botPermissions.js index dccd12b4..23bd0fb0 100644 --- a/functions/botPermissions.js +++ b/functions/botPermissions.js @@ -1,26 +1,25 @@ const permFlags = require("discord.js/src/util/Constants.js").PermissionFlags; -module.exports = client => { +module.exports = (client) => { + const genObject = {}; - let genObject = {}; - - for (let key in permFlags) { + for (const key in permFlags) { genObject[key] = false; } genObject.READ_MESSAGES = true; genObject.SEND_MESSAGES = true; - client.commands.forEach(command => { + client.commands.forEach((command) => { if (command.conf.botPerms.length > 0) { - command.conf.botPerms.forEach(val => { + command.conf.botPerms.forEach((val) => { if (genObject.hasOwnProperty(val)) genObject[val] = true; }); } }); let permNumber = 0; - for (let key in genObject) { + for (const key in genObject) { if (genObject[key] === true) { permNumber += permFlags[key]; } diff --git a/functions/clean.js b/functions/clean.js index bc448eaf..4c316989 100644 --- a/functions/clean.js +++ b/functions/clean.js @@ -1,19 +1,18 @@ -module.exports = (client, text) => { - if (typeof(text) === "string") { - return text.replace(sensitivePattern(client), "「redacted」").replace(client.user.email, "「redacted」").replace(/`/g, "`" + String.fromCharCode(8203)).replace(/@/g, "@" + String.fromCharCode(8203)); - } else { - return text; - } -}; - function sensitivePattern(client) { - if (!this._sensitivePattern) { + if (!this.sensitivePattern) { let pattern = ""; if (client.token) pattern += client.token; if (client.token) pattern += (pattern.length > 0 ? "|" : "") + client.token; if (client.email) pattern += (pattern.length > 0 ? "|" : "") + client.email; if (client.password) pattern += (pattern.length > 0 ? "|" : "") + client.password; - this._sensitivePattern = new RegExp(pattern, "gi"); + this.sensitivePattern = new RegExp(pattern, "gi"); } - return this._sensitivePattern; + return this.sensitivePattern; } + +module.exports = (client, text) => { + if (typeof (text) === "string") { + return text.replace(sensitivePattern(client), "「redacted」").replace(client.user.email, "「redacted」").replace(/`/g, `\`${String.fromCharCode(8203)}`).replace(/@/g, `@${String.fromCharCode(8203)}`); + } + return text; +}; diff --git a/functions/createDBSchema.js b/functions/createDBSchema.js index e616feff..52259c5d 100644 --- a/functions/createDBSchema.js +++ b/functions/createDBSchema.js @@ -1,24 +1,25 @@ -module.exports = data => { - let toRet = [], - names = []; +module.exports = (data) => { + const toRet = []; + const names = []; data.forEach((o, i) => { - const current = o.possibles[0], - loc = names.indexOf(current.name); - if (o.type === "optional") + const current = o.possibles[0]; + const loc = names.indexOf(current.name); + if (o.type === "optional") { current.canNull = true; - - if (loc >= 0) - throw `at field #${loc +1} and #${i +1}: There can't be two fields with the same name`; - + } + if (loc >= 0) { + throw `at field #${loc + 1} and #${i + 1}: There can't be two fields with the same name`; + } names.push(current.name); switch (current.type) { case "autots": case "autoid": case "bool": - if (current.max || current.min) - throw `at field #${i +1}: The type '${current.type}'' may not have a length`; + if (current.max || current.min) { + throw `at field #${i + 1}: The type '${current.type}'' may not have a length`; + } break; case "timestamp": case "int": @@ -29,7 +30,7 @@ module.exports = data => { case "string": break; default: - throw `at field #${i +1}: The type '${current.type}' is not supported`; + throw `at field #${i + 1}: The type '${current.type}' is not supported`; } toRet.push(current); diff --git a/functions/fullUsage.js b/functions/fullUsage.js index 5d8e3351..ad1cbd08 100644 --- a/functions/fullUsage.js +++ b/functions/fullUsage.js @@ -1,3 +1 @@ -module.exports = (client, command) => { - return `${client.config.prefix}${command.conf.aliases.length === 0 ? command.help.name : `(${command.help.name}|${command.conf.aliases.join("|")})`}${command.help.usage !== "" ? " " + command.help.usage.split(" ").join(command.help.usageDelim) : ""}`; -}; +module.exports = (client, command) => `${client.config.prefix}${command.conf.aliases.length === 0 ? command.help.name : `(${command.help.name}|${command.conf.aliases.join("|")})`}${command.help.usage !== "" ? ` ${command.help.usage.split(" ").join(command.help.usageDelim)}` : ""}`; diff --git a/functions/getFileListing.js b/functions/getFileListing.js index 7a34b2b6..b2b66d63 100644 --- a/functions/getFileListing.js +++ b/functions/getFileListing.js @@ -3,39 +3,39 @@ const fs = require("fs-extra"); module.exports = (client, baseDir, type) => { return new Promise((resolve, reject) => { - let dir = path.resolve(`${baseDir}/${type}/`); - let files = []; + const dir = path.resolve(`${baseDir}/${type}/`); + const files = []; try { fs.walk(dir) .on("data", (item) => { - let fileinfo = path.parse(item.path); + const fileinfo = path.parse(item.path); if (!fileinfo.ext) return; files.push({ path: fileinfo.dir, name: fileinfo.name, base: fileinfo.base, - ext: fileinfo.ext + ext: fileinfo.ext, }); }) .on("end", () => { - //client.funcs.log(`Modules: ${categories.join(",")}`); + // client.funcs.log(`Modules: ${categories.join(",")}`); resolve(files); }) .on("errors", (root, nodeStatsArray, next) => { - nodeStatsArray.forEach(function(n) { - client.funcs.log("[ERROR] " + n.name, "error"); - client.funcs.log(n.error.message || (n.error.code + ": " + n.error.path), "error"); + nodeStatsArray.forEach(function (n) { + client.funcs.log(`[ERROR] " ${n.name}, "error"`); + client.funcs.log(n.error.message || (`${n.error.code}: ${n.error.path}`), "error"); }); next(); }); } catch (e) { if (e.code === "MODULE_NOT_FOUND") { - let module = /'[^']+'/g.exec(e.toString()); + const module = /'[^']+'/g.exec(e.toString()); client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadCommands(client); }) - .catch(e => { + .catch((e) => { console.error(e); process.exit(); }); diff --git a/functions/impliedPermissions.js b/functions/impliedPermissions.js index 49b184cb..8c00a91b 100644 --- a/functions/impliedPermissions.js +++ b/functions/impliedPermissions.js @@ -1,9 +1,9 @@ const permFlags = require("discord.js/src/util/Constants.js").PermissionFlags; module.exports = () => { - let genObject = {}; + const genObject = {}; - for (let key in permFlags) { + for (const key in permFlags) { genObject[key] = false; } diff --git a/functions/loadCommandInhibitors.js b/functions/loadCommandInhibitors.js index e654778f..9e05da5c 100644 --- a/functions/loadCommandInhibitors.js +++ b/functions/loadCommandInhibitors.js @@ -1,30 +1,29 @@ const fs = require("fs-extra"); const path = require("path"); -module.exports = client => { +module.exports = (client) => { client.commandInhibitors.clear(); - let counts = [0, 0]; - loadCommandInhibitors(client, client.coreBaseDir, counts).then(counts => { - loadCommandInhibitors(client, client.clientBaseDir, counts).then(counts => { - let [p, o] = counts; + const counts = [0, 0]; + loadCommandInhibitors(client, client.coreBaseDir, counts).then((counts) => { + loadCommandInhibitors(client, client.clientBaseDir, counts).then((counts) => { + const [p, o] = counts; client.funcs.log(`Loaded ${p} command inhibitors, with ${o} optional.`); }); }); - }; const loadCommandInhibitors = (client, baseDir, counts) => { return new Promise((resolve, reject) => { - let dir = path.resolve(baseDir + "./inhibitors/"); - fs.ensureDir(dir, err => { + const dir = path.resolve(`${baseDir}./inhibitors/`); + fs.ensureDir(dir, (err) => { if (err) console.error(err); fs.readdir(dir, (err, files) => { if (err) console.error(err); let [p, o] = counts; try { - files = files.filter(f => { return f.slice(-3) === ".js"; }); - files.forEach(f => { - let file = f.split("."); + files = files.filter((f) => { return f.slice(-3) === ".js"; }); + files.forEach((f) => { + const file = f.split("."); let props; if (file[1] !== "opt") { props = require(`${dir}/${f}`); @@ -35,16 +34,15 @@ const loadCommandInhibitors = (client, baseDir, counts) => { client.commandInhibitors.set(file[0], props); o++; } - }); } catch (e) { if (e.code === "MODULE_NOT_FOUND") { - let module = /'[^']+'/g.exec(e.toString()); + const module = /'[^']+'/g.exec(e.toString()); client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadCommandInhibitors(client); }) - .catch(e => { + .catch((e) => { console.error(e); process.exit(); }); diff --git a/functions/loadCommands.js b/functions/loadCommands.js index 1a63e9e6..ed13e9a6 100644 --- a/functions/loadCommands.js +++ b/functions/loadCommands.js @@ -1,42 +1,29 @@ const fs = require("fs-extra"); const path = require("path"); -module.exports = client => { - client.commands.clear(); - client.aliases.clear(); - let counts = [0, 0]; - loadCommands(client, client.coreBaseDir, counts).then(counts => { - loadCommands(client, client.clientBaseDir, counts).then(counts => { - let [c, a] = counts; - client.funcs.log(`Loaded ${c} commands, with ${a} aliases.`); - }); - }); -}; - const loadCommands = (client, baseDir, counts) => { - return new Promise( (resolve, reject) => { - let dir = path.resolve(baseDir + "./commands/"); - + return new Promise((resolve, reject) => { + const dir = path.resolve(`${baseDir}./commands/`); let [c, a] = counts; try { - fs.ensureDir(dir, err => { - if(err) reject(err); + fs.ensureDir(dir, (err) => { + if (err) reject(err); fs.walk(dir) .on("data", (item) => { - let fileinfo = path.parse(item.path), - fileDir = fileinfo.dir, - name = fileinfo.name, - ext = fileinfo.ext; + const fileinfo = path.parse(item.path); + const fileDir = fileinfo.dir; + const name = fileinfo.name; + const ext = fileinfo.ext; - if(!ext || ext !== ".js") return; + if (!ext || ext !== ".js") return; - client.funcs.loadSingleCommand(client, name, false, `${fileDir}${path.sep}${fileinfo.base}`).then(cmd => { + client.funcs.loadSingleCommand(client, name, false, `${fileDir}${path.sep}${fileinfo.base}`).then((cmd) => { c++; cmd.conf.aliases.forEach(() => { a++; }); }) - .catch(e=>{ + .catch((e) => { client.funcs.log(e, "Error"); }); }) @@ -46,12 +33,12 @@ const loadCommands = (client, baseDir, counts) => { }); } catch (e) { if (e.code === "MODULE_NOT_FOUND") { - let module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1,-1)) + const module = /'[^']+'/g.exec(e.toString()); + client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadCommands(client); }) - .catch(e => { + .catch((e) => { console.error(e); process.exit(); }); @@ -61,3 +48,15 @@ const loadCommands = (client, baseDir, counts) => { } }); }; + +module.exports = (client) => { + client.commands.clear(); + client.aliases.clear(); + const counts = [0, 0]; + loadCommands(client, client.coreBaseDir, counts).then((counts) => { + loadCommands(client, client.clientBaseDir, counts).then((counts) => { + const [c, a] = counts; + client.funcs.log(`Loaded ${c} commands, with ${a} aliases.`); + }); + }); +}; diff --git a/functions/loadDataProviders.js b/functions/loadDataProviders.js index 43222710..34994f01 100644 --- a/functions/loadDataProviders.js +++ b/functions/loadDataProviders.js @@ -1,29 +1,18 @@ const fs = require("fs-extra"); const path = require("path"); -module.exports = client => { - client.dataProviders.clear(); - let counts = [0, 0]; - loadDataProviders(client, client.coreBaseDir, counts).then(counts => { - loadDataProviders(client, client.clientBaseDir, counts).then(counts => { - let [d, o] = counts; - client.funcs.log(`Loaded ${d} database handlers, with ${o} optional.`); - }); - }); -}; - const loadDataProviders = (client, baseDir, counts) => { return new Promise((resolve, reject) => { - let dir = path.resolve(baseDir + "./dataProviders/"); - fs.ensureDir(dir, err => { + const dir = path.resolve(`${baseDir}./dataProviders/`); + fs.ensureDir(dir, (err) => { if (err) console.error(err); fs.readdir(dir, (err, files) => { if (err) console.error(err); let [d, o] = counts; try { - files = files.filter(f => { return f.slice(-3) === ".js"; }); - files.forEach(f => { - let file = f.split("."); + files = files.filter((f) => { return f.slice(-3) === ".js"; }); + files.forEach((f) => { + const file = f.split("."); let props; if (file[1] !== "opt") { props = require(`${dir}/${f}`); @@ -39,12 +28,12 @@ const loadDataProviders = (client, baseDir, counts) => { }); } catch (e) { if (e.code === "MODULE_NOT_FOUND") { - let module = /'[^']+'/g.exec(e.toString()); + const module = /'[^']+'/g.exec(e.toString()); client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadDataProviders(client, baseDir, counts); }) - .catch(e => { + .catch((e) => { console.error(e); process.exit(); }); @@ -57,3 +46,14 @@ const loadDataProviders = (client, baseDir, counts) => { }); }); }; + +module.exports = (client) => { + client.dataProviders.clear(); + const counts = [0, 0]; + loadDataProviders(client, client.coreBaseDir, counts).then((counts) => { + loadDataProviders(client, client.clientBaseDir, counts).then((counts) => { + const [d, o] = counts; + client.funcs.log(`Loaded ${d} database handlers, with ${o} optional.`); + }); + }); +}; diff --git a/functions/loadEvents.js b/functions/loadEvents.js index 29386f66..470148ee 100644 --- a/functions/loadEvents.js +++ b/functions/loadEvents.js @@ -1,31 +1,23 @@ const fs = require("fs-extra"); const path = require("path"); + let events = require("discord.js/src/util/Constants.js").Events; events = Object.keys(events).map(k => events[k]); -module.exports = client => { - let count = 0; - loadEvents(client, client.coreBaseDir, count).then(count => { - loadEvents(client, client.clientBaseDir, count).then(count => { - client.funcs.log(`Loaded ${count} events`); - }); - }); -}; - const loadEvents = (client, baseDir, count) => { return new Promise((resolve, reject) => { - let dir = path.resolve(baseDir + "./events/"); - fs.ensureDir(dir, err => { + const dir = path.resolve(`${baseDir}./events/`); + fs.ensureDir(dir, (err) => { if (err) reject(err); fs.readdir(dir, (err, files) => { if (err) reject(err); let e = count; - files = files.filter(f => { - let name = f.split(".")[0]; + files = files.filter((f) => { + const name = f.split(".")[0]; return events.includes(name); }); - files.forEach(f => { - let name = f.split(".")[0]; + files.forEach((f) => { + const name = f.split(".")[0]; client.on(name, (...args) => require(`${dir}/${f}`).run(client, ...args)); e++; }); @@ -34,3 +26,12 @@ const loadEvents = (client, baseDir, count) => { }); }); }; + +module.exports = (client) => { + const count = 0; + loadEvents(client, client.coreBaseDir, count).then((count) => { + loadEvents(client, client.clientBaseDir, count).then((count) => { + client.funcs.log(`Loaded ${count} events`); + }); + }); +}; diff --git a/functions/loadFunctions.js b/functions/loadFunctions.js index 012e6f15..7b5a0149 100644 --- a/functions/loadFunctions.js +++ b/functions/loadFunctions.js @@ -1,30 +1,17 @@ const fs = require("fs-extra"); const path = require("path"); -module.exports = client => { - return new Promise((resolve, reject) => { - let counts = [0, 0]; - loadFunctions(client, client.coreBaseDir, counts).then(counts => { - loadFunctions(client, client.clientBaseDir, counts).then(counts => { - let [d, o] = counts; - client.funcs.log(`Loaded ${d} functions, with ${o} optional.`); - resolve(); - }); - }).catch(reject); - }); -}; - const loadFunctions = (client, baseDir, counts) => { return new Promise((resolve, reject) => { - let dir = path.resolve(baseDir + "./functions/"); + const dir = path.resolve(`${baseDir}./functions/`); fs.ensureDirSync(dir); fs.readdir(dir, (err, files) => { if (err) reject(err); - files = files.filter(f => { return f.slice(-3) === ".js"; }); + files = files.filter((f) => { return f.slice(-3) === ".js"; }); let [d, o] = counts; try { - files.forEach(f => { - let file = f.split("."); + files.forEach((f) => { + const file = f.split("."); if (file[0] === "loadFunctions") return; if (file[1] !== "opt") { client.funcs[file[0]] = require(`${dir}/${f}`); @@ -37,12 +24,12 @@ const loadFunctions = (client, baseDir, counts) => { resolve([d, o]); } catch (e) { if (e.code === "MODULE_NOT_FOUND") { - let module = /'[^']+'/g.exec(e.toString()); + const module = /'[^']+'/g.exec(e.toString()); client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadDatabaseHandlers(client); }) - .catch(e => { + .catch((e) => { console.error(e); process.exit(); }); @@ -53,3 +40,16 @@ const loadFunctions = (client, baseDir, counts) => { }); }); }; + +module.exports = (client) => { + return new Promise((resolve, reject) => { + const counts = [0, 0]; + loadFunctions(client, client.coreBaseDir, counts).then((counts) => { + loadFunctions(client, client.clientBaseDir, counts).then((counts) => { + const [d, o] = counts; + client.funcs.log(`Loaded ${d} functions, with ${o} optional.`); + resolve(); + }); + }).catch(reject); + }); +}; diff --git a/functions/loadSingleCommand.js b/functions/loadSingleCommand.js index a46d89d4..b241e42d 100644 --- a/functions/loadSingleCommand.js +++ b/functions/loadSingleCommand.js @@ -1,8 +1,10 @@ const path = require("path"); -module.exports = function(client, command, reload = false, loadPath = null) { +module.exports = function (client, command, reload = false, loadPath = null) { return new Promise((resolve, reject) => { - let category, subCategory, cmd; + let category; + let subCategory; + let cmd; if (!loadPath && !reload) return reject("Path must be provided when loading a new command."); if (reload) { if (!client.commands.has(command)) { @@ -21,7 +23,6 @@ module.exports = function(client, command, reload = false, loadPath = null) { } catch (e) { reject(`Could not load existing command data: ${e.stack}`); } - } else { try { cmd = require(loadPath); @@ -34,12 +35,12 @@ module.exports = function(client, command, reload = false, loadPath = null) { subCategory = client.funcs.toTitleCase(cmd.help.subCategory ? cmd.help.subCategory : (pathParts[1] && pathParts[1].length > 0 && !~pathParts[1].indexOf(".") ? pathParts[1] : "General")); } catch (e) { if (e.code === "MODULE_NOT_FOUND") { - let module = /'[^']+'/g.exec(e.toString()); + const module = /'[^']+'/g.exec(e.toString()); client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadSingleCommand(client, command, false, loadPath); }) - .catch(e => { + .catch((e) => { console.error(e); process.exit(); }); @@ -55,7 +56,7 @@ module.exports = function(client, command, reload = false, loadPath = null) { cmd.help.filePath = loadPath; // Load Aliases - cmd.conf.aliases.forEach(alias => { + cmd.conf.aliases.forEach((alias) => { client.aliases.set(alias, cmd.help.name); }); @@ -63,16 +64,15 @@ module.exports = function(client, command, reload = false, loadPath = null) { if (!client.helpStructure.has(category)) { client.helpStructure.set(category, new Map()); } - let catMap = client.helpStructure.get(category); + const catMap = client.helpStructure.get(category); if (!catMap.has(subCategory)) { catMap.set(subCategory, new Map()); } - let subCatMap = catMap.get(subCategory); + const subCatMap = catMap.get(subCategory); subCatMap.set(cmd.help.name, cmd.help.description); client.commands.set(cmd.help.name, cmd); resolve(cmd); - }); }; diff --git a/functions/log.js b/functions/log.js index 48ddb61e..2e457b96 100644 --- a/functions/log.js +++ b/functions/log.js @@ -1,10 +1,10 @@ const moment = require("moment"); const chalk = require("chalk"); -const clk = new chalk.constructor({ enabled: true }); -module.exports = function(data, type = "log") { +const clk = new chalk.constructor({ enabled: true }); - switch(type.toLowerCase()) { +module.exports = function (data, type = "log") { + switch (type.toLowerCase()) { case "debug": console.log(`${clk.bgMagenta(`[${moment().format("YYYY-MM-DD HH:mm:ss")}]`)} ${data}`); break; @@ -18,5 +18,4 @@ module.exports = function(data, type = "log") { console.log(`${clk.bgBlue(`[${moment().format("YYYY-MM-DD HH:mm:ss")}]`)} ${data}`); break; } - }; diff --git a/functions/parseTags.js b/functions/parseTags.js index 2f5991aa..b9cc2bce 100644 --- a/functions/parseTags.js +++ b/functions/parseTags.js @@ -8,17 +8,18 @@ class ParserError { } toString() { - var ret = "Error"; + let ret = "Error"; if (this.start) { - if (this.end !== undefined) + if (this.end !== undefined) { ret += ` from ${this.type} #${this.end} to ${this.type} #${this.start}`; - else + } else { ret += ` at ${this.type} #${this.start}`; + } } - if (this.content) + if (this.content) { ret += ` '${this.content}'`; - + } ret += `: ${this.message}`; return ret; } @@ -27,66 +28,70 @@ class ParserError { const alphaNumeric = /^[a-zA-Z0-9]+$/; const parseTagData = (data, disallow, tag) => { - let toRet = [], - types = []; + const toRet = []; + const types = []; - var possiblilies = data.split("|"); + const possiblilies = data.split("|"); - if (disallow && possiblilies.length > 1) // Remove this in case you want posibilities + if (disallow && possiblilies.length > 1) { // Remove this in case you want posibilities throw new ParserError("There can't be a more than one posibility in the tag", "tag", tag); - + } possiblilies.forEach((p, i) => { const bounds = p.split(":", 3); - if (bounds.length > 2) - throw new ParserError("Invalid syntax, found at least two ':' inside the same posibility", "tag(possibility)", `${tag}(${i+1})`); - - if (!bounds[0]) - throw new ParserError("The tag name must not be empty", "tag(possibility)", `${tag}(${i+1})`); - - if (disallow && !alphaNumeric.test(bounds[0])) - throw new ParserError("The name must be alpha-numeric", "tag(possibility)", `${tag}(${i+1})`); - - let bound = { + if (bounds.length > 2) { + throw new ParserError("Invalid syntax, found at least two ':' inside the same posibility", "tag(possibility)", `${tag}(${i + 1})`); + } + if (!bounds[0]) { + throw new ParserError("The tag name must not be empty", "tag(possibility)", `${tag}(${i + 1})`); + } + if (disallow && !alphaNumeric.test(bounds[0])) { + throw new ParserError("The name must be alpha-numeric", "tag(possibility)", `${tag}(${i + 1})`); + } + const bound = { name: bounds[0], - type: disallow ? "string" : "literal" + type: disallow ? "string" : "literal", }; if (bounds[1]) { - let opened = false, - second = false, - mustEnd = false, - current = ""; + let opened = false; + let second = false; + let mustEnd = false; + let current = ""; - bounds[1].split("").forEach(c => { + bounds[1].split("").forEach((c) => { switch (c) { case "{": opened = true; - if (!current && !disallow) - throw new ParserError("You canno't specify the length of a literal", "tag(possibility)", `${tag}(${i+1})`); - if (current) + if (!current && !disallow) { + throw new ParserError("You canno't specify the length of a literal", "tag(possibility)", `${tag}(${i + 1})`); + } + if (current) { bound.type = current.toLowerCase(); + } current = ""; break; case "}": - if (!current) - throw new ParserError("The length definition might not be empty", "tag(possibility)", `${tag}(${i+1})`); + if (!current) { + throw new ParserError("The length definition might not be empty", "tag(possibility)", `${tag}(${i + 1})`); + } - if (second) + if (second) { bound.max = parseFloat(current); - else if (bound.min === undefined) + } else if (bound.min === undefined) { bound.min = parseFloat(current); - + } current = ""; mustEnd = true; opened = false; break; case ",": - if (!opened) - throw new ParserError("Unexpected character ',' at this point", "tag(possibility)", `${tag}(${i+1})`); - - if (second) - throw new ParserError("Found character ',' two or more times inside the length definition", "tag(possibility)", `${tag}(${i+1})`); + if (!opened) { + throw new ParserError("Unexpected character ',' at this point", "tag(possibility)", `${tag}(${i + 1})`); + } + if (second) { + throw new ParserError("Found character ',' two or more times inside the length definition", "tag(possibility)", `${tag}(${i + 1})`); + } if (current) { try { bound.min = parseFloat(current); @@ -98,44 +103,52 @@ const parseTagData = (data, disallow, tag) => { second = true; break; case ".": - if (!opened) - throw new ParserError("Unexpected character '.' at this point", "tag(possibility)", `${tag}(${i+1})`); + if (!opened) { + throw new ParserError("Unexpected character '.' at this point", "tag(possibility)", `${tag}(${i + 1})`); + } current += c; break; default: - if (opened && isNaN(c)) - throw new ParserError("there're only numbers allowed to define the length", "tag(possibility)", `${tag}(${i+1}) in the length definition`); - - if (mustEnd) - throw new ParserError("Invalid syntax, expected an end after the length", "tag(possibility)", `${tag}(${i+1}) in the length definition`); - + if (opened && isNaN(c)) { + throw new ParserError("there're only numbers allowed to define the length", "tag(possibility)", `${tag}(${i + 1}) in the length definition`); + } + if (mustEnd) { + throw new ParserError("Invalid syntax, expected an end after the length", "tag(possibility)", `${tag}(${i + 1}) in the length definition`); + } current += c; break; } }); - if (opened) - throw new ParserError("unclosed '{' found", "tag(possibility)", `${tag}(${i+1})`); + if (opened) { + throw new ParserError("unclosed '{' found", "tag(possibility)", `${tag}(${i + 1})`); + } - if (types.includes(bound.type)) + if (types.includes(bound.type)) { throw new ParserError("Two bounds with the same type has been found in the same tag", "tag", `${tag}`); + } - if (types.includes("string")) + if (types.includes("string")) { throw new ParserError("String type is vague, must be defined at the end of possiblilies", "tag", `${tag}`); + } if (["string", "str"].includes(bound.type)) { - if (bound.max && bound.max % 1 !== 0 || bound.min && bound.min % 1 !== 0) - throw new ParserError("String types may have an integer length", "tag(possibility)", `${tag}(${i+1}) in the length definition`); + if (bound.max && bound.max % 1 !== 0 || bound.min && bound.min % 1 !== 0) { + throw new ParserError("String types may have an integer length", "tag(possibility)", `${tag}(${i + 1}) in the length definition`); + } } - if (bound.max && bound.min && bound.min > bound.max) - throw new ParserError("The max cannot be lower than the min", "tag(possibility)", `${tag}(${i+1}) in the length definition`); + if (bound.max && bound.min && bound.min > bound.max) { + throw new ParserError("The max cannot be lower than the min", "tag(possibility)", `${tag}(${i + 1}) in the length definition`); + } - if (!alphaNumeric.test(bound.type)) - throw new ParserError("The type must be alpha-numeric", "tag(possibility)", `${tag}(${i+1}) in the length definition`); + if (!alphaNumeric.test(bound.type)) { + throw new ParserError("The type must be alpha-numeric", "tag(possibility)", `${tag}(${i + 1}) in the length definition`); + } - if (current) + if (current) { bound.type = current.toLowerCase(); + } } toRet.push(bound); @@ -147,7 +160,7 @@ const parseTagData = (data, disallow, tag) => { module.exports = (command, disallowCharacters) => { /*** - parseTags("[asda:asd{1.5,2.2}] [asd] [...]").then(tags => console.log(util.inspect(tags, false, null))).catch(e => console.log(e + "")); + parseTags("[asda:asd{1.5,2.2}] [asd] [...]").then(tags => console.log(util.inspect(tags, false, null))).catch(e => console.log(e + "")); ***/ let opened, current = "", tags = [], diff --git a/functions/permissionLevel.js b/functions/permissionLevel.js index be24db91..90b397ac 100644 --- a/functions/permissionLevel.js +++ b/functions/permissionLevel.js @@ -1,24 +1,28 @@ module.exports = (client, user, guild = null) => { return new Promise((resolve, reject) => { - let guildConf = client.funcs.confs.get(guild); + const guildConf = client.funcs.confs.get(guild); let permlvl = 0; if (guild) { try { - let member = guild.member(user); - let mod_role = guild.roles.find("name", guildConf.mod_role); - if (mod_role && member.roles.has(mod_role.id)) + const member = guild.member(user); + const mod_role = guild.roles.find("name", guildConf.mod_role); + if (mod_role && member.roles.has(mod_role.id)) { permlvl = 2; - let admin_role = guild.roles.find("name", guildConf.admin_role); - if (admin_role && member.roles.has(admin_role.id)) + } + const admin_role = guild.roles.find("name", guildConf.admin_role); + if (admin_role && member.roles.has(admin_role.id)) { permlvl = 3; - if (member === guild.owner) + } + if (member === guild.owner) { permlvl = 4; + } } catch (e) { reject(e); } } - if (user.id === client.config.ownerid) + if (user.id === client.config.ownerid) { permlvl = 10; + } resolve(permlvl); }); }; diff --git a/functions/runCommandInhibitors.js b/functions/runCommandInhibitors.js index 4e6fb2db..524731dd 100644 --- a/functions/runCommandInhibitors.js +++ b/functions/runCommandInhibitors.js @@ -1,6 +1,6 @@ module.exports = (client, msg, cmd, selective = false) => { return new Promise((resolve, reject) => { - let mps = [true]; + const mps = [true]; let i = 1; let usage; client.commandInhibitors.forEach((mProc, key) => { @@ -11,9 +11,9 @@ module.exports = (client, msg, cmd, selective = false) => { i++; }); Promise.all(mps) - .then(value => { + .then((value) => { resolve(value[usage]); - }, reason => { + }, (reason) => { reject(reason); }); }); diff --git a/functions/toTitleCase.js b/functions/toTitleCase.js index da8eaa5d..8b53901c 100644 --- a/functions/toTitleCase.js +++ b/functions/toTitleCase.js @@ -1,5 +1,5 @@ module.exports = (str) => { - return str.replace(/\w\S*/g, function(txt) { + return str.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); }); }; diff --git a/inhibitors/disable.js b/inhibitors/disable.js index 73f7ae95..a21fc50f 100644 --- a/inhibitors/disable.js +++ b/inhibitors/disable.js @@ -1,6 +1,6 @@ exports.conf = { enabled: true, - spamProtection: false + spamProtection: false, }; exports.run = (client, msg, cmd) => { diff --git a/inhibitors/guildOnly.js b/inhibitors/guildOnly.js index bff730c1..b20e9d89 100644 --- a/inhibitors/guildOnly.js +++ b/inhibitors/guildOnly.js @@ -1,6 +1,6 @@ exports.conf = { enabled: true, - spamProtection: false + spamProtection: false, }; exports.run = (client, msg, cmd) => { diff --git a/inhibitors/missingBotPermissions.js b/inhibitors/missingBotPermissions.js index ffb5f152..fdc329e9 100644 --- a/inhibitors/missingBotPermissions.js +++ b/inhibitors/missingBotPermissions.js @@ -1,17 +1,16 @@ exports.conf = { enabled: true, - spamProtection: false + spamProtection: false, }; exports.run = (client, msg, cmd) => { return new Promise((resolve, reject) => { - let missing = []; if (msg.channel.type === "text") { missing = msg.channel.permissionsFor(client.user).missingPermissions(cmd.conf.botPerms); } else { - let impliedPermissions = client.funcs.impliedPermissions(); - cmd.conf.botPerms.forEach(perm => { + const impliedPermissions = client.funcs.impliedPermissions(); + cmd.conf.botPerms.forEach((perm) => { if (!impliedPermissions[perm]) missing.push(perm); }); } diff --git a/inhibitors/permissions.js b/inhibitors/permissions.js index 6e99fb4a..ae1a0e2b 100644 --- a/inhibitors/permissions.js +++ b/inhibitors/permissions.js @@ -1,16 +1,17 @@ exports.conf = { enabled: true, - spamProtection: false + spamProtection: false, }; exports.run = (client, msg, cmd) => { return new Promise((resolve, reject) => { client.funcs.permissionLevel(client, msg.author, msg.guild) - .then(permlvl => { - if (permlvl >= cmd.conf.permLevel) + .then((permlvl) => { + if (permlvl >= cmd.conf.permLevel) { resolve(); - else + } else { reject("You do not have permission to use this command."); + } }); }); }; diff --git a/inhibitors/requiredFuncs.js b/inhibitors/requiredFuncs.js index 43716ffe..44293511 100644 --- a/inhibitors/requiredFuncs.js +++ b/inhibitors/requiredFuncs.js @@ -1,11 +1,11 @@ exports.conf = { enabled: true, - spamProtection: false + spamProtection: false, }; exports.run = (client, msg, cmd) => { return new Promise((resolve, reject) => { - cmd.conf.requiredFuncs.forEach(func => { + cmd.conf.requiredFuncs.forEach((func) => { if (!client.funcs.hasOwnProperty(func)) reject(`The client is missing **${func}**, and cannot run.`); }); resolve(); diff --git a/inhibitors/selfBot.js b/inhibitors/selfBot.js index a60746c7..5aa4ab16 100644 --- a/inhibitors/selfBot.js +++ b/inhibitors/selfBot.js @@ -1,6 +1,6 @@ exports.conf = { enabled: true, - spamProtection: false + spamProtection: false, }; exports.run = (client, msg, cmd) => { diff --git a/inhibitors/usage.js b/inhibitors/usage.js index 8c799f42..3a6ba63a 100644 --- a/inhibitors/usage.js +++ b/inhibitors/usage.js @@ -1,14 +1,18 @@ exports.conf = { enabled: true, - spamProtection: true + spamProtection: true, }; exports.run = (client, msg, cmd) => { return new Promise((resolve, reject) => { - let usage = client.funcs.parseUsage(cmd.help.usage); + const usage = client.funcs.parseUsage(cmd.help.usage); let prefixLength = msg.guildConf.prefix.length; if (client.config.prefixMention.test(msg.content)) prefixLength = client.config.prefixMention.exec(msg.content)[0].length + 1; - let args = msg.content.slice(prefixLength).split(" ").slice(1).join(" ").split(cmd.help.usageDelim !== "" ? cmd.help.usageDelim : null); + let args = msg.content.slice(prefixLength) + .split(" ") + .slice(1) + .join(" ") + .split(cmd.help.usageDelim !== "" ? cmd.help.usageDelim : null); if (args[0] === "") args = []; let currentUsage; let repeat = false; @@ -18,23 +22,23 @@ exports.run = (client, msg, cmd) => { if (i >= usage.length && i >= args.length) { return resolve(args); } else if (usage[i]) { - if (usage[i].type !== "repeat") { //Handle if args length > usage length + if (usage[i].type !== "repeat") { // Handle if args length > usage length currentUsage = usage[i]; - } else if (usage[i].type === "repeat") { //Handle if usage ends in a repeat - currentUsage.type = "optional"; //if there are no optional args passed + } else if (usage[i].type === "repeat") { // Handle if usage ends in a repeat + currentUsage.type = "optional"; // if there are no optional args passed repeat = true; } - } else if (!repeat) { //Handle if usage does not end in a repeat + } else if (!repeat) { // Handle if usage does not end in a repeat return resolve(args); } - if (currentUsage.type === "optional" && (args[i] === undefined || args[i] === "")) { //Handle if args length < required usage length - if (usage.slice(i).some(u => { return u.type === "required"; })) { + if (currentUsage.type === "optional" && (args[i] === undefined || args[i] === "")) { // Handle if args length < required usage length + if (usage.slice(i).some((u) => { return u.type === "required"; })) { return reject("Missing one or more required arguments after end of input."); } else { return resolve(args); } } else if (currentUsage.type === "required" && args[i] === undefined) { - return reject(currentUsage.possibles.length === 1 ? `${currentUsage.possibles[0].name} is a required argument.` : `Missing a required option: (${currentUsage.possibles.map(p => {return p.name;}).join(", ")})`); + return reject(currentUsage.possibles.length === 1 ? `${currentUsage.possibles[0].name} is a required argument.` : `Missing a required option: (${currentUsage.possibles.map((p) => { return p.name; }).join(", ")})`); } else if (currentUsage.possibles.length === 1) { switch (currentUsage.possibles[0].type) { case "literal": @@ -45,7 +49,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - return reject(`Your option did not litterally match the only possibility: (${currentUsage.possibles.map(p => {return p.name;}).join(", ")})\nThis is likely caused by a mistake in the usage string.`); + return reject(`Your option did not litterally match the only possibility: (${currentUsage.possibles.map((p) => { return p.name; }).join(", ")})\nThis is likely caused by a mistake in the usage string.`); } break; case "msg": @@ -53,9 +57,9 @@ exports.run = (client, msg, cmd) => { if (/^\d+$/.test(args[i])) { if (client.config.selfbot) { msg.channel.fetchMessages({ - around: args[i] - }).then(m => { - args[i] = m.filter(e => e.id == args[i]).first(); + around: args[i], + }).then((m) => { + args[i] = m.filter(e => e.id === args[i]).first(); validateArgs(++i); }).catch(() => { if (currentUsage.type === "optional" && !repeat) { @@ -67,7 +71,7 @@ exports.run = (client, msg, cmd) => { }); } else { msg.channel.fetchMessage(args[i]) - .then(m => { + .then((m) => { args[i] = m; validateArgs(++i); }) @@ -101,10 +105,12 @@ exports.run = (client, msg, cmd) => { break; case "boolean": if (/^true|false$/.test(args[i])) { - if (args[i] === "true") + if (args[i] === "true") { args[i] = true; - else args[i] = false; - validateArgs(++i); + } else { + args[i] = false; + validateArgs(++i); + } } else if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); @@ -163,12 +169,10 @@ exports.run = (client, msg, cmd) => { if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); + } else if (currentUsage.possibles[0].min === currentUsage.possibles[0].max) { + return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min} characters.`); } else { - if (currentUsage.possibles[0].min === currentUsage.possibles[0].max) { - return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min} characters.`); - } else { - return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max} characters.`); - } + return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max} characters.`); } } else { validateArgs(++i); @@ -218,13 +222,11 @@ exports.run = (client, msg, cmd) => { } else { return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min}\nSo why didn't the dev use a literal?`); } + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); } else { - if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); - } + return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); } } else { validateArgs(++i); @@ -278,13 +280,11 @@ exports.run = (client, msg, cmd) => { } else { return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min}\nSo why didn't the dev use a literal?`); } + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); } else { - if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); - } + return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); } } else { validateArgs(++i); @@ -319,7 +319,7 @@ exports.run = (client, msg, cmd) => { } break; case "url": - if (!/^((https?|ftps?|sftp):\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|(([a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])*\.[a-zA-Z]{2,}))(:\b([0-9]|[1-8][0-9]|9[0-9]|[1-8][0-9]{2}|9[0-8][0-9]|99[0-9]|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])\b)?(\/([a-zA-Z0-9:\/\?#\[\]@!$&'()*+,;=%-._~]+)?)?$/.test(args[i])) { + if (!/^((https?|ftps?|sftp):\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|(([a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])*\.[a-zA-Z]{2,}))(:\b([0-9]|[1-8][0-9]|9[0-9]|[1-8][0-9]{2}|9[0-8][0-9]|99[0-9]|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])\b)?(\/([a-zA-Z0-9:#[\]@!$&'()*+,;=%-._~]+)?)?$/.test(args[i])) { if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); @@ -346,7 +346,7 @@ exports.run = (client, msg, cmd) => { args.splice(i, 0, undefined); validateArgs(++i); } else { - return reject(`Your option didn't match any of the possibilities: (${currentUsage.possibles.map(p => {return p.name;}).join(", ")})`); + return reject(`Your option didn't match any of the possibilities: (${currentUsage.possibles.map((p) => { return p.name; }).join(", ")})`); } return; } @@ -364,7 +364,7 @@ exports.run = (client, msg, cmd) => { case "message": if (/^\d+$/.test(args[i])) { msg.channel.fetchMessage(args[i]) - .then(m => { + .then((m) => { args[i] = m; validated = true; multiPossibles(++p); @@ -377,7 +377,7 @@ exports.run = (client, msg, cmd) => { } break; case "user": - case "mention": + case "mention": { const result = /\d+/.exec(args[i]); if (result && args[i].length > 5 && client.users.has(result[0])) { args[i] = client.users.get(/\d+/.exec(args[i])[0]); @@ -387,6 +387,7 @@ exports.run = (client, msg, cmd) => { multiPossibles(++p); } break; + } case "boolean": if (/^true|false$/.test(args[i])) { if (args[i] === "true") args[i] = true; @@ -397,7 +398,8 @@ exports.run = (client, msg, cmd) => { multiPossibles(++p); } break; - case "member": + case "member": { + const result = /\d+/.exec(args[i]); if (result && args[i].length > 5 && msg.guild.members.has(result[0])) { args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); validated = true; @@ -406,6 +408,7 @@ exports.run = (client, msg, cmd) => { multiPossibles(++p); } break; + } case "channel": if (/^<#\d+>$/.test(args[i]) || client.channels.has(args[i])) { args[i] = client.channels.get(/\d+/.exec(args[i])[0]); @@ -529,7 +532,7 @@ exports.run = (client, msg, cmd) => { } break; case "url": - if (/^((https?|ftps?|sftp):\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|(([a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])*\.[a-zA-Z]{2,}))(:\b([0-9]|[1-8][0-9]|9[0-9]|[1-8][0-9]{2}|9[0-8][0-9]|99[0-9]|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])\b)?(\/([a-zA-Z0-9:\/\?#\[\]@!$&'()*+,;=%-._~]+)?)?$/.test(args[i])) { + if (/^((https?|ftps?|sftp):\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|(([a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])*\.[a-zA-Z]{2,}))(:\b([0-9]|[1-8][0-9]|9[0-9]|[1-8][0-9]{2}|9[0-8][0-9]|99[0-9]|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])\b)?(\/([a-zA-Z0-9:#[\]@!$&'()*+,;=%-._~]+)?)?$/.test(args[i])) { validated = true; multiPossibles(++p); } else { From 7eb0db666739b6a5fb2a619c851c7009bd896706 Mon Sep 17 00:00:00 2001 From: CyberiumShadow Date: Sat, 19 Nov 2016 22:15:54 +1100 Subject: [PATCH 36/51] ESlint them all --- .eslintrc.json | 3 +- commands/System/conf.js | 4 +- commands/System/download.js | 74 ++- commands/System/eval.js | 10 +- commands/System/help.js | 59 +- commands/System/reboot.js | 1 + commands/System/reload.js | 4 +- commands/System/stats.js | 44 +- functions/addCommas.js | 2 +- functions/confs.js | 4 +- functions/createDBSchema.js | 6 +- functions/getFileListing.js | 34 +- functions/installNPM.js | 26 +- functions/loadCommandInhibitors.js | 64 ++- functions/loadCommands.js | 44 +- functions/loadDataProviders.js | 66 ++- functions/loadEvents.js | 43 +- functions/loadFunctions.js | 84 ++- functions/loadSingleCommand.js | 115 ++-- functions/log.js | 3 +- functions/parseTags.js | 47 +- functions/parseUsage.js | 132 ++--- functions/permissionLevel.js | 50 +- functions/runCommandInhibitors.js | 28 +- functions/toTitleCase.js | 6 +- functions/validateData.js | 56 +- inhibitors/disable.js | 16 +- inhibitors/guildOnly.js | 16 +- inhibitors/missingBotPermissions.js | 34 +- inhibitors/permissions.js | 8 +- inhibitors/requiredFuncs.js | 12 +- inhibitors/selfBot.js | 20 +- inhibitors/usage.js | 797 ++++++++++++++-------------- 33 files changed, 949 insertions(+), 963 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 3801676c..3994e101 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -21,6 +21,7 @@ "no-restricted-syntax": "warn", "guard-for-in": "warn", "consistent-return": ["warn", { "treatUndefinedAsUnspecified": true }], - "no-use-before-define": ["warn", { "functions": true, "classes": true }] + "no-use-before-define": ["warn", { "functions": true, "classes": true }], + "no-eval": "warn" } } diff --git a/commands/System/conf.js b/commands/System/conf.js index 62b81586..bfe25748 100644 --- a/commands/System/conf.js +++ b/commands/System/conf.js @@ -1,6 +1,8 @@ +const util = require("util").inspect; + exports.run = (client, msg, [action, key, ...value]) => { if (action === "list") { - msg.channel.sendCode("json", require("util").inspect(msg.guildConf)); + msg.channel.sendCode("json", util(msg.guildConf)); } else if (action === "get") { diff --git a/commands/System/download.js b/commands/System/download.js index c53719f2..b02334a7 100644 --- a/commands/System/download.js +++ b/commands/System/download.js @@ -1,18 +1,19 @@ const request = require("superagent"); const vm = require("vm"); const exec = require("child_process").exec; -var fs = require("fs-extra"); +const fs = require("fs-extra"); +const path = require("path"); exports.run = (client, msg, [url, folder = "Downloaded"]) => { request.get(url, (err, res) => { if (err) console.log(err); // Load Command Data - var mod = { - exports: {} + const mod = { + exports: {}, }; - let code = + const code = `(function(require) { ${res.text}; })`; @@ -21,29 +22,28 @@ exports.run = (client, msg, [url, folder = "Downloaded"]) => { vm.runInNewContext(code, { module: mod, exports: mod.exports }, { timeout: 500 })(require); } catch (e) { if (e.message.startsWith("Cannot find module ")) { - msg.channel.sendMessage("Couldn't find module... Attempting to download.").then(m => { - let moduleName = e.message.substring(19).replace(/'/g, ""); - client.funcs.installNPM(moduleName).then((resolved) => { + msg.channel.sendMessage("Couldn't find module... Attempting to download.").then((m) => { + const moduleName = e.message.substring(19).replace(/'/g, ""); + client.funcs.installNPM(moduleName).then(() => { m.edit(`Downloaded **${moduleName}!** I will make an attempt to load the command now.`); if (client.tempmodules === undefined) client.tempmodules = []; client.tempmodules.push(moduleName); client.commands.get("download").run(client, msg, [url, folder]); - }).catch(e => { - console.log(e); + }).catch((error) => { + console.log(error); }); - return; }); } else if (e.message.startsWith("ENOENT: no such file or directory, open ")) { msg.channel.sendMessage("Couldn't find module... Attempting to download."); - let string = e.message.substring(e.message.indexOf("node_modules"), e.message.lastIndexOf("\\")); - let moduleName = string.substring(string.indexOf("\\") + 1, string.length); - client.funcs.installNPM(moduleName).then((resolved) => { - m.edit(`Downloaded **${moduleName}!** I will make an attempt to load the command now.`); + const string = e.message.substring(e.message.indexOf("node_modules"), e.message.lastIndexOf("\\")); + const moduleName = string.substring(string.indexOf("\\") + 1, string.length); + client.funcs.installNPM(moduleName).then(() => { + msg.edit(`Downloaded **${moduleName}!** I will make an attempt to load the command now.`); if (client.tempmodules === undefined) client.tempmodules = []; client.tempmodules.push(moduleName); client.commands.get("download").run(client, msg, [url, folder]); - }).catch(e => { - console.log(e); + }).catch((error) => { + console.log(error); }); return; } else { @@ -53,8 +53,8 @@ exports.run = (client, msg, [url, folder = "Downloaded"]) => { return; } - let name = mod.exports.help.name; - let description = mod.exports.help.description; + const name = mod.exports.help.name; + const description = mod.exports.help.description; if (client.commands.has(name)) { msg.reply(`The command \`${name}\` already exists in the bot!`); @@ -63,21 +63,19 @@ exports.run = (client, msg, [url, folder = "Downloaded"]) => { } if (mod.exports.conf.selfbot && !client.config.selfbot) { - msg.channel.sendMessage(`The command \`${name}\` is only usable in selfbots! I'll uninstall the modules for you.`).then(m => { + msg.channel.sendMessage(`The command \`${name}\` is only usable in selfbots! I'll uninstall the modules for you.`).then((m) => { exec(`npm uninstall ${client.tempmodules.join(" ")}`, (e, stdout, stderr) => { if (e) { msg.channel.sendMessage("Failed uninstalling the modules.. Sorry about that."); console.log(e); - return; } else { console.log(stdout); console.log(stderr); m.edit(`Succesfully uninstalled : **${client.tempmodules.join(", ")}**`); - client.tempmodules.forEach(module => { + client.tempmodules.forEach((module) => { delete require.cache[require.resolve(module)]; }); delete client.tempmodules; - return; } }); }); @@ -94,10 +92,10 @@ ${description} \`\`\``); const collector = msg.channel.createCollector(m => m.author === msg.author, { - time: 8000 + time: 8000, }); - collector.on("message", m => { + collector.on("message", (m) => { if (m.content.toLowerCase() === "no") collector.stop("aborted"); if (m.content.toLowerCase() === "yes") collector.stop("success"); }); @@ -105,21 +103,19 @@ ${description} collector.on("end", (collected, reason) => { if (reason === "aborted" || reason === "time") { if (client.tempmodules !== undefined) { - msg.channel.sendMessage(":no_mobile_phones: Load Aborted. Command not installed. Lemme remove those useless modules for you :smile:").then(m => { + msg.channel.sendMessage(":no_mobile_phones: Load Aborted. Command not installed. Lemme remove those useless modules for you :smile:").then((m) => { exec(`npm uninstall ${client.tempmodules.join(" ")}`, (e, stdout, stderr) => { if (e) { - msg.channel.sendMessage(`Failed uninstalling the modules.. Sorry about that, the modules you need to uninstall are in \`client.tempmodules\``); + msg.channel.sendMessage("Failed uninstalling the modules.. Sorry about that, the modules you need to uninstall are in `client.tempmodules`"); console.log(e); - return; } else { console.log(stdout); console.log(stderr); m.edit(`Succesfully uninstalled : **${client.tempmodules.join(", ")}**`); - client.tempmodules.forEach(module => { + client.tempmodules.forEach((module) => { delete require.cache[require.resolve(module)]; }); delete client.tempmodules; - return; } }); }); @@ -129,21 +125,21 @@ ${description} } } if (reason === "success") { - msg.channel.sendMessage(":inbox_tray: `Loading Command...`").then(m => { - let category = mod.exports.help.category ? mod.exports.help.category : client.funcs.toTitleCase(folder); - let dir = require("path").resolve(`${client.clientBaseDir}/commands/${category}/`); + msg.channel.sendMessage(":inbox_tray: `Loading Command...`").then((m) => { + const category = mod.exports.help.category ? mod.exports.help.category : client.funcs.toTitleCase(folder); + const dir = path.resolve(`${client.clientBaseDir}/commands/${category}/`); m.edit(`:inbox_tray: \`Loading Command into ${dir}/${name}.js...\``); - fs.ensureDir(dir, err => { - if (err) console.error(err); - fs.writeFile(`${dir}/${name}.js`, res.text, (err) => { - if (err) console.error(err); + fs.ensureDir(dir, (error) => { + if (error) console.error(err); + fs.writeFile(`${dir}/${name}.js`, res.text, (errorn) => { + if (errorn) console.error(errorn); client.funcs.loadSingleCommand(client, name, false, `${dir}/${name}.js`) .then((cmd) => { m.edit(`:inbox_tray: Successfully Loaded: ${cmd.help.name}`); delete client.tempmodules; }) - .catch(e => { + .catch((e) => { m.edit(`:no_mobile_phones: Command load failed: ${name}\n\`\`\`${e.stack}\`\`\``); fs.unlink(`${dir}/${name}.js`); delete client.tempmodules; @@ -162,12 +158,12 @@ exports.conf = { aliases: [], permLevel: 5, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "download", description: "Downloads a command and installs it to Komada", usage: " [folder:str]", - usageDelim: " " + usageDelim: " ", }; diff --git a/commands/System/eval.js b/commands/System/eval.js index 90ac11cc..481fb511 100644 --- a/commands/System/eval.js +++ b/commands/System/eval.js @@ -1,14 +1,16 @@ +const inspect = require("util").inspect; + exports.run = (client, msg, [code]) => { try { let evaled = eval(code); if (typeof evaled !== "string") { - evaled = require("util").inspect(evaled); + evaled = inspect(evaled); } msg.channel.sendCode("xl", client.funcs.clean(client, evaled)); } catch (err) { - msg.channel.sendMessage("`ERROR` ```xl\n" + - client.funcs.clean(err) + - "\n```"); + msg.channel.sendMessage(`\`ERROR\` \`\`\`xl\n${ + client.funcs.clean(err) + }\n\`\`\``); } }; diff --git a/commands/System/help.js b/commands/System/help.js index d602bbad..dfed720e 100644 --- a/commands/System/help.js +++ b/commands/System/help.js @@ -1,24 +1,21 @@ exports.run = (client, msg, [cmd]) => { if (!cmd) { buildHelp(client, msg) - .then(help => { - let helpMessage = []; - for (let key in help) { + .then((help) => { + const helpMessage = []; + for (const key in help) { helpMessage.push(`**${key} Commands**: \`\`\`asciidoc`); - for (let key2 in help[key]) { + for (const key2 in help[key]) { helpMessage.push(`= ${key2} =`); - helpMessage.push(help[key][key2].join("\n") + "\n"); + helpMessage.push(`${help[key][key2].join("\n")}\n`); } helpMessage.push("```\n\u200b"); } - msg.channel.sendMessage(helpMessage, { split: { char: "\u200b" } }).catch(e => { console.error(e); }); + msg.channel.sendMessage(helpMessage, { split: { char: "\u200b" } }).catch((e) => { console.error(e); }); }); - - } else { - if (client.commands.has(cmd)) { - cmd = client.commands.get(cmd); - msg.channel.sendCode("asciidoc", `= ${cmd.help.name} = \n${cmd.help.description}\nusage :: ${client.funcs.fullUsage(client, cmd)}`); - } + } else if (client.commands.has(cmd)) { + cmd = client.commands.get(cmd); + msg.channel.sendCode("asciidoc", `= ${cmd.help.name} = \n${cmd.help.description}\nusage :: ${client.funcs.fullUsage(client, cmd)}`); } }; @@ -28,32 +25,29 @@ exports.conf = { aliases: [], permLevel: 0, botPerms: [], - requiredFuncs: [] + requiredFuncs: [], }; exports.help = { name: "help", description: "Display help for a command.", usage: "[command:str]", - usageDelim: "" + usageDelim: "", }; -const buildHelp = (client, msg) => { - return new Promise(resolve => { - let help = {}; - let mps = []; +const buildHelp = (client, msg) => new Promise((resolve) => { + const help = {}; + const mps = []; - let commandNames = Array.from(client.commands.keys()); - let longest = commandNames.reduce((longest, str) => { - return Math.max(longest, str.length); - }, 0); + const commandNames = Array.from(client.commands.keys()); + const longest = commandNames.reduce((longest, str) => Math.max(longest, str.length), 0); - client.commands.forEach(command => { - mps.push(new Promise(res => { - client.funcs.runCommandInhibitors(client, msg, command, true) + client.commands.forEach((command) => { + mps.push(new Promise((res) => { + client.funcs.runCommandInhibitors(client, msg, command, true) .then(() => { - let cat = command.help.category; - let subcat = command.help.subCategory; + const cat = command.help.category; + const subcat = command.help.subCategory; if (!help.hasOwnProperty(cat)) help[cat] = {}; if (!help[cat].hasOwnProperty(subcat)) help[cat][subcat] = []; help[cat][subcat].push(`${msg.guildConf.prefix}${command.help.name}::${" ".repeat(longest - command.help.name.length)} ${command.help.description}`); @@ -62,10 +56,9 @@ const buildHelp = (client, msg) => { .catch(() => { res(); }); - })); - }); - Promise.all(mps).then(() => { - resolve(help); - }); + })); }); -}; + Promise.all(mps).then(() => { + resolve(help); + }); +}); diff --git a/commands/System/reboot.js b/commands/System/reboot.js index c1d2ab65..82ea31a0 100644 --- a/commands/System/reboot.js +++ b/commands/System/reboot.js @@ -19,6 +19,7 @@ exports.run = (client, msg) => { console.error(e); }); } + return true; }); }; diff --git a/commands/System/reload.js b/commands/System/reload.js index eeca7e73..93f6ae52 100644 --- a/commands/System/reload.js +++ b/commands/System/reload.js @@ -1,3 +1,5 @@ +const path = require("path"); + exports.run = (client, msg, [commandname]) => { if (commandname === "all") { client.funcs.log("Reloading all commands"); @@ -17,7 +19,7 @@ exports.run = (client, msg, [commandname]) => { newCommands.forEach((file) => { msg.channel.sendMessage(`Loading New Command: ${commandname}`) .then((m) => { - client.funcs.loadSingleCommand(client, command, false, `${file.path}${require("path").sep}${file.base}`).then((cmd) => { + client.funcs.loadSingleCommand(client, command, false, `${file.path}${path.sep}${file.base}`).then((cmd) => { m.edit(`Successfully Loaded: ${cmd.help.name}`); }) .catch((e) => { diff --git a/commands/System/stats.js b/commands/System/stats.js index c285260e..5eda75ec 100644 --- a/commands/System/stats.js +++ b/commands/System/stats.js @@ -1,31 +1,33 @@ -const Discord = require("discord.js"); -const moment = require("moment"); -require("moment-duration-format"); + const Discord = require("discord.js"); + const moment = require("moment"); + const komada = require("../package.json"); + require("moment-duration-format"); -exports.run = (client, msg) => { - const duration = moment.duration(client.uptime).format(" D [days], H [hrs], m [mins], s [secs]"); - msg.channel.sendCode("asciidoc", `= STATISTICS = + exports.run = (client, msg) => { + const duration = moment.duration(client.uptime).format(" D [days], H [hrs], m [mins], s [secs]"); + msg.channel.sendCode("asciidoc", `= STATISTICS = • Mem Usage :: ${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB • Uptime :: ${duration} • Users :: ${client.users.size} • Servers :: ${client.guilds.size} • Channels :: ${client.channels.size} +• Komada :: ${komada.version} • Discord.js :: v${Discord.version}`); -}; + }; -exports.conf = { - enabled: true, - guildOnly: false, - aliases: ["details", "what"], - permLevel: 0, - botPerms: [], - requiredFuncs: [], -}; + exports.conf = { + enabled: true, + guildOnly: false, + aliases: ["details", "what"], + permLevel: 0, + botPerms: [], + requiredFuncs: [], + }; -exports.help = { - name: "stats", - description: "Provides some details about the bot and stats.", - usage: "", - usageDelim: "", -}; + exports.help = { + name: "stats", + description: "Provides some details about the bot and stats.", + usage: "", + usageDelim: "", + }; diff --git a/functions/addCommas.js b/functions/addCommas.js index 432d56fc..e2e80182 100644 --- a/functions/addCommas.js +++ b/functions/addCommas.js @@ -5,7 +5,7 @@ module.exports = (nStr) => { const x2 = x.length > 1 ? `.${x[1]}` : ""; const rgx = /(\d+)(\d{3})/; while (rgx.test(x1)) { - x1 = x1.replace(rgx, "$1" + "," + "$2"); + x1 = x1.replace(rgx, "$1,$2"); } return x1 + x2; }; diff --git a/functions/confs.js b/functions/confs.js index ad54dce4..55c7de8a 100644 --- a/functions/confs.js +++ b/functions/confs.js @@ -12,8 +12,8 @@ exports.init = (client) => { defaultConf = { prefix: { type: "String", data: client.config.prefix }, disabledCommands: { type: "Array", data: [] }, - mod_role: { type: "String", data: "Mods" }, - admin_role: { type: "String", data: "Devs" }, + modRole: { type: "String", data: "Mods" }, + adminRole: { type: "String", data: "Devs" }, }; fs.ensureFileSync(`${dataDir}${path.sep}${defaultFile}`); try { diff --git a/functions/createDBSchema.js b/functions/createDBSchema.js index 52259c5d..ada79e8a 100644 --- a/functions/createDBSchema.js +++ b/functions/createDBSchema.js @@ -9,7 +9,7 @@ module.exports = (data) => { current.canNull = true; } if (loc >= 0) { - throw `at field #${loc + 1} and #${i + 1}: There can't be two fields with the same name`; + throw new Error(`at field #${loc + 1} and #${i + 1}: There can't be two fields with the same name`); } names.push(current.name); @@ -18,7 +18,7 @@ module.exports = (data) => { case "autoid": case "bool": if (current.max || current.min) { - throw `at field #${i + 1}: The type '${current.type}'' may not have a length`; + throw new Error(`at field #${i + 1}: The type '${current.type}'' may not have a length`); } break; case "timestamp": @@ -30,7 +30,7 @@ module.exports = (data) => { case "string": break; default: - throw `at field #${i + 1}: The type '${current.type}' is not supported`; + throw new Error(`at field #${i + 1}: The type '${current.type}' is not supported`); } toRet.push(current); diff --git a/functions/getFileListing.js b/functions/getFileListing.js index b2b66d63..65f3ff6d 100644 --- a/functions/getFileListing.js +++ b/functions/getFileListing.js @@ -1,12 +1,11 @@ const path = require("path"); const fs = require("fs-extra"); -module.exports = (client, baseDir, type) => { - return new Promise((resolve, reject) => { - const dir = path.resolve(`${baseDir}/${type}/`); - const files = []; - try { - fs.walk(dir) +module.exports = (client, baseDir, type) => new Promise((resolve, reject) => { + const dir = path.resolve(`${baseDir}/${type}/`); + const files = []; + try { + fs.walk(dir) .on("data", (item) => { const fileinfo = path.parse(item.path); if (!fileinfo.ext) return; @@ -22,26 +21,25 @@ module.exports = (client, baseDir, type) => { resolve(files); }) .on("errors", (root, nodeStatsArray, next) => { - nodeStatsArray.forEach(function (n) { + nodeStatsArray.forEach((n) => { client.funcs.log(`[ERROR] " ${n.name}, "error"`); client.funcs.log(n.error.message || (`${n.error.code}: ${n.error.path}`), "error"); }); next(); }); - } catch (e) { - if (e.code === "MODULE_NOT_FOUND") { - const module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1, -1)) + } catch (e) { + if (e.code === "MODULE_NOT_FOUND") { + const module = /'[^']+'/g.exec(e.toString()); + client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadCommands(client); }) - .catch((e) => { - console.error(e); + .catch((err) => { + console.error(err); process.exit(); }); - } else { - reject(e); - } + } else { + reject(e); } - }); -}; + } +}); diff --git a/functions/installNPM.js b/functions/installNPM.js index a022e6a0..7feead0f 100644 --- a/functions/installNPM.js +++ b/functions/installNPM.js @@ -1,17 +1,15 @@ const exec = require("child_process").exec; -module.exports = (module) => { - return new Promise((resolve, reject) => { - exec(`npm i ${module}`, (e, stdout, stderr) => { - if (e) { - console.log("=====NEW DEPENDANCY INSTALL FAILED HORRIBLY====="); - reject(e); - } else { - console.log("=====INSTALLED NEW DEPENDANCY====="); - console.log(stdout); - console.error(stderr); - resolve(); - } - }); +module.exports = module => new Promise((resolve, reject) => { + exec(`npm i ${module}`, (e, stdout, stderr) => { + if (e) { + console.log("=====NEW DEPENDANCY INSTALL FAILED HORRIBLY====="); + reject(e); + } else { + console.log("=====INSTALLED NEW DEPENDANCY====="); + console.log(stdout); + console.error(stderr); + resolve(); + } }); -}; +}); diff --git a/functions/loadCommandInhibitors.js b/functions/loadCommandInhibitors.js index 9e05da5c..a79bbcd3 100644 --- a/functions/loadCommandInhibitors.js +++ b/functions/loadCommandInhibitors.js @@ -12,33 +12,32 @@ module.exports = (client) => { }); }; -const loadCommandInhibitors = (client, baseDir, counts) => { - return new Promise((resolve, reject) => { - const dir = path.resolve(`${baseDir}./inhibitors/`); - fs.ensureDir(dir, (err) => { +const loadCommandInhibitors = (client, baseDir, counts) => new Promise((resolve, reject) => { + const dir = path.resolve(`${baseDir}./inhibitors/`); + fs.ensureDir(dir, (err) => { + if (err) console.error(err); + fs.readdir(dir, (err, files) => { if (err) console.error(err); - fs.readdir(dir, (err, files) => { - if (err) console.error(err); - let [p, o] = counts; - try { - files = files.filter((f) => { return f.slice(-3) === ".js"; }); - files.forEach((f) => { - const file = f.split("."); - let props; - if (file[1] !== "opt") { - props = require(`${dir}/${f}`); - client.commandInhibitors.set(file[0], props); - p++; - } else if (client.config.commandInhibitors.includes(file[0])) { - props = require(`${dir}/${f}`); - client.commandInhibitors.set(file[0], props); - o++; - } - }); - } catch (e) { - if (e.code === "MODULE_NOT_FOUND") { - const module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1, -1)) + let [p, o] = counts; + try { + files = files.filter(f => f.slice(-3) === ".js"); + files.forEach((f) => { + const file = f.split("."); + let props; + if (file[1] !== "opt") { + props = require(`${dir}/${f}`); + client.commandInhibitors.set(file[0], props); + p++; + } else if (client.config.commandInhibitors.includes(file[0])) { + props = require(`${dir}/${f}`); + client.commandInhibitors.set(file[0], props); + o++; + } + }); + } catch (e) { + if (e.code === "MODULE_NOT_FOUND") { + const module = /'[^']+'/g.exec(e.toString()); + client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadCommandInhibitors(client); }) @@ -46,13 +45,12 @@ const loadCommandInhibitors = (client, baseDir, counts) => { console.error(e); process.exit(); }); - } else { - console.error(e); - } - reject(); + } else { + console.error(e); } - resolve([p, o]); - }); + reject(); + } + resolve([p, o]); }); }); -}; +}); diff --git a/functions/loadCommands.js b/functions/loadCommands.js index ed13e9a6..00df02af 100644 --- a/functions/loadCommands.js +++ b/functions/loadCommands.js @@ -1,14 +1,13 @@ const fs = require("fs-extra"); const path = require("path"); -const loadCommands = (client, baseDir, counts) => { - return new Promise((resolve, reject) => { - const dir = path.resolve(`${baseDir}./commands/`); - let [c, a] = counts; - try { - fs.ensureDir(dir, (err) => { - if (err) reject(err); - fs.walk(dir) +const loadCommands = (client, baseDir, counts) => new Promise((resolve, reject) => { + const dir = path.resolve(`${baseDir}./commands/`); + let [c, a] = counts; + try { + fs.ensureDir(dir, (err) => { + if (err) reject(err); + fs.walk(dir) .on("data", (item) => { const fileinfo = path.parse(item.path); const fileDir = fileinfo.dir; @@ -30,32 +29,31 @@ const loadCommands = (client, baseDir, counts) => { .on("end", () => { resolve([c, a]); }); - }); - } catch (e) { - if (e.code === "MODULE_NOT_FOUND") { - const module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1, -1)) + }); + } catch (e) { + if (e.code === "MODULE_NOT_FOUND") { + const module = /'[^']+'/g.exec(e.toString()); + client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadCommands(client); }) - .catch((e) => { - console.error(e); + .catch((err) => { + console.error(err); process.exit(); }); - } else { - reject(e); - } + } else { + reject(e); } - }); -}; + } +}); module.exports = (client) => { client.commands.clear(); client.aliases.clear(); const counts = [0, 0]; - loadCommands(client, client.coreBaseDir, counts).then((counts) => { - loadCommands(client, client.clientBaseDir, counts).then((counts) => { - const [c, a] = counts; + loadCommands(client, client.coreBaseDir, counts).then((count) => { + loadCommands(client, client.clientBaseDir, count).then((countss) => { + const [c, a] = countss; client.funcs.log(`Loaded ${c} commands, with ${a} aliases.`); }); }); diff --git a/functions/loadDataProviders.js b/functions/loadDataProviders.js index 34994f01..5f03d22c 100644 --- a/functions/loadDataProviders.js +++ b/functions/loadDataProviders.js @@ -1,35 +1,34 @@ const fs = require("fs-extra"); const path = require("path"); -const loadDataProviders = (client, baseDir, counts) => { - return new Promise((resolve, reject) => { - const dir = path.resolve(`${baseDir}./dataProviders/`); - fs.ensureDir(dir, (err) => { +const loadDataProviders = (client, baseDir, counts) => new Promise((resolve, reject) => { + const dir = path.resolve(`${baseDir}./dataProviders/`); + fs.ensureDir(dir, (err) => { + if (err) console.error(err); + fs.readdir(dir, (err, files) => { if (err) console.error(err); - fs.readdir(dir, (err, files) => { - if (err) console.error(err); - let [d, o] = counts; - try { - files = files.filter((f) => { return f.slice(-3) === ".js"; }); - files.forEach((f) => { - const file = f.split("."); - let props; - if (file[1] !== "opt") { - props = require(`${dir}/${f}`); - client.dataProviders.set(file[0], props); - props.init(client); - d++; - } else if (client.config.dataProviders.includes(file[0])) { - props = require(`${dir}/${f}`); - client.dataProviders.set(file[0], props); - props.init(client); - o++; - } - }); - } catch (e) { - if (e.code === "MODULE_NOT_FOUND") { - const module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1, -1)) + let [d, o] = counts; + try { + files = files.filter(f => f.slice(-3) === ".js"); + files.forEach((f) => { + const file = f.split("."); + let props; + if (file[1] !== "opt") { + props = require(`${dir}/${f}`); + client.dataProviders.set(file[0], props); + props.init(client); + d++; + } else if (client.config.dataProviders.includes(file[0])) { + props = require(`${dir}/${f}`); + client.dataProviders.set(file[0], props); + props.init(client); + o++; + } + }); + } catch (e) { + if (e.code === "MODULE_NOT_FOUND") { + const module = /'[^']+'/g.exec(e.toString()); + client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadDataProviders(client, baseDir, counts); }) @@ -37,15 +36,14 @@ const loadDataProviders = (client, baseDir, counts) => { console.error(e); process.exit(); }); - } else { - reject(e); - } + } else { + reject(e); } - resolve([d, o]); - }); + } + resolve([d, o]); }); }); -}; +}); module.exports = (client) => { client.dataProviders.clear(); diff --git a/functions/loadEvents.js b/functions/loadEvents.js index 470148ee..ba537a44 100644 --- a/functions/loadEvents.js +++ b/functions/loadEvents.js @@ -2,36 +2,35 @@ const fs = require("fs-extra"); const path = require("path"); let events = require("discord.js/src/util/Constants.js").Events; + events = Object.keys(events).map(k => events[k]); -const loadEvents = (client, baseDir, count) => { - return new Promise((resolve, reject) => { - const dir = path.resolve(`${baseDir}./events/`); - fs.ensureDir(dir, (err) => { - if (err) reject(err); - fs.readdir(dir, (err, files) => { - if (err) reject(err); - let e = count; - files = files.filter((f) => { - const name = f.split(".")[0]; - return events.includes(name); - }); - files.forEach((f) => { - const name = f.split(".")[0]; - client.on(name, (...args) => require(`${dir}/${f}`).run(client, ...args)); - e++; - }); - resolve(e); +const loadEvents = (client, baseDir, count) => new Promise((resolve, reject) => { + const dir = path.resolve(`${baseDir}./events/`); + fs.ensureDir(dir, (err) => { + if (err) reject(err); + fs.readdir(dir, (error, files) => { + if (error) reject(err); + let e = count; + files = files.filter((f) => { + const name = f.split(".")[0]; + return events.includes(name); + }); + files.forEach((f) => { + const name = f.split(".")[0]; + client.on(name, (...args) => require(`${dir}/${f}`).run(client, ...args)); + e++; }); + resolve(e); }); }); -}; +}); module.exports = (client) => { const count = 0; - loadEvents(client, client.coreBaseDir, count).then((count) => { - loadEvents(client, client.clientBaseDir, count).then((count) => { - client.funcs.log(`Loaded ${count} events`); + loadEvents(client, client.coreBaseDir, count).then((counts) => { + loadEvents(client, client.clientBaseDir, counts).then((countss) => { + client.funcs.log(`Loaded ${countss} events`); }); }); }; diff --git a/functions/loadFunctions.js b/functions/loadFunctions.js index 7b5a0149..8c6d1b6f 100644 --- a/functions/loadFunctions.js +++ b/functions/loadFunctions.js @@ -1,55 +1,51 @@ const fs = require("fs-extra"); const path = require("path"); -const loadFunctions = (client, baseDir, counts) => { - return new Promise((resolve, reject) => { - const dir = path.resolve(`${baseDir}./functions/`); - fs.ensureDirSync(dir); - fs.readdir(dir, (err, files) => { - if (err) reject(err); - files = files.filter((f) => { return f.slice(-3) === ".js"; }); - let [d, o] = counts; - try { - files.forEach((f) => { - const file = f.split("."); - if (file[0] === "loadFunctions") return; - if (file[1] !== "opt") { - client.funcs[file[0]] = require(`${dir}/${f}`); - d++; - } else if (client.config.functions.includes(file[0])) { - client.funcs[file[0]] = require(`${dir}/${f}`); - o++; - } - }); - resolve([d, o]); - } catch (e) { - if (e.code === "MODULE_NOT_FOUND") { - const module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1, -1)) +const loadFunctions = (client, baseDir, counts) => new Promise((resolve, reject) => { + const dir = path.resolve(`${baseDir}./functions/`); + fs.ensureDirSync(dir); + fs.readdir(dir, (err, files) => { + if (err) reject(err); + files = files.filter(f => f.slice(-3) === ".js"); + let [d, o] = counts; + try { + files.forEach((f) => { + const file = f.split("."); + if (file[0] === "loadFunctions") return; + if (file[1] !== "opt") { + client.funcs[file[0]] = require(`${dir}/${f}`); + d++; + } else if (client.config.functions.includes(file[0])) { + client.funcs[file[0]] = require(`${dir}/${f}`); + o++; + } + }); + resolve([d, o]); + } catch (e) { + if (e.code === "MODULE_NOT_FOUND") { + const module = /'[^']+'/g.exec(e.toString()); + client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadDatabaseHandlers(client); }) - .catch((e) => { - console.error(e); + .catch((error) => { + console.error(error); process.exit(); }); - } else { - reject(e); - } + } else { + reject(e); } - }); + } }); -}; +}); -module.exports = (client) => { - return new Promise((resolve, reject) => { - const counts = [0, 0]; - loadFunctions(client, client.coreBaseDir, counts).then((counts) => { - loadFunctions(client, client.clientBaseDir, counts).then((counts) => { - const [d, o] = counts; - client.funcs.log(`Loaded ${d} functions, with ${o} optional.`); - resolve(); - }); - }).catch(reject); - }); -}; +module.exports = client => new Promise((resolve, reject) => { + const counts = [0, 0]; + loadFunctions(client, client.coreBaseDir, counts).then((count) => { + loadFunctions(client, client.clientBaseDir, count).then((countss) => { + const [d, o] = countss; + client.funcs.log(`Loaded ${d} functions, with ${o} optional.`); + resolve(); + }); + }).catch(reject); +}); diff --git a/functions/loadSingleCommand.js b/functions/loadSingleCommand.js index b241e42d..7ad7a9ee 100644 --- a/functions/loadSingleCommand.js +++ b/functions/loadSingleCommand.js @@ -1,42 +1,41 @@ const path = require("path"); -module.exports = function (client, command, reload = false, loadPath = null) { - return new Promise((resolve, reject) => { - let category; - let subCategory; - let cmd; - if (!loadPath && !reload) return reject("Path must be provided when loading a new command."); - if (reload) { - if (!client.commands.has(command)) { - reject("Reload requested, but command does not exist."); - } - try { - cmd = client.commands.get(command); - category = cmd.help.category; - subCategory = cmd.help.subCategory; - loadPath = cmd.help.filePath; - client.aliases.forEach((cmd, alias) => { - if (cmd === command) client.aliases.delete(alias); - }); - delete require.cache[require.resolve(loadPath)]; - cmd = require(loadPath); - } catch (e) { - reject(`Could not load existing command data: ${e.stack}`); +module.exports = (client, command, reload = false, loadPath = null) => new Promise((resolve, reject) => { + let category; + let subCategory; + let cmd; + if (!loadPath && !reload) return reject("Path must be provided when loading a new command."); + if (reload) { + if (!client.commands.has(command)) { + reject("Reload requested, but command does not exist."); + } + try { + cmd = client.commands.get(command); + category = cmd.help.category; + subCategory = cmd.help.subCategory; + loadPath = cmd.help.filePath; + client.aliases.forEach((cmds, alias) => { + if (cmds === command) client.aliases.delete(alias); + }); + delete require.cache[require.resolve(loadPath)]; + cmd = require(loadPath); + } catch (e) { + reject(`Could not load existing command data: ${e.stack}`); + } + } else { + try { + cmd = require(loadPath); + if (cmd.conf.selfbot && !client.config.selfbot) { + return reject(`The command \`${cmd.help.name}\` is only usable in selfbots!`); } - } else { - try { - cmd = require(loadPath); - if (cmd.conf.selfbot && !client.config.selfbot) { - return reject(`The command \`${cmd.help.name}\` is only usable in selfbots!`); - } - let pathParts = loadPath.split(path.sep); - pathParts = pathParts.slice(pathParts.indexOf("commands") + 1); - category = client.funcs.toTitleCase(cmd.help.category ? cmd.help.category : (pathParts[0] && pathParts[0].length > 0 ? pathParts[0] : "General")); - subCategory = client.funcs.toTitleCase(cmd.help.subCategory ? cmd.help.subCategory : (pathParts[1] && pathParts[1].length > 0 && !~pathParts[1].indexOf(".") ? pathParts[1] : "General")); - } catch (e) { - if (e.code === "MODULE_NOT_FOUND") { - const module = /'[^']+'/g.exec(e.toString()); - client.funcs.installNPM(module[0].slice(1, -1)) + let pathParts = loadPath.split(path.sep); + pathParts = pathParts.slice(pathParts.indexOf("commands") + 1); + category = client.funcs.toTitleCase(cmd.help.category ? cmd.help.category : (pathParts[0] && pathParts[0].length > 0 ? pathParts[0] : "General")); + subCategory = client.funcs.toTitleCase(cmd.help.subCategory ? cmd.help.subCategory : (pathParts[1] && pathParts[1].length > 0 && !~pathParts[1].indexOf(".") ? pathParts[1] : "General")); + } catch (e) { + if (e.code === "MODULE_NOT_FOUND") { + const module = /'[^']+'/g.exec(e.toString()); + client.funcs.installNPM(module[0].slice(1, -1)) .then(() => { client.funcs.loadSingleCommand(client, command, false, loadPath); }) @@ -44,35 +43,35 @@ module.exports = function (client, command, reload = false, loadPath = null) { console.error(e); process.exit(); }); - } else { - reject(`Could not load new command data: ${e.stack}`); - } + } else { + reject(`Could not load new command data: ${e.stack}`); } } + } // complement data from meta - cmd.help.category = category; - cmd.help.subCategory = subCategory; - cmd.help.filePath = loadPath; + cmd.help.category = category; + cmd.help.subCategory = subCategory; + cmd.help.filePath = loadPath; // Load Aliases - cmd.conf.aliases.forEach((alias) => { - client.aliases.set(alias, cmd.help.name); - }); + cmd.conf.aliases.forEach((alias) => { + client.aliases.set(alias, cmd.help.name); + }); // update help structure - if (!client.helpStructure.has(category)) { - client.helpStructure.set(category, new Map()); - } - const catMap = client.helpStructure.get(category); - if (!catMap.has(subCategory)) { - catMap.set(subCategory, new Map()); - } - const subCatMap = catMap.get(subCategory); - subCatMap.set(cmd.help.name, cmd.help.description); + if (!client.helpStructure.has(category)) { + client.helpStructure.set(category, new Map()); + } + const catMap = client.helpStructure.get(category); + if (!catMap.has(subCategory)) { + catMap.set(subCategory, new Map()); + } + const subCatMap = catMap.get(subCategory); + subCatMap.set(cmd.help.name, cmd.help.description); - client.commands.set(cmd.help.name, cmd); + client.commands.set(cmd.help.name, cmd); - resolve(cmd); - }); -}; + resolve(cmd); + return true; +}); diff --git a/functions/log.js b/functions/log.js index 2e457b96..183f8e72 100644 --- a/functions/log.js +++ b/functions/log.js @@ -3,7 +3,7 @@ const chalk = require("chalk"); const clk = new chalk.constructor({ enabled: true }); -module.exports = function (data, type = "log") { +module.exports = (data, type = "log") => { switch (type.toLowerCase()) { case "debug": console.log(`${clk.bgMagenta(`[${moment().format("YYYY-MM-DD HH:mm:ss")}]`)} ${data}`); @@ -17,5 +17,6 @@ module.exports = function (data, type = "log") { case "log": console.log(`${clk.bgBlue(`[${moment().format("YYYY-MM-DD HH:mm:ss")}]`)} ${data}`); break; + // no default } }; diff --git a/functions/parseTags.js b/functions/parseTags.js index b9cc2bce..1315d82c 100644 --- a/functions/parseTags.js +++ b/functions/parseTags.js @@ -96,7 +96,7 @@ const parseTagData = (data, disallow, tag) => { try { bound.min = parseFloat(current); } catch (e) { - throw ""; + throw new Error(""); } current = ""; } @@ -133,7 +133,7 @@ const parseTagData = (data, disallow, tag) => { } if (["string", "str"].includes(bound.type)) { - if (bound.max && bound.max % 1 !== 0 || bound.min && bound.min % 1 !== 0) { + if ((bound.max && bound.max % 1 !== 0) || (bound.min && bound.min % 1 !== 0)) { throw new ParserError("String types may have an integer length", "tag(possibility)", `${tag}(${i + 1}) in the length definition`); } } @@ -159,52 +159,60 @@ const parseTagData = (data, disallow, tag) => { }; module.exports = (command, disallowCharacters) => { - /*** + /** * parseTags("[asda:asd{1.5,2.2}] [asd] [...]").then(tags => console.log(util.inspect(tags, false, null))).catch(e => console.log(e + "")); ***/ - let opened, current = "", - tags = [], - closed = false; + let opened; + let current = ""; + const tags = []; + let closed = false; command.split("").forEach((c, i) => { - switch (c) { case "<": case "[": - if (closed) + if (closed) { throw new ParserError("You can't open another tag once a loop tag was set", "char", i + 1, c); - if (opened) + } + if (opened) { throw new ParserError("You cannot open a tag inside another tag", "char", i + 1, c); - if (current) - throw new ParserError("There can't be literals outside a tag", "char", i + 1, current, i + 1 - current.length); + } + if (current) { + throw new ParserError("There can't be literals outside a tag", "char", i + 1, current, (i + 1) - current.length); + } opened = c; break; case ">": case "]": - if (!opened) + if (!opened) { throw new ParserError("Invalid tag closure, no tag was open", "char", i + 1, c); + } - if (!current) + if (!current) { throw new ParserError("An empty tag was found", "char", i + 1, opened + c, i); + } - if (c === ">" && opened !== "<" || c === "]" && opened !== "[") + if ((c === ">" && opened !== "<") || (c === "]" && opened !== "[")) { throw new ParserError(`Invalid closure of '${opened}' with '${c}'`, "char", i + 1, opened + current + c, i - current.length); + } if (current === "..." && opened === "[" && !disallowCharacters) { - if (tags.length === 0) + if (tags.length === 0) { throw new ParserError("You cannot specify a loop tag in the begining", "tag", tags.length + 1); + } tags.push({ - type: "loop" + type: "loop", }); - //tags[tags.length -1].loop = true; + // tags[tags.length -1].loop = true; closed = true; - } else + } else { tags.push({ type: c === ">" ? "required" : "optional", - possibles: parseTagData(current, disallowCharacters, tags.length + 1) + possibles: parseTagData(current, disallowCharacters, tags.length + 1), }); + } current = ""; opened = null; @@ -217,7 +225,6 @@ module.exports = (command, disallowCharacters) => { current += c; break; } - }); return tags; }; diff --git a/functions/parseUsage.js b/functions/parseUsage.js index 947533c0..cbbd2b67 100644 --- a/functions/parseUsage.js +++ b/functions/parseUsage.js @@ -3,9 +3,9 @@ const parseTag = (tag, count) => { asd|asd:Number|asd:String */ - let literals = [], - types = [], - toRet = []; + const literals = []; + const types = []; + const toRet = []; const members = tag.split("|"); @@ -13,46 +13,48 @@ const parseTag = (tag, count) => { const result = /^([a-z0-9]+)(?::([a-z0-9]+)(?:{(?:(\d+(?:\.\d+)?))?(?:,(\d+(?:\.\d+)?))?})?)?$/i.exec(e); // I require to modify the regex if we wan't to handle invalid types instead of defaulting them - if (!result) - throw new Error(`at tag #${count} at bound #${i+1}: Invalid syntax, non spesific`); + if (!result) { throw new Error(`at tag #${count} at bound #${i + 1}: Invalid syntax, non spesific`); } - let fill = { + const fill = { name: result[1], - type: result[2] ? result[2].toLowerCase() : "literal" + type: result[2] ? result[2].toLowerCase() : "literal", }; if (result[3]) { - if (fill.type === "literal") - throw new Error(`at tag #${count} at bound #${i+1} at the type length definition (min): you canno't set a length for a literal type`); + if (fill.type === "literal") { + throw new Error(`at tag #${count} at bound #${i + 1} at the type length definition (min): you canno't set a length for a literal type`); + } const temp = parseFloat(result[3]); - if ((fill.type === "string" || fill.type === "str") && temp % 1 !== 0) - throw new Error(`at tag #${count} at bound #${i+1} at the type length definition (min): the string type must have an integer length`); + if ((fill.type === "string" || fill.type === "str") && temp % 1 !== 0) { + throw new Error(`at tag #${count} at bound #${i + 1} at the type length definition (min): the string type must have an integer length`); + } fill.min = temp; } if (result[4]) { - if (fill.type === "literal") - throw new Error(`at tag #${count} at bound #${i+1} at the type length definition (max): you canno't set a length for a literal type`); + if (fill.type === "literal") { + throw new Error(`at tag #${count} at bound #${i + 1} at the type length definition (max): you canno't set a length for a literal type`); + } const temp = parseFloat(result[4]); - if ((fill.type === "string" || fill.type === "str") && temp % 1 !== 0) - throw new Error(`at tag #${count} at bound #${i+1} at the type length definition (max): the string type must have an integer length`); + if ((fill.type === "string" || fill.type === "str") && temp % 1 !== 0) { throw new Error(`at tag #${count} at bound #${i + 1} at the type length definition (max): the string type must have an integer length`); } fill.max = temp; } if (fill.type === "literal") { - if (literals.includes(fill.name)) - throw new Error(`at tag #${count} at bound #${i+1}: there can't be two literals with the same text.`); + if (literals.includes(fill.name)) { throw new Error(`at tag #${count} at bound #${i + 1}: there can't be two literals with the same text.`); } literals.push(fill.name); } else if (members.length > 1) { - if (fill.type === "string" && members.length - 1 !== i) - throw new Error(`at tag #${count} at bound #${i+1}: the String type is vague, you must specify it at the last bound`); - if (types.includes(fill.type)) - throw new Error(`at tag #${count} at bound #${i+1}: there can't be two bounds with the same type (${fill.type})`); + if (fill.type === "string" && members.length - 1 !== i) { + throw new Error(`at tag #${count} at bound #${i + 1}: the String type is vague, you must specify it at the last bound`); + } + if (types.includes(fill.type)) { + throw new Error(`at tag #${count} at bound #${i + 1}: there can't be two bounds with the same type (${fill.type})`); + } types.push(fill.type); } @@ -62,76 +64,86 @@ const parseTag = (tag, count) => { return toRet; }; -module.exports = command => { - let tags = [], - opened = 0, - current = "", - openReq = false, - last = false; - var cmd = command.split(""); +module.exports = (command) => { + const tags = []; + let opened = 0; + let current = ""; + let openReq = false; + let last = false; + const cmd = command.split(""); cmd.forEach((c, i) => { - if (last && c !== " ") // Allow spaces which are ignored? - throw new Error(`at char #${i+1} '${c}': there can't be anything else after the repeat tag.`); + if (last && c !== " ") { + throw new Error(`at char #${i + 1} '${c}': there can't be anything else after the repeat tag.`); + } if (c === "<") { - if (opened) - throw new Error(`at char #${i+1} '<': you might not open a tag inside another tag.`); - if (current) - throw new Error(`from char #${i+1 -current.length} to #${i+1} '${current}': there can't be a literal outside a tag`); + if (opened) { + throw new Error(`at char #${i + 1} '<': you might not open a tag inside another tag.`); + } + if (current) { + throw new Error(`from char #${(i + 1) - current.length} to #${i + 1} '${current}': there can't be a literal outside a tag`); + } opened++; openReq = true; } else if (c === ">") { - if (!opened) - throw new Error(`at char #${i+1} '>': invalid close tag found`); - if (!openReq) - throw new Error(`at char #${i+1} '>': Invalid closure of '[${current}' with '>'`); + if (!opened) { + throw new Error(`at char #${i + 1} '>': invalid close tag found`); + } + if (!openReq) { + throw new Error(`at char #${i + 1} '>': Invalid closure of '[${current}' with '>'`); + } opened--; if (current) { tags.push({ type: "required", - possibles: parseTag(current, tags.length + 1) + possibles: parseTag(current, tags.length + 1), }); current = ""; - } else throw new Error(`at char #${i+1} '>': empty tag found`); + } else throw new Error(`at char #${i + 1} '>': empty tag found`); } else if (c === "[") { - if (opened) - throw new Error(`at char #${i+1} '[': you might not open a tag inside another tag.`); - if (current) - throw new Error(`from char #${i+1 -current.length} to #${i+1} '${current}': there can't be a literal outside a tag`); + if (opened) { + throw new Error(`at char #${i + 1} '[': you might not open a tag inside another tag.`); + } + if (current) { + throw new Error(`from char #${(i + 1) - current.length} to #${i + 1} '${current}': there can't be a literal outside a tag`); + } opened++; openReq = false; } else if (c === "]") { - if (!opened) - throw new Error(`at char #${i+1} ']': invalid close tag found`); - if (openReq) - throw new Error(`at char #${i+1} '>': Invalid closure of '<${current}' with ']'`); + if (!opened) { + throw new Error(`at char #${i + 1} ']': invalid close tag found`); + } + if (openReq) { throw new Error(`at char #${i + 1} '>': Invalid closure of '<${current}' with ']'`); } opened--; if (current === "...") { - if (tags.length < 1) - throw new Error(`from char #${i-3} to #${i} '[...]': there can't be a loop at teh begining`); + if (tags.length < 1) { + throw new Error(`from char #${i - 3} to #${i} '[...]': there can't be a loop at teh begining`); + } tags.push({ type: "repeat" }); last = true; current = ""; } else if (current) { tags.push({ type: "optional", - possibles: parseTag(current, tags.length + 1) + possibles: parseTag(current, tags.length + 1), }); current = ""; - } else throw new Error(`at char #${i+1} ']': empty tag found`); + } else throw new Error(`at char #${i + 1} ']': empty tag found`); } else if (c === " ") { - if (opened) - throw new Error(`at char #${i+1}: spaces aren't allowed inside a tag`); - if (current) - throw new Error(`from char #${i +1 -current.length} to char #${i} '${current}': there can't be a literal outside a tag.`); + if (opened) { throw new Error(`at char #${i + 1}: spaces aren't allowed inside a tag`); } + if (current) { + throw new Error(`from char #${(i + 1) - current.length} to char #${i} '${current}': there can't be a literal outside a tag.`); + } } else current += c; }); - if (opened) - throw new Error(`from char #${command.length -current.length} '${cmd[command.length -current.length-1]}' to end: a tag was left open`); + if (opened) { + throw new Error(`from char #${command.length - current.length} '${cmd[command.length - current.length - 1]}' to end: a tag was left open`); + } - if (current) - throw new Error(`from char #${command.length +1 -current.length} to end '${current}' a literal was found outside a tag.`); + if (current) { + throw new Error(`from char #${(command.length + 1) - current.length} to end '${current}' a literal was found outside a tag.`); + } return tags; }; diff --git a/functions/permissionLevel.js b/functions/permissionLevel.js index 90b397ac..ed4d9585 100644 --- a/functions/permissionLevel.js +++ b/functions/permissionLevel.js @@ -1,28 +1,26 @@ -module.exports = (client, user, guild = null) => { - return new Promise((resolve, reject) => { - const guildConf = client.funcs.confs.get(guild); - let permlvl = 0; - if (guild) { - try { - const member = guild.member(user); - const mod_role = guild.roles.find("name", guildConf.mod_role); - if (mod_role && member.roles.has(mod_role.id)) { - permlvl = 2; - } - const admin_role = guild.roles.find("name", guildConf.admin_role); - if (admin_role && member.roles.has(admin_role.id)) { - permlvl = 3; - } - if (member === guild.owner) { - permlvl = 4; - } - } catch (e) { - reject(e); +module.exports = (client, user, guild = null) => new Promise((resolve, reject) => { + const guildConf = client.funcs.confs.get(guild); + let permlvl = 0; + if (guild) { + try { + const member = guild.member(user); + const modRole = guild.roles.find("name", guildConf.modRole); + if (modRole && member.roles.has(modRole.id)) { + permlvl = 2; } + const adminRole = guild.roles.find("name", guildConf.adminRole); + if (adminRole && member.roles.has(adminRole.id)) { + permlvl = 3; + } + if (member === guild.owner) { + permlvl = 4; + } + } catch (e) { + reject(e); } - if (user.id === client.config.ownerid) { - permlvl = 10; - } - resolve(permlvl); - }); -}; + } + if (user.id === client.config.ownerid) { + permlvl = 10; + } + resolve(permlvl); +}); diff --git a/functions/runCommandInhibitors.js b/functions/runCommandInhibitors.js index 524731dd..9fe33f78 100644 --- a/functions/runCommandInhibitors.js +++ b/functions/runCommandInhibitors.js @@ -1,20 +1,18 @@ -module.exports = (client, msg, cmd, selective = false) => { - return new Promise((resolve, reject) => { - const mps = [true]; - let i = 1; - let usage; - client.commandInhibitors.forEach((mProc, key) => { - if (key === "usage") usage = i; - if (!mProc.conf.spamProtection || !selective) { - mps.push(mProc.run(client, msg, cmd)); - } - i++; - }); - Promise.all(mps) +module.exports = (client, msg, cmd, selective = false) => new Promise((resolve, reject) => { + const mps = [true]; + let i = 1; + let usage; + client.commandInhibitors.forEach((mProc, key) => { + if (key === "usage") usage = i; + if (!mProc.conf.spamProtection || !selective) { + mps.push(mProc.run(client, msg, cmd)); + } + i++; + }); + Promise.all(mps) .then((value) => { resolve(value[usage]); }, (reason) => { reject(reason); }); - }); -}; +}); diff --git a/functions/toTitleCase.js b/functions/toTitleCase.js index 8b53901c..5f09a687 100644 --- a/functions/toTitleCase.js +++ b/functions/toTitleCase.js @@ -1,5 +1 @@ -module.exports = (str) => { - return str.replace(/\w\S*/g, function (txt) { - return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); - }); -}; +module.exports = str => str.replace(/\w\S*/g, txt => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()); diff --git a/functions/validateData.js b/functions/validateData.js index 2c602f93..8bac80b2 100644 --- a/functions/validateData.js +++ b/functions/validateData.js @@ -1,58 +1,64 @@ module.exports = (data, properties, values) => { - let names = [], - compiled = []; + const names = []; + const compiled = []; properties.forEach((p, i) => { - var temp = data.find(e => e.name === p); - if (!temp) - throw `at property #${i +1}: Cannot find the name '${p}' in the schema, names are case sensitive`; + const temp = data.find(e => e.name === p); + if (!temp) { + throw new Error(`at property #${i + 1}: Cannot find the name '${p}' in the schema, names are case sensitive`); + } const loc = names.indexOf(temp.name); - if (loc >= 0) - throw `at properties #${loc +1} and #${i +1}: Duplicated properties found`; + if (loc >= 0) { + throw new Error(`at properties #${loc + 1} and #${i + 1}: Duplicated properties found`); + } names.push(temp.name); compiled.push(temp); }); - if (values.length !== compiled.length) - throw "The values and properties must contain the same amount of elements"; + if (values.length !== compiled.length) { + throw new Error("The values and properties must contain the same amount of elements"); + } values.forEach((v, i) => { - - var bound = compiled[i]; + const bound = compiled[i]; if (v === null) { - if (bound.canNull) + if (bound.canNull) { return; - else if (!["autots", "autoid"].includes(bound.type)) - throw `at value #${i +1}: Can't be null`; + } else if (!["autots", "autoid"].includes(bound.type)) { + throw new Error(`at value #${i + 1}: Can't be null`); + } } switch (bound.type) { case "autots": case "autoid": - if (v !== null) - throw `at value #${i +1}: The type '${bound.type}' must not be specified, try to set it to 'null', got '${v}`; + if (v !== null) { + throw new Error(`at value #${i + 1}: The type '${bound.type}' must not be specified, try to set it to 'null', got '${v}`); + } break; case "bool": - if (!["true", "false", true, false, 1, 0].includes(v.toLowerCase())) - throw `at value #${i +1}: The 'bool' type must be 'true(1)' or 'false(0)', got '${v}`; + if (!["true", "false", true, false, 1, 0].includes(v.toLowerCase())) { + throw new Error(`at value #${i + 1}: The 'bool' type must be 'true(1)' or 'false(0)', got '${v}`); + } break; case "timestamp": try { - if (new Date(parseInt(v)).getTime() <= 0) - throw null; + if (new Date(parseInt(v)).getTime() <= 0) { + throw new Error(null); + } } catch (e) { - throw `at value #${i +1}: The 'timestamp' type must be a integer number and greater than zero, got '${v}'`; + throw new Error(`at value #${i + 1}: The 'timestamp' type must be a integer number and greater than zero, got '${v}'`); } break; case "int": - if (isNaN(v) || v % 1 !== 0) - throw `at value #${i +1}: The '${bound.type}' must be a number without decimal places, got '${v}'`; + if (isNaN(v) || v % 1 !== 0) { + throw new Error(`at value #${i + 1}: The '${bound.type}' must be a number without decimal places, got '${v}'`); + } break; case "double": case "float": - if (isNaN(v)) - throw `at value #${i +1}: The '${bound.type}' must be a number, got '${v}`; + if (isNaN(v)) { throw new Error(`at value #${i + 1}: The '${bound.type}' must be a number, got '${v}`); } break; case "json": JSON.parse(JSON.stringify(v)); diff --git a/inhibitors/disable.js b/inhibitors/disable.js index a21fc50f..d000fdc0 100644 --- a/inhibitors/disable.js +++ b/inhibitors/disable.js @@ -3,12 +3,10 @@ exports.conf = { spamProtection: false, }; -exports.run = (client, msg, cmd) => { - return new Promise((resolve, reject) => { - if (cmd.conf.enabled && !msg.guildConf.disabledCommands.includes(cmd.help.name)) { - resolve(); - } else { - reject("This command is currently disabled"); - } - }); -}; +exports.run = (client, msg, cmd) => new Promise((resolve, reject) => { + if (cmd.conf.enabled && !msg.guildConf.disabledCommands.includes(cmd.help.name)) { + resolve(); + } else { + reject("This command is currently disabled"); + } +}); diff --git a/inhibitors/guildOnly.js b/inhibitors/guildOnly.js index b20e9d89..cb25618d 100644 --- a/inhibitors/guildOnly.js +++ b/inhibitors/guildOnly.js @@ -3,12 +3,10 @@ exports.conf = { spamProtection: false, }; -exports.run = (client, msg, cmd) => { - return new Promise((resolve, reject) => { - if (msg.guild || !cmd.conf.guildOnly) { - resolve(); - } else { - reject("This command is only available in a guild."); - } - }); -}; +exports.run = (client, msg, cmd) => new Promise((resolve, reject) => { + if (msg.guild || !cmd.conf.guildOnly) { + resolve(); + } else { + reject("This command is only available in a guild."); + } +}); diff --git a/inhibitors/missingBotPermissions.js b/inhibitors/missingBotPermissions.js index fdc329e9..36a923d8 100644 --- a/inhibitors/missingBotPermissions.js +++ b/inhibitors/missingBotPermissions.js @@ -3,21 +3,19 @@ exports.conf = { spamProtection: false, }; -exports.run = (client, msg, cmd) => { - return new Promise((resolve, reject) => { - let missing = []; - if (msg.channel.type === "text") { - missing = msg.channel.permissionsFor(client.user).missingPermissions(cmd.conf.botPerms); - } else { - const impliedPermissions = client.funcs.impliedPermissions(); - cmd.conf.botPerms.forEach((perm) => { - if (!impliedPermissions[perm]) missing.push(perm); - }); - } - if (missing.length > 0) { - reject(`Insufficient permissions, missing: **${client.funcs.toTitleCase(missing.join(", ").split("_").join(" "))}**`); - } else { - resolve(); - } - }); -}; +exports.run = (client, msg, cmd) => new Promise((resolve, reject) => { + let missing = []; + if (msg.channel.type === "text") { + missing = msg.channel.permissionsFor(client.user).missingPermissions(cmd.conf.botPerms); + } else { + const impliedPermissions = client.funcs.impliedPermissions(); + cmd.conf.botPerms.forEach((perm) => { + if (!impliedPermissions[perm]) missing.push(perm); + }); + } + if (missing.length > 0) { + reject(`Insufficient permissions, missing: **${client.funcs.toTitleCase(missing.join(", ").split("_").join(" "))}**`); + } else { + resolve(); + } +}); diff --git a/inhibitors/permissions.js b/inhibitors/permissions.js index ae1a0e2b..4b37788d 100644 --- a/inhibitors/permissions.js +++ b/inhibitors/permissions.js @@ -3,9 +3,8 @@ exports.conf = { spamProtection: false, }; -exports.run = (client, msg, cmd) => { - return new Promise((resolve, reject) => { - client.funcs.permissionLevel(client, msg.author, msg.guild) +exports.run = (client, msg, cmd) => new Promise((resolve, reject) => { + client.funcs.permissionLevel(client, msg.author, msg.guild) .then((permlvl) => { if (permlvl >= cmd.conf.permLevel) { resolve(); @@ -13,5 +12,4 @@ exports.run = (client, msg, cmd) => { reject("You do not have permission to use this command."); } }); - }); -}; +}); diff --git a/inhibitors/requiredFuncs.js b/inhibitors/requiredFuncs.js index 44293511..71d3e3df 100644 --- a/inhibitors/requiredFuncs.js +++ b/inhibitors/requiredFuncs.js @@ -3,11 +3,9 @@ exports.conf = { spamProtection: false, }; -exports.run = (client, msg, cmd) => { - return new Promise((resolve, reject) => { - cmd.conf.requiredFuncs.forEach((func) => { - if (!client.funcs.hasOwnProperty(func)) reject(`The client is missing **${func}**, and cannot run.`); - }); - resolve(); +exports.run = (client, msg, cmd) => new Promise((resolve, reject) => { + cmd.conf.requiredFuncs.forEach((func) => { + if (!client.funcs.hasOwnProperty(func)) reject(`The client is missing **${func}**, and cannot run.`); }); -}; + resolve(); +}); diff --git a/inhibitors/selfBot.js b/inhibitors/selfBot.js index 5aa4ab16..f3d07184 100644 --- a/inhibitors/selfBot.js +++ b/inhibitors/selfBot.js @@ -3,16 +3,14 @@ exports.conf = { spamProtection: false, }; -exports.run = (client, msg, cmd) => { - return new Promise((resolve, reject) => { - if (client.config.selfbot) { - if (msg.author === client.user) { - resolve(); - } else { - reject(); - } - } else { +exports.run = (client, msg, cmd) => new Promise((resolve, reject) => { + if (client.config.selfbot) { + if (msg.author === client.user) { resolve(); + } else { + reject(); } - }); -}; + } else { + resolve(); + } +}); diff --git a/inhibitors/usage.js b/inhibitors/usage.js index 3a6ba63a..59d622c7 100644 --- a/inhibitors/usage.js +++ b/inhibitors/usage.js @@ -3,74 +3,72 @@ exports.conf = { spamProtection: true, }; -exports.run = (client, msg, cmd) => { - return new Promise((resolve, reject) => { - const usage = client.funcs.parseUsage(cmd.help.usage); - let prefixLength = msg.guildConf.prefix.length; - if (client.config.prefixMention.test(msg.content)) prefixLength = client.config.prefixMention.exec(msg.content)[0].length + 1; - let args = msg.content.slice(prefixLength) +exports.run = (client, msg, cmd) => new Promise((resolve, reject) => { + const usage = client.funcs.parseUsage(cmd.help.usage); + let prefixLength = msg.guildConf.prefix.length; + if (client.config.prefixMention.test(msg.content)) prefixLength = client.config.prefixMention.exec(msg.content)[0].length + 1; + let args = msg.content.slice(prefixLength) .split(" ") .slice(1) .join(" ") .split(cmd.help.usageDelim !== "" ? cmd.help.usageDelim : null); - if (args[0] === "") args = []; - let currentUsage; - let repeat = false; - if (usage.length === 0) return resolve(); + if (args[0] === "") args = []; + let currentUsage; + let repeat = false; + if (usage.length === 0) return resolve(); - (function validateArgs(i) { - if (i >= usage.length && i >= args.length) { - return resolve(args); - } else if (usage[i]) { - if (usage[i].type !== "repeat") { // Handle if args length > usage length - currentUsage = usage[i]; - } else if (usage[i].type === "repeat") { // Handle if usage ends in a repeat - currentUsage.type = "optional"; // if there are no optional args passed - repeat = true; - } - } else if (!repeat) { // Handle if usage does not end in a repeat - return resolve(args); + (function validateArgs(i) { + if (i >= usage.length && i >= args.length) { + return resolve(args); + } else if (usage[i]) { + if (usage[i].type !== "repeat") { // Handle if args length > usage length + currentUsage = usage[i]; + } else if (usage[i].type === "repeat") { // Handle if usage ends in a repeat + currentUsage.type = "optional"; // if there are no optional args passed + repeat = true; } - if (currentUsage.type === "optional" && (args[i] === undefined || args[i] === "")) { // Handle if args length < required usage length - if (usage.slice(i).some((u) => { return u.type === "required"; })) { - return reject("Missing one or more required arguments after end of input."); - } else { - return resolve(args); - } - } else if (currentUsage.type === "required" && args[i] === undefined) { - return reject(currentUsage.possibles.length === 1 ? `${currentUsage.possibles[0].name} is a required argument.` : `Missing a required option: (${currentUsage.possibles.map((p) => { return p.name; }).join(", ")})`); - } else if (currentUsage.possibles.length === 1) { - switch (currentUsage.possibles[0].type) { - case "literal": - if (args[i].toLowerCase() === currentUsage.possibles[0].name.toLowerCase()) { - args[i] = args[i].toLowerCase(); - validateArgs(++i); - } else if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`Your option did not litterally match the only possibility: (${currentUsage.possibles.map((p) => { return p.name; }).join(", ")})\nThis is likely caused by a mistake in the usage string.`); - } - break; - case "msg": - case "message": - if (/^\d+$/.test(args[i])) { - if (client.config.selfbot) { - msg.channel.fetchMessages({ - around: args[i], - }).then((m) => { - args[i] = m.filter(e => e.id === args[i]).first(); + } else if (!repeat) { // Handle if usage does not end in a repeat + return resolve(args); + } + if (currentUsage.type === "optional" && (args[i] === undefined || args[i] === "")) { // Handle if args length < required usage length + if (usage.slice(i).some(u => u.type === "required")) { + return reject("Missing one or more required arguments after end of input."); + } + return resolve(args); + } else if (currentUsage.type === "required" && args[i] === undefined) { + return reject(currentUsage.possibles.length === 1 ? `${currentUsage.possibles[0].name} is a required argument.` : `Missing a required option: (${currentUsage.possibles.map(p => p.name).join(", ")})`); + } else if (currentUsage.possibles.length === 1) { + switch (currentUsage.possibles[0].type) { + case "literal": + if (args[i].toLowerCase() === currentUsage.possibles[0].name.toLowerCase()) { + args[i] = args[i].toLowerCase(); + validateArgs(++i); + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`Your option did not litterally match the only possibility: (${currentUsage.possibles.map(p => p.name).join(", ")})\nThis is likely caused by a mistake in the usage string.`); + } + break; + case "msg": + case "message": + if (/^\d+$/.test(args[i])) { + if (client.config.selfbot) { + msg.channel.fetchMessages({ + around: args[i], + }).then((m) => { + args[i] = m.filter(e => e.id === args[i]).first(); + validateArgs(++i); + }).catch(() => { + if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); validateArgs(++i); - }).catch(() => { - if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be a valid message id.`); - } - }); - } else { - msg.channel.fetchMessage(args[i]) + } else { + return reject(`${currentUsage.possibles[0].name} must be a valid message id.`); + } + }); + } else { + msg.channel.fetchMessage(args[i]) .then((m) => { args[i] = m; validateArgs(++i); @@ -83,287 +81,287 @@ exports.run = (client, msg, cmd) => { return reject(`${currentUsage.possibles[0].name} must be a valid message id.`); } }); - } - } else if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be a valid message id.`); } - break; - case "user": - case "mention": - if (/^<@!?\d+>$/.test(args[i]) && client.users.has(/\d+/.exec(args[i])[0]) && args[i].length > 5) { - args[i] = client.users.get(/\d+/.exec(args[i])[0]); - validateArgs(++i); - } else if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be a valid message id.`); + } + break; + case "user": + case "mention": + if (/^<@!?\d+>$/.test(args[i]) && client.users.has(/\d+/.exec(args[i])[0]) && args[i].length > 5) { + args[i] = client.users.get(/\d+/.exec(args[i])[0]); + validateArgs(++i); + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); + } + break; + case "boolean": + if (/^true|false$/.test(args[i])) { + if (args[i] === "true") { + args[i] = true; } else { - return reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); + args[i] = false; + validateArgs(++i); } - break; - case "boolean": - if (/^true|false$/.test(args[i])) { - if (args[i] === "true") { - args[i] = true; - } else { - args[i] = false; + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be true or false.`); + } + break; + case "member": + if (/^<@!?\d+>$/.test(args[i]) && msg.guild.members.has(/\d+/.exec(args[i])[0]) && args[i].length > 5) { + args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); + validateArgs(++i); + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); + } + break; + case "channel": + if (/^<#\d+>$/.test(args[i]) || client.channels.has(args[i])) { + args[i] = client.channels.get(/\d+/.exec(args[i])[0]); + validateArgs(++i); + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be a channel tag or valid channel id.`); + } + break; + case "guild": + if (client.guilds.has(args[i])) { + args[i] = client.guilds.get(/\d+/.exec(args[i])[0]); + validateArgs(++i); + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be a valid guild id.`); + } + break; + case "role": + if (/^<@&\d+>$/.test(args[i]) || msg.guild.roles.has(args[i])) { + args[i] = msg.guild.roles.get(/\d+/.exec(args[i])[0]); + validateArgs(++i); + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be a role mention or role id.`); + } + break; + case "str": + case "string": + if (currentUsage.possibles[0].min && currentUsage.possibles[0].max) { + if (args[i].length < currentUsage.possibles[0].min || args[i].length > currentUsage.possibles[0].max) { + if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); validateArgs(++i); + } else if (currentUsage.possibles[0].min === currentUsage.possibles[0].max) { + return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min} characters.`); + } else { + return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max} characters.`); } - } else if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); } else { - return reject(`${currentUsage.possibles[0].name} must be true or false.`); - } - break; - case "member": - if (/^<@!?\d+>$/.test(args[i]) && msg.guild.members.has(/\d+/.exec(args[i])[0]) && args[i].length > 5) { - args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); validateArgs(++i); - } else if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be a mention or valid user id.`); } - break; - case "channel": - if (/^<#\d+>$/.test(args[i]) || client.channels.has(args[i])) { - args[i] = client.channels.get(/\d+/.exec(args[i])[0]); - validateArgs(++i); - } else if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); + } else if (currentUsage.possibles[0].min) { + if (args[i].length < currentUsage.possibles[0].min) { + if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be longer than ${currentUsage.possibles[0].min} characters.`); + } } else { - return reject(`${currentUsage.possibles[0].name} must be a channel tag or valid channel id.`); - } - break; - case "guild": - if (client.guilds.has(args[i])) { - args[i] = client.guilds.get(/\d+/.exec(args[i])[0]); validateArgs(++i); - } else if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be a valid guild id.`); } - break; - case "role": - if (/^<@&\d+>$/.test(args[i]) || msg.guild.roles.has(args[i])) { - args[i] = msg.guild.roles.get(/\d+/.exec(args[i])[0]); + } else if (currentUsage.possibles[0].max) { + if (args[i].length > currentUsage.possibles[0].max) { + if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be shorter than ${currentUsage.possibles[0].max} characters.`); + } + } else { validateArgs(++i); - } else if (currentUsage.type === "optional" && !repeat) { + } + } else { + validateArgs(++i); + } + break; + case "int": + case "integer": + if (!Number.isInteger(parseInt(args[i]))) { + if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); } else { - return reject(`${currentUsage.possibles[0].name} must be a role mention or role id.`); + return reject(`${currentUsage.possibles[0].name} must be an integer.`); } - break; - case "str": - case "string": - if (currentUsage.possibles[0].min && currentUsage.possibles[0].max) { - if (args[i].length < currentUsage.possibles[0].min || args[i].length > currentUsage.possibles[0].max) { + } else if (currentUsage.possibles[0].min && currentUsage.possibles[0].max) { + args[i] = parseInt(args[i]); + if (args[i] < currentUsage.possibles[0].min || args[i] > currentUsage.possibles[0].max) { + if (currentUsage.possibles[0].min === currentUsage.possibles[0].max) { if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); - } else if (currentUsage.possibles[0].min === currentUsage.possibles[0].max) { - return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min} characters.`); } else { - return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max} characters.`); + return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min}\nSo why didn't the dev use a literal?`); } - } else { - validateArgs(++i); - } - } else if (currentUsage.possibles[0].min) { - if (args[i].length < currentUsage.possibles[0].min) { - if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be longer than ${currentUsage.possibles[0].min} characters.`); - } - } else { + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); validateArgs(++i); - } - } else if (currentUsage.possibles[0].max) { - if (args[i].length > currentUsage.possibles[0].max) { - if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be shorter than ${currentUsage.possibles[0].max} characters.`); - } } else { - validateArgs(++i); + return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); } } else { validateArgs(++i); } - break; - case "int": - case "integer": - if (!Number.isInteger(parseInt(args[i]))) { + } else if (currentUsage.possibles[0].min) { + args[i] = parseInt(args[i]); + if (args[i] < currentUsage.possibles[0].min) { if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); } else { - return reject(`${currentUsage.possibles[0].name} must be an integer.`); + return reject(`${currentUsage.possibles[0].name} must be greater than ${currentUsage.possibles[0].min}.`); } - } else if (currentUsage.possibles[0].min && currentUsage.possibles[0].max) { - args[i] = parseInt(args[i]); - if (args[i] < currentUsage.possibles[0].min || args[i] > currentUsage.possibles[0].max) { - if (currentUsage.possibles[0].min === currentUsage.possibles[0].max) { - if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min}\nSo why didn't the dev use a literal?`); - } - } else if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); - } - } else { + } else { + validateArgs(++i); + } + } else if (currentUsage.possibles[0].max) { + args[i] = parseInt(args[i]); + if (args[i] > currentUsage.possibles[0].max) { + if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); validateArgs(++i); - } - } else if (currentUsage.possibles[0].min) { - args[i] = parseInt(args[i]); - if (args[i] < currentUsage.possibles[0].min) { - if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be greater than ${currentUsage.possibles[0].min}.`); - } } else { - validateArgs(++i); + return reject(`${currentUsage.possibles[0].name} must be less than ${currentUsage.possibles[0].max}.`); } - } else if (currentUsage.possibles[0].max) { - args[i] = parseInt(args[i]); - if (args[i] > currentUsage.possibles[0].max) { + } else { + validateArgs(++i); + } + } else { + args[i] = parseInt(args[i]); + validateArgs(++i); + } + break; + case "num": + case "number": + case "float": + if (parseFloat(args[i]) === "NaN") { + if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be a valid number.`); + } + } else if (currentUsage.possibles[0].min && currentUsage.possibles[0].max) { + args[i] = parseFloat(args[i]); + if (args[i] < currentUsage.possibles[0].min || args[i] > currentUsage.possibles[0].max) { + if (currentUsage.possibles[0].min === currentUsage.possibles[0].max) { if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); } else { - return reject(`${currentUsage.possibles[0].name} must be less than ${currentUsage.possibles[0].max}.`); + return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min}\nSo why didn't the dev use a literal?`); } - } else { + } else if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); validateArgs(++i); + } else { + return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); } } else { - args[i] = parseInt(args[i]); validateArgs(++i); } - break; - case "num": - case "number": - case "float": - if (parseFloat(args[i]) === "NaN") { + } else if (currentUsage.possibles[0].min) { + args[i] = parseFloat(args[i]); + if (args[i] < currentUsage.possibles[0].min) { if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); } else { - return reject(`${currentUsage.possibles[0].name} must be a valid number.`); - } - } else if (currentUsage.possibles[0].min && currentUsage.possibles[0].max) { - args[i] = parseFloat(args[i]); - if (args[i] < currentUsage.possibles[0].min || args[i] > currentUsage.possibles[0].max) { - if (currentUsage.possibles[0].min === currentUsage.possibles[0].max) { - if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be exactly ${currentUsage.possibles[0].min}\nSo why didn't the dev use a literal?`); - } - } else if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be between ${currentUsage.possibles[0].min} and ${currentUsage.possibles[0].max}.`); - } - } else { - validateArgs(++i); - } - } else if (currentUsage.possibles[0].min) { - args[i] = parseFloat(args[i]); - if (args[i] < currentUsage.possibles[0].min) { - if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be greater than ${currentUsage.possibles[0].min}.`); - } - } else { - validateArgs(++i); - } - } else if (currentUsage.possibles[0].max) { - args[i] = parseFloat(args[i]); - if (args[i] > currentUsage.possibles[0].max) { - if (currentUsage.type === "optional" && !repeat) { - args.splice(i, 0, undefined); - validateArgs(++i); - } else { - return reject(`${currentUsage.possibles[0].name} must be less than ${currentUsage.possibles[0].max}.`); - } - } else { - validateArgs(++i); + return reject(`${currentUsage.possibles[0].name} must be greater than ${currentUsage.possibles[0].min}.`); } } else { - args[i] = parseFloat(args[i]); validateArgs(++i); } - break; - case "url": - if (!/^((https?|ftps?|sftp):\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|(([a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])*\.[a-zA-Z]{2,}))(:\b([0-9]|[1-8][0-9]|9[0-9]|[1-8][0-9]{2}|9[0-8][0-9]|99[0-9]|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])\b)?(\/([a-zA-Z0-9:#[\]@!$&'()*+,;=%-._~]+)?)?$/.test(args[i])) { + } else if (currentUsage.possibles[0].max) { + args[i] = parseFloat(args[i]); + if (args[i] > currentUsage.possibles[0].max) { if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); } else { - return reject(`${currentUsage.possibles[0].name} must be a valid url.`); + return reject(`${currentUsage.possibles[0].name} must be less than ${currentUsage.possibles[0].max}.`); } } else { validateArgs(++i); } - break; - default: - console.warn("Unknown Argument Type encountered"); + } else { + args[i] = parseFloat(args[i]); validateArgs(++i); - break; - } - } else { - let validated = false; - (function multiPossibles(p) { - if (validated) { - validateArgs(++i); - return; - } else if (p >= currentUsage.possibles.length) { + } + break; + case "url": + if (!/^((https?|ftps?|sftp):\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|(([a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])*\.[a-zA-Z]{2,}))(:\b([0-9]|[1-8][0-9]|9[0-9]|[1-8][0-9]{2}|9[0-8][0-9]|99[0-9]|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])\b)?(\/([a-zA-Z0-9:#[\]@!$&'()*+,;=%-._~]+)?)?$/.test(args[i])) { if (currentUsage.type === "optional" && !repeat) { args.splice(i, 0, undefined); validateArgs(++i); } else { - return reject(`Your option didn't match any of the possibilities: (${currentUsage.possibles.map((p) => { return p.name; }).join(", ")})`); + return reject(`${currentUsage.possibles[0].name} must be a valid url.`); } - return; + } else { + validateArgs(++i); } - switch (currentUsage.possibles[p].type) { - case "literal": - if (args[i].toLowerCase() === currentUsage.possibles[p].name.toLowerCase()) { - args[i] = args[i].toLowerCase(); - validated = true; - multiPossibles(++p); - } else { - multiPossibles(++p); - } - break; - case "msg": - case "message": - if (/^\d+$/.test(args[i])) { - msg.channel.fetchMessage(args[i]) + break; + default: + console.warn("Unknown Argument Type encountered"); + validateArgs(++i); + break; + } + } else { + let validated = false; + (function multiPossibles(p) { + if (validated) { + validateArgs(++i); + return; + } else if (p >= currentUsage.possibles.length) { + if (currentUsage.type === "optional" && !repeat) { + args.splice(i, 0, undefined); + validateArgs(++i); + } else { + return reject(`Your option didn't match any of the possibilities: (${currentUsage.possibles.map(p => p.name).join(", ")})`); + } + return; + } + switch (currentUsage.possibles[p].type) { + case "literal": + if (args[i].toLowerCase() === currentUsage.possibles[p].name.toLowerCase()) { + args[i] = args[i].toLowerCase(); + validated = true; + multiPossibles(++p); + } else { + multiPossibles(++p); + } + break; + case "msg": + case "message": + if (/^\d+$/.test(args[i])) { + msg.channel.fetchMessage(args[i]) .then((m) => { args[i] = m; validated = true; @@ -372,88 +370,118 @@ exports.run = (client, msg, cmd) => { .catch(() => { multiPossibles(++p); }); - } else { - multiPossibles(++p); - } - break; - case "user": - case "mention": { - const result = /\d+/.exec(args[i]); - if (result && args[i].length > 5 && client.users.has(result[0])) { - args[i] = client.users.get(/\d+/.exec(args[i])[0]); - validated = true; - multiPossibles(++p); - } else { - multiPossibles(++p); - } - break; + } else { + multiPossibles(++p); } - case "boolean": - if (/^true|false$/.test(args[i])) { - if (args[i] === "true") args[i] = true; - else args[i] = false; - validated = true; - multiPossibles(++p); - } else { - multiPossibles(++p); - } - break; - case "member": { - const result = /\d+/.exec(args[i]); - if (result && args[i].length > 5 && msg.guild.members.has(result[0])) { - args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); - validated = true; - multiPossibles(++p); - } else { - multiPossibles(++p); - } - break; + break; + case "user": + case "mention": { + const result = /\d+/.exec(args[i]); + if (result && args[i].length > 5 && client.users.has(result[0])) { + args[i] = client.users.get(/\d+/.exec(args[i])[0]); + validated = true; + multiPossibles(++p); + } else { + multiPossibles(++p); + } + break; + } + case "boolean": + if (/^true|false$/.test(args[i])) { + if (args[i] === "true") args[i] = true; + else args[i] = false; + validated = true; + multiPossibles(++p); + } else { + multiPossibles(++p); + } + break; + case "member": { + const result = /\d+/.exec(args[i]); + if (result && args[i].length > 5 && msg.guild.members.has(result[0])) { + args[i] = msg.guild.members.get(/\d+/.exec(args[i])[0]); + validated = true; + multiPossibles(++p); + } else { + multiPossibles(++p); } - case "channel": - if (/^<#\d+>$/.test(args[i]) || client.channels.has(args[i])) { - args[i] = client.channels.get(/\d+/.exec(args[i])[0]); + break; + } + case "channel": + if (/^<#\d+>$/.test(args[i]) || client.channels.has(args[i])) { + args[i] = client.channels.get(/\d+/.exec(args[i])[0]); + validated = true; + multiPossibles(++p); + } else { + multiPossibles(++p); + } + break; + case "guild": + if (client.guilds.has(args[i])) { + args[i] = client.guilds.get(/\d+/.exec(args[i])[0]); + validated = true; + multiPossibles(++p); + } else { + multiPossibles(++p); + } + break; + case "role": + if (/^<@&\d+>$/.test(args[i]) || msg.guild.roles.has(args[i])) { + args[i] = msg.guild.roles.get(/\d+/.exec(args[i])[0]); + validated = true; + multiPossibles(++p); + } else { + multiPossibles(++p); + } + break; + case "str": + case "string": + if (currentUsage.possibles[p].min && currentUsage.possibles[p].max) { + if (args[i].length <= currentUsage.possibles[p].max && args[i].length >= currentUsage.possibles[p].min) { validated = true; multiPossibles(++p); } else { multiPossibles(++p); } - break; - case "guild": - if (client.guilds.has(args[i])) { - args[i] = client.guilds.get(/\d+/.exec(args[i])[0]); + } else if (currentUsage.possibles[p].min) { + if (args[i].length >= currentUsage.possibles[p].min) { validated = true; multiPossibles(++p); } else { multiPossibles(++p); } - break; - case "role": - if (/^<@&\d+>$/.test(args[i]) || msg.guild.roles.has(args[i])) { - args[i] = msg.guild.roles.get(/\d+/.exec(args[i])[0]); + } else if (currentUsage.possibles[p].max) { + if (args[i].length <= currentUsage.possibles[p].max) { validated = true; multiPossibles(++p); } else { multiPossibles(++p); } - break; - case "str": - case "string": + } else { + validated = true; + multiPossibles(++p); + } + break; + case "int": + case "integer": + if (Number.isInteger(parseInt(args[i]))) { + args[i] = parseInt(args[i]); if (currentUsage.possibles[p].min && currentUsage.possibles[p].max) { - if (args[i].length <= currentUsage.possibles[p].max && args[i].length >= currentUsage.possibles[p].min) { + if (args[i] <= currentUsage.possibles[p].max && args[i] >= currentUsage.possibles[p].min) { validated = true; multiPossibles(++p); } else { multiPossibles(++p); } } else if (currentUsage.possibles[p].min) { - if (args[i].length >= currentUsage.possibles[p].min) { + if (args[i] >= currentUsage.possibles[p].min) { validated = true; multiPossibles(++p); } else { multiPossibles(++p); } } else if (currentUsage.possibles[p].max) { - if (args[i].length <= currentUsage.possibles[p].max) { + if (args[i] <= currentUsage.possibles[p].max) { validated = true; multiPossibles(++p); } else { @@ -463,89 +491,58 @@ exports.run = (client, msg, cmd) => { validated = true; multiPossibles(++p); } - break; - case "int": - case "integer": - if (Number.isInteger(parseInt(args[i]))) { - args[i] = parseInt(args[i]); - if (currentUsage.possibles[p].min && currentUsage.possibles[p].max) { - if (args[i] <= currentUsage.possibles[p].max && args[i] >= currentUsage.possibles[p].min) { - validated = true; - multiPossibles(++p); - } else { - multiPossibles(++p); - } - } else if (currentUsage.possibles[p].min) { - if (args[i] >= currentUsage.possibles[p].min) { - validated = true; - multiPossibles(++p); - } else { - multiPossibles(++p); - } - } else if (currentUsage.possibles[p].max) { - if (args[i] <= currentUsage.possibles[p].max) { - validated = true; - multiPossibles(++p); - } else { - multiPossibles(++p); - } - } else { + } else { + multiPossibles(++p); + } + break; + case "num": + case "number": + case "float": + if (parseFloat(args[i]) !== "NaN") { + args[i] = parseFloat(args[i]); + if (currentUsage.possibles[p].min && currentUsage.possibles[p].max) { + if (args[i] <= currentUsage.possibles[p].max && args[i] >= currentUsage.possibles[p].min) { validated = true; multiPossibles(++p); + } else { + multiPossibles(++p); } - } else { - multiPossibles(++p); - } - break; - case "num": - case "number": - case "float": - if (parseFloat(args[i]) !== "NaN") { - args[i] = parseFloat(args[i]); - if (currentUsage.possibles[p].min && currentUsage.possibles[p].max) { - if (args[i] <= currentUsage.possibles[p].max && args[i] >= currentUsage.possibles[p].min) { - validated = true; - multiPossibles(++p); - } else { - multiPossibles(++p); - } - } else if (currentUsage.possibles[p].min) { - if (args[i] >= currentUsage.possibles[p].min) { - validated = true; - multiPossibles(++p); - } else { - multiPossibles(++p); - } - } else if (currentUsage.possibles[p].max) { - if (args[i] <= currentUsage.possibles[p].max) { - validated = true; - multiPossibles(++p); - } else { - multiPossibles(++p); - } + } else if (currentUsage.possibles[p].min) { + if (args[i] >= currentUsage.possibles[p].min) { + validated = true; + multiPossibles(++p); } else { + multiPossibles(++p); + } + } else if (currentUsage.possibles[p].max) { + if (args[i] <= currentUsage.possibles[p].max) { validated = true; multiPossibles(++p); + } else { + multiPossibles(++p); } } else { - multiPossibles(++p); - } - break; - case "url": - if (/^((https?|ftps?|sftp):\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|(([a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])*\.[a-zA-Z]{2,}))(:\b([0-9]|[1-8][0-9]|9[0-9]|[1-8][0-9]{2}|9[0-8][0-9]|99[0-9]|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])\b)?(\/([a-zA-Z0-9:#[\]@!$&'()*+,;=%-._~]+)?)?$/.test(args[i])) { validated = true; multiPossibles(++p); - } else { - multiPossibles(++p); } - break; - default: - console.warn("Unknown Argument Type encountered"); + } else { multiPossibles(++p); - break; - } - })(0); - } - })(0); - }); -}; + } + break; + case "url": + if (/^((https?|ftps?|sftp):\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|(([a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(\.[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])*\.[a-zA-Z]{2,}))(:\b([0-9]|[1-8][0-9]|9[0-9]|[1-8][0-9]{2}|9[0-8][0-9]|99[0-9]|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])\b)?(\/([a-zA-Z0-9:#[\]@!$&'()*+,;=%-._~]+)?)?$/.test(args[i])) { + validated = true; + multiPossibles(++p); + } else { + multiPossibles(++p); + } + break; + default: + console.warn("Unknown Argument Type encountered"); + multiPossibles(++p); + break; + } + }(0)); + } + }(0)); +}); From de822344b4d2a86fea2f18105c96d7a5866f24a0 Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Sat, 19 Nov 2016 22:29:13 +1100 Subject: [PATCH 37/51] Fucked up? --- commands/System/stats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/System/stats.js b/commands/System/stats.js index 5eda75ec..9fb32c6c 100644 --- a/commands/System/stats.js +++ b/commands/System/stats.js @@ -1,6 +1,6 @@ const Discord = require("discord.js"); const moment = require("moment"); - const komada = require("../package.json"); + const komada = require("../../package.json"); require("moment-duration-format"); exports.run = (client, msg) => { From d5c9885e98b4af3904c6afddc52ff1491794847d Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Sat, 19 Nov 2016 22:31:09 +1100 Subject: [PATCH 38/51] Semver Patch --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b088251b..9b479b32 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "komada", - "version": "0.8.7", + "version": "0.8.8", "author": "Evelyne Lachance", "description": "Komada: Croatian for 'pieces', is a modular bot system including reloading modules and easy to use custom commands.", "main": "app.js", From c31f6649604459280d304fb2436fde360be3510a Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Sat, 19 Nov 2016 23:06:22 +1100 Subject: [PATCH 39/51] Fixes --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index e5de3992..0f667471 100644 --- a/app.js +++ b/app.js @@ -18,7 +18,7 @@ exports.start = (config) => { client.dataProviders = new Discord.Collection(); client.coreBaseDir = `${__dirname}/`; - client.clientBaseDir = `${__dirname}/`; + client.clientBaseDir = `${process.cwd()}/`; // Load core functions, then everything else require("./functions/loadFunctions.js")(client).then(() => { From 4ca7374da8f83e027572395b84f1bdd175793c8c Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Sat, 19 Nov 2016 23:06:56 +1100 Subject: [PATCH 40/51] Bumped --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9b479b32..fbb7150c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "komada", - "version": "0.8.8", + "version": "0.8.9", "author": "Evelyne Lachance", "description": "Komada: Croatian for 'pieces', is a modular bot system including reloading modules and easy to use custom commands.", "main": "app.js", From b396018f7a3fbecbf44f4102c1be7e72c03194be Mon Sep 17 00:00:00 2001 From: Faith Date: Sat, 19 Nov 2016 18:40:50 -0500 Subject: [PATCH 41/51] Monitors addition (#71) * Monitors Loading && Monitors Running * Message Event ignores bot messages and runs monitors * Profanity- 1st Monitor Example * Ignores Bots, Outputs Error Stacks into console * Semver minor bump Monitors * removal of max-len from linter * oops. I mean semver patch --- .eslintrc.json | 3 +- app.js | 7 +++- functions/loadCommandMonitors.js | 58 ++++++++++++++++++++++++++++++++ functions/runCommandMonitors.js | 16 +++++++++ monitors/profanity.js | 19 +++++++++++ package.json | 2 +- 6 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 functions/loadCommandMonitors.js create mode 100644 functions/runCommandMonitors.js create mode 100644 monitors/profanity.js diff --git a/.eslintrc.json b/.eslintrc.json index 3994e101..82fcba44 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -22,6 +22,7 @@ "guard-for-in": "warn", "consistent-return": ["warn", { "treatUndefinedAsUnspecified": true }], "no-use-before-define": ["warn", { "functions": true, "classes": true }], - "no-eval": "warn" + "no-eval": "warn", + "max-len": "off" } } diff --git a/app.js b/app.js index 0f667471..fe315acf 100644 --- a/app.js +++ b/app.js @@ -15,6 +15,7 @@ exports.start = (config) => { client.commands = new Discord.Collection(); client.aliases = new Discord.Collection(); client.commandInhibitors = new Discord.Collection(); + client.commandMonitors = new Discord.Collection(); client.dataProviders = new Discord.Collection(); client.coreBaseDir = `${__dirname}/`; @@ -25,6 +26,7 @@ exports.start = (config) => { client.funcs.loadDataProviders(client); client.funcs.loadCommands(client); client.funcs.loadCommandInhibitors(client); + client.funcs.loadCommandMonitors(client); client.funcs.loadEvents(client); }); @@ -42,8 +44,10 @@ exports.start = (config) => { }); client.on("message", (msg) => { + if (msg.author.bot) return; const conf = client.funcs.confs.get(msg.guild); msg.guildConf = conf; + client.funcs.runCommandMonitors(client, msg).catch(reason => msg.channel.sendMessage(reason).catch(console.error)); if (!msg.content.startsWith(conf.prefix) && !client.config.prefixMention.test(msg.content)) return; let prefixLength = conf.prefix.length; if (client.config.prefixMention.test(msg.content)) prefixLength = client.config.prefixMention.exec(msg.content)[0].length + 1; @@ -74,7 +78,8 @@ exports.start = (config) => { }) .catch((reason) => { if (reason) { - msg.channel.sendMessage(reason).catch(console.error); + client.funcs.log(reason.stack, 'error'); + msg.channel.sendCode(reason).catch(console.error); } }); }); diff --git a/functions/loadCommandMonitors.js b/functions/loadCommandMonitors.js new file mode 100644 index 00000000..34459da0 --- /dev/null +++ b/functions/loadCommandMonitors.js @@ -0,0 +1,58 @@ +const fs = require("fs-extra"); +const path = require("path"); + +module.exports = (client) => { + client.commandMonitors.clear(); + const counts = [0, 0]; + loadCommandMonitors(client, client.coreBaseDir, counts).then((counts) => { + loadCommandMonitors(client, client.clientBaseDir, counts).then((counts) => { + const [p, o] = counts; + client.funcs.log(`Loaded ${p} command monitors, with ${o} optional.`); + }); + }); +}; + +const loadCommandMonitors = (client, baseDir, counts) => { + return new Promise((resolve, reject) => { + const dir = path.resolve(`${baseDir}./monitors/`); + fs.ensureDir(dir, (err) => { + if (err) console.error(err); + fs.readdir(dir, (err, files) => { + if (err) console.error(err); + let [p, o] = counts; + try { + files = files.filter((f) => { return f.slice(-3) === ".js"; }); + files.forEach((f) => { + const file = f.split("."); + let props; + if (file[1] !== "opt") { + props = require(`${dir}/${f}`); + client.commandMonitors.set(file[0], props); + p++; + } else if (client.config.commandMonitors.includes(file[0])) { + props = require(`${dir}/${f}`); + client.commandMonitors.set(file[0], props); + o++; + } + }); + } catch (e) { + if (e.code === "MODULE_NOT_FOUND") { + const module = /'[^']+'/g.exec(e.toString()); + client.funcs.installNPM(module[0].slice(1, -1)) + .then(() => { + client.funcs.loadCommandMonitors(client); + }) + .catch((e) => { + console.error(e); + process.exit(); + }); + } else { + console.error(e); + } + reject(); + } + resolve([p, o]); + }); + }); + }); +}; diff --git a/functions/runCommandMonitors.js b/functions/runCommandMonitors.js new file mode 100644 index 00000000..5c895b97 --- /dev/null +++ b/functions/runCommandMonitors.js @@ -0,0 +1,16 @@ +module.exports = (client, msg) => { + return new Promise((resolve, reject) => { + const mps = [true]; + client.commandMonitors.forEach((mProc) => { + if (mProc.conf.enabled) { + mps.push(mProc.run(client, msg)); + } + }); + Promise.all(mps) + .then((value) => { + resolve(value); + }, (reason) => { + reject(reason); + }); + }); +}; diff --git a/monitors/profanity.js b/monitors/profanity.js new file mode 100644 index 00000000..ee8d7c6f --- /dev/null +++ b/monitors/profanity.js @@ -0,0 +1,19 @@ +const profanityFinder = require("profanity-finder"); + +const findProfanity = profanityFinder.findprofanity; + +exports.conf = { + enabled: false, +}; + +exports.run = (client, msg) => { + return new Promise((resolve, reject) => { + const bool = findProfanity(msg.content); + if (bool) { + msg.delete(); + reject("You're not allowed to use profanity in your messages!"); + } else { + resolve(); + } + }); +}; diff --git a/package.json b/package.json index fbb7150c..ef094116 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "komada", - "version": "0.8.9", + "version": "0.8.10", "author": "Evelyne Lachance", "description": "Komada: Croatian for 'pieces', is a modular bot system including reloading modules and easy to use custom commands.", "main": "app.js", From d01be704203cdda068feb5aa8da5225bc92dcaed Mon Sep 17 00:00:00 2001 From: Faith Date: Sat, 19 Nov 2016 21:08:59 -0500 Subject: [PATCH 42/51] Better Support for Arrays/Ints/Booleans/Strings --- commands/System/conf.js | 18 ++++++---- functions/confs.js | 80 +++++++++++++++++++++++++++++++++-------- 2 files changed, 78 insertions(+), 20 deletions(-) diff --git a/commands/System/conf.js b/commands/System/conf.js index bfe25748..233232d8 100644 --- a/commands/System/conf.js +++ b/commands/System/conf.js @@ -11,14 +11,20 @@ exports.run = (client, msg, [action, key, ...value]) => { } else if (action === "set") { - if (!key || value === undefined) return msg.reply("Please provide both a key and value!"); - if (msg.guildConf[key].constructor.name === "String") { - value = value.join(" "); - } else - if (msg.guildConf[key].constructor.name === "Boolean") { - value = value[0]; + if (!key || value[0] === undefined) return msg.reply("Please provide both a key and value!"); + const type = value[0].constructor.name; + if (["TextChannel", "GuildChannel", "Message", "User", "GuildMember", "Guild", "Role", "VoiceChannel", "Emoji", "Invite"].includes(type)) { + value = value[0].id; + } else { + value = value.join(" ").toString(); } client.funcs.confs.set(msg.guild, key, value); + if (msg.guildConf[key].constructor.name === "Array") { + if (msg.guildConf[key].includes(value)) { + return msg.reply(`The value ${value} for ${key} has been added.`); + } + return msg.reply(`The value ${value} for ${key} has been removed.`); + } return msg.reply(`The value for ${key} has been set to: ${value}`); } else diff --git a/functions/confs.js b/functions/confs.js index 55c7de8a..9067f145 100644 --- a/functions/confs.js +++ b/functions/confs.js @@ -84,11 +84,39 @@ exports.setKey = (key, defaultValue) => { if (!(key in defaultConf)) { throw new Error(`:x: The key \`${key}\` does not seem to be present in the default configuration.`); } - if (defaultValue.constructor.name !== defaultConf[key].type) { - throw new Error(`:x: The key \`${key}\` does not correspond to the type: ${defaultConf[key].type}.`); + switch (defaultConf[key].type) { + case "Array": { + const dataArray = []; + if (defaultConf[key]) { + dataArray.splice(dataArray.indexOf(defaultValue), 1); + defaultValue = dataArray; + } else { + dataArray.push(defaultValue); + defaultValue = dataArray; + } + break; + } + case "Boolean": + if (defaultValue === "true") { + defaultValue = true; + } else if (defaultValue === "false") { + defaultValue = false; + } else { + throw new Error(`:x: The value ${defaultValue} does not correspond to the type boolean.`); + } + break; + case "Integer": + defaultValue = parseInt(defaultValue); + if (isNaN(defaultValue)) { + throw new Error(`:x: The value ${defaultValue} does not correspond to the type integer.`); + } + break; + default: + defaultValue = defaultValue.toString(); } defaultConf[key].data = defaultValue; fs.outputJSONSync(path.resolve(`${dataDir}${path.sep}${defaultFile}`), defaultConf); + return defaultConf; }; exports.resetKey = (guild, key) => { @@ -103,16 +131,17 @@ exports.resetKey = (guild, key) => { if (Object.keys(thisConf).length > 0) { guildConfs.set(guild.id, thisConf); fs.outputJSONSync(path.resolve(`${dataDir}${path.sep}${guild.id}.json`), thisConf); - } else { - fs.unlinkSync(path.resolve(`${dataDir}${path.sep}${guild.id}.json`)); + return thisConf; } + fs.unlinkSync(path.resolve(`${dataDir}${path.sep}${guild.id}.json`)); + return `Deleted empty configuration file for ${guild.name}`; }; exports.delKey = (key, delFromAll) => { if (!(key in defaultConf)) { throw new Error(`:x: The key \`${key}\` does not seem to be present in the default configuration.`); } - if (["mod_role", "admin_role", "disabledCommands", "prefix"].includes(key)) { + if (["modRole", "adminRole", "disabledCommands", "prefix"].includes(key)) { throw new Error(`:x: The key \`${key}\` is core and cannot be deleted.`); } delete defaultConf[key]; @@ -123,9 +152,10 @@ exports.delKey = (key, delFromAll) => { delete conf[key]; if (Object.keys(conf).length > 0) { fs.outputJSONSync(path.resolve(`${dataDir}${path.sep}${MapIter.next().value}.json`), conf); - } else { - fs.unlinkSync(path.resolve(`${dataDir}${path.sep}${MapIter.next().value}.json`)); + return true; } + fs.unlinkSync(path.resolve(`${dataDir}${path.sep}${MapIter.next().value}.json`)); + return "Deleted Empty Configuration Files"; }); } }; @@ -142,13 +172,35 @@ exports.set = (guild, key, value) => { throw new Error(`:x: The key \`${key}\` is not valid according to the Default Configuration.`); } - if (value.constructor.name !== defaultConf[key].type) { - throw new Error(`:x: The key \`${key}\` does not correspond to the type: ${defaultConf[key].type}.`); - } - - const type = value.constructor.name; - if (["TextChannel", "GuildChannel", "Message", "User", "GuildMember", "Guild", "Role", "VoiceChannel", "Emoji", "Invite"].includes(type)) { - value = value.id; + switch (defaultConf[key].type) { + case "Array": { + const dataArray = []; + if (thisConf[key]) { + dataArray.splice(dataArray.indexOf(value), 1); + value = dataArray; + } else { + dataArray.push(value); + value = dataArray; + } + break; + } + case "Boolean": + if (value === "true") { + value = true; + } else if (value === "false") { + value = false; + } else { + throw new Error(`:x: The value ${value} does not correspond to the Boolean type.`); + } + break; + case "Integer": + value = parseInt(value); + if (isNaN(value)) { + throw new Error(`:x: The value ${value} does not correspond to the Integer type.`); + } + break; + default: + value = value.toString(); } thisConf[key] = { data: value, type: defaultConf[key].type }; From 228314e8245ba5d99c1638ae865fd10a96d22011 Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Sun, 20 Nov 2016 13:50:47 +1100 Subject: [PATCH 43/51] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ef094116..7c34ab41 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "komada", - "version": "0.8.10", + "version": "0.9.0", "author": "Evelyne Lachance", "description": "Komada: Croatian for 'pieces', is a modular bot system including reloading modules and easy to use custom commands.", "main": "app.js", From 66849b73f4068c344a4e2174e79c5f3437ae5770 Mon Sep 17 00:00:00 2001 From: Faith Date: Sat, 19 Nov 2016 23:23:20 -0500 Subject: [PATCH 44/51] Monitors/Inhibitors Uncaught Exception fix --- functions/loadCommandInhibitors.js | 3 +-- functions/loadCommandMonitors.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/functions/loadCommandInhibitors.js b/functions/loadCommandInhibitors.js index a79bbcd3..d94cb938 100644 --- a/functions/loadCommandInhibitors.js +++ b/functions/loadCommandInhibitors.js @@ -46,9 +46,8 @@ const loadCommandInhibitors = (client, baseDir, counts) => new Promise((resolve, process.exit(); }); } else { - console.error(e); + reject(e); } - reject(); } resolve([p, o]); }); diff --git a/functions/loadCommandMonitors.js b/functions/loadCommandMonitors.js index 34459da0..772f0717 100644 --- a/functions/loadCommandMonitors.js +++ b/functions/loadCommandMonitors.js @@ -47,9 +47,8 @@ const loadCommandMonitors = (client, baseDir, counts) => { process.exit(); }); } else { - console.error(e); + reject(e); } - reject(); } resolve([p, o]); }); From e0eebdb0bea38cd60c684744eb44cddf6a106ca3 Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Sun, 20 Nov 2016 15:33:01 +1100 Subject: [PATCH 45/51] Verison Bumps --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c34ab41..edf4001b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "komada", - "version": "0.9.0", + "version": "0.9.1", "author": "Evelyne Lachance", "description": "Komada: Croatian for 'pieces', is a modular bot system including reloading modules and easy to use custom commands.", "main": "app.js", From 62920f7ab1c612b417dac52f9cee701294a29fae Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Sun, 20 Nov 2016 18:57:04 +1100 Subject: [PATCH 46/51] Fixes Galore --- functions/confs.js | 1 + 1 file changed, 1 insertion(+) diff --git a/functions/confs.js b/functions/confs.js index 9067f145..9c7c6120 100644 --- a/functions/confs.js +++ b/functions/confs.js @@ -53,6 +53,7 @@ exports.remove = (guild) => { exports.has = guild => guildConfs.has(guild.id); exports.get = (guild) => { + const defaultConf = fs.readJSONSync(path.resolve(`${dataDir}${path.sep}${defaultFile}`)); const conf = {}; if (!!guild && guildConfs.has(guild.id)) { const guildConf = guildConfs.get(guild.id); From 32f475f13613855eb615b0ac1adbfc97b8d5b4bf Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Sun, 20 Nov 2016 21:50:10 +1100 Subject: [PATCH 47/51] Aye Fixed Komada not listening to itself --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index fe315acf..b874e0b5 100644 --- a/app.js +++ b/app.js @@ -44,7 +44,7 @@ exports.start = (config) => { }); client.on("message", (msg) => { - if (msg.author.bot) return; + if (msg.author.bot && msg.author.id !== client.user.id) return; const conf = client.funcs.confs.get(msg.guild); msg.guildConf = conf; client.funcs.runCommandMonitors(client, msg).catch(reason => msg.channel.sendMessage(reason).catch(console.error)); From 880d1c1439e8707f4cbec97e18b3dde45363e457 Mon Sep 17 00:00:00 2001 From: Faith Date: Mon, 21 Nov 2016 03:58:17 -0500 Subject: [PATCH 48/51] Reload all the things! (#75) * Fixes last eslint issues and codeblock undefined issue * New Reload.js Command. * Reload Function! Reload all the pieces now! * Fixes for Function/Command reload.js * Semver Minor. Preparing for NPM release --- app.js | 7 +- commands/System/reload.js | 102 +++++++++++++--------- functions/reload.js | 173 ++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 4 files changed, 241 insertions(+), 43 deletions(-) create mode 100644 functions/reload.js diff --git a/app.js b/app.js index b874e0b5..81626440 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,6 @@ const Discord = require("discord.js"); const chalk = require("chalk"); +const loadFunctions = require("./functions/loadFunctions.js"); const clk = new chalk.constructor({ enabled: true }); @@ -22,7 +23,7 @@ exports.start = (config) => { client.clientBaseDir = `${process.cwd()}/`; // Load core functions, then everything else - require("./functions/loadFunctions.js")(client).then(() => { + loadFunctions(client).then(() => { client.funcs.loadDataProviders(client); client.funcs.loadCommands(client); client.funcs.loadCommandInhibitors(client); @@ -78,8 +79,8 @@ exports.start = (config) => { }) .catch((reason) => { if (reason) { - client.funcs.log(reason.stack, 'error'); - msg.channel.sendCode(reason).catch(console.error); + if (reason.stack) client.funcs.log(reason.stack, "error"); + msg.channel.sendCode("", reason).catch(console.error); } }); }); diff --git a/commands/System/reload.js b/commands/System/reload.js index 93f6ae52..47ef1baf 100644 --- a/commands/System/reload.js +++ b/commands/System/reload.js @@ -1,44 +1,67 @@ -const path = require("path"); - -exports.run = (client, msg, [commandname]) => { - if (commandname === "all") { - client.funcs.log("Reloading all commands"); - client.funcs.loadCommands(client); - return; - } - let command; - if (client.commands.has(commandname)) { - command = commandname; - } else if (client.aliases.has(commandname)) { - command = client.aliases.get(commandname); - } - if (!command) { - client.funcs.getFileListing(client, client.coreBaseDir, "commands") - .then((files) => { - const newCommands = files.filter(f => f.name === command); - newCommands.forEach((file) => { - msg.channel.sendMessage(`Loading New Command: ${commandname}`) - .then((m) => { - client.funcs.loadSingleCommand(client, command, false, `${file.path}${path.sep}${file.base}`).then((cmd) => { - m.edit(`Successfully Loaded: ${cmd.help.name}`); - }) - .catch((e) => { - m.edit(`Command load failed for ${command}: \n\`\`\`${e.stack}\`\`\``); - }); - }); +exports.run = (client, msg, [type, name]) => { + switch (type) { + case "function": + msg.channel.sendMessage(`Attemping to reload function ${name}`).then((m) => { + client.funcs.reload.function(client, msg, client.clientBaseDir, name).then(() => { + m.edit(`:white_check_mark: Succesfully reloaded function ${name}`); + }).catch((e) => { + m.edit(e); }); }); - } else { - msg.channel.sendMessage(`Reloading: ${command}`) - .then((m) => { - client.funcs.loadSingleCommand(client, command, true) - .then((cmd) => { - m.edit(`Successfully reloaded: ${cmd.help.name}`); - }) - .catch((e) => { - m.edit(`Command reload failed for ${command}: \n\`\`\`${e}\`\`\``); - }); + break; + case "inhibitor": + msg.channel.sendMessage(`Attempting to reload inhibitor ${name}`).then((m) => { + client.funcs.reload.inhibitor(client, msg, client.clientBaseDir, name).then(() => { + m.edit(`:white_check_mark: Succesfully reloaded inhibitor ${name}`); + }).catch((e) => { + m.edit(e); + }); + }); + break; + case "monitor": + msg.channel.sendMessage(`Attempting to reload monitor ${name}`).then((m) => { + client.funcs.reload.monitor(client, msg, client.clientBaseDir, name).then(() => { + m.edit(`:white_check_mark: Succesfully reloaded monitor ${name}`); + }).catch((e) => { + m.edit(e); + }); + }); + break; + case "provider": + msg.channel.sendMessage(`Attempting to reload provider ${name}`).then((m) => { + client.funcs.reload.provider(client, msg, client.clientBaseDir, name).then(() => { + m.edit(`:white_check_mark: Succesfully reloaded provider ${name}`); + }).catch((e) => { + m.edit(e); + }); }); + break; + case "event": + msg.channel.sendMessage(`Attempting to reload event ${name}`).then((m) => { + client.funcs.reload.event(client, msg, name).then(() => { + m.edit(`:white_check_mark: Succesfully reloaded event ${name}`); + }).catch((e) => { + m.edit(e); + }); + }); + break; + case "command": + switch (name) { + case "all": + client.funcs.loadCommands(client); + msg.channel.sendMessage(":white_check_mark: Reloaded all commands."); + break; + default: + msg.channel.sendMessage(`Attempting to reload command ${name}`).then((m) => { + client.funcs.reload.command(client, msg, client.clientBaseDir, name).then(() => { + m.edit(`:white_check_mark: Succesfully reloaded command ${name}`); + }).catch((e) => { + m.edit(e); + }); + }); + break; + } + break; } }; @@ -54,5 +77,6 @@ exports.conf = { exports.help = { name: "reload", description: "Reloads the command file, if it's been updated or modified.", - usage: "", + usage: " ", + usageDelim: " ", }; diff --git a/functions/reload.js b/functions/reload.js new file mode 100644 index 00000000..c4a3b980 --- /dev/null +++ b/functions/reload.js @@ -0,0 +1,173 @@ +const path = require("path"); + +exports.function = (client, msg, dir, funcName) => new Promise((resolve, reject) => { + if (client.funcs.hasOwnProperty(funcName)) { + client.funcs.getFileListing(client, dir, "functions").then((files) => { + const oldFunction = files.filter(f => f.name === funcName); + if (oldFunction[0]) { + client.funcs[funcName] = ""; + try { + oldFunction.forEach((file) => { + delete require.cache[require.resolve(`${file.path}${path.sep}${file.base}`)]; + client.funcs[funcName] = require(`${file.path}${path.sep}${file.base}`); + if (client.funcs[funcName].init) { + client.funcs[funcName].init(client); + } + }); + } catch (error) { + reject(`:x: ${error}`); + return; + } + resolve(); + } else { + reject(`:x: The function **${funcName}** does not reside in ${dir}functions`); + } + }); + } else { + reject(`:x: The function **${funcName}** does not seem to exist!`); + } +}); + +exports.inhibitor = (client, msg, dir, inhibName) => new Promise((resolve, reject) => { + if (client.commandInhibitors.has(inhibName)) { + client.funcs.getFileListing(client, dir, "inhibitors").then((files) => { + const oldInhibitor = files.filter(f => f.name === inhibName); + if (oldInhibitor[0]) { + try { + oldInhibitor.forEach((file) => { + client.commandInhibitors.delete(file.name); + delete require.cache[require.resolve(`${file.path}${path.sep}${file.base}`)]; + const props = require(`${file.path}${path.sep}${file.base}`); + client.commandInhibitors.set(file.name, props); + if (props.init) { + props.init(client); + } + }); + } catch (error) { + reject(`:x: ${error}`); + return; + } + resolve(); + } else { + reject(`:x: The inhibitor **${inhibName}** does not seem to reside in ${dir}inhibitors`); + } + }); + } else { + reject(`:x: The inhibitor **${inhibName}** does not seem to exist!`); + } +}); + +exports.monitor = (client, msg, dir, monitName) => new Promise((resolve, reject) => { + if (client.commandMonitors.has(monitName)) { + client.funcs.getFileListing(client, dir, "monitors").then((files) => { + const oldMonitor = files.filter(f => f.name === monitName); + if (oldMonitor[0]) { + try { + oldMonitor.forEach((file) => { + client.commandMonitors.delete(file.name); + delete require.cache[require.resolve(`${file.path}${path.sep}${file.base}`)]; + const props = require(`${file.path}${path.sep}${file.base}`); + client.commandMonitors.set(file.name, props); + if (props.init) { + props.init(client); + } + }); + } catch (error) { + reject(`:x: ${error}`); + return; + } + resolve(); + } else { + reject(`:x: The monitor **${monitName}** does not reside in ${dir}monitors`); + } + }); + } else { + reject(`:x: The monitor **${monitName}** does not seem to exist!`); + } +}); + +exports.provider = (client, msg, dir, providerName) => new Promise((resolve, reject) => { + if (client.dataProviders.has(providerName)) { + client.funcs.getFileListing(client, dir, "dataProviders").then((files) => { + const oldProvider = files.filter(f => f.name === providerName); + if (oldProvider[0]) { + try { + oldProvider.forEach((file) => { + client.dataProviders.delete(file.name); + delete require.cache[require.resolve(`${file.path}${path.sep}${file.base}`)]; + const props = require(`${file.path}${path.sep}${file.base}`); + client.dataProviders.set(file.name, props); + if (props.init) { + props.init(client); + } + }); + } catch (error) { + reject(`:x: ${error}`); + return; + } + resolve(); + } else { + reject(`:x: The provider **${providerName}** does not seem to reside in ${dir}dataProviders`); + } + }); + } else { + reject(`:x: The provider **${providerName}** does not seem to exist!`); + } +}); + +exports.event = (client, msg, eventName) => new Promise((resolve, reject) => { + client.funcs.getFileListing(client, client.clientBaseDir, "events").then((files) => { + const oldEvent = files.filter(f => f.name === eventName); + if (oldEvent[0] && oldEvent[0].name === eventName) { + let listener; + if (client._events[eventName].length !== 0) { + listener = client._events[eventName][1]; + } else { + listener = client._events[eventName]; + } + client.removeListener(eventName, listener); + try { + oldEvent.forEach((file) => { + delete require.cache[require.resolve(`${file.path}${path.sep}${file.base}`)]; + client.on(file.name, (...args) => require(`${file.path}${path.sep}${file.base}`).run(client, ...args)); + }); + } catch (error) { + reject(`:x: ${error}`); + return; + } + resolve(); + } else { + reject(`:x: The event **${eventName}** does not seem to exist!`); + } + }); +}); + +exports.command = (client, msg, commandName) => new Promise((resolve, reject) => { + let command; + if (client.commands.has(commandName)) { + command = commandName; + } else if (client.aliases.has(commandName)) { + command = client.aliases.get(commandName); + } + if (!command) { + client.funcs.getFileListing(client, client.coreBaseDir, "commands") + .then((files) => { + const newCommands = files.filter(f => f.name === command); + newCommands.forEach((file) => { + client.funcs.loadSingleCommand(client, command, false, `${file.path}${path.sep}${file.base}`) + .catch((e) => { + reject(`:x: ${e}`); + }); + }); + }); + resolve(); + } else { + client.funcs.loadSingleCommand(client, command, true) + .then(() => { + resolve(); + }) + .catch((e) => { + reject(`:x: ${e}`); + }); + } +}); diff --git a/package.json b/package.json index edf4001b..86216371 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "komada", - "version": "0.9.1", + "version": "0.10.0", "author": "Evelyne Lachance", "description": "Komada: Croatian for 'pieces', is a modular bot system including reloading modules and easy to use custom commands.", "main": "app.js", From cd5732bbedbcaa2cc09df2c1e20bde9447229fef Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Mon, 21 Nov 2016 20:07:07 +1100 Subject: [PATCH 49/51] Create CHANGELOG.MD --- CHANGELOG.MD | 1 + 1 file changed, 1 insertion(+) create mode 100644 CHANGELOG.MD diff --git a/CHANGELOG.MD b/CHANGELOG.MD new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/CHANGELOG.MD @@ -0,0 +1 @@ + From 29360cf3d03bc719a84f51597046d42d24b60fb3 Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Mon, 21 Nov 2016 20:07:21 +1100 Subject: [PATCH 50/51] Rename CHANGELOG.MD to CHANGELOG.md --- CHANGELOG.MD => CHANGELOG.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CHANGELOG.MD => CHANGELOG.md (100%) diff --git a/CHANGELOG.MD b/CHANGELOG.md similarity index 100% rename from CHANGELOG.MD rename to CHANGELOG.md From 5a0795ba445a5a0c65aa621ed8dc5038e71446ce Mon Sep 17 00:00:00 2001 From: Johnson Chen Date: Mon, 21 Nov 2016 20:40:31 +1100 Subject: [PATCH 51/51] Changelog Released. --- CHANGELOG.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b137891..b30db571 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1,52 @@ +# Change Log +All notable changes to this project will be documented in this file. +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + +## [0.10.0] - 2016-11-21 +### Added +- Reloading for Functions, Events, Inhibitors, Monitors from [UnseenFaith] +- Monitors from [UnseenFaith] +- ESLint Rules added from [CyberiumShadow] and [hkwu] +- Discord.JS Indev Support from [CyberiumShadow] +- Custom Permissions Roles from [UnseenFaith] + +### Changed +- New Reload.js Command. from [UnseenFaith] +- Komada no longer listens to bots. from [CyberiumShadow] +- Better support for Arrays/Ints/Booleans/Strings in confs from [UnseenFaith] +- Changing commands to bot owner only. from [eslachance] +- Allowing multiword values to be used in confs from [CyberiumShadow] +- Padding from [vzwGrey] + +### Fixed +- Fixes for Function/Command reload.js from [UnseenFaith] +- Fixes last eslint issues and codeblock undefined issue from [UnseenFaith] +- Monitors/Inhibitors Uncaught Exception fix from [UnseenFaith] +- The Great Conf Fix from [UnseenFaith] +- Fixed Promise Resolve/Rejects to prevent further code execution from [bdistin] +- Download.js VM "Cannot Find Module" Fix from [UnseenFaith] +- Various Confs fixes from [UnseenFaith] +- Usage Addition/ParseUsage fix from [UnseenFaith] + +### Contribution Count (Latest Update) +- [UnseenFaith]: 12 contributions +- [CyberiumShadow]: 4 contributions +- [bdistin]: 1 contribution +- [hkwu]: 1 contribution +- [eslachance]: 1 contribution +- [vzwGrey]: 1 contribution + + +[Unreleased]: https://github.com/eslachance/komada/compare/v0.10.0...HEAD +[0.10.0]: https://github.com/eslachance/komada/compare/1627e6deb1d8c352d83e52ccd590f2330f5f8bb2...v0.10.0 + +[vzwGrey]: https://github.com/vzwGrey +[eslachance]: https://github.com/eslachance +[hkwu]: https://github.com/hkwu +[bdistin]: https://github.com/bdistin +[UnseenFaith]: https://github.com/UnseenFaith +[CyberiumShadow]: https://github.com/CyberiumShadow