steamutils 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SteamClient.js ADDED
@@ -0,0 +1,534 @@
1
+ import SteamUser 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 from "./helpers/protos.js";
9
+
10
+ const Protos = helpers([{
11
+ name: 'csgo',
12
+ protos: fs.readdirSync(__dirname + '/protos/').filter(s => s.endsWith('.proto')).map(s => __dirname + '/protos/' + s)
13
+ }])
14
+
15
+ export const RANKS = {
16
+ 0: 'Unranked',
17
+ 1: 'Silver I',
18
+ 2: 'Silver II',
19
+ 3: 'Silver III',
20
+ 4: 'Silver IV',
21
+ 5: 'Silver Elite',
22
+ 6: 'Silver Elite Master',
23
+ 7: 'Gold Nova I',
24
+ 8: 'Gold Nova II',
25
+ 9: 'Gold Nova III',
26
+ 10: 'Gold Nova Master',
27
+ 11: 'Master Guardian I',
28
+ 12: 'Master Guardian II',
29
+ 13: 'Master Guardian Elite',
30
+ 14: 'Distinguished Master Guardian',
31
+ 15: 'Legendary Eagle',
32
+ 16: 'Legendary Eagle Master',
33
+ 17: 'Supreme Master First Class',
34
+ 18: 'The Global Elite'
35
+ }
36
+ export const LOCS = {
37
+ 20054: 'VN',
38
+ 23115: 'KZ',
39
+ 20041: 'IN',
40
+ 20035: 'CN',
41
+ 17474: 'BD',
42
+ 17481: 'ID',
43
+ 22861: 'MY',
44
+ 18516: 'TH',
45
+ 22356: 'TW',
46
+ 21067: 'KR',
47
+ 19272: 'HK',
48
+ 18512: 'PH',
49
+ 21842: 'RU',
50
+ 16716: 'LA',
51
+ 20558: 'NP',
52
+ 18259: 'SG',
53
+ 19789: 'MM',
54
+ 20045: 'MN',
55
+ 18251: 'KG',
56
+ 18507: 'KH',
57
+ 22605: 'MX',
58
+ 19280: 'PK',
59
+ 20301: 'HK/MO',//hongkong or macau
60
+ 21333: 'Unknown',
61
+ 21825: 'AU',
62
+ }
63
+
64
+
65
+ const appid = 730
66
+ let CSGO_VER = null
67
+ GetCurrentVersion(appid).then(function (ver) {
68
+ CSGO_VER = ver
69
+ })
70
+
71
+ async function GetCurrentVersion(appid) {
72
+ const result = await axios.request({
73
+ url: 'https://api.steampowered.com/ISteamApps/UpToDateCheck/v1/?format=json&appid=' + appid + '&version=0'
74
+ })
75
+ return result.data.response.required_version
76
+ }
77
+
78
+ function SteamClient({
79
+ username,
80
+ password,
81
+ cookie,
82
+ }) {
83
+ const steamClient = new SteamUser()
84
+ let prime = false
85
+ let gamename = null;
86
+
87
+ const events = {
88
+ loggedOn: []
89
+ }
90
+
91
+ const personasCache = []
92
+
93
+ async function getPersonas(steamIDs) {
94
+ const notCachesteamIDs = steamIDs.filter(id => !personasCache.some(p => p.id == id))
95
+ const cachedPersonas = personasCache.filter(p => steamIDs.includes(p.id))
96
+
97
+ if (notCachesteamIDs.length) {
98
+ let personas = null
99
+ try {
100
+ personas = (await steamClient.getPersonas(steamIDs))?.personas
101
+ } catch (e) {
102
+ }
103
+ if (!personas) {
104
+ try {
105
+ personas = (await steamClient.getPersonas(steamIDs))?.personas
106
+ } catch (e) {
107
+ }
108
+ }
109
+ if (!personas) {
110
+ return {}
111
+ } else {
112
+ for (let sid64 in personas) {
113
+ personas[sid64].avatar_hash = Buffer.from(personas[sid64].avatar_hash).toString("hex")
114
+ personasCache.push(personas[sid64])
115
+ cachedPersonas.push(personas[sid64])
116
+ }
117
+ }
118
+ }
119
+
120
+ while (personasCache.length > 500) {
121
+ personasCache.shift()
122
+ }
123
+ return cachedPersonas
124
+ }
125
+
126
+ const sleep = (ms) => {
127
+ return new Promise(resolve => {
128
+ setTimeout(resolve, ms)
129
+ })
130
+ }
131
+
132
+ const partySearchCallback = []
133
+
134
+ /**
135
+ * Get a list of lobbies (* = Unsure description could be wrong)
136
+ * @param {Number} ver Game version we are searching for
137
+ * @param {Boolean} apr Prime or not*
138
+ * @param {Number} ark Rank multiplied by 10*
139
+ * @param {Array.<Number>} grps *
140
+ * @param {Number} launcher If we are using the China CSGO launcher or not*
141
+ * @param {Number} game_type Game type, 8 Competitive, 10 Wingman
142
+ * @returns {Promise.<Object>}
143
+ */
144
+ async function partySearch({
145
+ prime = false, game_type = 'Competitive', rank = 'Silver Elite',
146
+ }) {
147
+
148
+ return new Promise(resolve => {
149
+ steamClient.sendToGC(appid, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Search, {}, protoEncode(Protos.csgo.CMsgGCCStrike15_v2_Party_Search, {
150
+ ver: CSGO_VER,
151
+ apr: prime ? 1 : 0,
152
+ ark: Object.keys(RANKS).find(k => RANKS[k] === rank) * 10,
153
+ grps: [],
154
+ launcher: 0,
155
+ game_type: game_type === 'Competitive' ? 8 : 10
156
+ }))
157
+ partySearchCallback.push(resolve)
158
+ setTimeout(resolve, 10000)
159
+ })
160
+ }
161
+
162
+ async function sendHello() {
163
+ console.log('sendHello')
164
+ steamClient.sendToGC(appid, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello, {}, Buffer.alloc(0))
165
+ steamClient.sendToGC(appid, Protos.csgo.EGCBaseClientMsg.k_EMsgGCClientHello, {}, Buffer.alloc(0))
166
+ console.log('sendHello done')
167
+ }
168
+
169
+ const requestCoPlaysCallback = []
170
+
171
+ async function requestCoPlays() {
172
+ console.log('sendMessageAccount_RequestCoPlays')
173
+ return new Promise(resolve => {
174
+ steamClient.sendToGC(appid, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Account_RequestCoPlays, {}, Buffer.alloc(0))
175
+ requestCoPlaysCallback.push(resolve)
176
+ setTimeout(resolve, 10000)
177
+ })
178
+ }
179
+
180
+
181
+ function bindEvent() {
182
+ steamClient.on('disconnected', async (eresult, msg) => {
183
+ console.log('disconnected')
184
+ })
185
+ steamClient.on('error', async (e) => {
186
+ let errorStr = ``
187
+ switch (e.eresult) {
188
+ case 5:
189
+ errorStr = `Invalid Password`
190
+ break
191
+ case 6:
192
+ case 34:
193
+ errorStr = `Logged In Elsewhere`
194
+ break
195
+ case 84:
196
+ errorStr = `Rate Limit Exceeded`
197
+ break
198
+ case 65:
199
+ errorStr = `steam guard is invalid`
200
+ break
201
+ default:
202
+ errorStr = `Unknown: ${e.eresult}`
203
+ break
204
+ }
205
+ console.log('error', e?.message)
206
+ })
207
+
208
+ steamClient.on('webSession', (sessionID, cookies) => {
209
+ // console.log('webSession', sessionID, cookies);
210
+ })
211
+
212
+ steamClient.on('receivedFromGC', async (appid, msgType, payload) => {
213
+ const key = getECsgoGCMsgKey(msgType)
214
+ switch (msgType) {
215
+ case Protos.csgo.EMsg.k_EMsgClientChatInvite: {
216
+ console.log(payload)
217
+ break
218
+ }
219
+ case Protos.csgo.ECsgoGCMsg.k_EMsgClientMMSJoinLobbyResponse: {
220
+ let msg = protoDecode(Protos.csgo.CMsgClientMMSJoinLobbyResponse, payload)
221
+ console.log(msg)
222
+ break
223
+ }
224
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Invite: {
225
+ let msg = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_Party_Invite, payload)
226
+ let sid = SteamID.fromIndividualAccountID(msg.accountid);
227
+ // console.log(msg)
228
+ let personas = await getPersonas([sid])
229
+ console.log(personas?.[sid]?.player_name, `https://steamcommunity.com/profiles/${sid.getSteamID64()}`);
230
+ // joinLobby(msg.lobbyid, msg.accountid)
231
+ break
232
+ }
233
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Account_RequestCoPlays: {
234
+ const msg = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_Account_RequestCoPlays, payload);
235
+ const personas = msg.players.map(p => SteamID.fromIndividualAccountID(p.accountid));
236
+ requestCoPlaysCallback?.shift()?.(personas)
237
+ break
238
+ }
239
+ case Protos.csgo.EGCBaseClientMsg.k_EMsgGCClientWelcome: {
240
+ const CMsgClientWelcome = protoDecode(Protos.csgo.CMsgClientWelcome, payload);
241
+ for (const outofdate_cache of CMsgClientWelcome.outofdate_subscribed_caches) {
242
+ for (const cache_object of outofdate_cache.objects) {
243
+ if (cache_object.object_data.length === 0) {
244
+ continue
245
+ }
246
+ switch (cache_object.type_id) {
247
+ case 7: {
248
+ let CSOEconGameAccountClient = protoDecode(Protos.csgo.CSOEconGameAccountClient, cache_object.object_data[0])
249
+ if ((CSOEconGameAccountClient.bonus_xp_usedflags & 16) != 0) { // EXPBonusFlag::PrestigeEarned
250
+ prime = true
251
+ }
252
+ if (CSOEconGameAccountClient.elevated_state == 5) { // bought prime
253
+ prime = true
254
+ }
255
+ break
256
+ }
257
+ }
258
+ }
259
+ }
260
+ break
261
+ }
262
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchmakingGC2ClientUpdate: {
263
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_MatchmakingGC2ClientUpdate, payload)
264
+ break
265
+ }
266
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_GC2ClientGlobalStats: {
267
+ const result = protoDecode(Protos.csgo.CMsgClientUGSGetGlobalStatsResponse, payload)
268
+ break
269
+ }
270
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_GC2ClientTextMsg: {
271
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_GC2ClientTextMsg, payload)
272
+ break
273
+ }
274
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello: {
275
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_MatchmakingGC2ClientHello, payload)
276
+ break
277
+ }
278
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientReportResponse: {
279
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientReportResponse, payload)
280
+ break
281
+ }
282
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientCommendPlayerQueryResponse: {
283
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientCommendPlayer, payload)
284
+ break
285
+ }
286
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_PlayerOverwatchCaseAssignment: {
287
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_PlayerOverwatchCaseAssignment, payload)
288
+ break
289
+ }
290
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_MatchList: {
291
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_MatchList, payload)
292
+ break
293
+ }
294
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_GetEventFavorites_Response: {
295
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_GetEventFavorites_Response, payload)
296
+ break
297
+ }
298
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_StartAgreementSessionInGame: {
299
+
300
+ break
301
+ }
302
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_ClientDeepStats: {
303
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_ClientDeepStats, payload)
304
+ break
305
+ }
306
+ case Protos.csgo.EGCBaseClientMsg.k_EMsgGCClientConnectionStatus: {
307
+ const result = protoDecode(Protos.csgo.CMsgConnectionStatus, payload)
308
+ break
309
+ }
310
+ case Protos.csgo.EGCItemMsg.k_EMsgGCStoreGetUserDataResponse: {
311
+ const result = protoDecode(Protos.csgo.CMsgStoreGetUserDataResponse, payload)
312
+ break
313
+ }
314
+ case Protos.csgo.EGCItemMsg.k_EMsgGCStorePurchaseFinalizeResponse: {
315
+ const result = protoDecode(Protos.csgo.CMsgGCStorePurchaseFinalizeResponse, payload)
316
+ break
317
+ }
318
+ case Protos.csgo.EGCItemMsg.k_EMsgGCStorePurchaseCancelResponse: {
319
+ const result = protoDecode(Protos.csgo.CMsgGCStorePurchaseCancelResponse, payload)
320
+ break
321
+ }
322
+ case Protos.csgo.EGCItemMsg.k_EMsgGCStorePurchaseInitResponse: {
323
+ const result = protoDecode(Protos.csgo.CMsgGCStorePurchaseInitResponse, payload)
324
+ break
325
+ }
326
+ case Protos.csgo.EMsg.k_EMsgClientMMSCreateLobbyResponse: {
327
+ const result = protoDecode(Protos.csgo.CMsgClientMMSCreateLobbyResponse, payload)
328
+ break
329
+ }
330
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientGCRankUpdate: {
331
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_ClientGCRankUpdate, payload)
332
+ break
333
+ }
334
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Search: {
335
+ const result = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_Party_SearchResults, payload)
336
+ const entries = _.uniqBy(result.entries, 'id')
337
+
338
+ const players = []
339
+
340
+ const steamIDs = entries
341
+ .map(p => SteamID.fromIndividualAccountID(p.id).getSteamID64())
342
+ const personas = await getPersonas(steamIDs)
343
+
344
+ for (const player of entries) {
345
+ try {
346
+ const prime = player.apr === 1 ? 'PRIME' : 'NON-PRIME'
347
+ const loc = LOCS[player.loc] || player.loc
348
+ const steamID = SteamID.fromIndividualAccountID(player.id).getSteamID64()
349
+ const persona = personas.find(p => p.id == player.id)
350
+ const player_name = persona.player_name
351
+ const friendCode = FriendCode.encode(steamID)
352
+
353
+ if ((LOCS[player.loc] == 'VN' || !LOCS[player.loc])) {
354
+ players.push({
355
+ prime,
356
+ player_name: player_name,
357
+ rank: RANKS[player.ark],
358
+ loc: loc,
359
+ steamID,
360
+ friendCode,
361
+ avatar_hash: persona.avatar_hash,
362
+ })
363
+ }
364
+ } catch (e) {
365
+ }
366
+ }
367
+
368
+ partySearchCallback.shift()?.(players)
369
+ break
370
+ }
371
+ case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_PlayersProfile: {
372
+ let data = protoDecode(Protos.csgo.CMsgGCCStrike15_v2_PlayersProfile, payload)?.account_profiles
373
+ const dataExample = [{
374
+ my_current_event_teams: [],
375
+ my_current_event_stages: [],
376
+ rankings: [{
377
+ account_id: 1225887169, rank_id: 0, wins: 6, rank_change: 0, rank_type_id: 7, tv_control: 0
378
+ }, {
379
+ account_id: 1225887169, rank_id: 0, wins: 0, rank_change: 0, rank_type_id: 10, tv_control: 0
380
+ }],
381
+ account_id: 1225887169,
382
+ ongoingmatch: null,
383
+ global_stats: null,
384
+ penalty_seconds: 0,
385
+ penalty_reason: 0,
386
+ vac_banned: 0,
387
+ ranking: {
388
+ account_id: 1225887169,
389
+ rank_id: 8,
390
+ wins: 469,
391
+ rank_change: 0,
392
+ rank_type_id: 6,
393
+ tv_control: 0
394
+ },
395
+ commendation: {
396
+ cmd_friendly: 51, cmd_teaching: 40, cmd_leader: 40
397
+ },
398
+ medals: {
399
+ display_items_defidx: [4819, 4737], featured_display_item_defidx: 4819
400
+ },
401
+ my_current_event: null,
402
+ my_current_team: null,
403
+ survey_vote: 0,
404
+ activity: null,
405
+ player_level: 32,
406
+ player_cur_xp: 327682846,
407
+ player_xp_bonus_flags: 0
408
+ }]
409
+ console.log(data);
410
+ break
411
+ }
412
+ default:
413
+ console.log(`receivedFromGC ${msgType} ${key}`)
414
+ const results = Object.values(Protos.csgo).map(function (p) {
415
+ try {
416
+ return protoDecode(p, payload)
417
+ } catch (e) {
418
+ }
419
+ }).filter(function (result) {
420
+ return result && Object.keys(result).length
421
+ })
422
+ console.log(key, results)
423
+ }
424
+ })
425
+
426
+ function getECsgoGCMsgKey(_key) {
427
+ for (let key in Protos.csgo.ECsgoGCMsg) {
428
+ if (Protos.csgo.ECsgoGCMsg[key] == _key) {
429
+ return key
430
+ }
431
+ }
432
+ for (let key in Protos.csgo.EGCBaseClientMsg) {
433
+ if (Protos.csgo.EGCBaseClientMsg[key] == _key) {
434
+ return key
435
+ }
436
+ }
437
+ for (let key in Protos.csgo.EMsg) {
438
+ if (Protos.csgo.EMsg[key] == _key) {
439
+ return key
440
+ }
441
+ }
442
+ for (let key in Protos.csgo.EGCItemMsg) {
443
+ if (Protos.csgo.EGCItemMsg[key] == _key) {
444
+ return key
445
+ }
446
+ }
447
+ }
448
+
449
+ steamClient.on('loggedOn', async (loggedOnResponse) => {
450
+ await steamClient.requestFreeLicense(appid)
451
+ await sleep(5000)
452
+
453
+ if (gamename) {
454
+ steamClient.gamesPlayed([{
455
+ game_id: appid, game_extra_info: gamename
456
+ }], true);
457
+ } else {
458
+ steamClient.gamesPlayed(appid, true)
459
+ }
460
+
461
+ steamClient.setPersona(SteamUser.EPersonaState.LookingToPlay)
462
+
463
+ while (!steamClient.accountInfo) {
464
+ await sleep(500)
465
+ }
466
+
467
+ console.log(`app ${appid} launched on account ${steamClient.accountInfo.name}`)
468
+ await sendHello()
469
+
470
+ events.loggedOn.forEach(e => e?.invoke?.())
471
+ })
472
+ }
473
+
474
+ function getPlayersProfile(accountid) {
475
+ steamClient.sendToGC(730, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientRequestPlayersProfile, {}, protoEncode(Protos.csgo.CMsgGCCStrike15_v2_ClientRequestPlayersProfile, {
476
+ account_id: accountid, // account_id: new SteamID('76561199184696945').accountid,
477
+ request_level: 32
478
+ }))
479
+ }
480
+
481
+ async function login() {
482
+ if (cookie) {
483
+ console.log('login with cookie')
484
+ const result = (await axios.request({
485
+ url: 'https://steamcommunity.com/chat/clientjstoken', headers: {
486
+ cookie,
487
+ }
488
+ }))?.data
489
+ if (result) {
490
+ Object.assign(result, {
491
+ steamID: new SteamID(result.steamid), accountName: result.account_name, webLogonToken: result.token
492
+ })
493
+ steamClient.logOn(result)
494
+ }
495
+ } else if (username && password) {
496
+ console.log(`login with username ${username}`)
497
+ steamClient.logOn({
498
+ accountName: username, password: password, rememberPassword: true, machineName: 'Natri',
499
+ })
500
+ }
501
+ }
502
+
503
+ function init() {
504
+ bindEvent()
505
+ login()
506
+ }
507
+
508
+
509
+ function partyRegister() {
510
+ console.log("partyRegister", steamClient?.accountInfo?.name || username, prime);
511
+ steamClient.sendToGC(730, Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_Party_Register, {}, protoEncode(Protos.csgo.CMsgGCCStrike15_v2_Party_Register, {
512
+ // id : 0,
513
+ ver: CSGO_VER, apr: prime ? 1 : 0,//prime
514
+ ark: prime ? 180 : 0, grps: [], launcher: 0, game_type: 8
515
+ }))
516
+ }
517
+
518
+ return {
519
+ init, partySearch, partyRegister, requestCoPlays, getPersonas, getUsername: function () {
520
+ return username
521
+ }, onEvent: function (name, cb) {
522
+ if (!events[name]) {
523
+ events[name] = []
524
+ }
525
+ events[name].push(cb)
526
+ }, setPersona: function (state, name) {
527
+ steamClient.setPersona(state, name)
528
+ }, setGameName: function (name) {
529
+ gamename = name
530
+ },
531
+ }
532
+ }
533
+
534
+ export default SteamClient
@@ -0,0 +1,33 @@
1
+ import Protobuf from "protobufjs";
2
+ import fs from "fs";
3
+ import path from "path";
4
+
5
+ export default function Protos(protos, ignoreErrors = true) {
6
+ const protobufs = {};
7
+
8
+ for (let proto of protos) {
9
+ let root = new Protobuf.Root();
10
+ let files = Array.isArray(proto.protos) ? proto.protos : fs.readdirSync(proto.protos).map(file => path.join(proto.protos, file));
11
+
12
+ for (let file of files) {
13
+ if (!file.endsWith(".proto") || !fs.existsSync(file)) {
14
+ continue;
15
+ }
16
+
17
+ try {
18
+ root = root.loadSync(file, {
19
+ keepCase: true
20
+ });
21
+ } catch (err) {
22
+ if (!ignoreErrors) {
23
+ throw err;
24
+ }
25
+ }
26
+ ;
27
+ }
28
+
29
+ protobufs[proto.name] = root;
30
+ }
31
+
32
+ return protobufs;
33
+ }
@@ -0,0 +1,60 @@
1
+ export function penalty_reason_string(id) {
2
+ switch (id) {
3
+ case 0:
4
+ return 0;
5
+ case 1:
6
+ return "Kicked";
7
+ case 2:
8
+ return "TK Limit";
9
+ case 3:
10
+ return "TK Spawn";
11
+ case 4:
12
+ return "Disconnected Too Long";
13
+ case 5:
14
+ return "Abandon";
15
+ case 6:
16
+ return "TD Limit";
17
+ case 7:
18
+ return "TD Spawn";
19
+ case 8:
20
+ case 14:
21
+ return "Untrusted";
22
+ case 9:
23
+ return "Kicked Too Much";
24
+ case 10:
25
+ return "Overwatch (Cheat)";
26
+ case 11:
27
+ return "Overwatch (Grief)";
28
+ case 16:
29
+ return "Failed To Connect";
30
+ case 17:
31
+ return "Kick Abuse";
32
+ case 18:
33
+ case 19:
34
+ case 20:
35
+ return "Rank Calibration";
36
+ case 21:
37
+ return "Reports (Grief)"
38
+ default:
39
+ return `Unknown(${id})`;
40
+ }
41
+ }
42
+
43
+ export function penalty_reason_permanent(id) {
44
+ switch (id) {
45
+ case 8:
46
+ case 14:
47
+ case 10:
48
+ return true;
49
+ default:
50
+ return false;
51
+ }
52
+ }
53
+
54
+ export function protoDecode(proto, obj) {
55
+ return proto.toObject(proto.decode(obj), {defaults: true});
56
+ }
57
+
58
+ export function protoEncode(proto, obj) {
59
+ return proto.encode(proto.create(obj)).finish();
60
+ }
package/index.js CHANGED
@@ -1864,6 +1864,7 @@ class SteamUser {
1864
1864
  let result = (await this._httpRequest('chat/clientjstoken'))?.data
1865
1865
  if (!result?.steamid) {
1866
1866
  if (retry !== null && retry !== undefined && retry >= 0) {
1867
+ await sleep(2000)
1867
1868
  return await this.getClientJsToken(retry - 1)
1868
1869
  } else {
1869
1870
  return null
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "steamutils",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "dependencies": {
5
5
  "axios": "^1.3.4",
6
6
  "cheerio": "^1.0.0-rc.12",
7
7
  "crypto-js": "^4.1.1",
8
+ "csgo-friendcode": "^3.0.3",
8
9
  "lodash": "^4.17.21",
9
10
  "moment": "^2.29.4",
10
11
  "node-bignumber": "^1.2.2",
12
+ "steam-user": "^4.28.1",
11
13
  "steamid": "^2.0.0",
12
14
  "url-parse": "^1.5.10",
13
15
  "xml-js": "^1.6.11",