steamutils 1.3.45 → 1.3.46

Sign up to get free protection for your applications and to get access to all the features.
package/SteamClient.js CHANGED
@@ -1,2337 +1,2356 @@
1
- import NodeSteamUser from "steam-user";
2
- import _ from "lodash";
3
- import fs from "fs";
4
- import {protoDecode, protoEncode} from "./helpers/util.js";
5
- import SteamID from "steamid";
6
- import FriendCode from "csgo-friendcode";
7
- import axios from "axios";
8
- import helpers, {loadProfos} from "./helpers/protos.js";
9
- import {fileURLToPath} from "url";
10
- import path from "path";
11
- import SteamUser from "./index.js";
12
- import {v4 as uuidv4} from 'uuid';
13
- import EFriendRelationship from "steam-user/enums/EFriendRelationship.js";
14
- import SteamCommunity from "steamcommunity";
15
- import moment from "moment-timezone";
16
- import {encode, encodeUids} from "./bufferHelpers.js";
17
-
18
- const __filename = fileURLToPath(import.meta.url);
19
- const __dirname = path.dirname(__filename);
20
-
21
- const Protos = helpers([{
22
- name: 'csgo',
23
- protos: loadProfos(__dirname + '/protos/')
24
- }])
25
-
26
- export const RANKS = {
27
- 0: 'Unranked',
28
- 1: 'Silver I',
29
- 2: 'Silver II',
30
- 3: 'Silver III',
31
- 4: 'Silver IV',
32
- 5: 'Silver Elite',
33
- 6: 'Silver Elite Master',
34
- 7: 'Gold Nova I',
35
- 8: 'Gold Nova II',
36
- 9: 'Gold Nova III',
37
- 10: 'Gold Nova Master',
38
- 11: 'Master Guardian I',
39
- 12: 'Master Guardian II',
40
- 13: 'Master Guardian Elite',
41
- 14: 'Distinguished Master Guardian',
42
- 15: 'Legendary Eagle',
43
- 16: 'Legendary Eagle Master',
44
- 17: 'Supreme Master First Class',
45
- 18: 'The Global Elite'
46
- }
47
- export const LOCS = {
48
- 20054: 'VN',
49
- 23115: 'KZ',
50
- 20041: 'IN',
51
- 20035: 'CN',
52
- 17474: 'BD',
53
- 17481: 'ID',
54
- 22861: 'MY',
55
- 18516: 'TH',
56
- 22356: 'TW',
57
- 21067: 'KR',
58
- 19272: 'HK',
59
- 18512: 'PH',
60
- 21842: 'RU',
61
- 16716: 'LA',
62
- 20558: 'NP',
63
- 18259: 'SG',
64
- 19789: 'MM',
65
- 20045: 'MN',
66
- 18251: 'KG',
67
- 18507: 'KH',
68
- 22605: 'MX',
69
- 19280: 'PK',
70
- 20301: 'HK/MO',//hongkong or macau
71
- 21333: 'Unknown',
72
- 21825: 'AU',
73
- 20034: 'Unkown',
74
- }
75
-
76
-
77
- const AppID = 730
78
- export let CSGO_VER = 13960
79
- export const FreeAppList = JSON.parse(fs.readFileSync(path.join(__dirname, 'free_packages.json'))).packages
80
-
81
- SteamUser.getAppVersion(AppID).then(function (ver) {
82
- CSGO_VER = ver
83
- })
84
-
85
- const PersonasCache = []
86
- let isSendingFriendMessages = false;
87
-
88
- function SteamClient({
89
- username,
90
- password,
91
- cookie,
92
- clientJsToken,
93
- isAutoRequestFreeLicense = true,
94
- isFakeGameScore = true,
95
- isPartyRegister = true,
96
- isAutoPlay = false,
97
- isInvisible = false,
98
- autoAcceptTradeRequest = false,
99
- autoReconnect = true,
100
- MAX_GAME_PLAY = 10,
101
- games = null
102
- }) {
103
- const steamClient = new NodeSteamUser()
104
- let prime = null
105
- let state = 'Offline'//InGame, Online, Invisible
106
- let isLogOff = false
107
- let playingBlocked = null
108
- const richPresence = {}
109
- let sendMessageTimestamp = 0
110
- let lastTimePartyRegister = 0
111
- let lastTimePartySearch = 0
112
- const ownedApps = []
113
- let logOffEvent = null
114
-
115
- const currentLobby = {
116
- lobbyID: null,
117
- timestamp: 0
118
- }
119
-
120
- const onAnyCallbacks = []
121
-
122
- const events = {
123
- user: [],
124
- loggedOn: [],
125
- csgoOnline: [],
126
- csgoClientHello: [],
127
- webSession: [],
128
- friendMessage: [],
129
- friendTyping: [],
130
- disconnected: [],
131
- error: [],
132
- playersProfile: [],
133
- partyInvite: [],
134
- friendRelationship: [],
135
- tradeOffers: [],
136
- offlineMessages: [],
137
- friendsList: [],
138
- gifts: [],
139
- playingState: [],
140
- emailInfo: [],
141
- accountLimitations: [],
142
- }
143
-
144
- const gcCallback = {}
145
-
146
- function pushGCCallback(name, cb, timeout) {
147
- if (!gcCallback[name]) {
148
- gcCallback[name] = {}
149
- }
150
- let t = null
151
- let id = uuidv4()
152
-
153
- function callback(...arg) {
154
- if (t) {
155
- clearTimeout(t)
156
- }
157
- delete gcCallback[name][id]
158
- cb?.apply(null, arg)
159
- }
160
-
161
- if (timeout) {
162
- t = setTimeout(callback, timeout)
163
- }
164
- gcCallback[name][id] = callback
165
- }
166
-
167
- function callGCCallback(name, ...arg) {
168
- if (gcCallback[name]) {
169
- for (const id in gcCallback[name]) {
170
- gcCallback[name][id]?.(...arg)
171
- }
172
- }
173
- }
174
-
175
- function callEvent(_events, data) {
176
- const eventName = Object.keys(events).find(eventName => events[eventName] === _events)
177
- eventName && onAnyCallbacks.forEach(cb => cb?.({eventName, data}))
178
-
179
- _events?.forEach?.((e) => {
180
- e.callback?.(data)
181
- e.timeout && clearTimeout(e.timeout)
182
- delete e.timeout
183
- if (e.once) {
184
- delete e.callback
185
- }
186
- })
187
- _.remove(_events, e => !e || e?.once)
188
- }
189
-
190
- function onEvent(name, callback, once, timeout) {
191
- if (!events[name]) {
192
- events[name] = []
193
- }
194
- const t = timeout ? setTimeout(callback, timeout) : null
195
- events[name].push({
196
- once,
197
- callback,
198
- timeout: t,
199
- })
200
- }
201
-
202
-
203
- function offEvent(name) {
204
- if (Array.isArray(events[name])) {
205
- for (const eventElement of events[name]) {
206
- if (eventElement.timeout) {
207
- clearTimeout(eventElement.timeout)
208
- }
209
- }
210
- }
211
-
212
- delete events[name]
213
- }
214
-
215
- function onAnyEvent(callback) {
216
- onAnyCallbacks.push(callback)
217
- }
218
-
219
- function offAllEvent() {
220
- for (const name in events) {
221
- for (const event of events[name]) {
222
- if (event.timeout) {
223
- try {
224
- clearTimeout(event.timeout)
225
- } catch (e) {
226
- }
227
- delete event.timeout
228
- }
229
- }
230
- delete events[name]
231
- }
232
- onAnyCallbacks.length = 0
233
- }
234
-
235
- const intervals = {}
236
- const intervalRandoms = {}
237
-
238
- function doSetInterval(cb, timeout, key) {
239
- const isRandom = Array.isArray(timeout)
240
- if (!key) {
241
- key = uuidv4()
242
- }
243
- if (isRandom) {
244
- if (intervalRandoms[key] !== undefined) {
245
- try {
246
- clearTimeout(intervalRandoms[key])
247
- } catch (e) {
248
- }
249
- }
250
- intervalRandoms[key] = setTimeout(function () {
251
- doSetInterval(cb, timeout, key)
252
- if (state !== 'Offline') {
253
- cb()
254
- }
255
- }, _.random(timeout[0], timeout[1]))
256
- } else {
257
- if (intervals[key] !== undefined) {
258
- try {
259
- clearInterval(intervals[key])
260
- } catch (e) {
261
- }
262
- }
263
-
264
- intervals[key] = setInterval(function () {
265
- if (state !== 'Offline') {
266
- cb()
267
- }
268
- }, timeout)
269
- }
270
-
271
- return key
272
- }
273
-
274
- function doClearIntervals() {
275
- for (const key in intervals) {
276
- clearInterval(intervals[key])
277
- delete intervals[key]
278
- }
279
- for (const key in intervalRandoms) {
280
- clearTimeout(intervalRandoms[key])
281
- delete intervalRandoms[key]
282
- }
283
- }
284
-
285
- function doClearInterval(key) {
286
- try {
287
- clearInterval(intervals[key])
288
- } catch (e) {
289
- }
290
- delete intervals[key]
291
-
292
-
293
- try {
294
- clearTimeout(intervalRandoms[key])
295
- } catch (e) {
296
- }
297
- delete intervalRandoms[key]
298
- }
299
-
300
- function getAccountInfoName() {
301
- return [steamClient?.accountInfo?.name, steamClient?._logOnDetails?.account_name].filter(Boolean).join(" - ")
302
- }
303
-
304
- function getPersonaName() {
305
- return steamClient?.accountInfo?.name
306
- }
307
-
308
- function log(...msg) {
309
- const now = moment().tz('Asia/Ho_Chi_Minh').format("DD/MM/YYYY HH:mm:ss")
310
- console.log(`[${now}] [${getAccountInfoName()}]`, ...msg)
311
- }
312
-
313
- async function getPersonas(steamIDs) {
314
- steamIDs = steamIDs.map(steamId => steamId instanceof SteamID ? steamId.getSteamID64() : steamId)
315
- const notCachesteamIDs = steamIDs.filter(id => !PersonasCache.some(p => p.id == id))
316
- const cachedPersonas = PersonasCache.filter(p => steamIDs.includes(p.id))
317
-
318
- if (notCachesteamIDs.length) {
319
- let personas = null
320
- try {
321
- personas = (await steamClient.getPersonas(notCachesteamIDs))?.personas
322
- } catch (e) {
323
- }
324
- if (!personas || !Object.keys(personas).length) {
325
- try {
326
- personas = (await steamClient.getPersonas(notCachesteamIDs))?.personas
327
- } catch (e) {
328
- }
329
- }
330
- if (!personas || !Object.keys(personas).length) {
331
- try {
332
- personas = (await steamClient.getPersonas(notCachesteamIDs))?.personas
333
- } catch (e) {
334
- }
335
- }
336
- if (personas && Object.keys(personas).length) {
337
- for (let sid64 in personas) {
338
- personas[sid64].id = sid64
339
- personas[sid64].avatar_hash = Buffer.from(personas[sid64].avatar_hash).toString("hex")
340
- PersonasCache.push(personas[sid64])
341
- cachedPersonas.push(personas[sid64])
342
- }
343
- }
344
- }
345
-
346
- while (PersonasCache.length > 500) {
347
- PersonasCache.shift()
348
- }
349
- return cachedPersonas
350
- }
351
-
352
- function sleep(ms) {
353
- return new Promise(resolve => {
354
- setTimeout(resolve, ms)
355
- })
356
- }
357
-
358
- function getCookies() {
359
- return cookie || steamClient?.webSession?.cookies?.join?.(';')
360
- }
361
-
362
- async function getCookiesWait() {
363
- return getCookies() || new Promise(resolve => {
364
- onEvent('webSession', function (webSession) {
365
- resolve(webSession?.cookies)
366
- }, true, 30000)
367
- })
368
- }
369
-
370
- async function gamePlay() {
371
- if ((Array.isArray(games) && games.length) || (games && (typeof games === "number" || typeof games === "string"))) {
372
- return gamesPlayed(games)
373
- }
374
-
375
- let ownedApps = []
376
- for (let i = 0; i < 5; i++) {
377
- ownedApps = await getUserOwnedApps()
378
- if (ownedApps?.length) {
379
- break
380
- }
381
- }
382
- if (!ownedApps?.length) {
383
- gamesPlayed(730)
384
- } else {
385
- ownedApps = ownedApps.map(({appid}) => appid)
386
- ownedApps = _.shuffle(ownedApps)
387
- ownedApps.length = Math.min(ownedApps.length, MAX_GAME_PLAY - 1)
388
- _.remove(ownedApps, app => app == 730)
389
- gamesPlayed([...ownedApps, 730])
390
- }
391
- }
392
-
393
- async function autoGamePlay() {
394
- await gamePlay()
395
- doSetInterval(gamePlay, [15 * 60000, 30 * 60000], 'autoGamePlay')
396
- }
397
-
398
- async function offAutoGamePlay() {
399
- steamClient.gamesPlayed([])
400
- doClearInterval('autoGamePlay')
401
- }
402
-
403
-
404
- async function updateAutoGamePlay() {
405
- if (isAutoPlay) {
406
- autoGamePlay()
407
- } else {
408
- offAutoGamePlay()
409
- }
410
- }
411
-
412
-
413
- /**
414
- * Get a list of lobbies (* = Unsure description could be wrong)
415
- * @param {Number} ver Game version we are searching for
416
- * @param {Boolean} apr Prime or not*
417
- * @param {Number} ark Rank multiplied by 10*
418
- * @param {Array.<Number>} grps *
419
- * @param {Number} launcher If we are using the China CSGO launcher or not*
420
- * @param {Number} game_type Game type, 8 Competitive, 10 Wingman
421
- * @returns {Promise.<Object>}
422
- */
423
- async function partySearch({
424
- prime = false,
425
- game_type = 'Competitive',
426
- rank = 'Silver Elite',
427
- timeout = 5000,
428
- } = {}) {
429
- const players = await new Promise(resolve => {
430
- steamClient.sendToGC(AppID, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Search, {}, protoEncode(Protos.csgo.CMsgGCCStrike15_v2_Party_Search, {
431
- ver: CSGO_VER,
432
- apr: prime ? 1 : 0,
433
- ark: parseInt(Object.keys(RANKS).find(k => RANKS[k] === rank)) * 10,
434
- grps: [],
435
- launcher: 0,
436
- game_type: game_type === 'Competitive' ? 8 : 10
437
- }))
438
- lastTimePartySearch = new Date().getTime()
439
- pushGCCallback('partySearch', resolve, timeout)
440
- })
441
- if (Array.isArray(players) && players.length) {
442
- const personas = await getPersonas(players.map(p => p.steamId))
443
- for (const player of players) {
444
- const persona = personas.find(p => p.id == player.steamId)
445
- if (persona) {
446
- player.player_name = persona.player_name
447
- player.avatar_hash = persona.avatar_hash
448
- }
449
- }
450
- }
451
- return players
452
- }
453
-
454
- async function createLobby() {
455
- if (!steamClient.steamID) {
456
- return
457
- }
458
-
459
- return new Promise(resolve => {
460
- const timeout = setTimeout(function () {
461
- resolve()
462
- }, 30000)
463
-
464
- steamClient._send(
465
- {
466
- msg: Protos.csgo.EMsg.k_EMsgClientMMSCreateLobby,
467
- proto: {
468
- steamid: steamClient.steamID.getSteamID64(),
469
- routing_appid: 730
470
- }
471
- },
472
- protoEncode(Protos.csgo.CMsgClientMMSCreateLobby, {
473
- app_id: 730,
474
- max_members: 1,
475
- lobby_type: 1,
476
- lobby_flags: 1
477
- }), function (payload) {
478
- clearTimeout(timeout)
479
- const result = protoDecode(Protos.csgo.CMsgClientMMSCreateLobbyResponse, payload.toBuffer())
480
- const steam_id_lobby = result.steam_id_lobby.toString();
481
- currentLobby.lobbyID = steam_id_lobby
482
- currentLobby.timestamp = new Date().getTime()
483
- resolve(steam_id_lobby)
484
- }
485
- );
486
- })
487
-
488
- // return await getHandlerResult(Protos.csgo.EMsg.k_EMsgClientMMSCreateLobbyResponse, function (payload) {
489
- // const result = protoDecode(Protos.csgo.CMsgClientMMSCreateLobbyResponse, payload.toBuffer())
490
- // return result.steam_id_lobby.toString()
491
- // })
492
-
493
- // steamClient.sendToGC(730, Protos.csgo.EMsg.k_EMsgClientMMSCreateLobby, {
494
- // steamid: steamClient.steamID,
495
- // routing_appid: 730,
496
- // }, protoEncode(Protos.csgo.CMsgClientMMSCreateLobby, {
497
- // app_id: 730,
498
- // max_members: 1,
499
- // lobby_type: 1,
500
- // lobby_flags: 1
501
- // }))
502
- }
503
-
504
- async function updateLobby(lobbyID) {
505
- if (!steamClient.steamID) {
506
- return
507
- }
508
-
509
- return new Promise(resolve => {
510
- const timeout = setTimeout(function () {
511
- resolve()
512
- }, 30000)
513
-
514
- steamClient._send(
515
- {
516
- msg: Protos.csgo.EMsg.k_EMsgClientMMSSetLobbyData,
517
- proto: {
518
- steamid: steamClient.steamID.getSteamID64(),
519
- routing_appid: 730
520
- }
521
- },
522
- protoEncode(Protos.csgo.CMsgClientMMSSetLobbyData, {
523
- app_id: 730,
524
- steam_id_lobby: lobbyID,
525
- steam_id_member: '0',
526
- max_members: 10,
527
- lobby_type: 1,
528
- lobby_flags: 1,
529
- metadata: encode({
530
- 'game:ark': '0',
531
- // Country/Message
532
- 'game:loc': '',
533
- 'game:mapgroupname': 'mg_de_mirage',
534
- 'game:mode': 'competitive',
535
- 'game:prime': '1',
536
- 'game:type': 'classic',
537
- 'members:numPlayers': '1',
538
- 'options:action': 'custommatch',
539
- 'options:anytypemode': '0',
540
- 'system:access': 'private',
541
- 'system:network': 'LIVE',
542
- uids: [steamClient.steamID]
543
- }, [0x00, 0x00], [0x08], {uids: encodeUids}).toBuffer()
544
- }),
545
- function (payload) {
546
- clearTimeout(timeout)
547
- const result = protoDecode(Protos.csgo.CMsgClientMMSSetLobbyDataResponse, payload.toBuffer())
548
- const steam_id_lobby = result.steam_id_lobby.toString();
549
- currentLobby.lobbyID = steam_id_lobby
550
- currentLobby.timestamp = new Date().getTime()
551
- resolve(steam_id_lobby)
552
- }
553
- );
554
- })
555
-
556
- // return await getHandlerResult(Protos.csgo.EMsg.k_EMsgClientMMSSetLobbyDataResponse, function (payload) {
557
- // const result = protoDecode(Protos.csgo.CMsgClientMMSSetLobbyDataResponse, payload.toBuffer())
558
- // return result.steam_id_lobby.toString()
559
- // })
560
- }
561
-
562
- async function invite2Lobby(lobbyID, steamId) {
563
- if (!steamClient.steamID) {
564
- return
565
- }
566
-
567
- steamClient._send(
568
- {
569
- msg: Protos.csgo.EMsg.k_EMsgClientMMSInviteToLobby,
570
- proto: {
571
- steamid: steamClient.steamID.getSteamID64(),
572
- routing_appid: 730
573
- }
574
- },
575
- protoEncode(Protos.csgo.CMsgClientMMSInviteToLobby, {
576
- app_id: 730,
577
- steam_id_lobby: lobbyID,
578
- steam_id_user_invited: steamId,
579
- }));
580
-
581
- // lobbyID = new SteamID(lobbyID).accountid;
582
-
583
- // Protos.csgo.EMsg.k_EMsgGCHInviteUserToLobby
584
- // Protos.csgo.EMsg.k_EMsgClientMMSInviteToLobby
585
- // steamClient.sendToGC(730, Protos.csgo.EMsg.k_EMsgClientMMSInviteToLobby, {}, protoEncode(Protos.csgo.CMsgClientMMSInviteToLobby, {
586
- // app_id: 730,
587
- // steam_id_lobby: lobbyID,
588
- // steam_id_user_invited: accountid,
589
- // }), function (...args) {
590
- // console.log("invite2Lobby response", args)
591
- // })
592
- }
593
-
594
- async function createThenInvite2Lobby(steamIds, onInvite) {
595
- if (!steamClient.steamID) {
596
- return
597
- }
598
-
599
- if (!Array.isArray(steamIds)) {
600
- steamIds = [steamIds]
601
- }
602
-
603
- let lobbyID = null
604
- if (currentLobby.lobbyID && currentLobby.timestamp > new Date().getTime() - 30000) {//30 seconds
605
- lobbyID = currentLobby.lobbyID
606
- } else {
607
- lobbyID = await createLobby();
608
- lobbyID = await updateLobby(lobbyID)
609
- }
610
-
611
- for (const steamId of steamIds) {
612
- onInvite?.(lobbyID, steamId)
613
- await invite2Lobby(lobbyID, steamId)
614
- }
615
-
616
- return lobbyID
617
- }
618
-
619
-
620
- async function getLobbyData(lobbyID) {
621
- if (!steamClient.steamID) {
622
- return
623
- }
624
-
625
- return new Promise(resolve => {
626
- const timeout = setTimeout(function () {
627
- resolve()
628
- }, 30000)
629
-
630
- steamClient._send(
631
- {
632
- msg: Protos.csgo.EMsg.k_EMsgClientMMSGetLobbyData,
633
- proto: {
634
- steamid: steamClient.steamID.getSteamID64(),
635
- routing_appid: 730
636
- }
637
- },
638
- protoEncode(Protos.csgo.CMsgClientMMSGetLobbyData, {
639
- app_id: 730,
640
- steam_id_lobby: lobbyID.toString(),
641
- }),
642
- function (payload) {
643
- clearTimeout(timeout)
644
- const result = protoDecode(Protos.csgo.CMsgClientMMSLobbyData, payload.toBuffer())
645
- result.steam_id_lobby = result.steam_id_lobby.toString()
646
- resolve(result)
647
- }
648
- );
649
- })
650
- }
651
-
652
-
653
- async function joinLobby(lobbyID) {
654
- log("joinLobby", lobbyID);//SteamID.fromIndividualAccountID(lobbyId).accountid
655
-
656
- steamClient._send(
657
- {
658
- msg: Protos.csgo.EMsg.k_EMsgClientMMSJoinLobby,
659
- proto: {
660
- steamid: steamClient.steamID.getSteamID64(),
661
- routing_appid: 730
662
- }
663
- },//CMsgClientMMSUserJoinedLobby CMsgClientMMSJoinLobby
664
- protoEncode(Protos.csgo.CMsgClientMMSJoinLobby, {
665
- app_id: 730,
666
- steam_id_lobby: lobbyID,
667
- persona_name: steamClient.accountInfo.name,
668
- }),
669
- function (payload) {
670
- const result = protoDecode(Protos.csgo.CMsgClientMMSJoinLobbyResponse, payload.toBuffer())
671
- result.steam_id_lobby = result.steam_id_lobby.toString()
672
- result.steam_id_owner = result.steam_id_owner.toString()
673
- console.log(result);
674
- const resultExample = {
675
- members: [],
676
- app_id: 730,
677
- steam_id_lobby: "3641224920",
678
- chat_room_enter_response: 2,
679
- max_members: 0,
680
- lobby_type: 0,
681
- lobby_flags: 0,
682
- steam_id_owner: "0",
683
- metadata: null//Buffer
684
- }
685
- }
686
- )
687
- }
688
-
689
- async function sendHello() {
690
- steamClient.sendToGC(AppID, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello, {}, Buffer.alloc(0))
691
- steamClient.sendToGC(AppID, Protos.csgo.EGCBaseClientMsg.k_EMsgGCClientHello, {}, Buffer.alloc(0))
692
- }
693
-
694
- async function requestCoPlays() {
695
- return new Promise(resolve => {
696
- steamClient.sendToGC(AppID, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Account_RequestCoPlays, {}, Buffer.alloc(0))
697
- pushGCCallback('RequestCoPlays', resolve, 30000)
698
- })
699
- }
700
-
701
-
702
- function bindEvent() {
703
- const _events = {
704
- async disconnected(eresult, msg) {
705
- state = 'Offline'
706
- log('disconnected', eresult, msg)
707
-
708
- callEvent(events.disconnected, {eresult, msg})
709
-
710
- if (['ServiceUnavailable', 'NoConnection'].includes(msg) && autoReconnect && !isLogOff) {
711
- async function relogin(retry) {
712
- if (isLogOff) {
713
- console.error("Cannot relogin (logoff)")
714
- return false
715
- } else if (retry <= 0) {
716
- console.error("Cannot relogin")
717
- return false
718
- } else {
719
- const isSuccess = await login(true)
720
- if (isSuccess) {
721
- const loggedOnResponse = await new Promise(resolve => {
722
- onEvent('loggedOn', resolve, true, 180000)
723
- })
724
- if (loggedOnResponse) {
725
- console.log("Relogin success")
726
- return true
727
- } else {
728
- const isLogOff = await new Promise((resolve, reject) => {
729
- logOffEvent = resolve
730
- setTimeout(resolve, 120000)
731
- })
732
- logOffEvent = null
733
- if (isLogOff === true) {
734
- return false
735
- }
736
- return await relogin(retry - 1)
737
- }
738
- } else {
739
- const isLogOff = await new Promise((resolve, reject) => {
740
- logOffEvent = resolve
741
- setTimeout(resolve, 120000)
742
- })
743
- logOffEvent = null
744
- if (isLogOff === true) {
745
- return false
746
- }
747
- return await relogin(retry - 1)
748
- }
749
- }
750
- }
751
-
752
- const isLogOff = await new Promise((resolve, reject) => {
753
- logOffEvent = resolve
754
- setTimeout(resolve, 60000)
755
- })
756
- logOffEvent = null
757
- if (isLogOff === true) {
758
- offAllEvent()
759
- doClearIntervals()
760
- } else {
761
- const isSuccess = await relogin(50)
762
- if (!isSuccess) {
763
- offAllEvent()
764
- doClearIntervals()
765
- }
766
- }
767
- } else {
768
- offAllEvent()
769
- doClearIntervals()
770
- }
771
- },
772
- async error(e) {
773
- let errorStr = ``
774
- switch (e.eresult) {
775
- case 5:
776
- errorStr = `Invalid Password`
777
- break
778
- case 6:
779
- case 34:
780
- errorStr = `Logged In Elsewhere`
781
- break
782
- case 84:
783
- errorStr = `Rate Limit Exceeded`
784
- break
785
- case 65:
786
- errorStr = `steam guard is invalid`
787
- break
788
- default:
789
- errorStr = `Unknown: ${e.eresult}`
790
- break
791
- }
792
- log(`error [isLogOff: ${isLogOff}]`, e?.message)
793
- doClearIntervals()
794
- callEvent(events.error, {eresult: e.eresult, msg: e.message, error: errorStr})
795
- },
796
- async webSession(sessionID, cookies) {
797
- const webSession = {sessionID, cookies};
798
- steamClient.webSession = webSession
799
- callEvent(events.webSession, webSession)
800
- },
801
- async receivedFromGC(appid, msgType, payload) {
802
- const key = getECsgoGCMsgKey(msgType)
803
- switch (msgType) {
804
- case Protos.csgo.EMsg.k_EMsgClientChatInvite: {
805
- log(payload)
806
- break
807
- }
808
- case Protos.csgo.ECsgoGCMsg.k_EMsgClientMMSJoinLobbyResponse: {
809
- const msg = protoDecode(Protos.csgo.CMsgClientMMSJoinLobbyResponse, payload);
810
- log(msg)
811
- break
812
- }
813
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Invite: {
814
- const msg = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_Party_Invite, payload);
815
- const sid64 = SteamID.fromIndividualAccountID(msg.accountid).getSteamID64();
816
- if (events.partyInvite?.length) {
817
- const personas = await getPersonas([sid64]);
818
- const player_name = personas.find(p => p.id == sid64)?.player_name
819
- if (player_name === undefined) {
820
- log(sid64, personas);
821
- }
822
- callEvent(events.partyInvite, {player_name, steamId: sid64, lobbyId: msg.lobbyid})
823
- }
824
- // log(player_name, `https://steamcommunity.com/profiles/${sid64}`);
825
- // joinLobby(msg.lobbyid, msg.accountid)
826
- break
827
- }
828
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Account_RequestCoPlays: {
829
- const msg = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_Account_RequestCoPlays, payload);
830
- const personas = msg.players.map(p => SteamID.fromIndividualAccountID(p.accountid));
831
- callGCCallback('RequestCoPlays', personas)
832
- break
833
- }
834
- case Protos.csgo.EGCBaseClientMsg.k_EMsgGCClientWelcome: {
835
- prime = false
836
- const CMsgClientWelcome = protoDecode(Protos.csgo.CMsgClientWelcome, payload);
837
- const obj = {}
838
- for (const outofdate_cache of CMsgClientWelcome.outofdate_subscribed_caches) {
839
- for (const cache_object of outofdate_cache.objects) {
840
- for (const object_data of cache_object.object_data) {
841
- switch (cache_object.type_id) {
842
- case 1: {
843
- const result = protoDecode(Protos.csgo.CSOEconItem, object_data);
844
- result.id = result.id.toNumber()
845
- break
846
- }
847
- case 2: {
848
- const result = protoDecode(Protos.csgo.CSOPersonaDataPublic, object_data);
849
- obj.PersonaDataPublic = result
850
- const example = {
851
- player_level: 4,
852
- commendation: {
853
- cmd_friendly: 149,
854
- cmd_teaching: 108,
855
- cmd_leader: 115
856
- },
857
- elevated_state: true
858
- }
859
- break
860
- }
861
- case 5: {
862
- const result = protoDecode(Protos.csgo.CSOItemRecipe, object_data);
863
- break
864
- }
865
- case 7: {
866
- const CSOEconGameAccountClient = protoDecode(Protos.csgo.CSOEconGameAccountClient, object_data);
867
- const CSOEconGameAccountClientExample = {
868
- additional_backpack_slots: 0,
869
- bonus_xp_timestamp_refresh: 1688518800,//Wednesday 1:00:00 AM every week
870
- bonus_xp_usedflags: 19,
871
- elevated_state: 5,
872
- elevated_timestamp: 5
873
- } //1688518800
874
- if ((CSOEconGameAccountClient.bonus_xp_usedflags & 16) != 0) { // EXPBonusFlag::PrestigeEarned
875
- prime = true
876
- CSOEconGameAccountClient.prime = true
877
- }
878
- if (CSOEconGameAccountClient.elevated_state === 5) { // bought prime
879
- prime = true
880
- CSOEconGameAccountClient.prime = true
881
- }
882
- obj.GameAccountClient = CSOEconGameAccountClient
883
- break
884
- }
885
-
886
- case 35: {
887
- // const result =protoDecode(Protos.csgo.CSOSelectedItemPreset, object_data);
888
- break
889
- }
890
-
891
- case 36: {
892
- // const result =protoDecode(Protos.csgo.CSOEconItemPresetInstance, object_data);
893
- break
894
- }
895
- case 38: {
896
- const result = protoDecode(Protos.csgo.CSOEconItemDropRateBonus, object_data);
897
- break
898
- }
899
- case 39: {
900
- const result = protoDecode(Protos.csgo.CSOEconItemLeagueViewPass, object_data);
901
- break
902
- }
903
- case 40: {
904
- const result = protoDecode(Protos.csgo.CSOEconItemEventTicket, object_data);
905
- break
906
- }
907
- case 41: {
908
- const result = protoDecode(Protos.csgo.CSOAccountSeasonalOperation, object_data);
909
- break
910
- }
911
- case 42: {
912
- // const result =protoDecode(Protos.csgo.CSOEconItemTournamentPassport, object_data);
913
- break
914
- }
915
- case 43: {
916
- const result = protoDecode(Protos.csgo.CSOEconDefaultEquippedDefinitionInstanceClient, object_data);
917
- const example = {
918
- account_id: 1080136620,
919
- item_definition: 61,
920
- class_id: 3,
921
- slot_id: 2
922
- }
923
- break
924
- }
925
- case 45: {
926
- const result = protoDecode(Protos.csgo.CSOEconCoupon, object_data);
927
- break
928
- }
929
- case 46: {
930
- const result = protoDecode(Protos.csgo.CSOQuestProgress, object_data);
931
- break
932
- }
933
- case 4: {
934
- const result = protoDecode(Protos.csgo.CSOAccountItemPersonalStore, object_data);
935
- result.generation_time = result.generation_time * 1000
936
- if (Array.isArray(result.items)) {
937
- result.items = result.items.map(item => item.toNumber())
938
- }
939
- obj.personalStore = result
940
- break
941
- }
942
-
943
- default: {
944
- log("cache_object.type_id", cache_object.type_id);
945
- }
946
- }
947
- }
948
-
949
- }
950
- }
951
- callEvent(events.csgoOnline, obj)
952
-
953
- if (isPartyRegister) {
954
- partyRegister()
955
- doSetInterval(function () {
956
- partyRegister()
957
- }, [60000, 120000], 'autoPartyRegister')
958
- }
959
- break
960
- }
961
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchmakingGC2ClientUpdate: {
962
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_MatchmakingGC2ClientUpdate, payload)
963
- break
964
- }
965
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_GC2ClientGlobalStats: {
966
- const result = protoDecode(Protos.csgo.CMsgClientUGSGetGlobalStatsResponse, payload)
967
- break
968
- }
969
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientReportPlayer: {
970
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientReportPlayer, payload)
971
- break
972
- }
973
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_GC2ClientTextMsg: {
974
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_GC2ClientTextMsg, payload)
975
- break
976
- }
977
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello: {
978
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_MatchmakingGC2ClientHello, payload)
979
- const example = {
980
- my_current_event_teams: [],
981
- my_current_event_stages: [],
982
- rankings: [],
983
- account_id: 1080136620,
984
- ongoingmatch: null,
985
- global_stats: {
986
- search_statistics: [
987
- {
988
- game_type: 520,
989
- search_time_avg: 0,
990
- players_searching: 5141
991
- },
992
- {
993
- game_type: 32776,
994
- search_time_avg: 0,
995
- players_searching: 6561
996
- },
997
- ],
998
- players_online: 617207,
999
- servers_online: 230638,
1000
- players_searching: 13550,
1001
- servers_available: 126352,
1002
- ongoing_matches: 23264,
1003
- search_time_avg: 95993,
1004
- main_post_url: "*XA=https://blast.tv/live*XT=https://www.twitch.tv/blastpremier*XB=https://live.bilibili.com/35*XG=playcast://https://gotv.blast.tv/major-a*T=SGTAB*L=2@https://steamcommunity.com/broadcast/watch/76561199492362089",
1005
- required_appid_version: 13879,
1006
- pricesheet_version: 1688084844,
1007
- twitch_streams_version: 2,
1008
- active_tournament_eventid: 21,
1009
- active_survey_id: 0,
1010
- rtime32_cur: 0,
1011
- rtime32_event_start: 0
1012
- },
1013
- penalty_seconds: 0,
1014
- penalty_reason: 0,
1015
- vac_banned: 0,
1016
- ranking: {
1017
- account_id: 1080136620,
1018
- rank_id: 10,
1019
- wins: 209,
1020
- rank_change: 0,
1021
- rank_type_id: 6,
1022
- tv_control: 0
1023
- },
1024
- commendation: {
1025
- cmd_friendly: 149,
1026
- cmd_teaching: 108,
1027
- cmd_leader: 115
1028
- },
1029
- medals: null,
1030
- my_current_event: null,
1031
- my_current_team: null,
1032
- survey_vote: 0,
1033
- activity: null,
1034
- player_level: 4,
1035
- player_cur_xp: 327684501,
1036
- player_xp_bonus_flags: 0
1037
- }
1038
- if (result?.global_stats?.required_appid_version && (!CSGO_VER || result.global_stats.required_appid_version > CSGO_VER)) {
1039
- CSGO_VER = result.global_stats.required_appid_version
1040
- }
1041
- callEvent(events.csgoClientHello, result)
1042
- break
1043
- }
1044
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientReportResponse: {
1045
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientReportResponse, payload)
1046
- break
1047
- }
1048
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientCommendPlayerQueryResponse: {
1049
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientCommendPlayer, payload)
1050
- break
1051
- }
1052
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_PlayerOverwatchCaseAssignment: {
1053
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_PlayerOverwatchCaseAssignment, payload)
1054
- break
1055
- }
1056
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchList: {
1057
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_MatchList, payload)
1058
- break
1059
- }
1060
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_GetEventFavorites_Response: {
1061
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_GetEventFavorites_Response, payload)
1062
- break
1063
- }
1064
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_StartAgreementSessionInGame: {
1065
-
1066
- break
1067
- }
1068
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_ClientDeepStats: {
1069
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_ClientDeepStats, payload)
1070
- break
1071
- }
1072
- case Protos.csgo.EGCBaseClientMsg.k_EMsgGCClientConnectionStatus: {
1073
- const result = protoDecode(Protos.csgo.CMsgConnectionStatus, payload)
1074
- break
1075
- }
1076
- case Protos.csgo.EGCItemMsg.k_EMsgGCStoreGetUserDataResponse: {
1077
- const result = protoDecode(Protos.csgo.CMsgStoreGetUserDataResponse, payload)
1078
- break
1079
- }
1080
- case Protos.csgo.EGCItemMsg.k_EMsgGCStorePurchaseFinalizeResponse: {
1081
- const result = protoDecode(Protos.csgo.CMsgGCStorePurchaseFinalizeResponse, payload)
1082
- break
1083
- }
1084
- case Protos.csgo.EGCItemMsg.k_EMsgGCStorePurchaseCancelResponse: {
1085
- const result = protoDecode(Protos.csgo.CMsgGCStorePurchaseCancelResponse, payload)
1086
- break
1087
- }
1088
- case Protos.csgo.EGCItemMsg.k_EMsgGCStorePurchaseInitResponse: {
1089
- const result = protoDecode(Protos.csgo.CMsgGCStorePurchaseInitResponse, payload)
1090
- break
1091
- }
1092
- case Protos.csgo.EMsg.k_EMsgClientMMSCreateLobbyResponse: {
1093
- const result = protoDecode(Protos.csgo.CMsgClientMMSCreateLobbyResponse, payload)
1094
- console.log("k_EMsgClientMMSCreateLobbyResponse", result);
1095
- break
1096
- }
1097
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientGCRankUpdate: {
1098
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientGCRankUpdate, payload)
1099
- break
1100
- }
1101
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Search: {
1102
- const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_Party_SearchResults, payload)
1103
- const entries = _.uniqBy(result.entries, 'id')
1104
- //{
1105
- // id: 144900402,
1106
- // grp: 0,
1107
- // game_type: 8,
1108
- // apr: 1,
1109
- // ark: 17,
1110
- // loc: 20041,
1111
- // accountid: 0
1112
- // }
1113
-
1114
-
1115
- //{
1116
- // id: "76561199265943339",
1117
- // rich_presence: [],
1118
- // persona_state: null,
1119
- // game_played_app_id: null,
1120
- // game_server_ip: null,
1121
- // game_server_port: null,
1122
- // persona_state_flags: null,
1123
- // online_session_instances: null,
1124
- // persona_set_by_user: null,
1125
- // player_name: "杀人不见血",
1126
- // query_port: null,
1127
- // steamid_source: null,
1128
- // avatar_hash: "33994e26f1fe7e2093f8c7dee66c1ac91531050d",
1129
- // last_logoff: null,
1130
- // last_logon: null,
1131
- // last_seen_online: null,
1132
- // clan_rank: null,
1133
- // game_name: null,
1134
- // gameid: null,
1135
- // game_data_blob: null,
1136
- // clan_data: null,
1137
- // clan_tag: null,
1138
- // broadcast_id: null,
1139
- // game_lobby_id: null,
1140
- // watching_broadcast_accountid: null,
1141
- // watching_broadcast_appid: null,
1142
- // watching_broadcast_viewers: null,
1143
- // watching_broadcast_title: null,
1144
- // is_community_banned: null,
1145
- // player_name_pending_review: null,
1146
- // avatar_pending_review: null,
1147
- // avatar_url_icon: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/33/33994e26f1fe7e2093f8c7dee66c1ac91531050d.jpg",
1148
- // avatar_url_medium: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/33/33994e26f1fe7e2093f8c7dee66c1ac91531050d_medium.jpg",
1149
- // avatar_url_full: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/33/33994e26f1fe7e2093f8c7dee66c1ac91531050d_full.jpg"
1150
- // }
1151
-
1152
- const players = []
1153
- for (const player of entries) {
1154
- try {
1155
- const prime = player.apr === 1 ? 'PRIME' : 'NON-PRIME'
1156
- const loc = LOCS[player.loc] || player.loc
1157
- const steamId = SteamID.fromIndividualAccountID(player.id).getSteamID64()
1158
- const friendCode = FriendCode.encode(steamId)
1159
-
1160
- // if ((LOCS[player.loc] == 'VN' || !LOCS[player.loc])) {
1161
- players.push({
1162
- prime,
1163
- rank: RANKS[player.ark] !== undefined ? RANKS[player.ark] : player.ark,
1164
- loc,
1165
- steamId,
1166
- friendCode,
1167
- })
1168
- // }
1169
- } catch (e) {
1170
- }
1171
- }
1172
-
1173
- callGCCallback('partySearch', players)
1174
- break
1175
- }
1176
- case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_PlayersProfile: {
1177
- let data = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_PlayersProfile, payload)?.account_profiles
1178
- const dataExample = [{
1179
- my_current_event_teams: [],
1180
- my_current_event_stages: [],
1181
- rankings: [{
1182
- account_id: 1225887169,
1183
- rank_id: 0,
1184
- wins: 6,
1185
- rank_change: 0,
1186
- rank_type_id: 7,
1187
- tv_control: 0
1188
- }, {
1189
- account_id: 1225887169,
1190
- rank_id: 0,
1191
- wins: 0,
1192
- rank_change: 0,
1193
- rank_type_id: 10,
1194
- tv_control: 0
1195
- }],
1196
- account_id: 1225887169,
1197
- ongoingmatch: null,
1198
- global_stats: null,
1199
- penalty_seconds: 0,
1200
- penalty_reason: 0,
1201
- vac_banned: 0,
1202
- ranking: {
1203
- account_id: 1225887169,
1204
- rank_id: 8,
1205
- wins: 469,
1206
- rank_change: 0,
1207
- rank_type_id: 6,
1208
- tv_control: 0
1209
- },
1210
- commendation: {
1211
- cmd_friendly: 51, cmd_teaching: 40, cmd_leader: 40
1212
- },
1213
- medals: {
1214
- display_items_defidx: [4819, 4737], featured_display_item_defidx: 4819
1215
- },
1216
- my_current_event: null,
1217
- my_current_team: null,
1218
- survey_vote: 0,
1219
- activity: null,
1220
- player_level: 32,
1221
- player_cur_xp: 327682846,
1222
- player_xp_bonus_flags: 0
1223
- }]
1224
-
1225
- const player = data?.[0];
1226
- if (player) {
1227
- player.prime = !!(player.ranking?.account_id || player.player_level || player.player_cur_xp)
1228
- player.steamId = SteamID.fromIndividualAccountID(player.account_id).getSteamID64()
1229
- callGCCallback('PlayersProfile_' + player.account_id, player)
1230
- }
1231
- callEvent(events.playersProfile, player)
1232
- break
1233
- }
1234
- default:
1235
- log(`receivedFromGC ${msgType} ${key}`)
1236
- const results = Object.values(Protos.csgo).map(function (p) {
1237
- try {
1238
- return protoDecode(p, payload)
1239
- } catch (e) {
1240
- }
1241
- }).filter(function (result) {
1242
- return result && Object.keys(result).length
1243
- })
1244
- log(key, results)
1245
- }
1246
- },
1247
- async loggedOn(loggedOnResponse) {
1248
- callEvent(events.loggedOn, loggedOnResponse)
1249
- updateInvisible()
1250
- updateAutoRequestFreeLicense()
1251
- updateAutoGamePlay()
1252
- },
1253
- async user(steamId, data) {
1254
- callEvent(events.user, {steamId: steamId.getSteamID64(), data})
1255
- const dataExample = {
1256
- rich_presence: [
1257
- {
1258
- key: "status",
1259
- value: "Competitive Mirage [ 3 : 6 ]"
1260
- },
1261
- {
1262
- key: "version",
1263
- value: "13875"
1264
- },
1265
- {
1266
- key: "game:state",
1267
- value: "game"
1268
- },
1269
- {
1270
- key: "steam_display",
1271
- value: "#display_GameKnownMapScore"
1272
- },
1273
- {
1274
- key: "game:mode",
1275
- value: "competitive"
1276
- },
1277
- {
1278
- key: "game:mapgroupname",
1279
- value: "mg_de_mirage"
1280
- },
1281
- {
1282
- key: "game:map",
1283
- value: "de_mirage"
1284
- },
1285
- {
1286
- key: "game:server",
1287
- value: "kv"
1288
- },
1289
- {
1290
- key: "watch",
1291
- value: "1"
1292
- },
1293
- {
1294
- key: "steam_player_group",
1295
- value: "2134948645"
1296
- },
1297
- {
1298
- key: "game:score",
1299
- value: "[ 3 : 6 ]"
1300
- }
1301
- ],
1302
- friendid: "76561199405834425",
1303
- persona_state: 1,
1304
- game_played_app_id: 730,
1305
- game_server_ip: null,
1306
- game_server_port: null,
1307
- persona_state_flags: 1,
1308
- online_session_instances: 1,
1309
- persona_set_by_user: null,
1310
- player_name: "quỷ súng",
1311
- query_port: null,
1312
- steamid_source: "0",
1313
- avatar_hash: {
1314
- type: "Buffer",
1315
- data: [
1316
- 23,
1317
- 163,
1318
- 216,
1319
- 209,
1320
- 236,
1321
- 179,
1322
- 73,
1323
- 228,
1324
- 225,
1325
- 30,
1326
- 48,
1327
- 190,
1328
- 192,
1329
- 170,
1330
- 177,
1331
- 246,
1332
- 139,
1333
- 71,
1334
- 122,
1335
- 205
1336
- ]
1337
- },
1338
- last_logoff: 1683950268,
1339
- last_logon: 1683950281,
1340
- last_seen_online: 1683950268,
1341
- clan_rank: null,
1342
- game_name: "",
1343
- gameid: "730",
1344
- game_data_blob: {
1345
- type: "Buffer",
1346
- data: []
1347
- },
1348
- clan_data: null,
1349
- clan_tag: null,
1350
- broadcast_id: "0",
1351
- game_lobby_id: "0",
1352
- watching_broadcast_accountid: null,
1353
- watching_broadcast_appid: null,
1354
- watching_broadcast_viewers: null,
1355
- watching_broadcast_title: null,
1356
- is_community_banned: null,
1357
- player_name_pending_review: null,
1358
- avatar_pending_review: null
1359
- }
1360
- },
1361
- async playingState(playing_blocked, playing_app) {
1362
- playingBlocked = playing_blocked
1363
- if (playing_app === 0) {
1364
- playing_app = null
1365
- }
1366
- if (playing_blocked) {//true, false
1367
- console.log("Playing else where")
1368
- }
1369
- log('playingState', playing_blocked, playing_app);
1370
- callEvent(events.playingState, {playing_blocked, playing_app})
1371
- },
1372
- async friendRelationship(sid, relationship, previousRelationship) {
1373
- callEvent(events.friendRelationship, {
1374
- steamId: sid.getSteamID64(),
1375
- relationship,
1376
- previousRelationship
1377
- })
1378
- switch (relationship) {
1379
- case EFriendRelationship.None: {
1380
- //we got unfriended.
1381
- break
1382
- }
1383
- case EFriendRelationship.RequestRecipient: {
1384
- //we got invited as a friend
1385
- break
1386
- }
1387
- case EFriendRelationship.Friend: {
1388
- //we got added as a friend
1389
- break
1390
- }
1391
- }
1392
- },
1393
- async tradeOffers(count) {
1394
- callEvent(events.tradeOffers, count)
1395
- },
1396
- async offlineMessages(count, friends) {
1397
- callEvent(events.offlineMessages, {count, steamIdList: friends})
1398
- },
1399
- async tradeRequest(steamID, respond) {
1400
- if (autoAcceptTradeRequest) {
1401
- log(`Incoming trade request from ${steamID.getSteam3RenderedID()}, accepting`);
1402
- respond(true);
1403
- } else {
1404
- log(`Incoming trade request from ${steamID.getSteam3RenderedID()}, wating`);
1405
- }
1406
- },
1407
- async friendsList() {
1408
- callEvent(events.friendsList, getFriendList())
1409
- },
1410
- async gifts(gid, packageid, TimeCreated, TimeExpiration, TimeSent, TimeAcked, TimeRedeemed, RecipientAddress, SenderAddress, SenderName) {
1411
- callEvent(events.gifts, {
1412
- gid,
1413
- packageid,
1414
- TimeCreated,
1415
- TimeExpiration,
1416
- TimeSent,
1417
- TimeAcked,
1418
- TimeRedeemed,
1419
- RecipientAddress,
1420
- SenderAddress,
1421
- SenderName
1422
- })
1423
- },
1424
- async emailInfo(address, validated) {
1425
- callEvent(events.emailInfo, {address, validated})
1426
- },
1427
- async appLaunched() {
1428
- setTimeout(function () {
1429
- state = getPlayingAppIds().length ? 'InGame' : (isInvisible ? "Invisible" : 'Online')
1430
- }, 1000)
1431
- },
1432
- async appQuit() {
1433
- setTimeout(function () {
1434
- state = getPlayingAppIds().length ? 'InGame' : (isInvisible ? "Invisible" : 'Online')
1435
- }, 1000)
1436
- },
1437
- async accountLimitations(bis_limited_account, bis_community_banned, bis_locked_account, bis_limited_account_allowed_to_invite_friends) {
1438
- callEvent(events.accountLimitations, {
1439
- limited: bis_limited_account,
1440
- communityBanned: bis_community_banned,
1441
- locked: bis_locked_account,
1442
- canInviteFriends: bis_limited_account_allowed_to_invite_friends
1443
- })
1444
- },
1445
- }
1446
-
1447
- const _chatEvents = {
1448
- async friendMessage(data) {
1449
- if (!data) return
1450
- data.message_no_bbcode = data.message_no_bbcode?.replaceAll(`ː`, `:`)
1451
- data.message = data.message?.replaceAll(`ː`, `:`)
1452
- const example = {
1453
- steamid_friend: {
1454
- universe: 1,
1455
- type: 1,
1456
- instance: 1,
1457
- accountid: 1080136620
1458
- },
1459
- chat_entry_type: 1,
1460
- from_limited_account: false,
1461
- message: "xxx",
1462
- ordinal: 0,
1463
- local_echo: false,
1464
- message_no_bbcode: "xxx",
1465
- low_priority: false,
1466
- server_timestamp: "2023-05-14T09:26:25.000Z",
1467
- message_bbcode_parsed: [
1468
- "xxx"
1469
- ]
1470
- }
1471
- const timestamp = new Date(data.server_timestamp).getTime()
1472
- const steamId = data.steamid_friend.getSteamID64()
1473
- const invite = [`Invited you to play a game!`, `Đã mời bạn chơi một trò chơi!`].includes(data.message_no_bbcode || data.message)
1474
- const emotion = (data.message_no_bbcode || '').split(' ').find(m => m.startsWith(':') && m.endsWith(':'))
1475
-
1476
- callEvent(events.friendMessage, {
1477
- ...data,
1478
- message: data.message_no_bbcode,
1479
- invite,
1480
- steamId,
1481
- timestamp,
1482
- emotion,
1483
- })
1484
- },
1485
- async friendTyping(steamId, message) {
1486
- callEvent(events.friendTyping, {
1487
- steamId, message
1488
- })
1489
- },
1490
- }
1491
-
1492
- // steamClient.on('lobbyInvite', (inviterID, lobbyID ) => {
1493
- // joinLobby(lobbyID)
1494
- // })
1495
-
1496
- // steamClient.on('debug', (msg) => {
1497
- // if (!["ClientPersonaState","ClientClanState"].some(c => msg.includes(c))) {
1498
- // if(msg.startsWith("Received")){
1499
- // console.log(`------- ${msg}`)
1500
- // } else {
1501
- // console.log(msg)
1502
- // }
1503
- // }
1504
- // })
1505
-
1506
-
1507
- function getECsgoGCMsgKey(_key) {
1508
- for (let key in Protos.csgo.ECsgoGCMsg) {
1509
- if (Protos.csgo.ECsgoGCMsg[key] == _key) {
1510
- return key
1511
- }
1512
- }
1513
- for (let key in Protos.csgo.EGCBaseClientMsg) {
1514
- if (Protos.csgo.EGCBaseClientMsg[key] == _key) {
1515
- return key
1516
- }
1517
- }
1518
- for (let key in Protos.csgo.EMsg) {
1519
- if (Protos.csgo.EMsg[key] == _key) {
1520
- return key
1521
- }
1522
- }
1523
- for (let key in Protos.csgo.EGCItemMsg) {
1524
- if (Protos.csgo.EGCItemMsg[key] == _key) {
1525
- return key
1526
- }
1527
- }
1528
- }
1529
-
1530
-
1531
- for (const [name, _event] of Object.entries(_events)) {
1532
- steamClient.on(name, _event)
1533
- }
1534
-
1535
- for (const [name, _event] of Object.entries(_chatEvents)) {
1536
- steamClient.chat.on(name, _event)
1537
- }
1538
- }
1539
-
1540
- function getHandlerResult(msg, handler) {
1541
- const timeout = {current: null}
1542
- return new Promise(resolve => {
1543
-
1544
- function myhandler(...args) {
1545
- timeout.current && clearTimeout(timeout.current)
1546
- removeHandler()
1547
- resolve(handler?.(...args))
1548
- }
1549
-
1550
- function removeHandler() {
1551
- if (Array.isArray(steamClient._handlerManager._handlers[msg])) {
1552
- const index = steamClient._handlerManager._handlers[msg].findIndex(_handler => _handler === myhandler)
1553
- if (index > -1) {
1554
- steamClient._handlerManager._handlers[msg].splice(index, 1)
1555
- }
1556
- }
1557
- }
1558
-
1559
- timeout.current = setTimeout(function () {
1560
- removeHandler()
1561
- resolve()
1562
- }, 60000)
1563
- steamClient._handlerManager.add(msg, myhandler);
1564
- })
1565
- }
1566
-
1567
- function getFriendList() {
1568
- return Object.keys(steamClient.myFriends).filter(steamId => steamClient.myFriends[steamId] === NodeSteamUser.EFriendRelationship.Friend)
1569
- }
1570
-
1571
- function sendFriendTyping(steamId, callback) {
1572
- steamClient.chat.sendFriendTyping(steamId, callback)
1573
- }
1574
-
1575
-
1576
- /*
1577
- * usually take 400 -> 800 miliseconds
1578
- * */
1579
- function getPlayersProfile(steamId) {
1580
- const accountid = new SteamID(steamId).accountid
1581
- steamClient.sendToGC(730, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientRequestPlayersProfile, {}, protoEncode(Protos.csgo.CMsgGCCStrike15_v2_ClientRequestPlayersProfile, {
1582
- account_id: accountid, // account_id: new SteamID('76561199184696945').accountid,
1583
- request_level: 32
1584
- }))
1585
- return new Promise(resolve => {
1586
- pushGCCallback('PlayersProfile_' + accountid, resolve, 2000)
1587
- })
1588
- }
1589
-
1590
- async function checkPlayerPrimeStatus(steamId) {
1591
- const profile = await getPlayersProfile(steamId)
1592
- if (!profile) return false
1593
-
1594
- if (profile.ranking?.account_id) {
1595
- return true
1596
- }
1597
-
1598
- if (profile.player_level || profile.player_cur_xp) {
1599
- return true
1600
- }
1601
- return false
1602
- }
1603
-
1604
- async function _getStoreSteamPoweredResponse(cookie) {
1605
- let response = null
1606
- for (let i = 0; i < 50; i++) {
1607
- if (!response) {
1608
- try {
1609
- response = (await axios.request({
1610
- url: 'https://store.steampowered.com/', headers: {
1611
- cookie,
1612
- accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.75',
1613
- },
1614
- }))
1615
- } catch (e) {
1616
- await sleep(1000)
1617
- }
1618
- }
1619
- }
1620
- return response
1621
- }
1622
-
1623
- async function getNewCookie(cookie) {
1624
- if (!cookie) {
1625
- return
1626
- }
1627
- let response = await _getStoreSteamPoweredResponse(cookie)
1628
- if (!response) {
1629
- return
1630
- }
1631
- while (Array.isArray(response?.headers?.["set-cookie"])) {
1632
- console.log(cookie);
1633
- const cookieObj = cookie.split(';').reduce(function (accumulator, currentValue) {
1634
- accumulator[currentValue.trim().split('=')[0].trim()] = currentValue.trim().split('=')[1].trim()
1635
- return accumulator
1636
- }, {})
1637
- for (const mcookie of response.headers["set-cookie"]) {
1638
- const name = mcookie.split('=')[0].trim()
1639
- const value = mcookie.split('=')[1].split(";")[0].trim()
1640
- cookieObj[name] = value
1641
- }
1642
- cookie = Object.keys(cookieObj).map(name => `${name}=${cookieObj[name]}`).join(';')
1643
- response = await _getStoreSteamPoweredResponse(cookie)
1644
- }
1645
- return cookie
1646
- }
1647
-
1648
- async function loginWithCookie(cookie, tryNewCookie = false) {
1649
- let response;
1650
- for (let i = 0; i < 20; i++) {
1651
- try {
1652
- response = (await axios.request({
1653
- url: 'https://steamcommunity.com/chat/clientjstoken',
1654
- headers: {
1655
- cookie,
1656
- },
1657
- }));
1658
- } catch (e) {
1659
- await sleep(1000)
1660
- }
1661
- if (response) {
1662
- break;
1663
- }
1664
- }
1665
-
1666
- const result = response?.data
1667
- if (result?.logged_in) {
1668
- Object.assign(result, {
1669
- steamID: new SteamID(result.steamid), accountName: result.account_name, webLogonToken: result.token
1670
- })
1671
- steamClient.logOn(result)
1672
- return cookie
1673
- } else {
1674
- if (tryNewCookie) {
1675
- log('You are not logged in', cookie)
1676
- return null
1677
- } else {
1678
- const newCookie = await getNewCookie(cookie)
1679
- if (!newCookie) {
1680
- console.error("Cannot get new cookie")
1681
- return null
1682
- } else {
1683
- return await loginWithCookie(newCookie, true)
1684
- }
1685
- }
1686
- }
1687
- }
1688
-
1689
- async function login(reconnect = false) {
1690
- if (clientJsToken?.logged_in === true) {
1691
- log(reconnect ? 'reconnect with clientJsToken' : 'login with clientJsToken')
1692
- steamClient.logOn(clientJsToken)
1693
- setTimeout(function () {
1694
- clientJsToken = null
1695
- }, 1000)
1696
- return true
1697
- } else if (cookie) {
1698
- log(reconnect ? 'reconnect with cookie' : 'login with cookie')
1699
- const _clientJsToken = await new SteamUser(typeof cookie === "function" ? await cookie() : cookie).getClientJsToken()
1700
- if (_clientJsToken?.logged_in === true) {
1701
- try {
1702
- await steamClient.logOn(_clientJsToken)
1703
- return true
1704
- } catch (e) {
1705
- return false
1706
- }
1707
- } else {
1708
- return false
1709
- }
1710
- } else if (username && password) {
1711
- log(reconnect ? `reconnect with username ${username}` : `login with username ${username}`)
1712
- steamClient.logOn({
1713
- accountName: username, password: password, rememberPassword: true, machineName: 'Natri',
1714
- })
1715
- return true
1716
- }
1717
- }
1718
-
1719
- async function logOff() {
1720
- isLogOff = true
1721
- logOffEvent?.(true)
1722
- steamClient.logOff()
1723
- }
1724
-
1725
- function onCookie(callback) {
1726
- if (getCookies()) {
1727
- callback(getCookies())
1728
- } else {
1729
- onEvent('webSession', function (webSession) {
1730
- callback(webSession?.cookies?.join?.(';'))
1731
- }, true)
1732
- }
1733
- }
1734
-
1735
- function init() {
1736
- bindEvent()
1737
- login()
1738
-
1739
- steamClient._handlerManager.add(Protos.csgo.EMsg.k_EMsgClientRequestedClientStats, function (payload) {
1740
- const result = protoDecode(Protos.csgo.CMsgClientRequestedClientStats, payload.toBuffer())
1741
- // console.log("CMsgClientRequestedClientStats", result);
1742
- })
1743
- steamClient._handlerManager.add(Protos.csgo.EMsg.k_EMsgClientMMSLobbyData, function (payload) {
1744
- const result = protoDecode(Protos.csgo.CMsgClientMMSLobbyData, payload.toBuffer())
1745
- // console.log("CMsgClientMMSLobbyData", result, result.metadata);
1746
- })
1747
- }
1748
-
1749
-
1750
- function partyRegister() {
1751
- if (prime === null) {
1752
- _partyRegister(true)
1753
- _partyRegister(false)
1754
- } else {
1755
- _partyRegister(prime)
1756
- }
1757
- }
1758
-
1759
- function _partyRegister(prime) {
1760
- log("partyRegister", prime)
1761
- lastTimePartyRegister = new Date().getTime()
1762
- steamClient.sendToGC(730, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Register, {}, protoEncode(Protos.csgo.CMsgGCCStrike15_v2_Party_Register, {
1763
- // id : 0,
1764
- ver: CSGO_VER,
1765
- apr: prime ? 1 : 0,//prime
1766
- ark: prime ? 180 : 0, grps: [], launcher: 0, game_type: 8
1767
- }))
1768
- }
1769
-
1770
- async function sendFriendMessage(steamId, message) {
1771
- while (sendMessageTimestamp && new Date().getTime() - sendMessageTimestamp < 2000) {
1772
- await sleep(1000)
1773
- }
1774
-
1775
- while (isSendingFriendMessages) {
1776
- await sleep(5000)
1777
- }
1778
-
1779
- isSendingFriendMessages = true
1780
- const now = new Date().getTime()
1781
- while (new Date().getTime() - now < 2 * 60000) {//2 minutes
1782
- const result = await new Promise(resolve => {
1783
- steamClient.chat.sendFriendMessage(steamId, message, undefined, function (...arg) {
1784
- sendMessageTimestamp = new Date().getTime()
1785
- resolve(arg)
1786
- });
1787
- })
1788
-
1789
- if (result?.[1]?.server_timestamp) {
1790
- isSendingFriendMessages = false
1791
- return result?.[1]
1792
- } else if (result?.[0]?.message?.includes?.("RateLimitExceeded")) {
1793
- await sleep(5000)
1794
- } else {
1795
- isSendingFriendMessages = false
1796
- return result
1797
- }
1798
- }
1799
- isSendingFriendMessages = false
1800
- }
1801
-
1802
- async function autoRequestFreeLicense(shouldLog = false, max = 10) {
1803
- return
1804
- // const mCookies = await getCookiesWait()
1805
- // if (!mCookies) return
1806
- // let freeAppList = Array.isArray(steamClient.licenses) ? FreeAppList.filter(appId => steamClient.licenses.every(({package_id}) => package_id !== appId)) : FreeAppList;
1807
- const freeAppList = freeAppList.filter(appId => ownedApps.some(app => app.appid == appId))
1808
- const recommendedApps = _.shuffle(freeAppList)
1809
- if (max) {
1810
- recommendedApps.length = Math.min(recommendedApps.length, max)
1811
- }
1812
- try {
1813
- const response = await steamClient.requestFreeLicense(recommendedApps)
1814
- if (shouldLog) {
1815
- log(response)
1816
- }
1817
- } catch (e) {
1818
- log(e);
1819
- }
1820
- // if (Math.random() > 0.7) {
1821
- // for (const recommendedApp of recommendedApps) {
1822
- // try {
1823
- // await steamUtils.requestFreeLicense(recommendedApp)
1824
- // } catch (e) {
1825
- // }
1826
- // await sleep(2000)
1827
- // }
1828
- // } else {
1829
- // try {
1830
- // await steamClient.requestFreeLicense(recommendedApps)
1831
- // } catch (e) {
1832
- // log(e);
1833
- // }
1834
- // }
1835
-
1836
- // if (shouldLog) {
1837
- // await sleep(20000)
1838
- // const ownedAppsCount2 = (await steamUtils.getDynamicStoreUserData())?.rgOwnedApps?.length || 0
1839
- // const increaseNumber = ownedAppsCount2 - ownedAppsCount;
1840
- // log(`OwnedApps length ${ownedAppsCount2}, increase ${increaseNumber}`)
1841
- // }
1842
- }
1843
-
1844
- async function playCSGO() {
1845
- try {
1846
- await steamClient.requestFreeLicense(AppID)
1847
- await sleep(5000)
1848
- } catch (e) {
1849
- }
1850
- gamesPlayed(AppID)
1851
- }
1852
-
1853
- function doFakeGameScore() {
1854
- const maxRound = Math.random() > 0.7 ? 16 : 12
1855
- const maps = [
1856
- "ar_baggage",
1857
- "ar_dizzy",
1858
- "ar_monastery",
1859
- "ar_shoots",
1860
- "cs_agency",
1861
- "cs_assault",
1862
- "cs_italy",
1863
- "cs_militia",
1864
- "cs_office",
1865
- "de_ancient",
1866
- "de_anubis",
1867
- "de_bank",
1868
- "de_boyard",
1869
- "de_cache",
1870
- "de_canals",
1871
- "de_cbble",
1872
- "de_chalice",
1873
- "de_dust2",
1874
- "de_inferno",
1875
- "de_lake",
1876
- "de_mirage",
1877
- "de_nuke",
1878
- "de_overpass",
1879
- "de_safehouse",
1880
- // "de_shortnuke",
1881
- "de_stmarc",
1882
- "de_sugarcane",
1883
- "de_train",
1884
- "de_tuscan",
1885
- "de_vertigo",
1886
- "dz_ember",
1887
- "dz_vineyard",
1888
- "gd_cbble",
1889
- "training1"
1890
- ]
1891
-
1892
- if (richPresence.myScore === undefined) {
1893
- richPresence.myScore = _.random(0, maxRound)
1894
- }
1895
- if (richPresence.theirScore === undefined) {
1896
- richPresence.theirScore = _.random(0, maxRound)
1897
- }
1898
- if (richPresence.map === undefined) {
1899
- richPresence.map = maps[Math.floor(Math.random() * maps.length)]
1900
- }
1901
- if (richPresence.myScore === maxRound || richPresence.theirScore === maxRound) {
1902
- richPresence.myScore = 0
1903
- richPresence.theirScore = 0
1904
- richPresence.map = maps[Math.floor(Math.random() * maps.length)]
1905
- } else {
1906
- const isMyTeamWin = Math.random() > 0.5
1907
- if (isMyTeamWin) {
1908
- richPresence.myScore++
1909
- } else {
1910
- richPresence.theirScore++
1911
- }
1912
- }
1913
-
1914
- const score = richPresence.myScore === 0 && richPresence.theirScore === 0 ? '' : `[ ${richPresence.myScore} : ${richPresence.theirScore} ]`
1915
- steamClient.uploadRichPresence(730, {
1916
- 'game:state': 'game',
1917
- steam_display: '#display_GameKnownMapScore',
1918
- connect: '+gcconnectG082AA752',
1919
- version: CSGO_VER.toString(),
1920
- 'game:mode': 'competitive',
1921
- 'game:map': richPresence.map,
1922
- 'game:server': 'kv',
1923
- 'watch': _.random(1, 5).toString(),
1924
- 'game:score': score,
1925
- })
1926
- }
1927
-
1928
- function updateFakeGameScore() {
1929
- if (isFakeGameScore && getPlayingAppIds().some(a => a == 730)) {
1930
- doSetInterval(doFakeGameScore, [60000, 180000], 'uploadRichPresenceCSGO')
1931
- } else {
1932
- doClearInterval('uploadRichPresenceCSGO')
1933
- }
1934
- }
1935
-
1936
- function updateAutoRequestFreeLicense() {
1937
- if (isAutoRequestFreeLicense) {
1938
- doSetInterval(function () {
1939
- autoRequestFreeLicense(false, 50)
1940
- }, [5 * 60000, 10 * 60000], 'autoRequestFreeLicense')
1941
- } else {
1942
- doClearInterval('autoRequestFreeLicense')
1943
- }
1944
- }
1945
-
1946
- function updateInvisible() {
1947
- if (isInvisible) {
1948
- steamClient.setPersona(NodeSteamUser.EPersonaState.Invisible)
1949
- state = 'Invisible'
1950
- } else {
1951
- steamClient.setPersona(NodeSteamUser.EPersonaState.Online)
1952
- state = 'Online'
1953
- }
1954
- }
1955
-
1956
- async function gamesPlayed(apps) {
1957
- if (!Array.isArray(apps)) {
1958
- apps = [apps]
1959
- }
1960
-
1961
- steamClient.gamesPlayed(apps);
1962
- const shouldHello = apps.some(app => parseInt(app) === 730);
1963
- await sleep(1000)
1964
- if (shouldHello) {
1965
- await sendHello()
1966
- }
1967
- await sleep(1000)
1968
- if (shouldHello) {
1969
- await sendHello()
1970
- }
1971
- updateFakeGameScore()
1972
-
1973
- // await sleep(10000)
1974
- // self.steamUser.uploadRichPresence(730, {
1975
- // status: 'bussssss',
1976
- // 'game:state': 'lobby',
1977
- // steam_display: '#display_watch',
1978
- // currentmap: '#gamemap_de_empire',
1979
- // connect: '+gcconnectG082AA752',
1980
- // 'game:mode': 'competitive'
1981
- // })
1982
- }
1983
-
1984
- function getFriendsList() {
1985
- const methodName = "FriendsList.GetFriendsList#1"
1986
- const {users, myFriends} = steamClient//object
1987
- /*
1988
- users
1989
- * {
1990
- rich_presence: [],
1991
- player_name: "Kei #SkinsMonkey",
1992
- avatar_hash: [123,4543],
1993
- last_logoff: "2023-05-20T05:00:42.000Z",
1994
- last_logon: "2023-05-20T05:02:16.000Z",
1995
- last_seen_online: "2023-05-20T05:00:42.000Z",
1996
- avatar_url_icon: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/3e/3e9da0b107ac2ec384759544368a8a977359537a.jpg",
1997
- avatar_url_medium: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/3e/3e9da0b107ac2ec384759544368a8a977359537a_medium.jpg",
1998
- avatar_url_full: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/3e/3e9da0b107ac2ec384759544368a8a977359537a_full.jpg"
1999
- }
2000
- *
2001
-
2002
- myFriends
2003
- {
2004
- 76561198365087582: 3,
2005
- 76561199490395123: 3
2006
- }
2007
- * */
2008
- /*steamClient._send({
2009
- msg: 151,
2010
- proto: {
2011
- target_job_name: methodName
2012
- }
2013
- }, Buffer.alloc(0), function (body, hdr) {
2014
- const result = hdr.proto.eresult
2015
- const errorMessage = hdr.proto.error_message
2016
- const responseData = body.toBuffer()
2017
- console.log(`xxx`, result)
2018
- })*/
2019
-
2020
- steamClient.sendToGC(730, 767, {}, Buffer.alloc(0))
2021
- }
2022
-
2023
- async function getUserOwnedApps(steamId = steamClient.steamID) {
2024
- if (!steamId) {
2025
- return []
2026
- }
2027
- if (typeof steamId?.getSteamID64 === "function") {
2028
- steamId = steamId.getSteamID64()
2029
- }
2030
- const isMe = steamId === steamClient.steamID.getSteamID64();
2031
- if (isMe && ownedApps.length) {
2032
- return ownedApps
2033
- }
2034
- let result = {}
2035
- try {
2036
- result = await steamClient.getUserOwnedApps(steamId)
2037
- } catch (e) {
2038
- try {
2039
- result = await steamClient.getUserOwnedApps(steamId)
2040
- } catch (e) {
2041
- result = {}
2042
- }
2043
- }
2044
- if (isMe && Array.isArray(result.apps)) {
2045
- ownedApps.length = 0
2046
- ownedApps.push(...result.apps)
2047
- }
2048
- return result.apps || []
2049
- const resultExample = {
2050
- app_count: 22,
2051
- apps: [
2052
- {
2053
- content_descriptorids: [],
2054
- appid: 208030,
2055
- name: "Moon Breakers",
2056
- playtime_2weeks: null,
2057
- playtime_forever: 0,
2058
- img_icon_url: "",
2059
- has_community_visible_stats: null,
2060
- playtime_windows_forever: 0,
2061
- playtime_mac_forever: 0,
2062
- playtime_linux_forever: 0,
2063
- rtime_last_played: 0,
2064
- capsule_filename: null,
2065
- sort_as: null,
2066
- has_workshop: null,
2067
- has_market: null,
2068
- has_dlc: null,
2069
- has_leaderboards: null
2070
- },
2071
- ]
2072
- }
2073
- }
2074
-
2075
- function getPlayingAppIds() {
2076
- return steamClient._playingAppIds || []
2077
- }
2078
-
2079
- return {
2080
- init,
2081
- partySearch,
2082
- invite2Lobby,
2083
- createLobby,
2084
- updateLobby,
2085
- createThenInvite2Lobby,
2086
- joinLobby,
2087
- getLobbyData,
2088
- partyRegister,
2089
- requestCoPlays,
2090
- getPersonas,
2091
- getUsername() {
2092
- return username
2093
- },
2094
- getCookies,
2095
- getCookiesWait,
2096
- getLogOnDetails() {
2097
- return steamClient?._logOnDetails
2098
- },
2099
- onEvent,
2100
- offEvent,
2101
- offAllEvent,
2102
- setPersona(state, name) {
2103
- steamClient.setPersona(state, name)
2104
- },
2105
- sendFriendMessage,
2106
- sendFriendTyping,
2107
- getSteamClient() {
2108
- return steamClient
2109
- },
2110
- getAccountInfoName,
2111
- getPersonaName,
2112
- async getPlayersProfile(steamId, retry = 3) {
2113
- for (let i = 0; i < retry; i++) {
2114
- const profile = await getPlayersProfile(steamId)
2115
- if (profile) {
2116
- return profile
2117
- }
2118
- }
2119
- return null
2120
- },
2121
- autoRequestFreeLicense,
2122
- playCSGO,
2123
- doSetInterval,
2124
- doClearIntervals,
2125
- gamesPlayed,
2126
- sendHello,
2127
- checkPlayerPrimeStatus,
2128
- doClearInterval,
2129
- gamePlay,
2130
- autoGamePlay,
2131
- offAutoGamePlay,
2132
- updateAutoGamePlay,
2133
- getFriendsList,
2134
- setIsPartyRegister(change) {
2135
- change = !!change
2136
- if (isPartyRegister !== change) {
2137
- isPartyRegister = change
2138
- if (!isPartyRegister) {
2139
- doClearInterval('autoPartyRegister')
2140
- } else {
2141
- sendHello()
2142
- }
2143
- }
2144
- },
2145
- setAutoPlay(change) {
2146
- change = !!change
2147
- if (isAutoPlay !== change) {
2148
- isAutoPlay = change
2149
- updateAutoGamePlay()
2150
- }
2151
- },
2152
- setIsInvisible(change) {
2153
- change = !!change
2154
- if (isInvisible !== change) {
2155
- isInvisible = change
2156
- updateInvisible()
2157
- }
2158
- },
2159
- setFakeGameScore(change) {
2160
- change = !!change
2161
- if (isFakeGameScore !== change) {
2162
- isFakeGameScore = change
2163
- updateFakeGameScore()
2164
- }
2165
- },
2166
- setAutoRequestFreeLicense(change) {
2167
- change = !!change
2168
- if (isAutoRequestFreeLicense !== change) {
2169
- isAutoRequestFreeLicense = change
2170
- updateAutoRequestFreeLicense()
2171
- }
2172
- },
2173
- getState() {
2174
- return state
2175
- },
2176
- log,
2177
- isPrime() {
2178
- return prime === true
2179
- },
2180
- getFriendList,
2181
- logOff,
2182
- isPlayingBlocked() {
2183
- return playingBlocked
2184
- },
2185
- async getChatHistory(steamId) {
2186
- if (!steamClient.steamID) return []
2187
- const mySteamId = typeof steamClient.steamID.getSteamID64 === "function" ? steamClient.steamID.getSteamID64() : steamClient.steamID
2188
- return new Promise(resolve => {
2189
- setTimeout(resolve, 90000)
2190
- steamClient.getChatHistory(steamId, async function (error, result) {
2191
- const messages = (result || []).map(function (msg) {
2192
- const fromSteamId = typeof msg.steamID?.getSteamID64 === "function" ? msg.steamID.getSteamID64() : msg.steamID
2193
- return {
2194
- message: msg.message,
2195
- from: fromSteamId,
2196
- to: fromSteamId == mySteamId ? steamId : mySteamId,
2197
- _id: new Date(msg.timestamp).getTime().toString(),
2198
- timestamp: new Date(msg.timestamp).getTime(),
2199
- isMe: fromSteamId !== steamId
2200
- };
2201
- })
2202
- resolve(messages)
2203
- })
2204
- })
2205
- },
2206
- onAnyEvent,
2207
- async redeemGift(gid) {
2208
- try {
2209
- const community = new SteamCommunity();
2210
- let cookies = await getCookiesWait();
2211
- community.setCookies(typeof cookies === "string" ? cookies.split(';') : cookies)
2212
- community.redeemGift(gid)
2213
- } catch (e) {
2214
- }
2215
- },
2216
- async requestFreeLicense(...args) {
2217
- try {
2218
- return await steamClient.requestFreeLicense(...args)
2219
- } catch (e) {
2220
- }
2221
- },
2222
- getSteamId() {
2223
- try {
2224
- return steamClient.steamID.getSteamID64()
2225
- } catch (e) {
2226
- }
2227
- },
2228
- getLastTimePartyRegister() {
2229
- return lastTimePartyRegister
2230
- },
2231
- getLastTimePartySearch() {
2232
- return lastTimePartySearch
2233
- },
2234
- getLicenses() {
2235
- return steamClient.licenses
2236
- const exampleLicenses = [{
2237
- package_id: 303386,
2238
- time_created: 1680491335,
2239
- time_next_process: 0,
2240
- minute_limit: 0,
2241
- minutes_used: 0,
2242
- payment_method: 1024,
2243
- flags: 512,
2244
- purchase_country_code: "VN",
2245
- license_type: 1,
2246
- territory_code: 0,
2247
- change_number: 20615891,
2248
- owner_id: 1530068060,
2249
- initial_period: 0,
2250
- initial_time_unit: 0,
2251
- renewal_period: 0,
2252
- renewal_time_unit: 0,
2253
- access_token: "8049398090486337961",
2254
- master_package_id: null
2255
- }]
2256
- },
2257
- uploadRichPresence(appid, richPresence) {
2258
- if (Array.isArray(richPresence)) {
2259
- richPresence = richPresence.reduce(function (previousValue, currentValue, currentIndex, array) {
2260
- if (currentValue.key) {
2261
- previousValue[currentValue.key] = currentValue.value?.toString() || ''
2262
- }
2263
- return previousValue
2264
- })
2265
- }
2266
- steamClient.uploadRichPresence(appid, richPresence)
2267
- },
2268
- getUserOwnedApps,
2269
- getPlayingAppIds,
2270
- getCurrentLobby() {
2271
- return currentLobby
2272
- }
2273
- }
2274
- }
2275
-
2276
- export default SteamClient
2277
-
2278
- export function increaseCSGO_VER() {
2279
- return ++CSGO_VER
2280
- }
2281
-
2282
- SteamClient.isAccountPlayable = async function isAccountPlayable(params, timeoutMs) {
2283
- let clientJsToken = params.clientJsToken
2284
- delete params.clientJsToken
2285
- if(!clientJsToken && params.cookie){
2286
- clientJsToken = await new SteamUser(typeof params.cookie === "function" ? await params.cookie() : params.cookie).getClientJsToken()
2287
- }
2288
- if (clientJsToken?.logged_in !== true) {
2289
- return false
2290
- }
2291
- params.clientJsToken = clientJsToken
2292
-
2293
- return await new Promise((resolve) => {
2294
- const timeout = setTimeout(() => {
2295
- doResolve();
2296
- }, timeoutMs || 30000);
2297
-
2298
- const steamClient = new SteamClient({
2299
- isFakeGameScore: false,
2300
- isAutoPlay: true,
2301
- isPartyRegister: false,
2302
- isInvisible: false,
2303
- MAX_GAME_PLAY: 10,
2304
- games: 730,
2305
- ...params,
2306
- });
2307
-
2308
- steamClient.onEvent("error", ({eresult, msg, error}) => {
2309
- doResolve();
2310
- });
2311
-
2312
- steamClient.onEvent("csgoOnline", ClientWelcome => {
2313
- doResolve(ClientWelcome);
2314
- });
2315
-
2316
- steamClient.onEvent("csgoClientHello", ClientHello => {
2317
- doResolve(ClientHello);
2318
- });
2319
-
2320
- steamClient.onEvent("playingState", ({playing_blocked, playing_app}) => {
2321
- if (playing_blocked) {
2322
- doResolve();
2323
- }
2324
- },
2325
- );
2326
-
2327
- steamClient.init();
2328
-
2329
- function doResolve(data) {
2330
- clearTimeout(timeout);
2331
- steamClient.doClearIntervals();
2332
- steamClient.offAllEvent();
2333
- steamClient.logOff();
2334
- return resolve(!!data);
2335
- }
2336
- });
2337
- }
1
+ import NodeSteamUser from "steam-user";
2
+ import _ from "lodash";
3
+ import fs from "fs";
4
+ import { protoDecode, protoEncode } from "./helpers/util.js";
5
+ import SteamID from "steamid";
6
+ import FriendCode from "csgo-friendcode";
7
+ import axios from "axios";
8
+ import helpers, { loadProfos } from "./helpers/protos.js";
9
+ import { fileURLToPath } from "url";
10
+ import path from "path";
11
+ import SteamUser from "./index.js";
12
+ import { v4 as uuidv4 } from "uuid";
13
+ import EFriendRelationship from "steam-user/enums/EFriendRelationship.js";
14
+ import SteamCommunity from "steamcommunity";
15
+ import moment from "moment-timezone";
16
+ import { encode, encodeUids } from "./bufferHelpers.js";
17
+
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = path.dirname(__filename);
20
+
21
+ const Protos = helpers([
22
+ {
23
+ name: "csgo",
24
+ protos: loadProfos(`${__dirname}/protos/`),
25
+ },
26
+ ]);
27
+
28
+ export const RANKS = {
29
+ 0: "Unranked",
30
+ 1: "Silver I",
31
+ 2: "Silver II",
32
+ 3: "Silver III",
33
+ 4: "Silver IV",
34
+ 5: "Silver Elite",
35
+ 6: "Silver Elite Master",
36
+ 7: "Gold Nova I",
37
+ 8: "Gold Nova II",
38
+ 9: "Gold Nova III",
39
+ 10: "Gold Nova Master",
40
+ 11: "Master Guardian I",
41
+ 12: "Master Guardian II",
42
+ 13: "Master Guardian Elite",
43
+ 14: "Distinguished Master Guardian",
44
+ 15: "Legendary Eagle",
45
+ 16: "Legendary Eagle Master",
46
+ 17: "Supreme Master First Class",
47
+ 18: "The Global Elite",
48
+ };
49
+ export const LOCS = {
50
+ 20054: "VN",
51
+ 23115: "KZ",
52
+ 20041: "IN",
53
+ 20035: "CN",
54
+ 17474: "BD",
55
+ 17481: "ID",
56
+ 22861: "MY",
57
+ 18516: "TH",
58
+ 22356: "TW",
59
+ 21067: "KR",
60
+ 19272: "HK",
61
+ 18512: "PH",
62
+ 21842: "RU",
63
+ 16716: "LA",
64
+ 20558: "NP",
65
+ 18259: "SG",
66
+ 19789: "MM",
67
+ 20045: "MN",
68
+ 18251: "KG",
69
+ 18507: "KH",
70
+ 22605: "MX",
71
+ 19280: "PK",
72
+ 20301: "HK/MO", //hongkong or macau
73
+ 21333: "Unknown",
74
+ 21825: "AU",
75
+ 20034: "Unkown",
76
+ };
77
+
78
+ const AppID = 730;
79
+ export let CSGO_VER = 13960;
80
+ export const FreeAppList = JSON.parse(fs.readFileSync(path.join(__dirname, "free_packages.json"))).packages;
81
+
82
+ SteamUser.getAppVersion(AppID).then(function (ver) {
83
+ CSGO_VER = ver;
84
+ });
85
+
86
+ const PersonasCache = [];
87
+ let isSendingFriendMessages = false;
88
+
89
+ function SteamClient({ username, password, cookie, clientJsToken, isAutoRequestFreeLicense = true, isFakeGameScore = true, isPartyRegister = true, isAutoPlay = false, isInvisible = false, autoAcceptTradeRequest = false, autoReconnect = true, MAX_GAME_PLAY = 10, games = null }) {
90
+ const steamClient = new NodeSteamUser();
91
+ let prime = null;
92
+ let state = "Offline"; //InGame, Online, Invisible
93
+ let isLogOff = false;
94
+ let playingBlocked = null;
95
+ const richPresence = {};
96
+ let sendMessageTimestamp = 0;
97
+ let lastTimePartyRegister = 0;
98
+ let lastTimePartySearch = 0;
99
+ const ownedApps = [];
100
+ let logOffEvent = null;
101
+
102
+ const currentLobby = {
103
+ lobbyID: null,
104
+ timestamp: 0,
105
+ };
106
+
107
+ const onAnyCallbacks = [];
108
+
109
+ const events = {
110
+ user: [],
111
+ loggedOn: [],
112
+ csgoOnline: [],
113
+ csgoClientHello: [],
114
+ webSession: [],
115
+ friendMessage: [],
116
+ friendTyping: [],
117
+ disconnected: [],
118
+ error: [],
119
+ playersProfile: [],
120
+ fatalError: [],
121
+ partyInvite: [],
122
+ friendRelationship: [],
123
+ tradeOffers: [],
124
+ offlineMessages: [],
125
+ friendsList: [],
126
+ gifts: [],
127
+ playingState: [],
128
+ emailInfo: [],
129
+ accountLimitations: [],
130
+ };
131
+
132
+ const gcCallback = {};
133
+
134
+ function pushGCCallback(name, cb, timeout) {
135
+ if (!gcCallback[name]) {
136
+ gcCallback[name] = {};
137
+ }
138
+ let t = null;
139
+ let id = uuidv4();
140
+
141
+ function callback(...arg) {
142
+ if (t) {
143
+ clearTimeout(t);
144
+ }
145
+ delete gcCallback[name][id];
146
+ cb?.apply(null, arg);
147
+ }
148
+
149
+ if (timeout) {
150
+ t = setTimeout(callback, timeout);
151
+ }
152
+ gcCallback[name][id] = callback;
153
+ }
154
+
155
+ function callGCCallback(name, ...arg) {
156
+ if (gcCallback[name]) {
157
+ for (const id in gcCallback[name]) {
158
+ gcCallback[name][id]?.(...arg);
159
+ }
160
+ }
161
+ }
162
+
163
+ function callEvent(_events, data) {
164
+ const eventName = Object.keys(events).find((eventName) => events[eventName] === _events);
165
+ eventName && onAnyCallbacks.forEach((cb) => cb?.({ eventName, data }));
166
+
167
+ _events?.forEach?.((e) => {
168
+ e.callback?.(data);
169
+ e.timeout && clearTimeout(e.timeout);
170
+ delete e.timeout;
171
+ if (e.once) {
172
+ delete e.callback;
173
+ }
174
+ });
175
+ _.remove(_events, (e) => !e || e?.once);
176
+ }
177
+
178
+ function onEvent(name, callback, once, timeout) {
179
+ if (!events[name]) {
180
+ events[name] = [];
181
+ }
182
+ const t = timeout ? setTimeout(callback, timeout) : null;
183
+ events[name].push({
184
+ once,
185
+ callback,
186
+ timeout: t,
187
+ });
188
+ }
189
+
190
+ function offEvent(name) {
191
+ if (Array.isArray(events[name])) {
192
+ for (const eventElement of events[name]) {
193
+ if (eventElement.timeout) {
194
+ clearTimeout(eventElement.timeout);
195
+ }
196
+ }
197
+ }
198
+
199
+ delete events[name];
200
+ }
201
+
202
+ function onAnyEvent(callback) {
203
+ onAnyCallbacks.push(callback);
204
+ }
205
+
206
+ function offAllEvent() {
207
+ for (const name in events) {
208
+ for (const event of events[name]) {
209
+ if (event.timeout) {
210
+ try {
211
+ clearTimeout(event.timeout);
212
+ } catch (e) {}
213
+ delete event.timeout;
214
+ }
215
+ }
216
+ delete events[name];
217
+ }
218
+ onAnyCallbacks.length = 0;
219
+ }
220
+
221
+ const intervals = {};
222
+ const intervalRandoms = {};
223
+
224
+ function doSetInterval(cb, timeout, key) {
225
+ const isRandom = Array.isArray(timeout);
226
+ if (!key) {
227
+ key = uuidv4();
228
+ }
229
+ if (isRandom) {
230
+ if (intervalRandoms[key] !== undefined) {
231
+ try {
232
+ clearTimeout(intervalRandoms[key]);
233
+ } catch (e) {}
234
+ }
235
+ intervalRandoms[key] = setTimeout(
236
+ function () {
237
+ doSetInterval(cb, timeout, key);
238
+ if (state !== "Offline") {
239
+ cb();
240
+ }
241
+ },
242
+ _.random(timeout[0], timeout[1]),
243
+ );
244
+ } else {
245
+ if (intervals[key] !== undefined) {
246
+ try {
247
+ clearInterval(intervals[key]);
248
+ } catch (e) {}
249
+ }
250
+
251
+ intervals[key] = setInterval(function () {
252
+ if (state !== "Offline") {
253
+ cb();
254
+ }
255
+ }, timeout);
256
+ }
257
+
258
+ return key;
259
+ }
260
+
261
+ function doClearIntervals() {
262
+ for (const key in intervals) {
263
+ clearInterval(intervals[key]);
264
+ delete intervals[key];
265
+ }
266
+ for (const key in intervalRandoms) {
267
+ clearTimeout(intervalRandoms[key]);
268
+ delete intervalRandoms[key];
269
+ }
270
+ }
271
+
272
+ function doClearInterval(key) {
273
+ try {
274
+ clearInterval(intervals[key]);
275
+ } catch (e) {}
276
+ delete intervals[key];
277
+
278
+ try {
279
+ clearTimeout(intervalRandoms[key]);
280
+ } catch (e) {}
281
+ delete intervalRandoms[key];
282
+ }
283
+
284
+ function getAccountInfoName() {
285
+ return [steamClient?.accountInfo?.name, steamClient?._logOnDetails?.account_name].filter(Boolean).join(" - ");
286
+ }
287
+
288
+ function getPersonaName() {
289
+ return steamClient?.accountInfo?.name;
290
+ }
291
+
292
+ function log(...msg) {
293
+ const now = moment().tz("Asia/Ho_Chi_Minh").format("DD/MM/YYYY HH:mm:ss");
294
+ console.log(`[${now}] [${getAccountInfoName()}]`, ...msg);
295
+ }
296
+
297
+ async function getPersonas(steamIDs) {
298
+ steamIDs = steamIDs.map((steamId) => (steamId instanceof SteamID ? steamId.getSteamID64() : steamId));
299
+ const notCachesteamIDs = steamIDs.filter((id) => !PersonasCache.some((p) => p.id == id));
300
+ const cachedPersonas = PersonasCache.filter((p) => steamIDs.includes(p.id));
301
+
302
+ if (notCachesteamIDs.length) {
303
+ let personas = null;
304
+ try {
305
+ personas = (await steamClient.getPersonas(notCachesteamIDs))?.personas;
306
+ } catch (e) {}
307
+ if (!personas || !Object.keys(personas).length) {
308
+ try {
309
+ personas = (await steamClient.getPersonas(notCachesteamIDs))?.personas;
310
+ } catch (e) {}
311
+ }
312
+ if (!personas || !Object.keys(personas).length) {
313
+ try {
314
+ personas = (await steamClient.getPersonas(notCachesteamIDs))?.personas;
315
+ } catch (e) {}
316
+ }
317
+ if (personas && Object.keys(personas).length) {
318
+ for (let sid64 in personas) {
319
+ personas[sid64].id = sid64;
320
+ personas[sid64].avatar_hash = Buffer.from(personas[sid64].avatar_hash).toString("hex");
321
+ PersonasCache.push(personas[sid64]);
322
+ cachedPersonas.push(personas[sid64]);
323
+ }
324
+ }
325
+ }
326
+
327
+ while (PersonasCache.length > 500) {
328
+ PersonasCache.shift();
329
+ }
330
+ return cachedPersonas;
331
+ }
332
+
333
+ function sleep(ms) {
334
+ return new Promise((resolve) => {
335
+ setTimeout(resolve, ms);
336
+ });
337
+ }
338
+
339
+ function getCookies() {
340
+ return cookie || steamClient?.webSession?.cookies?.join?.(";");
341
+ }
342
+
343
+ async function getCookiesWait() {
344
+ return (
345
+ getCookies() ||
346
+ new Promise((resolve) => {
347
+ onEvent(
348
+ "webSession",
349
+ function (webSession) {
350
+ resolve(webSession?.cookies);
351
+ },
352
+ true,
353
+ 30000,
354
+ );
355
+ })
356
+ );
357
+ }
358
+
359
+ async function gamePlay() {
360
+ if ((Array.isArray(games) && games.length) || (games && (typeof games === "number" || typeof games === "string"))) {
361
+ return gamesPlayed(games);
362
+ }
363
+
364
+ let ownedApps = [];
365
+ for (let i = 0; i < 5; i++) {
366
+ ownedApps = await getUserOwnedApps();
367
+ if (ownedApps?.length) {
368
+ break;
369
+ }
370
+ }
371
+ if (!ownedApps?.length) {
372
+ gamesPlayed(730);
373
+ } else {
374
+ ownedApps = ownedApps.map(({ appid }) => appid);
375
+ ownedApps = _.shuffle(ownedApps);
376
+ ownedApps.length = Math.min(ownedApps.length, MAX_GAME_PLAY - 1);
377
+ _.remove(ownedApps, (app) => app == 730);
378
+ gamesPlayed([...ownedApps, 730]);
379
+ }
380
+ }
381
+
382
+ async function autoGamePlay() {
383
+ await gamePlay();
384
+ doSetInterval(gamePlay, [15 * 60000, 30 * 60000], "autoGamePlay");
385
+ }
386
+
387
+ async function offAutoGamePlay() {
388
+ steamClient.gamesPlayed([]);
389
+ doClearInterval("autoGamePlay");
390
+ }
391
+
392
+ async function updateAutoGamePlay() {
393
+ if (isAutoPlay) {
394
+ autoGamePlay();
395
+ } else {
396
+ offAutoGamePlay();
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Get a list of lobbies (* = Unsure description could be wrong)
402
+ * @param {Number} ver Game version we are searching for
403
+ * @param {Boolean} apr Prime or not*
404
+ * @param {Number} ark Rank multiplied by 10*
405
+ * @param {Array.<Number>} grps *
406
+ * @param {Number} launcher If we are using the China CSGO launcher or not*
407
+ * @param {Number} game_type Game type, 8 Competitive, 10 Wingman
408
+ * @returns {Promise.<Object>}
409
+ */
410
+ async function partySearch({ prime = false, game_type = "Competitive", rank = "Silver Elite", timeout = 5000 } = {}) {
411
+ const players = await new Promise((resolve) => {
412
+ steamClient.sendToGC(
413
+ AppID,
414
+ Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Search,
415
+ {},
416
+ protoEncode(Protos.csgo.CMsgGCCStrike15_v2_Party_Search, {
417
+ ver: CSGO_VER,
418
+ apr: prime ? 1 : 0,
419
+ ark: parseInt(Object.keys(RANKS).find((k) => RANKS[k] === rank)) * 10,
420
+ grps: [],
421
+ launcher: 0,
422
+ game_type: game_type === "Competitive" ? 8 : 10,
423
+ }),
424
+ );
425
+ lastTimePartySearch = new Date().getTime();
426
+ pushGCCallback("partySearch", resolve, timeout);
427
+ });
428
+ if (Array.isArray(players) && players.length) {
429
+ const personas = await getPersonas(players.map((p) => p.steamId));
430
+ for (const player of players) {
431
+ const persona = personas.find((p) => p.id == player.steamId);
432
+ if (persona) {
433
+ player.player_name = persona.player_name;
434
+ player.avatar_hash = persona.avatar_hash;
435
+ }
436
+ }
437
+ }
438
+ return players;
439
+ }
440
+
441
+ async function createLobby() {
442
+ if (!steamClient.steamID) {
443
+ return;
444
+ }
445
+
446
+ return new Promise((resolve) => {
447
+ const timeout = setTimeout(function () {
448
+ resolve();
449
+ }, 30000);
450
+
451
+ steamClient._send(
452
+ {
453
+ msg: Protos.csgo.EMsg.k_EMsgClientMMSCreateLobby,
454
+ proto: {
455
+ steamid: steamClient.steamID.getSteamID64(),
456
+ routing_appid: 730,
457
+ },
458
+ },
459
+ protoEncode(Protos.csgo.CMsgClientMMSCreateLobby, {
460
+ app_id: 730,
461
+ max_members: 1,
462
+ lobby_type: 1,
463
+ lobby_flags: 1,
464
+ }),
465
+ function (payload) {
466
+ clearTimeout(timeout);
467
+ const result = protoDecode(Protos.csgo.CMsgClientMMSCreateLobbyResponse, payload.toBuffer());
468
+ const steam_id_lobby = result.steam_id_lobby.toString();
469
+ currentLobby.lobbyID = steam_id_lobby;
470
+ currentLobby.timestamp = new Date().getTime();
471
+ resolve(steam_id_lobby);
472
+ },
473
+ );
474
+ });
475
+
476
+ // return await getHandlerResult(Protos.csgo.EMsg.k_EMsgClientMMSCreateLobbyResponse, function (payload) {
477
+ // const result = protoDecode(Protos.csgo.CMsgClientMMSCreateLobbyResponse, payload.toBuffer())
478
+ // return result.steam_id_lobby.toString()
479
+ // })
480
+
481
+ // steamClient.sendToGC(730, Protos.csgo.EMsg.k_EMsgClientMMSCreateLobby, {
482
+ // steamid: steamClient.steamID,
483
+ // routing_appid: 730,
484
+ // }, protoEncode(Protos.csgo.CMsgClientMMSCreateLobby, {
485
+ // app_id: 730,
486
+ // max_members: 1,
487
+ // lobby_type: 1,
488
+ // lobby_flags: 1
489
+ // }))
490
+ }
491
+
492
+ async function updateLobby(lobbyID) {
493
+ if (!steamClient.steamID) {
494
+ return;
495
+ }
496
+
497
+ return new Promise((resolve) => {
498
+ const timeout = setTimeout(function () {
499
+ resolve();
500
+ }, 30000);
501
+
502
+ steamClient._send(
503
+ {
504
+ msg: Protos.csgo.EMsg.k_EMsgClientMMSSetLobbyData,
505
+ proto: {
506
+ steamid: steamClient.steamID.getSteamID64(),
507
+ routing_appid: 730,
508
+ },
509
+ },
510
+ protoEncode(Protos.csgo.CMsgClientMMSSetLobbyData, {
511
+ app_id: 730,
512
+ steam_id_lobby: lobbyID,
513
+ steam_id_member: "0",
514
+ max_members: 10,
515
+ lobby_type: 1,
516
+ lobby_flags: 1,
517
+ metadata: encode(
518
+ {
519
+ "game:ark": "0",
520
+ // Country/Message
521
+ "game:loc": "",
522
+ "game:mapgroupname": "mg_de_mirage",
523
+ "game:mode": "competitive",
524
+ "game:prime": "1",
525
+ "game:type": "classic",
526
+ "members:numPlayers": "1",
527
+ "options:action": "custommatch",
528
+ "options:anytypemode": "0",
529
+ "system:access": "private",
530
+ "system:network": "LIVE",
531
+ uids: [steamClient.steamID],
532
+ },
533
+ [0x00, 0x00],
534
+ [0x08],
535
+ { uids: encodeUids },
536
+ ).toBuffer(),
537
+ }),
538
+ function (payload) {
539
+ clearTimeout(timeout);
540
+ const result = protoDecode(Protos.csgo.CMsgClientMMSSetLobbyDataResponse, payload.toBuffer());
541
+ const steam_id_lobby = result.steam_id_lobby.toString();
542
+ currentLobby.lobbyID = steam_id_lobby;
543
+ currentLobby.timestamp = new Date().getTime();
544
+ resolve(steam_id_lobby);
545
+ },
546
+ );
547
+ });
548
+
549
+ // return await getHandlerResult(Protos.csgo.EMsg.k_EMsgClientMMSSetLobbyDataResponse, function (payload) {
550
+ // const result = protoDecode(Protos.csgo.CMsgClientMMSSetLobbyDataResponse, payload.toBuffer())
551
+ // return result.steam_id_lobby.toString()
552
+ // })
553
+ }
554
+
555
+ async function invite2Lobby(lobbyID, steamId) {
556
+ if (!steamClient.steamID) {
557
+ return;
558
+ }
559
+
560
+ steamClient._send(
561
+ {
562
+ msg: Protos.csgo.EMsg.k_EMsgClientMMSInviteToLobby,
563
+ proto: {
564
+ steamid: steamClient.steamID.getSteamID64(),
565
+ routing_appid: 730,
566
+ },
567
+ },
568
+ protoEncode(Protos.csgo.CMsgClientMMSInviteToLobby, {
569
+ app_id: 730,
570
+ steam_id_lobby: lobbyID,
571
+ steam_id_user_invited: steamId,
572
+ }),
573
+ );
574
+
575
+ // lobbyID = new SteamID(lobbyID).accountid;
576
+
577
+ // Protos.csgo.EMsg.k_EMsgGCHInviteUserToLobby
578
+ // Protos.csgo.EMsg.k_EMsgClientMMSInviteToLobby
579
+ // steamClient.sendToGC(730, Protos.csgo.EMsg.k_EMsgClientMMSInviteToLobby, {}, protoEncode(Protos.csgo.CMsgClientMMSInviteToLobby, {
580
+ // app_id: 730,
581
+ // steam_id_lobby: lobbyID,
582
+ // steam_id_user_invited: accountid,
583
+ // }), function (...args) {
584
+ // console.log("invite2Lobby response", args)
585
+ // })
586
+ }
587
+
588
+ async function createThenInvite2Lobby(steamIds, onInvite) {
589
+ if (!steamClient.steamID) {
590
+ return;
591
+ }
592
+
593
+ if (!Array.isArray(steamIds)) {
594
+ steamIds = [steamIds];
595
+ }
596
+
597
+ let lobbyID = null;
598
+ if (currentLobby.lobbyID && currentLobby.timestamp > new Date().getTime() - 30000) {
599
+ //30 seconds
600
+ lobbyID = currentLobby.lobbyID;
601
+ } else {
602
+ lobbyID = await createLobby();
603
+ lobbyID = await updateLobby(lobbyID);
604
+ }
605
+
606
+ for (const steamId of steamIds) {
607
+ onInvite?.(lobbyID, steamId);
608
+ await invite2Lobby(lobbyID, steamId);
609
+ }
610
+
611
+ return lobbyID;
612
+ }
613
+
614
+ async function getLobbyData(lobbyID) {
615
+ if (!steamClient.steamID) {
616
+ return;
617
+ }
618
+
619
+ return new Promise((resolve) => {
620
+ const timeout = setTimeout(function () {
621
+ resolve();
622
+ }, 30000);
623
+
624
+ steamClient._send(
625
+ {
626
+ msg: Protos.csgo.EMsg.k_EMsgClientMMSGetLobbyData,
627
+ proto: {
628
+ steamid: steamClient.steamID.getSteamID64(),
629
+ routing_appid: 730,
630
+ },
631
+ },
632
+ protoEncode(Protos.csgo.CMsgClientMMSGetLobbyData, {
633
+ app_id: 730,
634
+ steam_id_lobby: lobbyID.toString(),
635
+ }),
636
+ function (payload) {
637
+ clearTimeout(timeout);
638
+ const result = protoDecode(Protos.csgo.CMsgClientMMSLobbyData, payload.toBuffer());
639
+ result.steam_id_lobby = result.steam_id_lobby.toString();
640
+ resolve(result);
641
+ },
642
+ );
643
+ });
644
+ }
645
+
646
+ async function joinLobby(lobbyID) {
647
+ log("joinLobby", lobbyID); //SteamID.fromIndividualAccountID(lobbyId).accountid
648
+
649
+ steamClient._send(
650
+ {
651
+ msg: Protos.csgo.EMsg.k_EMsgClientMMSJoinLobby,
652
+ proto: {
653
+ steamid: steamClient.steamID.getSteamID64(),
654
+ routing_appid: 730,
655
+ },
656
+ }, //CMsgClientMMSUserJoinedLobby CMsgClientMMSJoinLobby
657
+ protoEncode(Protos.csgo.CMsgClientMMSJoinLobby, {
658
+ app_id: 730,
659
+ steam_id_lobby: lobbyID,
660
+ persona_name: steamClient.accountInfo.name,
661
+ }),
662
+ function (payload) {
663
+ const result = protoDecode(Protos.csgo.CMsgClientMMSJoinLobbyResponse, payload.toBuffer());
664
+ result.steam_id_lobby = result.steam_id_lobby.toString();
665
+ result.steam_id_owner = result.steam_id_owner.toString();
666
+ console.log(result);
667
+ const resultExample = {
668
+ members: [],
669
+ app_id: 730,
670
+ steam_id_lobby: "3641224920",
671
+ chat_room_enter_response: 2,
672
+ max_members: 0,
673
+ lobby_type: 0,
674
+ lobby_flags: 0,
675
+ steam_id_owner: "0",
676
+ metadata: null, //Buffer
677
+ };
678
+ },
679
+ );
680
+ }
681
+
682
+ async function sendHello() {
683
+ steamClient.sendToGC(AppID, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello, {}, Buffer.alloc(0));
684
+ steamClient.sendToGC(AppID, Protos.csgo.EGCBaseClientMsg.k_EMsgGCClientHello, {}, Buffer.alloc(0));
685
+ }
686
+
687
+ async function requestCoPlays() {
688
+ return new Promise((resolve) => {
689
+ steamClient.sendToGC(AppID, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Account_RequestCoPlays, {}, Buffer.alloc(0));
690
+ pushGCCallback("RequestCoPlays", resolve, 30000);
691
+ });
692
+ }
693
+
694
+ function bindEvent() {
695
+ const _events = {
696
+ async disconnected(eresult, msg) {
697
+ state = "Offline";
698
+ log("disconnected", eresult, msg);
699
+
700
+ callEvent(events.disconnected, { eresult, msg });
701
+
702
+ if (["ServiceUnavailable", "NoConnection"].includes(msg) && autoReconnect && !isLogOff) {
703
+ async function relogin(retry) {
704
+ if (isLogOff) {
705
+ console.error("Cannot relogin (logoff)");
706
+ return false;
707
+ } else if (retry <= 0) {
708
+ console.error("Cannot relogin");
709
+ return false;
710
+ } else {
711
+ const isSuccess = await login(true);
712
+ if (isSuccess) {
713
+ const loggedOnResponse = await new Promise((resolve) => {
714
+ onEvent("loggedOn", resolve, true, 180000);
715
+ });
716
+ if (loggedOnResponse) {
717
+ console.log("Relogin success");
718
+ return true;
719
+ } else {
720
+ const isLogOff = await new Promise((resolve, reject) => {
721
+ logOffEvent = resolve;
722
+ setTimeout(resolve, 120000);
723
+ });
724
+ logOffEvent = null;
725
+ if (isLogOff === true) {
726
+ return false;
727
+ }
728
+ return await relogin(retry - 1);
729
+ }
730
+ } else {
731
+ const isLogOff = await new Promise((resolve, reject) => {
732
+ logOffEvent = resolve;
733
+ setTimeout(resolve, 120000);
734
+ });
735
+ logOffEvent = null;
736
+ if (isLogOff === true) {
737
+ return false;
738
+ }
739
+ return await relogin(retry - 1);
740
+ }
741
+ }
742
+ }
743
+
744
+ const isLogOff = await new Promise((resolve, reject) => {
745
+ logOffEvent = resolve;
746
+ setTimeout(resolve, 60000);
747
+ });
748
+ logOffEvent = null;
749
+ if (isLogOff === true) {
750
+ offAllEvent();
751
+ doClearIntervals();
752
+ } else {
753
+ const isSuccess = await relogin(50);
754
+ if (!isSuccess) {
755
+ offAllEvent();
756
+ doClearIntervals();
757
+ }
758
+ }
759
+ } else {
760
+ offAllEvent();
761
+ doClearIntervals();
762
+ }
763
+ },
764
+ async error(e) {
765
+ let errorStr = "";
766
+ switch (e.eresult) {
767
+ case 5:
768
+ errorStr = "Invalid Password";
769
+ break;
770
+ case 6:
771
+ case 34:
772
+ errorStr = "Logged In Elsewhere";
773
+ break;
774
+ case 84:
775
+ errorStr = "Rate Limit Exceeded";
776
+ break;
777
+ case 65:
778
+ errorStr = "steam guard is invalid";
779
+ break;
780
+ default:
781
+ errorStr = `Unknown: ${e.eresult}`;
782
+ break;
783
+ }
784
+ log(`error [isLogOff: ${isLogOff}]`, e?.message);
785
+ doClearIntervals();
786
+ callEvent(events.error, { eresult: e.eresult, msg: e.message, error: errorStr });
787
+ },
788
+ async webSession(sessionID, cookies) {
789
+ const webSession = { sessionID, cookies };
790
+ steamClient.webSession = webSession;
791
+ callEvent(events.webSession, webSession);
792
+ },
793
+ async receivedFromGC(appid, msgType, payload) {
794
+ const key = getECsgoGCMsgKey(msgType);
795
+ switch (msgType) {
796
+ case Protos.csgo.EMsg.k_EMsgClientChatInvite: {
797
+ log(payload);
798
+ break;
799
+ }
800
+ case Protos.csgo.ECsgoGCMsg.k_EMsgClientMMSJoinLobbyResponse: {
801
+ const msg = protoDecode(Protos.csgo.CMsgClientMMSJoinLobbyResponse, payload);
802
+ log(msg);
803
+ break;
804
+ }
805
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Invite: {
806
+ const msg = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_Party_Invite, payload);
807
+ const sid64 = SteamID.fromIndividualAccountID(msg.accountid).getSteamID64();
808
+ if (events.partyInvite?.length) {
809
+ const personas = await getPersonas([sid64]);
810
+ const player_name = personas.find((p) => p.id == sid64)?.player_name;
811
+ if (player_name === undefined) {
812
+ log(sid64, personas);
813
+ }
814
+ callEvent(events.partyInvite, { player_name, steamId: sid64, lobbyId: msg.lobbyid });
815
+ }
816
+ // log(player_name, `https://steamcommunity.com/profiles/${sid64}`);
817
+ // joinLobby(msg.lobbyid, msg.accountid)
818
+ break;
819
+ }
820
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Account_RequestCoPlays: {
821
+ const msg = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_Account_RequestCoPlays, payload);
822
+ const personas = msg.players.map((p) => SteamID.fromIndividualAccountID(p.accountid));
823
+ callGCCallback("RequestCoPlays", personas);
824
+ break;
825
+ }
826
+ case Protos.csgo.EGCBaseClientMsg.k_EMsgGCClientWelcome: {
827
+ prime = false;
828
+ const CMsgClientWelcome = protoDecode(Protos.csgo.CMsgClientWelcome, payload);
829
+ const obj = {};
830
+ for (const outofdate_cache of CMsgClientWelcome.outofdate_subscribed_caches) {
831
+ for (const cache_object of outofdate_cache.objects) {
832
+ for (const object_data of cache_object.object_data) {
833
+ switch (cache_object.type_id) {
834
+ case 1: {
835
+ const result = protoDecode(Protos.csgo.CSOEconItem, object_data);
836
+ result.id = result.id.toNumber();
837
+ break;
838
+ }
839
+ case 2: {
840
+ const result = protoDecode(Protos.csgo.CSOPersonaDataPublic, object_data);
841
+ obj.PersonaDataPublic = result;
842
+ const example = {
843
+ player_level: 4,
844
+ commendation: {
845
+ cmd_friendly: 149,
846
+ cmd_teaching: 108,
847
+ cmd_leader: 115,
848
+ },
849
+ elevated_state: true,
850
+ };
851
+ break;
852
+ }
853
+ case 5: {
854
+ const result = protoDecode(Protos.csgo.CSOItemRecipe, object_data);
855
+ break;
856
+ }
857
+ case 7: {
858
+ const CSOEconGameAccountClient = protoDecode(Protos.csgo.CSOEconGameAccountClient, object_data);
859
+ const CSOEconGameAccountClientExample = {
860
+ additional_backpack_slots: 0,
861
+ bonus_xp_timestamp_refresh: 1688518800, //Wednesday 1:00:00 AM every week
862
+ bonus_xp_usedflags: 19,
863
+ elevated_state: 5,
864
+ elevated_timestamp: 5,
865
+ }; //1688518800
866
+ if ((CSOEconGameAccountClient.bonus_xp_usedflags & 16) != 0) {
867
+ // EXPBonusFlag::PrestigeEarned
868
+ prime = true;
869
+ CSOEconGameAccountClient.prime = true;
870
+ }
871
+ if (CSOEconGameAccountClient.elevated_state === 5) {
872
+ // bought prime
873
+ prime = true;
874
+ CSOEconGameAccountClient.prime = true;
875
+ }
876
+ obj.GameAccountClient = CSOEconGameAccountClient;
877
+ break;
878
+ }
879
+
880
+ case 35: {
881
+ // const result =protoDecode(Protos.csgo.CSOSelectedItemPreset, object_data);
882
+ break;
883
+ }
884
+
885
+ case 36: {
886
+ // const result =protoDecode(Protos.csgo.CSOEconItemPresetInstance, object_data);
887
+ break;
888
+ }
889
+ case 38: {
890
+ const result = protoDecode(Protos.csgo.CSOEconItemDropRateBonus, object_data);
891
+ break;
892
+ }
893
+ case 39: {
894
+ const result = protoDecode(Protos.csgo.CSOEconItemLeagueViewPass, object_data);
895
+ break;
896
+ }
897
+ case 40: {
898
+ const result = protoDecode(Protos.csgo.CSOEconItemEventTicket, object_data);
899
+ break;
900
+ }
901
+ case 41: {
902
+ const result = protoDecode(Protos.csgo.CSOAccountSeasonalOperation, object_data);
903
+ break;
904
+ }
905
+ case 42: {
906
+ // const result =protoDecode(Protos.csgo.CSOEconItemTournamentPassport, object_data);
907
+ break;
908
+ }
909
+ case 43: {
910
+ const result = protoDecode(Protos.csgo.CSOEconDefaultEquippedDefinitionInstanceClient, object_data);
911
+ const example = {
912
+ account_id: 1080136620,
913
+ item_definition: 61,
914
+ class_id: 3,
915
+ slot_id: 2,
916
+ };
917
+ break;
918
+ }
919
+ case 45: {
920
+ const result = protoDecode(Protos.csgo.CSOEconCoupon, object_data);
921
+ break;
922
+ }
923
+ case 46: {
924
+ const result = protoDecode(Protos.csgo.CSOQuestProgress, object_data);
925
+ break;
926
+ }
927
+ case 4: {
928
+ const result = protoDecode(Protos.csgo.CSOAccountItemPersonalStore, object_data);
929
+ result.generation_time = result.generation_time * 1000;
930
+ if (Array.isArray(result.items)) {
931
+ result.items = result.items.map((item) => item.toNumber());
932
+ }
933
+ obj.personalStore = result;
934
+ break;
935
+ }
936
+
937
+ default: {
938
+ log("cache_object.type_id", cache_object.type_id);
939
+ }
940
+ }
941
+ }
942
+ }
943
+ }
944
+ callEvent(events.csgoOnline, obj);
945
+
946
+ if (isPartyRegister) {
947
+ partyRegister();
948
+ doSetInterval(
949
+ function () {
950
+ partyRegister();
951
+ },
952
+ [60000, 120000],
953
+ "autoPartyRegister",
954
+ );
955
+ }
956
+ break;
957
+ }
958
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchmakingGC2ClientUpdate: {
959
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_MatchmakingGC2ClientUpdate, payload);
960
+ break;
961
+ }
962
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_GC2ClientGlobalStats: {
963
+ const result = protoDecode(Protos.csgo.CMsgClientUGSGetGlobalStatsResponse, payload);
964
+ break;
965
+ }
966
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientReportPlayer: {
967
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientReportPlayer, payload);
968
+ break;
969
+ }
970
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_GC2ClientTextMsg: {
971
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_GC2ClientTextMsg, payload);
972
+ break;
973
+ }
974
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello: {
975
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_MatchmakingGC2ClientHello, payload);
976
+ const example = {
977
+ my_current_event_teams: [],
978
+ my_current_event_stages: [],
979
+ rankings: [],
980
+ account_id: 1080136620,
981
+ ongoingmatch: null,
982
+ global_stats: {
983
+ search_statistics: [
984
+ {
985
+ game_type: 520,
986
+ search_time_avg: 0,
987
+ players_searching: 5141,
988
+ },
989
+ {
990
+ game_type: 32776,
991
+ search_time_avg: 0,
992
+ players_searching: 6561,
993
+ },
994
+ ],
995
+ players_online: 617207,
996
+ servers_online: 230638,
997
+ players_searching: 13550,
998
+ servers_available: 126352,
999
+ ongoing_matches: 23264,
1000
+ search_time_avg: 95993,
1001
+ main_post_url: "*XA=https://blast.tv/live*XT=https://www.twitch.tv/blastpremier*XB=https://live.bilibili.com/35*XG=playcast://https://gotv.blast.tv/major-a*T=SGTAB*L=2@https://steamcommunity.com/broadcast/watch/76561199492362089",
1002
+ required_appid_version: 13879,
1003
+ pricesheet_version: 1688084844,
1004
+ twitch_streams_version: 2,
1005
+ active_tournament_eventid: 21,
1006
+ active_survey_id: 0,
1007
+ rtime32_cur: 0,
1008
+ rtime32_event_start: 0,
1009
+ },
1010
+ penalty_seconds: 0,
1011
+ penalty_reason: 0,
1012
+ vac_banned: 0,
1013
+ ranking: {
1014
+ account_id: 1080136620,
1015
+ rank_id: 10,
1016
+ wins: 209,
1017
+ rank_change: 0,
1018
+ rank_type_id: 6,
1019
+ tv_control: 0,
1020
+ },
1021
+ commendation: {
1022
+ cmd_friendly: 149,
1023
+ cmd_teaching: 108,
1024
+ cmd_leader: 115,
1025
+ },
1026
+ medals: null,
1027
+ my_current_event: null,
1028
+ my_current_team: null,
1029
+ survey_vote: 0,
1030
+ activity: null,
1031
+ player_level: 4,
1032
+ player_cur_xp: 327684501,
1033
+ player_xp_bonus_flags: 0,
1034
+ };
1035
+ if (result?.global_stats?.required_appid_version && (!CSGO_VER || result.global_stats.required_appid_version > CSGO_VER)) {
1036
+ CSGO_VER = result.global_stats.required_appid_version;
1037
+ }
1038
+ callEvent(events.csgoClientHello, result);
1039
+ break;
1040
+ }
1041
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientReportResponse: {
1042
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientReportResponse, payload);
1043
+ break;
1044
+ }
1045
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientCommendPlayerQueryResponse: {
1046
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientCommendPlayer, payload);
1047
+ break;
1048
+ }
1049
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_PlayerOverwatchCaseAssignment: {
1050
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_PlayerOverwatchCaseAssignment, payload);
1051
+ break;
1052
+ }
1053
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchList: {
1054
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_MatchList, payload);
1055
+ break;
1056
+ }
1057
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_GetEventFavorites_Response: {
1058
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_GetEventFavorites_Response, payload);
1059
+ break;
1060
+ }
1061
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_StartAgreementSessionInGame: {
1062
+ break;
1063
+ }
1064
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_ClientDeepStats: {
1065
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_ClientDeepStats, payload);
1066
+ break;
1067
+ }
1068
+ case Protos.csgo.EGCBaseClientMsg.k_EMsgGCClientConnectionStatus: {
1069
+ const result = protoDecode(Protos.csgo.CMsgConnectionStatus, payload);
1070
+ break;
1071
+ }
1072
+ case Protos.csgo.EGCItemMsg.k_EMsgGCStoreGetUserDataResponse: {
1073
+ const result = protoDecode(Protos.csgo.CMsgStoreGetUserDataResponse, payload);
1074
+ break;
1075
+ }
1076
+ case Protos.csgo.EGCItemMsg.k_EMsgGCStorePurchaseFinalizeResponse: {
1077
+ const result = protoDecode(Protos.csgo.CMsgGCStorePurchaseFinalizeResponse, payload);
1078
+ break;
1079
+ }
1080
+ case Protos.csgo.EGCItemMsg.k_EMsgGCStorePurchaseCancelResponse: {
1081
+ const result = protoDecode(Protos.csgo.CMsgGCStorePurchaseCancelResponse, payload);
1082
+ break;
1083
+ }
1084
+ case Protos.csgo.EGCItemMsg.k_EMsgGCStorePurchaseInitResponse: {
1085
+ const result = protoDecode(Protos.csgo.CMsgGCStorePurchaseInitResponse, payload);
1086
+ break;
1087
+ }
1088
+ case Protos.csgo.EMsg.k_EMsgClientMMSCreateLobbyResponse: {
1089
+ const result = protoDecode(Protos.csgo.CMsgClientMMSCreateLobbyResponse, payload);
1090
+ console.log("k_EMsgClientMMSCreateLobbyResponse", result);
1091
+ break;
1092
+ }
1093
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientGCRankUpdate: {
1094
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientGCRankUpdate, payload);
1095
+ break;
1096
+ }
1097
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Search: {
1098
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_Party_SearchResults, payload);
1099
+ const entries = _.uniqBy(result.entries, "id");
1100
+ //{
1101
+ // id: 144900402,
1102
+ // grp: 0,
1103
+ // game_type: 8,
1104
+ // apr: 1,
1105
+ // ark: 17,
1106
+ // loc: 20041,
1107
+ // accountid: 0
1108
+ // }
1109
+
1110
+ //{
1111
+ // id: "76561199265943339",
1112
+ // rich_presence: [],
1113
+ // persona_state: null,
1114
+ // game_played_app_id: null,
1115
+ // game_server_ip: null,
1116
+ // game_server_port: null,
1117
+ // persona_state_flags: null,
1118
+ // online_session_instances: null,
1119
+ // persona_set_by_user: null,
1120
+ // player_name: "杀人不见血",
1121
+ // query_port: null,
1122
+ // steamid_source: null,
1123
+ // avatar_hash: "33994e26f1fe7e2093f8c7dee66c1ac91531050d",
1124
+ // last_logoff: null,
1125
+ // last_logon: null,
1126
+ // last_seen_online: null,
1127
+ // clan_rank: null,
1128
+ // game_name: null,
1129
+ // gameid: null,
1130
+ // game_data_blob: null,
1131
+ // clan_data: null,
1132
+ // clan_tag: null,
1133
+ // broadcast_id: null,
1134
+ // game_lobby_id: null,
1135
+ // watching_broadcast_accountid: null,
1136
+ // watching_broadcast_appid: null,
1137
+ // watching_broadcast_viewers: null,
1138
+ // watching_broadcast_title: null,
1139
+ // is_community_banned: null,
1140
+ // player_name_pending_review: null,
1141
+ // avatar_pending_review: null,
1142
+ // avatar_url_icon: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/33/33994e26f1fe7e2093f8c7dee66c1ac91531050d.jpg",
1143
+ // avatar_url_medium: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/33/33994e26f1fe7e2093f8c7dee66c1ac91531050d_medium.jpg",
1144
+ // avatar_url_full: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/33/33994e26f1fe7e2093f8c7dee66c1ac91531050d_full.jpg"
1145
+ // }
1146
+
1147
+ const players = [];
1148
+ for (const player of entries) {
1149
+ try {
1150
+ const prime = player.apr === 1 ? "PRIME" : "NON-PRIME";
1151
+ const loc = LOCS[player.loc] || player.loc;
1152
+ const steamId = SteamID.fromIndividualAccountID(player.id).getSteamID64();
1153
+ const friendCode = FriendCode.encode(steamId);
1154
+
1155
+ // if ((LOCS[player.loc] == 'VN' || !LOCS[player.loc])) {
1156
+ players.push({
1157
+ prime,
1158
+ rank: RANKS[player.ark] !== undefined ? RANKS[player.ark] : player.ark,
1159
+ loc,
1160
+ steamId,
1161
+ friendCode,
1162
+ });
1163
+ // }
1164
+ } catch (e) {}
1165
+ }
1166
+
1167
+ callGCCallback("partySearch", players);
1168
+ break;
1169
+ }
1170
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_PlayersProfile: {
1171
+ let data = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_PlayersProfile, payload)?.account_profiles;
1172
+ const dataExample = [
1173
+ {
1174
+ my_current_event_teams: [],
1175
+ my_current_event_stages: [],
1176
+ rankings: [
1177
+ {
1178
+ account_id: 1225887169,
1179
+ rank_id: 0,
1180
+ wins: 6,
1181
+ rank_change: 0,
1182
+ rank_type_id: 7,
1183
+ tv_control: 0,
1184
+ },
1185
+ {
1186
+ account_id: 1225887169,
1187
+ rank_id: 0,
1188
+ wins: 0,
1189
+ rank_change: 0,
1190
+ rank_type_id: 10,
1191
+ tv_control: 0,
1192
+ },
1193
+ ],
1194
+ account_id: 1225887169,
1195
+ ongoingmatch: null,
1196
+ global_stats: null,
1197
+ penalty_seconds: 0,
1198
+ penalty_reason: 0,
1199
+ vac_banned: 0,
1200
+ ranking: {
1201
+ account_id: 1225887169,
1202
+ rank_id: 8,
1203
+ wins: 469,
1204
+ rank_change: 0,
1205
+ rank_type_id: 6,
1206
+ tv_control: 0,
1207
+ },
1208
+ commendation: {
1209
+ cmd_friendly: 51,
1210
+ cmd_teaching: 40,
1211
+ cmd_leader: 40,
1212
+ },
1213
+ medals: {
1214
+ display_items_defidx: [4819, 4737],
1215
+ featured_display_item_defidx: 4819,
1216
+ },
1217
+ my_current_event: null,
1218
+ my_current_team: null,
1219
+ survey_vote: 0,
1220
+ activity: null,
1221
+ player_level: 32,
1222
+ player_cur_xp: 327682846,
1223
+ player_xp_bonus_flags: 0,
1224
+ },
1225
+ ];
1226
+
1227
+ const player = data?.[0];
1228
+ if (player) {
1229
+ player.prime = !!(player.ranking?.account_id || player.player_level || player.player_cur_xp);
1230
+ player.steamId = SteamID.fromIndividualAccountID(player.account_id).getSteamID64();
1231
+ callGCCallback(`PlayersProfile_${player.account_id}`, player);
1232
+ }
1233
+ callEvent(events.playersProfile, player);
1234
+ break;
1235
+ }
1236
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientLogonFatalError: {
1237
+ const data = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientLogonFatalError, payload);
1238
+ console.log(data);
1239
+ const dataExample = {
1240
+ errorcode: 4,
1241
+ message: "",
1242
+ country: "VN",
1243
+ };
1244
+ callEvent(events.fatalError, data);
1245
+ break;
1246
+ }
1247
+ default:
1248
+ log(`receivedFromGC ${msgType} ${key}`);
1249
+ const results = Object.values(Protos.csgo)
1250
+ .map(function (p) {
1251
+ try {
1252
+ return protoDecode(p, payload);
1253
+ } catch (e) {}
1254
+ })
1255
+ .filter(function (result) {
1256
+ return result && Object.keys(result).length;
1257
+ });
1258
+ log(key, results);
1259
+ }
1260
+ },
1261
+ async loggedOn(loggedOnResponse) {
1262
+ callEvent(events.loggedOn, loggedOnResponse);
1263
+ updateInvisible();
1264
+ updateAutoRequestFreeLicense();
1265
+ updateAutoGamePlay();
1266
+ },
1267
+ async user(steamId, data) {
1268
+ callEvent(events.user, { steamId: steamId.getSteamID64(), data });
1269
+ const dataExample = {
1270
+ rich_presence: [
1271
+ {
1272
+ key: "status",
1273
+ value: "Competitive Mirage [ 3 : 6 ]",
1274
+ },
1275
+ {
1276
+ key: "version",
1277
+ value: "13875",
1278
+ },
1279
+ {
1280
+ key: "game:state",
1281
+ value: "game",
1282
+ },
1283
+ {
1284
+ key: "steam_display",
1285
+ value: "#display_GameKnownMapScore",
1286
+ },
1287
+ {
1288
+ key: "game:mode",
1289
+ value: "competitive",
1290
+ },
1291
+ {
1292
+ key: "game:mapgroupname",
1293
+ value: "mg_de_mirage",
1294
+ },
1295
+ {
1296
+ key: "game:map",
1297
+ value: "de_mirage",
1298
+ },
1299
+ {
1300
+ key: "game:server",
1301
+ value: "kv",
1302
+ },
1303
+ {
1304
+ key: "watch",
1305
+ value: "1",
1306
+ },
1307
+ {
1308
+ key: "steam_player_group",
1309
+ value: "2134948645",
1310
+ },
1311
+ {
1312
+ key: "game:score",
1313
+ value: "[ 3 : 6 ]",
1314
+ },
1315
+ ],
1316
+ friendid: "76561199405834425",
1317
+ persona_state: 1,
1318
+ game_played_app_id: 730,
1319
+ game_server_ip: null,
1320
+ game_server_port: null,
1321
+ persona_state_flags: 1,
1322
+ online_session_instances: 1,
1323
+ persona_set_by_user: null,
1324
+ player_name: "quỷ súng",
1325
+ query_port: null,
1326
+ steamid_source: "0",
1327
+ avatar_hash: {
1328
+ type: "Buffer",
1329
+ data: [23, 163, 216, 209, 236, 179, 73, 228, 225, 30, 48, 190, 192, 170, 177, 246, 139, 71, 122, 205],
1330
+ },
1331
+ last_logoff: 1683950268,
1332
+ last_logon: 1683950281,
1333
+ last_seen_online: 1683950268,
1334
+ clan_rank: null,
1335
+ game_name: "",
1336
+ gameid: "730",
1337
+ game_data_blob: {
1338
+ type: "Buffer",
1339
+ data: [],
1340
+ },
1341
+ clan_data: null,
1342
+ clan_tag: null,
1343
+ broadcast_id: "0",
1344
+ game_lobby_id: "0",
1345
+ watching_broadcast_accountid: null,
1346
+ watching_broadcast_appid: null,
1347
+ watching_broadcast_viewers: null,
1348
+ watching_broadcast_title: null,
1349
+ is_community_banned: null,
1350
+ player_name_pending_review: null,
1351
+ avatar_pending_review: null,
1352
+ };
1353
+ },
1354
+ async playingState(playing_blocked, playing_app) {
1355
+ playingBlocked = playing_blocked;
1356
+ if (playing_app === 0) {
1357
+ playing_app = null;
1358
+ }
1359
+ if (playing_blocked) {
1360
+ //true, false
1361
+ console.log("Playing else where");
1362
+ }
1363
+ log("playingState", playing_blocked, playing_app);
1364
+ callEvent(events.playingState, { playing_blocked, playing_app });
1365
+ },
1366
+ async friendRelationship(sid, relationship, previousRelationship) {
1367
+ callEvent(events.friendRelationship, {
1368
+ steamId: sid.getSteamID64(),
1369
+ relationship,
1370
+ previousRelationship,
1371
+ });
1372
+ switch (relationship) {
1373
+ case EFriendRelationship.None: {
1374
+ //we got unfriended.
1375
+ break;
1376
+ }
1377
+ case EFriendRelationship.RequestRecipient: {
1378
+ //we got invited as a friend
1379
+ break;
1380
+ }
1381
+ case EFriendRelationship.Friend: {
1382
+ //we got added as a friend
1383
+ break;
1384
+ }
1385
+ }
1386
+ },
1387
+ async tradeOffers(count) {
1388
+ callEvent(events.tradeOffers, count);
1389
+ },
1390
+ async offlineMessages(count, friends) {
1391
+ callEvent(events.offlineMessages, { count, steamIdList: friends });
1392
+ },
1393
+ async tradeRequest(steamID, respond) {
1394
+ if (autoAcceptTradeRequest) {
1395
+ log(`Incoming trade request from ${steamID.getSteam3RenderedID()}, accepting`);
1396
+ respond(true);
1397
+ } else {
1398
+ log(`Incoming trade request from ${steamID.getSteam3RenderedID()}, wating`);
1399
+ }
1400
+ },
1401
+ async friendsList() {
1402
+ callEvent(events.friendsList, getFriendList());
1403
+ },
1404
+ async gifts(gid, packageid, TimeCreated, TimeExpiration, TimeSent, TimeAcked, TimeRedeemed, RecipientAddress, SenderAddress, SenderName) {
1405
+ callEvent(events.gifts, {
1406
+ gid,
1407
+ packageid,
1408
+ TimeCreated,
1409
+ TimeExpiration,
1410
+ TimeSent,
1411
+ TimeAcked,
1412
+ TimeRedeemed,
1413
+ RecipientAddress,
1414
+ SenderAddress,
1415
+ SenderName,
1416
+ });
1417
+ },
1418
+ async emailInfo(address, validated) {
1419
+ callEvent(events.emailInfo, { address, validated });
1420
+ },
1421
+ async appLaunched() {
1422
+ setTimeout(function () {
1423
+ state = getPlayingAppIds().length ? "InGame" : isInvisible ? "Invisible" : "Online";
1424
+ }, 1000);
1425
+ },
1426
+ async appQuit() {
1427
+ setTimeout(function () {
1428
+ state = getPlayingAppIds().length ? "InGame" : isInvisible ? "Invisible" : "Online";
1429
+ }, 1000);
1430
+ },
1431
+ async accountLimitations(bis_limited_account, bis_community_banned, bis_locked_account, bis_limited_account_allowed_to_invite_friends) {
1432
+ callEvent(events.accountLimitations, {
1433
+ limited: bis_limited_account,
1434
+ communityBanned: bis_community_banned,
1435
+ locked: bis_locked_account,
1436
+ canInviteFriends: bis_limited_account_allowed_to_invite_friends,
1437
+ });
1438
+ },
1439
+ };
1440
+
1441
+ const _chatEvents = {
1442
+ async friendMessage(data) {
1443
+ if (!data) return;
1444
+ data.message_no_bbcode = data.message_no_bbcode?.replaceAll("ː", ":");
1445
+ data.message = data.message?.replaceAll("ː", ":");
1446
+ const example = {
1447
+ steamid_friend: {
1448
+ universe: 1,
1449
+ type: 1,
1450
+ instance: 1,
1451
+ accountid: 1080136620,
1452
+ },
1453
+ chat_entry_type: 1,
1454
+ from_limited_account: false,
1455
+ message: "xxx",
1456
+ ordinal: 0,
1457
+ local_echo: false,
1458
+ message_no_bbcode: "xxx",
1459
+ low_priority: false,
1460
+ server_timestamp: "2023-05-14T09:26:25.000Z",
1461
+ message_bbcode_parsed: ["xxx"],
1462
+ };
1463
+ const timestamp = new Date(data.server_timestamp).getTime();
1464
+ const steamId = data.steamid_friend.getSteamID64();
1465
+ const invite = ["Invited you to play a game!", "Đã mời bạn chơi một trò chơi!"].includes(data.message_no_bbcode || data.message);
1466
+ const emotion = (data.message_no_bbcode || "").split(" ").find((m) => m.startsWith(":") && m.endsWith(":"));
1467
+
1468
+ callEvent(events.friendMessage, {
1469
+ ...data,
1470
+ message: data.message_no_bbcode,
1471
+ invite,
1472
+ steamId,
1473
+ timestamp,
1474
+ emotion,
1475
+ });
1476
+ },
1477
+ async friendTyping(steamId, message) {
1478
+ callEvent(events.friendTyping, {
1479
+ steamId,
1480
+ message,
1481
+ });
1482
+ },
1483
+ };
1484
+
1485
+ // steamClient.on('lobbyInvite', (inviterID, lobbyID ) => {
1486
+ // joinLobby(lobbyID)
1487
+ // })
1488
+
1489
+ // steamClient.on('debug', (msg) => {
1490
+ // if (!["ClientPersonaState","ClientClanState"].some(c => msg.includes(c))) {
1491
+ // if(msg.startsWith("Received")){
1492
+ // console.log(`------- ${msg}`)
1493
+ // } else {
1494
+ // console.log(msg)
1495
+ // }
1496
+ // }
1497
+ // })
1498
+
1499
+ function getECsgoGCMsgKey(_key) {
1500
+ for (let key in Protos.csgo.ECsgoGCMsg) {
1501
+ if (Protos.csgo.ECsgoGCMsg[key] == _key) {
1502
+ return key;
1503
+ }
1504
+ }
1505
+ for (let key in Protos.csgo.EGCBaseClientMsg) {
1506
+ if (Protos.csgo.EGCBaseClientMsg[key] == _key) {
1507
+ return key;
1508
+ }
1509
+ }
1510
+ for (let key in Protos.csgo.EMsg) {
1511
+ if (Protos.csgo.EMsg[key] == _key) {
1512
+ return key;
1513
+ }
1514
+ }
1515
+ for (let key in Protos.csgo.EGCItemMsg) {
1516
+ if (Protos.csgo.EGCItemMsg[key] == _key) {
1517
+ return key;
1518
+ }
1519
+ }
1520
+ }
1521
+
1522
+ for (const [name, _event] of Object.entries(_events)) {
1523
+ steamClient.on(name, _event);
1524
+ }
1525
+
1526
+ for (const [name, _event] of Object.entries(_chatEvents)) {
1527
+ steamClient.chat.on(name, _event);
1528
+ }
1529
+ }
1530
+
1531
+ function getHandlerResult(msg, handler) {
1532
+ const timeout = { current: null };
1533
+ return new Promise((resolve) => {
1534
+ function myhandler(...args) {
1535
+ timeout.current && clearTimeout(timeout.current);
1536
+ removeHandler();
1537
+ resolve(handler?.(...args));
1538
+ }
1539
+
1540
+ function removeHandler() {
1541
+ if (Array.isArray(steamClient._handlerManager._handlers[msg])) {
1542
+ const index = steamClient._handlerManager._handlers[msg].findIndex((_handler) => _handler === myhandler);
1543
+ if (index > -1) {
1544
+ steamClient._handlerManager._handlers[msg].splice(index, 1);
1545
+ }
1546
+ }
1547
+ }
1548
+
1549
+ timeout.current = setTimeout(function () {
1550
+ removeHandler();
1551
+ resolve();
1552
+ }, 60000);
1553
+ steamClient._handlerManager.add(msg, myhandler);
1554
+ });
1555
+ }
1556
+
1557
+ function getFriendList() {
1558
+ return Object.keys(steamClient.myFriends).filter((steamId) => steamClient.myFriends[steamId] === NodeSteamUser.EFriendRelationship.Friend);
1559
+ }
1560
+
1561
+ function sendFriendTyping(steamId, callback) {
1562
+ steamClient.chat.sendFriendTyping(steamId, callback);
1563
+ }
1564
+
1565
+ /*
1566
+ * usually take 400 -> 800 miliseconds
1567
+ * */
1568
+ function getPlayersProfile(steamId) {
1569
+ const accountid = new SteamID(steamId).accountid;
1570
+ steamClient.sendToGC(
1571
+ 730,
1572
+ Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientRequestPlayersProfile,
1573
+ {},
1574
+ protoEncode(Protos.csgo.CMsgGCCStrike15_v2_ClientRequestPlayersProfile, {
1575
+ account_id: accountid, // account_id: new SteamID('76561199184696945').accountid,
1576
+ request_level: 32,
1577
+ }),
1578
+ );
1579
+ return new Promise((resolve) => {
1580
+ pushGCCallback(`PlayersProfile_${accountid}`, resolve, 2000);
1581
+ });
1582
+ }
1583
+
1584
+ async function checkPlayerPrimeStatus(steamId) {
1585
+ const profile = await getPlayersProfile(steamId);
1586
+ if (!profile) return false;
1587
+
1588
+ if (profile.ranking?.account_id) {
1589
+ return true;
1590
+ }
1591
+
1592
+ if (profile.player_level || profile.player_cur_xp) {
1593
+ return true;
1594
+ }
1595
+ return false;
1596
+ }
1597
+
1598
+ async function _getStoreSteamPoweredResponse(cookie) {
1599
+ let response = null;
1600
+ for (let i = 0; i < 50; i++) {
1601
+ if (!response) {
1602
+ try {
1603
+ response = await axios.request({
1604
+ url: "https://store.steampowered.com/",
1605
+ headers: {
1606
+ cookie,
1607
+ accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.75",
1608
+ },
1609
+ });
1610
+ } catch (e) {
1611
+ await sleep(1000);
1612
+ }
1613
+ }
1614
+ }
1615
+ return response;
1616
+ }
1617
+
1618
+ async function getNewCookie(cookie) {
1619
+ if (!cookie) {
1620
+ return;
1621
+ }
1622
+ let response = await _getStoreSteamPoweredResponse(cookie);
1623
+ if (!response) {
1624
+ return;
1625
+ }
1626
+ while (Array.isArray(response?.headers?.["set-cookie"])) {
1627
+ console.log(cookie);
1628
+ const cookieObj = cookie.split(";").reduce(function (accumulator, currentValue) {
1629
+ accumulator[currentValue.trim().split("=")[0].trim()] = currentValue.trim().split("=")[1].trim();
1630
+ return accumulator;
1631
+ }, {});
1632
+ for (const mcookie of response.headers["set-cookie"]) {
1633
+ const name = mcookie.split("=")[0].trim();
1634
+ const value = mcookie.split("=")[1].split(";")[0].trim();
1635
+ cookieObj[name] = value;
1636
+ }
1637
+ cookie = Object.keys(cookieObj)
1638
+ .map((name) => `${name}=${cookieObj[name]}`)
1639
+ .join(";");
1640
+ response = await _getStoreSteamPoweredResponse(cookie);
1641
+ }
1642
+ return cookie;
1643
+ }
1644
+
1645
+ async function loginWithCookie(cookie, tryNewCookie = false) {
1646
+ let response;
1647
+ for (let i = 0; i < 20; i++) {
1648
+ try {
1649
+ response = await axios.request({
1650
+ url: "https://steamcommunity.com/chat/clientjstoken",
1651
+ headers: {
1652
+ cookie,
1653
+ },
1654
+ });
1655
+ } catch (e) {
1656
+ await sleep(1000);
1657
+ }
1658
+ if (response) {
1659
+ break;
1660
+ }
1661
+ }
1662
+
1663
+ const result = response?.data;
1664
+ if (result?.logged_in) {
1665
+ Object.assign(result, {
1666
+ steamID: new SteamID(result.steamid),
1667
+ accountName: result.account_name,
1668
+ webLogonToken: result.token,
1669
+ });
1670
+ steamClient.logOn(result);
1671
+ return cookie;
1672
+ } else {
1673
+ if (tryNewCookie) {
1674
+ log("You are not logged in", cookie);
1675
+ return null;
1676
+ } else {
1677
+ const newCookie = await getNewCookie(cookie);
1678
+ if (!newCookie) {
1679
+ console.error("Cannot get new cookie");
1680
+ return null;
1681
+ } else {
1682
+ return await loginWithCookie(newCookie, true);
1683
+ }
1684
+ }
1685
+ }
1686
+ }
1687
+
1688
+ async function login(reconnect = false) {
1689
+ if (clientJsToken?.logged_in === true) {
1690
+ log(reconnect ? "reconnect with clientJsToken" : "login with clientJsToken");
1691
+ steamClient.logOn(clientJsToken);
1692
+ setTimeout(function () {
1693
+ clientJsToken = null;
1694
+ }, 1000);
1695
+ return true;
1696
+ } else if (cookie) {
1697
+ log(reconnect ? "reconnect with cookie" : "login with cookie");
1698
+ const _clientJsToken = await new SteamUser(typeof cookie === "function" ? await cookie() : cookie).getClientJsToken();
1699
+ if (_clientJsToken?.logged_in === true) {
1700
+ try {
1701
+ await steamClient.logOn(_clientJsToken);
1702
+ return true;
1703
+ } catch (e) {
1704
+ return false;
1705
+ }
1706
+ } else {
1707
+ return false;
1708
+ }
1709
+ } else if (username && password) {
1710
+ log(reconnect ? `reconnect with username ${username}` : `login with username ${username}`);
1711
+ steamClient.logOn({
1712
+ accountName: username,
1713
+ password: password,
1714
+ rememberPassword: true,
1715
+ machineName: "Natri",
1716
+ });
1717
+ return true;
1718
+ }
1719
+ }
1720
+
1721
+ async function logOff() {
1722
+ isLogOff = true;
1723
+ logOffEvent?.(true);
1724
+ steamClient.logOff();
1725
+ }
1726
+
1727
+ function onCookie(callback) {
1728
+ if (getCookies()) {
1729
+ callback(getCookies());
1730
+ } else {
1731
+ onEvent(
1732
+ "webSession",
1733
+ function (webSession) {
1734
+ callback(webSession?.cookies?.join?.(";"));
1735
+ },
1736
+ true,
1737
+ );
1738
+ }
1739
+ }
1740
+
1741
+ function init() {
1742
+ bindEvent();
1743
+ login();
1744
+
1745
+ steamClient._handlerManager.add(Protos.csgo.EMsg.k_EMsgClientRequestedClientStats, function (payload) {
1746
+ const result = protoDecode(Protos.csgo.CMsgClientRequestedClientStats, payload.toBuffer());
1747
+ // console.log("CMsgClientRequestedClientStats", result);
1748
+ });
1749
+ steamClient._handlerManager.add(Protos.csgo.EMsg.k_EMsgClientMMSLobbyData, function (payload) {
1750
+ const result = protoDecode(Protos.csgo.CMsgClientMMSLobbyData, payload.toBuffer());
1751
+ // console.log("CMsgClientMMSLobbyData", result, result.metadata);
1752
+ });
1753
+ }
1754
+
1755
+ function partyRegister() {
1756
+ if (prime === null) {
1757
+ _partyRegister(true);
1758
+ _partyRegister(false);
1759
+ } else {
1760
+ _partyRegister(prime);
1761
+ }
1762
+ }
1763
+
1764
+ function _partyRegister(prime) {
1765
+ log("partyRegister", prime);
1766
+ lastTimePartyRegister = new Date().getTime();
1767
+ steamClient.sendToGC(
1768
+ 730,
1769
+ Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Register,
1770
+ {},
1771
+ protoEncode(Protos.csgo.CMsgGCCStrike15_v2_Party_Register, {
1772
+ // id : 0,
1773
+ ver: CSGO_VER,
1774
+ apr: prime ? 1 : 0, //prime
1775
+ ark: prime ? 180 : 0,
1776
+ grps: [],
1777
+ launcher: 0,
1778
+ game_type: 8,
1779
+ }),
1780
+ );
1781
+ }
1782
+
1783
+ async function sendFriendMessage(steamId, message) {
1784
+ while (sendMessageTimestamp && new Date().getTime() - sendMessageTimestamp < 2000) {
1785
+ await sleep(1000);
1786
+ }
1787
+
1788
+ while (isSendingFriendMessages) {
1789
+ await sleep(5000);
1790
+ }
1791
+
1792
+ isSendingFriendMessages = true;
1793
+ const now = new Date().getTime();
1794
+ while (new Date().getTime() - now < 2 * 60000) {
1795
+ //2 minutes
1796
+ const result = await new Promise((resolve) => {
1797
+ steamClient.chat.sendFriendMessage(steamId, message, undefined, function (...arg) {
1798
+ sendMessageTimestamp = new Date().getTime();
1799
+ resolve(arg);
1800
+ });
1801
+ });
1802
+
1803
+ if (result?.[1]?.server_timestamp) {
1804
+ isSendingFriendMessages = false;
1805
+ return result?.[1];
1806
+ } else if (result?.[0]?.message?.includes?.("RateLimitExceeded")) {
1807
+ await sleep(5000);
1808
+ } else {
1809
+ isSendingFriendMessages = false;
1810
+ return result;
1811
+ }
1812
+ }
1813
+ isSendingFriendMessages = false;
1814
+ }
1815
+
1816
+ async function autoRequestFreeLicense(shouldLog = false, max = 10) {
1817
+ return;
1818
+ // const mCookies = await getCookiesWait()
1819
+ // if (!mCookies) return
1820
+ // let freeAppList = Array.isArray(steamClient.licenses) ? FreeAppList.filter(appId => steamClient.licenses.every(({package_id}) => package_id !== appId)) : FreeAppList;
1821
+ const freeAppList = freeAppList.filter((appId) => ownedApps.some((app) => app.appid == appId));
1822
+ const recommendedApps = _.shuffle(freeAppList);
1823
+ if (max) {
1824
+ recommendedApps.length = Math.min(recommendedApps.length, max);
1825
+ }
1826
+ try {
1827
+ const response = await steamClient.requestFreeLicense(recommendedApps);
1828
+ if (shouldLog) {
1829
+ log(response);
1830
+ }
1831
+ } catch (e) {
1832
+ log(e);
1833
+ }
1834
+ // if (Math.random() > 0.7) {
1835
+ // for (const recommendedApp of recommendedApps) {
1836
+ // try {
1837
+ // await steamUtils.requestFreeLicense(recommendedApp)
1838
+ // } catch (e) {
1839
+ // }
1840
+ // await sleep(2000)
1841
+ // }
1842
+ // } else {
1843
+ // try {
1844
+ // await steamClient.requestFreeLicense(recommendedApps)
1845
+ // } catch (e) {
1846
+ // log(e);
1847
+ // }
1848
+ // }
1849
+
1850
+ // if (shouldLog) {
1851
+ // await sleep(20000)
1852
+ // const ownedAppsCount2 = (await steamUtils.getDynamicStoreUserData())?.rgOwnedApps?.length || 0
1853
+ // const increaseNumber = ownedAppsCount2 - ownedAppsCount;
1854
+ // log(`OwnedApps length ${ownedAppsCount2}, increase ${increaseNumber}`)
1855
+ // }
1856
+ }
1857
+
1858
+ async function playCSGO() {
1859
+ try {
1860
+ await steamClient.requestFreeLicense(AppID);
1861
+ await sleep(5000);
1862
+ } catch (e) {}
1863
+ gamesPlayed(AppID);
1864
+ }
1865
+
1866
+ function doFakeGameScore() {
1867
+ const maxRound = Math.random() > 0.7 ? 16 : 12;
1868
+ const maps = [
1869
+ "ar_baggage",
1870
+ "ar_dizzy",
1871
+ "ar_monastery",
1872
+ "ar_shoots",
1873
+ "cs_agency",
1874
+ "cs_assault",
1875
+ "cs_italy",
1876
+ "cs_militia",
1877
+ "cs_office",
1878
+ "de_ancient",
1879
+ "de_anubis",
1880
+ "de_bank",
1881
+ "de_boyard",
1882
+ "de_cache",
1883
+ "de_canals",
1884
+ "de_cbble",
1885
+ "de_chalice",
1886
+ "de_dust2",
1887
+ "de_inferno",
1888
+ "de_lake",
1889
+ "de_mirage",
1890
+ "de_nuke",
1891
+ "de_overpass",
1892
+ "de_safehouse",
1893
+ // "de_shortnuke",
1894
+ "de_stmarc",
1895
+ "de_sugarcane",
1896
+ "de_train",
1897
+ "de_tuscan",
1898
+ "de_vertigo",
1899
+ "dz_ember",
1900
+ "dz_vineyard",
1901
+ "gd_cbble",
1902
+ "training1",
1903
+ ];
1904
+
1905
+ if (richPresence.myScore === undefined) {
1906
+ richPresence.myScore = _.random(0, maxRound);
1907
+ }
1908
+ if (richPresence.theirScore === undefined) {
1909
+ richPresence.theirScore = _.random(0, maxRound);
1910
+ }
1911
+ if (richPresence.map === undefined) {
1912
+ richPresence.map = maps[Math.floor(Math.random() * maps.length)];
1913
+ }
1914
+ if (richPresence.myScore === maxRound || richPresence.theirScore === maxRound) {
1915
+ richPresence.myScore = 0;
1916
+ richPresence.theirScore = 0;
1917
+ richPresence.map = maps[Math.floor(Math.random() * maps.length)];
1918
+ } else {
1919
+ const isMyTeamWin = Math.random() > 0.5;
1920
+ if (isMyTeamWin) {
1921
+ richPresence.myScore++;
1922
+ } else {
1923
+ richPresence.theirScore++;
1924
+ }
1925
+ }
1926
+
1927
+ const score = richPresence.myScore === 0 && richPresence.theirScore === 0 ? "" : `[ ${richPresence.myScore} : ${richPresence.theirScore} ]`;
1928
+ steamClient.uploadRichPresence(730, {
1929
+ "game:state": "game",
1930
+ steam_display: "#display_GameKnownMapScore",
1931
+ connect: "+gcconnectG082AA752",
1932
+ version: CSGO_VER.toString(),
1933
+ "game:mode": "competitive",
1934
+ "game:map": richPresence.map,
1935
+ "game:server": "kv",
1936
+ watch: _.random(1, 5).toString(),
1937
+ "game:score": score,
1938
+ });
1939
+ }
1940
+
1941
+ function updateFakeGameScore() {
1942
+ if (isFakeGameScore && getPlayingAppIds().some((a) => a == 730)) {
1943
+ doSetInterval(doFakeGameScore, [60000, 180000], "uploadRichPresenceCSGO");
1944
+ } else {
1945
+ doClearInterval("uploadRichPresenceCSGO");
1946
+ }
1947
+ }
1948
+
1949
+ function updateAutoRequestFreeLicense() {
1950
+ if (isAutoRequestFreeLicense) {
1951
+ doSetInterval(
1952
+ function () {
1953
+ autoRequestFreeLicense(false, 50);
1954
+ },
1955
+ [5 * 60000, 10 * 60000],
1956
+ "autoRequestFreeLicense",
1957
+ );
1958
+ } else {
1959
+ doClearInterval("autoRequestFreeLicense");
1960
+ }
1961
+ }
1962
+
1963
+ function updateInvisible() {
1964
+ if (isInvisible) {
1965
+ steamClient.setPersona(NodeSteamUser.EPersonaState.Invisible);
1966
+ state = "Invisible";
1967
+ } else {
1968
+ steamClient.setPersona(NodeSteamUser.EPersonaState.Online);
1969
+ state = "Online";
1970
+ }
1971
+ }
1972
+
1973
+ async function gamesPlayed(apps) {
1974
+ if (!Array.isArray(apps)) {
1975
+ apps = [apps];
1976
+ }
1977
+
1978
+ steamClient.gamesPlayed(apps);
1979
+ const shouldHello = apps.some((app) => parseInt(app) === 730);
1980
+ await sleep(10000);
1981
+ if (shouldHello) {
1982
+ await sendHello();
1983
+ }
1984
+ await sleep(1000);
1985
+ if (shouldHello) {
1986
+ await sendHello();
1987
+ }
1988
+ updateFakeGameScore();
1989
+
1990
+ // await sleep(10000)
1991
+ // self.steamUser.uploadRichPresence(730, {
1992
+ // status: 'bussssss',
1993
+ // 'game:state': 'lobby',
1994
+ // steam_display: '#display_watch',
1995
+ // currentmap: '#gamemap_de_empire',
1996
+ // connect: '+gcconnectG082AA752',
1997
+ // 'game:mode': 'competitive'
1998
+ // })
1999
+ }
2000
+
2001
+ function getFriendsList() {
2002
+ const methodName = "FriendsList.GetFriendsList#1";
2003
+ const { users, myFriends } = steamClient; //object
2004
+ /*
2005
+ users
2006
+ * {
2007
+ rich_presence: [],
2008
+ player_name: "Kei #SkinsMonkey",
2009
+ avatar_hash: [123,4543],
2010
+ last_logoff: "2023-05-20T05:00:42.000Z",
2011
+ last_logon: "2023-05-20T05:02:16.000Z",
2012
+ last_seen_online: "2023-05-20T05:00:42.000Z",
2013
+ avatar_url_icon: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/3e/3e9da0b107ac2ec384759544368a8a977359537a.jpg",
2014
+ avatar_url_medium: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/3e/3e9da0b107ac2ec384759544368a8a977359537a_medium.jpg",
2015
+ avatar_url_full: "https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/3e/3e9da0b107ac2ec384759544368a8a977359537a_full.jpg"
2016
+ }
2017
+ *
2018
+
2019
+ myFriends
2020
+ {
2021
+ 76561198365087582: 3,
2022
+ 76561199490395123: 3
2023
+ }
2024
+ * */
2025
+ /*steamClient._send({
2026
+ msg: 151,
2027
+ proto: {
2028
+ target_job_name: methodName
2029
+ }
2030
+ }, Buffer.alloc(0), function (body, hdr) {
2031
+ const result = hdr.proto.eresult
2032
+ const errorMessage = hdr.proto.error_message
2033
+ const responseData = body.toBuffer()
2034
+ console.log(`xxx`, result)
2035
+ })*/
2036
+
2037
+ steamClient.sendToGC(730, 767, {}, Buffer.alloc(0));
2038
+ }
2039
+
2040
+ async function getUserOwnedApps(steamId = steamClient.steamID) {
2041
+ if (!steamId) {
2042
+ return [];
2043
+ }
2044
+ if (typeof steamId?.getSteamID64 === "function") {
2045
+ steamId = steamId.getSteamID64();
2046
+ }
2047
+ const isMe = steamId === steamClient.steamID.getSteamID64();
2048
+ if (isMe && ownedApps.length) {
2049
+ return ownedApps;
2050
+ }
2051
+ let result = {};
2052
+ try {
2053
+ result = await steamClient.getUserOwnedApps(steamId);
2054
+ } catch (e) {
2055
+ try {
2056
+ result = await steamClient.getUserOwnedApps(steamId);
2057
+ } catch (e) {
2058
+ result = {};
2059
+ }
2060
+ }
2061
+ if (isMe && Array.isArray(result.apps)) {
2062
+ ownedApps.length = 0;
2063
+ ownedApps.push(...result.apps);
2064
+ }
2065
+ return result.apps || [];
2066
+ const resultExample = {
2067
+ app_count: 22,
2068
+ apps: [
2069
+ {
2070
+ content_descriptorids: [],
2071
+ appid: 208030,
2072
+ name: "Moon Breakers",
2073
+ playtime_2weeks: null,
2074
+ playtime_forever: 0,
2075
+ img_icon_url: "",
2076
+ has_community_visible_stats: null,
2077
+ playtime_windows_forever: 0,
2078
+ playtime_mac_forever: 0,
2079
+ playtime_linux_forever: 0,
2080
+ rtime_last_played: 0,
2081
+ capsule_filename: null,
2082
+ sort_as: null,
2083
+ has_workshop: null,
2084
+ has_market: null,
2085
+ has_dlc: null,
2086
+ has_leaderboards: null,
2087
+ },
2088
+ ],
2089
+ };
2090
+ }
2091
+
2092
+ function getPlayingAppIds() {
2093
+ return steamClient._playingAppIds || [];
2094
+ }
2095
+
2096
+ return {
2097
+ init,
2098
+ partySearch,
2099
+ invite2Lobby,
2100
+ createLobby,
2101
+ updateLobby,
2102
+ createThenInvite2Lobby,
2103
+ joinLobby,
2104
+ getLobbyData,
2105
+ partyRegister,
2106
+ requestCoPlays,
2107
+ getPersonas,
2108
+ getUsername() {
2109
+ return username;
2110
+ },
2111
+ getCookies,
2112
+ getCookiesWait,
2113
+ getLogOnDetails() {
2114
+ return steamClient?._logOnDetails;
2115
+ },
2116
+ onEvent,
2117
+ offEvent,
2118
+ offAllEvent,
2119
+ setPersona(state, name) {
2120
+ steamClient.setPersona(state, name);
2121
+ },
2122
+ sendFriendMessage,
2123
+ sendFriendTyping,
2124
+ getSteamClient() {
2125
+ return steamClient;
2126
+ },
2127
+ getAccountInfoName,
2128
+ getPersonaName,
2129
+ async getPlayersProfile(steamId, retry = 3) {
2130
+ for (let i = 0; i < retry; i++) {
2131
+ const profile = await getPlayersProfile(steamId);
2132
+ if (profile) {
2133
+ return profile;
2134
+ }
2135
+ }
2136
+ return null;
2137
+ },
2138
+ autoRequestFreeLicense,
2139
+ playCSGO,
2140
+ doSetInterval,
2141
+ doClearIntervals,
2142
+ gamesPlayed,
2143
+ sendHello,
2144
+ checkPlayerPrimeStatus,
2145
+ doClearInterval,
2146
+ gamePlay,
2147
+ autoGamePlay,
2148
+ offAutoGamePlay,
2149
+ updateAutoGamePlay,
2150
+ getFriendsList,
2151
+ setIsPartyRegister(change) {
2152
+ change = !!change;
2153
+ if (isPartyRegister !== change) {
2154
+ isPartyRegister = change;
2155
+ if (!isPartyRegister) {
2156
+ doClearInterval("autoPartyRegister");
2157
+ } else {
2158
+ sendHello();
2159
+ }
2160
+ }
2161
+ },
2162
+ setAutoPlay(change) {
2163
+ change = !!change;
2164
+ if (isAutoPlay !== change) {
2165
+ isAutoPlay = change;
2166
+ updateAutoGamePlay();
2167
+ }
2168
+ },
2169
+ setIsInvisible(change) {
2170
+ change = !!change;
2171
+ if (isInvisible !== change) {
2172
+ isInvisible = change;
2173
+ updateInvisible();
2174
+ }
2175
+ },
2176
+ setFakeGameScore(change) {
2177
+ change = !!change;
2178
+ if (isFakeGameScore !== change) {
2179
+ isFakeGameScore = change;
2180
+ updateFakeGameScore();
2181
+ }
2182
+ },
2183
+ setAutoRequestFreeLicense(change) {
2184
+ change = !!change;
2185
+ if (isAutoRequestFreeLicense !== change) {
2186
+ isAutoRequestFreeLicense = change;
2187
+ updateAutoRequestFreeLicense();
2188
+ }
2189
+ },
2190
+ getState() {
2191
+ return state;
2192
+ },
2193
+ log,
2194
+ isPrime() {
2195
+ return prime === true;
2196
+ },
2197
+ getFriendList,
2198
+ logOff,
2199
+ isPlayingBlocked() {
2200
+ return playingBlocked;
2201
+ },
2202
+ async getChatHistory(steamId) {
2203
+ if (!steamClient.steamID) return [];
2204
+ const mySteamId = typeof steamClient.steamID.getSteamID64 === "function" ? steamClient.steamID.getSteamID64() : steamClient.steamID;
2205
+ return new Promise((resolve) => {
2206
+ setTimeout(resolve, 90000);
2207
+ steamClient.getChatHistory(steamId, async function (error, result) {
2208
+ const messages = (result || []).map(function (msg) {
2209
+ const fromSteamId = typeof msg.steamID?.getSteamID64 === "function" ? msg.steamID.getSteamID64() : msg.steamID;
2210
+ return {
2211
+ message: msg.message,
2212
+ from: fromSteamId,
2213
+ to: fromSteamId == mySteamId ? steamId : mySteamId,
2214
+ _id: new Date(msg.timestamp).getTime().toString(),
2215
+ timestamp: new Date(msg.timestamp).getTime(),
2216
+ isMe: fromSteamId !== steamId,
2217
+ };
2218
+ });
2219
+ resolve(messages);
2220
+ });
2221
+ });
2222
+ },
2223
+ onAnyEvent,
2224
+ async redeemGift(gid) {
2225
+ try {
2226
+ const community = new SteamCommunity();
2227
+ let cookies = await getCookiesWait();
2228
+ community.setCookies(typeof cookies === "string" ? cookies.split(";") : cookies);
2229
+ community.redeemGift(gid);
2230
+ } catch (e) {}
2231
+ },
2232
+ async requestFreeLicense(...args) {
2233
+ try {
2234
+ return await steamClient.requestFreeLicense(...args);
2235
+ } catch (e) {}
2236
+ },
2237
+ getSteamId() {
2238
+ try {
2239
+ return steamClient.steamID.getSteamID64();
2240
+ } catch (e) {}
2241
+ },
2242
+ getLastTimePartyRegister() {
2243
+ return lastTimePartyRegister;
2244
+ },
2245
+ getLastTimePartySearch() {
2246
+ return lastTimePartySearch;
2247
+ },
2248
+ getLicenses() {
2249
+ return steamClient.licenses;
2250
+ const exampleLicenses = [
2251
+ {
2252
+ package_id: 303386,
2253
+ time_created: 1680491335,
2254
+ time_next_process: 0,
2255
+ minute_limit: 0,
2256
+ minutes_used: 0,
2257
+ payment_method: 1024,
2258
+ flags: 512,
2259
+ purchase_country_code: "VN",
2260
+ license_type: 1,
2261
+ territory_code: 0,
2262
+ change_number: 20615891,
2263
+ owner_id: 1530068060,
2264
+ initial_period: 0,
2265
+ initial_time_unit: 0,
2266
+ renewal_period: 0,
2267
+ renewal_time_unit: 0,
2268
+ access_token: "8049398090486337961",
2269
+ master_package_id: null,
2270
+ },
2271
+ ];
2272
+ },
2273
+ uploadRichPresence(appid, richPresence) {
2274
+ if (Array.isArray(richPresence)) {
2275
+ richPresence = richPresence.reduce(function (previousValue, currentValue, currentIndex, array) {
2276
+ if (currentValue.key) {
2277
+ previousValue[currentValue.key] = currentValue.value?.toString() || "";
2278
+ }
2279
+ return previousValue;
2280
+ });
2281
+ }
2282
+ steamClient.uploadRichPresence(appid, richPresence);
2283
+ },
2284
+ getUserOwnedApps,
2285
+ getPlayingAppIds,
2286
+ getCurrentLobby() {
2287
+ return currentLobby;
2288
+ },
2289
+ };
2290
+ }
2291
+
2292
+ export default SteamClient;
2293
+
2294
+ export function increaseCSGO_VER() {
2295
+ return ++CSGO_VER;
2296
+ }
2297
+
2298
+ SteamClient.isAccountPlayable = async function isAccountPlayable(params, timeoutMs) {
2299
+ let clientJsToken = params.clientJsToken;
2300
+ delete params.clientJsToken;
2301
+ if (!clientJsToken && params.cookie) {
2302
+ clientJsToken = await new SteamUser(typeof params.cookie === "function" ? await params.cookie() : params.cookie).getClientJsToken();
2303
+ }
2304
+ if (clientJsToken?.logged_in !== true) {
2305
+ return false;
2306
+ }
2307
+ params.clientJsToken = clientJsToken;
2308
+
2309
+ return await new Promise((resolve) => {
2310
+ const timeout = setTimeout(() => {
2311
+ doResolve();
2312
+ }, timeoutMs || 30000);
2313
+
2314
+ const steamClient = new SteamClient({
2315
+ isFakeGameScore: false,
2316
+ isAutoPlay: true,
2317
+ isPartyRegister: false,
2318
+ isInvisible: false,
2319
+ MAX_GAME_PLAY: 10,
2320
+ games: 730,
2321
+ ...params,
2322
+ });
2323
+
2324
+ steamClient.onEvent("error", ({ eresult, msg, error }) => {
2325
+ doResolve();
2326
+ });
2327
+
2328
+ steamClient.onEvent("csgoOnline", (ClientWelcome) => {
2329
+ doResolve(ClientWelcome);
2330
+ });
2331
+
2332
+ steamClient.onEvent("csgoClientHello", (ClientHello) => {
2333
+ doResolve(ClientHello);
2334
+ });
2335
+
2336
+ steamClient.onEvent("playingState", ({ playing_blocked, playing_app }) => {
2337
+ if (playing_blocked) {
2338
+ doResolve();
2339
+ }
2340
+ });
2341
+
2342
+ steamClient.onEvent("fatalError", () => {
2343
+ doResolve();
2344
+ });
2345
+
2346
+ steamClient.init();
2347
+
2348
+ function doResolve(data) {
2349
+ clearTimeout(timeout);
2350
+ steamClient.doClearIntervals();
2351
+ steamClient.offAllEvent();
2352
+ steamClient.logOff();
2353
+ return resolve(!!data);
2354
+ }
2355
+ });
2356
+ };