· 10 years ago · Apr 18, 2016, 05:03 PM
1//bot.js//
2var fs = require('fs');
3var crypto = require('crypto');
4var console = process.console;
5var config = require('./config.js');
6var Steam = require('steam');
7var SteamWebLogOn = require('steam-weblogon');
8var getSteamAPIKey = require('steam-web-api-key');
9var SteamTradeOffers = require('steam-tradeoffers');
10var redisClient, io, requestify;
11var SteamTotp = require('steam-totp');
12var SteamcommunityMobileConfirmations = require('steamcommunity-mobile-confirmations');
13module.exports.init = function(redis, ioSocket, requestifyCore) {
14 io = ioSocket;
15 redisClient = redis.createClient();
16 requestify = requestifyCore;
17}
18
19var logOnOptions = {
20 account_name: config.username,
21 password: config.password,
22 two_factor_code: SteamTotp.generateAuthCode(config.shared_secret)
23};
24function gucode(){
25 console.log('Код авторизиции '+SteamTotp.generateAuthCode(config.shared_secret));
26 setTimeout(function(){ gucode() }, 30000)
27}
28gucode();
29var authCode = SteamTotp.generateAuthCode(config.shared_secret); // code received by email
30
31try {
32 logOnOptions.sha_sentryfile = getSHA1(fs.readFileSync('sentry'));
33} catch (e) {
34
35 if (authCode !== '') {
36 logOnOptions.auth_code = authCode;
37 }
38}
39function getSHA1(bytes) {
40 var shasum = crypto.createHash('sha1');
41 shasum.end(bytes);
42 return shasum.read();
43}
44// if we've saved a server list, use it
45/*
46 if (fs.existsSync('servers')) {
47 Steam.servers = JSON.parse(fs.readFileSync('servers'));
48 }*/
49
50var steamClient = new Steam.SteamClient();
51var steamUser = new Steam.SteamUser(steamClient);
52var steamFriends = new Steam.SteamFriends(steamClient);
53var steamWebLogOn = new SteamWebLogOn(steamClient, steamUser);
54var offers = new SteamTradeOffers();
55
56var checkingOffers = [],
57 WebSession = false,
58 globalSession;
59
60const redisChannels = {
61 checkItemsList: 'checkItems.list',
62 checkList: 'check.list',
63 checkedList: 'checked.list',
64 betsList: 'bets.list',
65 sendOffersList: 'send.offers.list',
66 tradeoffersList: 'tradeoffers.list',
67 declineList: 'decline.list',
68 usersQueue: 'usersQueue.list'
69}
70
71function steamBotLogger(log){
72 console.tag('SteamBot').log(log);
73}
74steamClient.connect();
75steamClient.on('debug', steamBotLogger);
76steamClient.on('connected', function() {
77 steamUser.logOn(logOnOptions);
78});
79
80steamClient.on('logOnResponse', function(logonResp) {
81 if (logonResp.eresult === Steam.EResult.OK) {
82 steamBotLogger('Logged in!');
83 steamFriends.setPersonaState(Steam.EPersonaState.Online);
84
85 steamWebLogOn.webLogOn(function(sessionID, newCookie) {
86
87 function trademobile(){
88var hash = require('crypto').createHash('sha1');
89hash.update(Math.random().toString());
90hash = hash.digest('hex');
91device_id = 'android:' + hash;
92var steamcommunityMobileConfirmations = new SteamcommunityMobileConfirmations(
93{
94 steamid: config.steamid,
95identity_secret: config.identity_secret,
96device_id: this.device_id,
97 webCookie: newCookie,
98});
99steamcommunityMobileConfirmations.FetchConfirmations((function (err, confirmations)
100{
101 if (err)
102 {
103 console.tag('SteamBot').error(err);
104 return;
105 }
106 console.tag('ESCROW').log('Трейдов: ' + confirmations.length + '');
107 if ( ! confirmations.length)
108 {
109 return;
110 }
111 steamcommunityMobileConfirmations.AcceptConfirmation(confirmations[0], (function (err, result)
112 {
113 if (err)
114 {
115 console.tag('SteamBot').console.error(err);
116 return;
117 }
118 console.tag('ESCROW').log('Результат: ' + result);
119 }).bind(this));
120}).bind(this));
121 setTimeout(function(){ trademobile()}, 1000)
122}
123trademobile();
124 getSteamAPIKey({
125 sessionID: sessionID,
126 webCookie: newCookie
127 }, function(err, APIKey) {
128 offers.setup({
129 sessionID: sessionID,
130 webCookie: newCookie,
131 APIKey: APIKey
132 }, function(err){
133 WebSession = true;
134 globalSession = sessionID;
135 redisClient.lrange(redisChannels.tradeoffersList, 0, -1, function(err, offers){
136 offers.forEach(function(offer) {
137 checkingOffers.push(offer);
138 });
139 handleOffers();
140 });
141 steamBotLogger('Setup Offers!');
142 });
143
144 });
145 });
146 }
147});
148
149
150
151
152steamClient.on('servers', function(servers) {
153 fs.writeFile('servers', JSON.stringify(servers));
154});
155
156steamUser.on('updateMachineAuth', function(sentry, callback) {
157 fs.writeFileSync('sentry', sentry.bytes);
158 callback({ sha_file: getSHA1(sentry.bytes) });
159});
160
161function handleOffers() {
162 offers.getOffers({
163 get_received_offers: 1,
164 active_only: 1
165 }, function(error, body) {
166 if (
167 body
168 && body.response
169 && body.response.trade_offers_received
170 ) {
171 body.response.trade_offers_received.forEach(function(offer) {
172 if (offer.trade_offer_state == 2) {
173 if(is_checkingOfferExists(offer.tradeofferid)) return;
174
175 if(offer.items_to_give != null && config.admins.indexOf(offer.steamid_other) != -1) {
176 console.tag('SteamBot', 'TradeOffer').log('TRADE OFFER #' + offer.tradeofferid + ' FROM: Admin ' + offer.steamid_other);
177 offers.acceptOffer({tradeOfferId: offer.tradeofferid});
178 return;
179 }
180
181 offers.getTradeHoldDuration({tradeOfferId : offer.tradeofferid}, function(err, res)
182 {
183 console.log(offer.steamid_other);
184 console.log(offer.accessToken);
185 fs.writeFile('saved_response.txt', res, 'utf8');
186 if(res.their != 0){
187 requestify.post('http://'+config.domain+'/api/haventescrow', {secretKey: config.secretKey , steamid: offer.steamid_other});
188 console.tag('ESCROW').log(res.their+' отключён');
189 offers.declineOffer({tradeOfferId: offer.tradeofferid});
190 return;
191
192 }
193
194 });
195 if(offer.items_to_give != null) {
196 offers.declineOffer({tradeOfferId: offer.tradeofferid});
197 return;
198 }
199 if (offer.items_to_receive != null && offer.items_to_give == null) {
200 checkingOffers.push(offer.tradeofferid);
201 console.tag('SteamBot', 'TradeOffer').log('TRADE OFFER #' + offer.tradeofferid + ' FROM: ' + offer.steamid_other);
202 redisClient.multi([
203 ['rpush', redisChannels.tradeoffersList, offer.tradeofferid],
204 ['rpush', redisChannels.checkItemsList, JSON.stringify(offer)],
205 ['rpush', redisChannels.usersQueue, offer.steamid_other]
206 ]).exec(function(){
207 redisClient.lrange(redisChannels.usersQueue, 0, -1, function(err, queues) {
208 io.sockets.emit('queue', queues);
209 });
210 });
211 return;
212 }
213 }
214 });
215 }
216 });
217}
218
219steamUser.on('tradeOffers', function(number) {
220 if (number > 0) {
221 handleOffers();
222 }
223});
224
225
226var parseOffer = function(offer, offerJson){
227 offers.loadPartnerInventory({partnerSteamId: offer.steamid_other, appId: 730, contextId: 2, tradeOfferId: offer.tradeofferid, language: "russian"}, function(err, hitems) {
228 if (err) {
229 redisClient.multi([
230 ['rpush', redisChannels.declineList, offer.tradeofferid],
231 ['lrem', redisChannels.checkItemsList, 0, offerJson],
232 ['lrem', redisChannels.usersQueue, 1, offer.steamid_other]
233 ])
234 .exec(function (err, replies) {
235 parseItemsProcceed = false;
236 return;
237 });
238 return;
239 }
240 var items = offer.items_to_receive;
241 var items_to_check = [], num = 0;
242 for (var i = 0; i < items.length; i++) {
243 for (var j = 0; j < hitems.length; j++) {
244 if (items[i].assetid == hitems[j].id) {
245 items_to_check[num] = {
246 appid:hitems[j].appid,
247 name:hitems[j].market_name,
248 market_hash_name:hitems[j].market_hash_name,
249 classid:hitems[j].classid
250 };
251 var type = hitems[j].type;
252 var rarity = '';
253 var arr = type.split(',');
254 if (arr.length == 2) type = arr[1].trim();
255 if (arr.length == 3) type = arr[2].trim();
256 if (arr.length && arr[0] == 'Ðож') type = '★';
257 switch (type) {
258 case 'ÐрмейÑкое качеÑтво': rarity = 'milspec'; break;
259 case 'Запрещенное': rarity = 'restricted'; break;
260 case 'ЗаÑекреченное': rarity = 'classified'; break;
261 case 'Тайное': rarity = 'covert'; break;
262 case 'Ширпотреб': rarity = 'common'; break;
263 case 'Промышленное качеÑтво': rarity = 'common'; break;
264 case '★': rarity = 'rare'; break;
265 }
266 items_to_check[num].rarity = rarity;
267 num++;
268 break;
269 }
270 }
271 }
272 var value = {
273 offerid: offer.tradeofferid,
274 accountid: offer.steamid_other,
275 items: JSON.stringify(items_to_check)
276 };
277
278 console.tag('SteamBot', 'Offer #' + value.offerid).log(value);
279
280 redisClient.multi([
281 ['rpush', redisChannels.checkList, JSON.stringify(value)],
282 ['lrem', redisChannels.checkItemsList, 0, offerJson]
283 ])
284 .exec(function (err, replies) {
285 parseItemsProcceed = false;
286 });
287
288 });
289}
290
291var checkOfferPrice = function(){
292 requestify.get('http://'+config.domain+'/api/checkOffer', {
293 secretKey: config.secretKey
294 })
295 .then(function(response) {
296 var answer = JSON.parse(response.body);
297
298
299 if(answer.success){
300 checkProcceed = false;
301 }
302 },function(response){
303 console.tag('SteamBot').error('Something wrong with check offers. Retry...');
304 setTimeout(function(){checkOfferPrice()}, 1000);
305 });
306
307}
308
309var checkNewBet = function(){
310 requestify.get('http://'+config.domain+'/api/newBet', {
311 secretKey: config.secretKey
312 })
313 .then(function(response) {
314 var answer = JSON.parse(response.body);
315 if(answer.success){
316 betsProcceed = false;
317 }
318 },function(response){
319 console.tag('SteamBot').error('Something wrong with send a new bet. Retry...');
320 setTimeout(function(){checkNewBet()}, 1000);
321 });
322}
323
324var checkArrGlobal = [];
325
326var sendTradeOffer = function(appId, partnerSteamId, accessToken, sendItems, message, game, offerJson){
327 try {
328 offers.loadMyInventory({
329 appId: appId,
330 contextId: 2
331 }, function (err, items) {
332 if(err) {
333 console.log(err);
334 sendProcceed = false;
335 return;
336 }
337 var itemsFromMe = [],
338 checkArr = [],
339 num = 0;
340 var i = 0;
341 for (var i = 0; i < sendItems.length; i++) {
342 for (var j = 0; j < items.length; j++) {
343 if (items[j].tradable && (items[j].classid == sendItems[i])) {
344 if ((checkArr.indexOf(items[j].id) == -1) && (checkArrGlobal.indexOf(items[j].id) == -1)) {
345 checkArr[i] = items[j].id;
346 itemsFromMe[num] = {
347 appid: 730,
348 contextid: 2,
349 amount: items[j].amount,
350 assetid: items[j].id
351 };
352 num++;
353 break;
354 }
355 }
356 }
357 }
358 if (num > 0) {
359 offers.makeOffer({
360 partnerSteamId: partnerSteamId,
361 accessToken: accessToken,
362 itemsFromMe: itemsFromMe,
363 itemsFromThem: [],
364 message: 'Your winnings on the site '+config.domain+''
365 }, function (err, response) {
366 if (err) {
367 console.tag('SteamBot', 'SendPrize').error('Error to send offer:' + err.message);
368 getErrorCode(err.message, function(errCode){
369if(errCode == 15 || errCode == 25 || err.message.indexOf('an error sending your trade offer. Please try again later.')) {
370 redisClient.lrem(redisChannels.sendOffersList, 0, offerJson, function (err, data) {
371 setPrizeStatus(game, 2);
372 sendProcceed = false;
373 });
374 sendProcceed = false;
375 }
376 sendProcceed = false;
377 });
378 return;
379 }
380 checkArrGlobal = checkArrGlobal.concat(checkArr);
381 console.log(checkArrGlobal);
382 console.log(checkArr);
383 redisClient.lrem(redisChannels.sendOffersList, 0, offerJson, function(err, data){
384 setPrizeStatus(game, 1);
385 sendProcceed = false;
386 });
387 console.tag('SteamBot', 'SendPrize').log('TradeOffer #' + response.tradeofferid +' send!');
388 });
389 }else{
390 console.tag('SteamBot', 'SendPrize').log('Items not found!');
391 redisClient.lrem(redisChannels.sendOffersList, 0, offerJson, function(err, data){
392 setPrizeStatus(game, 1);
393 sendProcceed = false;
394 });
395 }
396 });
397
398 }catch(ex){
399 console.tag('SteamBot').error('Error to send the bet');
400 setPrizeStatus(game, 2);
401 sendProcceed = false;
402 }
403};
404
405var setPrizeStatus = function(game, status){
406 requestify.post('http://'+config.domain+'/api/setPrizeStatus', {
407 secretKey: config.secretKey,
408 game: game,
409 status: status
410 })
411 .then(function(response) {
412
413 },function(response){
414 console.tag('SteamBot').log('Something wrong with set prize status. Retry...');
415 setTimeout(function(){setPrizeStatus()}, 1000);
416 });
417}
418
419var is_checkingOfferExists = function(tradeofferid){
420 for(var i = 0, len = checkingOffers.length; i<len; ++i ){
421 var offer = checkingOffers[i];
422 if(offer == tradeofferid){
423 return true;
424 break;
425 }
426 }
427 return false;
428}
429
430var checkedOffersProcceed = function(offerJson){
431 var offer = JSON.parse(offerJson);
432 if (offer.success) {
433 console.tag('SteamBot').log('Procceding accept: #' + offer.offerid);
434 offers.acceptOffer({tradeOfferId: offer.offerid}, function (err, body) {
435 if (!err) {
436 redisClient.multi([
437 ["lrem", redisChannels.tradeoffersList, 0, offer.offerid],
438 ["lrem", redisChannels.usersQueue, 1, offer.steamid64],
439 ["rpush", redisChannels.betsList, offerJson],
440 ["lrem", redisChannels.checkedList, 0, offerJson]
441 ])
442 .exec(function (err, replies) {
443 redisClient.lrange(redisChannels.usersQueue, 0, -1, function(err, queues) {
444 io.sockets.emit('queue', queues);
445 console.tag('SteamBot').log("New bet Accepted!");
446 checkedProcceed = false;
447 });
448 });
449
450 } else {
451 console.tag('SteamBot').error('Error. With accept tradeoffer #' + offer.offerid)
452 .tag('SteamBot').log(err);
453
454 offers.getOffer({tradeOfferId: offer.offerid}, function (err, body){
455 if(body.response.offer){
456 var offerCheck = body.response.offer;
457 if(offerCheck.trade_offer_state == 2) {
458 checkedProcceed = false;
459 return;
460 }
461 if(offerCheck.trade_offer_state == 3){
462 redisClient.multi([
463 ["lrem", redisChannels.tradeoffersList, 0, offer.offerid],
464 ["lrem", redisChannels.usersQueue, 1, offer.steamid64],
465 ["rpush", redisChannels.betsList, offerJson],
466 ["lrem", redisChannels.checkedList, 0, offerJson]
467 ])
468 .exec(function (err, replies) {
469 redisClient.lrange(redisChannels.usersQueue, 0, -1, function(err, queues) {
470 io.sockets.emit('queue', queues);
471 checkedProcceed = false;
472 });
473 });
474 }else{
475 redisClient.multi([
476 ["lrem", redisChannels.tradeoffersList, 0, offer.offerid],
477 ["lrem", redisChannels.usersQueue, 1, offer.steamid64],
478 ["lrem", redisChannels.checkedList, 0, offerJson]
479 ])
480 .exec(function (err, replies) {
481 redisClient.lrange(redisChannels.usersQueue, 0, -1, function(err, queues) {
482 io.sockets.emit('queue', queues);
483 checkedProcceed = false;
484 });
485 });
486 }
487 }
488 })
489 }
490 });
491 }
492}
493
494var declineOffersProcceed = function(offerid){
495 console.tag('SteamBot').log('Procceding decline: #' + offerid);
496 offers.declineOffer({tradeOfferId: offerid}, function (err, body) {
497 if (!err) {
498 console.tag('SteamBot').log('Offer #' + offerid + ' Decline!');
499 redisClient.lrem(redisChannels.declineList, 0, offerid);
500 declineProcceed = false;
501 } else {
502 console.tag('SteamBot').error('Error. With decline tradeoffer #' + offer.offerid)
503 .tag('SteamBot').log(err);
504 declineProcceed = false;
505 }
506 });
507}
508
509var queueProceed = function(){
510 redisClient.llen(redisChannels.checkList, function(err, length) {
511 if (length > 0 && !checkProcceed) {
512 console.tag('SteamBot','Queues').info('CheckOffers:' + length);
513 checkProcceed = true;
514 checkOfferPrice();
515 }
516 });
517 redisClient.llen(redisChannels.checkedList, function(err, length) {
518 if(length > 0 && !checkedProcceed && WebSession) {
519 console.tag('SteamBot','Queues').info('CheckedOffers:' + length);
520 checkedProcceed = true;
521 redisClient.lindex(redisChannels.checkedList, 0,function (err, offer) {
522 checkedOffersProcceed(offer);
523 });
524 }
525 });
526 redisClient.llen(redisChannels.declineList, function(err, length) {
527 if(length > 0 && !declineProcceed && WebSession) {
528 console.tag('SteamBot','Queues').info('DeclineOffers:' + length);
529 declineProcceed = true;
530 redisClient.lindex(redisChannels.declineList, 0,function (err, offer) {
531 declineOffersProcceed(offer);
532 });
533 }
534 });
535 redisClient.llen(redisChannels.betsList, function(err, length) {
536 if (length > 0 && !betsProcceed && !delayForNewGame) {
537 console.tag('SteamBot','Queues').info('Bets:' + length);
538 betsProcceed = true;
539 checkNewBet();
540 }
541 });
542 redisClient.llen(redisChannels.sendOffersList, function(err, length) {
543 if (length > 0 && !sendProcceed && WebSession) {
544 console.tag('SteamBot','Queues').info('Send winner offers:' + length);
545 sendProcceed = true;
546 redisClient.lindex(redisChannels.sendOffersList, 0,function (err, offerJson) {
547 offer = JSON.parse(offerJson);
548 sendTradeOffer(offer.appId, offer.steamid, offer.accessToken, offer.items, '', offer.game, offerJson);
549 });
550 }
551 });
552 redisClient.llen(redisChannels.checkItemsList, function(err, length) {
553 if (length > 0 && !parseItemsProcceed && WebSession) {
554 console.tag('SteamBot','Queues').info('Parse items:' + length);
555 parseItemsProcceed = true;
556 redisClient.lindex(redisChannels.checkItemsList, 0, function (err, offerJson) {
557 offer = JSON.parse(offerJson);
558 parseOffer(offer, offerJson);
559 });
560 }
561 });
562}
563var parseItemsProcceed = false;
564var checkProcceed = false;
565var checkedProcceed = false;
566var declineProcceed = false;
567var betsProcceed = false;
568var sendProcceed = false;
569var delayForNewGame = false;
570setInterval(queueProceed, 1500);
571
572module.exports.handleOffers = handleOffers;
573module.exports.delayForNewGame = function(value){
574 delayForNewGame = value;
575};
576
577
578function getErrorCode(err, callback){
579 var errCode = 0;
580 var match = err.match(/\(([^()]*)\)/);
581 if(match != null && match.length == 2) errCode = match[1];
582 callback(errCode);
583}