diff --git a/discord-bot-core/.gitrepo b/discord-bot-core/.gitrepo index 5bb9057..3fc5ad0 100644 --- a/discord-bot-core/.gitrepo +++ b/discord-bot-core/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = git@github.com:benji7425/discord-bot-core.git branch = master - commit = a1a9b3045839d9e7ec594af8271f0d1c57e109d2 + commit = eca149944595a225377defa5b3e61b058001771f parent = 2b4335231ac1ccf4265ada5ce0a84d343021fcd6 method = merge cmdver = 0.3.1 diff --git a/discord-bot-core/BaseGuildData.js b/discord-bot-core/BaseGuildData.js index be70ab2..f4a4e8e 100644 --- a/discord-bot-core/BaseGuildData.js +++ b/discord-bot-core/BaseGuildData.js @@ -1,5 +1,9 @@ -module.exports = class BaseGuildData { - constructor(id) { - this.id = id; +const Camo = require("camo"); + +module.exports = class BaseGuildData extends Camo.Document { + constructor() { + super(); + + this.id = Number; } }; \ No newline at end of file diff --git a/discord-bot-core/Client.js b/discord-bot-core/Client.js index c175ae7..42663ff 100644 --- a/discord-bot-core/Client.js +++ b/discord-bot-core/Client.js @@ -1,13 +1,22 @@ -const FileSystem = require("fs"); -const Discord = require("discord.js"); -const JsonFile = require("jsonfile"); -const RequireAll = require("require-all"); const CoreUtil = require("./Util.js"); -const HandleMessage = require("./HandleMessage.js"); -// @ts-ignore +const Camo = require("camo"); +const CronJob = require("cron").CronJob; +const Discord = require("discord.js"); +const HandleGuildMessage = require("./HandleGuildMessage"); const InternalConfig = require("./internal-config.json"); +const RequireAll = require("require-all"); +const Util = require("./Util.js"); + +let neDB; module.exports = class Client extends Discord.Client { + /** + * Construct a new Discord.Client with some added functionality + * @param {string} token bot token + * @param {string} dataFile location for json data file + * @param {string} commandsDir location of dir containing commands .js files + * @param {*} guildDataModel GuildData model to be used for app; must extend BaseGuildData + */ constructor(token, dataFile, commandsDir, guildDataModel) { super(); @@ -17,80 +26,59 @@ module.exports = class Client extends Discord.Client { this.guildDataModel = guildDataModel; this.commands = RequireAll(this.commandsDir); - this.guildsData = FileSystem.existsSync(this.dataFile) ? this.fromJSON(JsonFile.readFileSync(this.dataFile)) : {}; - this.on("ready", this.onReady); - this.on("message", this.onMessage); - this.on("debug", this.onDebug); - this.on("guildCreate", this.onGuildCreate); - this.on("guildDelete", this.onGuildDelete); - process.on("uncaughtException", err => this.onUnhandledException(this, err)); + this.on("ready", this._onReady); + this.on("message", this._onMessage); + this.on("debug", this._onDebug); + this.on("guildCreate", this._onGuildCreate); + this.on("guildDelete", this._onGuildDelete); } bootstrap() { - this.beforeLogin(); - this.login(this._token); + Camo.connect("nedb://guilds-data").then(db => { + neDB = db; + + this.emit("beforeLogin"); + this.login(this._token); + }); } - beforeLogin() { - setInterval(() => this.writeFile(), InternalConfig.saveIntervalSec * 1000); - this.emit("beforeLogin"); - } - - onReady() { + _onReady() { this.user.setGame(InternalConfig.website.replace(/^https?:\/\//, "")); CoreUtil.dateLog(`Registered bot ${this.user.username}`); - for (let guildID of Object.keys(this.guildsData)) - if (!this.guilds.get(guildID)) - delete this.guildsData[guildID]; + new CronJob(InternalConfig.dbCompactionSchedule, () => compactCollections(), null, true); } - onMessage(message) { - if (message.channel.type === "text" && message.member) { - if (!this.guildsData[message.guild.id]) - this.guildsData[message.guild.id] = new this.guildDataModel({ id: message.guild.id }); - HandleMessage(this, message, this.commands, this.guildsData[message.guild.id]); - } + _onMessage(message) { + if (message.channel.type === "text" && message.member) + HandleGuildMessage(this, message, this.commands); } - onDebug(info) { + _onDebug(info) { info = info.replace(/Authenticated using token [^ ]+/, "Authenticated using token [redacted]"); if (!InternalConfig.debugIgnores.some(x => info.startsWith(x))) CoreUtil.dateDebug(info); } - onGuildCreate(guild) { + _onGuildCreate(guild) { CoreUtil.dateLog(`Added to guild ${guild.name}`); } - onGuildDelete(guild) { + _onGuildDelete(guild) { + this.guildDataModel.findOneAndDelete({ id: guild.id }); + CoreUtil.dateLog(`Removed from guild ${guild.name}, removing data for this guild`); - delete this.guildsData[guild.id]; - this.writeFile(); } +}; - onUnhandledException(client, err) { - CoreUtil.dateError(err); - CoreUtil.dateLog("Destroying existing client..."); - client.destroy().then(() => { - CoreUtil.dateLog("Client destroyed, recreating..."); - setTimeout(() => client.login(client._token), InternalConfig.reconnectTimeout); - }); - } - - writeFile() { - JsonFile.writeFile( - this.dataFile, - this.guildsData, - err => { if (err) CoreUtil.dateError(`Error writing data file! ${err.message || err}`); }); - } - - fromJSON(json) { - const guildsData = Object.keys(json); - guildsData.forEach(guildID => { - json[guildID] = new this.guildDataModel(json[guildID]); - }); - return json; - } -}; \ No newline at end of file +function compactCollections() { + /*I realise it is a bit of a cheat to just access _collections in this manner, but in the absence of + camo actually having any kind of solution for this it's the easiest method I could come up with. + Maybe at some point in future I should fork camo and add this feature. The compaction function is NeDB only + and camo is designed to work with both NeDB and MongoDB, which is presumably why it doesn't alraedy exist */ + for (let collectionName of Object.keys(neDB._collections)) + neDB._collections[collectionName].persistence.compactDatafile(); + + Util.dateLog("Executed compaction on loaded NeDB collections"); +} \ No newline at end of file diff --git a/discord-bot-core/HandleGuildMessage.js b/discord-bot-core/HandleGuildMessage.js new file mode 100644 index 0000000..404f8eb --- /dev/null +++ b/discord-bot-core/HandleGuildMessage.js @@ -0,0 +1,50 @@ +const RequireAll = require("require-all"); + +const internalCommands = RequireAll(__dirname + "/core-commands"); + +function handleGuildMessage(client, message, commands) { + if (isCommand(message)) + client.guildDataModel.findOne({ id: message.guild.id }) + .then(guildData => + handleGuildCommand( + client, + message, + Object.assign({}, internalCommands, commands), + guildData || client.guildDataModel.create({ id: message.guild.id }) + )); +} + +function handleGuildCommand(client, message, commands, guildData) { + const { botName, isMemberAdmin, params, command } = parseDetails(message, commands); + + if (params.length < command.expectedParamCount) + message.reply(`Incorrect syntax!\n**Expected:** *${botName} ${command.syntax}*\n**Need help?** *${botName} help*`); + + else if (isMemberAdmin || !command.admin) + command.invoke({ message, params, guildData, client, commands, isMemberAdmin }) + .then(response => { + guildData.save(); + if (response) message.reply(response); + }) + .catch(err => err && message.reply(err)); +} + +function parseDetails(message, commands) { + const split = message.content.split(/ +/); + const commandName = Object.keys(commands).find(x => + /**/ commands[x].name.toLowerCase() === (split[1] || "").toLowerCase()); + + return { + botName: "@" + (message.guild.me.nickname || message.guild.me.user.username), + isMemberAdmin: message.member.permissions.has("ADMINISTRATOR"), + params: split.slice(2, split.length), + command: commands[commandName] + }; +} + +function isCommand(message) { + //criteria for a command is bot being mentioned + return new RegExp(`^<@!?${/[0-9]{18}/.exec(message.guild.me.toString())[0]}>`).exec(message.content); +} + +module.exports = handleGuildMessage; \ No newline at end of file diff --git a/discord-bot-core/HandleMessage.js b/discord-bot-core/HandleMessage.js deleted file mode 100644 index ca6bccd..0000000 --- a/discord-bot-core/HandleMessage.js +++ /dev/null @@ -1,72 +0,0 @@ -const Discord = require("discord.js"); -// @ts-ignore -const ParentPackageJSON = require("../package.json"); -// @ts-ignore -const InternalConfig = require("./internal-config.json"); - -function handleMessage(client, message, commands, guildData) { - if (!message.content.startsWith(message.guild.me.toString()) //criteria for a command is the bot being tagged - && !message.content.startsWith(message.guild.me.toString().replace("!", ""))) //hacky fix for android mentions not including an exclamation mark - return; - - const botName = "@" + (message.guild.me.nickname || message.guild.me.user.username), - isMemberAdmin = message.member.permissions.has("ADMINISTRATOR"), - split = message.content.split(/ +/), - params = split.slice(2, split.length), - command = commands[Object.keys(commands).find(x => commands[x].name.toLowerCase() === (split[1] || "").toLowerCase())]; - - if (!command) - handleInternalCommand(message, split, commands, isMemberAdmin); - else if (params.length < command.expectedParamCount) - message.reply(`Incorrect syntax!\n**Expected:** *${botName} ${command.syntax}*\n**Need help?** *${botName} help*`); - else if (isMemberAdmin || !command.admin) - command.invoke({ message, params, guildData, client }) - .then(response => { - client.writeFile(); - if (response) - message.reply(response); - }) - .catch(err => { - if (err) - message.reply(err); - }); -} - -function handleInternalCommand(message, split, commands, isMemberAdmin) { - if (!split[1]) - return; - - if (split[1].toLowerCase() === "version") - message.reply(`${ParentPackageJSON.name} v${ParentPackageJSON.version}`); - else if (split[1].toLowerCase() === "help") { - const helpCommands = [...Object.keys(commands).map(x => commands[x])]; - helpCommands.push({ - name: "version", - description: "Return version number", - syntax: "version" - }); - helpCommands.push({ - name: "help", - description: "View help", - syntax: "help" - }); - message.reply(createHelpEmbed(ParentPackageJSON.name, helpCommands, isMemberAdmin)); - } -} - -function createHelpEmbed(name, commands, userIsAdmin) { - const commandsArr = Object.keys(commands).map(x => commands[x]).filter(x => userIsAdmin || !x.admin); - - const embed = new Discord.RichEmbed().setTitle(`__Help__ for ${(ParentPackageJSON.name + "").replace("discord-bot-", "")}`); - - commandsArr.forEach(command => { - embed.addField(command.name, `${command.description}\n**Usage:** *${name} ${command.syntax}*${userIsAdmin && command.admin ? "\n***Admin only***" : ""}`); - }); - - embed.addField("__Need more help?__", `[Visit my website](${InternalConfig.website}) or [Join my Discord](${InternalConfig.discordInvite})`, true); - - return { embed }; -} - - -module.exports = handleMessage; \ No newline at end of file diff --git a/discord-bot-core/Util.js b/discord-bot-core/Util.js index b56b9c3..0cd6c53 100644 --- a/discord-bot-core/Util.js +++ b/discord-bot-core/Util.js @@ -1,5 +1,6 @@ +// @ts-ignore +const InternalConfig = require("./internal-config.json"); const Console = require("console"); -const Discord = require("discord.js"); const SimpleFileWriter = require("simple-file-writer"); const logWriter = new SimpleFileWriter("./console.log"); @@ -8,15 +9,21 @@ const debugLogWriter = new SimpleFileWriter("./debug.log"); function ask(client, textChannel, member, question) { //return a promise which will resolve once the user next sends a message in this textChannel return new Promise((resolve, reject) => { + const cancelAsk = () => { + client.removeListener("message", handler); + textChannel.send("Response to question timed out"); + }; + + const askTimeout = setTimeout(cancelAsk, InternalConfig.askTimeout); + const handler = responseMessage => { - if (responseMessage.channel.id === textChannel.id && - responseMessage.member.id === member.id) { - client.removeListener("message", handler); + if (responseMessage.channel.id === textChannel.id && responseMessage.member.id === member.id) { + clearTimeout(askTimeout); resolve(responseMessage); } }; - client.on("message", handler); + client.once("message", handler); textChannel.send(member.toString() + " " + question).catch(reject); }); diff --git a/discord-bot-core/core-commands/help.js b/discord-bot-core/core-commands/help.js new file mode 100644 index 0000000..356244d --- /dev/null +++ b/discord-bot-core/core-commands/help.js @@ -0,0 +1,30 @@ +const Command = require("../Command.js"); +const Discord = require("discord.js"); +const InternalConfig = require("../internal-config.json"); +const ParentPackageJson = require("../../package.json"); + +module.exports = new Command({ + name: "help", + description: "Display available commands with descriptions", + syntax: "help", + admin: false, + invoke +}); + +function invoke({ commands, isMemberAdmin }) { + return Promise.resolve(createHelpEmbed(ParentPackageJson.name, commands, isMemberAdmin)); +} + +function createHelpEmbed(name, commands, userIsAdmin) { + const commandsArr = Object.keys(commands).map(x => commands[x]).filter(x => userIsAdmin || !x.admin); + + const embed = new Discord.RichEmbed().setTitle(`__${(ParentPackageJson.name + "").replace("discord-bot-", "")} help__`); + + commandsArr.forEach(command => { + embed.addField(command.name, `${command.description}\n**Usage:** *${name} ${command.syntax}*${userIsAdmin && command.admin ? "\n***Admin only***" : ""}`); + }); + + embed.addField("__Need more help?__", `[Visit my website](${InternalConfig.website}) or [Join my Discord](${InternalConfig.discordInvite})`, true); + + return { embed }; +} \ No newline at end of file diff --git a/discord-bot-core/core-commands/version.js b/discord-bot-core/core-commands/version.js new file mode 100644 index 0000000..b64ac57 --- /dev/null +++ b/discord-bot-core/core-commands/version.js @@ -0,0 +1,14 @@ +const Command = require("../Command.js"); +const ParentPackageJson = require("../../package.json"); + +module.exports = new Command({ + name: "version", + description: "Return version number", + syntax: "version", + admin: false, + invoke +}); + +function invoke() { + return Promise.resolve(ParentPackageJson.version); +} \ No newline at end of file diff --git a/discord-bot-core/internal-config.json b/discord-bot-core/internal-config.json index 999879a..88fc5ec 100644 --- a/discord-bot-core/internal-config.json +++ b/discord-bot-core/internal-config.json @@ -1,11 +1,10 @@ { - "saveIntervalSec": 60, + "dbCompactionSchedule": "0 0 0,3,6,9 * * *", "website": "https://benji7425.github.io", "discordInvite": "https://discord.gg/SSkbwSJ", - "defaultDMResponse": "This bot does not have any handling for direct messages. To learn more or get help please visit %s, or join my Discord server here: %s", - "reconnectTimeout": 5000, - "debugIgnores":[ + "debugIgnores": [ "[ws] [connection] Sending a heartbeat", "[ws] [connection] Heartbeat acknowledged" - ] + ], + "askTimeout": 60000 } \ No newline at end of file diff --git a/discord-bot-core/package-lock.json b/discord-bot-core/package-lock.json new file mode 100644 index 0000000..18919cf --- /dev/null +++ b/discord-bot-core/package-lock.json @@ -0,0 +1,420 @@ +{ + "name": "discord-bot-core", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "acorn": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", + "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ=" + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ast-types": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.8.15.tgz", + "integrity": "sha1-ju8IJ/BN/w7IhXupJavj/qYZTlI=" + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, + "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==" + }, + "base62": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz", + "integrity": "sha1-e0F0wvlESXU7EcJlHAg9qEGnsIQ=" + }, + "binary-search-tree": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/binary-search-tree/-/binary-search-tree-0.2.5.tgz", + "integrity": "sha1-fbs7IQ/coIJFDa0jNMMErzm9x4Q=", + "requires": { + "underscore": "1.4.4" + } + }, + "bson": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz", + "integrity": "sha1-5louPHUH/63kEJvHV1p25Q+NqRU=", + "optional": true + }, + "camo": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/camo/-/camo-0.12.3.tgz", + "integrity": "sha1-NuKKWV2c5vgG6tEy2+CLI86T+Rs=", + "requires": { + "depd": "1.1.0", + "lodash": "3.9.3", + "mongodb": "2.0.42", + "nedb": "1.8.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "depd": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=" + }, + "discord.js": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.2.0.tgz", + "integrity": "sha512-IqJoACKH7hGXuewvNHvaeWmdetAU8IRHkfTTmRbihOQkwzaRaJdaGWDcUXQIswEEFX40W8B6w7rhO2xSEB3W+w==", + "requires": { + "long": "3.2.0", + "prism-media": "0.0.1", + "snekfetch": "3.6.1", + "tweetnacl": "1.0.0", + "ws": "3.3.2" + } + }, + "es3ify": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/es3ify/-/es3ify-0.1.4.tgz", + "integrity": "sha1-rZ+l3xrjTz8x4SEbWBiy1RB439E=", + "requires": { + "esprima-fb": "3001.1.0-dev-harmony-fb", + "jstransform": "3.0.0", + "through": "2.3.8" + } + }, + "es6-promise": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-2.1.1.tgz", + "integrity": "sha1-A+jzxyl5KOVHjWqx0GQyUVB73t0=", + "optional": true + }, + "esmangle-evaluator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esmangle-evaluator/-/esmangle-evaluator-1.0.1.tgz", + "integrity": "sha1-Yg2GbvSGGzMR91dm1SqFcrs8YzY=" + }, + "esprima-fb": { + "version": "3001.1.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz", + "integrity": "sha1-t303q8046gt3Qmu4vCkizmtCZBE=" + }, + "falafel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-1.2.0.tgz", + "integrity": "sha1-wY0k71CRF0pJfzGM0ksCaiXN2rQ=", + "requires": { + "acorn": "1.2.2", + "foreach": "2.0.5", + "isarray": "0.0.1", + "object-keys": "1.0.11" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "optional": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inline-process-browser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/inline-process-browser/-/inline-process-browser-1.0.0.tgz", + "integrity": "sha1-RqYbFT3TybFiSxoAYm7bT39BTyI=", + "requires": { + "falafel": "1.2.0", + "through2": "0.6.5" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jstransform": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-3.0.0.tgz", + "integrity": "sha1-olkats7o2XvzvoMNv6IxO4fNZAs=", + "requires": { + "base62": "0.1.1", + "esprima-fb": "3001.1.0-dev-harmony-fb", + "source-map": "0.1.31" + } + }, + "kerberos": { + "version": "0.0.23", + "resolved": "https://registry.npmjs.org/kerberos/-/kerberos-0.0.23.tgz", + "integrity": "sha1-aqRq/bl4bGkZOIzFtAjwEscfD9E=", + "optional": true, + "requires": { + "nan": "2.5.1" + } + }, + "lie": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.0.2.tgz", + "integrity": "sha1-/9oh17uibzd8rYZdNkmy/Izjn+o=", + "requires": { + "es3ify": "0.1.4", + "immediate": "3.0.6", + "inline-process-browser": "1.0.0", + "unreachable-branch-transform": "0.3.0" + } + }, + "localforage": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.5.5.tgz", + "integrity": "sha1-VfwcOoikf2f1+sbxIxsl/xNVZCM=", + "requires": { + "lie": "3.0.2" + } + }, + "lodash": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.9.3.tgz", + "integrity": "sha1-AVnoaDL+/8bWHYUrEqlTuZSWvTI=" + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mongodb": { + "version": "2.0.42", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.0.42.tgz", + "integrity": "sha1-G614E9ByXOLjvVQYDzH67dJNnlM=", + "optional": true, + "requires": { + "es6-promise": "2.1.1", + "mongodb-core": "1.2.10", + "readable-stream": "1.0.31" + } + }, + "mongodb-core": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.2.10.tgz", + "integrity": "sha1-7OFyAb05WmR/uY9Ivo+64Vvgr9k=", + "optional": true, + "requires": { + "bson": "0.4.23", + "kerberos": "0.0.23" + } + }, + "nan": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.5.1.tgz", + "integrity": "sha1-1bAWkSUzJql6K77p5hxV2NYDUeI=", + "optional": true + }, + "nedb": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/nedb/-/nedb-1.8.0.tgz", + "integrity": "sha1-DjUCzYLABNU1WkPJ5VV3vXvZHYg=", + "requires": { + "async": "0.2.10", + "binary-search-tree": "0.2.5", + "localforage": "1.5.5", + "mkdirp": "0.5.1", + "underscore": "1.4.4" + } + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "parent-package-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/parent-package-json/-/parent-package-json-2.0.1.tgz", + "integrity": "sha512-dyHr5bP6k8vNT6oP0i4qsfD/rtUiSruJdv+I/BPr7rRtzYRnCu0v1qcM5yHmubobtvGX38SGe1XF2LBo1fN/xg==" + }, + "prism-media": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.1.tgz", + "integrity": "sha1-o0JcnKvVDRxsAuVDlBoRiVZnvRA=" + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "readable-stream": { + "version": "1.0.31", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz", + "integrity": "sha1-jyUC4LyeOw2huUUgqrtOJgPsr64=", + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "recast": { + "version": "0.10.43", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.10.43.tgz", + "integrity": "sha1-uV1Q9tYHYaX2JS4V2AZ4FoSRzn8=", + "requires": { + "ast-types": "0.8.15", + "esprima-fb": "15001.1001.0-dev-harmony-fb", + "private": "0.1.8", + "source-map": "0.5.7" + }, + "dependencies": { + "esprima-fb": { + "version": "15001.1001.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "require-all": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/require-all/-/require-all-2.2.0.tgz", + "integrity": "sha1-tEIMIzrAKC0P9Jsnf7iAqLXeCJQ=" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "simple-file-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-file-writer/-/simple-file-writer-2.0.0.tgz", + "integrity": "sha1-4oPAoghoptQhnX7aGUwe9eK1gvo=" + }, + "snekfetch": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.6.1.tgz", + "integrity": "sha512-aLEvf1YR440pINb0LEo/SL2Q2s/A26+YEqPlx09A0XpGH7qWp8iqIFFolVILHn2yudWXJne9QWyQu+lzDp+ksQ==" + }, + "source-map": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz", + "integrity": "sha1-n3BNDWnZ4TioG63267T94z0VHGE=", + "requires": { + "amdefine": "1.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "tweetnacl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.0.tgz", + "integrity": "sha1-cT2LgY2kIGh0C/aDhtBHnmb8ins=" + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=" + }, + "unreachable-branch-transform": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unreachable-branch-transform/-/unreachable-branch-transform-0.3.0.tgz", + "integrity": "sha1-2ZzExudG0mSSiEW2EdtUsPNHTKo=", + "requires": { + "esmangle-evaluator": "1.0.1", + "recast": "0.10.43", + "through2": "0.6.5" + } + }, + "ws": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.2.tgz", + "integrity": "sha512-t+WGpsNxhMR4v6EClXS8r8km5ZljKJzyGhJf7goJz9k5Ye3+b5Bvno5rjqPuIBn5mnn5GBb7o8IrIWHxX1qOLQ==", + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.1", + "ultron": "1.1.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } +} diff --git a/discord-bot-core/package.json b/discord-bot-core/package.json index 39aad29..4af9310 100644 --- a/discord-bot-core/package.json +++ b/discord-bot-core/package.json @@ -2,11 +2,12 @@ "version": "1.0.0", "main": "index.js", "dependencies": { + "camo": "0.12.3", "discord.js": "11.2.0", - "jsonfile": "3.0.1", + "nedb": "1.8.0", "parent-package-json": "2.0.1", - "simple-file-writer": "2.0.0", - "require-all": "2.2.0" + "require-all": "2.2.0", + "simple-file-writer": "2.0.0" }, "name": "discord-bot-core", "repository": {