diff --git a/bin/tipbot b/bin/tipbot index 19e5d40..70891c4 100644 --- a/bin/tipbot +++ b/bin/tipbot @@ -43,18 +43,21 @@ var client = new irc.Client(settings.connection.host, settings.login.nickname, { , channels: settings.channels , userName: settings.login.username , realName: settings.login.realname + +, debug: true }); // gets user's login status irc.Client.prototype.getLoginStatus = function(nickname, callback) { // request login status - this.say('NickServ', 'ACC ' + nickname); + this.say('NickServ', settings.connection.status_command + ' ' + nickname); // wait for response var listener = function(from, to, message) { // proceed only on NickServ's ACC response - if(from != undefined && from.toLowerCase() == 'nickserv' && /^(\S+) ACC (\d)/.test(message)) { - var match = message.match(/^(\S+) ACC (\d)/); + var regexp = new RegExp('^(\\S+) ' + settings.connection.status_command + ' (\\d)'); + if(from != undefined && from.toLowerCase() == 'nickserv' && regexp.test(message)) { + var match = message.match(regexp); var user = match[1]; var level = match[2]; @@ -101,172 +104,198 @@ client.addListener('registered', function(message) { winston.info('Connected to %s.', message.server); }); +client.addListener('close', function(message) { + client.log(message); + winston.warn('Server %s disconnected.', message); +}); + client.addListener('error', function(message) { winston.error('Received an error from IRC network: ', message); }); client.addListener('message', function(from, channel, message) { - if(/^!tip/.test(message)) { - var match = message.match(/^!tip (\S+) (\d+)/); - if(match == null || match < 3) { - client.say(channel, 'Usage: !tip ') - return; - } - var to = match[1]; - var amount = Number(match[2]); + var match = message.match(/^(!?)(\S+)/); + var prefix = match[1]; + var command = match[2]; - if(to.toLowerCase() == from.toLowerCase()) { - client.say(channel, settings.messages.self_tip.expand({name: from})); - return; - } + if(settings.commands[command]) { + if(channel == client.nick && settings.commands[command].pm === false) return; + if(channel != client.nick && (settings.commands[command].channel === false || prefix != '!')) return; + } else { + return; + } - if(amount < settings.coin.min_tip) { - client.say(channel, settings.messages.tip_too_small.expand({from: from, to: to, amount: amount})); - return; - } + // if pms, make sure to respond to pms instead to itself + if(channel == client.nick) channel = from; - client.getLoginStatus(from, function(status) { - // check if the sending user is logged in (identified) - if(status == 3) { - // check balance with min. 5 confirmations - coin.getBalance(from, 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; + switch(command) { + case 'tip': + var match = message.match(/^.?tip (\S+) (\d+)/); + if(match == null || match < 3) { + client.say(channel, 'Usage: !tip ') + return; + } + var to = match[1]; + var amount = Number(match[2]); - if(balance >= amount) { - client.getAddress(to, function(err, to_address) { // get the address to actually create a new one - if(err) { - winston.error('Error in !tip command', err); - client.say(channel, settings.messages.error.expand({name: from})); - return; - } + if(to.toLowerCase() == from.toLowerCase()) { + client.say(channel, settings.messages.self_tip.expand({name: from})); + return; + } - coin.send('move', from.toLowerCase(), to.toLowerCase(), amount, function(err, reply) { - if(err || !reply) { + if(amount < settings.coin.min_tip) { + client.say(channel, settings.messages.tip_too_small.expand({from: from, to: to, amount: amount})); + return; + } + + client.getLoginStatus(from, function(status) { + // check if the sending user is logged in (identified) + if(status == 3) { + // check balance with min. 5 confirmations + coin.getBalance(from, 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.getAddress(to, function(err, to_address) { // get the address to actually create a new one + if(err) { 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})); - }); - }) - } 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})); - } - }) - } else { - client.say(channel, settings.messages.not_identified.expand({name: from})); - } - }); - } - if(/^!address/.test(message)) { - var params = message.split(' '); - var user = params[1] || from; - client.getAddress(user, function(err, address) { - if(err) { - winston.error('Error in !address 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; + } - client.say(channel, settings.messages.deposit_address.expand({name: user, address: address})); - }); - } - - if(/^!balance/.test(message)) { - var params = message.split(' '); - var user = (params[1] || from).toLowerCase(); - coin.getBalance(user, settings.coin.min_confirmations, function(err, balance) { - if(err) { - winston.error('Error in !balance command', err); - client.say(channel, settings.messages.error.expand({name: from})); - return; - } - - var balance = typeof(balance) == 'object' ? balance.result : balance; - - coin.getBalance(user, 0, function(err, unconfirmed_balance) { - if(err) { - winston.error('Error in !balance command', err); - client.say(channel, settings.messages.balance.expand({balance: balance, name: user})); + 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); + client.say(channel, settings.messages.no_funds.expand({name: from, balance: balance, short: amount - balance, amount: amount})); + } + }) + } else { + client.say(channel, settings.messages.not_identified.expand({name: from})); + } + }); + break; + case 'address': + var user = from.toLowerCase(); + client.getAddress(user, function(err, address) { + if(err) { + winston.error('Error in !address command', err); + client.say(channel, settings.messages.error.expand({name: from})); return; } - var unconfirmed_balance = typeof(unconfirmed_balance) == 'object' ? unconfirmed_balance.result : unconfirmed_balance; + client.say(channel, settings.messages.deposit_address.expand({name: user, address: address})); + }); + break; + case 'balance': + var user = from.toLowerCase(); + coin.getBalance(user, settings.coin.min_confirmations, function(err, balance) { + if(err) { + winston.error('Error in !balance command', err); + client.say(channel, settings.messages.error.expand({name: from})); + return; + } - client.say(channel, settings.messages.balance_unconfirmed.expand({balance: balance, name: user, unconfirmed: unconfirmed_balance - balance})); - }) - }); - } + var balance = typeof(balance) == 'object' ? balance.result : balance; - if(/^!withdraw/.test(message)) { - var match = message.match(/^!withdraw (.*)$/); - if(match == null) { - client.say(channel, 'Usage: !withdraw <' + settings.coin.full_name + ' address>'); - return; - } - var address = match[1]; + coin.getBalance(user, 0, function(err, unconfirmed_balance) { + if(err) { + winston.error('Error in !balance command', err); + client.say(channel, settings.messages.balance.expand({balance: balance, name: user})); + return; + } - coin.validateAddress(address, function(err, reply) { - if(err) { - winston.error('Error in !withdraw command', err); - client.say(channel, settings.messages.error.expand({name: from})); + var unconfirmed_balance = typeof(unconfirmed_balance) == 'object' ? unconfirmed_balance.result : unconfirmed_balance; + + client.say(channel, settings.messages.balance_unconfirmed.expand({balance: balance, name: user, unconfirmed: unconfirmed_balance - balance})); + }) + }); + break; + case 'withdraw': + var match = message.match(/^.?withdraw (\S+)$/); + if(match == null) { + client.say(channel, 'Usage: !withdraw <' + settings.coin.full_name + ' address>'); return; } + var address = match[1]; - if(reply.isvalid) { - coin.getBalance(from.toLowerCase(), settings.coin.min_confirmations, function(err, balance) { - if(err) { - winston.error('Error in !withdraw command', err); - client.say(channel, settings.messages.error.expand({name: from})); - return; - } - var balance = typeof(balance) == 'object' ? balance.result : balance; + coin.validateAddress(address, function(err, reply) { + if(err) { + winston.error('Error in !withdraw command', err); + client.say(channel, settings.messages.error.expand({name: from})); + return; + } - if(balance <= settings.coin.min_withdraw) { - winston.warn('%s tried to withdraw %d, but min is set to %d', from, balance, settings.coin.min_withdraw); - client.say(channel, settings.messages.withdraw_too_small.expand({from: from, balance: balance})); - return; - } - - coin.sendFrom(from.toLowerCase(), address, balance - settings.coin.withdrawal_fee, function(err, reply) { + if(reply.isvalid) { + coin.getBalance(from.toLowerCase(), settings.coin.min_confirmations, function(err, balance) { if(err) { winston.error('Error in !withdraw command', err); client.say(channel, settings.messages.error.expand({name: from})); return; } + var balance = typeof(balance) == 'object' ? balance.result : balance; - client.say(channel, settings.messages.withdraw_success.expand({name: from, address: address, balance: balance, amount: balance - settings.coin.withdrawal_fee, transaction: reply})); - client.say(channel, settings.messages.withdraw_success2.expand({name: from, address: address, balance: balance, amount: balance - settings.coin.withdrawal_fee, transaction: reply})); + if(balance < settings.coin.min_withdraw) { + winston.warn('%s tried to withdraw %d, but min is set to %d', from, balance, settings.coin.min_withdraw); + client.say(channel, settings.messages.withdraw_too_small.expand({name: from, balance: balance})); + return; + } - // transfer the rest (usually withdrawal fee - txfee) to the master account - coin.getBalance(from.toLowerCase(), function(err, balance) { + coin.sendFrom(from.toLowerCase(), address, balance - settings.coin.withdrawal_fee, function(err, reply) { if(err) { - winston.error('Something went wrong while transferring fees', err); + winston.error('Error in !withdraw command', err); + client.say(channel, settings.messages.error.expand({name: from})); return; } - var balance = typeof(balance) == 'object' ? balance.result : balance; - coin.move(from.toLowerCase(), settings.rpc.master_account, balance, function(err) { + var values = {name: from, address: address, balance: balance, amount: balance - settings.coin.withdrawal_fee, transaction: reply} + for(var i = 0; i < settings.messages.withdraw_success.length; i++) { + var msg = settings.messages.withdraw_success[i]; + client.say(channel, msg.expand(values)); + }; + + // transfer the rest (usually withdrawal fee - txfee) to bots wallet + coin.getBalance(from.toLowerCase(), function(err, balance) { if(err) { winston.error('Something went wrong while transferring fees', err); return; } + + var balance = typeof(balance) == 'object' ? balance.result : balance; + coin.move(from.toLowerCase(), settings.login.nickname, balance, function(err) { + if(err) { + winston.error('Something went wrong while transferring fees', err); + return; + } + }); }); }); }); - }); - } else { - winston.warn('%s tried to withdraw to an invalid address', from); - client.say(channel, settings.messages.invalid_address.expand({address: address, name: from})); + } else { + winston.warn('%s tried to withdraw to an invalid address', from); + client.say(channel, settings.messages.invalid_address.expand({address: address, name: from})); + } + }); + break; + case 'help': + for(var i = 0; i < settings.messages.help.length; i++) { + var message = settings.messages.help[i]; + client.say(channel, message.expand({})); } - }); + break; } }); diff --git a/config/config.yml b/config/config.yml index 829d2f0..5dafedc 100644 --- a/config/config.yml +++ b/config/config.yml @@ -1,13 +1,15 @@ connection: - host: irc.freenode.net + host: rajaniemi.freenode.net port: 6667 secure: false + status_command: ACC login: nickname: nodetip username: nodetip realname: node.js dogecoin tipping bot channels: - '##unek' + - '##tipbots' log: file: tipbot.log rpc: @@ -15,14 +17,29 @@ rpc: port: 22555 user: dogecoinrpc pass: pass - master_account: nodetip coin: withdrawal_fee: 2 min_withdraw: 5 min_confirmations: 3 - min_tip: 5 - short_name: ' DOGE' + min_tip: 10 + short_name: Đ full_name: dogecoin +commands: + help: + pm: true + channel: false + tip: + pm: true + channel: true + balance: + pm: true + channel: false + withdraw: + pm: true + channel: false + address: + pm: true + channel: false messages: error: 'Sorry %name%, something went wrong.' no_funds: "Sorry %name%, you don't have enough funds (you're %short%%short_name% short)" @@ -30,10 +47,18 @@ messages: tipped: 'Wow! %from% tipped %to% %amount%%short_name%! "/msg %nick% help" to claim.' balance: '%name% has %balance%%short_name%.' balance_unconfirmed: '%name% has %balance%%short_name% (unconfirmed: %unconfirmed%%short_name%)' - deposit_address: "%name%'s deposit address is %address%" + deposit_address: Your deposit address %address% withdraw_too_small: 'Sorry %name%, you need to withdraw at least %min_withdraw%%short_name% (you have %balance%%short_name%)' invalid_address: 'Sorry %name%, the address you specified is invalid (%address%).' - withdraw_success: '%name%: %amount%%short_name% has been withdrawn from your account to %address%' - withdraw_success2: 'You have been charged %withdrawal_fee%%short_name% withdrawal fee. Transaction id: %transaction%.' 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!" \ No newline at end of file + tip_self: "Sorry %name%, you can't tip yourself!" + withdraw_success: + - '%name%: %amount%%short_name% has been withdrawn from your account to %address%' + - 'You have been charged %withdrawal_fee%%short_name% withdrawal fee.' + - 'Transaction %transaction% completed.' + help: + - 'You can use following commands:' + - 'balance - displays your current wallet balance' + - 'address - displays %full_name% address where you can send your funds to the tip bot' + - 'withdraw <%full_name% address> - withdraws your whole wallet balance to specified address (taking %withdrawal_fee% withdrawal fee)' + - 'tip - sends the specified amount of %full_name% to the specified nickname' \ No newline at end of file