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