rewrite claimbot

add missing packages
rename example config
update example config
This commit is contained in:
Niko Storni 2018-11-27 17:03:18 -05:00
parent 72ae7fd91c
commit c02e364759
No known key found for this signature in database
GPG key ID: F37FE63398800368
5 changed files with 268 additions and 286 deletions

View file

@ -1,26 +1,24 @@
'use strict';
let lbry;
let mongo;
let discordBot;
let moment = require('moment');
let request = require('request');
let sleep = require('sleep');
let config = require('config');
let channels = config.get('claimbot').channels;
const Discord = require('discord.js');
const rp = require('request-promise');
const jsonfile = require('jsonfile');
const path = require('path');
const fs = require('fs');
const appRoot = require('app-root-path');
const fileExists = require('file-exists');
const request = require('request');
let lastProcessedBlock = 0;
module.exports = {
init: init
};
function init(discordBot_) {
if (lbry) {
if (discordBot) {
throw new Error('init was already called once');
}
@ -35,7 +33,7 @@ function init(discordBot_) {
}
mongo = db;
console.log('Activating claimbot ');
console.log('Activating claimbot');
discordBot.channels.get(channels[0]).send('activating claimbot');
// Check that our syncState file exist.
@ -48,110 +46,101 @@ function init(discordBot_) {
}
});
setInterval(function() {
//announceClaims(); pause the claim until https://github.com/lbryio/chainquery/issues/58 has been fixed.
announceClaimsV2();
}, 60 * 1000);
//announceClaims();
}
);
).catch(console.error);
}
async function announceClaims() {
// get last block form the explorer API.
let lastBlockHeight = JSON.parse(await rp('https://explorer.lbry.io/api/v1/status')).status.height;
// get the latest claims from chainquery since last sync
let syncState = await getJSON(path.join(appRoot.path, 'syncState.json')); // get our persisted state
if (!syncState.LastSyncTime) {
syncState.LastSyncTime = new Date()
.toISOString()
.slice(0, 19)
.replace('T', ' ');
}
let claimsSince = JSON.parse(await getClaimsSince(syncState.LastSyncTime)).data;
// filter out the claims that we should add to discord
let claims = [];
for (let claim of claimsSince) {
claim.value = JSON.parse(claim.value);
if (claim.value.Claim && claim.value.Claim.stream) {
claim.metadata = claim.value.Claim.stream.metadata;
} else {
claim.metadata = null;
}
if (claim.bid_state !== 'Spent' || claim.bid_state !== 'Expired') {
claims.push(claim);
}
}
for (let claim of claims) {
console.log(claim);
}
// send each claim to discord.
for (let claim of claims) {
console.log(claim);
if (claim.metadata) {
// If its a claim, make a claimEmbed
let claimEmbed = new Discord.RichEmbed()
.setAuthor(
claim.channel ? `New claim from ${claim.channel}` : 'New claim from Anonymous',
'http://barkpost-assets.s3.amazonaws.com/wp-content/uploads/2013/11/3dDoge.gif',
`http://open.lbry.io/${claim.channel ? `${claim.channel}#${claim.channelId}/${claim['name']}` : `${claim['name']}#${claim['claimId']}`}`
)
.setTitle('lbry://' + (claim.channel ? `${claim.channel}/` : '') + claim['name'])
.setURL(`http://open.lbry.io/${claim.channel ? `${claim.channel}#${claim.channelId}/${claim['name']}` : `${claim['name']}#${claim['claimId']}`}`)
function announceClaimsV2() {
getClaimsForLastBlock()
.then(claims => {
let currentBlock = lastProcessedBlock;
claims.forEach(c => {
if (c.height <= lastProcessedBlock) return;
currentBlock = c.height;
console.log(JSON.stringify(c, null, 4));
//filter claims that we don't want to announce
if (c.bid_state === 'Expired' || c.bid_state === 'Spent') return;
discordPost(embedFromClaim(c));
});
lastProcessedBlock = currentBlock;
})
.catch(console.error);
}
/**
*
* @param {Object} claim
* @returns {RichEmbed} discordEmbeded
*/
function embedFromClaim(claim) {
let e = new Discord.RichEmbed();
const typeClaim = 1,
typeChannel = 2;
switch (claim.claim_type) {
case typeClaim:
let channelName = claim.channel_name ? claim.channel_name : 'Anonymous';
let channelPermalink = claim.channel_name ? `${claim.channel_name}#${claim.publisher_id}` : '';
let claimPermalink = claim.channel_name ? `${channelPermalink}/${claim.name}` : `${claim.name}#${claim.claim_id}`;
let metadata = JSON.parse(claim.value_as_json).claim.stream.metadata;
e.setAuthor(`New claim from ${channelName}`, 'http://barkpost-assets.s3.amazonaws.com/wp-content/uploads/2013/11/3dDoge.gif', `http://open.lbry.io/${claimPermalink}`)
.setTitle(`lbry://${claimPermalink}`)
.setURL(`http://open.lbry.io/${claimPermalink}`)
.setColor(1399626)
.setFooter(`Block ${claim.height} • Claim ID ${claim.claimId} • Data from Chainquery`);
if (claim.metadata['title']) claimEmbed.addField('Title', claim.metadata['title']);
if (claim.channel) claimEmbed.addField('Channel', claim.channel);
if (claim.metadata['description']) {
claimEmbed.addField('Description', claim.metadata['description'].substring(0, 1020));
.setFooter(`Block ${claim.height} • Claim ID ${claim.claim_id} • Data from Chainquery`);
if (metadata.title) e.addField('Title', claim.metadata['title']);
if (claim.channel_name) e.addField('Channel', claim.channel_name);
if (metadata.description) {
e.addField('Description', claim.metadata.description.substring(0, 1020));
}
if (claim.metadata['fee']) claimEmbed.addField('Fee', claim.metadata['fee'].amount + ' ' + claim.metadata['fee'].currency);
if (claim.metadata['license'] && claim.metadata['license'].length > 2) claimEmbed.addField('License', claim.metadata['license']);
if (!claim.metadata['nsfw'] && claim.metadata['thumbnail']) claimEmbed.setImage(claim.metadata['thumbnail']);
if (metadata.fee) e.addField('Fee', `${metadata.fee.amount} ${metadata.fee.currency}`);
if (metadata.license && metadata.license.length > 2) e.addField('License', metadata.license);
if (!metadata.nsfw && metadata.thumbnail) e.setImage(claim.metadata.thumbnail);
if (claim.bid_state !== 'Controlling' && claim.height < claim.valid_at_height) {
// Claim have not taken over the old claim, send approx time to event.
let takeoverTime = Date.now() + (claim.valid_at_height - lastBlockHeight) * 161 * 1000; // in theory this should be 150, but in practice its closer to 161
claimEmbed.addField('Takes effect on approx', moment(takeoverTime, 'x').format('MMMM Do [at] HH:mm [UTC]') + ` • at block height ${claim.valid_at_height}`);
let blockTime = 150 * 1000;
let takeoverTime = Date.now() + (claim.valid_at_height - lastBlockHeight) * blockTime;
e.addField('Takes effect on approx', `${moment(takeoverTime, 'x').format('MMMM Do [at] HH:mm [UTC]')} • at block height ${claim.valid_at_height}`);
}
claimEmbed.addField('Claimed for', `${Number.parseFloat(claim.outputValue)} LBC`);
discordPost(claimEmbed);
} else if (claim.name.charAt(0) === '@') {
// This is a channel claim
let channelEmbed = new Discord.RichEmbed()
.setAuthor('New channel claim', 'http://barkpost-assets.s3.amazonaws.com/wp-content/uploads/2013/11/3dDoge.gif', `http://open.lbry.io/${claim['name']}#${claim['claimId']}`)
.setTitle('lbry://' + (claim.channel ? claim.channel + '/' : '') + claim['name'])
.setURL(`http://open.lbry.io/${claim['name']}#${claim['claimId']}`)
e.addField('Claimed for', `${Number.parseFloat(claim.bid_amount)} LBC`);
break;
case typeChannel:
e.setAuthor('New channel claim', 'http://barkpost-assets.s3.amazonaws.com/wp-content/uploads/2013/11/3dDoge.gif', `https://open.lbry.io/${claim.name}#${claim.claim_id}`)
.setTitle(`lbry://${claim.name}`)
.setURL(`https://open.lbry.io/${claim.name}#${claim.claim_id}`)
.setColor(1399626)
.setFooter(`Block ${claim.height} • Claim ID ${claim.claimId} • Data from Chainquery`)
.addField('Channel Name', claim['name']);
discordPost(channelEmbed);
}
.setFooter(`Block ${claim.height} • Claim ID ${claim.claim_id} • Data from Chainquery`)
.addField('Channel Name', claim.name);
break;
}
// set the last sync time to the db.
syncState.LastSyncTime = new Date()
.toISOString()
.slice(0, 19)
.replace('T', ' ');
await saveJSON(path.join(appRoot.path, 'syncState.json'), syncState);
return e;
}
function getJSON(path) {
/**
*
* @returns {Promise} claims in last block
*/
function getClaimsForLastBlock() {
return new Promise((resolve, reject) => {
jsonfile.readFile(path, function(err, jsoncontent) {
if (err) {
reject(err);
} else {
resolve(jsoncontent);
}
});
});
}
function saveJSON(path, obj) {
return new Promise((resolve, reject) => {
jsonfile.writeFile(path, obj, function(err, jsoncontent) {
if (err) {
reject(err);
} else {
resolve();
}
let query =
'SELECT t1.*, t3.name AS channel_name, t4.value AS bid_amount FROM claim t1 INNER JOIN (SELECT MAX(height) AS height FROM block) t2 ON t1.height = t2.height LEFT JOIN claim t3 ON t1.publisher_id = t3.claim_id LEFT JOIN output t4 ON (t1.transaction_hash_id = t4.transaction_hash AND t1.vout = t4.vout)';
let options = {
method: 'GET',
url: 'https://chainquery.lbry.io/api/sql',
qs: { query: query },
headers: { 'Cache-Control': 'no-cache' }
};
request(options, function(error, response, body) {
if (error) return reject(error);
if (response.statusCode !== 200 || !body) return reject(response);
if (!body.success || body.error) return reject(response);
let claimsInBlock = body.data;
return resolve(claimsInBlock);
});
});
}
@ -164,39 +153,3 @@ function discordPost(embed) {
.catch(console.error);
});
}
function getClaimsSince(time) {
return new Promise((resolve, reject) => {
let query =
`` +
`SELECT ` +
`c.name,` +
`c.valid_at_height,` +
`c.height,` +
`p.name as channel,` +
`c.publisher_id as channelId,` +
`c.bid_state,` +
`c.effective_amount,` +
`c.claim_id as claimId,` +
`c.value_as_json as value, ` +
`c.transaction_hash_id, ` + // txhash and vout needed to leverage old format for comparison.
`c.vout, ` +
`o.value as outputValue ` +
`FROM claim c ` +
`LEFT JOIN claim p on p.claim_id = c.publisher_id ` +
`LEFT JOIN output o on (o.transaction_hash=c.transaction_hash_id and o.vout=c.vout) ` +
`WHERE c.created_at >='` +
time +
`'`;
// Outputs full query to console for copy/paste into chainquery (debugging)
// console.log(query);
rp(`https://chainquery.lbry.io/api/sql?query=` + query)
.then(function(htmlString) {
resolve(htmlString);
})
.catch(function(err) {
console.log('error', '[Importer] Error getting updated claims. ' + err);
reject(err);
});
});
}

View file

@ -0,0 +1,82 @@
{
// Bot configuration
"bot": {
"token": "",
"prefix": "!",
"debug": false
},
"moderation": {
"perms": ["Moderator Team", "LBRY TEAM"], // Roles that have access to all commands.
"logchannel": "371620338263523328" // Channel to log the bots moderation..
},
"lbrycrd": {
"host": "localhost",
"port": 9245,
"user": "USERHERE",
"pass": "PASSWORDHERE"
},
"mongodb": {
"url": "mongodb://localhost:27017/wunderbot"
},
"Channels": {
"verification": "363050496023592961",
"mining": "363049669636390913",
"random": "363084227518136322"
},
"speechbot": {
"channels": [
"363089721313722387",
"363085078403874823",
"363086945976320010",
"363086925428555776",
"363086752518242308",
"369896313082478594",
"363087606239461377",
"363088045366312962",
"363084227518136322",
"363084262028607488",
"371620338263523328"
], // Channels speech bot is allowed to post in
"mainchannel": "363085078403874823" // Main Speech Bot channel for directing with help message
},
"pricebot": {
"channels": ["363050205043621908", "369896313082478594", "371620338263523328"], // Chanels price bot is allowed to post in
"mainchannel": "363050205043621908" // Main Price Bot channel for directing with help message
},
"gitrelease": {
"channel": "370779899650375681" // Channel to send release info to using <!releasenotes post>
},
"spamdetection": {
"channels": ["363089721313722387", "363044238486798336", "363086719391629326", "363044275363119105", "363044260938776576", "372067478542745601", "369896313082478594", "371620338263523328"], // Channels excluded from Spam Detection
"users": ["244245498746241025"] // Users to exclude from Spam Detection (include other bots here)
},
"hashbot": {
"channels": ["363049669636390913", "369896313082478594", "371620338263523328"], // Channels Hash Bot is allowed to post in
"mainchannel": "363049669636390913" // Main Hash Bot channel for directing with help message
},
"statsbot": {
"channels": ["363050205043621908", "369896313082478594", "371620338263523328"], // Channels Stats Bot is allowed to post in
"mainchannel": "363050205043621908" // Main Stats Bot channel for directing with help message
},
"claimbot": {
"channels": ["363086719391629326"]
},
"rolelist": {
"baserole": "LBRYian",
"allowedroles": ["NSFW", "Traders", "Miners", "Off-Topic Chats", "International", "Dev"]
},
"irc": {
"nickname": "wunderbot",
"server": "chat.freenode.net",
"discordToken": "",
"ircOptions": {
"userName": "wunderbot",
"nick": "wunderbot",
"password": "",
"sasl": true
},
"channelMapping": {
"#shared": "#lbry"
}
}
}

View file

@ -1,101 +0,0 @@
{
// Bot configuration
"bot": {
"token": "discordbottoken",
"prefix": "!",
"debug": false
},
"moderation": {
"perms": ["Moderator Team","LBRY TEAM"], // Roles that have access to all commands.
"logchannel": "371620338263523328" // Channel to log the bots moderation..
},
//define channels for Commands.js usage
"Channels": {
"verification": "363050496023592961",
"mining": "363049669636390913",
"random": "363084227518136322",
"content": "377938982111019010"
},
"speechbot": {
"channels": [
"363089721313722387",
"363085078403874823",
"363086945976320010",
"363086925428555776",
"363086752518242308",
"369896313082478594",
"363087606239461377",
"363088045366312962",
"363084227518136322",
"363084262028607488",
"371620338263523328"
], // Channels speech bot is allowed to post in
"mainchannel": "363085078403874823" // Main Speech Bot channel for directing with help message
},
"pricebot": {
"channels": [
"363050205043621908",
"369896313082478594",
"371620338263523328"
], // Chanels price bot is allowed to post in
"mainchannel": "363050205043621908" // Main Price Bot channel for directing with help message
},
"gitrelease": {
"channel": "370779899650375681" // Channel to send release info to using <!releasenotes post>
},
"spamdetection": {
"channels": [
"363089721313722387",
"363044238486798336",
"363086719391629326",
"363044275363119105",
"363044260938776576",
"372067478542745601",
"369896313082478594",
"371620338263523328"
], // Channels excluded from Spam Detection
"users": [
"244245498746241025"
] // Users to exclude from Spam Detection (include other bots here)
},
"hashbot": {
"channels": [
"363049669636390913",
"369896313082478594",
"371620338263523328"
], // Channels Hash Bot is allowed to post in
"mainchannel": "363049669636390913" // Main Hash Bot channel for directing with help message
},
"statsbot": {
"channels": [
"363050205043621908",
"369896313082478594",
"371620338263523328"
], // Channels Stats Bot is allowed to post in
"mainchannel": "363050205043621908" // Main Stats Bot channel for directing with help message
},
"rolelist": {
// The roles here are Case Sensitive to how they are in your Discord Server!
"baserole": "LBRYian",
"allowedroles": ["NSFW", "Marketers", "Miners", "Off-Topic Chats", "International", "Dev"]
},
"claimbot": {
"channels": [
"377938982111019010"
]
},
"mongodb": {
"url": "mongodb://HOST:PORT/DATABASE"
},
"irc": {
"nickname": "nick",
"server": "chat.freenode.net",
"discordToken": "tokenhere",
"autoSendCommands": [
["PRIVMSG", "NickServ", "IDENTIFY password"]
],
"channelMapping": {
"#shared": "#lbry"
}
}
}

151
package-lock.json generated
View file

@ -606,9 +606,9 @@
}
},
"bson": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz",
"integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg=="
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.0.tgz",
"integrity": "sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA=="
},
"buffer-shims": {
"version": "1.0.0",
@ -664,7 +664,7 @@
},
"callsites": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
"resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
"integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
"dev": true
},
@ -844,9 +844,9 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"config": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/config/-/config-2.0.1.tgz",
"integrity": "sha512-aTaviJnC8ZjQYx8kQf4u6tWqIxWolyQQ3LqXgnCLAsIb78JrUshHG0YuzIarzTaVVe1Pazms3TXImfYra8UsyQ==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/config/-/config-2.0.2.tgz",
"integrity": "sha512-duIbkKb0gls0bOtGwd1vaD4236MwepQlZcrMheOGrn3/9Px7oYFh8G4LB3ylGOlPr5wGoJRm8Grb2RihJZxuHQ==",
"requires": {
"json5": "^1.0.1"
},
@ -1183,7 +1183,7 @@
},
"expand-range": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
"resolved": "http://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
"integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
"optional": true,
"requires": {
@ -1970,9 +1970,9 @@
}
},
"husky": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/husky/-/husky-1.1.4.tgz",
"integrity": "sha512-cZjGpS7qsaBSo3fOMUuR7erQloX3l5XzL1v/RkIqU6zrQImDdU70z5Re9fGDp7+kbYlM2EtS4aYMlahBeiCUGw==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/husky/-/husky-1.2.0.tgz",
"integrity": "sha512-/ib3+iycykXC0tYIxsyqierikVa9DA2DrT32UEirqNEFVqOj1bFMTgP3jAz8HM7FgC/C8pc/BTUa9MV2GEkZaA==",
"dev": true,
"requires": {
"cosmiconfig": "^5.0.6",
@ -2503,6 +2503,12 @@
"integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=",
"optional": true
},
"memory-pager": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.1.0.tgz",
"integrity": "sha512-Mf9OHV/Y7h6YWDxTzX/b4ZZ4oh9NSXblQL8dtPCOomOtZciEHxePR78+uHFLLlsk01A6jVHhHsQZZ/WcIPpnzg==",
"optional": true
},
"micromatch": {
"version": "2.3.11",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
@ -2583,51 +2589,23 @@
"integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y="
},
"mongodb": {
"version": "2.2.34",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.34.tgz",
"integrity": "sha1-o09Zu+thdUrsQy3nLD/iFSakTBo=",
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.1.10.tgz",
"integrity": "sha512-Uml42GeFxhTGQVml1XQ4cD0o/rp7J2ROy0fdYUcVitoE7vFqEhKH4TYVqRDpQr/bXtCJVxJdNQC1ntRxNREkPQ==",
"requires": {
"es6-promise": "3.2.1",
"mongodb-core": "2.1.18",
"readable-stream": "2.2.7"
},
"dependencies": {
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"readable-stream": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz",
"integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=",
"requires": {
"buffer-shims": "~1.0.0",
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"string_decoder": "~1.0.0",
"util-deprecate": "~1.0.1"
}
},
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
"mongodb-core": "3.1.9",
"safe-buffer": "^5.1.2"
}
},
"mongodb-core": {
"version": "2.1.18",
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz",
"integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=",
"version": "3.1.9",
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.1.9.tgz",
"integrity": "sha512-MJpciDABXMchrZphh3vMcqu8hkNf/Mi+Gk6btOimVg1XMxLXh87j6FAvRm+KmwD1A9fpu3qRQYcbQe4egj23og==",
"requires": {
"bson": "~1.0.4",
"require_optional": "~1.0.0"
"bson": "^1.1.0",
"require_optional": "^1.0.1",
"safe-buffer": "^5.1.2",
"saslprep": "^1.0.0"
}
},
"mongoose": {
@ -2657,6 +2635,57 @@
"requires": {
"lodash": "^4.14.0"
}
},
"bson": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz",
"integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg=="
},
"mongodb": {
"version": "2.2.34",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.34.tgz",
"integrity": "sha1-o09Zu+thdUrsQy3nLD/iFSakTBo=",
"requires": {
"es6-promise": "3.2.1",
"mongodb-core": "2.1.18",
"readable-stream": "2.2.7"
}
},
"mongodb-core": {
"version": "2.1.18",
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz",
"integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=",
"requires": {
"bson": "~1.0.4",
"require_optional": "~1.0.0"
}
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"readable-stream": {
"version": "2.2.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz",
"integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=",
"requires": {
"buffer-shims": "~1.0.0",
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"string_decoder": "~1.0.0",
"util-deprecate": "~1.0.1"
}
},
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
@ -3606,6 +3635,15 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"saslprep": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.2.tgz",
"integrity": "sha512-4cDsYuAjXssUSjxHKRe4DTZC0agDwsCqcMqtJAQPzC74nJ7LfAJflAtC1Zed5hMzEQKj82d3tuzqdGNRsLJ4Gw==",
"optional": true,
"requires": {
"sparse-bitfield": "^3.0.3"
}
},
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
@ -3834,6 +3872,15 @@
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
},
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
"optional": true,
"requires": {
"memory-pager": "^1.0.2"
}
},
"spdx-correct": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz",
@ -3996,7 +4043,7 @@
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"

View file

@ -20,7 +20,8 @@
"request": "^2.85.0",
"request-promise": "^4.2.2",
"sleep": "^5.1.1",
"wget": "^0.0.1"
"wget": "^0.0.1",
"mongodb": "latest"
},
"scripts": {
"prettier": "prettier --write \"{bot,.}/**/*.{js,json}\" --single-quote --print-width 240",