diff --git a/.gitignore b/.gitignore
index 0cffcb34..a131d28a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,5 @@
-config.json
\ No newline at end of file
+config.json
+node_modules/
+package.json
+package-lock.json
+.DS_Store
diff --git a/commands/args-info.js b/commands/args-info.js
new file mode 100644
index 00000000..c07af352
--- /dev/null
+++ b/commands/args-info.js
@@ -0,0 +1,12 @@
+module.exports = {
+    name: 'args-info',
+    description: 'change your text into arguments',
+    args: true,
+    usage: '<random arguments>',
+    execute(message, args) {
+        if (args[0] === 'foo') {
+            return message.channel.send('bar');
+        }
+        message.channel.send(`First argument: ${args[0]}`);
+    },
+};
diff --git a/commands/avatar.js b/commands/avatar.js
new file mode 100644
index 00000000..c0f46ba8
--- /dev/null
+++ b/commands/avatar.js
@@ -0,0 +1,15 @@
+module.exports = {
+    name: 'avatar',
+    aliases: ['icon', 'pfp'],
+    description: 'Send the avatar of the user mentionned',
+    execute(message) {
+        if (!message.mentions.users.size) {
+            return message.channel.send(`Your avatar: ${message.author.displayAvatarURL}`);
+        }
+
+        const avatarList = message.mentions.users.map(user => {
+            return `${user.username}'s avatar: ${user.displayAvatarURL}`;
+        });
+        message.channel.send(avatarList);
+    },
+};
diff --git a/commands/ded.js b/commands/ded.js
index b21f73e9..c4c3e7b4 100644
--- a/commands/ded.js
+++ b/commands/ded.js
@@ -1,6 +1,10 @@
-exports.run = (client,message) => {
-    if (message.author.id == "267065637183029248") {
-        message.channel.send("haha yes im ded now k bye thx").catch(console.error);
-        process.exit();
-}
-};
\ No newline at end of file
+module.exports = {
+    name: 'ded',
+    description: 'Reboot the bot',
+    aliases: ['shutdown', 'reboot'],
+    execute(message) {
+        if (message.author.id === '267065637183029248') {
+            process.exit();
+        }
+    },
+};
diff --git a/commands/eval.js b/commands/eval.js
deleted file mode 100644
index 4694289a..00000000
--- a/commands/eval.js
+++ /dev/null
@@ -1,27 +0,0 @@
-exports.run = (client, message, args) => {
-
-function clean(text) {
-    if (typeof (text) === "string")
-        return text.replace(/`/g, "`" + String.fromCharCode(8203)).replace(/@/g, "@" + String.fromCharCode(8203));
-    else
-        return text;
-}
-
-if (message.author.id == "267065637183029248") {
-            
-    try {
-        const code = args.join(" ");
-        let evaled = eval(code);
-
-        if (typeof evaled !== "string")
-            evaled = require("util").inspect(evaled);
-
-        message.channel.send(clean(evaled), { code: "xl" });
-    } catch (err) {
-        message.channel.send(`\`ERROR\` \`\`\`xl\n${clean(err)}\n\`\`\``);
-    }
-}
-else {
-    message.channel.send("Sick you thought");
-}
-}
\ No newline at end of file
diff --git a/commands/help.js b/commands/help.js
index e6422116..83203393 100644
--- a/commands/help.js
+++ b/commands/help.js
@@ -1,9 +1,46 @@
-exports.run = (client, message) => {
-    message.channel.send({embed: {
-        color: 3447003,
-        title: "Help",
-        description: "Ping: Pong! \n Kick: Kick people from the server (Staff only) {haha kick (mention user)(reasons)} \n Reload: reload a specific command without rebooting the bot (owner only) {haha reload (name of commands)} \n Eval: let the owner do any commands {haha eval (the command)}",
-        timestamp: new Date(),
-      }
-    });
-}
\ No newline at end of file
+const { prefix } = require('../config.json');
+
+module.exports = {
+	name: 'help',
+	description: 'List all of my commands or info about a specific command.',
+	aliases: ['commands'],
+	usage: '[command name]',
+	cooldown: 5,
+	execute(message, args) {
+		const data = [];
+		const { commands } = message.client;
+
+		if (!args.length) {
+			data.push('Here\'s a list of all my commands:');
+			data.push(commands.map(command => command.name).join(', '));
+			data.push(`\nYou can send \`${prefix}help [command name]\` to get info on a specific command!`);
+
+			return message.author.send(data, { split: true })
+				.then(() => {
+					if (message.channel.type === 'dm') return;
+					message.reply('I\'ve sent you a DM with all my commands!');
+				})
+				.catch(error => {
+					console.error(`Could not send help DM to ${message.author.tag}.\n`, error);
+					message.reply('it seems like I can\'t DM you!');
+				});
+		}
+
+		const name = args[0].toLowerCase();
+		const command = commands.get(name) || commands.find(c => c.aliases && c.aliases.includes(name));
+
+		if (!command) {
+			return message.reply('that\'s not a valid command!');
+		}
+
+		data.push(`**Name:** ${command.name}`);
+
+		if (command.aliases) data.push(`**Aliases:** ${command.aliases.join(', ')}`);
+		if (command.description) data.push(`**Description:** ${command.description}`);
+		if (command.usage) data.push(`**Usage:** ${prefix}${command.name} ${command.usage}`);
+
+		data.push(`**Cooldown:** ${command.cooldown || 3} second(s)`);
+
+		message.channel.send(data, { split: true });
+	},
+};
\ No newline at end of file
diff --git a/commands/kick.js b/commands/kick.js
deleted file mode 100644
index e1a3cc3f..00000000
--- a/commands/kick.js
+++ /dev/null
@@ -1,20 +0,0 @@
-exports.run = (client, message, [mention, ...reason]) => {
-    const StaffRole = message.guild.roles.find("name", "Staff");
-    if (!StaffRole)
-        return console.log("The Staff role does not exist");
-
-    if (!message.member.roles.has(StaffRole.id))
-        return message.reply("Sick you thought");
-
-    if (message.mentions.members.size === 0)
-        return message.reply("Please mention a user to kick");
-
-    if (!message.guild.me.hasPermission("KICK_MEMBERS"))
-        return message.reply("");
-
-    const kickMember = message.mentions.members.first();
-
-    kickMember.kick(reason.join(" ")).then(member => {
-        message.reply(`${member.user.username} was succesfully kicked.`);
-    });
-};
\ No newline at end of file
diff --git a/commands/ping.js b/commands/ping.js
index d2aef630..a8d62cfd 100644
--- a/commands/ping.js
+++ b/commands/ping.js
@@ -1,3 +1,7 @@
-exports.run = (client, message, args) => {
-    message.channel.send("pong!").catch(console.error);
-}
\ No newline at end of file
+module.exports = {
+    name: 'ping',
+    description: 'Ping!',
+    execute(message) {
+        message.channel.send('Pong.');
+    },
+};
diff --git a/commands/prune.js b/commands/prune.js
new file mode 100644
index 00000000..38f649fd
--- /dev/null
+++ b/commands/prune.js
@@ -0,0 +1,18 @@
+module.exports = {
+    name: 'prune',
+    description: 'Bulk delete messages',
+    execute(message, args) {
+        const amount = parseInt(args[0]) + 1;
+
+        if (isNaN(amount)) {
+            return message.reply('that dosen\'t seem to be a valid number.');
+        }
+        else if (amount <= 1 || amount > 100) {
+            return message.reply('you need to input a number between 1 and 99.');
+        }
+        message.channel.bulkDelete(amount, true).catch(err => {
+            console.error(err);
+            message.channel.send('there was an error trying to prune messages in this channel!');
+        });
+    },
+};
diff --git a/commands/purge b/commands/purge
deleted file mode 100644
index a17831c1..00000000
--- a/commands/purge
+++ /dev/null
@@ -1,15 +0,0 @@
-exports.run = (client, message, args) => {
-    const user = message.mentions.users.first();
-    const amount = !!parseInt(message.content.split(' ')[1]) ? parseInt(message.content.split(' ')[1]) : parseInt(message.content.split(' ')[2])
-    if (!amount) return message.reply('Must specify an amount to delete!');
-    if (!amount && !user) return message.reply('Must specify a user and amount, or just an amount, of messages to purge!');
-    message.channel.fetchMessages({
-     limit: 100,
-    }).then((messages) => {
-     if (user) {
-     const filterBy = user ? user.id : Client.user.id;
-     messages = messages.filter(m => m.author.id === filterBy).array().slice(0, amount);
-     }
-     message.channel.bulkDelete(messages).catch(error => console.log(error.stack));
-    });
-};
\ No newline at end of file
diff --git a/commands/reload.js b/commands/reload.js
deleted file mode 100644
index bc246f62..00000000
--- a/commands/reload.js
+++ /dev/null
@@ -1,17 +0,0 @@
-exports.run = (client, message, args) => {
-    if (message.author.id == "267065637183029248") {
-    if(!args || args.size < 1) return message.reply("Must provide a command name to reload.");
-    const commandName = args[0];
-
-    if(!client.commands.has(commandName)) {
-        return message.reply("That command does not exist");
-    }
-
-    delete require.cache[require.resolve(`./${commandName}.js`)];
-
-    client.commands.delete(commandName);
-    const props = require(`./${commandName}.js`);
-    client.commands.set(commandName, props);
-    message.reply(`The command ${commandName} has been reloaded`);
-};
-}
\ No newline at end of file
diff --git a/commands/server.js b/commands/server.js
new file mode 100644
index 00000000..03da67e1
--- /dev/null
+++ b/commands/server.js
@@ -0,0 +1,8 @@
+module.exports = {
+    name: 'server',
+    description: 'Send some informations about the server',
+    guildOnly: true,
+    execute(message) {
+        message.channel.send(`This server's name is: ${message.guild.name}\nTotal members: ${message.guild.memberCount}`);
+    },
+};
diff --git a/commands/user-info.js b/commands/user-info.js
new file mode 100644
index 00000000..ba8229eb
--- /dev/null
+++ b/commands/user-info.js
@@ -0,0 +1,7 @@
+module.exports = {
+    name: 'user-info',
+    description: 'Send some information about the user',
+    execute(message) {
+        message.channel.send(`Your username: ${message.author.username}\nYour ID: ${message.author.id}`);
+    },
+};
diff --git a/commands/yes b/commands/yes
deleted file mode 100644
index b87ce509..00000000
--- a/commands/yes
+++ /dev/null
@@ -1,3 +0,0 @@
-exports.run = (client, message, args) => {
-    message.channel.send("haha yes").catch(console.error);
-}
\ No newline at end of file
diff --git a/events/message.js b/events/message.js
deleted file mode 100644
index 14587efa..00000000
--- a/events/message.js
+++ /dev/null
@@ -1,14 +0,0 @@
-module.exports = (client, message) => {
-    if (message.author.bot) return;
-
-    if (message.content.indexOf(client.config.prefix) !== 0) return;
-
-    const args = message.content.slice(client.config.prefix.length).trim().split(/ +/g);
-    const command = args.shift().toLowerCase();
-
-    const cmd = client.commands.get(command);
-
-    if (!cmd) return;
-
-    cmd.run(client, message, args);
-};
\ No newline at end of file
diff --git a/events/ready.js b/events/ready.js
deleted file mode 100644
index 4613b0c9..00000000
--- a/events/ready.js
+++ /dev/null
@@ -1,3 +0,0 @@
-module.exports = (client) => {
-    console.log(`Ready to server in ${client.channels.size} channels on ${client.guilds.size} servers, for a total of ${client.users.size} users.`);
-};
\ No newline at end of file
diff --git a/hahayes.js b/hahayes.js
deleted file mode 100644
index 64ce4352..00000000
--- a/hahayes.js
+++ /dev/null
@@ -1,39 +0,0 @@
-const Discord = require("discord.js");
-const Enmap = require("enmap");
-const fs = require("fs");
-
-const client = new Discord.Client();
-const config = require("./config.json");
-const responseObject = require("./reply.json");
-
-client.config = config;
-
-fs.readdir("./events/", (err, files) => {
-  if (err) return console.error(err);
-  files.forEach(file => {
-    const event = require(`./events/${file}`);
-    let eventName = file.split(".")[0];
-    client.on(eventName, event.bind(null, client));
-  });
-});
-
-client.commands = new Enmap();
-
-fs.readdir("./commands/", (err, files) => {
-  if (err) return console.error(err);
-  files.forEach(file => {
-    if (!file.endsWith(".js")) return;
-    let props = require(`./commands/${file}`);
-    let commandName = file.split(".")[0];
-    console.log(`Attempting to load command ${commandName}`);
-    client.commands.set(commandName, props);
-  });
-});
-
-client.on("message", (message) => {
-  if(responseObject[message.content]) {
-    message.channel.send(responseObject[message.content]);
-  }
-});
-
-client.login(config.token);
\ No newline at end of file
diff --git a/hahayesv2.js b/hahayesv2.js
new file mode 100644
index 00000000..5dea136b
--- /dev/null
+++ b/hahayesv2.js
@@ -0,0 +1,83 @@
+const fs = require('fs');
+const Discord = require('discord.js');
+const { prefix, token } = require('./config.json');
+
+const client = new Discord.Client();
+client.commands = new Discord.Collection();
+const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
+
+for (const file of commandFiles) {
+    const command = require(`./commands/${file}`);
+    client.commands.set(command.name, command);
+}
+
+const cooldowns = new Discord.Collection();
+
+//  Ready
+
+client.on('ready', () => {
+    console.log('Ready!');
+});
+
+client.on('message', message => {
+    if (!message.content.startsWith(prefix) || message.author.bot) return;
+
+    const args = message.content.slice(prefix.length).split(/ +/);
+    const commandName = args.shift().toLowerCase();
+
+    if (!client.commands.has(commandName)) return;
+
+    const command = client.commands.get(commandName)
+        || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
+
+    if (!command) return;
+
+    if (command.guildOnly && message.channel.type !== 'text') {
+        return message.reply('I can\'t execute that command inside DMs!');
+    }
+
+    if (command.args && !args.length) {
+        let reply = `You didin't provide any arguments, ${message.author}!`;
+
+        if (command.usage) {
+            reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``;
+        }
+
+        return message.channel.send(reply);
+    }
+//  Cooldown
+
+    if (!cooldowns.has(command.name)) {
+        cooldowns.set(command.name, new Discord.Collection());
+    }
+
+    const now = Date.now();
+    const timestamps = cooldowns.get(command.name);
+    const cooldownAmount = (command.cooldown || 1) * 1000;
+
+    if (!timestamps.has(message.author.id)) {
+        timestamps.set(message.author.id, now);
+        setTimeout(() => timestamps.delete(message.author.id), cooldownAmount);
+    }
+    else {
+        const expirationTime = timestamps.get(message.author.id) + cooldownAmount;
+
+        if (now < expirationTime) {
+            const timeLeft = (expirationTime - now) / 1000;
+            return message.reply(`please wait ${timeLeft.toFixed(1)} more second(s) before reusing the \`${command.name}\` command.`);
+        }
+
+        timestamps.set(message.author.id, now);
+        setTimeout(() => timestamps.delete(message.author.id), cooldownAmount);
+    }
+//  Error
+    try {
+        command.execute(message, args);
+    }
+    catch (error) {
+        console.error(error);
+        message.reply('there was an error trying to execute that command!');
+    }
+});
+
+client.login(token);
\ No newline at end of file
diff --git a/index.js b/index.js
new file mode 100644
index 00000000..d22050f1
--- /dev/null
+++ b/index.js
@@ -0,0 +1,27 @@
+const { CommandoClient } = require('discord.js-commando');
+const path = require('path');
+const { token } = require('./config.json');
+
+const client = new CommandoClient({
+	commandPrefix: 'haha ',
+	owner: '267065637183029248',
+	invite: 'https://discord.gg/bRCvFy9',
+});
+
+client.registry
+	.registerDefaultTypes()
+	.registerGroups([
+		['first', 'Your First Command Group'],
+	])
+	.registerDefaultGroups()
+	.registerDefaultCommands()
+	.registerCommandsIn(path.join(__dirname, 'commands'));
+
+client.on('ready', () => {
+	console.log(`Logged in as ${client.user.tag}! (${client.user.id})`);
+	client.user.setActivity('with Commando');
+});
+
+client.on('error', console.error);
+
+client.login(token);
\ No newline at end of file
diff --git a/node_modules/async-limiter/package.json b/node_modules/async-limiter/package.json
index f61367ef..5733fff7 100644
--- a/node_modules/async-limiter/package.json
+++ b/node_modules/async-limiter/package.json
@@ -21,7 +21,7 @@
   "_resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
   "_shasum": "78faed8c3d074ab81f22b4e985d79e8738f720f8",
   "_spec": "async-limiter@~1.0.0",
-  "_where": "/Users/loic/Documents/DiscordJS/node_modules/ws",
+  "_where": "/Users/loic/Documents/DiscordBotV2/node_modules/ws",
   "author": {
     "name": "Samuel Reed"
   },
diff --git a/node_modules/discord.js/package.json b/node_modules/discord.js/package.json
index f9de024d..c37727ef 100644
--- a/node_modules/discord.js/package.json
+++ b/node_modules/discord.js/package.json
@@ -22,7 +22,7 @@
   "_resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.4.2.tgz",
   "_shasum": "54586981926521572051f2a30b984aad2b49786e",
   "_spec": "discord.js",
-  "_where": "/Users/loic/Documents/DiscordJS",
+  "_where": "/Users/loic/Documents/DiscordBotV2",
   "author": {
     "name": "Amish Shah",
     "email": "amishshah.2k@gmail.com"
diff --git a/node_modules/enmap/.eslintrc.json b/node_modules/enmap/.eslintrc.json
deleted file mode 100644
index 63d99075..00000000
--- a/node_modules/enmap/.eslintrc.json
+++ /dev/null
@@ -1,156 +0,0 @@
-{
-	"extends": "eslint:recommended",
-	"env": {
-		"node": true,
-		"es6": true
-	},
-	"parserOptions": {
-		"ecmaVersion": 2017
-	},
-	"rules": {
-		"no-extra-parens": ["warn", "all", {
-			"nestedBinaryExpressions": false
-		}],
-		"valid-jsdoc": ["warn", {
-			"requireReturn": false,
-			"requireReturnDescription": false,
-			"preferType": {
-				"String": "string",
-				"Number": "number",
-				"Boolean": "boolean",
-				"Symbol": "symbol",
-				"function": "Function",
-				"object": "Object",
-				"date": "Date",
-				"error": "Error"
-			}
-		}],
-
-		"accessor-pairs": "warn",
-		"array-callback-return": "error",
-		"complexity": "off",
-		"consistent-return": "error",
-		"curly": ["error", "multi-line", "consistent"],
-		"dot-location": ["error", "property"],
-		"dot-notation": "error",
-		"eqeqeq": "off",
-		"no-console": ["error", { "allow": ["log", "warn", "error"] }],
-		"no-empty-function": "error",
-		"no-floating-decimal": "error",
-		"no-implied-eval": "error",
-		"no-invalid-this": "error",
-		"no-lone-blocks": "error",
-		"no-multi-spaces": "error",
-		"no-new-func": "error",
-		"no-new-wrappers": "error",
-		"no-new": "error",
-		"no-octal-escape": "error",
-		"no-return-assign": "error",
-		"no-self-compare": "error",
-		"no-sequences": "error",
-		"no-unmodified-loop-condition": "error",
-		"no-unused-expressions": "error",
-		"no-useless-call": "error",
-		"no-useless-concat": "error",
-		"no-useless-escape": "error",
-		"no-void": "error",
-		"no-warning-comments": "warn",
-		"wrap-iife": "error",
-		"yoda": "error",
-
-		"no-label-var": "error",
-		"no-shadow": "error",
-		"no-undef-init": "error",
-
-		"callback-return": "error",
-		"handle-callback-err": "error",
-		"no-mixed-requires": "error",
-		"no-new-require": "error",
-		"no-path-concat": "error",
-		"no-process-env": "error",
-
-		"array-bracket-spacing": "error",
-		"block-spacing": "error",
-		"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
-		"camelcase": "error",
-		"comma-dangle": "error",
-		"comma-spacing": "error",
-		"comma-style": "error",
-		"computed-property-spacing": "error",
-		"consistent-this": "error",
-		"eol-last": "error",
-		"func-names": "error",
-		"func-style": ["error", "declaration", { "allowArrowFunctions": true }],
-		"id-length": ["error", { "exceptions": ["i", "j", "a", "b", "_"] }],
-		"indent": ["error", 2],
-		"key-spacing": "error",
-		"keyword-spacing": ["error", {
-			"overrides": {
-				"if": { "after": true },
-				"for": { "after": true },
-				"while": { "after": true },
-				"catch": { "after": true },
-				"switch": { "after": true }
-			}
-		}],
-		"max-depth": "error",
-		"max-len": ["error", 200, 2],
-		"max-nested-callbacks": ["error", { "max": 4 }],
-		"max-statements-per-line": ["error", { "max": 2 }],
-		"new-cap": "error",
-		"newline-per-chained-call": ["error", { "ignoreChainWithDepth": 6 }],
-		"no-array-constructor": "error",
-		"no-bitwise": "warn",
-		"no-inline-comments": "error",
-		"no-lonely-if": "error",
-		"no-mixed-operators": "error",
-		"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }],
-		"no-new-object": "error",
-		"no-spaced-func": "error",
-		"no-trailing-spaces": "error",
-		"no-unneeded-ternary": "error",
-		"no-whitespace-before-property": "error",
-		"object-curly-newline": "error",
-		"object-curly-spacing": ["error", "always"],
-		"operator-assignment": "error",
-		"operator-linebreak": ["error", "after"],
-		"padded-blocks": ["error", { "classes": "always", "blocks": "never", "switches": "never" }],
-		"quote-props": ["error", "as-needed"],
-		"quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }],
-		"semi-spacing": "error",
-		"semi": "error",
-		"space-before-blocks": "error",
-		"space-before-function-paren": ["error", {"anonymous": "always", "named": "never", "asyncArrow": "always"}],
-		"space-in-parens": "error",
-		"space-infix-ops": "error",
-		"space-unary-ops": "error",
-		"spaced-comment": "error",
-		"unicode-bom": "error",
-
-		"arrow-body-style": "error",
-		"arrow-spacing": "error",
-		"no-duplicate-imports": "error",
-		"no-useless-computed-key": "error",
-		"no-useless-constructor": "error",
-		"prefer-arrow-callback": "error",
-		"prefer-const": "error",
-		"prefer-destructuring": ["error", {
-			"VariableDeclarator": {
-				"array": false,
-				"object": true
-			},
-			"AssignmentExpression": {
-				"array": true,
-				"object": true
-			}
-			}, {
-			"enforceForRenamedProperties": false
-		}],
-		"prefer-rest-params": "error",
-		"prefer-spread": "error",
-		"prefer-template": "error",
-		"rest-spread-spacing": "error",
-		"template-curly-spacing": "error",
-		"yield-star-spacing": "error"
-	}
-}
diff --git a/node_modules/enmap/LICENSE b/node_modules/enmap/LICENSE
deleted file mode 100644
index f58a895c..00000000
--- a/node_modules/enmap/LICENSE
+++ /dev/null
@@ -1,208 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "{}"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-  APPENDIX: Code from other projects
-   This project contains partial code from Discord.js version 10.
-   Project Link: https://github.com/discordjs/discord.js
-   Author: Amish Shaw (hydrabolt)
-   License: https://github.com/discordjs/discord.js/blob/master/LICENSE
-
-
-   Copyright 2018 Évelyne Lachance <eslachance@gmail.com>
-  
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/node_modules/enmap/README.md b/node_modules/enmap/README.md
deleted file mode 100644
index 8e09c382..00000000
--- a/node_modules/enmap/README.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# Enmap - Enhanced Maps
-
-Enhanced Maps are a data structure that can be used to store data in memory that can also be saved in a database behind the scenes. These operations are fast, safe, and painless.
-
-The data is synchronized to the database automatically, seamlessly, and asynchronously for maximum effectiveness. The storage system used is an `sqlite` database which is fast,
-performant, can be easily backed up, and supports multiple simultaneous connections.
-
-## Documentation
-
- * [Installation](https://evie.gitbook.io/enmap/install)
- * [Basic Setup](https://evie.gitbook.io/enmap/usage)
- * [API Reference](https://evie.gitbook.io/enmap/api)
- * [Examples](https://evie.gitbook.io/enmap/examples)
-
-## Support
-
-Support is offered on my official [Evie.Codes Discord](https://discord.gg/N7ZKH3P).
-
-## FAQs
-
-### Q: So what's Enmap
-
-**A**: Enmaps are the Javascript Map() data structure with additional utility methods. This started
-as a pretty straight clone of the [Discord.js Collections](https://discord.js.org/#/docs/main/stable/class/Collection)
-but since its creation has grown far beyond those methods alone.
-
-### Q: What is "Persistent"?
-
-**A**: With the use of the optional providers modules, any data added to the Enmap
-is stored not only in temporary memory but also backed up in a local database. This means that
-when you restart your project, your data is not lost and is loaded on startup.
-
-### Q: How big can the Enmap be?
-
-**A**: The size of the memory used is directly proportional to the size of all the keys loaded in memory.
-The more data you have, the more complex it is, the more memory it can use. You can use the
-[fetchAll](https://evie.gitbook.io/enmap/usage/fetchall) options to reduce memory usage.
-
-### Q: Who did you make this for?
-
-**A**: Well, myself because I do use it often. But also, I built it specifically for beginners in mind. 
-Enmap's main goal is to remain simple to use, as fast as possible, and a solid as possible.
-
-### Q: What's is used for?
-
-**A**: Enmap is useful for storing very simple key/value data for easy retrieval, and also for more complex objects with many properties. 
-Mainly, because of who I originally made this for, it's used in Discord.js Bots to save currencies, content blocks, server settings, and
-user information for bans, blacklists, timers, warning systems, etc.
diff --git a/node_modules/enmap/index.d.ts b/node_modules/enmap/index.d.ts
deleted file mode 100644
index cadc6580..00000000
--- a/node_modules/enmap/index.d.ts
+++ /dev/null
@@ -1,338 +0,0 @@
-declare module 'enmap' {
-    /**
-     * A enhanced Map structure with additional utility methods.
-     * Can be made persistent
-     * @extends {Map}
-     */
-    export = Enmap;
-
-    type PropOrFun = (val: any, key: string | number, thisArg: Enmap) => any;
-    type filterFunc = (val: any, key: string | number, thisArg: Enmap) => boolean;
-    type someFunc = (val: any, key: string | number, thisArg: Enmap) => boolean;
-    type everyFunc = (val: any, key: string | number, thisArg: Enmap) => boolean;
-    type mapFunc = (val: any, key: string | number, thisArg: Enmap) => any;
-    type reduceFunc = (
-        accumulator: any,
-        currentValue: any,
-        currentKey: string | number,
-        thisArg: Enmap
-    ) => any;
-
-    class Enmap extends Map {
-        /**
-         * Initialize multiple Enmaps easily.
-         * @param {Array<string>} names Array of strings. Each array entry will create a separate enmap with that name.
-         * @param {EnmapProvider} Provider Valid EnmapProvider object.
-         * @param {Object} options Options object to pass to the provider. See provider documentation for its options.
-         * @returns {Array<Map>} An array of initialized Enmaps.
-         */
-        public static multi(names: string[], Provider: any, options?: any): Enmap[];
-
-        public fetchAll: boolean;
-
-        private db: object;
-        private defer: boolean;
-        private persistent: boolean;
-
-        constructor(iterable?: Iterable<any> | { provider: any }, options?: any);
-
-        /**
-         * Shuts down the underlying persistent enmap database.
-         */
-        public close(): void;
-
-        /**
-         * Retrieves a key from the enmap. If fetchAll is false, returns a promise.
-         * @param {string|number} key The key to retrieve from the enmap.
-         * @return {*|Promise<*>} The value or a promise containing the value.
-         */
-        public get(key: string | number): any | Promise<any>;
-
-        /**
-         * Force fetch one or more key values from the enmap. If the database has changed, that new value is used.
-         * @param {string|number} keyOrKeys A single key or array of keys to force fetch from the enmap database.
-         * @return {*|Map} A single value if requested, or a non-persistent enmap of keys if an array is requested.
-         */
-        public fetch(
-            keyOrKeys: string | number | Array<string | number>
-        ): any | Enmap;
-
-        /**
-         * Fetches every key from the persistent enmap and loads them into the current enmap value.
-         * @return {Map} The enmap containing all values.
-         */
-        public fetchEverything(): this;
-
-        /**
-         * Set the value in Enmap.
-         * @param {string|number} key Required. The key of the element to add to The Enmap.
-         * If the Enmap is persistent this value MUST be a string or number.
-         * @param {*} val Required. The value of the element to add to The Enmap.
-         * If the Enmap is persistent this value MUST be stringifiable as JSON.
-         * @return {Enmap} The Enmap.
-         */
-        public set(key: string | number, val: any): this;
-
-        /**
-         * Set the value in Enmap, but returns a promise that resolves once writte to the database.
-         * Useless on non-persistent Enmaps.
-         * @param {string|number} key Required. The key of the element to add to The Enmap.
-         * If the Enmap is persistent this value MUST be a string or number.
-         * @param {*} val Required. The value of the element to add to The Enmap.
-         * If the Enmap is persistent this value MUST be stringifiable as JSON.
-         * @return {Promise<Map>} The Enmap.
-         */
-        public setAsync(key: string | number, val: any): Promise<this>;
-
-        /**
-         * Returns the specific property within a stored value. If the value isn't an object or array,
-         * returns the unchanged data If the key does not exist or the value is not an object, throws an error.
-         * @param {string|number} key Required. The key of the element to get from The Enmap.
-         * @param {*} prop Required. The property to retrieve from the object or array.
-         * @return {*} The value of the property obtained.
-         */
-        public getProp(key: string | number, prop: any): any;
-
-        /**
-         * Modify the property of a value inside the enmap, if the value is an object or array.
-         * This is a shortcut to loading the key, changing the value, and setting it back.
-         * @param {string|number} key Required. The key of the element to add to The Enmap or array.
-         * This value MUST be a string or number.
-         * @param {*} prop Required. The property to modify inside the value object or array.
-         * @param {*} val Required. The value to apply to the specified property.
-         * @param {boolean} save Optional. Whether to save to persistent DB (used as false in init)
-         * @return {Map} The EnMap.
-         */
-        public setProp(key: string | number, prop: any, val: any): this;
-
-        /**
-         * Returns whether or not the key exists in the Enmap.
-         * @param {string|number} key Required. The key of the element to add to The Enmap or array.
-         * This value MUST be a string or number.
-         * @returns {Promise<boolean>}
-         */
-        public has(key: string | number): boolean;
-        public has(key: string | number): Promise<boolean>;
-
-        /**
-         * Returns whether or not the property exists within an object or array value in enmap.
-         * @param {string|number} key Required. The key of the element to check in the Enmap or array.
-         * @param {*} prop Required. The property to verify inside the value object or array.
-         * @return {boolean} Whether the property exists.
-         */
-        public hasProp(key: string | number, prop: any): boolean;
-
-        /**
-         * Delete a property from an object or array value in Enmap.
-         * @param {string|number} key Required. The key of the element to delete the property from in Enmap.
-         * @param {*} prop Required. The name of the property to remove from the object.
-         * @returns {Promise<Enmap>|Enmap} If fetchAll is true, return the Enmap. Otherwise return a promise containing
-         * the Enmap.
-         */
-        public deleteProp(key: string | number, prop: any): Promise<this> | this;
-
-        /**
-         * Deletes a key in the Enmap.
-         * @param {string|number} key Required. The key of the element to delete from The Enmap.
-         * @param {boolean} bulk Internal property used by the purge method.
-         */
-        public delete(key: string | number): boolean;
-
-        /**
-         *
-         * @param {string|number} key Required. The key of the element to delete from The Enmap.
-         * @param {boolean} bulk Internal property used by the purge method.
-         */
-        public deleteAsync(key: string | number): boolean;
-
-        /**
-         * Creates an ordered array of the values of this Enmap, and caches it internally.
-         * The array will only be reconstructed if an item is added to or removed from the Enmap,
-         * or if you change the length of the array itself. If you don't want this caching behaviour,
-         * use `Array.from(enmap.values())` instead.
-         * @returns {Array}
-         */
-        public array(): any[];
-
-        /**
-         * Creates an ordered array of the keys of this Enmap, and caches it internally.
-         * The array will only be reconstructed if an item is added to or removed from the Enmap,
-         * or if you change the length of the array itself. If you don't want this caching behaviour,
-         * use `Array.from(enmap.keys())` instead.
-         * @returns {Array}
-         */
-        public keyArray(): any[];
-
-        /**
-         * Obtains random value(s) from this Enmap. This relies on {@link Enmap#array},
-         * and thus the caching mechanism applies here as well.
-         * @param {number} [count] Number of values to obtain randomly
-         * @returns {*|Array<*>} The single value if `count` is undefined,
-         * or an array of values of `count` length
-         */
-        public random(count: number): any | any[];
-
-        /**
-         * Obtains random key(s) from this Enmap. This relies on {@link Enmap#keyArray},
-         * and thus the caching mechanism applies here as well.
-         * @param {number} [count] Number of keys to obtain randomly
-         * @returns {*|Array<*>} The single key if `count` is undefined,
-         * or an array of keys of `count` length
-         */
-        public randomKey(count: number): any | any[];
-
-        /**
-         * Searches for all items where their specified property's value is identical to the given value
-         * (`item[prop] === value`).
-         * @param {string} prop The property to test against
-         * @param {*} value The expected value
-         * @returns {Array}
-         * @example
-         * enmap.findAll('username', 'Bob');
-         */
-        public findAll(prop: string, value: any): any[];
-
-        /**
-         * Searches for a single item where its specified property's value is identical to the given value
-         * (`item[prop] === value`), or the given function returns a truthy value. In the latter case, this is identical to
-         * [Array.find()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find).
-         * <warn>All Enmap used in Discord.js are mapped using their `id` property, and if you want to find by id you
-         * should use the `get` method. See
-         * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get)
-         * for details.</warn>
-         * @param {string|Function} propOrFn The property to test against, or the function to test with
-         * @param {*} [value] The expected value - only applicable and required if using a property for the first argument
-         * @returns {*}
-         * @example
-         * enmap.find('username', 'Bob');
-         * @example
-         * enmap.find(val => val.username === 'Bob');
-         */
-        public find(propOrFn: string | PropOrFun, value: any): any;
-
-        /**
-         * Searches for the key of a single item where its specified property's value is identical to the given value
-         * (`item[prop] === value`), or the given function returns a truthy value. In the latter case, this is identical to
-         * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
-         * @param {string|Function} propOrFn The property to test against, or the function to test with
-         * @param {*} [value] The expected value - only applicable and required if using a property for the first argument
-         * @returns {*}
-         * @example
-         * enmap.findKey('username', 'Bob');
-         * @example
-         * enmap.findKey(val => val.username === 'Bob');
-         */
-        public findKey(propOrFn: string | PropOrFun, value: any): any;
-
-        /**
-         * Searches for the existence of a single item where its specified property's value is identical to the given value
-         * (`item[prop] === value`).
-         * <warn>Do not use this to check for an item by its ID. Instead, use `enmap.has(id)`. See
-         * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) for details.
-         * </warn>
-         * @param {string} prop The property to test against
-         * @param {*} value The expected value
-         * @returns {boolean}
-         * @example
-         * if (enmap.exists('username', 'Bob')) {
-   *  console.log('user here!');
-   * }
-         */
-        public exists(prop: string, value: any): boolean;
-
-        /**
-         * Identical to
-         * [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter),
-         * but returns a Enmap instead of an Array.
-         * @param {Function} fn Function used to test (should return a boolean)
-         * @param {Object} [thisArg] Value to use as `this` when executing function
-         * @returns {Enmap}
-         */
-        public filter(fn: filterFunc, thisArg?: any): Enmap;
-
-        /**
-         * Identical to
-         * [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter).
-         * @param {Function} fn Function used to test (should return a boolean)
-         * @param {Object} [thisArg] Value to use as `this` when executing function
-         * @returns {Array}
-         */
-        public filterArray(fn: filterFunc, thisArg?: any): any[];
-
-        /**
-         * Identical to
-         * [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
-         * @param {Function} fn Function that produces an element of the new array, taking three arguments
-         * @param {*} [thisArg] Value to use as `this` when executing function
-         * @returns {Array}
-         */
-        public map(fn: mapFunc, thisArg?: any): any[];
-
-        /**
-         * Identical to
-         * [Array.some()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
-         * @param {Function} fn Function used to test (should return a boolean)
-         * @param {Object} [thisArg] Value to use as `this` when executing function
-         * @returns {boolean}
-         */
-        public some(fn: someFunc, thisArg?: any): any[];
-
-        /**
-         * Identical to
-         * [Array.every()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every).
-         * @param {Function} fn Function used to test (should return a boolean)
-         * @param {Object} [thisArg] Value to use as `this` when executing function
-         * @returns {boolean}
-         */
-        public every(fn: everyFunc, thisArg?: any): any[];
-
-        /**
-         * Identical to
-         * [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce).
-         * @param {Function} fn Function used to reduce, taking four arguments; `accumulator`, `currentValue`, `currentKey`,
-         * and `enmap`
-         * @param {*} [initialValue] Starting value for the accumulator
-         * @returns {*}
-         */
-        public reduce(fn: reduceFunc, initialValue: any): any[];
-
-        /**
-         * Creates an identical shallow copy of this Enmap.
-         * @returns {Enmap}
-         * @example const newColl = someColl.clone();
-         */
-        public clone(): Enmap;
-
-        /**
-         * Combines this Enmap with others into a new Enmap. None of the source Enmaps are modified.
-         * @param {...Enmap} enmaps Enmaps to merge
-         * @returns {Enmap}
-         * @example const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl);
-         */
-        public concat(...enmaps: Enmap[]): Enmap;
-
-        /**
-         * Calls the `delete()` method on all items that have it.
-         * @param {boolean} bulk Optional. Defaults to True. whether to use the provider's "bulk" delete feature
-         * if it has one.
-         */
-        public deleteAll(bulk: boolean): void;
-
-        /**
-         * Calls the `delete()` method on all items that have it.
-         * @param {boolean} bulk Optional. Defaults to True. whether to use the provider's "bulk" delete feature
-         * if it has one.
-         * @return {Promise} Returns a promise that is resolved when the database is cleared.
-         */
-        public deleteAllAsync(bulk: boolean): Promise<any>;
-
-        /**
-         * Checks if this Enmap shares identical key-value pairings with another.
-         * This is different to checking for equality using equal-signs, because
-         * the Enmaps may be different objects, but contain the same data.
-         * @param {Enmap} enmap Enmap to compare with
-         * @returns {boolean} Whether the Enmaps have identical contents
-         */
-        public equals(enmap: Enmap): boolean;
-    }
-}
diff --git a/node_modules/enmap/index.js b/node_modules/enmap/index.js
deleted file mode 100644
index 0719f569..00000000
--- a/node_modules/enmap/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-const Enmap = require('./src/index.js');
-
-module.exports = Enmap;
diff --git a/node_modules/enmap/package.json b/node_modules/enmap/package.json
deleted file mode 100644
index 9b361be1..00000000
--- a/node_modules/enmap/package.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{
-  "_from": "enmap",
-  "_id": "enmap@4.0.12",
-  "_inBundle": false,
-  "_integrity": "sha512-jvK94Fyk8HtJlYQdW/XW4pNfUzxzsjF7UlaC1MalpZq944ti9HL+XcRLFTmM1/Px/9dZxGeUPLMBUhAO0/S6YA==",
-  "_location": "/enmap",
-  "_phantomChildren": {},
-  "_requested": {
-    "type": "tag",
-    "registry": true,
-    "raw": "enmap",
-    "name": "enmap",
-    "escapedName": "enmap",
-    "rawSpec": "",
-    "saveSpec": null,
-    "fetchSpec": "latest"
-  },
-  "_requiredBy": [
-    "#USER",
-    "/"
-  ],
-  "_resolved": "https://registry.npmjs.org/enmap/-/enmap-4.0.12.tgz",
-  "_shasum": "432a58a87b8b5605e49ad71e2fcbfaa78a967e88",
-  "_spec": "enmap",
-  "_where": "/Users/loic/Documents/DiscordJS",
-  "author": {
-    "name": "Evelyne Lachance"
-  },
-  "bugs": {
-    "url": "https://github.com/eslachance/enmap/issues"
-  },
-  "bundleDependencies": false,
-  "dependencies": {
-    "lodash": "^4.17.10"
-  },
-  "deprecated": false,
-  "description": "Enhanced Maps are a data structure that can be used to store data in memory that can also be saved in a database behind the scenes. These operations are fast, safe, and painless.",
-  "devDependencies": {
-    "eslint": "^4.19.1",
-    "eslint-config-airbnb-base": "^11.3.2",
-    "eslint-config-standard": "^10.2.1",
-    "eslint-plugin-import": "^2.13.0",
-    "eslint-plugin-node": "^5.1.1",
-    "eslint-plugin-promise": "^3.5.0",
-    "eslint-plugin-standard": "^3.0.1"
-  },
-  "homepage": "https://github.com/eslachance/enmap#readme",
-  "keywords": [],
-  "license": "Apache-2.0",
-  "main": "index.js",
-  "name": "enmap",
-  "peerDependencies": {
-    "better-sqlite-pool": "^0.1.2"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git+https://github.com/eslachance/enmap.git"
-  },
-  "scripts": {
-    "test": "mocha"
-  },
-  "types": "index.d.ts",
-  "version": "4.0.12"
-}
diff --git a/node_modules/enmap/src/error.js b/node_modules/enmap/src/error.js
deleted file mode 100644
index 8a88cddc..00000000
--- a/node_modules/enmap/src/error.js
+++ /dev/null
@@ -1,12 +0,0 @@
-class CustomError extends Error {
-
-  constructor(message, name = null) {
-    super();
-    Error.captureStackTrace(this, this.constructor);
-    this.name = name || 'EnmapError';
-    this.message = message;
-  }
-
-}
-
-module.exports = CustomError;
diff --git a/node_modules/enmap/src/index.js b/node_modules/enmap/src/index.js
deleted file mode 100644
index 3b54f7e0..00000000
--- a/node_modules/enmap/src/index.js
+++ /dev/null
@@ -1,1226 +0,0 @@
-// Lodash should probably be a core lib but hey, it's useful!
-const _ = require('lodash');
-
-// Custom error codes with stack support.
-const Err = require('./error.js');
-
-// Native imports
-const { resolve, sep } = require('path');
-const fs = require('fs');
-
-// Symbols are used to create "private" methods.
-// https://medium.com/front-end-hacking/private-methods-in-es6-and-writing-your-own-db-b2e30866521f
-const _mathop = Symbol('mathop');
-const _getHighestAutonum = Symbol('getHighestAutonum');
-const _check = Symbol('check');
-const _validateName = Symbol('validateName');
-const _fetchCheck = Symbol('fetchCheck');
-const _parseData = Symbol('parseData');
-const _readyCheck = Symbol('readyCheck');
-const _clone = Symbol('clone');
-const _init = Symbol('init');
-
-/**
- * A enhanced Map structure with additional utility methods.
- * Can be made persistent
- * @extends {Map}
- */
-class Enmap extends Map {
-
-  constructor(iterable, options = {}) {
-    if (!iterable || typeof iterable[Symbol.iterator] !== 'function') {
-      options = iterable || {};
-      iterable = null;
-    }
-    super(iterable);
-
-    let cloneLevel;
-    if (options.cloneLevel) {
-      const accepted = ['none', 'shallow', 'deep'];
-      if (!accepted.includes(options.cloneLevel)) throw new Err('Unknown Clone Level. Options are none, shallow, deep. Default is deep.', 'EnmapOptionsError');
-      cloneLevel = options.cloneLevel; // eslint-disable-line prefer-destructuring
-    } else {
-      cloneLevel = 'deep';
-    }
-
-    // Object.defineProperty ensures that the property is "hidden" when outputting
-    // the enmap in console. Only actual map entries are shown using this method.
-    Object.defineProperty(this, 'cloneLevel', {
-      value: cloneLevel,
-      writable: true,
-      enumerable: false,
-      configurable: false
-    });
-
-    if (options.name) {
-      // better-sqlite-pool is better than directly using better-sqlite3 for multi-process purposes.
-      // required only here because otherwise non-persistent database still need to install it!
-      const { Pool } = require('better-sqlite-pool');
-      Object.defineProperty(this, 'persistent', {
-        value: true,
-        writable: false,
-        enumerable: false,
-        configurable: false
-      });
-
-      if (!options.dataDir) {
-        if (!fs.existsSync('./data')) {
-          fs.mkdirSync('./data');
-        }
-      }
-      const dataDir = resolve(process.cwd(), options.dataDir || 'data');
-      const pool = new Pool(`${dataDir}${sep}enmap.sqlite`);
-
-      Object.defineProperties(this, {
-        name: {
-          value: options.name,
-          writable: true,
-          enumerable: false,
-          configurable: false
-        },
-        fetchAll: {
-          value: !_.isNil(options.fetchAll) ? options.fetchAll : true,
-          writable: true,
-          enumerable: false,
-          configurable: false
-        },
-        pool: {
-          value: pool,
-          writable: false,
-          enumerable: false,
-          configurable: false
-        },
-        autoFetch: {
-          value: !_.isNil(options.autoFetch) ? options.autoFetch : true,
-          writable: true,
-          enumerable: false,
-          configurable: false
-        },
-        defer: {
-          value: new Promise((res) =>
-            Object.defineProperty(this, 'ready', {
-              value: res,
-              writable: false,
-              enumerable: false,
-              configurable: false
-            })),
-          writable: false,
-          enumerable: false,
-          configurable: false
-        }
-      });
-      this[_validateName]();
-      this[_init](pool);
-    } else {
-      Object.defineProperty(this, 'name', {
-        value: 'MemoryEnmap',
-        writable: false,
-        enumerable: false,
-        configurable: false
-      });
-      Object.defineProperty(this, 'isReady', {
-        value: true,
-        writable: false,
-        enumerable: false,
-        configurable: false
-      });
-    }
-  }
-
-  /**
-   * Sets a value in Enmap.
-   * @param {string|number} key Required. The key of the element to add to The Enmap.
-   * @param {*} val Required. The value of the element to add to The Enmap.
-   * If the Enmap is persistent this value MUST be stringifiable as JSON.
-   * @param {string} path Optional. The path to the property to modify inside the value object or array.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   * @example
-   * // Direct Value Examples
-   * enmap.set('simplevalue', 'this is a string');
-   * enmap.set('isEnmapGreat', true);
-   * enmap.set('TheAnswer', 42);
-   * enmap.set('IhazObjects', { color: 'black', action: 'paint', desire: true });
-   * enmap.set('ArraysToo', [1, "two", "tree", "foor"])
-   *
-   * // Settings Properties
-   * enmap.set('IhazObjects', 'color', 'blue'); //modified previous object
-   * enmap.set('ArraysToo', 2, 'three'); // changes "tree" to "three" in array.
-   * @returns {Enmap} The enmap.
-   */
-  set(key, val, path = null) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    if (_.isNil(key) || !['String', 'Number'].includes(key.constructor.name)) {
-      throw new Err('Enmap require keys to be strings or numbers.', 'EnmapKeyTypeError');
-    }
-    let data = super.get(key);
-    const oldValue = super.has(key) ? data : null;
-    if (!_.isNil(path)) {
-      _.set(data, path, val);
-    } else {
-      data = val;
-    }
-    if (_.isFunction(this.changedCB)) {
-      this.changedCB(key, oldValue, data);
-    }
-    if (this.persistent) {
-      this.db.prepare(`INSERT OR REPLACE INTO ${this.name} (key, value) VALUES (?, ?);`).run(key, JSON.stringify(data));
-    }
-    return super.set(key, this[_clone](data));
-  }
-
-  /**
-   * Retrieves a key from the enmap. If fetchAll is false, returns a promise.
-   * @param {string|number} key The key to retrieve from the enmap.
-   * @param {string} path Optional. The property to retrieve from the object or array.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   * @example
-   * const myKeyValue = enmap.get("myKey");
-   * console.log(myKeyValue);
-   *
-   * const someSubValue = enmap.get("anObjectKey", "someprop.someOtherSubProp");
-   * @return {*} The value for this key.
-   */
-  get(key, path = null) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    if (!_.isNil(path)) {
-      this[_check](key, 'Object');
-      const data = super.get(key);
-      return _.get(data, path);
-    }
-    return super.get(key);
-  }
-
-  /**
-   * Retrieves the number of rows in the database for this enmap, even if they aren't fetched.
-   * @return {integer} The number of rows in the database.
-   */
-  get count() {
-    const data = this.db.prepare(`SELECT count(*) FROM '${this.name}';`).get();
-    return data['count(*)'];
-  }
-
-  /**
-   * Retrieves all the indexes (keys) in the database for this enmap, even if they aren't fetched.
-   * @return {array<string>} Array of all indexes (keys) in the enmap, cached or not.
-   */
-  get indexes() {
-    const rows = this.db.prepare(`SELECT key FROM '${this.name}';`).get();
-    return rows.map(row => row.key);
-  }
-
-  /**
-   * Migrates an Enmap from version 3 or lower to a Version 4 enmap, which is locked to sqlite backend only.
-   * Version 4 uses a different way of storing data, so is not directly compatible with version 3 data.
-   * Note that this migration also makes the data unuseable with version 3, so it should only be used to migrate once.
-   * @example
-   * // This example migrates from enmap-mongo to the new format.
-   * // Assumes: npm install enmap@3.1.4 enmap-sqlite@latest enmap-mongo@latest
-   * const Enmap = require("enmap");
-   * const Provider = require("enmap-mongo");
-   * const SQLite = require("enmap-sqlite");
-   *
-   * let options = {
-   *  name: 'test',
-   *  dbName: 'enmap',
-   *  url: 'mongodb://username:password@localhost:27017/enmap'
-   * };
-   *
-   * const source = new Provider(options);
-   * const target = new SQLite({"name": "points"});
-   *
-   * Enmap.migrate(source, target);
-   * @param {Provider} source A valid Enmap provider. Can be any existing provider.
-   * @param {Provider} target An SQLite Enmap Provider. Cannot work without enmap-sqlite as the target.
-   */
-  static async migrate(source, target) {
-    if (!source || !target) throw `Both source and target are required.`;
-    if (source.constructor.name !== 'EnmapProvider') throw new Err('Source must be a valid Enmap Provider (not an initialized enmap)');
-    if (target.constructor.name !== 'EnmapProvider') throw new Err('Target must be a valid Enmap Provider (not an initialized enmap)');
-    const sourceMap = new Enmap({ provider: source });
-    const targetMap = new Enmap({ fetchAll: false, provider: target });
-    await sourceMap.defer;
-    await targetMap.defer;
-    if (!targetMap.db.pool.path.includes('enmap.sqlite')) {
-      throw new Err('Target enmap is not an sqlite database. The migrate method is only to migrate from a 3.0 enmap to 4.0 sqlite enmap!');
-    }
-    const insertArray = [];
-    sourceMap.keyArray().forEach(key => {
-      insertArray.push(targetMap.db.set(key, JSON.stringify(sourceMap.get(key))));
-    });
-    await Promise.all(insertArray);
-    return;
-  }
-
-  /**
-   * Fetches every key from the persistent enmap and loads them into the current enmap value.
-   * @return {Enmap} The enmap containing all values.
-   */
-  fetchEverything() {
-    this[_readyCheck]();
-    const rows = this.db.prepare(`SELECT * FROM ${this.name};`).all();
-    for (const row of rows) {
-      super.set(row.key, this[_parseData](row.value));
-    }
-    return this;
-  }
-
-  /**
-   * Force fetch one or more key values from the enmap. If the database has changed, that new value is used.
-   * @param {string|number} keyOrKeys A single key or array of keys to force fetch from the enmap database.
-   * @return {Enmap} The Enmap, including the new fetched value(s).
-   */
-  fetch(keyOrKeys) {
-    this[_readyCheck]();
-    if (_.isArray(keyOrKeys)) {
-      const data = this.db.prepare(`SELECT * FROM ${this.name} WHERE key IN (${'?, '.repeat(keyOrKeys.length).slice(0, -2)})`).all(keyOrKeys);
-      for (const row of data) {
-        super.set(row.key, this[_parseData](row.value));
-      }
-      return this;
-    } else {
-      const data = this.db.prepare(`SELECT * FROM ${this.name} WHERE key = ?;`).get(keyOrKeys);
-      if (!data) return null;
-      super.set(keyOrKeys, this[_parseData](data.value));
-      return this[_parseData](data.value);
-    }
-  }
-
-  /**
-   * Removes a key or keys from the cache - useful when disabling autoFetch.
-   * @param {*} keyOrArrayOfKeys A single key or array of keys to remove from the cache.
-   * @returns {Enmap} The enmap minus the evicted keys.
-   */
-  evict(keyOrArrayOfKeys) {
-    if (_.isArray(keyOrArrayOfKeys)) {
-      keyOrArrayOfKeys.forEach(key => super.delete(key));
-    } else {
-      super.delete(keyOrArrayOfKeys);
-    }
-    return this;
-  }
-
-  /**
-   * Generates an automatic numerical key for inserting a new value.
-   * This is a "weak" method, it ensures the value isn't duplicated, but does not
-   * guarantee it's sequential (if a value is deleted, another can take its place).
-   * Useful for logging, but not much else.
-   * @example
-   * enmap.set(enmap.autonum(), "This is a new value");
-   * @return {number} The generated key number.
-   */
-  autonum() {
-    this[_fetchCheck]('internal::autonum', true);
-    const start = this.get('internal::autonum') || 0;
-    const highest = this[_getHighestAutonum](start);
-    this.set('internal::autonum', highest);
-    return highest;
-  }
-
-  /**
-   * Function called whenever data changes within Enmap after the initial load.
-   * Can be used to detect if another part of your code changed a value in enmap and react on it.
-   * @example
-   * enmap.changed((keyName, oldValue, newValue) => {
-   *   console.log(`Value of ${keyName} has changed from: \n${oldValue}\nto\n${newValue});
-   * });
-   * @param {Function} cb A callback function that will be called whenever data changes in the enmap.
-   */
-  changed(cb) {
-    this.changedCB = cb;
-  }
-
-  /**
-   * Shuts down the database. WARNING: USING THIS MAKES THE ENMAP UNUSEABLE. You should
-   * only use this method if you are closing your entire application.
-   * Note that honestly I've never had to use this, shutting down the app without a close() is fine.
-   * @return {Promise<*>} The promise of the database closing operation.
-   */
-  close() {
-    this[_readyCheck]();
-    return this.pool.close();
-  }
-
-
-  /**
-   * Modify the property of a value inside the enmap, if the value is an object or array.
-   * This is a shortcut to loading the key, changing the value, and setting it back.
-   * @param {string|number} key Required. The key of the element to add to The Enmap or array.
-   * This value MUST be a string or number.
-   * @param {*} path Required. The property to modify inside the value object or array.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   * @param {*} val Required. The value to apply to the specified property.
-   * @returns {Enmap} The enmap.
-   */
-  setProp(key, path, val) {
-    this[_readyCheck]();
-    if (_.isNil(path)) throw new Err(`No path provided to set a property in "${key}" of enmap "${this.name}"`, 'EnmapPathError');
-    return this.set(key, val, path);
-  }
-
-  /**
-   * Push to an array value in Enmap.
-   * @param {string|number} key Required. The key of the array element to push to in Enmap.
-   * This value MUST be a string or number.
-   * @param {*} val Required. The value to push to the array.
-   * @param {string} path Optional. The path to the property to modify inside the value object or array.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   * @param {boolean} allowDupes Optional. Allow duplicate values in the array (default: false).
-   * @example
-   * // Assuming
-   * enmap.set("simpleArray", [1, 2, 3, 4]);
-   * enmap.set("arrayInObject", {sub: [1, 2, 3, 4]});
-   *
-   * enmap.push("simpleArray", 5); // adds 5 at the end of the array
-   * enmap.push("arrayInObject", "five", "sub"); adds "five" at the end of the sub array
-   * @returns {Enmap} The enmap.
-   */
-  push(key, val, path = null, allowDupes = false) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    this[_check](key, 'Array', path);
-    const data = super.get(key);
-    if (!_.isNil(path)) {
-      const propValue = _.get(data, path);
-      if (!allowDupes && propValue.indexOf(val) > -1) return this;
-      propValue.push(val);
-      _.set(data, path, propValue);
-    } else {
-      if (!allowDupes && data.indexOf(val) > -1) return this;
-      data.push(val);
-    }
-    return this.set(key, data);
-  }
-
-  /**
-   * Push to an array element inside an Object or Array element in Enmap.
-   * @param {string|number} key Required. The key of the element.
-   * This value MUST be a string or number.
-   * @param {*} path Required. The name of the array property to push to.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   * @param {*} val Required. The value push to the array property.
-   * @param {boolean} allowDupes Allow duplicate values in the array (default: false).
-   * @returns {Enmap} The enmap.
-   */
-  pushIn(key, path, val, allowDupes = false) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    if (_.isNil(path)) throw new Err(`No path provided to push a value in "${key}" of enmap "${this.name}"`, 'EnmapPathError');
-    return this.push(key, val, path, allowDupes);
-  }
-
-  // AWESOME MATHEMATICAL METHODS
-
-  /**
-   * Executes a mathematical operation on a value and saves it in the enmap.
-   * @param {string|number} key The enmap key on which to execute the math operation.
-   * @param {string} operation Which mathematical operation to execute. Supports most
-   * math ops: =, -, *, /, %, ^, and english spelling of those operations.
-   * @param {number} operand The right operand of the operation.
-   * @param {string} path Optional. The property path to execute the operation on, if the value is an object or array.
-   * @example
-   * // Assuming
-   * points.set("number", 42);
-   * points.set("numberInObject", {sub: { anInt: 5 }});
-   *
-   * points.math("number", "/", 2); // 21
-   * points.math("number", "add", 5); // 26
-   * points.math("number", "modulo", 3); // 2
-   * points.math("numberInObject", "+", 10, "sub.anInt");
-   *
-   * @return {Map} The EnMap.
-   */
-  math(key, operation, operand, path = null) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    this[_check](key, 'Number', path);
-    if (_.isNil(path)) {
-      if (operation === 'random' || operation === 'rand') {
-        return this.set(key, Math.round(Math.random() * operand));
-      }
-      return this.set(key, this[_mathop](this.get(key), operation, operand));
-    } else {
-      const data = this.get(key);
-      const propValue = _.get(data, path);
-      if (operation === 'random' || operation === 'rand') {
-        return this.set(key, Math.round(Math.random() * propValue), path);
-      }
-      return this.set(key, this[_mathop](propValue, operation, operand), path);
-    }
-  }
-
-  /**
-   * Increments a key's value or property by 1. Value must be a number, or a path to a number.
-   * @param {string|number} key The enmap key where the value to increment is stored.
-   * @param {string} path Optional. The property path to increment, if the value is an object or array.
-   * @example
-   * // Assuming
-   * points.set("number", 42);
-   * points.set("numberInObject", {sub: { anInt: 5 }});
-   *
-   * points.inc("number"); // 43
-   * points.inc("numberInObject", "sub.anInt"); // {sub: { anInt: 6 }}
-   * @return {Map} The EnMap.
-   */
-  inc(key, path = null) {
-    this[_readyCheck]();
-    this[_check](key, 'Number', path);
-    if (_.isNil(path)) {
-      let val = this.get(key);
-      return this.set(key, ++val);
-    } else {
-      const data = this.get(key);
-      let propValue = _.get(data, path);
-      _.set(data, path, ++propValue);
-      return this.set(key, data);
-    }
-  }
-
-  /**
-   * Decrements a key's value or property by 1. Value must be a number, or a path to a number.
-   * @param {string|number} key The enmap key where the value to decrement is stored.
-   * @param {string} path Optional. The property path to decrement, if the value is an object or array.
-   * @example
-   * // Assuming
-   * points.set("number", 42);
-   * points.set("numberInObject", {sub: { anInt: 5 }});
-   *
-   * points.dec("number"); // 41
-   * points.dec("numberInObject", "sub.anInt"); // {sub: { anInt: 4 }}
-   * @return {Map} The EnMap.
-   */
-  dec(key, path = null) {
-    this[_readyCheck]();
-    this[_check](key, 'Number', path);
-    if (_.isNil(path)) {
-      let val = this.get(key);
-      return this.set(key, --val);
-    } else {
-      const data = this.get(key);
-      let propValue = _.get(data, path);
-      _.set(data, path, --propValue);
-      return this.set(key, data);
-    }
-  }
-
-  /**
-   * Returns the specific property within a stored value. If the key does not exist or the value is not an object, throws an error.
-   * @param {string|number} key Required. The key of the element to get from The Enmap.
-   * @param {*} path Required. The property to retrieve from the object or array.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   * @return {*} The value of the property obtained.
-   */
-  getProp(key, path) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    if (_.isNil(path)) throw new Err(`No path provided get a property from "${key}" of enmap "${this.name}"`, 'EnmapPathError');
-    return this.get(key, path);
-  }
-
-  /**
-   * Returns the key's value, or the default given, ensuring that the data is there.
-   * This is a shortcut to "if enmap doesn't have key, set it, then get it" which is a very common pattern.
-   * @param {string|number} key Required. The key you want to make sure exists.
-   * @param {*} defaultvalue Required. The value you want to save in the database and return as default.
-   * @example
-   * // Simply ensure the data exists (for using property methods):
-   * enmap.ensure("mykey", {some: "value", here: "as an example"});
-   * enmap.has("mykey"); // always returns true
-   * enmap.get("mykey", "here") // returns "as an example";
-   *
-   * // Get the default value back in a variable:
-   * const settings = mySettings.ensure("1234567890", defaultSettings);
-   * console.log(settings) // enmap's value for "1234567890" if it exists, otherwise the defaultSettings value.
-   * @return {*} The value from the database for the key, or the default value provided for a new key.
-   */
-  ensure(key, defaultvalue) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    if (_.isNil(defaultvalue)) throw new Err(`No default value provided on ensure method for "${key}" in "${this.name}"`, 'EnmapArgumentError');
-    if (super.has(key)) return super.get(key);
-    this.set(key, defaultvalue);
-    return defaultvalue;
-  }
-
-  /* BOOLEAN METHODS THAT CHECKS FOR THINGS IN ENMAP */
-
-  /**
-   * Returns whether or not the key exists in the Enmap.
-   * @param {string|number} key Required. The key of the element to add to The Enmap or array.
-   * This value MUST be a string or number.
-   * @param {string} path Optional. The property to verify inside the value object or array.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   * @example
-   * if(enmap.has("myKey")) {
-   *   // key is there
-   * }
-   *
-   * if(!enmap.has("myOtherKey", "oneProp.otherProp.SubProp")) return false;
-   * @returns {boolean}
-   */
-  has(key, path = null) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    if (!_.isNil(path)) {
-      this[_check](key, 'Object');
-      const data = super.get(key);
-      return _.has(data, path);
-    }
-    return super.has(key);
-  }
-
-  /**
-   * Returns whether or not the property exists within an object or array value in enmap.
-   * @param {string|number} key Required. The key of the element to check in the Enmap or array.
-   * @param {*} path Required. The property to verify inside the value object or array.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   * @return {boolean} Whether the property exists.
-   */
-  hasProp(key, path) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    if (_.isNil(path)) throw new Err(`No path provided to check for a property in "${key}" of enmap "${this.name}"`, 'EnmapPathError');
-    return this.has(key, path);
-  }
-
-  /**
-   * Deletes a key in the Enmap.
-   * @param {string|number} key Required. The key of the element to delete from The Enmap.
-   * @param {string} path Optional. The name of the property to remove from the object.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   * @returns {Enmap} The enmap.
-   */
-  delete(key, path = null) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    const oldValue = this.get(key);
-    if (!_.isNil(path)) {
-      let data = this.get(key);
-      path = _.toPath(path);
-      const last = path.pop();
-      const propValue = path.length ? _.get(data, path) : data;
-      if (_.isArray(propValue)) {
-        propValue.splice(last, 1);
-      } else {
-        delete propValue[last];
-      }
-      if (path.length) {
-        _.set(data, path, propValue);
-      } else {
-        data = propValue;
-      }
-      this.set(key, data);
-    } else {
-      super.delete(key);
-      if (this.persistent) {
-        return this.db.prepare(`DELETE FROM ${this.name} WHERE key = '${key}'`).run();
-      }
-      if (typeof this.changedCB === 'function') {
-        this.changedCB(key, oldValue, null);
-      }
-    }
-    return this;
-  }
-
-  /**
-   * Delete a property from an object or array value in Enmap.
-   * @param {string|number} key Required. The key of the element to delete the property from in Enmap.
-   * @param {*} path Required. The name of the property to remove from the object.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   */
-  deleteProp(key, path) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    if (_.isNil(path)) throw new Err(`No path provided to delete a property in "${key}" of enmap "${this.name}"`, 'EnmapPathError');
-    this.delete(key, path);
-  }
-
-  /**
-   * Deletes everything from the enmap. If persistent, clears the database of all its data for this table.
-   */
-  deleteAll() {
-    this[_readyCheck]();
-    if (this.persistent) {
-      this.db.prepare(`DELETE FROM ${this.name};`).run();
-    }
-    super.clear();
-  }
-
-  clear() { return this.deleteAll(); }
-
-  /**
-   * Remove a value in an Array or Object element in Enmap. Note that this only works for
-   * values, not keys. Complex values such as objects and arrays will not be removed this way.
-   * @param {string|number} key Required. The key of the element to remove from in Enmap.
-   * This value MUST be a string or number.
-   * @param {*} val Required. The value to remove from the array or object.
-   * @param {string} path Optional. The name of the array property to remove from.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3".
-   * If not presents, removes directly from the value.
-   * @return {Map} The EnMap.
-   */
-  remove(key, val, path = null) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    this[_check](key, ['Array', 'Object']);
-    const data = super.get(key);
-    if (!_.isNil(path)) {
-      const propValue = _.get(data, path);
-      if (_.isArray(propValue)) {
-        propValue.splice(propValue.indexOf(val), 1);
-        _.set(data, path, propValue);
-      } else if (_.isObject(propValue)) {
-        _.delete(data, `${path}.${val}`);
-      }
-    } else if (_.isArray(data)) {
-      const index = data.indexOf(val);
-      data.splice(index, 1);
-    } else if (_.isObject(data)) {
-      delete data[val];
-    }
-    return this.set(key, data);
-  }
-
-  /**
-   * Remove a value from an Array or Object property inside an Array or Object element in Enmap.
-   * Confusing? Sure is.
-   * @param {string|number} key Required. The key of the element.
-   * This value MUST be a string or number.
-   * @param {*} path Required. The name of the array property to remove from.
-   * Can be a path with dot notation, such as "prop1.subprop2.subprop3"
-   * @param {*} val Required. The value to remove from the array property.
-   * @return {Map} The EnMap.
-   */
-  removeFrom(key, path, val) {
-    this[_readyCheck]();
-    this[_fetchCheck](key);
-    if (_.isNil(path)) throw new Err(`No path provided to remove an array element in "${key}" of enmap "${this.name}"`, 'EnmapPathError');
-    return this.remove(key, val, path);
-  }
-
-  /**
-   * Initialize multiple Enmaps easily.
-   * @param {Array<string>} names Array of strings. Each array entry will create a separate enmap with that name.
-   * @param {Object} options Options object to pass to the provider. See provider documentation for its options.
-   * @example
-   * // Using local variables and the mongodb provider.
-   * const Enmap = require('enmap');
-   * const { settings, tags, blacklist } = Enmap.multi(['settings', 'tags', 'blacklist']);
-   *
-   * // Attaching to an existing object (for instance some API's client)
-   * const Enmap = require("enmap");
-   * Object.assign(client, Enmap.multi(["settings", "tags", "blacklist"]));
-   *
-   * @returns {Array<Map>} An array of initialized Enmaps.
-   */
-  static multi(names, options = {}) {
-    if (!names.length || names.length < 1) {
-      throw new Err('"names" argument must be an array of string names.', 'EnmapTypeError');
-    }
-
-    const returnvalue = {};
-    for (const name of names) {
-      const enmap = new Enmap(Object.assign(options, { name }));
-      returnvalue[name] = enmap;
-    }
-    return returnvalue;
-  }
-
-  /* INTERNAL (Private) METHODS */
-
-  /*
-   * Internal Method. Initializes the enmap depending on given values.
-   * @param {Map} pool In order to set data to the Enmap, one must be provided.
-   * @returns {Promise} Returns the defer promise to await the ready state.
-   */
-  async [_init](pool) {
-    Object.defineProperty(this, 'db', {
-      value: await pool.acquire(),
-      writable: false,
-      enumerable: false,
-      configurable: false
-    });
-    if (this.db) {
-      Object.defineProperty(this, 'isReady', {
-        value: true,
-        writable: false,
-        enumerable: false,
-        configurable: false
-      });
-    } else {
-      throw new Err('Database Could Not Be Opened', 'EnmapDBConnectionError');
-    }
-    const table = this.db.prepare(`SELECT count(*) FROM sqlite_master WHERE type='table' AND name = '${this.name}';`).get();
-    if (!table['count(*)']) {
-      this.db.prepare(`CREATE TABLE ${this.name} (key text PRIMARY KEY, value text)`).run();
-      this.db.pragma('synchronous = 1');
-      this.db.pragma('journal_mode = wal');
-    }
-    if (this.fetchAll) {
-      await this.fetchEverything();
-    }
-    this.ready();
-    return this.defer;
-  }
-
-  /*
-   * INTERNAL method used by autonum().
-   * Loops on incremental numerical values until it finds a free key
-   * of that value in the Enamp.
-   * @param {Integer} start The starting value to look for.
-   * @return {Integer} The first non-existant value found.
-   */
-  [_getHighestAutonum](start = 0) {
-    this[_readyCheck]();
-    let highest = start;
-    while (this.has(highest)) {
-      highest++;
-    }
-    return highest;
-  }
-
-  /*
-   * INTERNAL method to verify the type of a key or property
-   * Will THROW AN ERROR on wrong type, to simplify code.
-   * @param {string|number} key Required. The key of the element to check
-   * @param {string} type Required. The javascript constructor to check
-   * @param {string} path Optional. The dotProp path to the property in the object enmap.
-   */
-  [_check](key, type, path = null) {
-    if (!this.has(key)) throw new Err(`The key "${key}" does not exist in the enmap "${this.name}"`);
-    if (!type) return;
-    if (!_.isArray(type)) type = [type];
-    if (!_.isNil(path)) {
-      this[_check](key, 'Object');
-      const data = super.get(key);
-      if (!type.includes(_.get(data, path).constructor.name)) {
-        throw new Err(`The property "${path}" in key "${key}" is not of type "${type.join('" or "')}" in the enmap "${this.name}" (key was of type "${_.get(data, path).constructor.name}")`);
-      }
-    } else if (!type.includes(this.get(key).constructor.name)) {
-      throw new Err(`The key "${key}" is not of type "${type.join('" or "')}" in the enmap "${this.name}" (key was of type "${this.get(key).constructor.name}")`);
-    }
-  }
-
-  /*
-  * INTERNAL method to execute a mathematical operation. Cuz... javascript.
-  * And I didn't want to import mathjs!
-  * @param {number} base the lefthand operand.
-  * @param {string} op the operation.
-  * @param {number} opand the righthand operand.
-  * @return {number} the result.
-  */
-  [_mathop](base, op, opand) {
-    if (base == undefined || op == undefined || opand == undefined) throw new Err('Math Operation requires base and operation', 'TypeError');
-    switch (op) {
-    case 'add' :
-    case 'addition' :
-    case '+' :
-      return base + opand;
-    case 'sub' :
-    case 'subtract' :
-    case '-' :
-      return base - opand;
-    case 'mult' :
-    case 'multiply' :
-    case '*' :
-      return base * opand;
-    case 'div' :
-    case 'divide' :
-    case '/' :
-      return base / opand;
-    case 'exp' :
-    case 'exponent' :
-    case '^' :
-      return Math.pow(base, opand);
-    case 'mod' :
-    case 'modulo' :
-    case '%' :
-      return base % opand;
-    }
-    return null;
-  }
-
-  /**
-   * Internal method used to validate persistent enmap names (valid Windows filenames)
-   * @private
-   */
-  [_validateName]() {
-    this.name = this.name.replace(/[^a-z0-9]/gi, '_').toLowerCase();
-  }
-
-  /*
-   * Internal Method. Verifies if a key needs to be fetched from the database.
-   * If persistent enmap and autoFetch is on, retrieves the key.
-   * @param {string|number} key The key to check or fetch.
-   */
-  [_fetchCheck](key, force = false) {
-    if (force) {
-      this.fetch(key);
-      return;
-    }
-    if (super.has(key)) return;
-    if (!this.persistent || !this.autoFetch) return;
-    this.fetch(key);
-  }
-
-  /*
-   * Internal Method. Parses JSON data.
-   * Reserved for future use (logical checking)
-   * @param {*} data The data to check/parse
-   * @returns {*} An object or the original data.
-   */
-  [_parseData](data) {
-    return JSON.parse(data);
-  }
-
-  /*
-   * Internal Method. Clones a value or object with the enmap's set clone level.
-   * @param {*} data The data to clone.
-   * @return {*} The cloned value.
-   */
-  [_clone](data) {
-    if (this.cloneLevel === 'none') return data;
-    if (this.cloneLevel === 'shallow') return _.clone(data);
-    if (this.cloneLevel === 'deep') return _.cloneDeep(data);
-    throw new Err('Invalid cloneLevel. What did you *do*, this shouldn\'t happen!', 'EnmapOptionsError');
-  }
-
-  /*
-   * Internal Method. Verifies that the database is ready, assuming persistence is used.
-   */
-  [_readyCheck]() {
-    if (!this.isReady) throw new Err('Database is not ready. Refer to the readme to use enmap.defer', 'EnmapReadyError');
-  }
-
-  /*
-  BELOW IS DISCORD.JS COLLECTION CODE
-  Per notes in the LICENSE file, this project contains code from Amish Shah's Discord.js
-  library. The code is from the Collections object, in discord.js version 11.
-
-  All below code is sourced from Collections.
-  https://github.com/discordjs/discord.js/blob/stable/src/util/Collection.js
-  */
-
-  /**
-   * Creates an ordered array of the values of this Enmap.
-   * The array will only be reconstructed if an item is added to or removed from the Enmap,
-   * or if you change the length of the array itself. If you don't want this caching behaviour,
-   * use `Array.from(enmap.values())` instead.
-   * @returns {Array}
-   */
-  array() {
-    return Array.from(this.values());
-  }
-
-  /**
-     * Creates an ordered array of the keys of this Enmap
-     * The array will only be reconstructed if an item is added to or removed from the Enmap,
-     * or if you change the length of the array itself. If you don't want this caching behaviour,
-     * use `Array.from(enmap.keys())` instead.
-     * @returns {Array}
-     */
-  keyArray() {
-    return Array.from(this.keys());
-  }
-
-  /**
-     * Obtains random value(s) from this Enmap. This relies on {@link Enmap#array}.
-     * @param {number} [count] Number of values to obtain randomly
-     * @returns {*|Array<*>} The single value if `count` is undefined,
-     * or an array of values of `count` length
-     */
-  random(count) {
-    let arr = this.array();
-    if (count === undefined) return arr[Math.floor(Math.random() * arr.length)];
-    if (typeof count !== 'number') throw new TypeError('The count must be a number.');
-    if (!Number.isInteger(count) || count < 1) throw new RangeError('The count must be an integer greater than 0.');
-    if (arr.length === 0) return [];
-    const rand = new Array(count);
-    arr = arr.slice();
-    for (let i = 0; i < count; i++) {
-      rand[i] = [arr.splice(Math.floor(Math.random() * arr.length), 1)];
-    }
-    return rand;
-  }
-
-  /**
-     * Obtains random key(s) from this Enmap. This relies on {@link Enmap#keyArray}
-     * @param {number} [count] Number of keys to obtain randomly
-     * @returns {*|Array<*>} The single key if `count` is undefined,
-     * or an array of keys of `count` length
-     */
-  randomKey(count) {
-    let arr = this.keyArray();
-    if (count === undefined) return arr[Math.floor(Math.random() * arr.length)];
-    if (typeof count !== 'number') throw new TypeError('The count must be a number.');
-    if (!Number.isInteger(count) || count < 1) throw new RangeError('The count must be an integer greater than 0.');
-    if (arr.length === 0) return [];
-    const rand = new Array(count);
-    arr = arr.slice();
-    for (let i = 0; i < count; i++) {
-      rand[i] = [arr.splice(Math.floor(Math.random() * arr.length), 1)];
-    }
-    return rand;
-  }
-
-  /**
-     * Searches for all items where their specified property's value is identical to the given value
-     * (`item[prop] === value`).
-     * @param {string} prop The property to test against
-     * @param {*} value The expected value
-     * @returns {Array}
-     * @example
-     * enmap.findAll('username', 'Bob');
-     */
-  findAll(prop, value) {
-    if (typeof prop !== 'string') throw new TypeError('Key must be a string.');
-    if (typeof value === 'undefined') throw new Error('Value must be specified.');
-    const results = [];
-    for (const item of this.values()) {
-      if (item[prop] === value) results.push(item);
-    }
-    return results;
-  }
-
-  /**
-     * Searches for a single item where its specified property's value is identical to the given value
-     * (`item[prop] === value`), or the given function returns a truthy value. In the latter case, this is identical to
-     * [Array.find()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find).
-     * <warn>All Enmap used in Discord.js are mapped using their `id` property, and if you want to find by id you
-     * should use the `get` method. See
-     * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) for details.</warn>
-     * @param {string|Function} propOrFn The property to test against, or the function to test with
-     * @param {*} [value] The expected value - only applicable and required if using a property for the first argument
-     * @returns {*}
-     * @example
-     * enmap.find('username', 'Bob');
-     * @example
-     * enmap.find(val => val.username === 'Bob');
-     */
-  find(propOrFn, value) {
-    if (typeof propOrFn === 'string') {
-      if (typeof value === 'undefined') throw new Error('Value must be specified.');
-      for (const item of this.values()) {
-        if (item[propOrFn] === value) return item;
-      }
-      return null;
-    } else if (typeof propOrFn === 'function') {
-      for (const [key, val] of this) {
-        if (propOrFn(val, key, this)) return val;
-      }
-      return null;
-    }
-    throw new Error('First argument must be a property string or a function.');
-  }
-
-  /* eslint-disable max-len */
-  /**
-     * Searches for the key of a single item where its specified property's value is identical to the given value
-     * (`item[prop] === value`), or the given function returns a truthy value. In the latter case, this is identical to
-     * [Array.findIndex()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex).
-     * @param {string|Function} propOrFn The property to test against, or the function to test with
-     * @param {*} [value] The expected value - only applicable and required if using a property for the first argument
-     * @returns {*}
-     * @example
-     * enmap.findKey('username', 'Bob');
-     * @example
-     * enmap.findKey(val => val.username === 'Bob');
-     */
-  /* eslint-enable max-len */
-  findKey(propOrFn, value) {
-    if (typeof propOrFn === 'string') {
-      if (typeof value === 'undefined') throw new Error('Value must be specified.');
-      for (const [key, val] of this) {
-        if (val[propOrFn] === value) return key;
-      }
-      return null;
-    } else if (typeof propOrFn === 'function') {
-      for (const [key, val] of this) {
-        if (propOrFn(val, key, this)) return key;
-      }
-      return null;
-    }
-    throw new Error('First argument must be a property string or a function.');
-  }
-
-  /**
-     * Searches for the existence of a single item where its specified property's value is identical to the given value
-     * (`item[prop] === value`).
-     * <warn>Do not use this to check for an item by its ID. Instead, use `enmap.has(id)`. See
-     * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) for details.</warn>
-     * @param {string} prop The property to test against
-     * @param {*} value The expected value
-     * @returns {boolean}
-     * @example
-     * if (enmap.exists('username', 'Bob')) {
-     *  console.log('user here!');
-     * }
-     */
-  exists(prop, value) {
-    return Boolean(this.find(prop, value));
-  }
-
-  /**
-     * Identical to
-     * [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter),
-     * but returns a Enmap instead of an Array.
-     * @param {Function} fn Function used to test (should return a boolean)
-     * @param {Object} [thisArg] Value to use as `this` when executing function
-     * @returns {Enmap}
-     */
-  filter(fn, thisArg) {
-    if (thisArg) fn = fn.bind(thisArg);
-    const results = new Enmap();
-    for (const [key, val] of this) {
-      if (fn(val, key, this)) results.set(key, val);
-    }
-    return results;
-  }
-
-  /**
-     * Identical to
-     * [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter).
-     * @param {Function} fn Function used to test (should return a boolean)
-     * @param {Object} [thisArg] Value to use as `this` when executing function
-     * @returns {Array}
-     */
-  filterArray(fn, thisArg) {
-    if (thisArg) fn = fn.bind(thisArg);
-    const results = [];
-    for (const [key, val] of this) {
-      if (fn(val, key, this)) results.push(val);
-    }
-    return results;
-  }
-
-  /**
-     * Identical to
-     * [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
-     * @param {Function} fn Function that produces an element of the new array, taking three arguments
-     * @param {*} [thisArg] Value to use as `this` when executing function
-     * @returns {Array}
-     */
-  map(fn, thisArg) {
-    if (thisArg) fn = fn.bind(thisArg);
-    const arr = new Array(this.size);
-    let i = 0;
-    for (const [key, val] of this) arr[i++] = fn(val, key, this);
-    return arr;
-  }
-
-  /**
-     * Identical to
-     * [Array.some()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
-     * @param {Function} fn Function used to test (should return a boolean)
-     * @param {Object} [thisArg] Value to use as `this` when executing function
-     * @returns {boolean}
-     */
-  some(fn, thisArg) {
-    if (thisArg) fn = fn.bind(thisArg);
-    for (const [key, val] of this) {
-      if (fn(val, key, this)) return true;
-    }
-    return false;
-  }
-
-  /**
-     * Identical to
-     * [Array.every()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every).
-     * @param {Function} fn Function used to test (should return a boolean)
-     * @param {Object} [thisArg] Value to use as `this` when executing function
-     * @returns {boolean}
-     */
-  every(fn, thisArg) {
-    if (thisArg) fn = fn.bind(thisArg);
-    for (const [key, val] of this) {
-      if (!fn(val, key, this)) return false;
-    }
-    return true;
-  }
-
-  /**
-     * Identical to
-     * [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce).
-     * @param {Function} fn Function used to reduce, taking four arguments; `accumulator`, `currentValue`, `currentKey`,
-     * and `enmap`
-     * @param {*} [initialValue] Starting value for the accumulator
-     * @returns {*}
-     */
-  reduce(fn, initialValue) {
-    let accumulator;
-    if (typeof initialValue !== 'undefined') {
-      accumulator = initialValue;
-      for (const [key, val] of this) accumulator = fn(accumulator, val, key, this);
-    } else {
-      let first = true;
-      for (const [key, val] of this) {
-        if (first) {
-          accumulator = val;
-          first = false;
-          continue;
-        }
-        accumulator = fn(accumulator, val, key, this);
-      }
-    }
-    return accumulator;
-  }
-
-  /**
-     * Creates an identical shallow copy of this Enmap.
-     * @returns {Enmap}
-     * @example const newColl = someColl.clone();
-     */
-  clone() {
-    return new this.constructor(this);
-  }
-
-  /**
-     * Combines this Enmap with others into a new Enmap. None of the source Enmaps are modified.
-     * @param {...Enmap} enmaps Enmaps to merge
-     * @returns {Enmap}
-     * @example const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl);
-     */
-  concat(...enmaps) {
-    const newColl = this.clone();
-    for (const coll of enmaps) {
-      for (const [key, val] of coll) newColl.set(key, val);
-    }
-    return newColl;
-  }
-
-  /**
-     * Checks if this Enmap shares identical key-value pairings with another.
-     * This is different to checking for equality using equal-signs, because
-     * the Enmaps may be different objects, but contain the same data.
-     * @param {Enmap} enmap Enmap to compare with
-     * @returns {boolean} Whether the Enmaps have identical contents
-     */
-  equals(enmap) {
-    if (!enmap) return false;
-    if (this === enmap) return true;
-    if (this.size !== enmap.size) return false;
-    return !this.find((value, key) => {
-      const testVal = enmap.get(key);
-      return testVal !== value || (testVal === undefined && !enmap.has(key));
-    });
-  }
-
-}
-
-module.exports = Enmap;
-
-/**
- * @external forEach
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach}
- */
-
-/**
- * @external keys
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys}
- */
-
-/**
- * @external values
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values}
- */
diff --git a/node_modules/lodash/package.json b/node_modules/lodash/package.json
index c69b5fee..11db3d90 100644
--- a/node_modules/lodash/package.json
+++ b/node_modules/lodash/package.json
@@ -1,5 +1,5 @@
 {
-  "_from": "lodash@^4.17.10",
+  "_from": "lodash@^4.17.5",
   "_id": "lodash@4.17.10",
   "_inBundle": false,
   "_integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
@@ -8,20 +8,22 @@
   "_requested": {
     "type": "range",
     "registry": true,
-    "raw": "lodash@^4.17.10",
+    "raw": "lodash@^4.17.5",
     "name": "lodash",
     "escapedName": "lodash",
-    "rawSpec": "^4.17.10",
+    "rawSpec": "^4.17.5",
     "saveSpec": null,
-    "fetchSpec": "^4.17.10"
+    "fetchSpec": "^4.17.5"
   },
   "_requiredBy": [
-    "/enmap"
+    "/eslint",
+    "/inquirer",
+    "/table"
   ],
   "_resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
   "_shasum": "1b7793cf7259ea38fb3661d4d38b3260af8ae4e7",
-  "_spec": "lodash@^4.17.10",
-  "_where": "/Users/loic/Documents/DiscordJS/node_modules/enmap",
+  "_spec": "lodash@^4.17.5",
+  "_where": "/Users/loic/Documents/DiscordBotV2/node_modules/eslint",
   "author": {
     "name": "John-David Dalton",
     "email": "john.david.dalton@gmail.com",
diff --git a/node_modules/long/package.json b/node_modules/long/package.json
index 1d04102e..bd1cb4f5 100644
--- a/node_modules/long/package.json
+++ b/node_modules/long/package.json
@@ -21,7 +21,7 @@
   "_resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
   "_shasum": "9a7b71cfb7d361a194ea555241c92f7468d5bf28",
   "_spec": "long@^4.0.0",
-  "_where": "/Users/loic/Documents/DiscordJS/node_modules/discord.js",
+  "_where": "/Users/loic/Documents/DiscordBotV2/node_modules/discord.js",
   "author": {
     "name": "Daniel Wirtz",
     "email": "dcode@dcode.io"
diff --git a/node_modules/prism-media/package.json b/node_modules/prism-media/package.json
index 191a5d5d..2d04e43c 100644
--- a/node_modules/prism-media/package.json
+++ b/node_modules/prism-media/package.json
@@ -21,7 +21,7 @@
   "_resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.3.tgz",
   "_shasum": "8842d4fae804f099d3b48a9a38e3c2bab6f4855b",
   "_spec": "prism-media@^0.0.3",
-  "_where": "/Users/loic/Documents/DiscordJS/node_modules/discord.js",
+  "_where": "/Users/loic/Documents/DiscordBotV2/node_modules/discord.js",
   "author": {
     "name": "Amish Shah",
     "email": "amishshah.2k@gmail.com"
diff --git a/node_modules/safe-buffer/package.json b/node_modules/safe-buffer/package.json
index c8b6a762..ff436f2f 100644
--- a/node_modules/safe-buffer/package.json
+++ b/node_modules/safe-buffer/package.json
@@ -21,7 +21,7 @@
   "_resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
   "_shasum": "991ec69d296e0313747d59bdfd2b745c35f8828d",
   "_spec": "safe-buffer@~5.1.0",
-  "_where": "/Users/loic/Documents/DiscordJS/node_modules/ws",
+  "_where": "/Users/loic/Documents/DiscordBotV2/node_modules/ws",
   "author": {
     "name": "Feross Aboukhadijeh",
     "email": "feross@feross.org",
diff --git a/node_modules/snekfetch/package.json b/node_modules/snekfetch/package.json
index 6d1a442e..4c6ea933 100644
--- a/node_modules/snekfetch/package.json
+++ b/node_modules/snekfetch/package.json
@@ -21,7 +21,7 @@
   "_resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.6.4.tgz",
   "_shasum": "d13e80a616d892f3d38daae4289f4d258a645120",
   "_spec": "snekfetch@^3.6.4",
-  "_where": "/Users/loic/Documents/DiscordJS/node_modules/discord.js",
+  "_where": "/Users/loic/Documents/DiscordBotV2/node_modules/discord.js",
   "author": {
     "name": "Gus Caplan",
     "email": "me@gus.host"
diff --git a/node_modules/tweetnacl/package.json b/node_modules/tweetnacl/package.json
index 5f252501..19798b38 100644
--- a/node_modules/tweetnacl/package.json
+++ b/node_modules/tweetnacl/package.json
@@ -21,7 +21,7 @@
   "_resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.0.tgz",
   "_shasum": "713d8b818da42068740bf68386d0479e66fc8a7b",
   "_spec": "tweetnacl@^1.0.0",
-  "_where": "/Users/loic/Documents/DiscordJS/node_modules/discord.js",
+  "_where": "/Users/loic/Documents/DiscordBotV2/node_modules/discord.js",
   "author": {
     "name": "TweetNaCl-js contributors"
   },
diff --git a/node_modules/ws/package.json b/node_modules/ws/package.json
index ac3fc990..37874f31 100644
--- a/node_modules/ws/package.json
+++ b/node_modules/ws/package.json
@@ -21,7 +21,7 @@
   "_resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz",
   "_shasum": "a979b5d7d4da68bf54efe0408967c324869a7289",
   "_spec": "ws@^4.0.0",
-  "_where": "/Users/loic/Documents/DiscordJS/node_modules/discord.js",
+  "_where": "/Users/loic/Documents/DiscordBotV2/node_modules/discord.js",
   "author": {
     "name": "Einar Otto Stangvik",
     "email": "einaros@gmail.com",
diff --git a/package-lock.json b/package-lock.json
index 32d1ee6c..6bdcd5a8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,14 +1,227 @@
 {
-  "name": "DiscordJS",
+  "name": "DiscordBotV2",
   "version": "1.0.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
+      "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
+      "requires": {
+        "@babel/highlight": "^7.0.0"
+      }
+    },
+    "@babel/highlight": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
+      "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
+      "requires": {
+        "chalk": "^2.0.0",
+        "esutils": "^2.0.2",
+        "js-tokens": "^4.0.0"
+      }
+    },
+    "acorn": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.2.tgz",
+      "integrity": "sha512-cJrKCNcr2kv8dlDnbw+JPUGjHZzo4myaxOLmpOX8a+rgX94YeTcTMv/LFJUSByRpc+i4GgVnnhLxvMu/2Y+rqw=="
+    },
+    "acorn-jsx": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz",
+      "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==",
+      "requires": {
+        "acorn": "^5.0.3"
+      }
+    },
+    "ajv": {
+      "version": "6.5.3",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz",
+      "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==",
+      "requires": {
+        "fast-deep-equal": "^2.0.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      }
+    },
+    "ajv-keywords": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
+      "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="
+    },
+    "ansi-escapes": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
+      "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw=="
+    },
+    "ansi-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+      "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+    },
+    "ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "requires": {
+        "color-convert": "^1.9.0"
+      }
+    },
+    "argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "requires": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "array-union": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+      "requires": {
+        "array-uniq": "^1.0.1"
+      }
+    },
+    "array-uniq": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
+    },
+    "arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
+    },
     "async-limiter": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
       "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
     },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "caller-path": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
+      "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
+      "requires": {
+        "callsites": "^0.2.0"
+      }
+    },
+    "callsites": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+      "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo="
+    },
+    "chalk": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+      "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+      "requires": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      }
+    },
+    "chardet": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
+    },
+    "circular-json": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+      "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A=="
+    },
+    "cli-cursor": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+      "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+      "requires": {
+        "restore-cursor": "^2.0.0"
+      }
+    },
+    "cli-width": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
+    },
+    "color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "requires": {
+        "color-name": "1.1.3"
+      }
+    },
+    "color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+    },
+    "common-tags": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz",
+      "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw=="
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+    },
+    "cross-spawn": {
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+      "requires": {
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      }
+    },
+    "debug": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+      "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "deep-is": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
+    },
+    "del": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+      "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+      "requires": {
+        "globby": "^5.0.0",
+        "is-path-cwd": "^1.0.0",
+        "is-path-in-cwd": "^1.0.0",
+        "object-assign": "^4.0.1",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0",
+        "rimraf": "^2.2.8"
+      }
+    },
     "discord.js": {
       "version": "11.4.2",
       "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.4.2.tgz",
@@ -21,12 +234,361 @@
         "ws": "^4.0.0"
       }
     },
-    "enmap": {
-      "version": "4.0.12",
-      "resolved": "https://registry.npmjs.org/enmap/-/enmap-4.0.12.tgz",
-      "integrity": "sha512-jvK94Fyk8HtJlYQdW/XW4pNfUzxzsjF7UlaC1MalpZq944ti9HL+XcRLFTmM1/Px/9dZxGeUPLMBUhAO0/S6YA==",
+    "discord.js-commando": {
+      "version": "0.10.0",
+      "resolved": "https://registry.npmjs.org/discord.js-commando/-/discord.js-commando-0.10.0.tgz",
+      "integrity": "sha1-v6mL8zEIcDdvPHoNe3Nqaj5dCg8=",
       "requires": {
-        "lodash": "^4.17.10"
+        "common-tags": "^1.0.0",
+        "escape-string-regexp": "^1.0.0",
+        "require-all": "^2.0.0"
+      }
+    },
+    "doctrine": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+      "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+      "requires": {
+        "esutils": "^2.0.2"
+      }
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+    },
+    "eslint": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.5.0.tgz",
+      "integrity": "sha512-m+az4vYehIJgl1Z0gb25KnFXeqQRdNreYsei1jdvkd9bB+UNQD3fsuiC2AWSQ56P+/t++kFSINZXFbfai+krOw==",
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "ajv": "^6.5.3",
+        "chalk": "^2.1.0",
+        "cross-spawn": "^6.0.5",
+        "debug": "^3.1.0",
+        "doctrine": "^2.1.0",
+        "eslint-scope": "^4.0.0",
+        "eslint-utils": "^1.3.1",
+        "eslint-visitor-keys": "^1.0.0",
+        "espree": "^4.0.0",
+        "esquery": "^1.0.1",
+        "esutils": "^2.0.2",
+        "file-entry-cache": "^2.0.0",
+        "functional-red-black-tree": "^1.0.1",
+        "glob": "^7.1.2",
+        "globals": "^11.7.0",
+        "ignore": "^4.0.6",
+        "imurmurhash": "^0.1.4",
+        "inquirer": "^6.1.0",
+        "is-resolvable": "^1.1.0",
+        "js-yaml": "^3.12.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.3.0",
+        "lodash": "^4.17.5",
+        "minimatch": "^3.0.4",
+        "mkdirp": "^0.5.1",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.8.2",
+        "path-is-inside": "^1.0.2",
+        "pluralize": "^7.0.0",
+        "progress": "^2.0.0",
+        "regexpp": "^2.0.0",
+        "require-uncached": "^1.0.3",
+        "semver": "^5.5.1",
+        "strip-ansi": "^4.0.0",
+        "strip-json-comments": "^2.0.1",
+        "table": "^4.0.3",
+        "text-table": "^0.2.0"
+      }
+    },
+    "eslint-scope": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
+      "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==",
+      "requires": {
+        "esrecurse": "^4.1.0",
+        "estraverse": "^4.1.1"
+      }
+    },
+    "eslint-utils": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
+      "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q=="
+    },
+    "eslint-visitor-keys": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ=="
+    },
+    "espree": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz",
+      "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==",
+      "requires": {
+        "acorn": "^5.6.0",
+        "acorn-jsx": "^4.1.1"
+      }
+    },
+    "esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
+    },
+    "esquery": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
+      "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
+      "requires": {
+        "estraverse": "^4.0.0"
+      }
+    },
+    "esrecurse": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+      "requires": {
+        "estraverse": "^4.1.0"
+      }
+    },
+    "estraverse": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+      "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
+    },
+    "esutils": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
+    },
+    "external-editor": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
+      "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==",
+      "requires": {
+        "chardet": "^0.7.0",
+        "iconv-lite": "^0.4.24",
+        "tmp": "^0.0.33"
+      }
+    },
+    "fast-deep-equal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
+    },
+    "fast-json-stable-stringify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+    },
+    "fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
+    },
+    "figures": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+      "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+      "requires": {
+        "escape-string-regexp": "^1.0.5"
+      }
+    },
+    "file-entry-cache": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
+      "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+      "requires": {
+        "flat-cache": "^1.2.1",
+        "object-assign": "^4.0.1"
+      }
+    },
+    "flat-cache": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
+      "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+      "requires": {
+        "circular-json": "^0.3.1",
+        "del": "^2.0.2",
+        "graceful-fs": "^4.1.2",
+        "write": "^0.2.1"
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+    },
+    "functional-red-black-tree": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+      "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
+    },
+    "glob": {
+      "version": "7.1.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "globals": {
+      "version": "11.7.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz",
+      "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg=="
+    },
+    "globby": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+      "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+      "requires": {
+        "array-union": "^1.0.1",
+        "arrify": "^1.0.0",
+        "glob": "^7.0.3",
+        "object-assign": "^4.0.1",
+        "pify": "^2.0.0",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.1.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
+    },
+    "has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+    },
+    "iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      }
+    },
+    "ignore": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+      "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+    },
+    "inquirer": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz",
+      "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==",
+      "requires": {
+        "ansi-escapes": "^3.0.0",
+        "chalk": "^2.0.0",
+        "cli-cursor": "^2.1.0",
+        "cli-width": "^2.0.0",
+        "external-editor": "^3.0.0",
+        "figures": "^2.0.0",
+        "lodash": "^4.17.10",
+        "mute-stream": "0.0.7",
+        "run-async": "^2.2.0",
+        "rxjs": "^6.1.0",
+        "string-width": "^2.1.0",
+        "strip-ansi": "^4.0.0",
+        "through": "^2.3.6"
+      }
+    },
+    "is-fullwidth-code-point": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+    },
+    "is-path-cwd": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+      "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0="
+    },
+    "is-path-in-cwd": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
+      "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+      "requires": {
+        "is-path-inside": "^1.0.0"
+      }
+    },
+    "is-path-inside": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+      "requires": {
+        "path-is-inside": "^1.0.1"
+      }
+    },
+    "is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
+    },
+    "is-resolvable": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
+      "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg=="
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+    },
+    "js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+    },
+    "js-yaml": {
+      "version": "3.12.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
+      "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
+      "requires": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      }
+    },
+    "json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+    },
+    "json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+      "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
+    },
+    "levn": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+      "requires": {
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2"
       }
     },
     "lodash": {
@@ -39,26 +601,370 @@
       "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
       "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
     },
+    "mimic-fn": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "minimist": {
+      "version": "0.0.8",
+      "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+    },
+    "mkdirp": {
+      "version": "0.5.1",
+      "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "requires": {
+        "minimist": "0.0.8"
+      }
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+    },
+    "mute-stream": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+      "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
+    },
+    "natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "onetime": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+      "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+      "requires": {
+        "mimic-fn": "^1.0.0"
+      }
+    },
+    "optionator": {
+      "version": "0.8.2",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+      "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+      "requires": {
+        "deep-is": "~0.1.3",
+        "fast-levenshtein": "~2.0.4",
+        "levn": "~0.3.0",
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2",
+        "wordwrap": "~1.0.0"
+      }
+    },
+    "os-tmpdir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+    },
+    "path-is-inside": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+      "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
+    },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+    },
+    "pify": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+    },
+    "pinkie": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+    },
+    "pinkie-promise": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+      "requires": {
+        "pinkie": "^2.0.0"
+      }
+    },
+    "pluralize": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
+      "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow=="
+    },
+    "prelude-ls": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
+    },
     "prism-media": {
       "version": "0.0.3",
       "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.3.tgz",
       "integrity": "sha512-c9KkNifSMU/iXT8FFTaBwBMr+rdVcN+H/uNv1o+CuFeTThNZNTOrQ+RgXA1yL/DeLk098duAeRPP3QNPNbhxYQ=="
     },
+    "progress": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
+      "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8="
+    },
+    "punycode": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+    },
+    "regexpp": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz",
+      "integrity": "sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA=="
+    },
+    "require-all": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/require-all/-/require-all-2.2.0.tgz",
+      "integrity": "sha1-tEIMIzrAKC0P9Jsnf7iAqLXeCJQ="
+    },
+    "require-uncached": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+      "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
+      "requires": {
+        "caller-path": "^0.1.0",
+        "resolve-from": "^1.0.0"
+      }
+    },
+    "resolve-from": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
+      "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY="
+    },
+    "restore-cursor": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+      "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+      "requires": {
+        "onetime": "^2.0.0",
+        "signal-exit": "^3.0.2"
+      }
+    },
+    "rimraf": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+      "requires": {
+        "glob": "^7.0.5"
+      }
+    },
+    "run-async": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+      "requires": {
+        "is-promise": "^2.1.0"
+      }
+    },
+    "rxjs": {
+      "version": "6.3.2",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.2.tgz",
+      "integrity": "sha512-hV7criqbR0pe7EeL3O66UYVg92IR0XsA97+9y+BWTePK9SKmEI5Qd3Zj6uPnGkNzXsBywBQWTvujPl+1Kn9Zjw==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
       "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
     },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+    },
+    "semver": {
+      "version": "5.5.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
+      "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw=="
+    },
+    "shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+      "requires": {
+        "shebang-regex": "^1.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+    },
+    "signal-exit": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+    },
+    "slice-ansi": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
+      "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+      "requires": {
+        "is-fullwidth-code-point": "^2.0.0"
+      }
+    },
     "snekfetch": {
       "version": "3.6.4",
       "resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.6.4.tgz",
       "integrity": "sha512-NjxjITIj04Ffqid5lqr7XdgwM7X61c/Dns073Ly170bPQHLm6jkmelye/eglS++1nfTWktpP6Y2bFXjdPlQqdw=="
     },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+    },
+    "string-width": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+      "requires": {
+        "is-fullwidth-code-point": "^2.0.0",
+        "strip-ansi": "^4.0.0"
+      }
+    },
+    "strip-ansi": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+      "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+      "requires": {
+        "ansi-regex": "^3.0.0"
+      }
+    },
+    "strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
+    },
+    "supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "requires": {
+        "has-flag": "^3.0.0"
+      }
+    },
+    "table": {
+      "version": "4.0.3",
+      "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz",
+      "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==",
+      "requires": {
+        "ajv": "^6.0.1",
+        "ajv-keywords": "^3.0.0",
+        "chalk": "^2.1.0",
+        "lodash": "^4.17.4",
+        "slice-ansi": "1.0.0",
+        "string-width": "^2.1.1"
+      }
+    },
+    "text-table": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+      "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
+    },
+    "through": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+    },
+    "tmp": {
+      "version": "0.0.33",
+      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+      "requires": {
+        "os-tmpdir": "~1.0.2"
+      }
+    },
+    "tslib": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+      "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
+    },
     "tweetnacl": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.0.tgz",
       "integrity": "sha1-cT2LgY2kIGh0C/aDhtBHnmb8ins="
     },
+    "type-check": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+      "requires": {
+        "prelude-ls": "~1.1.2"
+      }
+    },
+    "uri-js": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+      "requires": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "wordwrap": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+    },
+    "write": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
+      "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+      "requires": {
+        "mkdirp": "^0.5.1"
+      }
+    },
     "ws": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz",
diff --git a/package.json b/package.json
index 8ed9908b..33ecf231 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
 {
-  "name": "DiscordJS",
+  "name": "DiscordBotV2",
   "version": "1.0.0",
   "description": "",
-  "main": "index.js",
+  "main": "hahayesv2.js",
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"
   },
@@ -11,6 +11,7 @@
   "license": "ISC",
   "dependencies": {
     "discord.js": "^11.4.2",
-    "enmap": "^4.0.12"
+    "discord.js-commando": "^0.10.0",
+    "eslint": "^5.5.0"
   }
 }
diff --git a/readme.md b/readme.md
deleted file mode 100644
index fe2af9b3..00000000
--- a/readme.md
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a simple bot for discord built using Discord.js
-This bot can kick people and reply to haha yes
-haha yes
-yes
diff --git a/reply.json b/reply.json
deleted file mode 100644
index 19329435..00000000
--- a/reply.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "lol": "haha yes funi",
-    "haha yes": "haha  yes"
-}
\ No newline at end of file