diff --git a/README.md b/README.md index 09ef117..da81e69 100644 --- a/README.md +++ b/README.md @@ -86,10 +86,11 @@ To run the bot simply use `node bin/tipbot` or `npm start`. | `tip` | ` ` | sends the specified amount of coins to the specified nickname | `help` | | displays configured help message (by default similiar to this one) | `terms` | | displays terms and conditions for using the tip bot +| `rain` | [max] | splits `amount` coins between `max` users on the channel ## Donations Donations are welcome! If you like my bot and want to donate me, here are my wallet addresses: +* **Bitcoin**: 1G7T2JNDnbxo3txFWZSuV5oYq8qwtSEg51 * **Dogecoin**: DGLT1pTSKAXLSSSz1NGFgZNLioDyHdaDyA -* **Flappycoin**: FPEBPCC1sr9FAJ4DbD3r4YFwMqrr9TppeK -* **Mintcoin**: MmfHmeWGUbzzd4he4u9yXRu5tQGLs1QNDL + diff --git a/bin/tipbot.js b/bin/tipbot.js index 60ccc14..9386695 100644 --- a/bin/tipbot.js +++ b/bin/tipbot.js @@ -76,11 +76,20 @@ var client = new irc.Client(settings.connection.host, settings.login.nickname, { // gets user's login status irc.Client.prototype.isIdentified = function(nickname, callback) { - client.whois(nick, function(reply) { + this.whois(nick, function(reply) { callback(!!reply.account); }); } +irc.Client.prototype.getNames = function(channel, callback) { + var listener = function(nicks) { + callback(nicks); + this.removeListener('names' + channel, listener); + } + + this.addListener('names' + channel, listener); +} + // gets a empty coin address irc.Client.prototype.getAddress = function(nickname, callback) { winston.debug('Requesting address for %s', nickname); @@ -159,9 +168,65 @@ client.addListener('message', function(from, channel, message) { } switch(command) { + case 'rain': + var match = message.match(/^.?tip ([\d\.]+) ?(\d+)?/); + if(match == null || match.length < 2) { + client.say(channel, 'Usage: !rain [max people]'); + return; + } + + var amount = Number(match[1]); + var max = Number(match[2]); + + if(isNaN(amount)) { + client.say(channel, settings.messages.invalid_amount.expand({name: from, amount: match[2]})); + return; + } + + if(amount < settings.coin.min_tip) { + client.say(channel, settings.messages.tip_too_small.expand({from: from, to: to, amount: amount})); + return; + } + + coin.getBalance(from.toLowerCase(), settings.coin.min_confirmations, function(err, balance) { + if(err) { + winston.error('Error in !tip command.', err); + client.say(channel, settings.messages.error.expand({name: from})); + return; + } + var balance = typeof(balance) == 'object' ? balance.result : balance; + + if(balance >= amount) { + client.getNames(channel, function(names) { + // remove tipper from the list + names.splice(names.indexOf(from), 1); + // shuffle the array + for(var j, x, i = names.length; i; j = Math.floor(Math.random() * i), x = names[--i], names[i] = names[j], names[j] = x); + + var max = max ? Math.min(max, names.length) : names.length; + if(max == 0) return; + var names = names.split(0, max); + + for (var i = 0; i < names.length; i++) { + coin.move(from.toLowerCase(), names[i].toLowerCase(), amount / max, function(err, reply) { + if(err || !reply) { + winston.error('Error in !tip command', err); + return; + } + }); + } + + client.say(channel, settings.messages.rain.expand({name: from, amount: amount / max, list: names.join(', ')})); + }); + } else { + winston.info('%s tried to tip %s %d, but has only %d', from, to, amount, balance); + client.say(channel, settings.messages.no_funds.expand({name: from, balance: balance, short: amount - balance, amount: amount})); + } + }) + break; case 'tip': var match = message.match(/^.?tip (\S+) ([\d\.]+)/); - if(match == null || match < 3) { + if(match == null || match.length < 3) { client.say(channel, 'Usage: !tip ') return; } @@ -192,23 +257,15 @@ client.addListener('message', function(from, channel, message) { var balance = typeof(balance) == 'object' ? balance.result : balance; if(balance >= amount) { - client.getAddress(to, function(err, to_address) { // get the address to actually create a new one - if(err) { + coin.send('move', from.toLowerCase(), to.toLowerCase(), amount, function(err, reply) { + if(err || !reply) { winston.error('Error in !tip command', err); client.say(channel, settings.messages.error.expand({name: from})); return; } - coin.send('move', from.toLowerCase(), to.toLowerCase(), amount, function(err, reply) { - if(err || !reply) { - winston.error('Error in !tip command', err); - client.say(channel, settings.messages.error.expand({name: from})); - return; - } - - winston.info('%s tipped %s %d%s', from, to, amount, settings.coin.short_name) - client.say(channel, settings.messages.tipped.expand({from: from, to: to, amount: amount})); - }); + winston.info('%s tipped %s %d%s', from, to, amount, settings.coin.short_name) + client.say(channel, settings.messages.tipped.expand({from: from, to: to, amount: amount})); }); } else { winston.info('%s tried to tip %s %d, but has only %d', from, to, amount, balance); diff --git a/config/config.sample.yml b/config/config.sample.yml index dac6c7e..f3c06cf 100644 --- a/config/config.sample.yml +++ b/config/config.sample.yml @@ -63,6 +63,7 @@ messages: tip_too_small: 'Sorry %from%, your tip to %to% (%amount%%short_name%) is too small (min. %min_tip%%short_name%).' tip_self: "Sorry %name%, you can't tip yourself!" invalid_amount: 'Sorry %name%, "%amount%" is not a correct amount.' + rain: '%name% rained %amount%%short_name% upon %list%.' withdraw_success: - '%name%: %amount%%short_name% has been withdrawn from your account to %address%' - 'You have been charged %withdrawal_fee%%short_name% withdrawal fee.'