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