· 9 years ago · Aug 07, 2016, 09:18 PM
1/* NodeJS бот | Разработано онлайн-магазином UpScripts.Pro */
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 SteamTotp = require('steam-totp');
11var SteamcommunityMobileConfirmations = require('steamcommunity-mobile-confirmations');
12
13var redisClient, requestify;
14module.exports.init = function(redis, requestifyCore) {
15 redisClient = redis.createClient();
16 requestify = requestifyCore;
17}
18
19var twofactorCode = SteamTotp.generateAuthCode(config.shopBot.sharedSecret);
20var logOnOptions = {
21 account_name: config.shopBot.username,
22 password: config.shopBot.password,
23 two_factor_code: twofactorCode
24};
25
26var authCode = '';
27
28try {
29 logOnOptions.sha_sentryfile = getSHA1(fs.readFileSync('sentry_shop'));
30} catch (e) {
31 if (authCode !== '') {
32 logOnOptions.auth_code = authCode;
33 }
34}
35function getSHA1(bytes) {
36 var shasum = crypto.createHash('sha1');
37 shasum.end(bytes);
38 return shasum.read();
39}
40if (fs.existsSync('servers')) {
41 Steam.servers = JSON.parse(fs.readFileSync('servers'));
42}
43
44var steamClient = new Steam.SteamClient();
45var steamUser = new Steam.SteamUser(steamClient);
46var steamFriends = new Steam.SteamFriends(steamClient);
47var steamWebLogOn = new SteamWebLogOn(steamClient, steamUser);
48var offers = new SteamTradeOffers();
49var steamcommunityMobileConfirmations;
50
51var checkingOffers = [],
52 WebSession = false,
53 globalSession;
54
55var redisChannels = {
56 itemsToSale: 'items.to.sale',
57 itemsToGive: 'items.to.give',
58 offersToCheck: 'offers.to.check'
59}
60
61function device(){
62 var hash = crypto.createHash('sha1');
63 hash.update(Math.random().toString());
64 hash = hash.digest('hex');
65//hash = '192D74783A0707D21D8A0EB121F7F8977554DF14';
66 return 'android:'+hash;
67}
68
69function steamBotLogger(log){
70 console.tag('ЗапуÑк Ñервера магазина').log(log);
71}
72steamClient.connect();
73steamClient.on('debug', steamBotLogger);
74steamClient.on('connected', function() {
75 steamUser.logOn(logOnOptions);
76});
77
78steamClient.on('logOnResponse', function(logonResp) {
79 if (logonResp.eresult === Steam.EResult.OK) {
80 steamBotLogger('ÐÐ²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ð¾Ð´ аккаунтом в Steam!');
81 steamFriends.setPersonaState(Steam.EPersonaState.Online);
82
83 steamWebLogOn.webLogOn(function(sessionID, newCookie) {
84 getSteamAPIKey({
85 sessionID: sessionID,
86 webCookie: newCookie
87 }, function(err, APIKey) {
88 offers.setup({
89 sessionID: sessionID,
90 webCookie: newCookie,
91 APIKey: APIKey
92 }, function(err){
93 WebSession = true;
94 globalSession = sessionID;
95 redisClient.lrange(redisChannels.tradeoffersList, 0, -1, function(err, offers){
96 offers.forEach(function(offer) {
97 checkingOffers.push(offer);
98 });
99 handleOffers();
100 });
101 steamBotLogger('Загрузка информации аккаунта в Steam!');
102 });
103 steamcommunityMobileConfirmations = new SteamcommunityMobileConfirmations({
104 steamid: config.shopBot.steamID,
105 identity_secret: config.shopBot.identitySecret,
106 device_id: device(),
107 webCookie: newCookie
108 });
109 setInterval(PhoneOk, 1500);
110 });
111 });
112 }
113});
114
115steamClient.on('servers', function(servers) {
116 fs.writeFile('servers', JSON.stringify(servers));
117});
118
119steamUser.on('updateMachineAuth', function(sentry, callback) {
120 fs.writeFileSync('sentry_shop', sentry.bytes);
121 callback({ sha_file: getSHA1(sentry.bytes) });
122});
123
124function handleOffers() {
125 offers.getOffers({
126 get_received_offers: 1,
127 active_only: 1
128 }, function(error, body) {
129 if (
130 body
131 && body.response
132 && body.response.trade_offers_received
133 ) {
134 body.response.trade_offers_received.forEach(function(offer) {
135 if (offer.trade_offer_state == 2) {
136 if(config.admins.indexOf(offer.steamid_other) != -1){
137 offers.acceptOffer({
138 tradeOfferId: offer.tradeofferid
139 }, function(error, traderesponse) {
140 if(!error) {
141 if ('undefined' != typeof traderesponse.tradeid) {
142 offers.getItems({
143 tradeId: traderesponse.tradeid
144 }, function (error, recieved_items) {
145 if (!error) {
146 var itemsForParse = [], itemsForSale = [], i = 0;
147 recieved_items.forEach(function(item){
148 itemsForParse[i++] = item.id;
149 })
150 offers.loadMyInventory({appId: 730, contextId: 2, language: 'russian'}, function(error, botItems){
151 if(!error){
152 i = 0;
153 botItems.forEach(function(item){
154 if(itemsForParse.indexOf(item.id) != -1){
155 var rarity = '', type = '';
156 var arr = item.type.split(',');
157 if (arr.length == 2) rarity = arr[1].trim();
158 if (arr.length == 3) rarity = arr[2].trim();
159 if (arr.length && arr[0] == 'Ðож') rarity = 'Тайное';
160 if (arr.length) type = arr[0];
161 var quality = item.market_name.match(/\(([^()]*)\)/);
162 if(quality != null && quality.length == 2) quality = quality[1];
163 itemsForSale[i++] = {
164 inventoryId: item.id,
165 classId: item.classid,
166 name: item.name,
167 market_hash_name: item.market_hash_name,
168 rarity: rarity,
169 quality: quality,
170 type: type
171 }
172 }
173 });
174 }
175 redisClient.rpush(redisChannels.itemsToSale, JSON.stringify(itemsForSale));
176 return;
177 });
178 }
179 return;
180 });
181 }
182 }
183 return;
184 });
185 }else{
186 offers.declineOffer({tradeOfferId: offer.tradeofferid});
187 }
188 return;
189 }
190 });
191 }
192 });
193}
194
195steamUser.on('tradeOffers', function(number) {
196 console.log('Обмены: ' + number);
197 if (number > 0) {
198 handleOffers();
199 }
200});
201
202var sendTradeOffer = function(offerJson){
203 var offer = JSON.parse(offerJson);
204 try {
205 offers.loadMyInventory({
206 appId: 730,
207 contextId: 2
208 }, function (err, items) {
209 var itemsFromMe = [];
210
211 items.forEach(function(item){
212 if(item.id == offer.itemId){
213 itemsFromMe[0] = {
214 appid: 730,
215 contextid: 2,
216 amount: item.amount,
217 assetid: item.id
218 };
219 }
220 });
221
222 if (itemsFromMe.length > 0) {
223 offers.makeOffer({
224 partnerSteamId: offer.partnerSteamId,
225 accessToken: offer.accessToken,
226 itemsFromMe: itemsFromMe,
227 itemsFromThem: [],
228 message: ''
229 }, function (err, response) {
230 if (err) {
231 console.tag('Бот магазина', 'Отправка товара').error('Ошибка при отправке обмена: ' + err);
232 setItemStatus(offer.id, 4);
233 sendProcceed = false;
234 }
235 redisClient.lrem(redisChannels.itemsToGive, 0, offerJson, function(err, data){
236 sendProcceed = false;
237 setItemStatus(offer.id, 3);
238 console.tag('Бот магазина', 'Отправка товара').log('Обмен #' + response.tradeofferid +' отправлен!');
239 redisClient.rpush(redisChannels.offersToCheck, response.tradeofferid);
240 });
241 });
242 }else{
243 console.tag('Бот магазина', 'Отправка товара').log('Предметы не найдены!');
244 setItemStatus(offer.id, 2);
245 redisClient.lrem(redisChannels.itemsToGive, 0, offerJson, function(err, data){
246 sendProcceed = false;
247 });
248 }
249 });
250
251 }catch(ex){
252 console.tag('Бот магазина').error('Ошибка отправки предмета!');
253 sendProcceed = false;
254 }
255};
256
257
258var setItemStatus = function(item, status){
259 requestify.post('http://'+config.domain+'/api/shop/setItemStatus', {
260 secretKey: config.secretKey,
261 id: item,
262 status: status
263 })
264 .then(function(response) {
265 },function(response){
266 console.tag('Бот магазина').error('Ошибка ÑтатуÑа предметов, почиÑтите Redis.');
267 setTimeout(function(){setItemStatus()}, 1000);
268 });
269}
270
271var addNewItems = function(){
272 requestify.get('http://'+config.domain+'/api/shop/newItems', {
273 secretKey: config.secretKey
274 })
275 .then(function(response) {
276 console.log('Bot+'+response);
277 var answer = JSON.parse(response.body);
278 if(answer.success){
279 itemsToSaleProcced = false;
280 }
281 },function(response){
282
283 console.tag('Бот магазина').error('Ошибка новых предметов, почиÑтите Redis.'+response);
284 setTimeout(function(){addNewItems()}, 1000);
285 });
286}
287
288var checkOfferForExpired = function(offer){
289 offers.getOffer({tradeOfferId: offer}, function (err, body){
290 if(body.response.offer){
291 var offerCheck = body.response.offer;
292 if(offerCheck.trade_offer_state == 2) {
293 var timeCheck = Math.floor(Date.now() / 1000) - offerCheck.time_created;
294 console.log(timeCheck);
295 if(timeCheck >= config.shopBot.timeForCancelOffer){
296 offers.cancelOffer({tradeOfferId: offer}, function(err, response){
297 if(!err){
298 redisClient.lrem(redisChannels.offersToCheck, 0, offer, function(err, data){
299 steamBotLogger('Обмен #' + offer + ' уÑтарел!')
300 checkProcceed = false;
301 });
302 }else{
303 checkProcceed = false;
304 }
305 });
306 }else{
307 checkProcceed = false;
308 }
309 return;
310 }else if(offerCheck.trade_offer_state == 3 || offerCheck.trade_offer_state == 7){
311 redisClient.lrem(redisChannels.offersToCheck, 0, offer, function(err, data){
312 checkProcceed = false;
313 });
314 }else{
315 checkProcceed = false;
316 }
317 }else{
318 checkProcceed = false;
319 }
320 })
321}
322
323var PhoneOk = function(){
324 steamcommunityMobileConfirmations.FetchConfirmations((function (err, confirmations){
325 if (err){
326 console.log(err);
327 return;
328 }
329 if ( ! confirmations.length){
330 return;
331 }
332 steamcommunityMobileConfirmations.AcceptConfirmation(confirmations[0], (function (err, result){
333 if (err){
334 console.log(err);
335 return;
336 }
337 console.tag('Подтверждение обмена', 'Ðутентификатор').log('уÑпешно подтвержден!');
338 }).bind(this));
339 }).bind(this));
340}
341
342var queueProceed = function(){
343 redisClient.llen(redisChannels.itemsToSale, function(err, length) {
344 if (length > 0 && !itemsToSaleProcced) {
345 console.tag('Бот магазина','Очередь').info('Ðовый предмет на продажу:' + length);
346 itemsToSaleProcced = true;
347 addNewItems();
348 }
349 });
350 console.log("im here: ");
351
352 redisClient.llen(redisChannels.itemsToGive, function(err, length) {
353 console.log("im here: len:"+length+" sendProcess: "+ sendProcceed+" WebSession: "+ WebSession);
354 if (length > 0 && !sendProcceed) {
355 console.tag('Бот магазина','Очередь').info('Отправка предмета клиенту:' + length);
356 sendProcceed = true;
357 redisClient.lindex(redisChannels.itemsToGive, 0,function (err, offerJson) {
358 sendTradeOffer(offerJson);
359 });
360 }
361 });
362 redisClient.llen(redisChannels.offersToCheck, function(err, length) {
363 if (length > 0 && !checkProcceed ) {
364 console.tag('Бот магазина','Очередь').info('Ðачало проверки обменов:' + length);
365 checkProcceed = true;
366 redisClient.lindex(redisChannels.offersToCheck, 0,function (err, offer) {
367 setTimeout(function(){
368 checkOfferForExpired(offer)
369 }, 1000 * config.shopBot.timeForCancelOffer);
370 });
371 }
372 });
373}
374var itemsToSaleProcced = false;
375var sendProcceed = false;
376var checkProcceed = false;
377setInterval(queueProceed, 1500);