merged tipbot into hashbot, generic framework for more bots

This commit is contained in:
Alex Grintsvayg 2016-07-14 17:34:37 -04:00
parent cfbbba8e31
commit 215260259c
5 changed files with 302 additions and 57 deletions

37
app.js Normal file
View file

@ -0,0 +1,37 @@
var SlackBot = require('slackbots');
['SLACK_TOKEN', 'RPCUSER', 'RPCPASSWORD'].forEach(function(envVar) {
if (!process.env[envVar]) {
throw new Error(envVar + ' env var required');
}
});
var slackbot = new SlackBot({
token: process.env.SLACK_TOKEN,
name: 'wunderbot'
});
var tipbot = require('./tipbot');
tipbot.init(process.env.RPCUSER, process.env.RPCPASSWORD);
var hashbot = require('./hashbot');
hashbot.init(slackbot, process.env.MINING_CHANNEL);
slackbot.on('start', function() {
slackbot.on('message', function(data) {
if (data.text) {
var command = data.text.trim().split(' ')[0];
if (command === hashbot.command) {
hashbot.respond(slackbot, data);
}
if (command === tipbot.command) {
tipbot.respond(slackbot, data);
}
}
});
});

57
bot.js
View file

@ -1,57 +0,0 @@
var SlackBot = require('slackbots');
var needle = require('needle');
var SLACK_TOKEN = process.env.SLACK_TOKEN;
var CHANNEL = process.env.CHANNEL;
if (!SLACK_TOKEN) {
throw new Error('SLACK_TOKEN env var required');
}
if (!CHANNEL) {
throw new Error('CHANNEL env var required');
}
var bot = new SlackBot({
token: SLACK_TOKEN,
name: 'hashbot'
});
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function getData() {
needle.get('https://explorer.lbry.io/api/getmininginfo', function(error, response) {
// if (!error && response.statusCode == 200) {
// console.log(response.body);
// }
var data = response.body,
hashrate = Math.round(data.networkhashps / 1000000000),
difficulty = numberWithCommas(Math.round(data.difficulty)),
block = numberWithCommas(data.blocks);
bot.postMessageToChannel(CHANNEL,
// 'Blockchain stats:\n' +
'Hashrate: ' + hashrate + ' GH/s\n' +
'Difficulty: ' + difficulty + '\n' +
'Current block: ' + block + '\n' +
'_Source: https://explorer.lbry.io_'
);
});
}
bot.on('start', function() {
// more information about additional params https://api.slack.com/methods/chat.postMessage
bot.on('message', function(data) {
if (data.text && data.text.trim() === '!hash') {
getData();
}
});
// Post every hour
setInterval(getData, 3600000);
getData();
});

64
hashbot.js Normal file
View file

@ -0,0 +1,64 @@
var needle = require('needle');
var command = '!hash';
module.exports={
command: command,
init: init,
respond: respond
};
function init(slackbot, channel) {
if (channel) {
setInterval(function() {
sendMiningInfo(slackbot, channel);
}, 3600000);
sendMiningInfo(slackbot, channel);
}
}
function respond(slackbot, data) {
var words = data.text.trim().split(' ');
if (words[0] !== command) {
// wtf?
return;
}
if (words.length > 1) {
// e.g. "!hash and some other words"
return;
}
sendMiningInfo(slackbot, data.channel);
}
function sendMiningInfo(slackbot, channel) {
needle.get('https://explorer.lbry.io/api/getmininginfo', function(error, response) {
if (error || response.statusCode !== 200) {
slackbot.postMessage(channel, 'Explorer API is not available');
}
else {
var data = response.body,
hashrate = Math.round(data.networkhashps / 1000000000),
difficulty = numberWithCommas(Math.round(data.difficulty)),
block = numberWithCommas(data.blocks);
slackbot.postMessage(channel,
// 'Blockchain stats:\n' +
'Hashrate: ' + hashrate + ' GH/s\n' +
'Difficulty: ' + difficulty + '\n' +
'Current block: ' + block + '\n' +
'_Source: https://explorer.lbry.io_'
);
}
});
}
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

View file

@ -4,6 +4,7 @@
"description": "A bot for slack wich displays lbrys current hashrate via the open api.",
"main": "bot.js",
"dependencies": {
"bitcoin": "^3.0.1",
"needle": "^1.0.0",
"slackbots": "^0.5.1"
},

200
tipbot.js Normal file
View file

@ -0,0 +1,200 @@
var lbry;
var command = '!tip';
module.exports={
command: command,
init: init,
respond: respond
};
function init(rpcuser, rpcpassword) {
if (lbry) {
throw new Error('init was already called once');
}
var bitcoin = require('bitcoin');
lbry = new bitcoin.Client({
host: 'localhost',
'port': 9245,
'user': rpcuser,
'pass': rpcpassword
});
}
function respond(bot, data) {
var tipper = data.user,
channel = data.channel,
words = data.text.trim().split(' ');
if (!lbry) {
bot.postMessage(channel, 'Failed to connect to lbrycrd');
return;
}
if (words[0] !== command) {
// wtf?
return;
}
var subcommand = words.length >= 2 ? words[1] : 'help';
if (subcommand === 'help') {
doHelp(bot, channel);
}
else if (subcommand === 'balance') {
doBalance(bot, channel, tipper);
}
else if (subcommand === 'deposit') {
doDeposit(bot, channel, tipper);
}
else if (subcommand === 'withdraw') {
doWithdraw(bot, channel, tipper, words);
}
else {
doTip(bot, channel, tipper, words);
}
}
function doBalance(bot, channel, tipper) {
lbry.getBalance(tipper, 1, function(err, balance) {
if (err) {
bot.postMessage(channel, 'Error getting balance');
}
else {
bot.postMessage(channel, 'You have *' + balance + '* LBC');
}
});
}
function doDeposit(bot, channel, tipper) {
getAddress(tipper, function(err, address) {
if (err) {
bot.postMessage(channel, 'Error getting deposit address');
}
else {
bot.postMessage(channel, 'Your address is ' + address);
}
});
}
function doWithdraw(bot, channel, tipper, words) {
if (words.length < 4) {
doHelp(bot, channel);
return;
}
var address = words[2],
amount = words[3];
if (!validateAmount(amount)) {
bot.postMessage(channel, 'I dont know how to withdraw that many credits');
return;
}
lbry.sendFrom(tipper, address, amount, function(err, txId) {
if (err) {
bot.postMessage(channel, err.message);
}
else {
bot.postMessage(channel, 'You withdrew ' + amount + ' to ' + address + ' (' + txLink(txId) + ')');
}
});
}
function doTip(bot, channel, tipper, words) {
if (words.length < 3) {
doHelp(bot, channel);
return;
}
var user = words[1],
amount = words[2];
if (!validateAmount(amount)) {
bot.postMessage(channel, 'I dont know how to tip that many credits');
return;
}
if (user.match(/^<@U[^>]+>$/)) {
var id = user.substr(2,user.length-3);
sendLbc(bot, channel, tipper, id, amount);
}
else {
bot.getUser(user).then(function(data) {
if (data.id) {
sendLbc(bot, channel, tipper, data.id, amount);
} else
{
bot.postMessage(channel, 'Sorry, I dont know that person');
}
})
}
}
function doHelp(bot, channel) {
bot.postMessage(channel,
'`' + command + ' help`: this message\n' +
'`' + command + ' balance`: get your balance\n' +
'`' + command + ' deposit`: get address for deposits\n' +
'`' + command + ' withdraw ADDRESS AMOUNT`: withdraw AMOUNT credits to ADDRESS\n' +
'`' + command + ' USER AMOUNT`: send AMOUNT credits to USER\n'
);
}
function sendLbc(bot, channel, tipper, id, amount) {
getAddress(id, function(err, address){
if (err){
bot.postMessage(channel, err.message);
}
else {
lbry.sendFrom(tipper, address, amount, 1, null, null, function(err, txId){
if (err) {
bot.postMessage(channel, err.message);
}
else {
bot.postMessage(channel, 'Wubba lubba dub dub! <@' + tipper + '> tipped <@' + id + '> ' + amount + ' (' + txLink(txId) + ')');
}
});
}
});
};
function getAddress(userId, cb) {
lbry.getAddressesByAccount(userId, function(err, addresses) {
if (err) {
cb(err);
}
else if(addresses.length > 0) {
cb(null, addresses[0]);
}
else {
lbry.getNewAddress(userId, function(err, address) {
if (err) {
cb(err);
}
else {
cb(null, address);
}
});
}
});
}
function validateAmount(amount) {
return amount.match(/^[0-9]+(\.[0-9]+)?$/);
}
function txLink(txId) {
return "<https://explorer.lbry.io/tx/" + txId + "|tx>";
}