Browse Source

Merge branch 'camo-integration'

shorten
benji7425 3 years ago
parent
commit
fe9781bdfe
  1. 2
      .gitignore
  2. 8
      app/commands/add-feed.js
  3. 2
      app/commands/remove-feed.js
  4. 2
      app/commands/view-feeds.js
  5. 61
      app/index.js
  6. 51
      app/models/feed-data.js
  7. 7
      app/models/guild-data.js
  8. 4
      discord-bot-core/.gitrepo
  9. 10
      discord-bot-core/BaseGuildData.js
  10. 102
      discord-bot-core/Client.js
  11. 50
      discord-bot-core/HandleGuildMessage.js
  12. 72
      discord-bot-core/HandleMessage.js
  13. 15
      discord-bot-core/Util.js
  14. 30
      discord-bot-core/core-commands/help.js
  15. 14
      discord-bot-core/core-commands/version.js
  16. 9
      discord-bot-core/internal-config.json
  17. 427
      discord-bot-core/package-lock.json
  18. 8
      discord-bot-core/package.json
  19. 843
      package-lock.json
  20. 3
      package.json

2
.gitignore

@ -1,5 +1,5 @@
update.sh
guilds.json
guilds-data/*
token.json*
log

8
app/commands/add-feed.js

@ -2,9 +2,8 @@ const Core = require("../../discord-bot-core");
const GetUrls = require("get-urls");
const FeedRead = require("feed-read");
const FeedData = require("../models/feed-data.js");
const GuildData = require("../models/guild-data.js");
// @ts-ignore
const Config = require("../config.json");
const ShortID = require("shortid");
module.exports = new Core.Command({
name: "add-feed",
@ -22,7 +21,8 @@ function invoke({ message, params, guildData, client }) {
return Promise.reject("Please provide both a channel and an RSS feed URL. You can optionally @mention a role also.");
const role = message.mentions.roles.first(),
feedData = new FeedData({
feedData = FeedData.create({
feedID: ShortID.generate(),
url: feedUrl,
channelID: channel.id,
roleID: role ? role.id : null,
@ -30,7 +30,7 @@ function invoke({ message, params, guildData, client }) {
});
return new Promise((resolve, reject) => {
FeedRead(feedUrl, (err, articles) => {
FeedRead(feedUrl, err => {
if (err)
return reject(`Unable to add the feed due to the following error:\n${err.message}`);

2
app/commands/remove-feed.js

@ -9,7 +9,7 @@ module.exports = new Core.Command({
});
function invoke({ message, params, guildData, client }) {
const idx = guildData.feeds.findIndex(feed => feed.id === params[0]);
const idx = guildData.feeds.findIndex(feed => feed.feedID === params[0]);
if (!Number.isInteger(idx))
return Promise.reject("Can't find feed with id " + params[0]);

2
app/commands/view-feeds.js

@ -19,5 +19,5 @@ function invoke({ message, params, guildData, client }) {
let responseStr = guildData.feeds.map(f => f.toString()).slice(startIdx, endIdx).join("\n");
if (guildData.feeds.length > endIdx)
responseStr += `Use *view-feeds ${startIdx + 2}* to view more`;
return Promise.resolve(responseStr);
return Promise.resolve(responseStr || "No feeds configured");
}

61
app/index.js

@ -14,61 +14,38 @@ client.on("beforeLogin", () => {
});
client.on("ready", () => {
doUpgradeJSON();
parseLinksInGuilds()
.then(() => checkFeedsInGuilds());
});
client.on("message", message => {
if (message.channel.type !== "text" || !message.member)
return;
client.on("message", message => {
if (message.channel.type !== "text" || !message.member)
return;
client.guildDataModel.findOne({ guildID: message.guild.id })
.then(guildData => {
if (guildData)
guildData.feeds.forEach(feedData => {
if (message.channel.id === feedData.channelID)
feedData.cachedLinks.push(...GetUrls(message.content));
});
});
const guildData = client.guildsData[message.guild.id];
if (guildData)
guildData.feeds.forEach(feedData => {
if (message.channel.id === feedData.channelID)
feedData.cachedLinks.push(...GetUrls(message.content));
});
});
});
client.bootstrap();
//INTERNAL FUNCTIONS//
function checkFeedsInGuilds() {
client.guilds.forEach(guild => {
const guildData = client.guildsData[guild.id];
if (guildData)
guildData.checkFeeds(guild);
});
client.guildDataModel.find().then(guildDatas =>
guildDatas.forEach(guildData =>
guildData.checkFeeds(client.guilds.get(guildData.guildID))));
}
function parseLinksInGuilds() {
const promises = [];
for (let guildId of client.guilds.keys()) {
const guildData = client.guildsData[guildId];
if (guildData)
promises.push(guildData.cachePastPostedLinks(client.guilds.get(guildId)));
}
return Promise.all(promises);
}
client.guildDataModel.find().then(guildDatas =>
guildDatas.forEach(guildData => promises.push(guildData.cachePastPostedLinks(client.guilds.get(guildData.guildID)))));
function doUpgradeJSON() {
Object.keys(client.guildsData).forEach(id => {
const guild = client.guilds.get(id);
if (!guild)
return;
client.guildsData[id].feeds.forEach(feed => {
if (feed.roleName) {
feed.roleID = client.guilds.get(id).roles.find(x => x.name.toLowerCase() === feed.roleName.toLowerCase()).id;
delete feed.roleName;
}
if (feed.channelName) {
feed.channelID = client.guilds.get(id).channels.find(x => x.name.toLowerCase() === feed.channelName.toLowerCase()).id;
delete feed.channelName;
}
});
});
return Promise.all(promises);
}

51
app/models/feed-data.js

@ -1,36 +1,33 @@
const DiscordUtil = require("../../discord-bot-core").util;
// @ts-ignore
const Camo = require("camo");
const Config = require("../config.json");
const Dns = require("dns"); //for host resolution checking
const Url = require("url"); //for url parsing
const FeedRead = require("feed-read"); //for extracing new links from RSS feeds
const GetUrls = require("get-urls"); //for extracting urls from messages
const ShortID = require("shortid"); //to provide ids for each feed, allowing guilds to remove them
module.exports = class FeedData {
constructor({ id = null, url, channelID, roleID, cachedLinks = null, maxCacheSize, roleName = undefined, channelName = undefined }) {
this.id = id || ShortID.generate();
this.url = url;
this.channelID = channelID;
this.roleID = roleID;
this.cachedLinks = cachedLinks || [];
this.maxCacheSize = maxCacheSize || 10;
//these two are actually deprecated, but need to be here for compatibility with old data files to be upgraded
this.roleName = roleName;
this.channelName = channelName;
this.cachedLinks.push = (...elements) => {
Array.prototype.push.apply(
this.cachedLinks,
elements
.map(el => normaliseUrl(el))
.filter(el => !this.cachedLinks.includes(el))
);
//seeing as new links come in at the end of the array, we need to remove the old links from the beginning
this.cachedLinks.splice(0, this.cachedLinks.length - this.maxCacheSize);
};
module.exports = class FeedData extends Camo.EmbeddedDocument {
constructor() {
super();
this.feedID = String;
this.url = String;
this.channelID = String;
this.roleID = String;
this.cachedLinks = [String];
this.maxCacheSize = Number;
}
cache(...elements) {
Array.prototype.push.apply(
this.cachedLinks,
elements
.map(el => normaliseUrl(el))
.filter(el => !this.cachedLinks.includes(el))
);
//seeing as new links come in at the end of the array, we need to remove the old links from the beginning
this.cachedLinks.splice(0, this.cachedLinks.length - this.maxCacheSize);
}
updatePastPostedLinks(guild) {

7
app/models/guild-data.js

@ -3,9 +3,10 @@ const Core = require("../../discord-bot-core");
const FeedData = require("./feed-data.js");
module.exports = class GuildData extends Core.BaseGuildData {
constructor({ id, feeds = [] }) {
super(id);
this.feeds = feeds.map(feed => new FeedData(feed));
constructor() {
super();
this.feeds = [FeedData];
}
cachePastPostedLinks(guild) {

4
discord-bot-core/.gitrepo

@ -6,7 +6,7 @@
[subrepo]
remote = git@github.com:benji7425/discord-bot-core.git
branch = master
commit = a1a9b3045839d9e7ec594af8271f0d1c57e109d2
parent = 2b4335231ac1ccf4265ada5ce0a84d343021fcd6
commit = be39d241b37f36d607bdfda972869e5ce4652d4d
parent = 1e749659fd566af374f0129943a98f0735ee4c70
method = merge
cmdver = 0.3.1

10
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.guildID = String;
}
};

102
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,69 @@ 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);
process.on("uncaughtException", err => this._onUnhandledException(this, err));
}
bootstrap() {
this.beforeLogin();
this.login(this._token);
}
Camo.connect("nedb://guilds-data").then(db => {
neDB = db;
beforeLogin() {
setInterval(() => this.writeFile(), InternalConfig.saveIntervalSec * 1000);
this.emit("beforeLogin");
this.emit("beforeLogin");
this.login(this._token);
});
}
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({ guildID: 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);
_onUnhandledException(client, err) {
CoreUtil.dateError("Unhandled exception!\n", 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;
}
};
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");
}

50
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({ guildID: message.guild.id })
.then(guildData =>
handleGuildCommand(
client,
message,
Object.assign({}, internalCommands, commands),
guildData || client.guildDataModel.create({ guildID: 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;

72
discord-bot-core/HandleMessage.js

@ -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;

15
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,10 +9,16 @@ 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);
}
};

30
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 };
}

14
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);
}

9
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
}

427
discord-bot-core/package-lock.json

@ -0,0 +1,427 @@
{
"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": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg="
},
"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="
},
"cron": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/cron/-/cron-1.3.0.tgz",
"integrity": "sha512-K/SF7JlgMmNjcThWxkKvsHhey2EDB4CeOEWJ9aXWj3fbQJppsvTPIeyLdHfNq5IbbsMUUjRW1nr5dSO95f2E4w==",
"requires": {
"moment-timezone": "0.5.14"
}
},
"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": "sha1-qt3iuGtpuQUWa4O8Sc/ENSOOGus=",
"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="
},
"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="
},
"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"
}
},
"moment": {
"version": "2.19.3",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.19.3.tgz",
"integrity": "sha1-vbmdJw1tf9p4zA+6zoVeJ/59pp8="
},
"moment-timezone": {
"version": "0.5.14",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.14.tgz",
"integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=",
"requires": {
"moment": "2.19.3"
}
},
"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": "sha1-SbVUqeLcyu1F1+GiXqjOyde7axI="
},
"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": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="
},
"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="
}
}
}

8
discord-bot-core/package.json

@ -2,11 +2,13 @@
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"camo": "0.12.3",
"cron": "1.3.0",
"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": {

843
package-lock.json

@ -0,0 +1,843 @@
{
"name": "discord-bot-rss-feed",
"version": "3.1.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"acorn": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz",
"integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ=",
"optional": true
},
"ajv": {
"version": "https://registry.npmjs.org/ajv/-/ajv-5.2.2.tgz",
"integrity": "sha1-R8aNaehvXZUxA7AHSpQw3GPaXjk=",
"requires": {
"co": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"fast-deep-equal": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
"json-schema-traverse": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
"json-stable-stringify": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz"
}
},
"amdefine": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
"optional": true
},
"asn1": {
"version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
},
"assert-plus": {
"version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"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=",
"optional": true
},
"async": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=",
"optional": true
},
"async-limiter": {
"version": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg="
},
"asynckit": {
"version": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"aws-sign2": {
"version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
"version": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
},
"base62": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz",
"integrity": "sha1-e0F0wvlESXU7EcJlHAg9qEGnsIQ=",
"optional": true
},
"bcrypt-pbkdf": {
"version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
"optional": true,
"requires": {
"tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz"
},
"dependencies": {
"tweetnacl": {
"version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"optional": true
}
}
},
"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=",
"optional": true,
"requires": {
"underscore": "1.4.4"
},
"dependencies": {
"underscore": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
"integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=",
"optional": true
}
}
},
"boom": {
"version": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
"integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
"requires": {
"hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz"
}
},
"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": "git+https://github.com/scottwrobinson/camo.git#3acde553b37ec7d2161a20424fa1975243f96179",
"requires": {
"depd": "1.1.0",
"lodash": "3.9.3",
"mongodb": "2.0.42",
"nedb": "1.8.0"
}
},
"caseless": {
"version": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"co": {
"version": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
},
"combined-stream": {
"version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
"integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
"requires": {
"delayed-stream": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
}
},
"core-util-is": {
"version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cryptiles": {
"version": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
"integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
"requires": {
"boom": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz"
},
"dependencies": {
"boom": {
"version": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
"integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=",
"requires": {
"hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz"
}
}
}
},
"dashdash": {
"version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
}
},
"delayed-stream": {
"version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"depd": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz",
"integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM="
},
"discord.js": {
"version": "https://registry.npmjs.org/discord.js/-/discord.js-11.2.0.tgz",
"integrity": "sha1-qt3iuGtpuQUWa4O8Sc/ENSOOGus=",
"requires": {
"long": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
"prism-media": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.1.tgz",
"snekfetch": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.3.0.tgz",
"tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.0.tgz",
"ws": "https://registry.npmjs.org/ws/-/ws-3.2.0.tgz"
}
},
"ecc-jsbn": {
"version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
"optional": true,
"requires": {
"jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz"
}
},
"es3ify": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/es3ify/-/es3ify-0.1.4.tgz",
"integrity": "sha1-rZ+l3xrjTz8x4SEbWBiy1RB439E=",
"optional": true,
"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=",
"optional": true
},
"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="
},
"extend": {
"version": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
},
"extsprintf": {
"version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"falafel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/falafel/-/falafel-1.2.0.tgz",
"integrity": "sha1-wY0k71CRF0pJfzGM0ksCaiXN2rQ=",
"optional": true,
"requires": {
"acorn": "1.2.2",
"foreach": "2.0.5",
"isarray": "0.0.1",
"object-keys": "1.0.11"
}
},
"fast-deep-equal": {
"version": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
"integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8="
},
"feed-read": {
"version": "https://registry.npmjs.org/feed-read/-/feed-read-0.0.1.tgz",
"integrity": "sha1-LaOTTX8Vu9vldNysVAOCHkFhY4s=",
"requires": {
"request": "https://registry.npmjs.org/request/-/request-2.82.0.tgz",
"sax": "https://registry.npmjs.org/sax/-/sax-0.3.5.tgz",
"underscore": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz"
}
},
"foreach": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
"optional": true
},
"forever-agent": {
"version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz",
"integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=",
"requires": {
"asynckit": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
"mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz"
}
},
"get-urls": {
"version": "https://registry.npmjs.org/get-urls/-/get-urls-7.0.0.tgz",
"integrity": "sha1-xICtx9TGzFy7ZLUxgj3GO5nsHlo=",
"requires": {
"normalize-url": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz",
"url-regex": "https://registry.npmjs.org/url-regex/-/url-regex-4.1.1.tgz"
}
},
"getpass": {
"version": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
}
},
"graceful-fs": {
"version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
"optional": true
},
"har-schema": {
"version": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
},
"har-validator": {
"version": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
"requires": {
"ajv": "https://registry.npmjs.org/ajv/-/ajv-5.2.2.tgz",
"har-schema": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz"
}
},
"hawk": {
"version": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
"integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=",
"requires": {
"boom": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
"cryptiles": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
"hoek": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz",
"sntp": "https://registry.npmjs.org/sntp/-/sntp-2.0.2.tgz"
}
},
"hoek": {
"version": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz",
"integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0="
},
"http-signature": {
"version": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"jsprim": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"sshpk": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz"
}
},
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
"optional": true
},
"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=",
"optional": true,
"requires": {
"falafel": "1.2.0",
"through2": "0.6.5"
}
},
"ip-regex": {
"version": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz",
"integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0="
},
"is-plain-obj": {
"version": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
},
"is-typedarray": {
"version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"isstream": {
"version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"jsbn": {
"version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
"json-schema": {
"version": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-schema-traverse": {
"version": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
},
"json-stable-stringify": {
"version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
"integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
"requires": {
"jsonify": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz"
}
},
"json-stringify-safe": {
"version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsonfile": {
"version": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz",
"integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=",
"requires": {
"graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz"
}
},
"jsonify": {
"version": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
},
"jsprim": {
"version": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"json-schema": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"verror": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz"
}
},
"jstransform": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/jstransform/-/jstransform-3.0.0.tgz",
"integrity": "sha1-olkats7o2XvzvoMNv6IxO4fNZAs=",
"optional": true,
"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=",
"optional": true,
"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=",
"optional": true,
"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": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
"integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s="
},
"mime-db": {
"version": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
"integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE="
},
"mime-types": {
"version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
"integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
"requires": {
"mime-db": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz"
}
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"optional": true
},
"mkdirp": {