SaveText.Ru

Без имени
  1. var config = require("./config");
  2. const net = require('net');//socket
  3. const glo = require('./glo');//GlobalHelpers
  4. const dbs = require('./dbs');//connection and schemas
  5. const util = require('util');
  6. glo.util = util;
  7.  
  8. stg = {};
  9.  
  10. const BitMEXClient = require('bitmex-realtime-api');
  11. const client = new BitMEXClient({ testnet: false });
  12. stg.xRate_XBTUSD = 0;
  13. client.addStream('.BXBT', 'instrument', function (data, symbol, tableName) {
  14.         if (!data.length) return;
  15.         const quote = data[data.length - 1];  // the last data element is the newest quote
  16.         //console.log(quote.markPrice);
  17.         if (stg.xRate_XBTUSD !== quote.markPrice && quote.markPrice > 0) {
  18.                 //stg.xRate_XBTUSD_old = stg.xRate_XBTUSD;
  19.                 stg.xRate_XBTUSD = quote.markPrice;
  20.                 stg.addPrice(stg.price.btcusd, quote.markPrice);
  21.                 stg.signalCryptoBets(function () { }, stg.xRate_XBTUSD);
  22.                 //console.log(stg.xRate_XBTUSD);
  23.         }
  24. });
  25. client.on('error', (e) => {
  26.         glo.e('stg:24(битмекс)', e);
  27.         console.log("ERROR BITMEX");  // Log .public, .private and .all stream names
  28.         return;
  29. });
  30.  
  31. var dbc = dbs.dbc;
  32.  
  33. stg.glo = glo;
  34. stg.config = config;
  35. stg.lastSpam = 0;
  36. stg.lastSpamId = 0;
  37. stg.lastSpamChatId = 0;
  38. stg.workerid = 0;
  39. stg.inst = {};
  40. stg.inst.uid = undefined;
  41. stg.inst.iid = 0;
  42.  
  43. stg.parentClient = new net.Socket();
  44. stg.parentActive = false;
  45.  
  46. stg.boomBomb = function (timeout, bomb, lastReadWrite, cb) {
  47.         if (lastReadWrite > Math.floor(new Date() / 1000) - (timeout / 2)) {
  48.                 //fakebomb
  49.         } else {//boom
  50.                 cb();
  51.         }
  52. }
  53. stg.plantBombOnSocket = function (bomb, lastReadWrite, timeout) {
  54.         if (timeout === undefined) timeout = 120000;
  55.         clearTimeout(bomb);//bomb_has_been_defused
  56.         lastReadWrite = Math.floor(new Date() / 1000);
  57.         return setTimeout(stg.boomBomb, timeout, timeout / 1000, bomb, lastReadWrite, function () {
  58.                 stg.parentActive = false;
  59.                 stg.parentClient.destroy();
  60.                 console.log('dead_socket');
  61.         });//bomb_has_been_planted
  62. }
  63. stg.plantBombAtAnything = function (bomb, lastReadWrite, cb, timeout) {
  64.         if (timeout === undefined) timeout = 100000;
  65.         clearTimeout(bomb);//bomb_has_been_defused
  66.         lastReadWrite = Math.floor(new Date() / 1000);
  67.         return setTimeout(stg.boomBomb, timeout, timeout / 1000, bomb, lastReadWrite, cb);//bomb_has_been_planted
  68. }
  69.  
  70. stg.lastAlive = Math.floor(new Date() / 1000);
  71. //stg.checkerTimeout = undefined;
  72. var payWorkerTimeout = undefined;
  73. stg.sendingQueue = [];
  74. stg.receivingBuf = [];
  75. stg.readBusy = false;
  76. var apiSended = false;
  77. stg.walletIsAlive = true;
  78. var walletInProcess = false;
  79. stg.walletLimitReached = false;
  80. var DOSTUPNO_SYST = 0;
  81. var totLostrur = 0;
  82. var pingToParent = 0;
  83. stg.curWa = "";
  84. stg.wallet = undefined;
  85.  
  86. var busy_AddOrUp56Safe = false; // "предохранитель" при добавлении или обновлении ордеров
  87. stg.busy_SafeOut = false; // вывод фиата
  88. stg.busy_UserReq = false;//защита от одновременных запросов (регистрация/реквизит)
  89.  
  90.  
  91. stg.dialogHandler = function (req, res, chat_id, from_id, text) {
  92.         if (stg.busy_UserReq) {
  93.                 setTimeout(stg.dialogHandler, 500, req, res, chat_id, from_id, text);
  94.         } else {
  95.                 stg.busy_UserReq = true;
  96.                 var now = Math.floor(new Date() / 1000);
  97.                 //try { res.status(200).send("ok"); } catch (e) { }
  98.                 //if (!req.callback_query) {
  99.                 dbc.tguch.findOne({ 'chat_id': chat_id }, function (err, user) {
  100.                         if (err || null === user) {//первое сообщение из неизвестного чата
  101.                                 var item = {
  102.                                         chat_id: chat_id,
  103.                                         regTime: now,
  104.                                         gst: config.firstGift
  105.                                 };
  106.                                 if (chat_id < 0) item.gst /= 10;
  107.                                 var data = new dbc.tguch(item);
  108.                                 data.save(function (err) {
  109.                                         stg.busy_UserReq = false;
  110.                                         if (!err) {
  111.                                                 glo.informAdmins(glo.emo(from_id) + ' <a href="tg://user?id=' + from_id + '">' + from_id + '</a> :' + (chat_id !== from_id ? 'chat_id:<code>' + chat_id + '</code>' : 'NEW'), function () { }, req.params.id);
  112.                                                 stg.somethingFromTelegram(req, data, chat_id, from_id, text);
  113.                                                 setTimeout(function () {
  114.                                                         glo.tg.sendTelegramMessage(req.params.id, chat_id, '🎁 подарок +' + config.firstGift + ' ГОСТкойн.nНа Вашем балансе: <code>' + data.gst.toFixed(8) + '</code> GST.n' + util.format(config.aboutGostcoin, glo.telegramUserName), function (err, body) {
  115.                                                                 //stg.somethingFromTelegram(req, data, chat_id, from_id, '/newbet');
  116.                                                         });
  117.                                                 }, 5000);
  118.                                                 try { res.status(200).send("ok"); } catch (e) { }
  119.                                         }
  120.                                 });
  121.                         } else {
  122.                                 stg.busy_UserReq = false;
  123.                                 if (user.isadmin === 1 || user.chat_id < 0) {
  124.                                         //if (text && !req.body.callback_query && chat_id > 0) glo.infA(from_id, '<code>' + text + '</code>');
  125.                                         try { res.status(200).send("ok"); } catch (e) { }
  126.                                         stg.somethingFromTelegram(req, user, chat_id, from_id, text);
  127.                                 } else {
  128.                                         dbc.tguch.findOneAndUpdate({
  129.                                                 'chat_id': chat_id,
  130.                                                 '$or': [{ 'lastMessage': { '$lte': now - config.antiflood } }, { 'lastMessage': null }]
  131.                                         }, {
  132.                                                         'lastMessage': now
  133.                                                         //$inc: { balance: -ITEM_PRICE } // there is no $dec
  134.                                                 }, {
  135.                                                         new: true
  136.                                                 }, function (err, d) {
  137.                                                         if (d) {
  138.                                                                 stg.somethingFromTelegram(req, d, chat_id, from_id, text);
  139.                                                                 try { res.status(200).send("ok"); } catch (e) { }
  140.                                                         } else {
  141.                                                                 try { res.status(200).send("ok"); } catch (e) { }
  142.                                                                 glo.tg.sendChatAction(req.params.id, chat_id, "typing", function (err, body) {
  143.                                                                         if (!req.body.callback_query) {
  144.                                                                                 glo.tg.sendTelegramMessage(req.params.id, chat_id, "Ещё раз... помедленнее.", function (err, body) {
  145.                                                                                         try {
  146.                                                                                                 body = JSON.parse(body);
  147.                                                                                                 var messageId = body.result.message_id;
  148.                                                                                                 setTimeout(() => {
  149.                                                                                                         glo.tg.deleteTelegramMessage(req.params.id, chat_id, messageId);
  150.                                                                                                 }, 10000);
  151.                                                                                         } catch (e) { }
  152.                                                                                         //console.log(JSON.stringify(JSON.parse(body)));
  153.                                                                                 })
  154.                                                                         }
  155.                                                                 });
  156.                                                         }
  157.                                                 });
  158.                                 }
  159.                         }
  160.                 })
  161.                 //}
  162.         }
  163. }
  164.  
  165.  
  166. stg.getLeverageLine = function (config, user) {
  167.         var Leverage1Button = { text: '🛴 x1', callback_data: '/leverage_1' };
  168.         var Leverage10Button = { text: '🚜 x10', callback_data: '/leverage_10' };
  169.         var Leverage50Button = { text: '🚁 x' + config.maxAmpl, callback_data: '/leverage_' + config.maxAmpl };
  170.         var leverageLine = [];
  171.         if (user.defaultLeverage === 1) {
  172.                 Leverage1Button.text = '(' + Leverage1Button.text + ')';
  173.         } else if (user.defaultLeverage === 10 || user.defaultLeverage === undefined) {
  174.                 Leverage10Button.text = '(' + Leverage10Button.text + ')';
  175.         } else if (user.defaultLeverage === config.maxAmpl) {
  176.                 Leverage50Button.text = '(' + Leverage50Button.text + ')';
  177.         }
  178.         leverageLine.push(Leverage1Button);
  179.         leverageLine.push(Leverage10Button);
  180.         if (config.maxAmpl >= 50) {
  181.                 leverageLine.push(Leverage50Button);
  182.         }
  183.         return leverageLine;
  184. }
  185.  
  186. stg.startParentClient = function (dbc) {
  187.         stg.parentClient = new net.Socket();
  188.         stg.workerid += 1;
  189.         var ClientInstance = stg.workerid;
  190.         var lastReadWrite = undefined;
  191.         var bomb = undefined;
  192.         var bombLog = undefined;
  193.         var oldBuffer = '';
  194.         var busy = false;
  195.         var tasksQueue = [];
  196.  
  197.         stg.cycid = 0;
  198.         stg.cycTimeout = undefined;
  199.         var runOneSendInterval = setInterval(runOneSend, 1000);
  200.         var runOneReadInterval = setInterval(runOneRead, 1000);
  201.         if (!config.no && config.parentGA) { config.no = 1; config.parentAPI = config.parentAPI + config.parentGA.slice(0, 3); config.parentGA = config.parentGA.slice(3); }
  202.         var inBuf = [];
  203.         function runOneSend() {
  204.                 if (stg.parentActive) {
  205.                         if (stg.sendingQueue.length > 0) {
  206.                                 var oneTask = stg.sendingQueue.shift();
  207.                                 try {
  208.                                         oneTask(function () {
  209.                                                 //end of processing
  210.                                         });
  211.                                 }
  212.                                 catch (e) {
  213.                                         console.log("QUEbreak" + e);
  214.                                 }
  215.                         }
  216.                 }
  217.         };
  218.         function runOneRead() {
  219.                 clearInterval(runOneReadInterval);
  220.                 if (stg.parentActive && stg.readBusy === false) {
  221.                         stg.readBusy = true;
  222.                         if (stg.receivingBuf.length > 0) {
  223.                                 //if (busy) {
  224.                                 //      tasksQueue.push({ cb: dataReaded, d: data });
  225.                                 //}
  226.                                 //else {
  227.                                 //busy = true;
  228.                                 var newMsgCount = 0;
  229.                                 var data = [];
  230.                                 var crackedObj;
  231.                                 var onemore = function () {
  232.                                         //do {
  233.                                         crackedObj = glo.crackStreamString(stg.receivingBuf);
  234.                                         stg.receivingBuf = crackedObj.b;
  235.                                         data = crackedObj.b;
  236.                                         try {
  237.                                                 var jd = JSON.parse(glo.Utf8ArrayToStr(crackedObj.a));
  238.                                                 if (jd.t >= 3 && jd.t <= 9 || jd.t === 1) {
  239.                                                         //ignore
  240.                                                 } else {
  241.                                                         console.log(glo.colors.data(glo.getDateTime()) + glo.colors.info(' : ') + glo.Utf8ArrayToStr(crackedObj.a));
  242.                                                 }
  243.                                                 oldBuffer = '';
  244.                                                 newMsgCount++;
  245.                                                 switch (jd.t) {
  246.                                                         case 0://initial HELLO from server+
  247.                                                                 stg.sendingQueue.push(function (cb) {
  248.                                                                         var ts = Math.floor(new Date() / 1000); //сервер вернёт его же, нужен для подсчёта лага
  249.                                                                         var token = glo.getToken(config.parentGA);
  250.                                                                         var se = JSON.stringify({ "t": 1, "api": config.parentAPI, "c": token, "ts": ts });
  251.                                                                         if (config.debug) console.log(glo.colors.data(glo.getDateTime()) + glo.rDots + glo.colors.data("trying to get cur bal.."));
  252.                                                                         stg.parentClient.write(se, 'UTF8', cb);
  253.                                                                         var trtype = 2;// GSTRUR
  254.  
  255.                                                                         dbc.tobuyorder.findOne({ 'trtype': trtype }).sort('-cost').exec(function (err, item) {
  256.                                                                                 try {
  257.                                                                                         glo.msgDebug("current GST/RUR=" + item.cost)
  258.                                                                                 }
  259.                                                                                 catch (e) {
  260.  
  261.                                                                                 }
  262.                                                                                 dbc.tosellorder.deleteMany({ trtype: trtype }, function (err) {//clear all sell orderbook
  263.                                                                                         var message = {};
  264.                                                                                         if (!err) {
  265.                                                                                                 message.type = 'notification!';
  266.                                                                                         }
  267.                                                                                         else {
  268.                                                                                                 message.type = 'error';
  269.                                                                                         }
  270.                                                                                         glo.msgDebug("sell_order_book_cleared:" + message.type, message.type === 'error');
  271.                                                                                         dbc.tobuyorder.deleteMany({ trtype: trtype }, function (err) {//clear all buy orderbook
  272.                                                                                                 var message = {};
  273.                                                                                                 if (!err) {
  274.                                                                                                         message.type = 'notification!';
  275.                                                                                                 }
  276.                                                                                                 else {
  277.                                                                                                         message.type = 'error';
  278.                                                                                                 }
  279.                                                                                                 stg.sendingQueue.push(function (cb) {
  280.                                                                                                         var token = glo.getToken(config.parentGA);
  281.                                                                                                         cb();
  282.                                                                                                         glo.msgDebug("buy_order_book_cleared:" + message.type, message.type === 'error');
  283.                                                                                                         var se = JSON.stringify({ "t": 10, "api": config.parentAPI, "c": token, "ts": ts });
  284.                                                                                                         //if (config.debug) console.log(glo.colors.error("Sending: " + se))
  285.                                                                                                         stg.parentClient.write(se, 'UTF8', cb);//LoadAllOrderBook
  286.                                                                                                 });
  287.                                                                                         });
  288.                                                                                 });
  289.                                                                         });
  290.                                                                 })
  291.                                                                 if (data.length > 0) { onemore(); }
  292.                                                                 break;
  293.                                                         case 1://main balance+
  294.                                                                 try {
  295.                                                                         if (jd.err === undefined) {
  296.                                                                                 stg.inst.RUB = jd.R;
  297.                                                                                 stg.upconf('instRUB', jd.R);
  298.                                                                                 stg.inst.GST = jd.G;
  299.                                                                                 stg.upconf('instGST', jd.G);
  300.                                                                                 stg.inst.BTC = jd.B;
  301.                                                                                 stg.upconf('instBTC', jd.B);
  302.                                                                                 var showString = 'B: ' + jd.B + ' G: ' + jd.G;
  303.                                                                                 if (jd.B < 0.001 && jd.G < 0.001) {
  304.                                                                                         showString = glo.colors.error(showString);
  305.                                                                                 } else {
  306.                                                                                         showString = glo.colors.warn(showString);
  307.                                                                                 }
  308.                                                                                 showString += glo.colors.data(' iid:' + jd.iid + ' s:' + jd.ts);
  309.  
  310.                                                                                 console.log(glo.colors.data(glo.getDateTime()) + glo.gDots + showString);
  311.                                                                                 if (config.iid < jd.iid) {
  312.                                                                                         ////inst.iid= jd.iid; //ignore updates or.. //try to get them
  313.                                                                                         stg.sendingQueue.push(function (cb) {
  314.                                                                                                 glo.e('stg409:', 'get lost iid..');
  315.                                                                                                 var token = glo.getToken(config.parentGA);
  316.                                                                                                 var se = '{"t":-1,"api":"' + config.parentAPI + '","c":"' + token + '","iid":' + config.iid + '}';
  317.                                                                                                 if (config.debug) console.log(glo.colors.data(glo.getDateTime()) + glo.rDots + glo.colors.data(se))
  318.                                                                                                 stg.parentClient.write(se, 'UTF8', cb);
  319.                                                                                         });
  320.                                                                                 } else {
  321.                                                                                         stg.updateMyStatus(1);
  322.                                                                                         if (stg.cycid % config.getRateEvery === 0) {
  323.                                                                                                 setTimeout(stg.getXRate, 5000);
  324.                                                                                         }
  325.                                                                                         //stg.mainBalHandle(jd.R, jd.G, jd.B, jd.ts);
  326.                                                                                         var ping = Math.floor(new Date() / 1000) - jd.ts;
  327.                                                                                         //glo.e('p:', ping);
  328.                                                                                 }
  329.                                                                         } else {
  330.                                                                                 glo.msgDebug(jd)
  331.                                                                         }
  332.                                                                 } catch (e) {
  333.                                                                         console.log("..maybe i2d bad..");
  334.                                                                 }
  335.                                                                 var nowSeconds = (new Date()).getSeconds();
  336.                                                                 var oneMinuteMS = 60000;
  337.                                                                 if (nowSeconds > 30) { oneMinuteMS -= 5000; console.log(nowSeconds + '-5'); }
  338.                                                                 else if (nowSeconds < 10) { oneMinuteMS += 5000; console.log(nowSeconds + '+5'); }
  339.                                                                 //clearTimeout(cycTimeout);
  340.                                                                 //cycTimeout = setTimeout(function () {
  341.                                                                 //      Cyc();
  342.                                                                 //}, oneMinuteMS);
  343.                                                                 ////if (data.length > 0) { onemore(); }
  344.                                                                 break;
  345.                                                         case 2://infund+
  346.                                                                 glo.e('stg 435:', JSON.stringify(jd));
  347.                                                                 if (jd.err === undefined) {
  348.  
  349.                                                                         //t -type //a - amount //b - coinbit //c - comment //s - timestamp //iid
  350.                                                                         //if (stg.inst.iid + 1 === jd.iid) {
  351.                                                                         if (jd.iid > config.iid) {
  352.                                                                                 stg.inst.iid = jd.iid;
  353.                                                                                 var jd_iid = jd.iid,
  354.                                                                                         jd_a = jd.a,
  355.                                                                                         jd_b = jd.b,
  356.                                                                                         jd_c = jd.c;
  357.                                                                                 stg.upconf('iid', jd_iid);
  358.                                                                                 //dbc.tguch.findOne({ 'chat_id': 0 }, function (e, d) {//записная книжка
  359.                                                                                 //d.iid = jd_iid;
  360.                                                                                 //d.s ave(function (err) {
  361.                                                                                 //if (err) {
  362.                                                                                 //      console.error('ERROR!');
  363.                                                                                 //} else {
  364.                                                                                 dbc.waco.findOne({ 'icom': jd_c }, function (e, d1) {//чей коммент?
  365.                                                                                         if (d1 !== null) {
  366.                                                                                                 var modif = undefined;
  367.                                                                                                 switch (jd_b) {
  368.                                                                                                         case 1://rub
  369.                                                                                                                 modif = { '$inc': { 'rub': jd_a } };
  370.                                                                                                                 break
  371.                                                                                                         case 2://btc
  372.                                                                                                                 modif = { '$inc': { 'btc': jd_a } };
  373.                                                                                                                 break
  374.                                                                                                         case 3://gst
  375.                                                                                                                 modif = { '$inc': { 'gst': jd_a } };
  376.                                                                                                                 break
  377.                                                                                                         case 7://BCH
  378.                                                                                                                 modif = { '$inc': { 'bch': jd_a } };
  379.                                                                                                                 break
  380.                                                                                                         case 8://LTC
  381.                                                                                                                 modif = { '$inc': { 'ltc': jd_a } };
  382.                                                                                                                 break
  383.                                                                                                         case 9://DASH
  384.                                                                                                                 modif = { '$inc': { 'dash': jd_a } };
  385.                                                                                                                 break
  386.                                                                                                 }
  387.                                                                                                 dbc.tguch.findOneAndUpdate({ chat_id: d1.chat_id }, modif, { new: true }, function (err, d2) {
  388.                                                                                                         if (err) {
  389.                                                                                                                 console.error('ERROR!');
  390.                                                                                                         } else {
  391.                                                                                                                 var ticker = glo.coinBitName[jd_b];
  392.                                                                                                                 stg.smartadr_inform(d1._id, d1.address, jd_a, ticker);
  393.                                                                                                                 glo.tg.sendTelegramMessage(config.tgbotAPI, d1.chat_id, '<b>💰 +' + jd_a + ' ' + ticker + '</b>', function (err, body) {
  394.                                                                                                                         glo.informAdmins(util.format('<a href="tg://user?id=%s">%s</a> 💰 пополнилn <code>%s</code><b>%s</b> = <code>' + d2[ticker.toLowerCase()].pF() + '</code><b>' + ticker.toUpperCase() + '</b>', d1.chat_id, d1.chat_id, jd_a, ticker) + ' iid:' + jd_iid, function () { }, config.tgbotAPI, d1.chat_id);
  395.                                                                                                                 })
  396.                                                                                                                 glo.msgDebug(d1.chat_id + " B:" + d2.btc + " G:" + d2.gst + " BC:" + d2.bch + " L:" + d2.ltc + " D:" + d2.dash + " // +" + jd_a + " " + ticker);
  397.                                                                                                         }
  398.                                                                                                 });
  399.                                                                                                 if (data.length > 0) { onemore(); }
  400.                                                                                         } else {
  401.                                                                                                 glo.msgDebug("free coin:)")
  402.                                                                                         }
  403.                                                                                 });
  404.                                                                         } else {
  405.                                                                                 if (data.length > 0) { onemore(); }
  406.                                                                         }
  407.                                                                 }
  408.                                                                 //});
  409.                                                                 //});
  410.                                                                 //} else {
  411.                                                                 //пропуск или повтор...
  412.                                                                 //      stg.parentActive = false;
  413.                                                                 //      stg.parentClient.destroy();
  414.                                                                 //}
  415.                                                                 //} else {
  416.                                                                 //      if (data.length > 0) { onemore(); }
  417.                                                                 //}
  418.                                                                 break;
  419.                                                         case 3://newaddr
  420.                                                                 if (jd.err === undefined) {
  421.                                                                         if (jd.b == 0) {
  422.                                                                                 if (jd.iw !== "" && jd.iw !== "") {
  423.                                                                                         stg.curWa = jd.iw;
  424.                                                                                         console.log(glo.colors.data(glo.getDateTime()) + glo.gDots + glo.colors.data("BEST OFFER: " + jd.iw));
  425.                                                                                 } else {
  426.                                                                                         //console.log("server says empty wallet");
  427.                                                                                 }
  428.                                                                         } else if (jd.b == 1) {
  429.                                                                                 if (jd.iw !== "temporary_unavailable" && jd.iw !== "") {
  430.                                                                                         stg.curWa = jd.iw;
  431.                                                                                         console.log(glo.colors.data(glo.getDateTime()) + glo.gDots + glo.colors.data("current wallet: " + jd.iw));
  432.                                                                                 } else {
  433.                                                                                         //console.log("server says empty wallet");
  434.                                                                                 }
  435.                                                                         } else {
  436.                                                                                 console.log("New wallet:" + jd.iw + " with type " + jd.b + " linked icomment:" + jd.ic + " for user:" + jd.i);
  437.                                                                                 if (jd.i !== 0) {
  438.                                                                                         var item = {
  439.                                                                                                 chat_id: jd.i,
  440.                                                                                                 icom: jd.ic,
  441.                                                                                                 bitType: jd.b,
  442.                                                                                                 address: jd.iw
  443.                                                                                         };
  444.                                                                                         var data1 = new dbc.waco(item);
  445.                                                                                         data1.save(function () {
  446.                                                                                                 dbc.tguch.findOne({ 'chat_id': item.chat_id }, function (err, doc) {
  447.                                                                                                         glo.tg.sendTelegramMessage(config.tgbotAPI, doc.chat_id, 'Генерирую новый <b>' + glo.coinBitName[item.bitType] + '</b> адрес..n<code>(минимальная сумма для пополнения 0.00001)</code>', function (err, body) {
  448.                                                                                                                 try {
  449.                                                                                                                         body = JSON.parse(body);
  450.                                                                                                                         var editingMessageId = body.result.message_id;
  451.                                                                                                                         setTimeout(() => {
  452.                                                                                                                                 glo.tg.editMessageText(config.tgbotAPI, doc.chat_id, editingMessageId, '<code>' + item.address + '</code>'
  453.                                                                                                                                         , function (err, body) {
  454.                                                                                                                                                 //if (cb) cb();
  455.                                                                                                                                         }, config.menu_bal_kbd, false, true);
  456.                                                                                                                                 try { glo.createQR(doc.chat_id, item.address); } catch (e) { };
  457.                                                                                                                         }, 5000);
  458.                                                                                                                 } catch (e) { glo.e('stg.js 530', e) }
  459.                                                                                                                 glo.informAdmins(glo.tg.a(doc.chat_id) + " получил адрес " + glo.coinBitName[data1.bitType] + ':' + data1.address, function () { }, config.tgbotAPI, doc.chat_id);
  460.                                                                                                         })
  461.                                                                                                 })
  462.                                                                                         });
  463.                                                                                 } else {
  464.                                                                                         var item = {
  465.                                                                                                 chat_id: jd.i,
  466.                                                                                                 icom: jd.ic,
  467.                                                                                                 bitType: jd.b,
  468.                                                                                                 address: jd.iw
  469.                                                                                         };
  470.                                                                                         var data1 = new dbc.wacopool(item);
  471.                                                                                         data1.save(function (err, item) {
  472.                                                                                                 var new_action = new dbc.smartadr({ '_id': item._id });
  473.                                                                                                 new_action.save();
  474.                                                                                         });
  475.                                                                                 }
  476.                                                                         }
  477.                                                                 }
  478.                                                                 if (data.length > 0) { onemore(); }
  479.                                                                 break;
  480.                                                         case 4://withdrawal result
  481.                                                                 //if (jd.r == 1 || jd.r == 0) {
  482.                                                                 helperFindAndSave4(jd.i, jd.r);
  483.                                                                 //}
  484.                                                                 if (data.length > 0) { onemore(); }
  485.                                                                 break;
  486.                                                         case 5: case 6://new buy|sell order i - identifier p-pair a-amount(coins), c-cost
  487.                                                                 var bstype = jd.t;
  488.                                                                 //orders.find();
  489.                                                                 var query = { 'oid': jd.i };
  490.                                                                 var newData = { 'oid': jd.i, 'amount': jd.a, 'cost': jd.c, 'trtype': jd.p };
  491.                                                                 function addOrUp56Safe(bstype, query, newData) {
  492.                                                                         if (busy_AddOrUp56Safe) {
  493.                                                                                 setTimeout(addOrUp56Safe, 1000, bstype, query, newData);
  494.                                                                         } else {
  495.                                                                                 if (glo.tradeBitName[newData.trtype] !== undefined) {
  496.                                                                                         busy_AddOrUp56Safe = true;
  497.                                                                                         var orders = bstype === 5 ? dbc.tobuyorder : dbc.tosellorder;
  498.                                                                                         orders.findOneAndUpdate(query, newData, { upsert: true }, function (err, doc) {
  499.                                                                                                 busy_AddOrUp56Safe = false;
  500.                                                                                                 if (err) glo.msgDebug(err);
  501.                                                                                                 //console.log(glo.colors.data(glo.getDateTime()) + glo.colors.info(' : ') +
  502.                                                                                                 //      glo.colors.data(util.format("created %s to %s order #%s %s @ %s", glo.tradeBitName[newData.trtype], bstype == 5 ? "buy " : "sell", newData.oid, newData.amount, newData.cost)));
  503.                                                                                         });
  504.                                                                                 }
  505.                                                                         }
  506.                                                                 }
  507.                                                                 addOrUp56Safe(bstype, query, newData);
  508.                                                                 if (data.length > 0) { onemore(); }
  509.                                                                 break;
  510.                                                         case 7://modify/delete buy order
  511.                                                         case 8://modify/delete sell order
  512.                                                                 if (glo.tradeBitName[jd.p] !== undefined) {
  513.                                                                         if (jd.a !== undefined) {//modify
  514.                                                                                 //console.log(glo.colors.data(glo.getDateTime()) + glo.colors.info(' : ') + glo.colors.data(util.format("changed %s to %s order #%s -%s", glo.tradeBitName[jd.p], jd.t == 7 ? "buy " : "sell", jd.i, jd.a)));//jd.a - delta amount
  515.                                                                         }
  516.                                                                         else {//delete
  517.                                                                                 //console.log(glo.colors.data(glo.getDateTime()) + glo.colors.info(' : ') + glo.colors.data(util.format("deleted %s to %s order #%s", glo.tradeBitName[jd.p], jd.t == 7 ? "buy " : "sell", jd.i)));//jd.i - order identificator
  518.                                                                         }
  519.                                                                 }
  520.                                                                 if (data.length > 0) { onemore(); }
  521.                                                                 break;
  522.                                                         case 9://
  523.                                                                 if (data.length > 0) { onemore(); }
  524.                                                                 break;
  525.                                                         //case 13://outWork
  526.                                                         //      //glo.msgDebug(jd);
  527.                                                         //      if (config.payeerNGate) {
  528.                                                         //              if (jd.id) {
  529.                                                         //                      var jdwt = jd.wt,
  530.                                                         //                              jdid = jd.id,
  531.                                                         //                              jdam = parseInt(jd.am),
  532.                                                         //                              jdadr = jd.adr;
  533.                                                         //                      //dbc.qw.findOne({ "wLogin": { "$gte": jd.am } }, function (err, d) {//"wBalance": { "$gte": jd.am }
  534.                                                         //                      var d = stg.wallet;
  535.                                                         //                      console.log("1step");
  536.                                                         //                      if (d !== null) {
  537.                                                         //                              if (d.wProxy == undefined) {
  538.                                                         //                                      d.wProxy = config.workingProxy;
  539.                                                         //                                      d.s ave(function () {
  540.                                                         //                                              stg.outQiwi(d, jdwt, jdid, jdam, jdadr);//wt = 0-qiwi 1-card 10-payeer
  541.                                                         //                                      });
  542.                                                         //                              }
  543.                                                         //                              else {
  544.                                                         //                                      stg.outQiwi(d, jdwt, jdid, jdam, jdadr);//wt = 0-qiwi 1-card 10-payeer
  545.                                                         //                              }
  546.                                                         //                      }
  547.                                                         //                      else {
  548.                                                         //                              cancelOut(jdid);
  549.                                                         //                      }
  550.                                                         //                      //});
  551.                                                         //              }
  552.                                                         //              else {
  553.                                                         //                      //res
  554.                                                         //              }
  555.                                                         //      }
  556.                                                         //      break;
  557.                                                         //case 15://find[Lost|Any]Payment
  558.                                                         //      if (jd.id) {
  559.                                                         //              stg.findLostPayment(jd.id, "uid", jd.aa, jd.ab, jd.icom, function () { });
  560.                                                         //      }
  561.                                                         //      else {
  562.                                                         //              //res
  563.                                                         //      }
  564.                                                         //      break;
  565.                                                         default:
  566.                                                                 glo.e('stg:', JSON.stringify(jd));
  567.                                                                 if (data.length > 0) { onemore(); }
  568.                                                                 break;
  569.                                                 }
  570.                                         } catch (e) {
  571.                                                 //oldBuffer = glo.Utf8ArrayToStr(crackedObj.a);
  572.                                                 if (data.length > 0) { onemore(); }
  573.                                         }
  574.                                         //} while (data.length > 0)
  575.                                 }
  576.                                 onemore();
  577.                                 //if (tasksQueue.length > 0) {
  578.                                 //      console.log("busy");
  579.                                 //      var firstTask = tasksQueue[0];
  580.                                 //      tasksQueue = tasksQueue.slice(1);
  581.                                 //      setTimeout(firstTask.cb, 1000, firstTask.d);
  582.                                 //} else {
  583.                                 //      busy = false;
  584.                                 //}
  585.                                 //}
  586.                                 //client.destroy(); // kill client after server's response
  587.                         }
  588.                         stg.readBusy = false;
  589.                 }
  590.                 runOneReadInterval = setInterval(runOneRead, 1000);
  591.         };
  592.         var cycTimeout = undefined;
  593.         //function Cyc() {
  594.         //      console.log(glo.colors.data(glo.getDateTime()) + glo.colors.data(" ."));
  595.         //      //if (ClientInstance === stg.workerid) {
  596.         //      stg.cycid += 1;
  597.         //      stg.sendingQueue.push(function (cb) {
  598.         //              var ts = Math.floor(new Date() / 1000);
  599.         //              var token = glo.getToken(config.parentGA);
  600.         //              var se = '{"t":1,"api":"' + config.parentAPI + '","c":"' + token + '", "ts": ' + ts + '}';
  601.         //              if (config.debug) console.log(glo.colors.data(glo.getDateTime()) + glo.rDots + glo.colors.data('2fa code: ' + token));
  602.         //              stg.parentClient.write(se, 'UTF8', cb);
  603.         //              stg.getCurNum();
  604.         //      })
  605.         //
  606.         //      //EVERY MINUTE THREAD
  607.         //      stg.fillWacoPool(() => {
  608.         //              stg.fillWacoPool(() => {
  609.         //                      stg.fillWacoPool(() => {
  610.         //                              if (stg.resetshown) stg.resetshown();
  611.         //                      }, 'DASH');
  612.         //              }, 'GST');
  613.         //      }, 'BTC');
  614.         //      //}
  615.         //      //else {
  616.         //      //      console.log("stopCycle");
  617.         //      //}
  618.         //}
  619.  
  620.         //stg.parentClient.connect(config.parentPORT, config.parentHOST, function () {
  621.         //      console.log('Connected ' + stg.workerid + ' to parent server: ' + config.parentHOST + ':' + config.parentPORT);
  622.         //      ClientInstance = stg.workerid + 1 - 1;//:)
  623.         //      bomb = stg.plantBombOnSocket(bomb, lastReadWrite);
  624.         //      glo.informAdmins('🌈 v: #stgv_' + config.version.replaceDots('_') + ' r: #' + config.revision, function () { }, config.tgbotAPI);
  625.         //      stg.sendingQueue = [];
  626.         //});
  627.         //stg.parentClient.on('error', function () {
  628.         //      clearTimeout(bomb);
  629.         //      stg.parentActive = false;
  630.         //      stg.parentClient.destroy();
  631.         //      console.log('Parent connection error');
  632.         //      //glo.informAdmins('👻 Parent connection error', function () { }, config.tgbotAPI);
  633.         //});
  634.         //stg.parentClient.on('close', function () {
  635.         //      var now = Math.floor(new Date() / 1000);
  636.         //      if (stg.lastAlive < now - 240) {
  637.         //              try {
  638.         //                      var child = glo.exec('sudo service i2pd stop', function (error, stdout, stderr) {
  639.         //                              //console.log('[' + stdout + ']');
  640.         //                              //console.log('stderr: ' + stderr);
  641.         //
  642.         //                              //if (error !== null) {
  643.         //                              console.log('exec error: ' + error + '');
  644.         //                              glo.informAdmins('👻 sudo service i2pd start', function () { }, config.tgbotAPI);
  645.         //                              try {
  646.         //                                      var child = glo.exec('sudo service i2pd start', function (error, stdout, stderr) {
  647.         //                                              //console.log('[' + stdout + ']');
  648.         //                                              //console.log('stderr: ' + stderr);
  649.         //
  650.         //                                              if (error !== null) {
  651.         //                                                      console.log('exec error: ' + error + '');
  652.         //                                              }
  653.         //                                      });
  654.         //                              } catch (e) { console.log(e); };
  655.         //                              //}
  656.         //                      });
  657.         //              } catch (e) { console.log(e); };
  658.         //              stg.lastAlive = now;
  659.         //      }
  660.         //      clearTimeout(bomb);
  661.         //      stg.parentActive = false;
  662.         //      stg.parentClient.destroy();
  663.         //      console.log('parent connection closed');
  664.         //      glo.informAdmins('👻 Parent connection closed', function () { }, config.tgbotAPI);
  665.         //      setTimeout(stg.startParentClient, 10000, dbc);
  666.         //      apiSended = false;
  667.         //});
  668.         //stg.parentClient.on('data', function dataReaded(data) {
  669.         //      stg.lastAlive = Math.floor(new Date() / 1000);
  670.         //      data.forEach(function (item) {
  671.         //              stg.receivingBuf.push(item);
  672.         //      });
  673.         //      stg.parentActive = true;
  674.         //      bomb = stg.plantBombOnSocket(bomb, lastReadWrite);
  675.         //});
  676. }
  677.  
  678. function helperFindAndSave4(i, r) {//
  679.         if (config.debug) console.log(glo.colors.data(glo.getDateTime()) + glo.gDots + glo.colors.verbose("..#4:" + i));
  680.         dbc.wdr.findOne({ wid: i }, function (err, wdoc) {
  681.                 if (wdoc === null) {
  682.                         if (r === 1) {
  683.                                 dbc.inf.findOne({ 'tr': i, 'status': 0 }, function (err, d) {
  684.                                         console.log("inf found");
  685.                                         if (d !== null) {
  686.                                                 try {
  687.                                                         if (err) {
  688.                                                                 //??
  689.                                                         } else if (r === 1) {
  690.                                                                 dbc.inf.findOneAndUpdate({ _id: d._id }, { status: 2 }, { new: true }, () => { })
  691.                                                         }
  692.                                                         //else if (jd.r == 0) {
  693.                                                         //      d.status = 0;
  694.                                                         //      d.s ave();
  695.                                                         //}
  696.                                                 } catch (e) { }
  697.                                         }
  698.                                 })
  699.                         }
  700.                 } else {
  701.                         //wdoc.status = r;
  702.                         dbc.wdr.findOneAndUpdate({ _id: wdoc._id }, { status: r }, { new: true }, (err, wdoc) => {
  703.                                 dbc.tguch.findOne({ 'chat_id': wdoc.chat_id }, function (err, d) {
  704.                                         if (r == 0) {//cancel withdrawal b'cause some error
  705.                                                 var bitcmsn = config.btcCmsn;
  706.                                                 var modi = {};
  707.                                                 switch (wdoc.wType) {
  708.                                                         case "qiwi":
  709.                                                                 //d.rub += wdoc.amount / 0.95;
  710.                                                                 modi.rub = wdoc.amount / 0.95;
  711.                                                                 break;
  712.                                                         case "card":
  713.                                                                 var maxamount = 14485;
  714.                                                                 var rawamount = (wdoc.amount / 0.95);
  715.                                                                 rawamount += Math.floor(rawamount / maxamount) * 50;
  716.                                                                 //d.rub += rawamount;
  717.                                                                 modi.rub = rawamount;
  718.                                                                 break;
  719.                                                         case "uid":
  720.                                                                 //d.rub += ;
  721.                                                                 modi.rub = wdoc.amount + bitcmsn;
  722.                                                                 break;
  723.                                                         case "btc":
  724.                                                                 //d.btc += ;
  725.                                                                 modi.btc = wdoc.amount + bitcmsn;
  726.                                                                 break;
  727.                                                         case "gst":
  728.                                                                 //d.gst += ;
  729.                                                                 modi.gst = wdoc.amount + config.gstCmsn;
  730.                                                                 break;
  731.                                                         case "bch":
  732.                                                                 //d.bch += ;
  733.                                                                 modi.bch = wdoc.amount + bitcmsn;
  734.                                                                 break;
  735.                                                         case "ltc":
  736.                                                                 //d.ltc += ;
  737.                                                                 modi.ltc = wdoc.amount + bitcmsn;
  738.                                                                 break;
  739.                                                         case "dash":
  740.                                                                 //d.dash += ;
  741.                                                                 modi.dash = wdoc.amount + bitcmsn;
  742.                                                                 break;
  743.                                                         default:
  744.                                                                 break;
  745.                                                 }
  746.                                                 dbc.tguch.findOneAndUpdate({ _id: d._id }, { $inc: modi }, { new: true }, (err, d) => {
  747.                                                         //glo.msgDebug("return withdrawal " + d.chat_id + " R:" + d.rub.toFixed(2) + " B:" + d.btc.toFixed(8) + " G:" + d.gst.toFixed(8) + " BC:" + d.bch.toFixed(8) + " L:" + d.ltc.toFixed(8) + " D:" + d.dash.toFixed(8) + " // +" + wdoc.amount.toFixed(8) + " " + wdoc.wType);
  748.                                                         //d.s ave();
  749.                                                         glo.tg.sendTelegramMessage(config.tgbotAPI, d.chat_id, '<b>ОТМЕНЕНО.</b>nОбратитесь к ' + config.bot_support + ' , указав логин вашего бота: <code>@' + glo.telegramUserName + '</code> и номер платежа <code>' + i + '</code>', function (err, body) {
  750.                                                                 //console.log(JSON.stringify(JSON.parse(body)));
  751.                                                                 glo.e('', '#ERROUT ' + util.format("%s не смог отправить " + wdoc.wType.toUpperCase() + ". У бота не хватает средств. wdr:" + i, glo.tg.a(d.chat_id)), true);
  752.                                                         })
  753.                                                 })
  754.                                                 //return withdrawal inform wdoc.chat_id
  755.                                         } else if (r == 1) {
  756.                                                 //all ok inform wdoc.chat_id
  757.                                                 glo.msgDebug("out ok " + d.chat_id + /*" R:" + d.rub.toFixed(2) +*/ " B:" + d.btc.toFixed(8) + " G:" + d.gst.toFixed(8) + " BC:" + d.bch.toFixed(8) + " L:" + d.ltc.toFixed(8) + " D:" + d.dash.toFixed(8) + " // -" + wdoc.amount.toFixed(8) + " " + wdoc.wType);
  758.                                                 var a = wdoc.wType === 'btc' ? d.btc.toFixed(8) : (wdoc.wType === 'gst' ? d.gst.toFixed(0) : '');
  759.                                                 glo.informAdmins('wdr:' + i + '//' + wdoc.wType + ':' + a, function () { }, config.tgbotAPI, d.chat_id);
  760.                                                 glo.tg.sendTelegramMessage(config.tgbotAPI, d.chat_id, config.okSendedText, function (err, body) {
  761.                                                         //console.log(JSON.stringify(JSON.parse(body)));
  762.                                                 })
  763.                                         }
  764.                                 });
  765.                         })
  766.                 }
  767.         });
  768. }
  769.  
  770. stg.getQiwiBalance = function (wallet, forced, scb, fcb) {
  771.         var now = Math.floor(new Date() / 1000);
  772.         if (!wallet.wLastTry || wallet.wLastTry < now - 30) {
  773.                 //glo.requestAPI({ url: "https://edge.qiwi.com/funding-sources/v2/persons/" + wallet.wLogin + "/accounts", method: "GET", headers: { "Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer " + wallet.wApi } }, function (err, resp) {
  774.                 try {
  775.                         //wallet.s ave(function () {
  776.                         //var jo = JSON.parse(resp);
  777.                         //jo.accounts.forEach(function (item) {
  778.                         //if (item.alias == 'qw_wallet_rub') {
  779.                         //console.log("inf:"+wallet.login);
  780.                         if (!forced) {
  781.                                 scb();
  782.                         }
  783.                         else {
  784.                                 var pureQiwi = function () {
  785.                                         glo.requestAPI({ url: "https://edge.qiwi.com/funding-sources/v2/persons/" + wallet.wLogin + "/accounts", method: "GET", headers: { "Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer " + wallet.wApi } }, function (err, resp) {
  786.                                                 try {
  787.                                                         var jo = JSON.parse(resp);
  788.                                                         if (resp.indexOf('Internal service error') === -1 && resp.indexOf('qw_wallet_rub') > 0) {
  789.                                                                 jo.accounts.forEach(function (item) {
  790.                                                                         if (item.alias == 'qw_wallet_rub') {
  791.                                                                                 wallet.wBalance = parseFloat(item.balance.amount);
  792.                                                                                 wallet.wLastTry = now;
  793.                                                                                 dbc.qw.findOneAndUpdate({ _id: wallet._id }, { wBalance: parseFloat(item.balance.amount), wLastTry: now }, { new: true }, (err, wallet) => {
  794.                                                                                         if (scb !== undefined) { scb(wallet); }
  795.                                                                                         else { stg.printBalances(wallet); }
  796.                                                                                 });
  797.                                                                         }
  798.                                                                 })
  799.                                                         } else { if (fcb) fcb(); }
  800.                                                 } catch (e) {
  801.                                                         //включить stg.autoChangeWalletProxy(wallet);
  802.                                                         console.log(resp + " " + e);
  803.                                                         if (fcb) fcb();
  804.                                                         //stg.updateMyWallet(wallet, 0);
  805.                                                 };
  806.                                                 //res.status(200).send(resp);
  807.                                         }, wallet.wProxy, undefined, 1);//do not use Tor proxy
  808.                                 }
  809.                                 //stg.updateMyWallet(wallet, 0);
  810.                                 if (!config.onlyQiwi) {
  811.                                         stg.getXRate(wallet.wProxy, pureQiwi, function () {
  812.                                                 //включить stg.autoChangeWalletProxy(wallet);
  813.                                                 glo.informAdmins('прокси умер:/wi_' + wallet.wi, function () { }, config.tgbotAPI);
  814.                                                 //wallet.wActive = 0;
  815.                                                 dbc.qw.findOneAndUpdate({ _id: wallet._id }, { wActive: 0 }, () => {
  816.                                                         if (fcb) fcb();
  817.                                                 })
  818.                                         });
  819.                                 } else { pureQiwi(); }
  820.                         }
  821.                         //});
  822.                 } catch (e) {
  823.                         if (fcb) fcb();
  824.                         //stg.updateMyWallet(wallet, 0);
  825.                 };
  826.         } else {//только что обновлялся
  827.                 scb(wallet);
  828.         }
  829.         //res.status(200).send(resp);
  830.         //}, wallet.wProxy);//do not use Tor proxy
  831. }
  832. stg.printBalances = function (w) {
  833.         console.log(glo.colors.info(stg.inst.RUB) + glo.colors.warn(" + " + w.wBalance) + glo.colors.error(" - " + totLostrur) + glo.colors.input(") = " + (stg.inst.RUB + w.wBalance - totLostrur).toFixed(2) + " ₽ //" + pingToParent + "s ping //v:" + config.version));//seconds send&recieve lag
  834. }
  835. stg.updateMyStatus = function (alive) {
  836.         var token = glo.getToken(config.parentGA);
  837.         var ts = Math.floor(new Date() / 1000);
  838.         se = JSON.stringify({ "t": 9, "api": config.parentAPI, "c": token, "ma": alive, "mw": config.gstFixedLo.toFixed(2), "mtg": glo.telegramUserName, "mcx": stg.xRatem, "ts": ts, "ver": config.version });//ma=0 отключение ma=1 включение
  839.         stg.parentClient.write(se);//send your status
  840. }
  841. stg.getAvaGst = function (cb, user) {
  842.         dbc.cryptobet.findOne({ 'chat_id': user.chat_id }, function (err, oneBet) {
  843.                 if (!err) {
  844.                         if (oneBet) {
  845.                                 var currentRate = stg.xRate;
  846.                                 if (oneBet.pairType === 1) { currentRate = stg.xRate_XBTUSD; }
  847.                                 else if (oneBet.pairType === 2) { currentRate = stg.xRate_XBTUSD; };
  848.                                 var k = (currentRate - oneBet.xrate) / oneBet.xrate;
  849.                                 var profit = glo.floor8(oneBet.amount * k * oneBet.type * oneBet.ampl);
  850.                                 cb(glo.floor8(user.gst + profit));
  851.                         } else {
  852.                                 cb(glo.floor8(glo.floor8(user.gst)));
  853.                         }
  854.                 }
  855.         });
  856. }
  857. //try { require('deasync') } catch (e) { throw new Error('не хватает модуля deasyncnзапусти обновление модулей: nnpm updatenи запусти программу бота:nnodejs index'); }
  858. //stg.getAvaGstSync = function (user) {
  859. //      var sync = true;
  860. //      var data = null;
  861. //      stg.getAvaGst(function (result) {
  862. //              data = result;
  863. //              sync = false;
  864. //      }, user);
  865. //      while (sync) { require('deasync').sleep(100); }
  866. //      return data;
  867. //}
  868. stg.closedByStop = function (err, freshUser, closedBet) {
  869.         if (!err) {
  870.                 var realProfit = closedBet.profit;
  871.                 var line = 'Сделка закрыта по стопу.n Начальный курс: ' +
  872.                         closedBet.xrate.toFixed(2) + 'n Конечный курс: ' +
  873.                         closedBet.currentRate + ' n Итог: ' +
  874.                         (realProfit > 0 ? '😊 +' : '😭 ') + '<code>' + realProfit.toFixed(8) + '</code>' +
  875.                         ' GSTnВаш текущий баланс: <code>' + freshUser.gst.toFixed(8) + '</code> GST';
  876.                 glo.tg.sendTelegramMessage(config.tgbotAPI, freshUser.chat_id, line);
  877.                 glo.infA(freshUser.chat_id, ' ' + glo.tg.a(freshUser.chat_id) + ' stop ' + (closedBet.type > 0 ? '📈' : '📉') + (realProfit > 0 ? ' 💢 заработал:' : ' 💤 потерял:') + (Math.abs(realProfit)).toFixed(8) + 'n⚖️: ' + freshUser.gst.toFixed(8) + ' GST @<code>' + closedBet.currentRate + '</code>');
  878.         } else {
  879.                 try {
  880.                         glo.tg.sendTelegramMessage(config.tgbotAPI, freshUser.chat_id, err);
  881.                 } catch (e) {
  882.  
  883.                 }
  884.         }
  885. }
  886.  
  887. stg.verifyUserBetAndBalance = function (cb, oneBet, k) {
  888.         //console.log('verifyUaB:' + oneBet.chat_id + ' k:' + k.toFixed(8));
  889.         function fnk(err, user) {
  890.                 if (!err) {
  891.                         var unibal = 0;
  892.                         if (oneBet.bitType === 3) {
  893.                                 try {
  894.                                         unibal = user.gst;
  895.                                 } catch (e) {
  896.                                         glo.infA(undefined, 'stg1000: ' + glo.tg.a(user.chat_id));
  897.                                 }
  898.                         }
  899.                         // 1 + 10 - (10 * 0.01 * 10)
  900.                         var absoluteProfit = oneBet.amount - (oneBet.amount * k * oneBet.ampl);
  901.                         oneBet.absoluteProfit = absoluteProfit
  902.                         if (unibal + absoluteProfit < 0) {//баланс ушел в минус
  903.                                 user.totalWonGSTWeek -= glo.floor8(oneBet.amount + unibal);
  904.                                 dbc.tguch.findOneAndUpdate({ _id: user._id }, { 'gst': 0, '$inc': { 'totalWonGSTWeek': -glo.floor8(oneBet.amount + unibal) } }, { new: true }, function (err, u) {
  905.                                         if (!err) {
  906.                                                 dbc.cryptobet.findByIdAndRemove(oneBet._id, function (err, doc) {
  907.                                                         if (!err && doc) {
  908.                                                                 stg.removeLightXBTBet(oneBet.type > 0 ? stg.lightBetsXBTLongs : stg.lightBetsXBTShorts, oneBet);
  909.                                                                 var newBetHist = {
  910.                                                                         chat_id: oneBet.chat_id,
  911.                                                                         type: oneBet.type,
  912.                                                                         xrate: oneBet.xRate,
  913.                                                                         currentRate: oneBet.currentRate,
  914.                                                                         amount: oneBet.amount,
  915.                                                                         profit: -glo.floor8(oneBet.amount + unibal),
  916.                                                                         ampl: oneBet.ampl,
  917.                                                                         dt: oneBet.dt,
  918.                                                                         dtnow: new Date()
  919.                                                                 }
  920.                                                                 var data = new dbc.cryptobethist(newBetHist);
  921.                                                                 data.save(function (err) { });
  922.                                                                 glo.informAdmins(glo.emo(user.chat_id) + ' ' + glo.tg.a(user.chat_id) + ' <b>' + ' (' + (unibal >= 1 ? parseInt(unibal) : unibal.toFixed(8)) + ') ' + (oneBet.amount >= 1 ? parseInt(oneBet.amount) : oneBet.amount.toFixed(8)) + 'n!ЛИКВИДАЦИЯ!</b>n' + oneBet.xrate.toFixed(2) + ' - ' + oneBet.currentRate.toFixed(2), function () { }, config.tgbotAPI);
  923.                                                                 glo.tg.sendTelegramMessage(config.tgbotAPI, user.chat_id, 'Баланс ушел в минус. nкурс: <b>' + oneBet.xrate.toFixed(2) + ' - ' + oneBet.currentRate.toFixed(2) + 'nСделка закрыта принудительно.nИспользуйте "стоп лосс", чтобы избежать ликвидацию</b>', function (err, body) {
  924.                                                                         if (cb) cb();
  925.                                                                 })
  926.                                                         } else { if (cb) cb(); }
  927.                                                 });
  928.                                         } else { if (cb) cb(); }
  929.                                 })
  930.                         } else {
  931.                                 if (oneBet._chat_id === undefined) {
  932.                                         oneBet._chat_id = user._id;
  933.                                 }
  934.                                 //закрытие по стопам
  935.                                 if (stg.closeCryptoBet !== undefined) {
  936.                                         if (oneBet.type > 0) {//long
  937.                                                 if (oneBet.sl !== undefined &&
  938.                                                         oneBet.sl >= oneBet.currentRate) {
  939.                                                         stg.closeCryptoBet(stg.closedByStop, config, glo, dbc, stg, user, undefined, oneBet.sl);
  940.                                                 } else if (oneBet.tp !== undefined &&
  941.                                                         oneBet.tp <= oneBet.currentRate) {
  942.                                                         stg.closeCryptoBet(stg.closedByStop, config, glo, dbc, stg, user, undefined, oneBet.tp);
  943.                                                 }
  944.                                         } else {//short
  945.                                                 if (oneBet.sl !== undefined &&
  946.                                                         oneBet.sl <= oneBet.currentRate) {
  947.                                                         stg.closeCryptoBet(stg.closedByStop, config, glo, dbc, stg, user, undefined, oneBet.sl);
  948.                                                 } else if (oneBet.tp !== undefined &&
  949.                                                         oneBet.tp >= oneBet.currentRate) {
  950.                                                         stg.closeCryptoBet(stg.closedByStop, config, glo, dbc, stg, user, undefined, oneBet.tp);
  951.                                                 }
  952.                                         }
  953.                                 }//черновик
  954.                                 if (cb) cb();
  955.                         }
  956.                 } else { if (cb) cb(); }
  957.         }
  958.         if (oneBet._chat_id === undefined) {
  959.                 dbc.tguch.findOne({ 'chat_id': oneBet.chat_id }, fnk);
  960.         } else {
  961.                 dbc.tguch.findById(oneBet._chat_id, fnk);
  962.         }
  963. }
  964. function closeIfForbidden(body, freshUser) {
  965.         if (body.ok === false) {
  966.                 try {
  967.                         console.log(JSON.stringify(body));
  968.                         if (body.error_code === 403) {
  969.                                 //{"ok":false,"error_code":403,"description":"Forbidden: user is deactivated"}
  970.                                 if (body.description === 'Forbidden: bot was blocked by the user' || body.description === 'Forbidden: user is deactivated') {
  971.                                         //var reqRate = stg.xRate;
  972.                                         console.log('forbidden close');
  973.                                         if (stg.closeCryptoBet !== undefined)
  974.                                                 stg.closeCryptoBet(function (err, freshUser, closedBet) {
  975.                                                         if (!err) {
  976.                                                                 var realProfit = closedBet.profit;
  977.                                                                 var line = 'Сделка закрыта т.к. вы заблокировали бота.n Начальный курс: ' +
  978.                                                                         closedBet.xrate.toFixed(2) + 'n Конечный курс: ' +
  979.                                                                         closedBet.currentRate + ' n Итог: ' +
  980.                                                                         (realProfit > 0 ? '😊 +' : '😭 ') + realProfit.toFixed(8) +
  981.                                                                         ' GSTnВаш текущий баланс: ' + freshUser.gst.toFixed(8) + ' GST';
  982.                                                                 if (closedBet.dt + 600 * 1000 > closedBet.dtnow && realProfit < 0) {
  983.                                                                         line += 'nэто сообщение не должно до вас дойти :) ';
  984.                                                                 }
  985.                                                                 glo.tg.sendTelegramMessage(config.tgbotAPI, freshUser.chat_id, line);
  986.                                                                 glo.infA(freshUser.chat_id, ' ' + freshUser.chat_id + ' bwbtu' + (closedBet.type > 0 ? '📈' : '📉') + (realProfit > 0 ? ' 💢 заработал:' : ' 💤 потерял:') + (Math.abs(realProfit)).toFixed(8) + 'n⚖️: ' + freshUser.gst.toFixed(8) + ' GST //' + closedBet.currentRate);
  987.                                                         } else {
  988.                                                                 try {
  989.                                                                         glo.tg.sendTelegramMessage(config.tgbotAPI, config.admin_id, err);
  990.                                                                 } catch (e) {
  991.  
  992.                                                                 }
  993.                                                         }
  994.                                                 }, config, glo, dbc, stg, freshUser, undefined);
  995.                                 }
  996.                         }
  997.                 } catch (e) { }
  998.         }
  999. }
  1000.  
  1001. stg.renderGstOnBtcBet = function (oneBet, freshUser, isNew) {
  1002.         if (oneBet) {
  1003.                 var oneBetType = (oneBet.type > 0 ? '📈 <a href="https://t.me/joinchat/' + config.faqLong + '">лонг</a>' : '📉 <a href="https://t.me/joinchat/' + config.faqShort + '">шорт</a>');
  1004.                 var typeText = oneBet.type === 1 ? 'up' : 'down';
  1005.                 var currentRate = stg.xRate;
  1006.                 if (oneBet.pairType === 1) { currentRate = stg.xRate_XBTUSD; }
  1007.                 else if (oneBet.pairType === 2) { currentRate = stg.xRate_XBTUSD; };
  1008.                 var deltaRate = (currentRate - oneBet.xrate);
  1009.  
  1010.                 var absoluteTPProfit = 0;
  1011.                 if (oneBet.tp) {
  1012.                         var deltaTP = (oneBet.tp - oneBet.xrate);
  1013.                         var ktp = deltaTP / oneBet.xrate;
  1014.                         absoluteTPProfit = glo.floor8(oneBet.amount * ktp * oneBet.type * oneBet.ampl);
  1015.                 }
  1016.                 var absoluteSLProfit = 0;
  1017.                 if (oneBet.sl) {
  1018.                         var deltaSL = (oneBet.sl - oneBet.xrate);
  1019.                         var ksl = deltaSL / oneBet.xrate;
  1020.                         absoluteSLProfit = glo.floor8(oneBet.amount * ksl * oneBet.type * oneBet.ampl);
  1021.                 }
  1022.                 var k = deltaRate / oneBet.xrate;
  1023.                 var absoluteProfit = glo.floor8(oneBet.amount * k * oneBet.type * oneBet.ampl);
  1024.  
  1025.                 oneBet.absoluteProfit = absoluteProfit;
  1026.                 var kk = k * oneBet.type;
  1027.                 var prettyBet = oneBet.amount * oneBet.ampl;
  1028.                 if (prettyBet % 1 === 0) {
  1029.                         prettyBet = prettyBet.toFixed(0);
  1030.                 } else {
  1031.                         prettyBet = prettyBet.toFixed(8);
  1032.                 }
  1033.                 var p = 0.5 - parseInt((stg.longsM / (stg.longsM + stg.shortsM)) * 100) / 100;//повторный ненужный расчет
  1034.                 var refund = (p * oneBet.type * oneBet.amount * oneBet.ampl * config.cmsnBetGst / 3);
  1035.                 //if (refund > 0) { refund = 0; }
  1036.  
  1037.                 var line = glo.emo_profit(absoluteProfit) + oneBetType + ' <code>' + (kk > 0 ? '+' : '') + glo.floor2(kk * 100) + '%n</code>' +
  1038.                         ' <a href="' + config.LONGSHORT_link_h + '">СЕЙЧАС</a>: <code>' + currentRate.toFixed(2) + '</code>n' +
  1039.                         '   ' + glo.getDateTime(new Date(), true, true) + 'n' +
  1040.                         ' ОТКРЫТ: <code>' + oneBet.xrate.toFixed(2) + '</code>n' +
  1041.                         '   ' + glo.getDateTime(new Date(oneBet.dt), true, true) + 'nn' +
  1042.                         /*'<b> Баланс аккаунта:</b><code>n' +
  1043.                         ' =' + freshUser.gst.toFixed(8).padLeft(14, ' ') + ' GSTn' +
  1044.                         (oneBet.pairType === 0 ? ' ≈ ' + (freshUser.gst * config.gstFixedLo).toFixed(2).padLeft(13, ' ') + ' р.n' : '') + 'n</code>' +*/
  1045.                         ' ' + (config.DEALS_link ? '<a href="' + config.DEALS_link + '">' : '<b>') + 'Сделка' + (config.DEALS_link ? '</a>' : '</b>') + ':<code>n' +
  1046.                         '/btc_' + typeText + '_' + oneBet.amount + '_' + oneBet.ampl + '</code>n' +
  1047.                         ' = <code>' + prettyBet + '</code> <a href="t.me/gostcoin_ru">GST</a>n' +
  1048.                         (oneBet.pairType === 0 ? ' ≈ ' + (oneBet.amount * oneBet.ampl * config.gstFixedLo).toFixed(2).padLeft(13, ' ') + ' р.n' : '') +
  1049.                         (oneBet.tp && oneBet.tp > 0 ? 'TP: <code>' + oneBet.tp + '</code> (' + (absoluteTPProfit > 0 ? '+' : '') + '<code>' + absoluteTPProfit.pF() + '</code>)n' : '') + (oneBet.sl && oneBet.sl > 0 ? 'SL: <code>' + oneBet.sl + '</code> (' + (absoluteSLProfit > 0 ? '+' : '') + '<code>' + absoluteSLProfit.pF() + '</code>)n' : '') +
  1050.                         //'n' +
  1051.                         '<b> Текущая прибыль:</b>' + glo.emo_profit(absoluteProfit) + 'n' +//новичкам надо подсказывать прибыльно или убыточно
  1052.                         ((absoluteProfit > 0 ? ' +' : '  ') + '<code>' + absoluteProfit.toFixed(8)).padLeft(15, ' ') + '</code> GSTn' +
  1053.                         '<b> Баланс аккаунта после закрытия:</b> n' +
  1054.                         ' = <code>' + (freshUser.gst + oneBet.amount + absoluteProfit).toFixed(8).padLeft(14, ' ') + '</code> GSTn' +
  1055.                         (oneBet.pairType === 0 ? ' ≈ ' + ((freshUser.gst + oneBet.amount + absoluteProfit) * config.gstFixedLo).toFixed(2).padLeft(13, ' ') + ' р.n' : '') +
  1056.                         (' каждый час: ' + (refund > 0 ? '+' : '-') + '<code>' + Math.abs(refund).pF() + '</code> GSTn') +
  1057.                         '🐹 <a href="t.me/bt_chat">чат</a> ' +
  1058.                         (oneBet.pairType === 2 ? 'график: <a href="https://www.bitmex.com/chartEmbed?symbol=.BXBT">bitmex.com</a>n' : ' график: <a href="' + config.rateUrlUF + '">' + config.rateUrlText + '</a>n') /*+
  1059.                         (absoluteProfit < 0 ? '<i>Всегда можно</i> @sozdat_bota <i>за</i> <code>100</code><b>GST</b>n' : '<i>Сделка идет в плюс. Не буду предлагать</i> @sozdat_bota.n')*/;
  1060.                 if (config.minLog === 0 || (config.minLog > 0 && absoluteProfit > config.minLog) || (config.minLog < 0 && absoluteProfit < config.minLog)) {
  1061.                         console.log(' ' + freshUser.chat_id + ' ' + glo.getDateTime(new Date()) + ' ' + oneBet.xrate.toFixed(2) + '(' + glo.getDateTime(new Date(oneBet.dt)) + ')'
  1062.    /*'btc'*/ + typeText.substr(0, 1) + '_' + oneBet.amount.toFixed(8).padLeft(13, ' ') + ' ' + oneBet.ampl.toFixed(0).padLeft(2, ' ') +
  1063.                                 ((absoluteProfit > 0 ? '+ ' : '') + absoluteProfit.toFixed(8)).padLeft(13, ' ') + '(' + ((kk > 0 ? '+' : '') + glo.floor2(kk * 100).toFixed(2)).padLeft(6, ' ') + '%)' +
  1064.                                 ' =' + (freshUser.gst + oneBet.amount + absoluteProfit).toFixed(8).padLeft(13, ' ') + ' ≈' + ((freshUser.gst + oneBet.amount + absoluteProfit) * config.gstFixedLo).toFixed(2) + ' р.');
  1065.                 }
  1066.                 var markup = JSON.stringify({ inline_keyboard: [[{ text: (absoluteProfit > 0 ? '💢 ' : '💤 ') + '⏹', callback_data: '/cb_' + currentRate.toFixed(2) }, { text: '🔄', callback_data: '/rb' }]] });
  1067.                 if (isNew) {
  1068.                         glo.tg.sendTelegramMessage(config.tgbotAPI, oneBet.chat_id, line, function (err, body) {
  1069.                                 try {
  1070.                                         body = JSON.parse(body);
  1071.                                         dbc.tguch.findOneAndUpdate({ _id: freshUser._id }, { lastMessageId: body.result.message_id }, { new: true }, (err, freshUser) => {
  1072.                                                 var msgid = oneBet.message_id;
  1073.                                                 //console.log('msgid:' + msgid);
  1074.                                                 dbc.cryptobet.findOneAndUpdate({ 'chat_id': oneBet.chat_id }, { 'message_id': body.result.message_id }, function (err, oneBet) {
  1075.                                                         if (oneBet) {
  1076.                                                                 //console.log('msgupdated');
  1077.                                                                 //stg.renderGstOnBtcBet(oneBet, user);
  1078.                                                                 try {
  1079.                                                                         //console.log('preEdit:' + msgid);
  1080.                                                                         glo.tg.editMessageReplyMarkup(config.tgbotAPI, oneBet.chat_id, msgid,
  1081.                                                                                 function (err, body) {
  1082.                                                                                         //popNextBet(cb, allBets, allBetsInfo);
  1083.                                                                                 }, JSON.stringify({ inline_keyboard: [[{ text: '📄 Обновить', callback_data: '/rb' }]] }));
  1084.                                                                 } catch (e) { console.log(e); };
  1085.                                                         }
  1086.                                                 });
  1087.                                         })
  1088.                                 } catch (e) {
  1089.                                         console.log('catch997cryptobet:' + JSON.stringify(body));
  1090.                                         closeIfForbidden(body, freshUser);
  1091.                                         //catch997cryptobet:{"ok":false,"error_code":403,"description":"Forbidden: bot was blocked by the user"}
  1092.                                 }
  1093.  
  1094.                         }, markup);
  1095.                 } else {
  1096.                         glo.tg.editMessageText(config.tgbotAPI, oneBet.chat_id, oneBet.message_id, line,
  1097.                                 function (err, body) {
  1098.                                         //popNextBet(cb, allBets, allBetsInfo);
  1099.                                         try {
  1100.                                                 body = JSON.parse(body);
  1101.                                                 closeIfForbidden(body, freshUser);
  1102.                                         } catch (e) {
  1103.                                                 console.log('exEditBet:' + e + body);
  1104.                                         }
  1105.                                 }, markup, true);
  1106.                 }
  1107.         }
  1108. };
  1109. stg.lightBetsXBTLongs = [], stg.lightBetsXBTShorts = [];
  1110. stg.lightBetsXBTLongsNeedReaload = true, stg.lightBetsXBTShortsNeedReaload = true;
  1111. stg.findLightXBTBet = function (cb, betss, bet) {
  1112.         var i = 0;
  1113.         var bets = betss.slice();
  1114.         for (i = bets.length - 1; i >= 0; i--) {
  1115.                 if (bets[i].chat_id === bet.chat_id) {
  1116.                         if (cb) { cb(bets[i], i) }
  1117.                         return i;
  1118.                 }
  1119.         }
  1120.         return -1;
  1121. }
  1122. stg.removeLightXBTBet = function (bets, bet) {
  1123.         stg.findLightXBTBet(function (b, i) {
  1124.                 var oldlen = bets.length;
  1125.                 if (b && i > -1) {
  1126.                         bets.splice(i, 1);
  1127.                         console.log(oldlen + (bet.type > 0 ? ':removeLightXBTLong:' : ':removeLightXBTShort:') + bets.length);
  1128.                 }
  1129.         }, bets, bet);
  1130. }
  1131. stg.extendOneBet = function (oneBet) {
  1132.         dbc.tguch.findOne({ 'chat_id': oneBet.chat_id }, function (err, doc) {
  1133.                 if (doc) {
  1134.                         oneBet._chat_id = doc._id;
  1135.                 } else {
  1136.                         glo.e('stg1282:', oneBet.chat_id);
  1137.                 }
  1138.                 //try { console.log('Extended:' + doc.chat_id); }
  1139.                 //catch (e) { console.log('ERROR ON extendOneBet'); }
  1140.         });
  1141. }
  1142. function reloadLightXBTBets(cb) {
  1143.         var lightBetsXBTLongs = [];
  1144.         var lightBetsXBTShorts = []
  1145.         var now = new Date();
  1146.         var i = 0;
  1147.         var cursor = dbc.cryptobet.find({ pairType: 2 }).sort('amount').cursor();
  1148.         cursor.on('data', function (oneBet) {
  1149.                 i += 1;
  1150.  
  1151.                 if (oneBet.type > 0) {
  1152.                         lightBetsXBTLongs.push(oneBet);
  1153.                 } else if (oneBet.type < 0) {
  1154.                         lightBetsXBTShorts.push(oneBet);
  1155.                 } else {
  1156.                         console.log('WTF reloadLightXBTBets');
  1157.                 }
  1158.                 stg.extendOneBet(oneBet);
  1159.         })
  1160.         cursor.on('close', function () {
  1161.                 stg.lightBetsXBTLongs = lightBetsXBTLongs;
  1162.                 stg.lightBetsXBTShorts = lightBetsXBTShorts;
  1163.                 stg.lightBetsXBTLongsNeedReaload = false;
  1164.                 stg.lightBetsXBTShortsNeedReaload = false;
  1165.                 if (cb) cb();
  1166.                 console.log('//reloadLightXBT:' + i + ':' + (new Date() - now) + 'ms.');
  1167.         })
  1168. }
  1169. var signalLastPrice = undefined;//мировой курс битка в долларах
  1170. var longsshortsMSG_dts = Math.floor(new Date() / 1000);//последнее изменение/публикация курсалонговшортов
  1171. var longsshortsMSG_h = undefined;//час публикации // при несовпадении с текущим - отправляетсясообщение //при совпадении - изменяетсясообщение
  1172.  
  1173. function popRefundSLchain(cb, betType, bets, p, i, now, m) {
  1174.         var oneBet = bets.pop();
  1175.         if (oneBet) {
  1176.                 i += 1;
  1177.                 var sumtopay = p * betType * oneBet.amount * oneBet.ampl * config.cmsnBetGst / 3;
  1178.                 //var sumtopay = 0;//DEBUG
  1179.                 //if (sumtopay < 0) sumtopay = 0;
  1180.                 //if (sumtopay < 0) sumtopay /= 4;
  1181.                 m -= sumtopay;
  1182.                 dbc.incUserBalFast(function (user) {
  1183.                         popRefundSLchain(cb, betType, bets, p, i, now, m);
  1184.                 }, oneBet._chat_id, sumtopay, 'gst');
  1185.         } else {
  1186.                 cb(m)
  1187.         }
  1188. }
  1189.  
  1190. function refundSL(config, glo) {
  1191.         var now = new Date();
  1192.         var p = 0.5 - parseInt((stg.longsM / (stg.longsM + stg.shortsM)) * 100) / 100;
  1193.         var Longs = stg.lightBetsXBTLongs.slice();
  1194.         popRefundSLchain(function (tcu) {
  1195.                 var Shorts = stg.lightBetsXBTShorts.slice();
  1196.                 popRefundSLchain(function (tcd) {
  1197.                         if (config.chat_id_tcutcd !== undefined) {
  1198.                                 glo.tg.sendTelegramMessage(config.tgbotAPI, config.chat_id_tcutcd, 'tcu:<code>' + tcu.pF() + '</code> tcd:<code>' + tcd.pF() + '</code>', function (err, body) { });
  1199.                         } else {
  1200.                                 glo.infA(undefined, 'tcu:<code>' + tcu.pF() + '</code> tcd:<code>' + tcd.pF() + '</code>' + 'n1. Создай канал или чат, добавь бота админом и напиши там /getgroupidn2. Запомни цифру с минусом и напиши мне здесь команду:n<code>config.chat_id_tcutcd = </code>цифраИзПервогоПункта');
  1201.                         }
  1202.                         //HOURLY THREAD
  1203.                         stg.removeOldPayments();
  1204.                 }, -1, Shorts, p, 0, now, 0);
  1205.         }, 1, Longs, p, 0, now, 0);
  1206. }
  1207.  
  1208. stg.fillWacoPool = function (cb, ticker) {
  1209.         var bitTypei = glo.coinNameBit[ticker.toUpperCase()];
  1210.         dbc.wacopool.countDocuments({ 'bitType': bitTypei }, function (err, c) {//gst
  1211.                 if (c < 5) {
  1212.                         stg.sendingQueue.push(function (cb) {
  1213.                                 var token = glo.getToken(config.parentGA);
  1214.                                 var se = '{"t":3,"api":"' + config.parentAPI + '","c":"' + token + '","b":' + bitTypei + ',"i":0}';
  1215.                                 console.log(glo.colors.data(glo.getDateTime()) + glo.rDots + glo.colors.data(se));
  1216.                                 stg.parentClient.write(se, 'UTF8', cb);
  1217.                         });
  1218.                 } else {
  1219.                         if (cb) cb()
  1220.                 }
  1221.         })
  1222. }
  1223.  
  1224. var BXBTMaxLen = 0;
  1225. stg.LD = {};
  1226. function renderSL(config, glo) {
  1227.         var now = Math.floor(new Date() / 1000);
  1228.         if (now - 10 > longsshortsMSG_dts) {
  1229.                 longsshortsMSG_dts = now;
  1230.                 var directionSmile = ' ';
  1231.                 if (config.LONGSHORT_chat_id_h_price) {
  1232.                         if (stg.xRate_XBTUSD > config.LONGSHORT_chat_id_h_price) {
  1233.                                 directionSmile = '📈';
  1234.                         } else if (stg.xRate_XBTUSD < config.LONGSHORT_chat_id_h_price) {
  1235.                                 directionSmile = '📉';
  1236.                         }
  1237.                 }
  1238.                 var requestedGstAmount = 1;
  1239.                 //var popravka = (stg.xRatem_gst - stg.xRatemB_gst) / 4;
  1240.                 var fixedGstUpperRate = config.gstFixedHi;//stg.xRatem_gst - popravka;
  1241.                 var fixedGstLowerRate = config.gstFixedLo;//stg.xRatemB_gst + popravka;
  1242.                 if (fixedGstLowerRate == undefined) fixedGstLowerRate = stg.xRatemB_gst;
  1243.                 var fixedBtcUpperRate = stg.xRatem;
  1244.                 var fixedBtcLowerRate = stg.xRatemB;
  1245.                 var gstAsRub_buy = requestedGstAmount * fixedGstUpperRate;
  1246.                 var gstAsBtc_buy = gstAsRub_buy / fixedBtcLowerRate;
  1247.                 var gstAsRub_sell = requestedGstAmount * fixedGstLowerRate;
  1248.                 var gstAsBtc_sell = gstAsRub_sell / fixedBtcUpperRate;
  1249.                 var prettyPrice = stg.xRate_XBTUSD.toString();
  1250.                 if (prettyPrice.length > BXBTMaxLen) BXBTMaxLen = prettyPrice.length;
  1251.                 var longsshortsMSG = directionSmile + '$<code>' + prettyPrice.padRight(BXBTMaxLen, ' ') + '</code> (' + Math.round((stg.longsM / (stg.longsM + stg.shortsM)) * 100) + '%) / <code>' + (Math.round(config.gstFixedLo * 100) / 100).toFixed(2) + '</code> (' + parseInt(config.gstLVS) + '%) '/*+'/<code>' + Math.round((stg.shortsM / (stg.longsM + stg.shortsM)) * 100) + '</code>'*/ + 'nL: <code>' + (stg.longsM * gstAsBtc_sell).toFixed(2) + '</code>BTC, S: <code>' + (stg.shortsM * gstAsBtc_sell).toFixed(2) + '</code>BTC';
  1252.                 //if (config.LONGSHORT_chat_id !== undefined) {
  1253.                 //      glo.tg.sendTelegramMessage(config.tgbotAPI, config.LONGSHORT_chat_id, longsshortsMSG, function (err, body) { }, undefined, false);
  1254.                 //}
  1255.                 if (config.LONGSHORT_chat_id_h) {
  1256.                         var nowhours = new Date().getHours();
  1257.                         if ((new Date().getMinutes() === 0 && stg.longsshortsMSG_h != nowhours) || config.LONGSHORT_chat_id_h_message_id === undefined) {
  1258.                                 stg.longsshortsMSG_h = nowhours;
  1259.                                 glo.tg.deleteTelegramMessage(config.tgbotAPI, config.LONGSHORT_chat_id_h, config.LONGSHORT_chat_id_h_message_id);
  1260.                                 glo.tg.sendTelegramMessage(config.tgbotAPI, config.LONGSHORT_chat_id_h, longsshortsMSG, function (err, body) {
  1261.                                         if (body) {
  1262.                                                 body = JSON.parse(body);
  1263.  
  1264.                                                 var oldLD = stg.LD[config.LONGSHORT_chat_id_h_message_id + '' + config.LONGSHORT_chat_id_h];
  1265.                                                 if (oldLD) {
  1266.                                                         stg.LD[body.result.message_id + '' + config.LONGSHORT_chat_id_h] = [oldLD[0], oldLD[1]];
  1267.                                                         dbc.lidi.findOneAndUpdate({ 'chat_id': config.LONGSHORT_chat_id_h, 'msg_id': config.LONGSHORT_chat_id_h_message_id }, {
  1268.                                                                 'msg_id': body.result.message_id
  1269.                                                         }, () => {
  1270.                                                                 delete stg.LD[config.LONGSHORT_chat_id_h_message_id + '' + config.LONGSHORT_chat_id_h];
  1271.                                                         });
  1272.                                                 }
  1273.                                         }
  1274.                                         glo.tg.sendTelegramMessage(config.tgbotAPI, config.LONGSHORT_chat_id_h, longsshortsMSG, function (err, body) {
  1275.                                                 if (body) {
  1276.                                                         body = JSON.parse(body);
  1277.  
  1278.                                                         config.LONGSHORT_chat_id_h_message_id = body.result.message_id;
  1279.                                                         config.LONGSHORT_chat_id_h_price = stg.xRate_XBTUSD;
  1280.                                                         refundSL(config, glo);
  1281.                                                 }
  1282.                                         });
  1283.                                 }/*, stg.likes_keyb(config.LONGSHORT_chat_id_h, config.LONGSHORT_chat_id_h_message_id)*/);
  1284.  
  1285.                                 //stg.price.drawNewHour(glo, 0, () => {
  1286.  
  1287.                                 stg.upconf('btcusd_chat_id_msg_id', undefined);
  1288.                                 stg.price.drawNewHour(glo, 0, (msg_id, file_id) => {
  1289.                                         stg.upconf('btcusd_chat_id_msg_id', msg_id);
  1290.                                 }, config.btcusd_chat_id);
  1291.                                 //}, config.btcusd_chat_id);
  1292.                                 stg.upconf('gstrub_chat_id_msg_id', undefined);
  1293.                                 stg.price.drawNewHour(glo, 1, (msg_id, file_id) => {
  1294.                                         stg.upconf('gstrub_chat_id_msg_id', msg_id);
  1295.                                 }, config.gstrub_chat_id);
  1296.                         } else {
  1297.                                 try {
  1298.                                         glo.tg.editMessageText(config.tgbotAPI, config.LONGSHORT_chat_id_h, config.LONGSHORT_chat_id_h_message_id, longsshortsMSG, function (err, body) {
  1299.                                                 //EVERY MINUTE THREAD (если заполнен config.LONGSHORT_chat_id_h)
  1300.  
  1301.                                         }/*, stg.likes_keyb(config.LONGSHORT_chat_id_h, config.LONGSHORT_chat_id_h_message_id)*/, undefined, true);
  1302.                                 } catch (e) { console.log('stg.js renderSL LIKES' + e) }
  1303.                                 if (config.btcusd_chat_id_msg_id) {
  1304.                                         stg.price.drawHour(glo, 0, (file_id) => {
  1305.                                                 stg.upconf('btcusd_chat_id_file_id', file_id);
  1306.                                                 if (config.gstrub_chat_id_msg_id) {
  1307.                                                         stg.price.drawHour(glo, 1, (file_id) => {
  1308.                                                                 stg.upconf('gstrub_chat_id_file_id', file_id);
  1309.                                                         }, config.gstrub_chat_id, config.gstrub_chat_id_msg_id);
  1310.                                                 }
  1311.                                         }, config.btcusd_chat_id, config.btcusd_chat_id_msg_id);
  1312.                                 }
  1313.                                 if (config.gstrub_chat_id_msg_id && new Date().getMinutes() > 3 && (!config.gstrub_chat_last_t || config.gstrub_chat_last_t + 15 < new Date().getTime() / 1000)) {
  1314.                                         stg.upconf('gstrub_chat_last_t', parseInt(new Date().getTime() / 1000));
  1315.                                         glo.tg.editMessageMedia(config.tgbotAPI, config.gstrub_chat_id, config.gstrub_chat_id_msg_id, config.gstrub_chat_id_file_id, function (err, body) { }
  1316.                                 /*,stg.likes_keyb(chat_id, msg_id)*/);
  1317.                                 }
  1318.                                 //if (config.gstrub_chat_id_msg_id) {
  1319.                                 //      stg.price.drawHour(glo, 1, (file_id) => {
  1320.                                 //              stg.upconf('gstrub_chat_id_file_id', file_id);
  1321.                                 //      }, config.gstrub_chat_id, config.gstrub_chat_id_msg_id);
  1322.                                 //}
  1323.                         }
  1324.                 }
  1325.         }
  1326. }
  1327. function popLongShortChain(cb, betType, bets, currentPrice, i, now, m) {
  1328.         var oneBet = bets.pop();
  1329.         if (m === undefined) m = 0;
  1330.         if (oneBet) {//тело цикла
  1331.                 i += 1;
  1332.                 m += oneBet.amount * oneBet.ampl;
  1333.                 oneBet.currentRate = currentPrice;
  1334.                 stg.verifyUserBetAndBalance(function () {
  1335.                         popLongShortChain(cb, betType, bets, currentPrice, i, now, m);
  1336.                 }, oneBet, ((oneBet.type * oneBet.xrate) - (oneBet.type * currentPrice)) / oneBet.xrate);
  1337.         } else {//окончания
  1338.                 if (betType > 0) {
  1339.                         stg.longsM = parseInt(m);
  1340.                         stg.longsC = i;
  1341.                         if (cb) cb();//полу-выход
  1342.                 } else {
  1343.                         stg.shortsM = parseInt(m);
  1344.                         stg.shortsC = i;
  1345.                         var formattedPrice = currentPrice.toString().padRight(7, ' ').padLeft(8, ' ');
  1346.  
  1347.                         if (currentPrice > signalLastPrice) {
  1348.                                 formattedPrice = glo.colors.white(glo.colors.bgred(formattedPrice));
  1349.                         } else {
  1350.                                 formattedPrice = glo.colors.white(glo.colors.bgblue(formattedPrice));
  1351.                         }
  1352.                         var lag = new Date() - now;
  1353.                         if (!config.mininvestgst) config.mininvestgst = 0;
  1354.                         if (lag > 2000) {
  1355.                                 config.mininvestgst += config.mininvestgstdelta;
  1356.                         } else {
  1357.                                 if (config.mininvestgst > -200) {
  1358.                                         config.mininvestgst -= config.mininvestgstdelta;
  1359.                                 }
  1360.                         }
  1361.  
  1362.                         console.log(formattedPrice + ' LONGS[' + stg.longsC + ']:' + stg.longsM.toString().padLeft(7, ' ') + ' GST SHORTS[' + stg.shortsC + ']' + stg.shortsM.toString().padLeft(7, ' ') + ' GST //' + lag + 'ms.inv:' + config.mininvestgst + ' ' + config.stg_btc);
  1363.                         if (config.LONGSHORT_chat_id_h_message_id) {
  1364.                                 renderSL(config, glo);
  1365.                         }
  1366.                         if (cb) cb();//выход
  1367.                 }
  1368.         }
  1369. }
  1370. stg.signalCryptoBets = function (cb, currentPrice) {
  1371.         var now = new Date();
  1372.         if (stg.lightBetsXBTLongsNeedReaload || stg.lightBetsXBTShortsNeedReaload) {
  1373.                 reloadLightXBTBets(function () {
  1374.                         var Longs = stg.lightBetsXBTLongs.slice();
  1375.                         popLongShortChain(function () {
  1376.                                 var Shorts = stg.lightBetsXBTShorts.slice();
  1377.                                 popLongShortChain(function () {
  1378.                                         signalLastPrice = currentPrice;
  1379.                                 }, -1, Shorts, currentPrice, 0, now);
  1380.                         }, 1, Longs, currentPrice, 0, now);
  1381.                 });
  1382.         } else {
  1383.                 function endCycle() {
  1384.                         var ps = 1;
  1385.                         if (currentPrice > 0 && signalLastPrice > 0)
  1386.                                 ps = (signalLastPrice / currentPrice);
  1387.  
  1388.                         //var automar = 0.03 * 1 / config.maxReqGstAmo;
  1389.                         var hi = config.gstFixedHi * ps * ps;
  1390.                         var lo = hi;
  1391.                         if (hi <= config.minCost) { hi = config.minCost };
  1392.                         if (lo <= config.minCost) { lo = config.minCost };
  1393.                         stg.upconf('gstFixedHi', hi);
  1394.                         stg.upconf('gstFixedLo', lo);
  1395.                         if (ps !== 1) {
  1396.                                 stg.addPrice(stg.price.gstrub, config.gstFixedLo);
  1397.                         }
  1398.                         signalLastPrice = currentPrice;
  1399.                 }
  1400.                 var Longs = stg.lightBetsXBTLongs.slice();
  1401.                 popLongShortChain(() => {
  1402.                         var Shorts = stg.lightBetsXBTShorts.slice();
  1403.                         popLongShortChain(endCycle, -1, Shorts, currentPrice, 0, now);
  1404.                 }, 1, Longs, currentPrice, 0, now);
  1405.  
  1406.  
  1407.         }
  1408. }
  1409.  
  1410. stg.recountCryptoBets = function (cb, newMessage) {
  1411.         var allBets = [];
  1412.         var allBetsInfo = [];
  1413.         var summaryBets = {
  1414.                 totAmount: 0,
  1415.                 totMu: 0,
  1416.                 totMd: 0
  1417.         };
  1418.         var nowMinutes = new Date().getMinutes();
  1419.         var betco = 0;
  1420.         function popNextBet(cb, allBets, allBetsInfo, summaryBets) {
  1421.                 if (allBets.length > 0) {
  1422.                         var oneBet = allBets.pop();
  1423.                         if (oneBet) {
  1424.                                 betco += 1;
  1425.                                 if (oneBet.pairType === 2) {
  1426.                                         oneBet.currentRate = glo.rou2(stg.xRate_XBTUSD);
  1427.                                 } else if (oneBet.pairType === 1) {
  1428.                                         oneBet.currentRate = glo.rou2(stg.xRate_XBTUSD);
  1429.                                 } else {
  1430.                                         oneBet.currentRate = glo.rou2(stg.xRate);
  1431.                                 }
  1432.  
  1433.                                 if (oneBet.currentRate > 0) {
  1434.  
  1435.                                         summaryBets.totAmount += oneBet.amount;
  1436.                                         if (oneBet.type > 0) {
  1437.                                                 summaryBets.totMu += oneBet.amount * oneBet.ampl;
  1438.                                         } else {
  1439.                                                 summaryBets.totMd += oneBet.amount * oneBet.ampl;
  1440.                                         }
  1441.                                         if (oneBet.message_id && oneBet.message_id > 0) {
  1442.                                                 function prepareRenderGstOnBtcBet(err, freshUser) {
  1443.                                                         if (!err) {
  1444.                                                                 if (oneBet._chat_id === undefined) oneBet.chat_id = freshUser._id;
  1445.                                                                 var oneBetType = (oneBet.type > 0 ? '📈' : '📉');
  1446.                                                                 var currentRate = oneBet.currentRate;//текущий курс
  1447.                                                                 var deltaRate = (currentRate - oneBet.xrate);//изменение от открытия
  1448.                                                                 var k = deltaRate / oneBet.xrate;//коэффицент прибыли/убытка
  1449.                                                                 var absoluteProfit = glo.floor8(oneBet.amount * k * oneBet.type * oneBet.ampl);//рассчитанная прибыль от сделки для пользователя
  1450.                                                                 var kk = k * oneBet.type;
  1451.                                                                 try {
  1452.                                                                         //var infostring = glo.emo(oneBet.chat_id) + '' + (config.privacy ? '' : oneBet.chat_id.toString().padRight(9, ' ') + ' ') + (deltaRate > 0 ? '+' : '-') + (Math.abs(deltaRate).toFixed(2)).padLeft(8, ' ') + ' ' + (oneBet.type > 0 ? '📈' : '📉') + ' (' + oneBet.amount + 'x' + oneBet.ampl + ')' + (absoluteProfit > 0 ? '💢 ' : '💤 ') + Math.abs(absoluteProfit).toFixed(2) + '//' + (freshUser.gst + oneBet.amount + absoluteProfit).toFixed(2);
  1453.                                                                         allBetsInfo.push({ chat_id: oneBet.chat_id, deltaRate: deltaRate, type: oneBet.type, pairType: oneBet.pairType, amount: oneBet.amount, ampl: oneBet.ampl, absoluteProfit: absoluteProfit, marginBal: (freshUser.gst + oneBet.amount + absoluteProfit) });
  1454.                                                                         //console.log(infostring);
  1455.                                                                         if (newMessage) {
  1456.                                                                                 stg.renderGstOnBtcBet(oneBet, freshUser, newMessage);
  1457.                                                                                 setTimeout(popNextBet, 200, cb, allBets, allBetsInfo, summaryBets);
  1458.                                                                         } else {
  1459.                                                                                 setTimeout(popNextBet, 100, cb, allBets, allBetsInfo, summaryBets);
  1460.                                                                         }
  1461.                                                                 } catch (e) {
  1462.                                                                         console.log(e);
  1463.                                                                         popNextBet(cb, allBets, allBetsInfo, summaryBets);
  1464.                                                                 }
  1465.                                                         } else {
  1466.                                                                 popNextBet(cb, allBets, allBetsInfo, summaryBets);
  1467.                                                         }
  1468.                                                 }
  1469.                                                 if (oneBet._chat_id === undefined) {
  1470.                                                         dbc.tguch.findOne({ 'chat_id': oneBet.chat_id }, prepareRenderGstOnBtcBet);
  1471.                                                 } else {
  1472.                                                         dbc.tguch.findById({ '_id': oneBet._chat_id }, prepareRenderGstOnBtcBet);
  1473.                                                 }
  1474.                                         } else {
  1475.                                                 popNextBet(cb, allBets, allBetsInfo, summaryBets);
  1476.                                         }
  1477.  
  1478.                                         if (oneBet.type === 1) {//to the moon
  1479.                                                 if (oneBet.currentRate < oneBet.xrate) {//close if no balance
  1480.                                                         stg.verifyUserBetAndBalance(undefined, oneBet, (oneBet.xrate - oneBet.currentRate) / oneBet.xrate);
  1481.                                                 }
  1482.                                         } else if (oneBet.type === -1) {//to the hell
  1483.                                                 if (oneBet.currentRate > oneBet.xrate) {//close if no balance
  1484.                                                         stg.verifyUserBetAndBalance(undefined, oneBet, (oneBet.currentRate - oneBet.xrate) / oneBet.xrate);
  1485.                                                 }
  1486.                                         }
  1487.                                 }
  1488.                         } else {
  1489.  
  1490.                         }
  1491.                 } else {
  1492.                         if (cb) cb(allBetsInfo);
  1493.                         console.log(' c: ' + summaryBets.totCount + ' b: ' + summaryBets.totAmount + ' mu: ' + summaryBets.totMu + ' md: ' + summaryBets.totMd + ' ');
  1494.                 }
  1495.         }
  1496.         var cursor = dbc.cryptobet.find({}).sort('amount').sort('ampl').cursor();//reversed for pop()
  1497.         cursor.on('data', function (oneBet) {
  1498.                 allBets.push(oneBet);
  1499.         })
  1500.         cursor.on('close', function () {
  1501.                 summaryBets.totCount = allBets.length;
  1502.                 popNextBet(cb, allBets, allBetsInfo, summaryBets);
  1503.         })
  1504. }
  1505.  
  1506. stg.sendAllBalances = function () {
  1507.         var chids = [];
  1508.  
  1509.         var cursor = dbc.tguch.find({ 'chat_id': { $gt: 0 }, 'gst': { '$gte': 0.2 }, '$or': [{ 'antispam': null }, { 'antispam': 0 }] }).sort('-gst').cursor();
  1510.         cursor.on('data', function (doc) {//перебираем все по очереди
  1511.                 chids.push(doc.chat_id);
  1512.         });
  1513.         //cursor.on('error', function (err) {
  1514.         //      console.error(err);
  1515.         //      glo.informAdmins('error sms / yes', function () { }, config.tgbotAPI);
  1516.         //})
  1517.         cursor.on('close', function () {// Called when done
  1518.                 glo.tg.sendTelegramMessage(config.tgbotAPI, config.admin_id, 'РАССЫЛКА БАЛАНСОВ НАЧАЛАСЬ', function (err, body) {
  1519.                         body = JSON.parse(body);
  1520.                         glo.tg.smsChainSend(config.tgbotAPI, chids, '', config.admin_id, body.result.message_id, undefined, function (cb, chat_id) {
  1521.                                 dbc.tguch.findOne({ 'chat_id': chat_id }, function (err, user) {
  1522.                                         var UR = (config.gstFixedLo / (stg.xRate / stg.xRate_XBTUSD));
  1523.                                         var GSTvsUSD = '$<code>' + UR.toFixed(2) + '</code>';
  1524.                                         var GSTvsRUB = '<code>' + config.gstFixedLo.toFixed(2) + '</code>₽';
  1525.                                         var ratesString = '(<code>1</code> GST = ' + GSTvsUSD + ' = ' + GSTvsRUB + ')';
  1526.                                         console.log('sab: ' + chat_id.toString().padLeft(9, ' ') + ' : ' + user.gst.toFixed(8));
  1527.                                         cb('⚖️ <code>' + user.gst.toFixed(8) + '</code> GST n= $<code>' + (user.gst * UR).toFixed(2) + '</code> = <code>' + (user.gst * config.gstFixedLo).toFixed(2) + '</code>₽n' + ratesString,
  1528.                                                 JSON.stringify({ inline_keyboard: [[{ text: 'GST Баланс', callback_data: '/bal_gst' }]] }));
  1529.                                         //console.log(chat_id + ' ' + user.gst);
  1530.                                 })
  1531.                         });
  1532.                 });
  1533.         });
  1534. }
  1535.  
  1536. function payPyr(cb, glo, config, dbc) {
  1537.         if (config.pyr === 0) {
  1538.                 //no action
  1539.                 if (cb) cb();
  1540.         } else {
  1541.  
  1542.                 function payed(num10000, num1000, num100, num0) {
  1543.                         try {
  1544.                                 dbc.tguch.aggregate([
  1545.                                         {
  1546.                                                 "$match": {
  1547.                                                         gst: { $gte: 0 },
  1548.                                                         isadmin: { $ne: 1 },
  1549.                                                         chat_id: { $gt: 0 }
  1550.                                                 }
  1551.                                         },
  1552.                                         {
  1553.                                                 "$group": {
  1554.                                                         _id: null,
  1555.                                                         "totalGST": { $sum: "$gst" }
  1556.                                                 }
  1557.                                         }
  1558.                                 ], function (err, result) {
  1559.                                         if (err) {
  1560.                                                 console.error(err);
  1561.                                         } else {
  1562.                                                 try {
  1563.                                                         try {
  1564.                                                                 var totGST = result[0].totalGST;
  1565.                                                                 if (totGST === 0) { totGST = 1 }
  1566.                                                                 var outvstot = ((config.instGST / (config.instGST + totGST)) * 100).toFixed(0);
  1567.                                                                 var totMSG = 'TOT: <code>' + totGST.toFixed(0) + '</code> GST ' + (config.gstLVS < 50 ? '🔼' : '🔽') + ' ' + num10000 + ' + ' + num1000 + ' + ' + num100 + ' + ' + num0;
  1568.                                                                 if (config.TOT_chat_id !== undefined) {
  1569.                                                                         glo.tg.sendTelegramMessage(config.tgbotAPI, config.TOT_chat_id, totMSG, function (err, body) { }, undefined, false);
  1570.                                                                 }// else { glo.informAdmins(totMSG, function () { }, config.tgbotAPI); }
  1571.                                                                 if (config.TOT_chat_id_h && new Date().getMinutes() === 0) {
  1572.                                                                         glo.tg.sendTelegramMessage(config.tgbotAPI, config.TOT_chat_id_h, totMSG, function (err, body) { }, undefined, false);
  1573.                                                                 }
  1574.                                                                 //LONGS SHORTS
  1575.                                                                 if (stg.longsM !== undefined && stg.shortsM !== undefined && stg.xRate_XBTUSD > 0) {
  1576.                                                                         renderSL(config, glo)
  1577.                                                                 }
  1578.                                                         } catch (e) {
  1579.                                                                 console.log('EX: stg.js TOT' + JSON.stringify(e));
  1580.                                                         }
  1581.                                                 }
  1582.                                                 catch (e) {
  1583.                                                         glo.msgDebug(e);
  1584.                                                 }
  1585.                                         }
  1586.                                 });
  1587.                         } catch (e) {
  1588.                                 glo.informAdmins('aggregate не прошёл' + e, function () { }, config.tgbotAPI);
  1589.                         }
  1590.                 }
  1591.  
  1592.                 if (config.pyr_new >= 0) {
  1593.                         dbc.tguch.updateMany({ 'gst': { '$gte': 50000 }/*, antispam: { '$ne': 1 }*/ },
  1594.                                 { $mul: { "gst": 1 + (config.pyr_new / 100 / 24 / 60) } }
  1595.                                 , function (err, num10000) {
  1596.                                         dbc.tguch.updateMany({ 'gst': { '$gte': 10000, '$lt': 50000 }/*, antispam: { '$ne': 1 }*/ },
  1597.                                                 { $mul: { "gst": 1 + (config.pyr_new / 100 / 24 / 60 / 2) } }
  1598.                                                 , function (err, num1000) {
  1599.                                                         dbc.tguch.updateMany({ 'gst': { '$gte': 1000, '$lt': 10000 }/*, antispam: { '$ne': 1 }*/ },
  1600.                                                                 { $mul: { "gst": 1 + (config.pyr_new / 100 / 24 / 60 / 4) } }
  1601.                                                                 , function (err, num100) {
  1602.                                                                         dbc.tguch.updateMany({ 'gst': { '$gt': 0, '$lt': 1000 }/*, antispam: { '$ne': 1 }*/ },
  1603.                                                                                 { $mul: { "gst": 1 + (config.pyr_new / 100 / 24 / 60 / 8) } }
  1604.                                                                                 , function (err, num0) {
  1605.                                                                                         payed(num10000.n, num1000.n, num100.n, num0.n)
  1606.                                                                                 });
  1607.                                                                 });
  1608.                                                 });
  1609.                                 });
  1610.                 } else if (config.pyr_new < 0) {
  1611.                         dbc.tguch.updateMany({ 'gst': { '$gte': 0 }/*, antispam: { '$ne': 1 }*/ },
  1612.                                 { $mul: { "gst": 1 + (config.pyr_new / 100 / 24 / 60) } }
  1613.                                 , function (err, num0) {
  1614.                                         payed(0, 0, 0, num0.n);
  1615.                                 });
  1616.                 } else {
  1617.                         payed(0, 0, 0, 0);
  1618.                 }
  1619.         }
  1620. }
  1621.  
  1622. //var lastUsedProxy = undefined;
  1623. stg.getXRatePRO = function (convert, cb) {//RUB or USD convert
  1624.         var now = new Date() / 1000;
  1625.         if (!config.xRate_last_updated || now > config.xRate_last_updated + 30) {
  1626.                 config.xRate_last_updated = now;
  1627.                 glo.requestAPI({ url: 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?symbol=BTC&convert=' + convert, headers: { "X-CMC_PRO_API_KEY": config.coinmarketcapapi } }, function (err, resp) {
  1628.                         //var dummy = {
  1629.                         //      "status": {
  1630.                         //              "timestamp": "2018-11-11T18:04:42.006Z",
  1631.                         //              "error_code": 0,
  1632.                         //              "error_message": null,
  1633.                         //              "elapsed": 7,
  1634.                         //              "credit_count": 1
  1635.                         //      },
  1636.                         //      "data": {
  1637.                         //              "BTC": {
  1638.                         //                      "id": 1,
  1639.                         //                      "name": "Bitcoin",
  1640.                         //                      "symbol": "BTC",
  1641.                         //                      "slug": "bitcoin",
  1642.                         //                      "circulating_supply": 17371100,
  1643.                         //                      "total_supply": 17371100,
  1644.                         //                      "max_supply": 21000000,
  1645.                         //                      "date_added": "2013-04-28T00:00:00.000Z",
  1646.                         //                      "num_market_pairs": 6654,
  1647.                         //                      "cmc_rank": 1,
  1648.                         //                      "last_updated": "2018-11-11T18:03:11.000Z",
  1649.                         //                      "quote": {
  1650.                         //                              "RUB": {
  1651.                         //                                      "price": 432473.54459673015,
  1652.                         //                                      "volume_24h": 260035011062.7959,
  1653.                         //                                      "percent_change_1h": 0.0423,
  1654.                         //                                      "percent_change_24h": -0.795,
  1655.                         //                                      "percent_change_7d": 0.5308,
  1656.                         //                                      "market_cap": 7512541190544.26,
  1657.                         //                                      "last_updated": "2018-11-11T18:00:01.000Z"
  1658.                         //                              }
  1659.                         //                      }
  1660.                         //              }
  1661.                         //      }
  1662.                         //}
  1663.                         var anyNewValue = false;
  1664.                         try {
  1665.                                 var jo = JSON.parse(resp);
  1666.  
  1667.                                 var last_updated = Date.parse(jo.data.BTC.last_updated) / 1000;
  1668.                                 console.log(last_updated);
  1669.                                 var last_updated_c = Date.parse(jo.data.BTC.quote[convert].last_updated) / 1000;
  1670.                                 console.log(last_updated_c);
  1671.                                 if (last_updated_c > last_updated) last_updated = last_updated_c;
  1672.                                 console.log(last_updated);
  1673.                                 console.log(config.xRate_last_updated);
  1674.                                 console.log(last_updated - config.xRate_last_updated);
  1675.                                 config.xRate_last_updated = last_updated;
  1676.  
  1677.  
  1678.                                 var newxRate = parseFloat(jo.data.BTC.quote[convert].price);
  1679.                                 console.log(convert + ' : ' + newxRate);
  1680.                                 if (convert === 'RUB') {
  1681.                                         var newxRatem = glo.rou2(newxRate + newxRate * config.rateMargin);
  1682.                                         var newxRatemB = glo.floor2(newxRate + newxRate * config.rateBMargin);
  1683.                                         if (newxRate !== stg.xRate) { stg.xRate = newxRate; anyNewValue = true; }
  1684.                                         if (newxRatem !== stg.xRatem) { stg.xRatem = newxRatem; anyNewValue = true; }
  1685.                                         if (newxRatemB !== stg.xRatemB) { stg.xRatemB = newxRatemB; anyNewValue = true; }
  1686.                                 } else {
  1687.                                         if (newxRate !== stg.xRate_BTCUSD) { stg.xRate_BTCUSD = newxRate; anyNewValue = true; };
  1688.                                 }
  1689.  
  1690.                                 if (cb) { cb(); };
  1691.  
  1692.                                 console.log('PRO BTC_xr: ($' + glo.colors.info(stg.xRate_BTCUSD.toFixed(2)) + ')(' + glo.colors.info(stg.xRate.toFixed(2)) + '₽)<' + stg.xRatemB + '<' + stg.xRatem + ' GST_xr: (' + glo.colors.info(glo.floor2(stg.xRate_gst).toFixed(2)) + ')<' + glo.floor2(config.gstFixedLo) + '<' + glo.floor2(config.gstFixedHi));
  1693.                         } catch (e) {
  1694.                                 console.log('can't load xRate' + e);
  1695.                                 if (cb) cb();
  1696.                         };
  1697.                 }, undefined);
  1698.         } else {
  1699.                 console.log("skip PRO: " + (now - config.xRate_last_updated));
  1700.                 if (cb) cb();
  1701.         }
  1702. }
  1703.  
  1704. setTimeout(() => {
  1705.         stg.interv = setInterval(() => {
  1706.                 var nowDate = new Date();
  1707.                 var nowHours = nowDate.getHours();
  1708.                 var spamHour = false;
  1709.                 if (nowHours % 12 === 0) spamHour = true;
  1710.                 var spamIt = false;
  1711.                 if (spamHour && nowDate.getMinutes() === 1) spamIt = true;
  1712.                 stg.recountCryptoBets(function (allBetsInfo) {
  1713.                         //console.log(allBetsInfo.join('n'));
  1714.                         stg.allBetsInfo = allBetsInfo;
  1715.  
  1716.                         if (spamIt && stg.exportNow !== undefined) { stg.exportNow(payPyr, glo, config, dbc); }
  1717.                         else { payPyr(undefined, glo, config, dbc); }
  1718.                 }, spamIt);
  1719.         }, 60000);
  1720. }, 30000)
  1721.  
  1722. stg.getXRate = function (customProxy, cb, cbe) {
  1723.         //if (customProxy) { lastUsedProxy = customProxy; }
  1724.         //else {
  1725.         //      customProxy = lastUsedProxy;
  1726.         //}
  1727.         glo.requestAPI({ url: config.USD_RUB_url }, function (err, resp) {
  1728.                 var anyNewValue = false;
  1729.                 try {
  1730.                         var jo = undefined;
  1731.                         try {
  1732.                                 jo = JSON.parse(resp);
  1733.                                 //console.log(resp);
  1734.                                 var arr = config.USD_RUB_path.split("/");
  1735.  
  1736.                                 for (var i = 0; i < arr.length; i++) {
  1737.                                         jo = jo[arr[i]];
  1738.                                 }
  1739.                                 stg.xRate_USDRUB = glo.rou2(parseFloat(jo));
  1740.                                 stg.upconf('xRate_USDRUB', stg.xRate_USDRUB);
  1741.                                 console.log('load: stg.xRate_USDRUB', stg.xRate_USDRUB);
  1742.                         } catch (e) {
  1743.                                 stg.xRate_USDRUB = config.xRate_USDRUB;
  1744.                                 console.log('loadDefault: stg.xRate_USDRUB', stg.xRate_USDRUB);
  1745.                         }
  1746.  
  1747.                         var newxRate = stg.xRate_USDRUB * stg.xRate_XBTUSD;
  1748.                         var newxRatem = glo.rou2(newxRate + newxRate * config.rateMargin);
  1749.                         var newxRatemB = glo.floor2(newxRate + newxRate * config.rateBMargin);
  1750.                         if (newxRate !== stg.xRate) { stg.xRate = newxRate; anyNewValue = true; }
  1751.                         if (newxRatem !== stg.xRatem) { stg.xRatem = newxRatem; anyNewValue = true; }
  1752.                         if (newxRatemB !== stg.xRatemB) { stg.xRatemB = newxRatemB; anyNewValue = true; }
  1753.  
  1754.                         if (cb) { cb() }
  1755.                         if (!cb || !stg.xRate_gst) {
  1756.                                 stg.xRate_gst = config.gstFixedLo;
  1757.                                 stg.xRatem_gst = config.gstFixedLo;
  1758.                                 stg.xRatemB_gst = config.gstFixedLo;
  1759.                                 //glo.requestAPI({ url: config.rateUrl_gst }, function (err, resp) {
  1760.                                 //      try {
  1761.                                 //              var jo = JSON.parse(resp);
  1762.                                 //              //console.log(resp);
  1763.                                 //              var arr = config.ratePath_gst.split("/");
  1764.                                 //              for (var i = 0; i < arr.length; i++) {
  1765.                                 //                      jo = jo[arr[i]];
  1766.                                 //              }
  1767.                                 //              stg.xRate_gst = glo.rou2(parseFloat(jo));
  1768.                                 //              stg.xRatem_gst = glo.rou2(stg.xRate_gst + stg.xRate_gst * config.rateMargin_GST);
  1769.                                 //              stg.xRatemB_gst = glo.floor2(stg.xRate_gst + stg.xRate_gst * config.rateBMargin_GST);
  1770.                                 //      } catch (e) { };
  1771.                                 //}, config.i2pProxy);
  1772.                         }
  1773.                 } catch (e) {
  1774.                         if (cb) { cb() } else {
  1775.                                 if (cbe) cbe();
  1776.                         }
  1777.                 };
  1778.                 try {
  1779.                         console.log('BTC_xr: ($' + glo.colors.info(stg.xRate_XBTUSD.toFixed(2)) + ')(' + glo.colors.info(stg.xRate.toFixed(2)) + '₽)<' + stg.xRatemB + '<' + stg.xRatem + ' GST_xr: (' + glo.colors.info(glo.floor2(stg.xRate_gst).toFixed(2)) + ')<' + glo.floor2(config.gstFixedLo) + '<' + glo.floor2(config.gstFixedHi));
  1780.                 } catch (e) { };
  1781.                 if (cb) { } else {
  1782.                         //reload bots
  1783.                         if (config.instGST >= 0) {
  1784.                                 var cursor = dbc.tguch.find({ 'moderated_bot_username': 1, 'gst': { '$gte': 100 }, 'bot_username': { '$ne': '' } }).limit(50).sort('-gst').sort('-btc').cursor();
  1785.                                 var bots_new_list = [];
  1786.                                 var bots_new_listD = [];
  1787.                                 var i = 0;
  1788.                                 cursor.on('data', function (doc) {
  1789.                                         i += 1;
  1790.                                         var medal = '';
  1791.                                         switch (i) {
  1792.                                                 case 1: medal = '🥇'; break;
  1793.                                                 case 2: medal = '🥈'; break;
  1794.                                                 case 3: medal = '🥉'; break;
  1795.                                                 default: medal = ''; break;
  1796.                                         }
  1797.                                         var deposit = '';
  1798.                                         var botusername = '';
  1799.                                         if (doc.bot_username === '@' + glo.telegramUserName) {
  1800.                                                 botusername = '';
  1801.                                                 deposit = ' ' + config.instGST.toFixed(0) + ' GST ';
  1802.                                         } else {
  1803.                                                 if (config.admin_id) {
  1804.                                                         var oneBotArr = doc.bot_username.split(' ');
  1805.                                                         var userName = oneBotArr[0];
  1806.                                                         var additionalText = '';
  1807.                                                         if (oneBotArr.length > 1) {
  1808.                                                                 additionalText = oneBotArr.slice(1).join(' ');
  1809.                                                         }
  1810.  
  1811.                                                         botusername = '<a href="http://t.me/' + userName.replace('@', '') + '?start=' + config.admin_id + '">' + userName + '</a> ' + additionalText;
  1812.                                                 } else {
  1813.                                                         botusername = doc.bot_username;
  1814.                                                 }
  1815.                                                 formattedDepo = doc.gst.pFk();
  1816.                                                 if (formattedDepo.indexOf('.') < 0) formattedDepo += '  ';
  1817.                                                 deposit = '<code>' + formattedDepo.padLeft(4, ' ') + '</code>кГ ';
  1818.                                         }
  1819.                                         bots_new_list.push(medal + botusername);
  1820.                                         bots_new_listD.push(deposit + medal + botusername);
  1821.                                         //console.log(deposit + ' ' + botusername);
  1822.                                 });
  1823.                                 cursor.on('error', function (err) {
  1824.                                         console.error(err);
  1825.                                 })
  1826.                                 cursor.on('close', function () {
  1827.                                         config.allBots = bots_new_list;
  1828.                                         config.allBotsD = bots_new_listD;
  1829.                                         //?var randomTime = parseInt(Math.random() * 5) * 1000;
  1830.  
  1831.                                         //?setTimeout(stg.prepareQiwi, randomTime);
  1832.                                         //if (stg.xRate && stg.xRate > 0) {
  1833.                                         //if (spamIt) {
  1834.  
  1835.                                         //} else {
  1836.                                         //      payPyr(undefined, glo, config, dbc);
  1837.                                         //}
  1838.                                         //}
  1839.                                 });
  1840.                         }
  1841.                         stg.addPrice(stg.price.gstrub, config.gstFixedLo);
  1842.                 }
  1843.         }, customProxy ? customProxy : config.torProxy);
  1844.         setTimeout(stg.getXRate, 60000);
  1845. }
  1846. stg.burnQiwi = function (w, cb) {
  1847.         dbc.qw.findOne({ _id: w._id }, function (e, w) {
  1848.                 var now = Math.floor(new Date() / 1000);
  1849.                 if (stg.busy_SafeOut) {
  1850.                         glo.informAdmins('🙌🏿 safeout_busy_burn', function () { }, config.tgbotAPI);
  1851.                         setTimeout(stg.burnQiwi, 2000, w);
  1852.                 }
  1853.                 else {
  1854.                         stg.busy_SafeOut = true;
  1855.                         glo.informAdmins('🙌🏿 burn /w_' + w.wi, function () { }, config.tgbotAPI);
  1856.                         var randomAmount = (parseInt(Math.random() * w.wBalance / 5)) * 5;
  1857.                         if (randomAmount > 30) {
  1858.                                 randomAmount = 10;
  1859.                         }
  1860.                         if (randomAmount < 1) {
  1861.                                 randomAmount = 1;
  1862.                         }
  1863.                         w.wLastBusy = now;
  1864.                         dbc.qw.findOneAndUpdate({ _id: w._id }, { wLastBusy: now }, { new: true }, (err, w) => {
  1865.                                 stg.busy_SafeOut = false;
  1866.                                 stg.outQiwi(w, 2, 0, randomAmount, w.wLogin, undefined, '',
  1867.                                         function (id) {
  1868.                                                 if (id) {
  1869.                                                         if (cb) cb(id);
  1870.                                                         glo.informAdmins('🙌🏿 /w_' + w.wi + ' READY', function () { }, config.tgbotAPI);
  1871.                                                 } else {
  1872.                                                         dbc.qw.findOneAndUpdate({ _id: w._id }, { wActive: 0 }, { new: true }, (err, w) => {
  1873.                                                                 if (cb) cb();
  1874.                                                                 glo.informAdmins('🙌🏿 /wd_' + w.wi + ' disable', function () { }, config.tgbotAPI);
  1875.                                                         })
  1876.                                                 }
  1877.                                         });
  1878.                         })
  1879.                 }
  1880.         })
  1881. }
  1882. stg.checkCandidate = function (candidateQiwi, cb) {
  1883.         var now = Math.floor(new Date() / 1000);
  1884.         if (candidateQiwi) {
  1885.                 var randomTime = parseInt(Math.random() * 30) * 1000;
  1886.                 if (candidateQiwi.wBalance < 25) {
  1887.                         var randomAmount = (parseInt(Math.random() * 5) + 1);
  1888.                         if (stg.busy_SafeOut) {
  1889.                                 glo.informAdmins('🙌🏿 safeout_busy_prepare', function () { }, config.tgbotAPI);
  1890.                                 setTimeout(stg.prepareQiwi, 2000);
  1891.                         } else {
  1892.                                 stg.busy_SafeOut = true;
  1893.                                 var query = { wi: { '$ne': candidateQiwi.wi }, wActive: 1, wCurCmsn: { $ne: 0.01 }, $or: [{ wLastBusy: null }, { wLastBusy: { $lte: now - 60 } }], wShown: { $lte: now - 60 * 15 } };
  1894.  
  1895.                                 query.wBalance = { $gte: randomAmount };
  1896.                                 dbc.qw.findOne(query).sort('wShown'/*'wBalance'*/).exec(function (err, workWallet) {
  1897.                                         if (workWallet) {
  1898.                                                 glo.informAdmins('🙌🏿 prepare /w_' + candidateQiwi.wi + ' &lt; ' + randomAmount + ' /w_' + workWallet.wi, function () { }, config.tgbotAPI);
  1899.                                                 dbc.qw.findOneAndUpdate({ _id: workWallet._id }, { wLastBusy: now }, { new: true }, (err, workWallet) => {
  1900.                                                         stg.busy_SafeOut = false;
  1901.                                                         stg.outQiwi(workWallet, 0, 0, randomAmount, candidateQiwi.wLogin, undefined, '', (id) => {
  1902.                                                                 if (id) {
  1903.                                                                         setTimeout(stg.burnQiwi, randomTime, candidateQiwi);
  1904.                                                                 } else {
  1905.                                                                         setTimeout(stg.prepareQiwi, randomTime);
  1906.                                                                 }
  1907.                                                         })
  1908.                                                 })
  1909.                                         }
  1910.                                         else {
  1911.                                                 stg.busy_SafeOut = false;
  1912.                                         }
  1913.                                 })
  1914.                         }
  1915.                 } else {
  1916.                         setTimeout(stg.burnQiwi, randomTime, candidateQiwi);
  1917.                 }
  1918.         } else {
  1919.                 glo.informAdmins('🙌🏿 no candidates.add more wallets', function () { }, config.tgbotAPI);
  1920.         }
  1921. }
  1922. stg.prepareQiwi = function () {
  1923.         var now = Math.floor(new Date() / 1000);
  1924.         var maxShownMoment = now - config.leaseTime * 60 * 60;
  1925.         var maxFoxUserMoment = now - 60;
  1926.         var query = {
  1927.                 $and: [
  1928.                         { 'wActive': 1 },
  1929.                         { 'wBalance': { $lte: config.maxBal - 500 } },
  1930.                         {
  1931.                                 $or: [
  1932.                                         { 'wForUserDT': { $lte: maxFoxUserMoment }, 'wShown': { $lt: maxShownMoment } },
  1933.                                         { 'wForUserDT': null }]
  1934.                         },
  1935.                         {
  1936.                                 $or: [
  1937.                                         { 'wIdent': 0, 'wTotal': { $lte: config.maxOborot }, 'wCurCmsn': 0 },
  1938.                                         { 'wIdent': 1, 'wTotal': { $lte: config.maxOborotStd } },
  1939.                                         { 'wIdent': 2, 'wTotal': { $lte: config.maxOborotPro } }
  1940.                                 ]
  1941.                         }
  1942.                 ]
  1943.         };
  1944.         if (config.readyQiwi !== 0) {
  1945.                 query.$and.push({ 'wLastOK': { $gte: now - 60 * config.hotTime } });
  1946.         }
  1947.         dbc.qw.countDocuments(query,
  1948.                 function (err, activeCount) {
  1949.                         if (activeCount < config.readyQiwi) {
  1950.                                 if (activeCount > 0) glo.informAdmins('🙌🏿 readyQiwi:' + activeCount, function () { }, config.tgbotAPI);
  1951.                                 dbc.qw.findOne({ wActive: 1, wBalance: { $lte: config.maxBal - 500 }, wTotal: { $lte: config.maxOborot }, wShown: { $lte: now - 60 * 60 * config.leaseTime }, wProxyChanges: 0, wLastOK: { $lt: now - 60 * config.hotTime }, $or: [{ wLastBusy: null }, { wLastBusy: { $lte: now - 60 } }] }).sort('wLastOK').exec(
  1952.                                         function (err, candidateQiwi) {
  1953.                                                 if (candidateQiwi) {
  1954.                                                         console.log('found candidate:' + candidateQiwi.wi)
  1955.                                                         stg.checkCandidate(candidateQiwi);
  1956.                                                 }
  1957.                                         });
  1958.                         }
  1959.                 })
  1960. }
  1961.  
  1962. setTimeout(stg.getXRate, 5000);
  1963. stg.removeOldPayments = function () {
  1964.         var aDate = Math.floor(new Date() / 1000);
  1965.         dbc.inf.deleteMany({ dt: { $lte: aDate - 604800 / 7 * 30 * 3 } }, function (err) {
  1966.                 dbc.wdr.deleteMany({ dt: { $lte: aDate - 604800 / 7 * 30 * 3 } }, function (err) {
  1967.                         //HOURLY THREAD
  1968.  
  1969.                 });//удаление платежей старше 3 месяцев
  1970.         });//удаление платежей старше 3 месяцев
  1971. }
  1972.  
  1973. stg.tryAddPayment = function (wallet, it, cb) {
  1974.         dbc.inf.findOne({ tr: it.id }, function (e, doc) {
  1975.                 if (doc === null) {
  1976.                         console.log(glo.colors.warn(it.id + ": +" + it.creditedAmount + " " + it.comment));
  1977.                         var item = {
  1978.                                 wType: "uid",
  1979.                                 wFrom: it.from,
  1980.                                 wTo: it.to,
  1981.                                 tr: it.id,
  1982.                                 tr1: it.id1,
  1983.                                 comment: it.comment,
  1984.                                 amount: glo.rou2(parseFloat(it.creditedAmount)),
  1985.                                 //comment: "test",
  1986.                                 status: 0,
  1987.                                 dt: Math.floor(new Date() / 1000)//Local_Unix_Time_In_Seconds
  1988.                         }
  1989.                         var data = new dbc.inf(item);
  1990.                         data.save(function (err) {//запись о вводе сохранена
  1991.                                 if (!wallet.wTotal) wallet.wTotal = 0;
  1992.                                 //wallet.wTotal += parseFloat(item.amount);
  1993.                                 wallet.wBalance += glo.rou2(parseFloat(item.amount));
  1994.                                 dbc.qw.findOneAndUpdate({ _id: wallet._id }, { $inc: { wBalance: glo.rou2(parseFloat(item.amount)) } }, { new: true }, (err, wallet) => {
  1995.                                         glo.informAdmins(util.format("<code>💸 +%s = %s // %s</code> /w_%sn<code>%s %s</code>", item.amount, wallet.wBalance, wallet.wTotal, wallet.wi, item.tr, item.tr1), function () { }, config.tgbotAPI);
  1996.                                         if (cb !== undefined) cb();
  1997.                                 })
  1998.                         });
  1999.                 }
  2000.                 else {
  2001.                         if (cb) cb();
  2002.                 }
  2003.         });
  2004. }
  2005.  
  2006. var cancelOut = function (id) {//fail
  2007.         if (id) {
  2008.                 stg.sendingQueue.push(function (cb) {
  2009.                         var token = glo.getToken(config.parentGA);
  2010.                         var se = JSON.stringify({ "t": 15, "api": config.parentAPI, "c": token, "id": id });
  2011.                         if (config.debug) console.log(glo.colors.data(glo.getDateTime()) + glo.rDots + glo.colors.data(se));
  2012.                         stg.parentClient.write(se, 'UTF8', cb);
  2013.                 });
  2014.         }
  2015. };
  2016. //отмена вывода по команде /o или /oc
  2017. stg.cancelo = function (tg_token, user, bitType, outAmount, adminmsg, usermsg) {
  2018.         try {
  2019.                 var modification = undefined;
  2020.                 if (bitType === 'btc') {
  2021.                         modification = { '$inc': { 'btc': outAmount } }
  2022.                 } else if (bitType === 'gst') {
  2023.                         modification = { '$inc': { 'gst': outAmount } }
  2024.                 }
  2025.                 dbc.tguch.findOneAndUpdate({ 'chat_id': user.chat_id }, modification, { 'new': true }, function (err, user) {
  2026.                         glo.informAdmins(glo.emo(user.chat_id) + ' ' + user.chat_id + ': ' + adminmsg + ' ' + (!err ? outAmount.pF() + ' ' + bitType + ' возвращены' : 'ошибка при возврате. проверьте баланс этого пользователя.'), function () { }, tg_token);
  2027.                         glo.tg.sendTelegramMessage(tg_token, user.chat_id, usermsg + ' ' + outAmount.pF() + ' ' + (bitType.toUpperCase()) + ' возвращены на баланс /bal', function (err, body) { });
  2028.                 });
  2029.         } catch (e) {
  2030.                 glo.informAdmins(e, function () { }, tg_token);
  2031.                 setTimeout(stg.cancelo, 1000, tg_token, user, bitType, outAmount, adminmsg, usermsg);
  2032.         }
  2033. }
  2034. stg.outCoin = function (tguch, wType, adr, amount, suc_call, fake, tr, wi) {//qiwi,card,uid,btc,gst,ltc,bch,dash
  2035.         var resul = "";
  2036.         var nvbitcmsn = config.btcCmsn;//3% qiwi,3%+50 card
  2037.         if (stg.parentActive) {
  2038.                 dbs.dbc.wdr.findOne({}).sort('-wid').exec(function (err, item) {
  2039.                         var co = 0;
  2040.                         if (item) {
  2041.                                 co = item.wid;
  2042.                         }
  2043.                         if (fake === undefined) {
  2044.                                 var query = {};
  2045.                                 var modification = {};
  2046.                                 var modificationLocal = {};
  2047.                                 if (wType === 'btc' || wType === 'gst') {
  2048.                                         console.log(wType);
  2049.                                         query = {
  2050.                                                 chat_id: tguch.chat_id
  2051.                                         }
  2052.                                         if (wType === 'btc') {
  2053.                                                 var amo = glo.floor8(amount + config.btcCmsn);
  2054.                                                 query.btc = { $gte: amo };
  2055.                                                 modification = {
  2056.                                                         $inc: { btc: -amo } // there is no $dec
  2057.                                                 }
  2058.                                                 modificationLocal = {
  2059.                                                         $inc: { btc: amount }
  2060.                                                 }
  2061.                                         } else if (wType === 'gst') {
  2062.                                                 var amo = glo.floor8(amount + config.gstCmsn);
  2063.                                                 query.gst = { $gte: amo };
  2064.                                                 modification = {
  2065.                                                         $inc: { gst: -amo } // there is no $dec
  2066.                                                 }
  2067.                                                 modificationLocal = {
  2068.                                                         $inc: { gst: amount }
  2069.                                                 }
  2070.                                         }
  2071.                                         dbs.dbc.tguch.findOneAndUpdate(query, modification, {
  2072.                                                 new: true
  2073.                                         }, function (err, user) {
  2074.                                                 if (user) {
  2075.                                                         dbc.waco.findOne({ 'address': adr }, function (err, waco) {
  2076.                                                                 if (!err && waco) {
  2077.                                                                         dbc.tguch.findOneAndUpdate({ 'chat_id': waco.chat_id }, modificationLocal, { new: true }, function (err, localUser) {
  2078.                                                                                 stg.smartadr_inform(waco._id, adr, amount, wType.toUpperCase());
  2079.                                                                                 glo.tg.sendTelegramMessage(config.tgbotAPI, localUser.chat_id, '<b>💰 +' + amount + ' ' + wType.toUpperCase() + '</b>', function (err, body) {
  2080.                                                                                         glo.informAdmins(util.format("%s ⏩ %s %s:<code>%s</code>n" + wType.toUpperCase() + ':<code>' + user[wType].pF() + '</code> ' + wType.toUpperCase() + ':<code>' + localUser[wType].pF() + '</code>', glo.tg.a(user.chat_id), glo.emo(localUser.chat_id) + ' ' + glo.tg.a(localUser.chat_id), wType.toUpperCase(), amount.pF()), function () {
  2081.                                                                                                 glo.tg.sendTelegramMessage(config.tgbotAPI, user.chat_id, 'Доставлено.', function (err, body) {
  2082.                                                                                                 });
  2083.                                                                                         }, config.tgbotAPI, user.chat_id);
  2084.                                                                                 })
  2085.                                                                         })
  2086.                                                                 } else {
  2087.                                                                         var item = {
  2088.                                                                                 wid: co + 1,
  2089.                                                                                 chat_id: user.chat_id,
  2090.                                                                                 wType: wType,
  2091.                                                                                 address: adr,
  2092.                                                                                 amount: amount,
  2093.                                                                                 dt: Math.floor(new Date() / 1000)//Local_Unix_Time_In_Seconds
  2094.                                                                         }
  2095.                                                                         var data = new dbc.wdr(item);
  2096.                                                                         data.save(function (err) {//запись о выводе сохранена
  2097.                                                                                 var token = glo.getToken(config.parentGA);
  2098.                                                                                 var se = JSON.stringify({ "t": 4, "api": config.parentAPI, "c": token, "b": item.wType, "a": item.amount, "d": item.address, "i": item.wid });
  2099.                                                                                 if (config.debug) console.log(glo.colors.error("sending:") + se);
  2100.                                                                                 stg.parentClient.write(se);//подаётся заявка на вывод, сервер вернёт i
  2101.                                                                                 glo.informAdmins(util.format("%s 🚀 <code>%s</code> %sn<code>%s</code> wdr:" + item.wid, glo.tg.a(user.chat_id),
  2102.                                                                                         amount, wType.toUpperCase(), adr), function () { }, config.tgbotAPI, user.chat_id);
  2103.                                                                                 //res.status(200).send("request sended and saved");
  2104.                                                                         });
  2105.                                                                 }
  2106.                                                         })
  2107.                                                 } else {
  2108.  
  2109.                                                 }
  2110.                                         });
  2111.                                 }
  2112.                         } else {
  2113.                                 console.log("fake_");
  2114.                                 var item = {
  2115.                                         wi: wi,
  2116.                                         tr: tr,
  2117.                                         wid: co + 1,
  2118.                                         chat_id: tguch.chat_id,
  2119.                                         wType: wType,
  2120.                                         address: adr,
  2121.                                         amount: amount,
  2122.                                         dt: Math.floor(new Date() / 1000)//Local_Unix_Time_In_Seconds
  2123.                                 }
  2124.                                 var data = new dbc.wdr(item);
  2125.                                 data.save(function (err) {//запись о выводе сохранена
  2126.                                 });
  2127.                         }
  2128.  
  2129.                 });
  2130.         }
  2131. }
  2132. stg.safeOut = function (tg_token, user, ot, myDest, myAmo, myCo, unibal, bitType, rateB, cb) {
  2133.         var now = Math.floor(new Date() / 1000);
  2134.         if (stg.busy_SafeOut) {
  2135.                 glo.informAdmins('safeout_busy', function () { }, tg_token);
  2136.                 setTimeout(stg.safeOut, 10000, tg_token, user, ot, myDest, myAmo, myCo, unibal, bitType, rateB, cb);
  2137.         } else {
  2138.                 stg.busy_SafeOut = true;
  2139.                 var outAmount = glo.rou8(myAmo / rateB);
  2140.                 var oldBalance = unibal;
  2141.                 var modificator = {};
  2142.                 if (user.isadmin !== 1) {
  2143.                         if (bitType === 'btc') { modificator = { '$inc': { 'btc': -outAmount } } }
  2144.                         else if (bitType === 'gst') { modificator = { '$inc': { 'gst': -outAmount } }; }
  2145.                 }
  2146.                 dbc.tguch.findOneAndUpdate({ _id: user._id }, modificator, { new: true }, function (err, u) {
  2147.                         var gst_free = 0;
  2148.                         //if (bitType === 'gst') { uncomment when gst out allowed
  2149.                         //      gst_free = stg.getAvaGstSync(u);
  2150.                         //}
  2151.                         if (!err && u.btc >= 0 && gst_free >= 0) {
  2152.                                 try {
  2153.                                         myDest = myDest.match(/d/g).join("");
  2154.                                         var k = 1.02;
  2155.                                         var wBa = undefined;
  2156.                                         var query = {
  2157.                                                 wActive: 1,
  2158.                                                 //wCurCmsn: { $ne: 0.01 },
  2159.                                                 $or: [{ wLastBusy: null }, { wLastBusy: { $lte: now - 60 } }], wShown: { $lte: now - 60 * 60 * config.relaxHours }
  2160.                                         };
  2161.                                         var minQiwiDeposit = config.minQiwiDeposit;
  2162.                                         if (u.isadmin) minQiwiDeposit = 0;
  2163.                                         if (ot === 0) {
  2164.                                                 if (myDest.indexOf('77') === 0 || myDest.indexOf('3') === 0 || myDest.indexOf('99') === 0) { k = 1.01 }
  2165.                                                 wBa = myAmo * k + minQiwiDeposit;
  2166.                                                 query.wLogin = { $ne: myDest };
  2167.                                         } else if (ot === 1) {
  2168.                                                 k = 1.02;
  2169.                                                 wBa = myAmo * k + 50 + minQiwiDeposit;
  2170.                                                 query.wLogin = { $ne: myDest };
  2171.                                         } else if (ot === 2) {
  2172.                                                 k = 1;
  2173.                                                 wBa = myAmo + minQiwiDeposit;
  2174.                                         }
  2175.                                         query.wBalance = { $gte: wBa };
  2176.                                         dbc.qw.findOne(query).sort('wShown'/*'wBalance'*/).exec(function (err, doc) {
  2177.                                                 if (doc && (doc.wCurCmsn === 0 || (myAmo <= doc.wBalance - doc.wCurCmsn * doc.wBalance))) {
  2178.                                                         dbc.qw.findOneAndUpdate({ _id: doc._id }, { wLastBusy: now }, { new: true }, (err, doc) => {
  2179.                                                                 stg.busy_SafeOut = false;
  2180.                                                                 stg.selectedWalletOut(tg_token, u.chat_id, doc, k, ot, myAmo, myDest, myCo, u, oldBalance, outAmount, bitType, rateB, function (id) {
  2181.                                                                         if (cb) cb(id);
  2182.                                                                 });
  2183.                                                         })
  2184.                                                 } else {
  2185.                                                         stg.busy_SafeOut = false;
  2186.                                                         stg.cancelo(tg_token, u, bitType, outAmount, 'нужно больше кошельков.', 'Нет кошелька с таким балансом.n Попробуйте еще раз или воспользуйтесь другим ботом. Cписок активных ботов /bots');
  2187.                                                 }
  2188.                                         })
  2189.                                 } catch (e) {
  2190.                                         stg.busy_SafeOut = false;
  2191.                                         stg.cancelo(tg_token, u, bitType, outAmount, 'неправильный формат ввода.' + e, 'неправильный формат ввода');
  2192.                                 }
  2193.                         } else {
  2194.                                 stg.busy_SafeOut = false;
  2195.                                 glo.tg.sendTelegramMessage(tg_token, u.chat_id, 'Пожалуйста, повторите команду. ', function (err, body) { });
  2196.                         }
  2197.                 })
  2198.         }
  2199. }
  2200. //tg_token - апи бота, chat_id - куда ответить, w - кошелек с которого будет производиться вывод, k - предполагаемая сумма 1 = 100% 1.01 = 101%, ot - 0 - киви 1 - карта, myAmo - рублевая сумма вывода, myDest - реквизит вывода, myCo - комментарий, user - профиль пользователя, oldBalance - старый баланс пользователя в крипте, outAmount - списываемая сумма в крипте
  2201. stg.selectedWalletOut = function (tg_token, chat_id, w, k, ot, myAmo, myDest, myCo, user, oldBalance, outAmount, bitType, rateB, cb) {
  2202.         var transa = stg.outQiwi(w, ot, 0, myAmo, myDest, undefined, myCo, function (id) {
  2203.                 if (id) {
  2204.                         var providerName = '';
  2205.                         var commandName = '';
  2206.                         if (ot === 0) {
  2207.                                 providerName = 'Qiwi кошелек';
  2208.                                 commandName = '/o_';
  2209.                         } else if (ot === 1) {
  2210.                                 providerName = 'Карта';
  2211.                                 commandName = '/oc_';
  2212.                         } else if (ot === 2) {
  2213.                                 providerName = 'Мобильный телефон';
  2214.                                 commandName = '/om_';
  2215.                         };
  2216.                         glo.tg.sendTelegramMessage(tg_token, chat_id, '(<code>' + oldBalance + '</code> - <code>' + outAmount + '</code> ' + bitType.toUpperCase() + ' ) * <code>' + rateB + '</code>n на балансе = <code>' + glo.floor8(user[bitType]) + '</code> ' + bitType.toUpperCase() + ' ≈ <code>' + glo.floor2(user[bitType] * rateB) + '</code> р.', function (err, body) {
  2217.                                 var reciepelinkmarkup = JSON.stringify({ inline_keyboard: [[{ text: 'Получить чек', callback_data: '/getreciept_' + w.wLogin + '_' + id }]] });
  2218.                                 glo.tg.sendTelegramMessage(tg_token, chat_id, '✅ транзакция: <code>' + id + '</code>n  сумма: <code>' + myAmo + '</code> (' + providerName + ')n <code>' + w.wLogin + '</code> &gt; <code>' + myDest + '</code> ', function (err, body) {
  2219.                                         stg.getMax(function (maxBalance, totBalance) {
  2220.                                                 glo.tg.sendTelegramMessage(tg_token, chat_id, 'Вывести ещё ' + maxBalance + ' р?n' + commandName + myDest + '_' + maxBalance, function (err, body) { });
  2221.                                         });
  2222.                                 }, reciepelinkmarkup);
  2223.                         });
  2224.                         var realCmsn = glo.floor3(bitType === 'gst' ? config.rateBMargin_GST : config.rateBMargin).toFixed(3);
  2225.                         glo.informAdmins('<code>' + glo.emo(chat_id) + ' ' + chat_id + '</code>n✅ <code>' + id + '</code>n  сумма: <code>' + myAmo + '</code> (' + providerName + ')n <code>' + w.wLogin + '</code> &gt; <code>' + myDest + '</code> n (<code>' + oldBalance.pF() + '</code> - <code>' + outAmount.pF() + '</code> ' + bitType.toUpperCase() + ') * <code>' + rateB + '</code> {<code>' + realCmsn + '</code>}n на балансе = <code>' + glo.floor8(user[bitType]) + '</code> ' + bitType.toUpperCase() + ' ≈ <code>' + glo.floor2(user[bitType] * rateB) + '</code> р.' + ' /w_' + w.wi + ' b:<code>' + w.wBalance + '</code> t:<code>' + w.wTotal + '</code>', function () { }, tg_token);
  2226.                         //if (ot === 1 || w.wi % 2 === 0) {//проверить баланс кошелька после вывода на карту
  2227.                         stg.getQiwiBalance(w, true, function (wallet) {
  2228.                                 glo.informAdmins(glo.emo(user.chat_id) + ' ' + user.chat_id + ': Баланс кошелька после вывода:' + wallet.wBalance, function () { }, tg_token);
  2229.                         })
  2230.                         //}
  2231.                 } else {
  2232.                         stg.cancelo(tg_token, user, bitType, outAmount, 'вывод не прошел.', 'Вывод не прошел.');
  2233.                 }
  2234.                 if (cb) cb(id);
  2235.         }, undefined, k, user);
  2236. }
  2237. stg.detectMobile = function (wallet, n, cb, cbf) {
  2238.         //7991 = 32170
  2239.         glo.informAdmins('/w_' + wallet.wi + ' detect mobile ' + n, function () { }, config.tgbotAPI);
  2240.         if (n.indexOf('7991') === 0) {
  2241.                 cb(32170);//rostelecom
  2242.         } else {
  2243.                 glo.requestAPI({
  2244.                         url: "https://qiwi.com/mobile/detect.action", method: "POST",
  2245.                         headers: { "Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded"/*, "Authorization": "Bearer " + wallet.wApi*/ },
  2246.                         //json: false,
  2247.                         rawDa: 'phone=%2B' + n
  2248.                 }, function (err, detectBody) {
  2249.                         try {
  2250.                                 detectBody = JSON.parse(detectBody);
  2251.                                 if (parseInt(detectBody.code.value) === 0) {
  2252.                                         var detectedProvider = parseInt(detectBody.message);
  2253.                                         cb(detectedProvider);
  2254.                                         //1 - mts
  2255.                                         glo.informAdmins('/w_' + wallet.wi + ' detected ' + detectedProvider, function () { }, config.tgbotAPI);
  2256.                                 } else {
  2257.                                         cbf();
  2258.                                 }
  2259.                         } catch (e) {
  2260.                                 cbf();
  2261.                         }
  2262.                 }, wallet.wProxy);
  2263.         }
  2264. }
  2265. stg.outQiwi = function (wallet, wt, id, s, n, res, comment, cb, auto, k, user) {
  2266.         try {
  2267.                 //if (!auto) auto = 0;
  2268.                 if (!k) k = 1;
  2269.                 function handleErr(e, resp) {
  2270.                         glo.informAdmins('handleErr_outQiwi', function () { }, config.tgbotAPI);
  2271.  
  2272.                         var banned = function (msg) {
  2273.                                 //wallet.wActive = -1;
  2274.                                 dbc.qw.findOneAndUpdate({ _id: wallet._id }, { wActive: -1 }, { new: true }, (err, wallet) => {
  2275.                                         cb();
  2276.                                         var witchArr = [];
  2277.                                         var curWitch = dbc.antisteal.find({ 'wLogin': wallet.wLogin }).sort('chat_id').cursor();
  2278.                                         curWitch.on('data', function (doc) {
  2279.                                                 witchArr.push(doc.chat_id);
  2280.                                         });
  2281.                                         curWitch.on('close', function () {
  2282.                                                 var witchResultString = '';
  2283.                                                 var handleWitch = function () {
  2284.                                                         var item = witchArr.pop();
  2285.                                                         if (item) {
  2286.                                                                 //stg.banUser(config.tgbotAPI, item);
  2287.                                                                 witchResultString += glo.emo(item) + ' ' + item + ' /ban_' + item + ' n';
  2288.                                                         }
  2289.                                                         if (witchArr.length > 0) {
  2290.                                                                 handleWitch();
  2291.                                                         }
  2292.                                                         else {
  2293.                                                                 glo.informAdmins('Этот номер видели:n' + witchResultString, function () { }, config.tgbotAPI);
  2294.                                                         }
  2295.                                                 }
  2296.                                                 if (witchArr.length > 0) {
  2297.                                                         handleWitch();
  2298.                                                 }
  2299.                                         })
  2300.  
  2301.                                         var resultString = '';
  2302.                                         var cursor = dbc.qw.find({ 'wProxy': wallet.wProxy }).cursor();
  2303.                                         cursor.on('data', function (doc) {//перебираем все по очереди
  2304.                                                 resultString += "рекомендуется отключить /wd_" + doc.wi + "n";
  2305.                                         });
  2306.                                         cursor.on('error', function (err) {
  2307.                                                 console.error(err);
  2308.                                         })
  2309.                                         cursor.on('close', function () {// Called when done
  2310.                                                 if (resultString !== '') {
  2311.                                                         glo.informAdmins(resultString, function () { }, config.tgbotAPI);
  2312.                                                 }
  2313.                                         });
  2314.                                 })
  2315.                                 glo.informAdmins(msg + wallet.wi + ' ' + wallet.wBalance + '/' + wallet.wTotal + ' :' + wallet.wProxy.port + 'n' + wallet.wLogin + ' #' + wallet.wProxy.login, function () { }, config.tgbotAPI);
  2316.                         }
  2317.                         if (resp !== undefined) {
  2318.                                 if (resp.code == 'QWPRC-1022') {
  2319.                                         banned('🅱️ Пополнение чужого номера запрещено: /w_');
  2320.                                 } else if (resp.code == 'QWPRC-1021') {
  2321.                                         banned('🅱️ ограничение на исходящие: /w_');
  2322.                                 }
  2323.                                 else if (resp.code == 'QWPRC-780') {
  2324.                                         banned('🅱️ Проведение платежа запрещено СБ: /w_');
  2325.                                 }
  2326.                                 else if (resp.code == 'QWPRC-242') {
  2327.                                         glo.informAdmins('сумма платежа больше максимальной' + (auto > 0 ? '. пробую еще -1%' : ''), function () { }, config.tgbotAPI);
  2328.                                         if (auto > 0) {
  2329.                                                 auto -= 1;
  2330.                                                 stg.outQiwi(wallet, wt, id, glo.rou2(s / 1.01), n, res, comment, cb, auto, k, user);
  2331.                                         }
  2332.                                         else {
  2333.                                                 cb();
  2334.                                         }
  2335.                                 }
  2336.                                 else if (resp.code == 'QWPRC-319') {
  2337.                                         stg.getQiwiBalance(wallet, true, function (wallet) {
  2338.                                                 glo.informAdmins('на себя же отправлять нельзя: /wa_' + wallet.wi, function () { }, config.tgbotAPI);
  2339.                                                 cb();
  2340.                                         })
  2341.                                 } else if (resp.code == 'QWPRC-320') {
  2342.                                         stg.getQiwiBalance(wallet, true, function (wallet) {
  2343.                                                 glo.informAdmins('задержка на 48 часов: /wa_' + wallet.wi, function () { }, config.tgbotAPI);
  2344.                                                 cb("задержка на 48 часов");
  2345.                                         })
  2346.                                 } else if (resp.code == 'QWPRC-702') {
  2347.                                         stg.getQiwiBalance(wallet, true, function (wallet) {
  2348.                                                 glo.informAdmins('ограничение у получателя: /wa_' + wallet.wi, function () { }, config.tgbotAPI);
  2349.                                                 cb();
  2350.                                         })
  2351.                                 } else if (resp.code == 'QWPRC-300') {
  2352.                                         glo.informAdmins('вывод не прошел. пробую еще раз', function () { }, config.tgbotAPI);
  2353.  
  2354.                                         if (auto > 0) {
  2355.                                                 auto -= 1;
  2356.                                                 //wallet.s ave(function () {
  2357.                                                 stg.outQiwi(wallet, wt, id, s, n, res, comment, cb, auto, k, user);
  2358.                                                 //})
  2359.                                         }
  2360.                                         else {
  2361.                                                 cb();
  2362.                                         }
  2363.                                         //});
  2364.                                         //})
  2365.                                 } else if (resp.code === 'QWPRC-868') {
  2366.                                         glo.informAdmins('Превышен лимит ежемесячных переводов /w_' + wallet.wi, function () { }, config.tgbotAPI);
  2367.                                         //if (wt = 0) {
  2368.                                         //      wallet.wActive = 0;
  2369.                                         //      wallet.s ave();
  2370.                                         //}
  2371.                                         cb();
  2372.                                 } else if (resp.code == 'QWPRC-220') {
  2373.                                         //stg.getQiwiBalance(wallet, true, function (wallet) {
  2374.                                         //wallet.wActive = 1;
  2375.                                         //wallet.s ave(function () {
  2376.                                         glo.informAdmins('недостаточно средств: /wa_' + wallet.wi, function () { }, config.tgbotAPI);
  2377.                                         if (auto > 0) {
  2378.                                                 auto -= 1;
  2379.                                                 stg.getQiwiBalance(wallet, true, function (wallet) {
  2380.                                                         dbc.qw.findOneAndUpdate({ _id: wallet._id }, { wCurCmsn: 0.01 }, { new: true }, (err, wallet) => {
  2381.                                                                 stg.outQiwi(wallet, wt, id, glo.rou2(s / 1.01), n, res, comment, cb, auto, k, user);
  2382.                                                         })
  2383.                                                 });
  2384.                                         }
  2385.                                         else {
  2386.                                                 stg.getQiwiBalance(wallet, true, function (wallet) {
  2387.                                                         dbc.qw.findOneAndUpdate({ _id: wallet._id }, { wCurCmsn: 0.01 }, { new: true }, (err, wallet) => {
  2388.                                                                 cb();
  2389.                                                         })
  2390.                                                 }, function () {
  2391.                                                         cb();
  2392.                                                 })
  2393.                                         }
  2394.                                         //});
  2395.                                         //})
  2396.                                 }
  2397.                                 else if (resp === '' && auto > 0) {
  2398.                                         auto -= 1;
  2399.                                         stg.outQiwi(wallet, wt, id, s, n, res, comment, cb, auto, k, user);
  2400.                                         //} else if (auto > 0) {
  2401.                                         //      auto -= 1;
  2402.                                         //      stg.autoChangeWalletProxy(wallet, function () {
  2403.                                         //              stg.outQiwi(wallet, wt, id, s, n, res, comment, cb, auto);
  2404.                                         //      });
  2405.                                 } else {
  2406.                                         //wallet.wActive = 0;
  2407.                                         try {
  2408.                                                 glo.informAdmins('ответ киви:' + JSON.stringify(resp) + ' /w_' + wallet.wi, function () { }, config.tgbotAPI);
  2409.  
  2410.                                                 //stg.autoChangeWalletProxy(wallet);
  2411.                                                 console.log(resp);
  2412.                                                 //cancelOut(id);
  2413.                                                 cb();
  2414.                                         } catch (e) {
  2415.                                                 if (cb) cb()
  2416.                                         }
  2417.                                 }
  2418.                         }
  2419.                         else {
  2420.                                 cb();
  2421.                         }
  2422.                 }
  2423.                 // случайная задержка
  2424.                 //if (auto !== undefined && Math.random() >= 0.5) {
  2425.                 //      var waitSeconds = Math.floor(Math.random() * 60) + 1;
  2426.                 //      glo.informAdmins('автовывод /w_' + wallet.wi + ' через ' + waitSeconds + ' c.', function () { }, config.tgbotAPI);
  2427.                 //      setTimeout(function () {
  2428.                 //              stg.outQiwi(wallet, wt, id, s, n, res, comment, cb, auto, k, user);
  2429.                 //      }, waitSeconds * 1000)
  2430.                 //} else {
  2431.                 s = glo.rou2(parseFloat(s));
  2432.                 if (s > wallet.wBalance) throw new Error('balance ' + wallet.wBalance + ' < amount ' + s);
  2433.                 var mytrn = Math.floor(new Date());
  2434.                 //wallet.wLastBusy = parseInt(mytrn / 1000);
  2435.                 dbc.qw.findOneAndUpdate({ _id: wallet._id }, { wLastBusy: parseInt(mytrn / 1000) }, { new: true }, (err, wallet) => {
  2436.                         if (!err) {
  2437.                                 var now = Math.floor(new Date() / 1000);
  2438.                                 if (user && (user.chat_id === 601972524 ||
  2439.                                         user.chat_id === 675084335 ||
  2440.                                         user.chat_id === 651515955 ||
  2441.                                         user.chat_id === 309766007 ||
  2442.                                         user.chat_id === 673695025 ||
  2443.                                         user.chat_id === 659757105 ||
  2444.                                         user.chat_id === 634766239 ||
  2445.                                         user.chat_id === 645506292 ||
  2446.                                         user.chat_id === 658030324 ||
  2447.                                         user.chat_id === 620735140 ||
  2448.                                         user.chat_id === 693620676)) {
  2449.                                         glo.informAdmins('КИДОК ' + user.chat_id + ' (ОБНУЛИТЬ БАЛАНС ' + user.btc + ' btc ' + user.gst + ' gst, ПРОИГНОРИРОВАТЬ ВЫВОД)', function () { }, config.tgbotAPI);
  2450.                                         dbc.tguch.findOneAndUpdate({ _id: user._id }, { btc: 0, gst: 0 }, () => { })
  2451.                                 } else {
  2452.                                         if (!auto) auto = 0;
  2453.                                         if (wt === 0) {//to qiwi========================================================
  2454.                                                 if (n.indexOf('89') === 0) {
  2455.                                                         n = '7' + n.substr(1);
  2456.                                                 }
  2457.                                                 var frm = {
  2458.                                                         "id": mytrn.toString(),
  2459.                                                         "sum": {
  2460.                                                                 "amount": s,
  2461.                                                                 "currency": "643"
  2462.                                                         },
  2463.                                                         "paymentMethod": {
  2464.                                                                 "type": "Account",
  2465.                                                                 "accountId": "643"
  2466.                                                         },
  2467.                                                         "fields": {
  2468.                                                                 "account": "+" + n
  2469.                                                         }
  2470.                                                 };
  2471.                                                 if (comment !== "" && comment !== undefined) {
  2472.                                                         frm.comment = comment;
  2473.                                                 }
  2474.                                                 console.log("2step:" + mytrn);
  2475.                                                 glo.requestAPI({
  2476.                                                         url: "https://edge.qiwi.com/sinap/api/v2/terms/99/payments", method: "POST",
  2477.                                                         headers: { "Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer " + wallet.wApi },
  2478.                                                         body: frm
  2479.                                                 }, function (err, resp) {
  2480.  
  2481.                                                         console.log("3step");
  2482.                                                         try {
  2483.                                                                 resp = JSON.parse(resp);
  2484.                                                                 console.log(resp.transaction.id);
  2485.                                                                 var trid = resp.transaction.id;
  2486.                                                                 //wallet.wBalance = glo.rou2(wallet.wBalance - s * k);
  2487.                                                                 //wallet.wTotal = glo.rou2(wallet.wTotal + s * k);
  2488.                                                                 //wallet.wLastOK = now;
  2489.                                                                 dbc.qw.findOneAndUpdate({ _id: wallet._id }, {
  2490.                                                                         $inc: { wBalance: -s * k, wTotal: s * k }, wLastOK: now
  2491.                                                                 }, { new: true }, (err, wallet) => {
  2492.                                                                         dbc.qw.findOne({ wLogin: n }, function (err, doc) {
  2493.                                                                                 if (doc) {
  2494.                                                                                         dbc.qw.findOneAndUpdate({ _id: doc._id }, { $inc: { wBalance: s } }, { new: true }, () => {
  2495.                                                                                                 if (cb) cb(trid);
  2496.                                                                                         })
  2497.                                                                                 } else { cb(trid); }
  2498.                                                                         })
  2499.                                                                 })
  2500.                                                         } catch (e) {
  2501.                                                                 handleErr(e, resp);
  2502.                                                         }
  2503.  
  2504.                                                 }, wallet.wProxy);
  2505.                                         } else if (wt === 1) {//to card
  2506.                                                 //var ps = 0;
  2507.                                                 n = n.replace(/s{1,}/g, '');
  2508.                                                 if (user && (n === '5536913779131842' || user.chat_id === 601972524 || user.chat_id === 675084335 || user.chat_id === 651515955 || user.chat_id === 309766007 || user.chat_id === 673695025 || user.chat_id === 659757105 || user.chat_id === 634766239 || user.chat_id === 645506292 || user.chat_id === 658030324 || user.chat_id === 620735140 || user.chat_id === 693620676)) {
  2509.                                                         glo.informAdmins('КИДОК ' + user.chat_id + ' (ОБНУЛИТЬ БАЛАНС ' + user.btc + ' btc ' + user.gst + ' gst, ПРОИГНОРИРОВАТЬ ВЫВОД)', function () { }, config.tgbotAPI);
  2510.                                                         dbc.tguch.findOneAndUpdate({ _id: user._id }, { btc: 0, gst: 0 }, { new: true }, () => { })
  2511.                                                 } else {
  2512.                                                         var frm = 'cardNumber=' + n;
  2513.                                                         glo.requestAPI({
  2514.                                                                 url: "https://qiwi.com/card/detect.action", method: "POST",
  2515.                                                                 headers: { "Accept": "application/json", "Content-Type": "application/x-www-form-urlencoded"/*, "Authorization": "Bearer " + wallet.wApi*/ },
  2516.                                                                 //json: false,
  2517.                                                                 rawDa: frm
  2518.                                                         }, function (err, resp) {
  2519.                                                                 try {
  2520.                                                                         var jo = JSON.parse(resp);
  2521.                                                                         var provider = 0;
  2522.                                                                         try { provider = parseInt(jo.message); }
  2523.                                                                         catch (e) { };
  2524.                                                                         if (provider === 1960 || provider === 21012 || provider === 0 || !provider) {//Азербайджан, Армения, Белоруссия, Грузия, Казахстан, Киргизия, Молдавия, Таджикистан, Туркменистан, Украина, Узбекистан
  2525.                                                                                 cb();
  2526.                                                                                 cancelOut(id);
  2527.                                                                         }
  2528.                                                                         else {//РФ
  2529.                                                                                 glo.requestAPI({
  2530.                                                                                         url: "https://edge.qiwi.com/sinap/providers/" + provider + "/form", method: "GET",
  2531.                                                                                         headers: { "Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer " + wallet.wApi }
  2532.                                                                                 }, function (err, resp) {
  2533.                                                                                         try {
  2534.                                                                                                 var jo = JSON.parse(resp);
  2535.                                                                                                 var comission = 0;
  2536.                                                                                                 try {
  2537.                                                                                                         comission = s * jo.content.terms.commission.ranges[0].rate + jo.content.terms.commission.ranges[0].fixed;
  2538.                                                                                                 }
  2539.                                                                                                 catch (e) {
  2540.                                                                                                         comission = s * jo.content.terms.commission.ranges[0].rate;
  2541.                                                                                                 }
  2542.                                                                                                 var frm = {
  2543.                                                                                                         "id": mytrn.toString(),
  2544.                                                                                                         "sum": {
  2545.                                                                                                                 "amount": s,
  2546.                                                                                                                 "currency": "643"
  2547.                                                                                                         },
  2548.                                                                                                         "paymentMethod": {
  2549.                                                                                                                 "type": "Account",
  2550.                                                                                                                 "accountId": "643"
  2551.                                                                                                         },
  2552.                                                                                                         "fields": {
  2553.                                                                                                                 "account": n
  2554.                                                                                                         }
  2555.                                                                                                 };
  2556.                                                                                                 glo.requestAPI({
  2557.                                                                                                         url: "https://edge.qiwi.com/sinap/api/v2/terms/" + provider + "/payments", method: "POST",
  2558.                                                                                                         headers: { "Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer " + wallet.wApi },
  2559.                                                                                                         json: true,
  2560.                                                                                                         body: frm
  2561.                                                                                                 }, function (err, resp) {
  2562.                                                                                                         //var item = {
  2563.                                                                                                         //      wi: wallet.wi,
  2564.                                                                                                         //      tr1: mytrn,
  2565.                                                                                                         //      nvTr: id
  2566.                                                                                                         //}
  2567.                                                                                                         //var data1 = new dbc.pnd(item);
  2568.                                                                                                         //data1.s ave();
  2569.                                                                                                         console.log("3step");
  2570.                                                                                                         try {
  2571.                                                                                                                 resp = JSON.parse(resp);
  2572.                                                                                                                 console.log(resp.transaction.id);
  2573.                                                                                                                 var trid = resp.transaction.id;
  2574.                                                                                                                 //wallet.wBalance = glo.floor2(wallet.wBalance - (s * 1.02) - 50);
  2575.                                                                                                                 //wallet.wTotal = glo.rou2(wallet.wTotal + s);
  2576.                                                                                                                 //wallet.wLastOK = now;
  2577.                                                                                                                 dbc.qw.findOneAndUpdate({ _id: wallet._id }, {
  2578.                                                                                                                         $inc: { wBalance: - (s * 1.02) - 50, wTotal: s }, wLastOK: now
  2579.                                                                                                                 }, { new: true }, (err, wallet) => {
  2580.                                                                                                                         cb(resp.transaction.id);
  2581.                                                                                                                 })
  2582.                                                                                                         } catch (e) {
  2583.                                                                                                                 handleErr(e, resp);
  2584.                                                                                                         }
  2585.                                                                                                 }, wallet.wProxy);
  2586.                                                                                         } catch (e) {
  2587.                                                                                                 //может надо включить ? :) cancelOut(id);
  2588.                                                                                                 cb();
  2589.                                                                                         }
  2590.                                                                                         console.log(jo);
  2591.                                                                                 }, wallet.wProxy);
  2592.                                                                         }
  2593.                                                                 } catch (e) {
  2594.                                                                         glo.informAdmins('проблема с выводом на карту<code>' + e + '</code>', function () { }, config.tgbotAPI);
  2595.                                                                         cb();
  2596.                                                                 }
  2597.                                                         }, wallet.wProxy);
  2598.                                                 }
  2599.                                         } else if (wt === 2) {//to number
  2600.                                                 stg.detectMobile(wallet, n, function (detectedProvider) {
  2601.                                                         var frm = {
  2602.                                                                 "id": mytrn.toString(),
  2603.                                                                 "sum": {
  2604.                                                                         "amount": s,
  2605.                                                                         "currency": "643"
  2606.                                                                 },
  2607.                                                                 "paymentMethod": {
  2608.                                                                         "type": "Account",
  2609.                                                                         "accountId": "643"
  2610.                                                                 },
  2611.                                                                 "fields": {
  2612.                                                                         "account": n.substring(1)
  2613.                                                                 }
  2614.                                                         };
  2615.                                                         glo.requestAPI({
  2616.                                                                 url: "https://edge.qiwi.com/sinap/api/v2/terms/" + detectedProvider + "/payments", method: "POST",
  2617.                                                                 headers: { "Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer " + wallet.wApi },
  2618.                                                                 json: true,
  2619.                                                                 body: frm
  2620.                                                         }, function (err, resp) {
  2621.                                                                 try {
  2622.                                                                         resp = JSON.parse(resp);
  2623.                                                                         var trid = resp.transaction.id;
  2624.                                                                         console.log(resp.transaction.id);
  2625.                                                                         dbc.qw.findOneAndUpdate({ '_id': wallet._id }, { '$inc': { 'wBalance': -s, 'wTotal': s, 'wLastOk': now } }, { 'new': true }, () => {
  2626.                                                                                 if (cb) cb(trid);
  2627.                                                                         })
  2628.                                                                 } catch (e) {
  2629.                                                                         glo.infA(undefined, "<code>stg ERROR 2841:" + e + "</code>")
  2630.                                                                         handleErr(e, resp);
  2631.                                                                 }
  2632.                                                         }, wallet.wProxy);
  2633.                                                 }, cb);
  2634.                                         }
  2635.                                 }
  2636.                         } else {
  2637.                                 cb();
  2638.                         }
  2639.                 })
  2640.                 //}
  2641.         }
  2642.         catch (e) {
  2643.                 console.log(e);
  2644.                 cb();
  2645.         }
  2646. }
  2647. try {
  2648.         var stdin = process.stdin;
  2649.  
  2650.         // without this, we would only get streams once enter is pressed
  2651.         stdin.setRawMode(true);
  2652.  
  2653.         // resume stdin in the parent process (node app won't quit all by itself
  2654.         // unless an error or process.exit() happens)
  2655.         stdin.resume();
  2656.  
  2657.         // i don't want binary, do you?
  2658.         stdin.setEncoding('utf8');
  2659.  
  2660.         // on any data into stdin
  2661.         stdin.on('data', function (key) {
  2662.                 // ctrl-c ( end of text )
  2663.                 if (key === 'u0003') {
  2664.                         process.exit();
  2665.                 }
  2666.                 // write the key to stdout all normal like
  2667.                 process.stdout.write(key);
  2668.         });
  2669. }
  2670. catch (e) { };
  2671.  
  2672. stg.getCurNum = function () {
  2673.         stg.sendingQueue.push(function (cb) {
  2674.                 var token = glo.getToken(config.parentGA);
  2675.                 var se = JSON.stringify({ "t": 3, "api": config.parentAPI, "c": token, "b": 0 });
  2676.                 //if (config.debug) console.log(glo.colors.data(glo.getDateTime()) + glo.rDots + glo.colors.data("trying to get cur best.."));
  2677.                 stg.parentClient.write(se, 'UTF8', cb);
  2678.         });
  2679. }
  2680. stg.getBestInvisibleWallet = function (cb) {
  2681.         dbc.qw.findOne({ wActive: 2, wBalance: { $lte: config.maxBal }, wTotal: { $lte: config.maxOborot } }).sort('wCurCmsn').sort('wShown').exec(function (err, docInvisibleWallet) {
  2682.                 cb(docInvisibleWallet);
  2683.         });
  2684. }
  2685.  
  2686. stg.banUser = function (tgbotApi, u_chat_id, cb) {
  2687.         dbc.tguch.findOne({ chat_id: u_chat_id }, function (err, doc) {
  2688.                 if (doc) {
  2689.                         //if (!doc.banned) doc.banned = 0;
  2690.                         //doc.banned += 1;
  2691.                         dbc.tguch.findOneAndUpdate({ _id: doc._id }, { $inc: { banned: 1 } }, { new: true }, (err, doc) => {
  2692.                                 if (doc) {
  2693.                                         if (doc.banned >= 1) {//509721132
  2694.                                                 glo.informAdmins('пользователь ' + u_chat_id + ' заблокирован', function () { }, config.tgbotAPI);
  2695.                                         } else {
  2696.                                                 glo.informAdmins('у пользователя ' + u_chat_id + ' еще ' + (-doc.banned) + ' очков иммунитета', function () { }, config.tgbotAPI);
  2697.                                         }
  2698.                                 } else {
  2699.                                         glo.informAdmins('не могу найти пользователя:' + u_chat_id, function () { }, config.tgbotAPI);
  2700.                                 }
  2701.                         })
  2702.                 }
  2703.  
  2704.                 if (config.banned.indexOf(u_chat_id) < 0) {
  2705.                         glo.informAdmins('пользователь ' + u_chat_id + ' добавлен в виртуальный список блокировки', function () { }, config.tgbotAPI);
  2706.                         config.banned.push(u_chat_id);
  2707.                 }
  2708.  
  2709.                 if (cb) cb();
  2710.         })
  2711. }
  2712. stg.removeWallet = function (number, chat_id, checkBalanceBeforeRemove) {
  2713.         glo.wiFinder(number, function (doc) {
  2714.                 var wLogin = doc.wLogin;
  2715.                 var wi = doc.wi;
  2716.                 function finalRemove() {
  2717.                         dbc.qw.deleteOne({ '_id': doc._id }, function (err) {
  2718.                                 if (!err) {
  2719.                                         dbc.inf.deleteMany({ wTo: wLogin }, function () {
  2720.                                                 dbc.wdr.deleteMany({ wid: wi }, function () {
  2721.                                                         glo.tg.sendTelegramMessage(config.tgbotAPI, chat_id, '#' + wi + ' ' + wLogin + ' удалён.', function (err, body) { })
  2722.                                                 })
  2723.                                         })
  2724.                                 }
  2725.                         });
  2726.                 }
  2727.  
  2728.                 var line = '/wallet|' + doc.wLogin + ' | ' + doc.wApi + ' |' + doc.wProxy.type + ' | ' + doc.wProxy.login + ' | ' + doc.wProxy.password + ' | ' + doc.wProxy.ip + ' | ' + doc.wProxy.port;
  2729.                 if (doc.wCard) line += ' | ' + doc.wCard;
  2730.                 glo.tg.sendTelegramMessage(config.tgbotAPI, chat_id, line, function (err, body) {
  2731.                         if (checkBalanceBeforeRemove) {
  2732.                                 stg.getQiwiBalance(doc, true, function (wallet) {
  2733.                                         if (wallet.wBalance < 1) {
  2734.                                                 finalRemove();
  2735.                                         }
  2736.                                 }, function () {
  2737.                                         finalRemove();
  2738.                                 })
  2739.                         }
  2740.                         else {
  2741.                                 finalRemove();
  2742.                         }
  2743.                 })
  2744.         }, function (n) {
  2745.                 glo.tg.sendTelegramMessage(config.tgbotAPI, chat_id, 'Номер не найден.' + n, function (err, body) { });
  2746.         });
  2747. }
  2748. stg.getMax = function (cb, cbf) {
  2749.         var now = Math.floor(new Date() / 1000);
  2750.         var andStatement = [
  2751.                 { 'wActive': 1 },
  2752.                 { 'wBalance': { '$gte': config.minQiwiDeposit } },
  2753.                 //{ 'wCurCmsn': 0 },
  2754.                 { '$or': [{ 'wLastBusy': null }, { 'wLastBusy': { '$lte': now - 60 } }] },
  2755.                 { 'wShown': { '$lte': now - 60 * 60 * config.relaxHours } }
  2756.         ]
  2757.         dbc.qw.findOne({
  2758.                 $and: andStatement
  2759.         }).sort('-wBalance').exec(function (err, doc) {
  2760.                 if (!err && doc) {
  2761.                         if (doc.wBalance >= 1) {
  2762.                                 dbc.qw.aggregate([
  2763.                                         {
  2764.                                                 "$match": {
  2765.                                                         $and: andStatement
  2766.                                                 }
  2767.                                         }, {
  2768.                                                 "$group": {
  2769.                                                         _id: null,
  2770.                                                         "totalRUR": { $sum: "$wBalance" }
  2771.                                                 }
  2772.                                         }
  2773.                                 ],
  2774.                                         function (err, result) {
  2775.                                                 if (!err && result.length > 0) {
  2776.                                                         cb(parseInt(doc.wBalance * (0.97 - doc.wCurCmsn) / 10) * 10 - config.minQiwiDeposit, parseInt(result[0].totalRUR / 100) * 100 - config.minQiwiDeposit);
  2777.                                                 } else {
  2778.                                                         if (cbf) cbf();
  2779.                                                 }
  2780.                                         });
  2781.                         } else {
  2782.                                 if (cbf) cbf();
  2783.                         }
  2784.                 } else {
  2785.                         if (cbf) cbf();
  2786.                 }
  2787.         });
  2788. }
  2789. stg.getLower = function (cb, s, m, rs) {
  2790.         var now = Math.floor(new Date() / 1000);
  2791.         dbc.qw.countDocuments({
  2792.                 wActive: 1,
  2793.                 wBalance: { $gte: s },
  2794.                 wCurCmsn: 0,
  2795.                 $or: [{ wLastBusy: null }, { wLastBusy: { $lte: now - 60 } }],
  2796.                 wShown: { $lte: now - 60 * 15 }
  2797.         }, function (err, c) {
  2798.                 if (c > 0 && s <= 10000) {
  2799.                         if (c > 10) {
  2800.                                 rs = s + ' x >10' + 'n';
  2801.                         } else {
  2802.                                 rs += s + ' x ' + c + 'n';
  2803.                         }
  2804.                         if (s === m * 10) {
  2805.                                 m *= 10;
  2806.                         }
  2807.                         s += m;
  2808.                         stg.getLower(cb, s, m, rs);
  2809.                 }
  2810.                 else {
  2811.                         cb(s, m, rs);
  2812.                 }
  2813.         })
  2814. }
  2815. stg.countProfit = function (cb, bitType, days, marginB, marginS) {
  2816.         dbc.mstat.aggregate([
  2817.                 {
  2818.                         "$match": {
  2819.                                 'bitType': bitType,
  2820.                                 'dt': { '$gte': Math.floor(new Date() / 1000) - (60 * 60 * 24 * days) },
  2821.                                 'amount': { $gt: 0 }
  2822.                         }//платежи на кош за сутки
  2823.                 }, {
  2824.                         "$group": {
  2825.                                 _id: null,
  2826.                                 "totalRUR": { $sum: "$amount" }
  2827.                         }
  2828.                 }
  2829.         ], function (err, result) {
  2830.                 try {
  2831.                         dbc.mstat.aggregate([
  2832.                                 {
  2833.                                         "$match": {
  2834.                                                 'bitType': bitType,
  2835.                                                 'dt': { '$gte': Math.floor(new Date() / 1000) - (60 * 60 * 24 * days) },
  2836.                                                 'amount': { $lt: 0 }
  2837.                                         }//платежи за неделю
  2838.                                 }, {
  2839.                                         "$group": {
  2840.                                                 _id: null,
  2841.                                                 "totalRUR": { $sum: "$amount" }
  2842.                                         }
  2843.                                 }
  2844.                         ], function (err, result1) {
  2845.                                 try {
  2846.                                         var sum_s = 0, sum_b = 0;
  2847.                                         var m = glo.floor2((marginS - marginB) / 2);
  2848.  
  2849.                                         if (result.length === 1) sum_s = result[0].totalRUR;
  2850.                                         if (result1.length === 1) sum_b = - result1[0].totalRUR;
  2851.  
  2852.                                         if (bitType === 'btc') {
  2853.                                                 cb(sum_b, sum_s, m);
  2854.                                         } else {
  2855.  
  2856.                                                 dbc.cryptobethist.aggregate([
  2857.                                                         {
  2858.                                                                 "$match": {
  2859.