Advertisement
jwinterm

tipbot

Mar 5th, 2015
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. var irc    = require('irc'),
  2.   winston  = require('winston'),
  3.   fs       = require('fs'),
  4. //  http     = require('http'),
  5. //  https    = require('https'),
  6. //  http     = require('follow-redirects').http,
  7. //  https    = require('follow-redirects').https,
  8.   request  = require('request'),
  9.   yaml     = require('js-yaml'),
  10.   coin     = require('node-dogecoin'),
  11.   webadmin = require('../lib/webadmin/app');
  12.  
  13. // check if the config file exists
  14. if(!fs.existsSync('./config/config.yml')) {
  15.   winston.error('Configuration file doesn\'t exist! Please read the README.md file first.');
  16.   process.exit(1);
  17. }
  18.  
  19. // handle sigint
  20. process.on('exit', function() {
  21.   winston.info('Exiting...');
  22.   if(client != null) {
  23.     client.disconnect('My master ordered me to leave.');
  24.   }
  25. });
  26.  
  27. // load settings
  28. var settings = yaml.load(fs.readFileSync('./config/config.yml', 'utf-8'));
  29.  
  30. // load winston's cli defaults
  31. winston.cli();
  32.  
  33. // write logs to file
  34. if(settings.log.file) {
  35.   winston.add(winston.transports.File, {
  36.     filename: settings.log.file,
  37.     level: 'debug'});
  38. }
  39.  
  40. // connect to coin json-rpc
  41. winston.info('Connecting to coind...');
  42.  
  43. var coin = coin({
  44.   host: settings.rpc.host,
  45.   port: settings.rpc.port,
  46.   user: settings.rpc.user,
  47.   pass: settings.rpc.pass
  48. });
  49.  
  50. coin.getBalance(function(err, balance) {
  51.   if(err) {
  52.     winston.error('Could not connect to %s RPC API! ', settings.coin.full_name, err);
  53.     process.exit(1);
  54.     return;
  55.   }
  56.  
  57.   var balance = typeof(balance) == 'object' ? balance.result : balance;
  58.   winston.info('Connected to JSON RPC API. Current total balance is %d' + settings.coin.short_name, balance);
  59. })
  60.  
  61. // run webadmin
  62. if(settings.webadmin.enabled)
  63. {
  64.   winston.info('Running webadmin on port %d', settings.webadmin.port);
  65.   webadmin.app(settings.webadmin.port, coin, settings, winston);
  66. }
  67.  
  68. // connect to the server
  69. winston.info('Connecting to the server...');
  70.  
  71. var client = new irc.Client(settings.connection.host, settings.login.nickname, {
  72.   port:   settings.connection.port,
  73.   secure: settings.connection.secure,
  74.  
  75.   userName: settings.login.username,
  76.   realName: settings.login.realname,
  77.  
  78.   debug: settings.connection.debug
  79. });
  80.  
  81. // gets user's login status
  82. irc.Client.prototype.isIdentified = function(nickname, callback) {
  83.   // request login status
  84.   this.say('NickServ', 'ACC ' + nickname);
  85.  
  86.   // wait for response
  87.   var listener = function(from, to, message) {
  88.    // proceed only on NickServ's ACC response
  89.     var regexp = new RegExp('^(\\S+) ACC (\\d)');
  90.     if(from != undefined && from.toLowerCase() == 'nickserv' && regexp.test(message)) {
  91.       var match = message.match(regexp);
  92.       var user  = match[1];
  93.       var level = match[2];
  94.  
  95.       // if the right response, call the callback and remove this listener
  96.       if(user.toLowerCase() == nickname.toLowerCase()) {
  97.         callback(level == 3);
  98.         this.removeListener('notice', listener);
  99.       }
  100.     }
  101.   }
  102.  
  103.   this.addListener('notice', listener);
  104. }
  105.  
  106. irc.Client.prototype.getNames = function(channel, callback) {
  107.   client.send('NAMES', channel);
  108.   var listener = function(nicks) {
  109.     var names = [];
  110.     for(name in nicks) {
  111.       names.push(name);
  112.     }
  113.     callback(names);
  114.     this.removeListener('names' + channel, listener);
  115.   }
  116.  
  117.   this.addListener('names' + channel, listener);
  118. }
  119.  
  120. irc.Client.prototype.getAddress = function(nickname, callback) {
  121.   winston.debug('Requesting address for %s', nickname);
  122.   coin.send('getaccountaddress', settings.rpc.prefix + nickname.toLowerCase(), function(err, address) {
  123.     if(err) {
  124.       winston.error('Something went wrong while getting address. ' + err);
  125.       callback(err);
  126.  
  127.       return false;
  128.     }
  129.  
  130.     callback(false, address);
  131.   });
  132. }
  133.  
  134. String.prototype.expand = function(values) {
  135.   var global = {
  136.     nick: client.nick
  137.   }
  138.   return this.replace(/%([a-zA-Z_]+)%/g, function(str, variable) {
  139.     return typeof(values[variable]) == 'undefined' ?
  140.       (typeof(settings.coin[variable]) == 'undefined' ?
  141.         (typeof(global[variable]) == 'undefined' ?
  142.           str : global[variable]) : settings.coin[variable]) : values[variable];
  143.   });
  144. }
  145.  
  146. // basic handlers
  147. client.addListener('registered', function(message) {
  148.   winston.info('Connected to %s.', message.server);
  149.  
  150.   client.say('NickServ', 'IDENTIFY ' + settings.login.nickserv_password);
  151. });
  152.  
  153. client.addListener('error', function(message) {
  154.   winston.error('Received an error from IRC network: ', message);
  155. });
  156.  
  157.  
  158. function escapeHtml(text) {
  159.   return text
  160.     .replace(/&/g, "&")
  161.     .replace(/&lt;/g, "<")
  162.     .replace(/&gt;/g, ">")
  163.     .replace(/&quot;/g, '"')
  164.     .replace(/&#039;/g, "'")
  165.     .replace(/&laquo;/g, "<<")
  166.     .replace(/&raquo;/g, ">>")
  167. }
  168.  
  169. var urlRegExp = new RegExp("https?://[a-z0-9\\.\\-]+(\\S*)");
  170. var titleRegExp = new RegExp("<title[^>]*>([^]+?)</title>", "i");
  171. client.addListener('message', function(from, channel, message) {
  172.   //Check urls and say title
  173.   if(urlRegExp.test(message)) {
  174.     var url = urlRegExp.exec(message)[0];
  175.     request(url, function(error, response, body) {
  176.       if (!error && response.statusCode == 200) {
  177.         // console.log(body);
  178.         var match = titleRegExp.exec(body);
  179.         if(match && match[1]){
  180.           client.say(channel, 'Title: ' + escapeHtml(match[1].trim()));
  181.         }
  182.       } else {
  183.         client.say(channel, 'Error finding URL');
  184.       }
  185.     });
  186.   }
  187. });
  188.  
  189. var last_active = {};
  190. var locks       = [];
  191. var inGame      = [];
  192.  
  193. client.addListener('message', function(from, channel, message) {
  194.   last_active[from] = Date.now();
  195.   var match = message.match(/^(!?)(\S+)/);
  196.   if(match == null) return;
  197.   var prefix  = match[1];
  198.   var command = match[2];
  199.  
  200.  
  201.   if(settings.commands[command]) {
  202.     if(channel == client.nick && settings.commands[command].pm === false) return;
  203.     if(channel != client.nick && (settings.commands[command].channel === false || prefix != '!')) return;
  204.   } else {
  205.     return;
  206.   }
  207.  
  208.  
  209.   // if pms, make sure to respond to pms instead to itself
  210.   if(channel == client.nick) channel = from;
  211.  
  212.   // comands that don't require identifying
  213.   if(command == 'help' || command == 'terms') {
  214.     var msg = [];
  215.     for(var i = 0; i < settings.messages[command].length; i++) {
  216.       client.say(from, settings.messages[command][i].expand({}));
  217.     }
  218.     return;
  219.   }
  220.  
  221.   // if not that, message will be undefined for some reason
  222.   // todo: find a fix for that
  223.   var msg = message;
  224.  
  225.   var balance;
  226.  
  227.   client.isIdentified(from, function(status) {
  228.     var message = msg;
  229.     // check user balance up front
  230.     coin.getBalance(settings.rpc.prefix + from.toLowerCase(), settings.coin.min_confirmations, function(err, balance) {
  231.       if(err) {
  232.         locks[from.toLowerCase()] = null;          
  233.         winston.error('Error in !tip command.', err);
  234.         client.say(channel, settings.messages.error.expand({name: from}));
  235.         return;
  236.       }
  237.       if (balance) {
  238.         balance = typeof(balance) == 'object' ? balance.result : balance;
  239.         console.log(balance);
  240.       }
  241.     })
  242.      
  243.     // check if the sending user is logged in (identified) with nickserv
  244.     if(!status) {
  245.       winston.info('%s tried to use command `%s`, but is not identified.', from, message);
  246.       client.say(channel, settings.messages.not_identified.expand({name: from}));
  247.       return;
  248.     }
  249.  
  250.     console.log(balance);
  251.     console.log(locks);
  252.    
  253.     switch(command) {
  254.        
  255.       case 'rain':
  256.         var match = message.match(/^.?rain (random)?([\d\.]+) ?(\d+)?/);
  257.         if(match == null || !match[2]) {
  258.           client.say(channel, 'Usage: !rain <amount> [max people]');
  259.           return;
  260.         }
  261.         console.log(match);
  262.         var random = match[1];
  263.         var amount = Number(match[2]);
  264.         var max    = Number(match[3]);
  265.  
  266.         if(isNaN(amount)) {
  267.           client.say(channel, settings.messages.invalid_amount.expand({name: from, amount: match[2]}));
  268.           return;
  269.         }
  270.  
  271.         if(random) {
  272.           var min = settings.coin.min_rain;
  273.           var maxAmount = amount;
  274.           amount  = Math.floor(Math.random() * (maxAmount - min + 1)) + min;
  275.         }
  276.  
  277.         if(isNaN(max) || max < 1) {
  278.           max = false;
  279.         } else {
  280.           max = Math.floor(max);
  281.         }
  282.        
  283.         // lock
  284.         if(locks.hasOwnProperty(from.toLowerCase()) && locks[from.toLowerCase()]) return;
  285.         locks[from.toLowerCase()] = true;
  286.        
  287.         coin.getBalance(settings.rpc.prefix + from.toLowerCase(), settings.coin.min_confirmations, function(err, balance) {
  288.           if(err) {
  289.             locks[from.toLowerCase()] = null;          
  290.             winston.error('Error in !tip command.', err);
  291.             client.say(channel, settings.messages.error.expand({name: from}));
  292.             return;
  293.           }
  294.           var balance = typeof(balance) == 'object' ? balance.result : balance;
  295.  
  296.           if(balance >= amount) {
  297.             client.getNames(channel, function(names) {
  298.               // rain only on nicknames active within the last x seconds
  299.               if(settings.commands.rain.rain_on_last_active) {
  300.                 for (var i = names.length - 1; i >= 0; i--) {
  301.                   if(!last_active.hasOwnProperty(names[i]) || last_active[names[i]] + settings.commands.rain.rain_on_last_active * 1000 < Date.now()) {
  302.                     names.splice(i, 1);
  303.                   }
  304.                 };
  305.               }
  306.               // remove tipper from the list
  307.               names.splice(names.indexOf(from), 1);
  308.               // shuffle the array
  309.               for(var j, x, i = names.length; i; j = Math.floor(Math.random() * i), x = names[--i], names[i] = names[j], names[j] = x);
  310.  
  311.               max = max ? Math.min(max, names.length) : names.length;
  312.               if(max == 0) return;
  313.               var whole_channel = false;
  314.               if(max == names.length) whole_channel = true;
  315.               names = names.slice(0, max);
  316.  
  317.               if(amount / max < settings.coin.min_rain) {
  318.                 locks[from.toLowerCase()] = null;              
  319.                 client.say(channel, settings.messages.rain_too_small.expand({from: from, amount: amount, min_rain: settings.coin.min_rain * max}));
  320.                 return;
  321.               }
  322.  
  323.               for (var i = 0; i < names.length; i++) {
  324.                 coin.move(settings.rpc.prefix + from.toLowerCase(), settings.rpc.prefix + names[i].toLowerCase(), amount / max, function(err, reply) {
  325.                   if(i == names.length) locks[from.toLowerCase()] = null;
  326.                   if(err || !reply) {
  327.                     winston.error('Error in !tip command', err);
  328.                     return;
  329.                   }
  330.                 });
  331.               }
  332.  
  333.               client.say(channel, settings.messages.rain.expand({name: from, amount: amount / max, list: (whole_channel && !settings.commands.rain.rain_on_last_active) ? 'the whole channel' : names.join(', ')}));
  334.             });
  335.           } else {
  336.             locks[from.toLowerCase()] = null;
  337.             winston.info('%s tried to tip %s %d, but has only %d', from, to, amount, balance);
  338.             client.say(channel, settings.messages.no_funds.expand({name: from, balance: balance, short: amount - balance, amount: amount}));
  339.           }
  340.         })
  341.         break;
  342.        
  343.        
  344.       case 'rainall':
  345.         var match = message.match(/^.?rainall (random)?([\d\.]+)/);
  346.         if(match == null || !match[2]) {
  347.           client.say(channel, 'Usage: !rainall <amount>');
  348.           return;
  349.         }
  350.  
  351.         var random = match[1];
  352.         var amount = Number(match[2]);
  353.  
  354.         if(isNaN(amount)) {
  355.           client.say(channel, settings.messages.invalid_amount.expand({name: from, amount: match[2]}));
  356.           return;
  357.         }
  358.  
  359.         if(random) {
  360.           var min = settings.coin.min_rain;
  361.           var maxAmount = amount;
  362.           amount  = Math.floor(Math.random() * (maxAmount - min + 1)) + min;
  363.         }
  364.  
  365.         if(isNaN(max) || max < 1) {
  366.           max = false;
  367.         } else {
  368.           max = Math.floor(max);
  369.         }
  370.        
  371.         // lock
  372.         if(locks.hasOwnProperty(from.toLowerCase()) && locks[from.toLowerCase()]) return;
  373.         locks[from.toLowerCase()] = true;
  374.        
  375.         coin.getBalance(settings.rpc.prefix + from.toLowerCase(), settings.coin.min_confirmations, function(err, balance) {
  376.           if(err) {
  377.             locks[from.toLowerCase()] = null;
  378.             winston.error('Error in !tip command.', err);
  379.             client.say(channel, settings.messages.error.expand({name: from}));
  380.             return;
  381.           }
  382.           var balance = typeof(balance) == 'object' ? balance.result : balance;
  383.  
  384.           if(balance >= amount) {
  385.             client.getNames(channel, function(names) {
  386.               names.splice(names.indexOf(from), 1);
  387.               names.splice(names.indexOf("myrbot"), 1);
  388.               // shuffle the array
  389.               for(var j, x, i = names.length; i; j = Math.floor(Math.random() * i), x = names[--i], names[i] = names[j], names[j] = x);
  390.  
  391.               max = max ? Math.min(max, names.length) : names.length;
  392.               if(max == 0) return;
  393.               var whole_channel = false;
  394.               if(max == names.length) whole_channel = true;
  395.               names = names.slice(0, max);
  396.  
  397.               if(amount / max < settings.coin.min_rain) {
  398.                 locks[from.toLowerCase()] = null;
  399.                 client.say(channel, settings.messages.rain_too_small.expand({from: from, amount: amount, min_rain: settings.coin.min_rain * max}));
  400.                 return;
  401.               }
  402.  
  403.               for (var i = 0; i < names.length; i++) {
  404.                 coin.move(settings.rpc.prefix + from.toLowerCase(), settings.rpc.prefix + names[i].toLowerCase(), amount / max, function(err, reply) {
  405.                   if(i == names.length) locks[from.toLowerCase()] = null;
  406.                   if(err || !reply) {
  407.                     winston.error('Error in !tip command', err);
  408.                     return;
  409.                   }
  410.                 });
  411.               }
  412.  
  413.               client.say(channel, settings.messages.rain.expand({name: from, amount: amount / max, list: (whole_channel && !settings.commands.rain.rain_on_last_active) ? 'the whole channel' : names.join(', ')}));
  414.             });
  415.           } else {
  416.             locks[from.toLowerCase()] = null;
  417.             winston.info('%s tried to tip %s %d, but has only %d', from, to, amount, balance);
  418.             client.say(channel, settings.messages.no_funds.expand({name: from, balance: balance, short: amount - balance, amount: amount}));
  419.           }
  420.         })
  421.         break;
  422.        
  423.        
  424.       case 'tip':
  425.         var match = message.match(/^.?tip (\S+) (random)?([\d\.]+)/);
  426.         if(match == null || match.length < 3) {
  427.           client.say(channel, 'Usage: !tip <nickname> <amount>')
  428.           return;
  429.         }
  430.         var to     = match[1];
  431.         var random = match[2];
  432.         var amount = Number(match[3]);
  433.  
  434.         // lock
  435.         if(locks.hasOwnProperty(from.toLowerCase()) && locks[from.toLowerCase()]) return;
  436.         locks[from.toLowerCase()] = true;        
  437.        
  438.         if(isNaN(amount)) {
  439.           client.say(channel, settings.messages.invalid_amount.expand({name: from, amount: match[3]}));
  440.           return;
  441.         }
  442.  
  443.         if(random) {
  444.           var min = settings.coin.min_tip;
  445.           var max = amount;
  446.           amount  = Math.floor(Math.random() * (max - min + 1)) + min;
  447.         }
  448.  
  449.         if(to.toLowerCase() == from.toLowerCase()) {
  450.           locks[from.toLowerCase()] = null;
  451.           client.say(channel, settings.messages.tip_self.expand({name: from}));
  452.           return;
  453.         }
  454.  
  455.         if(amount < settings.coin.min_tip) {
  456.           locks[from.toLowerCase()] = null;
  457.           client.say(channel, settings.messages.tip_too_small.expand({from: from, to: to, amount: amount}));
  458.           return;
  459.         }
  460.         // check balance with min. 5 confirmations
  461.         coin.getBalance(settings.rpc.prefix + from.toLowerCase(), settings.coin.min_confirmations, function(err, balance) {
  462.           if(err) {
  463.             locks[from.toLowerCase()] = null;
  464.             winston.error('Error in !tip command.', err);
  465.             client.say(channel, settings.messages.error.expand({name: from}));
  466.             return;
  467.           }
  468.           var balance = typeof(balance) == 'object' ? balance.result : balance;
  469.  
  470.           if(balance >= amount) {
  471.             coin.send('move', settings.rpc.prefix + from.toLowerCase(), settings.rpc.prefix + to.toLowerCase(), amount, function(err, reply) {
  472.               locks[from.toLowerCase()] = null;
  473.               if(err || !reply) {
  474.                 winston.error('Error in !tip command', err);
  475.                 client.say(channel, settings.messages.error.expand({name: from}));
  476.                 return;
  477.               }
  478.  
  479.               winston.info('%s tipped %s %d%s', from, to, amount, settings.coin.short_name)
  480.               client.say(channel, settings.messages.tipped.expand({from: from, to: to, amount: amount}));
  481.             });
  482.           } else {
  483.             locks[from.toLowerCase()] = null;
  484.             winston.info('%s tried to tip %s %d, but has only %d', from, to, amount, balance);
  485.             client.say(channel, settings.messages.no_funds.expand({name: from, balance: balance, short: amount - balance, amount: amount}));
  486.           }
  487.         });
  488.         break;
  489.        
  490.        
  491.       case 'address':
  492.         var user = from.toLowerCase();
  493.         client.getAddress(user, function(err, address) {
  494.           if(err) {
  495.             winston.error('Error in !address command', err);
  496.             client.say(channel, settings.messages.error.expand({name: from}));
  497.             return;
  498.           }
  499.  
  500.           client.say(channel, settings.messages.deposit_address.expand({name: user, address: address}));
  501.         });
  502.         break;
  503.        
  504.        
  505.       case 'balance':
  506.         var user = from.toLowerCase();
  507.         coin.getBalance(settings.rpc.prefix + user, settings.coin.min_confirmations, function(err, balance) {
  508.           if(err) {
  509.             winston.error('Error in !balance command', err);
  510.             client.say(channel, settings.messages.error.expand({name: from}));
  511.             return;
  512.           }
  513.  
  514.           var balance = typeof(balance) == 'object' ? balance.result : balance;
  515.  
  516.           coin.getBalance(settings.rpc.prefix + user, 0, function(err, unconfirmed_balance) {
  517.           if(err) {
  518.               winston.error('Error in !balance command', err);
  519.               client.say(channel, settings.messages.balance.expand({balance: balance, name: user}));
  520.               return;
  521.             }
  522.  
  523.             var unconfirmed_balance = typeof(unconfirmed_balance) == 'object' ? unconfirmed_balance.result : unconfirmed_balance;
  524.  
  525.             client.say(channel, settings.messages.balance_unconfirmed.expand({balance: balance, name: user, unconfirmed: unconfirmed_balance - balance}));
  526.           })
  527.         });
  528.         break;
  529.        
  530.  
  531.       case 'dice':
  532.         var match = message.match(/^.?dice ([\d\.]+) ?(10|5|2)?/);
  533.         if(match == null || !match[1]) {
  534.           client.say(channel, 'Usage: !dice <amount> [multiplier]\nmultiplier should be either 2, 5, or 10 (default 2)');
  535.           return;
  536.         }
  537.         console.log(match);
  538.         console.log(match[1]);
  539.         console.log(match[2]);
  540.        
  541.         var maxBet = 100;
  542.        
  543.         var amount = Number(match[1]);
  544.         if (Number(match[2])) {
  545.             var multiplier = Number(match[2]);
  546.         } else {
  547.             var multiplier = 2;
  548.         }
  549.        
  550.  
  551.         if(isNaN(amount)) {
  552.           client.say(channel, settings.messages.invalid_amount.expand({name: from, amount: match[2]}));
  553.           return;
  554.         }
  555.  
  556.         if(amount > maxBet) {
  557.           client.say(channel, "Max bet is " + maxBet);
  558.           return;
  559.         }
  560.        
  561.         // lock
  562.         if(locks.hasOwnProperty(from.toLowerCase()) && locks[from.toLowerCase()]) return;
  563.         locks[from.toLowerCase()] = true;
  564.        
  565.         coin.getBalance(settings.rpc.prefix + from.toLowerCase(), settings.coin.min_confirmations, function(err, balance) {
  566.           if(err) {
  567.             locks[from.toLowerCase()] = null;          
  568.             winston.error('Error in !dice command.', err);
  569.             client.say(channel, settings.messages.error.expand({name: from}));
  570.             return;
  571.           }
  572.           var balance = typeof(balance) == 'object' ? balance.result : balance;
  573.  
  574.           if(balance >= amount) {
  575.             console.log(amount, multiplier);
  576.             var roll = Math.random();
  577.            
  578.             if (roll < (1/multiplier - 0.01)) {
  579.               if (multiplier == 2) {
  580.                   var winnings = amount;
  581.               } else {
  582.                   var winnings = amount*multiplier;
  583.               }
  584.               coin.send('move', settings.rpc.prefix + "myrbot", settings.rpc.prefix + from.toLowerCase(), winnings, function(err, reply) {
  585.               locks[from.toLowerCase()] = null;
  586.               if(err || !reply) {
  587.                 winston.error('Error in !dice command', err);
  588.                 client.say(channel, settings.messages.error.expand({name: from}));
  589.                 return;
  590.               }
  591.  
  592.               winston.info('%s transferred %s %d%s', "myrbot", from, winnings, settings.coin.short_name)
  593.               client.say(channel, from + " rolled " + Number(roll).toFixed(4) + " on target of " + Number(1/multiplier - 0.01).toFixed(2) + "...win " + winnings + " MYR!");
  594.               });
  595.             }
  596.            
  597.             else {
  598.               coin.send('move', settings.rpc.prefix + settings.rpc.prefix + from.toLowerCase(), "myrbot", amount, function(err, reply) {
  599.               locks[from.toLowerCase()] = null;
  600.               if(err || !reply) {
  601.                 winston.error('Error in !dice command', err);
  602.                 client.say(channel, settings.messages.error.expand({name: from}));
  603.                 return;
  604.               }
  605.  
  606.               winston.info('%s transferred %s %d%s', from, "myrbot", amount, settings.coin.short_name)
  607.               client.say(channel, from + " rolled " + Number(roll).toFixed(4) + " on target of " + Number(1/multiplier - 0.01).toFixed(2) + "...lose " + amount + " MYR!");
  608.               });
  609.             }
  610.           }  
  611.           else {
  612.             locks[from.toLowerCase()] = null;
  613.             winston.info('%s tried to roll %d, but has only %d', from, amount, balance);
  614.             client.say(channel, settings.messages.no_funds.expand({name: from, balance: balance, short: amount - balance, amount: amount}));
  615.           }
  616.         })
  617.         break;        
  618.        
  619.        
  620.       case 'withdraw':
  621.         var match = message.match(/^.?withdraw (\S+)$/);
  622.         if(match == null) {
  623.           client.say(channel, 'Usage: !withdraw <' + settings.coin.full_name + ' address>');
  624.           return;
  625.         }
  626.         var address = match[1];
  627.  
  628.         coin.validateAddress(address, function(err, reply) {
  629.           if(err) {
  630.             winston.error('Error in !withdraw command', err);
  631.             client.say(channel, settings.messages.error.expand({name: from}));
  632.             return;
  633.           }
  634.  
  635.           if(reply.isvalid) {
  636.             coin.getBalance(settings.rpc.prefix + from.toLowerCase(), settings.coin.min_confirmations, function(err, balance) {
  637.               if(err) {
  638.                 winston.error('Error in !withdraw command', err);
  639.                 client.say(channel, settings.messages.error.expand({name: from}));
  640.                 return;
  641.               }
  642.               var balance = typeof(balance) == 'object' ? balance.result : balance;
  643.  
  644.               if(balance < settings.coin.min_withdraw) {
  645.                 winston.warn('%s tried to withdraw %d, but min is set to %d', from, balance, settings.coin.min_withdraw);
  646.                 client.say(channel, settings.messages.withdraw_too_small.expand({name: from, balance: balance}));
  647.                 return;
  648.               }
  649.  
  650.               coin.sendFrom(settings.rpc.prefix + from.toLowerCase(), address, balance - settings.coin.withdrawal_fee, function(err, reply) {
  651.                 if(err) {
  652.                   winston.error('Error in !withdraw command', err);
  653.                   client.say(channel, settings.messages.error.expand({name: from}));
  654.                   return;
  655.                 }
  656.  
  657.                 var values = {name: from, address: address, balance: balance, amount: balance - settings.coin.withdrawal_fee, transaction: reply}
  658.                 for(var i = 0; i < settings.messages.withdraw_success.length; i++) {
  659.                   var msg = settings.messages.withdraw_success[i];
  660.                   client.say(channel, msg.expand(values));
  661.                 };
  662.  
  663.                 // transfer the rest (withdrawal fee - txfee) to bots wallet
  664.                 coin.getBalance(settings.rpc.prefix + from.toLowerCase(), function(err, balance) {
  665.                   if(err) {
  666.                     winston.error('Something went wrong while transferring fees', err);
  667.                     return;
  668.                   }
  669.  
  670.                   var balance = typeof(balance) == 'object' ? balance.result : balance;
  671.  
  672.                   // moves the rest to bot's wallet
  673.                   coin.move(settings.rpc.prefix + from.toLowerCase(), settings.rpc.prefix + settings.login.nickname.toLowerCase(), balance);
  674.                 });
  675.               });
  676.             });
  677.           } else {
  678.             winston.warn('%s tried to withdraw to an invalid address', from);
  679.             client.say(channel, settings.messages.invalid_address.expand({address: address, name: from}));
  680.           }
  681.         });
  682.         break;
  683.     }
  684.   });
  685. });
  686.  
  687. client.addListener('notice', function(nick, to, text, message) {
  688.   if(nick && nick.toLowerCase() == 'nickserv' && !text.match(/ ACC /)) {
  689.     winston.info('%s: %s', nick, text);
  690.     if(text.match(/^You are now identified/)) {
  691.       for (var i = settings.channels.length - 1; i >= 0; i--) {
  692.         client.join(settings.channels[i]);
  693.       };
  694.     }
  695.   }
  696. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement