steamutils 1.3.77 → 1.3.78

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