A Twitch.tv viewer reward and games system.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1353 lines
54 KiB

11 years ago
  1. /**
  2. * api:
  3. * Currency(irc object, database object, [required options])
  4. *
  5. * example:
  6. * var Currency = require('./lib/plugins/currency.js')(irc, db, {
  7. * currency : 'currency name',
  8. * subscribers : 'google doc spreadsheet until it's available from twitch api'
  9. * });
  10. *
  11. * commands:
  12. * !<currency>
  13. * reply with currency amount
  14. *
  15. * !<currency> on/[off repeat on/off]
  16. * toggle currency request status,
  17. * repeat status only available when
  18. * turning off requests
  19. *
  20. * !<currency> auction open
  21. * open a new auction
  22. *
  23. * !<currency> auction close
  24. * close current auction
  25. *
  26. * !<currency> auction cancel
  27. * cancel current auction
  28. *
  29. * !<currency> auction draw
  30. * draw the next highest bidder
  31. *
  32. * !bid <amount>
  33. * place a bid on an open auction,
  34. * only valid amounts will be accepted
  35. *
  36. * !<currency> raffle open <price> <max>
  37. * open a new raffle
  38. * price and max is optional
  39. * default price: 10
  40. * default max: 10
  41. *
  42. * !<currency> raffle close
  43. * draw the another ticket from raffle
  44. *
  45. * !<currency> raffle cancel
  46. * cancel the open raffle
  47. *
  48. * !<currency> raffle draw
  49. * open a new auction
  50. *
  51. * !<currency> raffle restore
  52. * restores a previous raffle if a new
  53. * one is accidentally opened
  54. *
  55. * !ticket <amount>
  56. * place a bid on an open auction,
  57. * only valid amounts will be accepted
  58. */
  59. var https = require('https'),
  60. http = require('http'),
  61. utils = require('./utils.js');
  62. //-------- Construct ---------
  63. function Currency(irc, db, options) {
  64. var __self = this;
  65. __self.irc = irc;
  66. __self.db = db;
  67. // config
  68. __self.config = options || {};
  69. __self.config.currency = options.currency || 'coins';
  70. __self.config.subscribers_json = options.subscribers || '';
  71. __self.config.website = options.website || '';
  72. // general settings
  73. __self.pre_text = '> ' + __self.config.currency + ': ';
  74. __self.max_requests = 10;//response after 10 request
  75. __self.temp = {};
  76. // currency request settings
  77. __self.coin_flood = [];
  78. __self.coin_response = null;
  79. __self.coin_response_timer = 3000;
  80. __self.coin_response_reset = true;
  81. __self.coin_toggle = false;
  82. __self.coin_toggle_msg = null;
  83. __self.coin_toggle_timer = 180000;//milliseconds
  84. // auction settings
  85. __self.auction_status = false;
  86. __self.auction_bids = [];
  87. __self.auction_previous_bid = {};
  88. __self.auction_bid_response = null;
  89. __self.auction_bid_response_long = null;
  90. // handout coins settings
  91. __self.viewer_list = [];
  92. __self.streaming = false;
  93. __self.streaming_check = 4;//minutes
  94. __self.give_coins = false;
  95. __self.give_coins_timer = options.payrate || 30;//minutes
  96. __self.subscriber_check = 4;//minutes
  97. __self.subscribers = [];
  98. // raffle settings
  99. __self.raffle_status = false;
  100. __self.raffle_ticket_requests = [];
  101. __self.raffle_tickets = [];
  102. __self.raffle_ticket_cost = 10;//currency cost per ticket
  103. __self.raffle_max_tickets = 10;
  104. // raffle restoration
  105. __self.raffle_restore_ticket_requests = [];
  106. __self.raffle_restore_tickets = [];
  107. // gambling settings
  108. __self.bets_status = false;
  109. __self.bets_board = [];
  110. __self.bets_viewers = [];
  111. __self.bets_payout = false;
  112. }
  113. //-------- Methods ---------
  114. Currency.prototype.start = function () {
  115. var __self = this;
  116. __self.handout_coins();
  117. };
  118. Currency.prototype.commands = function (data) {
  119. var __self = this,
  120. broadcaster_bot_initiated = __self.irc.caller(data[0]).toLowerCase() === __self.irc.config.broadcaster.toLowerCase() || __self.irc.caller(data[0]).toLowerCase() === __self.irc.config.name.toLowerCase(),
  121. moderator_initiated = __self.irc.mods.indexOf(__self.irc.caller(data[0])) > 0;
  122. // handle !<currency> commands
  123. if (data[3].slice(1) === '!' + __self.config.currency.toLowerCase()) {
  124. // public commands
  125. if (!__self.coin_toggle && data[4] === undefined) {
  126. __self.get_coins(__self.irc.caller(data[0]));
  127. }
  128. // broadcaster only commands
  129. if (broadcaster_bot_initiated) {
  130. //open / close auction system
  131. if (data[4] === 'auction') {
  132. switch (data[5]) {
  133. case 'open':
  134. __self.auction(true);
  135. break;
  136. case 'close':
  137. __self.auction(false);
  138. break;
  139. case 'draw':
  140. __self.next_auction_winner();
  141. break;
  142. case 'cancel':
  143. __self.auction('cancel');
  144. break;
  145. }
  146. }
  147. // open / close raffle system
  148. if (data[4] === 'raffle') {
  149. switch (data[5]) {
  150. case 'open':
  151. if (data[6] && data[7] && !__self.raffle_status) {
  152. if(parseInt(data[6], 10) > 0 && parseInt(data[7], 10) > 0) {
  153. // save default values
  154. __self.temp.raffle_ticket_cost = __self.raffle_ticket_cost;
  155. __self.temp.raffle_max_tickets = __self.raffle_max_tickets;
  156. // set new raffle cost / amount
  157. __self.raffle_ticket_cost = data[6];
  158. __self.raffle_max_tickets = data[7];
  159. }
  160. } else if (__self.temp.raffle_ticket_cost && __self.temp.raffle_max_tickets && !__self.raffle_status){
  161. __self.raffle_ticket_cost = __self.temp.raffle_ticket_cost;
  162. __self.raffle_max_tickets = __self.temp.raffle_max_tickets;
  163. delete __self.temp.raffle_ticket_cost;
  164. delete __self.temp.raffle_max_tickets;
  165. }
  166. __self.raffle(true);
  167. break;
  168. case 'close':
  169. __self.raffle(false);
  170. break;
  171. case 'draw':
  172. __self.next_raffle_winner();
  173. break;
  174. case 'cancel':
  175. __self.raffle('cancel');
  176. break;
  177. case 'restore':
  178. __self.raffle('restore');
  179. break;
  180. }
  181. }
  182. // open / close betting system
  183. if (data[4] === 'bet') {
  184. switch (data[5]) {
  185. case 'open':
  186. if (data[5] && data[6]) {
  187. __self.bets(true, data);
  188. } else {
  189. __self.irc.emit('message', {message:__self.pre_text + 'Unable to open betting, need at least two items to bet against'});
  190. }
  191. break;
  192. case 'close':
  193. __self.bets(false, null);
  194. break;
  195. case 'winner':
  196. //__self.bets('winner');
  197. break;
  198. }
  199. }
  200. // add currency
  201. if (data[4] === 'add') {
  202. if(parseInt(data[5], 10) > 0 && data[6]) {
  203. __self.adjust_currency('add', data[5], data[6]);
  204. }
  205. }
  206. // remove currency
  207. if (data[4] === 'remove') {
  208. if(parseInt(data[5], 10) > 0 && data[6]) {
  209. __self.adjust_currency('remove', data[5], data[6]);
  210. }
  211. }
  212. // push currency to new viewer
  213. if (data[4] === 'push') {
  214. if(parseInt(data[5], 10) > 0 && data[6]) {
  215. __self.adjust_currency('push', data[5], data[6]);
  216. }
  217. }
  218. }
  219. // moderator commands
  220. if (broadcaster_bot_initiated || moderator_initiated) {
  221. // enable/disable currency requests
  222. switch (data[4]) {
  223. case 'on':
  224. if (!__self.auction_status && !__self.raffle_status) {
  225. __self.coin_toggle = false;
  226. // output currency request status
  227. __self.irc.emit('message', {message:__self.pre_text + 'Currency requests are now enabled. Type !' + __self.config.currency.toLowerCase() + ' to view your total'});
  228. // stop periodic message
  229. clearInterval(__self.coin_toggle_msg);
  230. }
  231. break;
  232. case 'off':
  233. if (!__self.auction_status && !__self.raffle_status) {
  234. var msg;
  235. if (!__self.coin_toggle) {
  236. // output message depending on if an offsite is provided
  237. if (__self.config.website !== '') {
  238. msg = __self.pre_text + 'Currency requests have been disabled. To view your ' + __self.config.currency + ' please visit ' + __self.config.website;
  239. __self.irc.emit('message', {message:msg});
  240. } else {
  241. msg = __self.pre_text + 'Currency requests have been disabled';
  242. __self.irc.emit('message', {message:msg});
  243. }
  244. }
  245. // start the periodic message
  246. if (data[5] !== undefined && data[6] !== undefined) {
  247. // manually enable / disable repeat
  248. if (data[5] === 'repeat') {
  249. switch (data[6]) {
  250. case 'on':
  251. __self.irc.emit('message', {message:'+ Periodic notification enabled'});
  252. __self.coin_toggle_msg = setInterval(function () {
  253. if (__self.coin_toggle) {
  254. msg = __self.pre_text + 'To view your ' + __self.config.currency + ' please visit ' + __self.config.website;
  255. __self.irc.emit('message', {message:msg});
  256. }
  257. }, __self.coin_toggle_timer);
  258. break;
  259. case 'off':
  260. __self.irc.emit('message', {message:'+ Periodic notification disabled'});
  261. clearInterval(__self.coin_toggle_msg);
  262. }
  263. }
  264. }
  265. __self.coin_toggle = true;
  266. }
  267. break;
  268. }
  269. // adjust currency response rate
  270. if (data[4] === 'timer') {
  271. if (isNaN(parseInt(data[5], 10)) === false) {
  272. if (data[5] >= 3 && data[5] % 1 === 0) {
  273. __self.coin_response_timer = data[5] * 1000;
  274. __self.irc.emit('message', {message:__self.pre_text + 'Currency totals will now show ' + data[5] + ' seconds after request'});
  275. if (data[6] && data[7]) {
  276. if (data[6] === 'reset') {
  277. switch(data[7]) {
  278. case 'on':
  279. __self.irc.emit('message', {message:'+ Timer will now reset after each new request'});
  280. __self.coin_response_reset = true;
  281. break;
  282. case 'off':
  283. __self.irc.emit('message', {message:'+ Timer will not reset after each new request'});
  284. __self.coin_response_reset = false;
  285. break;
  286. }
  287. }
  288. }
  289. } else if (data[5] < 3) {
  290. __self.irc.emit('message', {message:__self.pre_text + 'Timer cannot be less than 2 seconds'});
  291. }
  292. }
  293. }
  294. }
  295. }
  296. // public commands related to !<currency>
  297. switch (data[3].slice(1)) {
  298. // submit bid for the auction
  299. case '!bid':
  300. if (isNaN(parseInt(data[4], 10)) === false) {
  301. if (data[4] > 0 && data[4] % 1 === 0) {
  302. __self.bid(__self.irc.caller(data[0]), parseInt(data[4], 10));
  303. }
  304. }
  305. break;
  306. // purchase a ticket for raffle
  307. case '!ticket':
  308. if (isNaN(parseInt(data[4], 10)) === false) {
  309. if (data[4] >= 0 && data[4] % 1 === 0) {
  310. __self.collect_tickets(__self.irc.caller(data[0]), parseInt(data[4], 10));
  311. }
  312. }
  313. break;
  314. }
  315. // place a bet
  316. if (__self.bets_status === true) {
  317. for (var i = 0; i < __self.bets_board.length; i++) {
  318. if (data[3].slice(1) === '!' + __self.bets_board[i]) {
  319. if (isNaN(parseInt(data[4], 10)) === false) {
  320. if (data[4] >= 0 && data[4] % 1 === 0) {
  321. __self.collect_bets(__self.irc.caller(data[0]), __self.bets_board[i], parseInt(data[4], 10));
  322. break;
  323. }
  324. }
  325. }
  326. }
  327. }
  328. };
  329. /**
  330. * ============================================
  331. * CURRENCY REQUESTS
  332. * --------------------------------------------
  333. */
  334. Currency.prototype.get_coins = function (caller) {
  335. var __self = this;
  336. function fill_request(viewer, points) {
  337. var request = '(' + points + ')';
  338. if (__self.raffle_status) {
  339. for (var i = 0; i < __self.raffle_ticket_requests.length; i++){
  340. if (__self.raffle_ticket_requests[i].viewer.toLowerCase() === viewer.toLowerCase() && (__self.raffle_ticket_requests[i].tickets * __self.raffle_ticket_cost) <= points) {
  341. request = '(' + (points - (__self.raffle_ticket_requests[i].tickets * __self.raffle_ticket_cost)) + ') [' + __self.raffle_ticket_requests[i].tickets + ']';
  342. break;
  343. }
  344. }
  345. return request;
  346. } else {
  347. return request;
  348. }
  349. }
  350. function do_work() {
  351. var multi_response = '';
  352. if (__self.coin_flood.length > 1) {// send flood requests
  353. __self.query_coins(__self.coin_flood, function (rows) {
  354. for (var i = 0; i < rows.length; i++) {
  355. var currency_request = fill_request(rows[i].user, rows[i].points);
  356. // setup currency response
  357. if (i !== rows.length - 1) {
  358. multi_response += rows[i].user + ' ' + currency_request + ', ';
  359. } else {
  360. multi_response += rows[i].user + ' ' + currency_request;
  361. }
  362. }
  363. __self.irc.emit('message', {message:__self.pre_text + multi_response, timer: 1});
  364. });
  365. } else if (__self.coin_flood.length === 1) {// send single request
  366. __self.query_coins(caller, function (rows) {
  367. var currency_request = fill_request(rows[0].user, rows[0].points);
  368. __self.irc.emit('message', {message:__self.pre_text + caller + ' ' + currency_request, timer: 1});
  369. });
  370. }
  371. // clear flood requests
  372. __self.coin_flood = [];
  373. }
  374. // add flood users to array
  375. if (__self.coin_flood.indexOf(caller) < 0) {
  376. __self.coin_flood.push(caller);
  377. }
  378. // clear timer on flood
  379. if (__self.coin_response_reset) {
  380. clearTimeout(__self.coin_response);
  381. }
  382. // check if flood has a set amount of requests and output
  383. // if not, set the output timer
  384. if (__self.coin_flood.length === __self.max_requests) {
  385. do_work();
  386. } else {
  387. if (__self.coin_response_reset) {
  388. __self.coin_response = setTimeout(function () {do_work();}, __self.coin_response_timer);
  389. } else {
  390. setTimeout(function () {do_work();}, __self.coin_response_timer);
  391. }
  392. }
  393. };
  394. Currency.prototype.query_coins = function (data, callback) {
  395. var __self = this, sql = '';
  396. // build sql conditions
  397. if (typeof data === 'string') {
  398. sql = 'SELECT * FROM viewers WHERE ' + 'user = \'' + data.toLowerCase() + '\'';
  399. } else {
  400. for (var i = 0; i < data.length; i++) {
  401. if (i !== data.length - 1) {
  402. sql += 'SELECT * FROM viewers WHERE ' + 'user = \'' + data[i].toLowerCase() + '\'' + ';';
  403. } else {
  404. sql += 'SELECT * FROM viewers WHERE ' + 'user = \'' + data[i].toLowerCase() + '\'';
  405. }
  406. }
  407. }
  408. // execute query
  409. __self.db.execute(sql, function (rows) {
  410. var temp = [], newrows = [];
  411. if (typeof data !== 'string') {
  412. // get rid of the nested arrays
  413. for (var i = 0; i < rows.length; i++) {
  414. if (rows[i].length > 0) {
  415. newrows.push(rows[i][0]);
  416. }
  417. }
  418. // separate users into their own array
  419. for (var i = 0; i < newrows.length; i++) {
  420. temp.push(newrows[i].user.charAt(0).toUpperCase() + newrows[i].user.slice(1));
  421. }
  422. // compare the users in the data array against the temp array
  423. // if not found, push them to rows with 0 points
  424. for (var i = 0; i < data.length; i++) {
  425. if (temp.indexOf(data[i]) < 0) {
  426. newrows.push({'user' : data[i], 'points' : 0});
  427. }
  428. }
  429. // capitalize usernames on rows
  430. for (var key in newrows) {
  431. if (newrows.hasOwnProperty(key)) {
  432. newrows[key].user = newrows[key].user.charAt(0).toUpperCase() + newrows[key].user.slice(1);
  433. }
  434. }
  435. rows = newrows;
  436. } else {
  437. if (rows.length === 0) {
  438. rows = [{'user' : data, 'points' : 0}];
  439. } else {
  440. rows[0].user = rows[0].user.charAt(0).toUpperCase() + rows[0].user.slice(1);
  441. }
  442. }
  443. callback(rows);
  444. });
  445. };
  446. /**
  447. * ============================================
  448. * HANDOUT CURRENCY
  449. * --------------------------------------------
  450. */
  451. Currency.prototype.handout_coins = function () {
  452. var __self = this;
  453. // check stream status
  454. function stream_status() {
  455. var time = utils.make_interval(__self.streaming_check);
  456. if (time === 0) {
  457. // get stream status
  458. https.get('https://api.twitch.tv/kraken/streams/' + __self.irc.config.channel.slice(1), function (response) {
  459. var body = '';
  460. // put together response
  461. response.on('data', function (chunk) {
  462. body += chunk;
  463. });
  464. // start / stop handing out coins based on stream status
  465. response.on('end', function () {
  466. var json = JSON.parse(body);
  467. __self.streaming = json.stream !== null;
  468. if (__self.streaming && __self.give_coins === false) {
  469. insert_coins();
  470. }
  471. __self.irc.emit('data', 'DATA - Online Status Check - Returned: ' + __self.streaming);
  472. setTimeout(stream_status, 1000);
  473. });
  474. });
  475. } else {
  476. setTimeout(stream_status, time);
  477. }
  478. }
  479. // get subscribers
  480. function subscribers() {
  481. var time = utils.make_interval(__self.subscriber_check);
  482. if (time === 0) {
  483. // get stream status
  484. http.get(__self.config.subscribers_json, function (response) {
  485. var body = '';
  486. // put together response
  487. response.on('data', function (chunk) {
  488. body += chunk;
  489. });
  490. // start / stop handing out coins based on stream status
  491. response.on('end', function () {
  492. var json = JSON.parse(body);
  493. var entries = json.feed.entry, subs = '';
  494. __self.subscribers = [];
  495. for (var i = 0; i < entries.length; i++) {
  496. __self.subscribers.push(entries[i].title['$t']);
  497. subs += entries[i].title['$t'] + ' ';
  498. }
  499. __self.irc.emit('data', 'DATA - Subscriber Check - Returned: ' + subs);
  500. setTimeout(subscribers, 1000);
  501. });
  502. });
  503. } else {
  504. setTimeout(subscribers, time);
  505. }
  506. }
  507. // trigger coin handout
  508. function insert_coins() {
  509. __self.give_coins = __self.streaming;
  510. if (__self.give_coins) {
  511. var time = utils.make_interval(__self.give_coins_timer);
  512. if (time === 0) {
  513. __self.irc.raw('WHO ' + __self.irc.config.channel);
  514. setTimeout(insert_coins, 1000);
  515. } else {
  516. setTimeout(insert_coins, time);
  517. }
  518. }
  519. }
  520. // monitor viewers in irc
  521. __self.irc.on('data', function (data) {
  522. if (__self.streaming) {
  523. var data_split = data.split(' '), viewer = '';
  524. // viewers from \who
  525. if (data_split[3] == '352') {
  526. if (data_split[6] !== undefined) {
  527. viewer = data_split[6].toLowerCase();
  528. if (__self.viewer_list.indexOf(viewer) < 0) {
  529. __self.viewer_list.push(viewer);
  530. }
  531. }
  532. }
  533. // viewers chatting
  534. if (data_split[3] == 'PRIVMSG') {
  535. var servernick = data_split[2].toLowerCase().split('!');
  536. viewer = servernick[0];
  537. if (viewer != __self.irc.config.name.toLowerCase()) {
  538. viewer = viewer.slice(1);
  539. }
  540. if (__self.viewer_list.indexOf(viewer) < 0) {
  541. __self.viewer_list.push(viewer);
  542. }
  543. }
  544. // give coins after \who and handout_coins is true
  545. if (__self.give_coins && data_split[3] == '315') {
  546. var clone_viewer_list = __self.viewer_list;
  547. // clear old list and start recording
  548. __self.viewer_list = [];
  549. // build sql from the saved viewer list
  550. var sql = '';
  551. for (var i = 0; i < clone_viewer_list.length; i++) {
  552. var currency_amount = __self.subscribers.indexOf(clone_viewer_list[i]) >= 0 ? 2 : 1;
  553. if (clone_viewer_list[i] !== '') {
  554. if (i != clone_viewer_list.length - 1) {
  555. sql += 'INSERT INTO viewers (user, points) ';
  556. sql += 'VALUES (\'' + clone_viewer_list[i] + '\', ' + currency_amount + ') ';
  557. sql += 'ON DUPLICATE KEY UPDATE points = points + ' + currency_amount + '; ';
  558. } else {
  559. sql += 'INSERT INTO viewers (user, points) ';
  560. sql += 'VALUES (\'' + clone_viewer_list[i] + '\', ' + currency_amount + ') ';
  561. sql += 'ON DUPLICATE KEY UPDATE points = points + ' + currency_amount;
  562. }
  563. }
  564. }
  565. // execute query
  566. __self.db.execute(sql, function () {});
  567. }
  568. } else {
  569. __self.viewer_list = [];
  570. }
  571. });
  572. stream_status();
  573. // only start subscribers if gdoc is available
  574. if (__self.config.subscribers_json !== '') {
  575. subscribers();
  576. }
  577. };
  578. /**
  579. * ============================================
  580. * Adjust Currency
  581. * --------------------------------------------
  582. */
  583. Currency.prototype.adjust_currency = function (method, amount, viewer) {
  584. var __self = this;
  585. viewer = viewer.toLowerCase();
  586. __self.db.execute('SELECT * FROM viewers WHERE user=\'' + viewer + '\'', function(rows){
  587. if (rows.length > 0 || method === 'push') {
  588. var check = rows.length > 0 ? rows[0].user : rows.push({user: viewer});
  589. if (check === viewer || method === 'push') {
  590. var sql = '', settings = [];
  591. // push settings for message
  592. if (method === 'add' || method === 'push') {
  593. settings.push('+');
  594. settings.push('Added');
  595. settings.push('to');
  596. } else if (method === 'remove') {
  597. settings.push('-');
  598. settings.push('Removed');
  599. settings.push('from');
  600. }
  601. settings.push(rows[0].user.charAt(0).toUpperCase() + rows[0].user.slice(1));
  602. // create sql
  603. if (method === 'add' || method === 'remove') {
  604. sql += 'UPDATE viewers ';
  605. sql += 'SET points = points ' + settings[0] + ' ' + amount + ' ';
  606. sql += 'WHERE user = \'' + rows[0].user + '\'; ';
  607. } else if (method === 'push') {
  608. sql += 'INSERT INTO viewers (user, points) ';
  609. sql += 'VALUES (\'' + viewer + '\', ' + amount + ') ';
  610. sql += 'ON DUPLICATE KEY UPDATE points = points + ' + amount + '; ';
  611. }
  612. //execute adjustment
  613. __self.db.execute(sql, function(){
  614. __self.irc.emit('message', {message:__self.pre_text + settings[1] + ' ' + amount + ' ' + __self.config.currency + ' ' + settings[2] + ' ' + settings[3]});
  615. });
  616. }
  617. } else {
  618. __self.irc.emit('message', {message:__self.pre_text + 'User was not found, use the push command to add a new user'});
  619. }
  620. });
  621. };
  622. /**
  623. * ============================================
  624. * AUCTION SYSTEM
  625. * --------------------------------------------
  626. */
  627. Currency.prototype.auction = function (status) {
  628. var __self = this;
  629. switch (status) {
  630. case true:
  631. if (!__self.bets_status) {
  632. if (!__self.raffle_status) {
  633. if (!__self.auction_status) {
  634. // open up the auction
  635. __self.auction_status = true;
  636. // request toggle
  637. if (__self.temp.raffle_toggle) {
  638. __self.temp.auction_toggle = __self.temp.raffle_toggle;
  639. } else {
  640. __self.temp.auction_toggle = __self.coin_toggle;
  641. }
  642. __self.coin_toggle = false;
  643. // default request timer
  644. if (__self.temp.raffle_timer && __self.temp.raffle_timer_reset) {
  645. __self.temp.auction_timer = __self.temp.raffle_timer;
  646. __self.temp.auction_timer_reset = __self.temp.raffle_timer_reset;
  647. } else {
  648. __self.temp.auction_timer = __self.coin_response_timer;
  649. __self.temp.auction_timer_reset = __self.coin_response_reset;
  650. }
  651. __self.coin_response_timer = 3000;
  652. __self.coin_response_reset = true;
  653. // clear previous bids
  654. __self.auction_bids = [];
  655. __self.auction_previous_bid = {};
  656. // auction open response
  657. __self.irc.emit('message', {message:__self.pre_text + 'Auction opened, accepting bids'})
  658. } else {
  659. // auction is already open response
  660. __self.irc.emit('message', {message:__self.pre_text + 'Auction already in progress'});
  661. }
  662. } else {
  663. // raffle currently running
  664. __self.irc.emit('message', {message:__self.pre_text + 'You must close the raffle before you can open an auction'});
  665. }
  666. } else {
  667. // gambling currently running
  668. __self.irc.emit('message', {message:__self.pre_text + 'Betting must be closed before you can open an auction'});
  669. }
  670. break;
  671. case false:
  672. if (__self.auction_status) {
  673. // close the auction
  674. __self.auction_status = false;
  675. // request toggle
  676. __self.coin_toggle = __self.temp.auction_toggle;
  677. delete __self.temp.auction_toggle;
  678. // default request timer
  679. __self.coin_response_timer = __self.temp.auction_timer;
  680. __self.coin_response_reset = __self.temp.auction_timer_reset;
  681. delete __self.temp.auction_timer;
  682. delete __self.temp.auction_timer_reset;
  683. // clear response timers
  684. clearTimeout(__self.auction_bid_response);
  685. clearInterval(__self.auction_bid_response_long);
  686. if (__self.auction_bids.length > 0) {
  687. // pick a winner response
  688. for (var i = 0; i < __self.auction_bids.length; i++) {
  689. if (__self.auction_bids[i].bid === utils.max(__self.auction_bids)) {
  690. __self.irc.emit('message', {message:__self.pre_text + 'Auction closed, Winner: ' + __self.auction_bids[i].viewer + ' @ ' + __self.auction_bids[i].bid});
  691. // save the winners info for draw refund
  692. __self.auction_previous_bid.viewer = __self.auction_bids[i].viewer;
  693. __self.auction_previous_bid.bid = __self.auction_bids[i].bid;
  694. // remove winners money
  695. var sql = '';
  696. sql += 'UPDATE viewers ';
  697. sql += 'SET points = points - ' + __self.auction_bids[i].bid + ' ';
  698. sql += 'WHERE user = \'' + __self.auction_bids[i].viewer + '\'';
  699. __self.db.execute(sql, function() {});
  700. // remove winner from main list
  701. __self.auction_bids.splice(i, 1);
  702. break;
  703. }
  704. }
  705. } else {
  706. // no bidders to pick from response
  707. __self.irc.emit('message', {message:__self.pre_text + 'Auction closed, no bidders to pick a winner'});
  708. }
  709. } else {
  710. // auction is already open response
  711. __self.irc.emit('message', {message:__self.pre_text + 'Auction is already closed'});
  712. }
  713. break;
  714. case 'cancel':
  715. if (__self.auction_status) {
  716. // close the auction
  717. __self.auction_status = false;
  718. // request toggle
  719. __self.coin_toggle = __self.temp.auction_toggle;
  720. delete __self.temp.auction_toggle;
  721. // default request timer
  722. __self.coin_response_timer = __self.temp.auction_timer;
  723. __self.coin_response_reset = __self.temp.auction_timer_reset;
  724. delete __self.temp.auction_timer;
  725. delete __self.temp.auction_timer_reset;
  726. // clear response timers
  727. clearTimeout(__self.auction_bid_response);
  728. clearInterval(__self.auction_bid_response_long);
  729. // clear previous bids
  730. __self.auction_bids = [];
  731. __self.auction_previous_bid = {};
  732. // auction cancelled notification
  733. __self.irc.emit('message', {message:__self.pre_text + 'Auction has been cancelled'});
  734. } else {
  735. // auction cancelled notification
  736. __self.irc.emit('message', {message:__self.pre_text + 'Auction is not opened'});
  737. }
  738. break;
  739. }
  740. };
  741. Currency.prototype.bid = function (caller, amount) {
  742. var __self = this;
  743. function find_duplicate(amount) {
  744. var duplicate = false;
  745. for (var i = 0; i < __self.auction_bids.length; i++) {
  746. if (__self.auction_bids[i].bid === amount) {
  747. duplicate = true;
  748. break;
  749. }
  750. }
  751. return duplicate;
  752. }
  753. if (__self.auction_status) {
  754. // verify that bidder has the coins for bidding
  755. __self.query_coins(caller, function (rows) {
  756. var has_tickets = false;
  757. // only add bid if they have the enough to pay
  758. if (rows[0].points >= amount) {
  759. if (__self.auction_bids.length > 0) {
  760. // check if an existing bid exists and modify it
  761. for (var i = 0; i < __self.auction_bids.length; i++) {
  762. if (__self.auction_bids[i].viewer === caller) {
  763. has_tickets = true;
  764. // check if bid is higher then original and not a duplicate
  765. if (__self.auction_bids[i].bid < amount && !find_duplicate(amount)) {
  766. __self.auction_bids[i].bid = amount;
  767. }
  768. break;
  769. }
  770. }
  771. // add new bids to list if they are not a duplicate
  772. if (!has_tickets && !find_duplicate(amount)) {
  773. __self.auction_bids.push({viewer: caller, bid: amount});
  774. }
  775. } else {
  776. // push first bid
  777. __self.auction_bids.push({viewer: caller, bid: amount});
  778. }
  779. }
  780. // clear timers on flood
  781. clearTimeout(__self.auction_bid_response);
  782. clearInterval(__self.auction_bid_response_long);
  783. // reply after set amount of bids
  784. if ((__self.auction_bids.length % __self.max_requests) === 0) {
  785. // bulk flood response
  786. for (var i = 0; i < __self.auction_bids.length; i++) {
  787. if (__self.auction_bids[i].bid === utils.max(__self.auction_bids)) {
  788. __self.irc.msg(__self.pre_text + 'Highest bid, ' + __self.auction_bids[i].viewer + ' @ ' + __self.auction_bids[i].bid);
  789. }
  790. }
  791. } else {
  792. // response after time without flood has passed
  793. var viewer, bid;
  794. for (var i = 0; i < __self.auction_bids.length; i++) {
  795. if (__self.auction_bids[i].bid === utils.max(__self.auction_bids)) {
  796. viewer = __self.auction_bids[i].viewer;
  797. bid = __self.auction_bids[i].bid;
  798. }
  799. }
  800. if (viewer !== undefined && bid !== undefined && __self.auction_status) {
  801. var msg = __self.pre_text + 'Highest bid, ' + viewer + ' @ ' + bid;
  802. __self.auction_bid_response = setTimeout(function () {__self.irc.emit('message', {message:msg, timer: 1});}, 5000);
  803. __self.auction_bid_response_long = setInterval(function () {__self.irc.emit('message', {message:msg, timer: 1});}, 30000);
  804. }
  805. }
  806. });
  807. }
  808. };
  809. Currency.prototype.next_auction_winner = function () {
  810. var __self = this, empty_list = [];
  811. // custom dialog when the bidder list is empty
  812. empty_list.push('Hey, I just met you and this is crazy, but there\'s no more bidders, so start an new auction maybe?');
  813. empty_list.push('Are there more bidders? Well, to tell you the truth, in all this excitement I kind of lost track myself.');
  814. empty_list.push('Heyyyyyy there\'s no more bidders, Op, op, op, op, Open Auction Style.');
  815. empty_list.push('Da bids! Da bids! Where are all da bids, boss?');
  816. if (!__self.auction_status) {
  817. // get next highest bidder or prompt to open new auction
  818. if (__self.auction_bids.length > 0) {
  819. for (var i = 0; i < __self.auction_bids.length; i++) {
  820. if (__self.auction_bids[i].bid === utils.max(__self.auction_bids)) {
  821. __self.irc.emit('message',{message:__self.pre_text + 'Drawing the next highest bid: ' + __self.auction_bids[i].viewer + ' @ ' + __self.auction_bids[i].bid});
  822. // refund previous winner's money
  823. var sql = '';
  824. sql += 'UPDATE viewers ';
  825. sql += 'SET points = points + ' + __self.auction_previous_bid.bid + ' ';
  826. sql += 'WHERE user = \'' + __self.auction_previous_bid.viewer + '\'';
  827. __self.db.execute(sql, function() {});
  828. // save the new winner's info for next draw
  829. __self.auction_previous_bid.viewer = __self.auction_bids[i].viewer;
  830. __self.auction_previous_bid.bid = __self.auction_bids[i].bid;
  831. // remove winners money
  832. sql = '';
  833. sql += 'UPDATE viewers ';
  834. sql += 'SET points = points - ' + __self.auction_bids[i].bid + ' ';
  835. sql += 'WHERE user = \'' + __self.auction_bids[i].viewer + '\'';
  836. __self.db.execute(sql, function() {});
  837. // remove winner from main list
  838. __self.auction_bids.splice(i, 1);
  839. break;
  840. }
  841. }
  842. } else {
  843. // check if a previous viewer is saved
  844. if (__self.auction_previous_bid.viewer !== null) {
  845. // refund previous winner's money
  846. var sql = '';
  847. sql += 'UPDATE viewers ';
  848. sql += 'SET points = points + ' + __self.auction_previous_bid.bid + ' ';
  849. sql += 'WHERE user = \'' + __self.auction_previous_bid.viewer + '\'';
  850. __self.db.execute(sql, function() {});
  851. // clear previous bid
  852. __self.auction_previous_bid = {};
  853. }
  854. // notify that there's no more bids
  855. __self.irc.emit('message',{message:__self.pre_text + utils.selectRandomArrayItem(empty_list)});
  856. }
  857. }
  858. };
  859. /**
  860. * ============================================
  861. * RAFFLE SYSTEM
  862. * --------------------------------------------
  863. */
  864. Currency.prototype.raffle = function (status) {
  865. var __self = this;
  866. switch (status) {
  867. case true:
  868. if (!__self.bets_status) {
  869. if (!__self.auction_status) {
  870. if (!__self.raffle_status) {
  871. // open up a raffle
  872. __self.raffle_status = true;
  873. // request toggle
  874. if (__self.temp.auction_toggle) {
  875. __self.temp.raffle_toggle = __self.temp.auction_toggle;
  876. } else {
  877. __self.temp.raffle_toggle = __self.coin_toggle;
  878. }
  879. __self.coin_toggle = false;
  880. // default request timer
  881. if (__self.temp.auction_timer && __self.temp.auction_timer_reset) {
  882. __self.temp.raffle_timer = __self.temp.auction_timer;
  883. __self.temp.raffle_timer_reset = __self.temp.auction_timer_reset;
  884. } else {
  885. __self.temp.raffle_timer = __self.coin_response_timer;
  886. __self.temp.raffle_timer_reset = __self.coin_response_reset;
  887. }
  888. __self.coin_response_timer = 3000;
  889. __self.coin_response_reset = true;
  890. // save previous raffle settings in case
  891. // a new one is opened on accident
  892. __self.raffle_restore_ticket_requests = __self.raffle_ticket_requests;
  893. __self.raffle_restore_tickets = __self.raffle_tickets;
  894. // clear previous tickets
  895. __self.raffle_ticket_requests = [];
  896. __self.raffle_tickets = [];
  897. // raffle open response
  898. __self.irc.emit('message',{message:__self.pre_text + 'Raffle opened'});
  899. __self.irc.emit('message',{message:'+ Tickets cost ' + __self.raffle_ticket_cost + ' ' + __self.config.currency.toLowerCase() + ' / Maximum of ' + __self.raffle_max_tickets + ' tickets per viewer'});
  900. } else {
  901. // raffle in progress response
  902. __self.irc.emit('message',{message:__self.pre_text + 'Raffle already in progress'});
  903. }
  904. } else {
  905. // auction in progress
  906. __self.irc.emit('message', {message:__self.pre_text + 'You must close the auction before you can open an a raffle'});
  907. }
  908. } else {
  909. // gambling currently running
  910. __self.irc.emit('message', {message:__self.pre_text + 'Betting must be closed before you can open a raffle'});
  911. }
  912. break;
  913. case false:
  914. if (__self.raffle_status) {
  915. // close the raffle
  916. __self.raffle_status = false;
  917. // request toggle
  918. __self.coin_toggle = __self.temp.raffle_toggle;
  919. delete __self.temp.raffle_toggle;
  920. // default request timer
  921. __self.coin_response_timer = __self.temp.raffle_timer;
  922. __self.coin_response_reset = __self.temp.raffle_timer_reset;
  923. delete __self.temp.raffle_timer;
  924. delete __self.temp.raffle_timer_reset;
  925. // validation / winner / deduction
  926. __self.raffle_winner();
  927. } else {
  928. // raffle is already open response
  929. __self.irc.emit('message',{message:__self.pre_text + 'Raffle is already closed'});
  930. }
  931. break;
  932. case 'cancel':
  933. if (__self.raffle_status) {
  934. // close the raffle
  935. __self.raffle_status = false;
  936. // request toggle
  937. __self.coin_toggle = __self.temp.raffle_toggle;
  938. delete __self.temp.raffle_toggle;
  939. // default request timer
  940. __self.coin_response_timer = __self.temp.raffle_timer;
  941. __self.coin_response_reset = __self.temp.raffle_timer_reset;
  942. delete __self.temp.raffle_timer;
  943. delete __self.temp.raffle_timer_reset;
  944. // clear previous tickets
  945. __self.raffle_ticket_requests = [];
  946. __self.raffle_tickets = [];
  947. // raffle cancelled notification
  948. __self.irc.emit('message', {message:__self.pre_text + 'Raffle has been cancelled'});
  949. } else {
  950. // raffle cancelled notification
  951. __self.irc.emit('message', {message:__self.pre_text + 'Raffle is not opened'});
  952. }
  953. break;
  954. case 'restore':
  955. if (__self.raffle_status) {
  956. // close raffle
  957. __self.raffle_status = false;
  958. // restore previous raffle tickets
  959. __self.raffle_ticket_requests = __self.raffle_restore_ticket_requests;
  960. __self.raffle_tickets = __self.raffle_restore_tickets;
  961. __self.irc.emit('message', {message:__self.pre_text + 'Previous raffle has been restored'});
  962. } else {
  963. // raffle restore failed notification
  964. __self.irc.emit('message', {message:__self.pre_text + 'Raffle is closed, unable to restore'});
  965. }
  966. break;
  967. }
  968. };
  969. Currency.prototype.collect_tickets = function (caller, amount) {
  970. var __self = this, has_tickets = false;
  971. if (__self.raffle_ticket_requests.length > 0) {
  972. // check if viewer already has tickets
  973. for (var i = 0; i < __self.raffle_ticket_requests.length; i++) {
  974. if (__self.raffle_ticket_requests[i].viewer === caller) {
  975. has_tickets = true;
  976. if (amount <= __self.raffle_max_tickets && amount >= 1) {
  977. __self.raffle_ticket_requests[i].tickets = amount;
  978. } else if (amount === 0) {
  979. __self.raffle_ticket_requests.splice(i, 1);
  980. }
  981. break;
  982. }
  983. }
  984. // if viewer doesn't have tickets and meets > 1 < max req add their request
  985. if (!has_tickets && amount <= __self.raffle_max_tickets && amount >= 1 && amount !== 0) {
  986. __self.raffle_ticket_requests.push({viewer: caller, tickets: amount});
  987. }
  988. } else {
  989. // push first ticket if > 1 < max
  990. if (amount <= __self.raffle_max_tickets && amount >= 1 && amount !== 0) {
  991. __self.raffle_ticket_requests.push({viewer: caller, tickets: amount});
  992. }
  993. }
  994. };
  995. Currency.prototype.raffle_winner = function () {
  996. var __self = this, sql = '';
  997. if (__self.raffle_ticket_requests.length > 0) {
  998. // setup sql to grab all viewers that request coins from the database
  999. sql += 'SELECT * FROM viewers WHERE ';
  1000. for (var i = 0; i < __self.raffle_ticket_requests.length; i++) {
  1001. if (i !== __self.raffle_ticket_requests.length - 1) {
  1002. sql += 'user=\'' + __self.raffle_ticket_requests[i].viewer.toLowerCase() + '\' OR ';
  1003. } else {
  1004. sql += 'user=\'' + __self.raffle_ticket_requests[i].viewer.toLowerCase() + '\'';
  1005. }
  1006. }
  1007. // execute viewer search query
  1008. __self.db.execute(sql, function(rows) {
  1009. // currency validation
  1010. // - this takes the results of the query and uses the names from the database
  1011. // to filter through the viewers that requested tickets (since they have to be in the
  1012. // database in the first place)
  1013. // - during the filtering process the viewers requested tickets are multiplied by the
  1014. // ticket cost and compared against their currency amount
  1015. // - if the viewer has the funds, their tickets are added and the sql is updated to include their
  1016. // deduction
  1017. sql = '';
  1018. for (var i = 0; i < rows.length; i++) {
  1019. for (var j = 0; j < __self.raffle_ticket_requests.length; j++) {
  1020. if (__self.raffle_ticket_requests[j].viewer.toLowerCase() === rows[i].user) {
  1021. var money = __self.raffle_ticket_requests[j].tickets * __self.raffle_ticket_cost;
  1022. if (rows[i].points >= money) {
  1023. for (var k = 1; k <= __self.raffle_ticket_requests[j].tickets; k++) {
  1024. __self.raffle_tickets.push(__self.raffle_ticket_requests[j].viewer);
  1025. }
  1026. if (i !== rows.length - 1) {
  1027. sql += 'UPDATE viewers ';
  1028. sql += 'SET points = points - ' + money + ' ';
  1029. sql += 'WHERE user = \'' + rows[i].user + '\'; ';
  1030. } else {
  1031. sql += 'UPDATE viewers ';
  1032. sql += 'SET points = points - ' + money + ' ';
  1033. sql += 'WHERE user = \'' + rows[i].user + '\'';
  1034. }
  1035. }
  1036. break;
  1037. }
  1038. }
  1039. }
  1040. // randomize array before selecting a random winner
  1041. __self.raffle_tickets.sort(function () {return 0.5 - Math.random();});
  1042. // select random ticket from array
  1043. var winner = utils.selectRandomArrayItem(__self.raffle_tickets);
  1044. // count winner's tickets
  1045. var winning_ticket_amount;
  1046. for (var i = 0; i < __self.raffle_ticket_requests.length; i++) {
  1047. if (__self.raffle_ticket_requests[i].viewer === winner) {
  1048. winning_ticket_amount = __self.raffle_ticket_requests[i].tickets;
  1049. break;
  1050. }
  1051. }
  1052. // output winner to chat
  1053. __self.irc.emit('message', {message:__self.pre_text + 'Raffle closed, ' + __self.raffle_tickets.length + ' tickets purchased!'});
  1054. __self.irc.emit('message', {message:'+ Winner: ' + winner + ' (' + winning_ticket_amount + ' tickets purchased)'});
  1055. // remove one ticket from raffle bowl
  1056. if (__self.raffle_tickets.indexOf(winner) >= 0 ) {
  1057. __self.raffle_tickets.splice(__self.raffle_tickets.indexOf(winner), 1);
  1058. }
  1059. // execute query
  1060. __self.db.execute(sql, function () {});
  1061. });
  1062. } else {
  1063. // no tickets to pick from response
  1064. __self.irc.emit('message', {message:__self.pre_text + 'Raffle closed, no tickets to draw a winner'});
  1065. }
  1066. };
  1067. Currency.prototype.next_raffle_winner = function () {
  1068. var __self = this, empty_list = [];
  1069. // custom dialog when there are no more raffle tickets
  1070. empty_list.push('Hey, I just met you and this is crazy, but there\'s no more tickets, so start an new raffle maybe?');
  1071. empty_list.push('Are there more tickets? Well, to tell you the truth, in all this excitement I kind of lost track myself.');
  1072. empty_list.push('Heyyyyyy there\'s no more tickets, Op, op, op, op, Open Raffle Style.');
  1073. empty_list.push('Da tickets! Da tickets! Where are all da tickets, boss?');
  1074. if (!__self.raffle_status) {
  1075. // draw next ticket or prompt to open new raffle
  1076. if (__self.raffle_tickets.length > 0) {
  1077. // randomize array before selecting a random winner
  1078. __self.raffle_tickets.sort(function () {return 0.5 - Math.random();});
  1079. // select random ticket from array
  1080. var winner = utils.selectRandomArrayItem(__self.raffle_tickets);
  1081. // count next winner's tickets
  1082. var winning_ticket_amount;
  1083. for (var i = 0; i < __self.raffle_ticket_requests.length; i++) {
  1084. if (__self.raffle_ticket_requests[i].viewer === winner) {
  1085. winning_ticket_amount = __self.raffle_ticket_requests[i].tickets;
  1086. break;
  1087. }
  1088. }
  1089. // output winner to chat
  1090. __self.irc.emit('message', {message:__self.pre_text + 'Drawing next ticket'});
  1091. __self.irc.emit('message', {message:'+ Winner: ' + winner + ' (' + winning_ticket_amount + ' tickets purchased)'});
  1092. // remove one ticket from raffle bowl
  1093. if (__self.raffle_tickets.indexOf(winner) >= 0 ) {
  1094. __self.raffle_tickets.splice(__self.raffle_tickets.indexOf(winner), 1);
  1095. }
  1096. } else {
  1097. __self.irc.emit('message', {message:__self.pre_text + utils.selectRandomArrayItem(empty_list)});
  1098. }
  1099. }
  1100. };
  1101. /**
  1102. * ============================================
  1103. * BETTING SYSTEM
  1104. * --------------------------------------------
  1105. */
  1106. Currency.prototype.bets = function(status, data) {
  1107. var __self = this;
  1108. switch(status){
  1109. case true:
  1110. if (!__self.auction_status) {
  1111. if (!__self.raffle_status) {
  1112. if (!__self.bets_status && !__self.bets_payout) {
  1113. var wager_msg = '';
  1114. // open up bets
  1115. __self.bets_status = true;
  1116. __self.bets_payout = true;
  1117. // clear previous board / bets
  1118. __self.bets_board = [];
  1119. __self.bets_viewers = [];
  1120. // create new betting board
  1121. __self.bets_board = data.join().split(',').filter(function(n){return n}).slice(6);
  1122. // create chat message on how to place a bet
  1123. for (var i = 0; i < __self.bets_board.length; i++) {
  1124. if (i !== __self.bets_board.length - 1) {
  1125. wager_msg += '"!' + __self.bets_board[i] + '" / ';
  1126. } else {
  1127. wager_msg += '"!' + __self.bets_board[i] + '"';
  1128. }
  1129. }
  1130. // output to chat
  1131. __self.irc.emit('message', {message:__self.pre_text + 'Betting is now open'});
  1132. __self.irc.emit('message', {message:'+ Type ' + wager_msg + ' and the bet amount to enter'});
  1133. } else {
  1134. if (__self.bets_payout) {
  1135. // payout pending message
  1136. __self.irc.emit('message', {message:__self.pre_text + 'Unable to take new bets until previous have been paid out'});
  1137. } else {
  1138. // gambling is already open response
  1139. __self.irc.emit('message', {message:__self.pre_text + 'Betting already in progress'});
  1140. }
  1141. }
  1142. } else {
  1143. // raffle in progress
  1144. __self.irc.emit('message', {message:__self.pre_text + 'Betting must be closed before you can open a raffle'});
  1145. }
  1146. } else {
  1147. // auction currently running
  1148. __self.irc.emit('message', {message:__self.pre_text + 'Betting must be closed before you can open an auction'});
  1149. }
  1150. break;
  1151. case false:
  1152. if (__self.bets_status && __self.bets_payout) {
  1153. // close out bets
  1154. __self.bets_status = false;
  1155. // output to chat
  1156. if (__self.bets_viewers.length > 0) {
  1157. __self.irc.emit('message', {message:__self.pre_text + 'Betting is now closed'});
  1158. } else {
  1159. __self.irc.emit('message', {message:__self.pre_text + 'Betting closed, no bets were placed'});
  1160. }
  1161. // deduct bets from viewers amounts
  1162. __self.bets_deduct_bets();
  1163. }
  1164. break;
  1165. case 'winner':
  1166. // set payout to complete
  1167. __self.bets_payout = false;
  1168. break;
  1169. }
  1170. };
  1171. Currency.prototype.collect_bets = function (caller, bet, amount) {
  1172. var __self = this, has_bet = false;
  1173. if (__self.bets_viewers.length > 0) {
  1174. for (var i = 0; i < __self.bets_viewers.length; i++) {
  1175. if (__self.bets_viewers[i].viewer === caller) {
  1176. has_bet = true;
  1177. if (amount >= 1) {
  1178. __self.bets_viewers[i].bet = bet;
  1179. __self.bets_viewers[i].amount = amount;
  1180. } else if (amount === 0 && bet === __self.bets_viewers[i].bet) {
  1181. __self.bets_viewers.splice(i, 1);
  1182. }
  1183. break;
  1184. }
  1185. }
  1186. if (!has_bet && amount >= 1 && amount !== 0) {
  1187. __self.bets_viewers.push({viewer: caller, bet: bet, amount: amount});
  1188. }
  1189. } else {
  1190. if (amount >= 1 && amount !== 0) {
  1191. __self.bets_viewers.push({viewer: caller, bet: bet, amount: amount});
  1192. }
  1193. }
  1194. console.log(__self.bets_viewers);
  1195. };
  1196. Currency.prototype.bets_deduct_bets = function () {
  1197. };
  1198. module.exports = function (irc, db, options) {
  1199. return new Currency(irc, db, options);
  1200. };