· 7 years ago · Mar 13, 2018, 02:52 PM
1var fs = require('fs');
2var crypto = require('crypto');
3var console = process.console;
4var config = require('./config.js');
5var getSteamAPIKey = require('steam-web-api-key');
6var redisClient, io, requestify;
7var requestify = require('requestify');
8
9module.exports.init = function(redis, ioSocket, requestifyCore) {
10 io = ioSocket;
11 redisClient = redis.createClient();
12 requestify = requestifyCore;
13}
14
15var hash = require('crypto').createHash('sha1');
16hash.update(Math.random().toString());
17hash = hash.digest('hex');
18var device_id = 'android:' + hash;
19
20function log(log) {console.log('[BOTS] ' + log);}
21
22requestify.post('http://' + config.domain + '/api/getBots')
23.then((response) => {
24 response = JSON.parse(response.body);
25 if(!response.success) {
26 log('Ðе удалоÑÑŒ найти бота!');
27 return;
28 }
29 getBots(response.bots);
30}, (response) => {
31 log(JSON.stringify(response.body));
32});
33
34function getBots(bots) {
35
36for(var i = 0; i < bots.length; i++) startBot(bots[i]);
37
38}
39
40function startBot(data) {
41function botLog(log) {
42 console.tag('ROULETTE', logTime()).log(log);
43 }
44var logOnOptions = {
45 account_name : data.username,
46 password : data.password
47}
48
49var g_Steamid = data.steamid64;
50var g_Device_ID = device_id;
51var g_Indentity_Secret = data.identity;
52var g_Shared_Secret = data.shared;
53
54function getSHA1(bytes) {
55 var shasum = crypto.createHash('sha1');
56 shasum.end(bytes);
57 return shasum.read();
58}
59
60var Steam = require('steam');
61var steam = new Steam.SteamClient();
62var SteamTradeOffers = require('steam-tradeoffers');
63var offers = new SteamTradeOffers();
64var steamUser = new Steam.SteamUser(steam);
65var SteamTotp = require('steam-totp');
66var steamFriends = new Steam.SteamFriends(steam);
67var SteamWebLogOn = require('steam-weblogon');
68var steamWebLogOn = new SteamWebLogOn(steam, steamUser);
69var SteamConf = require('steamcommunity-mobile-confirmations');
70var steamConf;
71var confirmTimer;
72steam.connect();
73
74function GetEscrowCode(){
75 botLog('Код авторизиции : '+SteamTotp.generateAuthCode(data.shared));
76 setTimeout(function(){
77 GetEscrowCode()
78 }, 30000);
79}
80GetEscrowCode();
81logOnOptions['two_factor_code'] = SteamTotp.generateAuthCode(g_Shared_Secret);
82steam.on('connected', function() {
83 steamUser.logOn(logOnOptions);
84 });
85
86steam.on('debug', botLog);
87
88steam.on('logOnResponse', function(result) {
89 if (result.eresult === Steam.EResult.OK) {
90 botLog('ÐвторизовалиÑÑŒ!');
91 reWebLogOn(steam);
92 steamFriends.setPersonaState(Steam.EPersonaState.Online);
93 } else {
94 botLog('Ошибка при авторизиции - ' + result.eresult);
95 }
96});
97
98
99function logTime() {
100
101 var date = new Date();
102 var hour = date.getHours();
103 var min = date.getMinutes();
104 var sec = date.getSeconds();
105
106 var year = date.getFullYear();
107 var month = date.getMonth() + 1;
108 var day = date.getDate();
109
110 hour = (hour < 10 ? "0" : "") + hour;
111 min = (min < 10 ? "0" : "") + min;
112 sec = (sec < 10 ? "0" : "") + sec;
113 month = (month < 10 ? "0" : "") + month;
114 day = (day < 10 ? "0" : "") + day;
115
116 return hour + ":" + min + ":" + sec;
117}
118
119
120var checkingOffers = [],
121 WebSession = false,
122 globalSession;
123
124function reWebLogOn(steam, callback) {
125 steamWebLogOn.webLogOn(function(webSessionID, newCookie){
126 botLog('Подключили cookie! - ' + newCookie);
127 steamConf = new SteamConf(
128 {
129 steamid: g_Steamid,
130 identity_secret: g_Indentity_Secret,
131 device_id: g_Device_ID,
132 webCookie: newCookie,
133 });
134 getSteamAPIKey({
135 sessionID: webSessionID,
136 webCookie: newCookie
137 }, function(err, APIKey) {
138 offers.setup({
139 sessionID: webSessionID,
140 webCookie: newCookie,
141 APIKey: APIKey
142 }, function(err){
143 WebSession = true;
144 globalSession = webSessionID;
145 redisClient.lrange(redisChannels.tradeoffersList, 0, -1, function(err, offers){
146 offers.forEach(function(offer) {
147 checkingOffers.push(offer);
148 });
149 handleOffers();
150 });
151 botLog('ÐаÑтройка Офферов!');
152 });
153 botLog('Создал ÑеÑÑию! - '+ webSessionID);
154 });
155
156 });
157}
158
159function confirmTrade(){
160 steamConf.FetchConfirmations((function (err, confirmations) {
161 if (err) {
162 botLog('Ошибка Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¾Ñ„Ñ„ÐµÑ€Ð°: ' + err);
163 return;
164 }
165 botLog('Трейдов в ожидании:' + confirmations.length);
166 if (!confirmations.length) {
167 return;
168 }
169 steamConf.AcceptConfirmation(confirmations[0], (function (err, result) {
170 if (err) {
171 botLog('Ошибка Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¾Ñ„Ñ„ÐµÑ€Ð°: ' + err);
172 return;
173 }
174 botLog('Result:' + result);
175 }).bind(this));
176 }).bind(this));
177
178
179
180}
181
182
183const redisChannels = {
184 checkItemsList: 'checkItems.list',
185 checkList: 'check.list',
186 checkedList: 'checked.list',
187 betsList: 'bets.list',
188 sendOffersList: 'send.offers.list',
189 tradeoffersList: 'tradeoffers.list',
190 declineList: 'decline.list',
191 usersQueue: 'usersQueue.list'
192}
193
194
195steamUser.on('updateMachineAuth', function(sentry, callback) {
196 fs.writeFileSync('sentry', sentry.bytes);
197 callback({ sha_file: getSHA1(sentry.bytes) });
198});
199
200
201
202
203
204function handleOffers() {
205 offers.getOffers({
206 get_received_offers: 1,
207 active_only: 1
208 }, function(error, body) {
209 if (
210 body
211 && body.response
212 && body.response.trade_offers_received
213 ) {
214 body.response.trade_offers_received.forEach(function(offer) {
215 if (offer.trade_offer_state == 2) {
216 if(is_checkingOfferExists(offer.tradeofferid)) return;
217
218 if(offer.items_to_give != null && config.admins.indexOf(offer.steamid_other) != -1) {
219 botLog('Оффер #' + offer.tradeofferid + ' От: Admin ' + offer.steamid_other);
220 offers.acceptOffer({tradeOfferId: offer.tradeofferid});
221 confirmTrade();
222 return;
223 }
224
225 offers.getTradeHoldDuration({tradeOfferId : offer.tradeofferid}, function(err, response)
226 {
227 botLog(offer.steamid_other);
228 botLog(offer.accessToken);
229
230 if (response && response.their != 0)
231 {
232 botLog('Hold TradeOfferID: '+offer.tradeofferid+' days: '+response.their);
233
234
235 redisClient.multi([
236 ['rpush', redisChannels.declineList, offer.tradeofferid],
237 ['lrem', redisChannels.checkItemsList, 0, offer],
238 ['lrem', redisChannels.checkedList, 0, offer]
239 ])
240 .exec(function (err, replies) {
241 });
242
243
244 requestify.post('http://'+config.domain+'/api/haventescrow', {secretKey: config.secretKey , steamid: offer.steamid_other});
245
246 return;
247 }
248
249 });
250 if(offer.items_to_give != null) {
251 offers.declineOffer({tradeOfferId: offer.tradeofferid});
252 return;
253 }
254 if (offer.items_to_receive != null && offer.items_to_give == null) {
255 checkingOffers.push(offer.tradeofferid);
256 botLog('Оффер #' + offer.tradeofferid + ' От: ' + offer.steamid_other);
257 redisClient.multi([
258 ['rpush', redisChannels.tradeoffersList, offer.tradeofferid],
259 ['rpush', redisChannels.checkItemsList, JSON.stringify(offer)],
260 ['rpush', redisChannels.usersQueue, offer.steamid_other]
261 ]).exec(function(){
262 redisClient.lrange(redisChannels.usersQueue, 0, -1, function(err, queues) {
263 io.sockets.emit('queue', queues);
264 });
265 });
266 return;
267 }
268 }
269 });
270 }
271 });
272}
273
274
275steamUser.on('tradeOffers', function(number) {
276 if (number > 0) {
277 handleOffers();
278 }
279});
280
281
282var parseOffer = function(offer, offerJson){
283 offers.loadPartnerInventory({partnerSteamId: offer.steamid_other, appId: 730, contextId: 2, tradeOfferId: offer.tradeofferid, language: "russian"}, function(err, hitems) {
284 if (err) {
285 redisClient.multi([
286 ['rpush', redisChannels.declineList, offer.tradeofferid],
287 ['lrem', redisChannels.checkItemsList, 0, offerJson],
288 ['lrem', redisChannels.usersQueue, 1, offer.steamid_other]
289 ])
290 .exec(function (err, replies) {
291 parseItemsProcceed = false;
292 return;
293 });
294 return;
295 }
296 var items = offer.items_to_receive;
297 var items_to_check = [], num = 0;
298 for (var i = 0; i < items.length; i++) {
299 for (var j = 0; j < hitems.length; j++) {
300 if (items[i].assetid == hitems[j].id) {
301 items_to_check[num] = {
302 appid:hitems[j].appid,
303 name:hitems[j].market_name,
304 market_hash_name:hitems[j].market_hash_name,
305 classid:hitems[j].classid
306 };
307 var type = hitems[j].type;
308 var rarity = '';
309 var arr = type.split(',');
310 if (arr.length == 2) type = arr[1].trim();
311 if (arr.length == 3) type = arr[2].trim();
312 if (arr.length && arr[0] == 'Ðож') type = '★';
313 switch (type) {
314 case 'ÐрмейÑкое качеÑтво': rarity = 'milspec'; break;
315 case 'Запрещенное': rarity = 'restricted'; break;
316 case 'ЗаÑекреченное': rarity = 'classified'; break;
317 case 'Тайное': rarity = 'covert'; break;
318 case 'Ширпотреб': rarity = 'common'; break;
319 case 'Промышленное качеÑтво': rarity = 'common'; break;
320 case '★': rarity = 'rare'; break;
321 }
322 items_to_check[num].rarity = rarity;
323 num++;
324 break;
325 }
326 }
327 }
328 var value = {
329 offerid: offer.tradeofferid,
330 accountid: offer.steamid_other,
331 items: JSON.stringify(items_to_check)
332 };
333
334 console.tag('ROULETTE','OFFER:' + value.offerid).log(value);
335
336 redisClient.multi([
337 ['rpush', redisChannels.checkList, JSON.stringify(value)],
338 ['lrem', redisChannels.checkItemsList, 0, offerJson]
339 ])
340 .exec(function (err, replies) {
341 parseItemsProcceed = false;
342 });
343
344 });
345}
346
347var checkOfferPrice = function () {
348 requestify.get('http://' + config.domain + '/api/checkOffer', {
349 secretKey: config.secretKey
350 })
351 .then(function (response) {
352 var answer = JSON.parse(response.body);
353
354 if (answer.success) {
355 checkProcceed = false;
356 }
357 }, function (response) {
358 console.tag('SteamBot', logTime()).error('Что-то не так Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¾Ð¹ офферов.');
359 setTimeout(function () {
360 checkOfferPrice()
361 }, 1000);
362 });
363
364}
365
366var checkNewBet = function () {
367 requestify.get('http://' + config.domain + '/api/newBet', {
368 secretKey: config.secretKey
369 })
370 .then(function (response) {
371 var answer = JSON.parse(response.body);
372 if (answer.success) {
373 betsProcceed = false;
374 }
375 }, function (response) {
376 console.tag('SteamBot', logTime()).error('Что-то не так Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸ÐµÐ¼ новой Ñтавки.');
377 setTimeout(function () {
378 checkNewBet()
379 }, 1000);
380 });
381}
382
383var checkArrGlobal = [];
384
385var sendTradeOffer = function(appId, partnerSteamId, accessToken, sendItems, message, game, offerJson){
386 try {
387 offers.loadMyInventory({
388 appId: appId,
389 contextId: 2
390 }, function (err, items) {
391 if(err) {
392 botLog(err);
393 sendProcceed = false;
394 return;
395 }
396 var itemsFromMe = [],
397 checkArr = [],
398 num = 0;
399 var i = 0;
400 for (var i = 0; i < sendItems.length; i++) {
401 for (var j = 0; j < items.length; j++) {
402 if (items[j].tradable && (items[j].classid == sendItems[i])) {
403 if ((checkArr.indexOf(items[j].id) == -1) && (checkArrGlobal.indexOf(items[j].id) == -1)) {
404 checkArr[i] = items[j].id;
405 itemsFromMe[num] = {
406 appid: 730,
407 contextid: 2,
408 amount: items[j].amount,
409 assetid: items[j].id
410 };
411 num++;
412 break;
413 }
414 }
415 }
416 }
417 if (num > 0) {
418 offers.makeOffer({
419 partnerSteamId: partnerSteamId,
420 accessToken: accessToken,
421 itemsFromMe: itemsFromMe,
422 itemsFromThem: [],
423 message: 'ПоздравлÑем Ñ Ð¿Ð¾Ð±ÐµÐ´Ð¾Ð¹ на Ñайте '+config.nameSite+' > Ð’ игре #' + game
424 }, function (err, response) {
425 if (err) {
426 console.tag('SteamBot', 'SendPrize', logTime()).error('Ошибка Ð¾Ñ‚Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ„Ñ„ÐµÑ€Ð°:' + err.message);
427 getErrorCode(err.message, function(errCode) {
428 if(errCode == 2 || errCode == 3 || errCode == 6 || errCode == 15 || errCode == 16 || errCode == 25 || errCode == 50 || err.message.indexOf('was an error sending your trade offer. Please try again later.')) { // if there is an error in submitting the winning re-send it
429 redisClient.lrem(redisChannels.sendOffersList, 0, offerJson, function (err, data) {
430 setPrizeStatus(game, 2);
431 CheckGameForSend(game, 1);
432 setTimeout(function () {
433 CheckGameForSend(game, 0);
434 setPrizeStatus(game, 1);
435 console.tag('SteamBot', 'SendPrize', logTime()).log('Прошло 10 минут, оÑтанавливем переотправку, и Ñтавим ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°ÑƒÐ½Ð´Ð° - 1.');
436 }, 60000);
437 sendProcceed = false;
438 });
439 sendProcceed = false;
440 }
441 sendProcceed = false;
442 });
443 return;
444 }
445 checkArrGlobal = checkArrGlobal.concat(checkArr);
446 botLog(checkArrGlobal);
447 botLog(checkArr);
448 redisClient.lrem(redisChannels.sendOffersList, 0, offerJson, function(err, data){
449 setPrizeStatus(game, 1);
450 CheckGameForSend(game, 0);
451 sendProcceed = false;
452 });
453 botLog('Оффер #' + response.tradeofferid +' отправлен!');
454 confirmTrade();
455 });
456 }else{
457 botLog('Ðету предметов!');
458 redisClient.lrem(redisChannels.sendOffersList, 0, offerJson, function(err, data){
459 setPrizeStatus(game, 1);
460 CheckGameForSend(game, 0);
461 sendProcceed = false;
462 });
463 }
464 });
465
466 }catch(ex){
467 console.tag('SteamBot', logTime()).error('Error to send the bet');
468 setPrizeStatus(game, 2);
469 CheckGameForSend(game, 1);
470 sendProcceed = false;
471 }
472};
473
474
475
476var setPrizeStatus = function(game, status){
477 requestify.post('http://'+config.domain+'/api/setPrizeStatus', {
478 secretKey: config.secretKey,
479 game: game,
480 status: status
481 })
482 .then(function(response) {
483
484 },function(response){
485 botLog('Что-то не так Ñ ÑƒÑтановкой prize status.');
486 setTimeout(function(){setPrizeStatus()}, 1000);
487 });
488}
489
490var CheckGameForSend = function(game, status){
491 requestify.post('http://'+config.domain+'/api/CheckGameForSend', {
492 secretKey: config.secretKey,
493 game: game,
494 status: status
495 })
496 .then(function(response) {
497
498 },function(response){
499 botLog('Что-то не так Ñ ÑƒÑтановкой CheckGameForSend.');
500 setTimeout(function(){CheckGameForSend()}, 1000);
501 });
502}
503
504var is_checkingOfferExists = function(tradeofferid){
505 for(var i = 0, len = checkingOffers.length; i<len; ++i ){
506 var offer = checkingOffers[i];
507 if(offer == tradeofferid){
508 return true;
509 break;
510 }
511 }
512 return false;
513}
514
515var checkedOffersProcceed = function(offerJson){
516 var offer = JSON.parse(offerJson);
517 if (offer.success) {
518 botLog('Принимаем: #' + offer.offerid);
519 offers.acceptOffer({tradeOfferId: offer.offerid}, function (err, body) {
520 if (!err) {
521 redisClient.multi([
522 ["lrem", redisChannels.tradeoffersList, 0, offer.offerid],
523 ["lrem", redisChannels.usersQueue, 1, offer.steamid64],
524 ["rpush", redisChannels.betsList, offerJson],
525 ["lrem", redisChannels.checkedList, 0, offerJson]
526 ])
527 .exec(function (err, replies) {
528 redisClient.lrange(redisChannels.usersQueue, 0, -1, function(err, queues) {
529 io.sockets.emit('queue', queues);
530 botLog("Ðовый депозит принÑÑ‚!");
531 checkedProcceed = false;
532 });
533 });
534
535 } else {
536 botLog('Ошибка. Ðе могу принÑть оффер #' + offer.offerid + ' Log: ' + err)
537
538 offers.getOffer({tradeOfferId: offer.offerid}, function (err, body){
539 if(body && body.response && body.response.offer){
540 var offerCheck = body.response.offer;
541 if(offerCheck.trade_offer_state == 2) {
542 checkedProcceed = false;
543 return;
544 }
545 if(offerCheck.trade_offer_state == 3){
546 redisClient.multi([
547 ["lrem", redisChannels.tradeoffersList, 0, offer.offerid],
548 ["lrem", redisChannels.usersQueue, 1, offer.steamid64],
549 ["rpush", redisChannels.betsList, offerJson],
550 ["lrem", redisChannels.checkedList, 0, offerJson]
551 ])
552 .exec(function (err, replies) {
553 redisClient.lrange(redisChannels.usersQueue, 0, -1, function(err, queues) {
554 io.sockets.emit('queue', queues);
555 checkedProcceed = false;
556 });
557 });
558 }else{
559 redisClient.multi([
560 ["lrem", redisChannels.tradeoffersList, 0, offer.offerid],
561 ["lrem", redisChannels.usersQueue, 1, offer.steamid64],
562 ["lrem", redisChannels.checkedList, 0, offerJson]
563 ])
564 .exec(function (err, replies) {
565 redisClient.lrange(redisChannels.usersQueue, 0, -1, function(err, queues) {
566 io.sockets.emit('queue', queues);
567 checkedProcceed = false;
568 });
569 });
570 }
571 }
572 })
573 }
574 });
575 }
576}
577
578var declineOffersProcceed = function(offerid){
579 botLog('ОтменÑем: #' + offerid);
580 offers.declineOffer({tradeOfferId: offerid}, function (err, body) {
581 if (!err) {
582 botLog('Оффер #' + offerid + ' Отменен!');
583 redisClient.lrem(redisChannels.declineList, 0, offerid);
584 declineProcceed = false;
585 } else {
586 botLog('Ошибка. Ðе могу отменить оффер #' + offer.offerid + ' Log: ' + err)
587 declineProcceed = false;
588 }
589 });
590}
591
592
593var queueProceed = function(){
594 redisClient.llen(redisChannels.checkList, function(err, length) {
595 if (length > 0 && !checkProcceed && WebSession) {
596 console.tag('SteamBot','Queues', logTime()).info('ПроверÑем Офферы:' + length);
597 checkProcceed = true;
598 checkOfferPrice();
599 }
600 });
601 redisClient.llen(redisChannels.declineList, function(err, length) {
602 if(length > 0 && !declineProcceed && WebSession) {
603 console.tag('SteamBot','Queues', logTime()).info('ОтклонÑем Офферы:' + length);
604 declineProcceed = true;
605 redisClient.lindex(redisChannels.declineList, 0,function (err, offer) {
606 declineOffersProcceed(offer);
607 });
608 }
609 });
610 redisClient.llen(redisChannels.checkedList, function(err, length) {
611 if(length > 0 && !checkedProcceed && WebSession) {
612 console.tag('SteamBot','Queues', logTime()).info('Проверенные Офферы:' + length);
613 checkedProcceed = true;
614 redisClient.lindex(redisChannels.checkedList, 0,function (err, offer) {
615 checkedOffersProcceed(offer);
616 });
617 }
618 });
619 redisClient.llen(redisChannels.betsList, function(err, length) {
620 if (length > 0 && !betsProcceed && !delayForNewGame) {
621 console.tag('SteamBot','Queues', logTime()).info('Ставки:' + length);
622 betsProcceed = true;
623 checkNewBet();
624 }
625 });
626 redisClient.llen(redisChannels.sendOffersList, function(err, length) {
627 if (length > 0 && !sendProcceed && WebSession) {
628 console.tag('SteamBot','Queues', logTime()).info('ОтправлÑем победителю оффер:' + length);
629 sendProcceed = true;
630 redisClient.lindex(redisChannels.sendOffersList, 0,function (err, offerJson) {
631 offer = JSON.parse(offerJson);
632 sendTradeOffer(offer.appId, offer.steamid, offer.accessToken, offer.items, '', offer.game, offerJson);
633 });
634 }
635 });
636 redisClient.llen(redisChannels.checkItemsList, function(err, length) {
637 if (length > 0 && !parseItemsProcceed && WebSession) {
638 console.tag('SteamBot','Queues', logTime()).info('ПарÑим предметы:' + length);
639 parseItemsProcceed = true;
640 redisClient.lindex(redisChannels.checkItemsList, 0, function (err, offerJson) {
641 offer = JSON.parse(offerJson);
642 parseOffer(offer, offerJson);
643 });
644 }
645 });
646}
647var parseItemsProcceed = false;
648var checkProcceed = false;
649var checkedProcceed = false;
650var declineProcceed = false;
651var betsProcceed = false;
652var sendProcceed = false;
653var delayForNewGame = false;
654setInterval(queueProceed, 1500);
655
656module.exports.handleOffers = handleOffers;
657module.exports.delayForNewGame = function(value){
658 delayForNewGame = value;
659};
660
661function getErrorCode(err, callback){
662 var errCode = 0;
663 var match = err.match(/\(([^()]*)\)/);
664 if(match != null && match.length == 2) errCode = match[1];
665 callback(errCode);
666}
667
668}