steamutils 1.3.78 → 1.3.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/.idea/deployment.xml +8 -1
  2. package/.idea/steamutils.iml +1 -1
  3. package/.idea/vcs.xml +1 -1
  4. package/.prettierrc.json +3 -3
  5. package/SteamClient.js +2437 -2437
  6. package/bufferHelpers.js +115 -115
  7. package/cheerio.js +103 -103
  8. package/const.js +336 -336
  9. package/create_remote_file.js +66 -66
  10. package/free_packages.json +10048 -10048
  11. package/index.js +7074 -7052
  12. package/package.json +1 -1
  13. package/protos/csgo/base_gcmessages.proto +553 -553
  14. package/protos/csgo/base_gcmessages_csgo.proto +547 -547
  15. package/protos/csgo/c_peer2peer_netmessages.proto +55 -55
  16. package/protos/csgo/clientmessages.proto +48 -48
  17. package/protos/csgo/connectionless_netmessages.proto +17 -17
  18. package/protos/csgo/cs_gameevents.proto +35 -35
  19. package/protos/csgo/cs_usercmd.proto +34 -34
  20. package/protos/csgo/cstrike15_gcmessages.proto +1431 -1431
  21. package/protos/csgo/cstrike15_usermessages.proto +592 -592
  22. package/protos/csgo/demo.proto +165 -165
  23. package/protos/csgo/econ_gcmessages.proto +219 -219
  24. package/protos/csgo/engine_gcmessages.proto +14 -14
  25. package/protos/csgo/enums_clientserver.proto +1529 -1529
  26. package/protos/csgo/fatdemo.proto +125 -125
  27. package/protos/csgo/gameevents.proto +120 -120
  28. package/protos/csgo/gcsdk_gcmessages.proto +323 -323
  29. package/protos/csgo/gcsystemmsgs.proto +243 -243
  30. package/protos/csgo/netmessages.proto +618 -618
  31. package/protos/csgo/network_connection.proto +126 -126
  32. package/protos/csgo/networkbasetypes.proto +246 -246
  33. package/protos/csgo/networksystem_protomessages.proto +17 -17
  34. package/protos/csgo/steamdatagram_messages_auth.proto +65 -65
  35. package/protos/csgo/steamdatagram_messages_sdr.proto +534 -534
  36. package/protos/csgo/steammessages.proto +620 -620
  37. package/protos/csgo/steammessages_base.proto +301 -301
  38. package/protos/csgo/steammessages_cloud.steamworkssdk.proto +68 -68
  39. package/protos/csgo/steammessages_gamenetworkingui.proto +61 -61
  40. package/protos/csgo/steammessages_helprequest.steamworkssdk.proto +22 -22
  41. package/protos/csgo/steammessages_oauth.steamworkssdk.proto +18 -18
  42. package/protos/csgo/steammessages_player.steamworkssdk.proto +254 -254
  43. package/protos/csgo/steammessages_publishedfile.steamworkssdk.proto +233 -233
  44. package/protos/csgo/steammessages_unified_base.steamworkssdk.proto +30 -30
  45. package/protos/csgo/steamnetworkingsockets_messages.proto +205 -205
  46. package/protos/csgo/steamnetworkingsockets_messages_certs.proto +39 -39
  47. package/protos/csgo/steamnetworkingsockets_messages_udp.proto +75 -75
  48. package/protos/csgo/te.proto +259 -259
  49. package/protos/csgo/uifontfile_format.proto +13 -13
  50. package/protos/csgo/usercmd.proto +39 -39
  51. package/protos/csgo/usermessages.proto +752 -752
  52. package/protos/csgo/valveextensions.proto +17 -17
  53. package/protos/google/protobuf/descriptor.proto +281 -281
  54. package/protos/steam/clientmetrics.proto +45 -45
  55. package/protos/steam/content_manifest.proto +62 -62
  56. package/protos/steam/contenthubs.proto +41 -41
  57. package/protos/steam/encrypted_app_ticket.proto +10 -10
  58. package/protos/steam/enums.proto +501 -501
  59. package/protos/steam/enums_clientserver.proto +1508 -1508
  60. package/protos/steam/enums_productinfo.proto +14 -14
  61. package/protos/steam/htmlmessages.proto +1039 -1039
  62. package/protos/steam/offline_ticket.proto +8 -8
  63. package/protos/steam/steamdatagram_messages_auth.proto +65 -65
  64. package/protos/steam/steamdatagram_messages_sdr.proto +533 -533
  65. package/protos/steam/steammessages_accounthardware.steamclient.proto +167 -167
  66. package/protos/steam/steammessages_appoverview.proto +204 -204
  67. package/protos/steam/steammessages_auth.steamclient.proto +375 -375
  68. package/protos/steam/steammessages_base.proto +335 -335
  69. package/protos/steam/steammessages_broadcast.steamclient.proto +618 -618
  70. package/protos/steam/steammessages_chat.steamclient.proto +1070 -1070
  71. package/protos/steam/steammessages_client_objects.proto +649 -649
  72. package/protos/steam/steammessages_clientlanp2p.proto +43 -43
  73. package/protos/steam/steammessages_clientmetrics.steamclient.proto +192 -192
  74. package/protos/steam/steammessages_clientnotificationtypes.proto +250 -250
  75. package/protos/steam/steammessages_clientserver.proto +392 -392
  76. package/protos/steam/steammessages_clientserver_2.proto +771 -771
  77. package/protos/steam/steammessages_clientserver_appinfo.proto +131 -131
  78. package/protos/steam/steammessages_clientserver_friends.proto +260 -260
  79. package/protos/steam/steammessages_clientserver_gameservers.proto +159 -159
  80. package/protos/steam/steammessages_clientserver_lbs.proto +70 -70
  81. package/protos/steam/steammessages_clientserver_login.proto +167 -167
  82. package/protos/steam/steammessages_clientserver_mms.proto +233 -233
  83. package/protos/steam/steammessages_clientserver_ucm.proto +207 -207
  84. package/protos/steam/steammessages_clientserver_uds.proto +125 -125
  85. package/protos/steam/steammessages_clientserver_ufs.proto +45 -45
  86. package/protos/steam/steammessages_clientserver_userstats.proto +80 -80
  87. package/protos/steam/steammessages_clientsettings.proto +208 -208
  88. package/protos/steam/steammessages_cloud.steamclient.proto +422 -422
  89. package/protos/steam/steammessages_contentsystem.steamclient.proto +123 -123
  90. package/protos/steam/steammessages_credentials.steamclient.proto +96 -96
  91. package/protos/steam/steammessages_datapublisher.steamclient.proto +102 -102
  92. package/protos/steam/steammessages_depotbuilder.steamclient.proto +99 -99
  93. package/protos/steam/steammessages_deviceauth.steamclient.proto +169 -169
  94. package/protos/steam/steammessages_econ.steamclient.proto +137 -137
  95. package/protos/steam/steammessages_familygroups.steamclient.proto +441 -441
  96. package/protos/steam/steammessages_friendmessages.steamclient.proto +141 -141
  97. package/protos/steam/steammessages_gamenetworking.steamclient.proto +25 -25
  98. package/protos/steam/steammessages_gamenetworkingui.proto +61 -61
  99. package/protos/steam/steammessages_gamenotifications.steamclient.proto +131 -131
  100. package/protos/steam/steammessages_gameservers.steamclient.proto +136 -136
  101. package/protos/steam/steammessages_hiddevices.proto +157 -157
  102. package/protos/steam/steammessages_inventory.steamclient.proto +172 -172
  103. package/protos/steam/steammessages_linkfilter.steamclient.proto +39 -39
  104. package/protos/steam/steammessages_lobbymatchmaking.steamclient.proto +29 -29
  105. package/protos/steam/steammessages_market.steamclient.proto +22 -22
  106. package/protos/steam/steammessages_marketingmessages.steamclient.proto +273 -273
  107. package/protos/steam/steammessages_offline.steamclient.proto +33 -33
  108. package/protos/steam/steammessages_parental.steamclient.proto +262 -262
  109. package/protos/steam/steammessages_parties.steamclient.proto +75 -75
  110. package/protos/steam/steammessages_partnerapps.steamclient.proto +106 -106
  111. package/protos/steam/steammessages_player.steamclient.proto +915 -915
  112. package/protos/steam/steammessages_publishedfile.steamclient.proto +737 -737
  113. package/protos/steam/steammessages_qms.steamclient.proto +111 -111
  114. package/protos/steam/steammessages_remoteclient.proto +100 -100
  115. package/protos/steam/steammessages_remoteclient_discovery.proto +244 -244
  116. package/protos/steam/steammessages_remoteclient_service.steamclient.proto +31 -31
  117. package/protos/steam/steammessages_remoteclient_service_messages.proto +217 -217
  118. package/protos/steam/steammessages_remoteplay.proto +975 -975
  119. package/protos/steam/steammessages_secrets.steamclient.proto +35 -35
  120. package/protos/steam/steammessages_shader.steamclient.proto +89 -89
  121. package/protos/steam/steammessages_site_license.steamclient.proto +103 -103
  122. package/protos/steam/steammessages_sitelicenseclient.proto +38 -38
  123. package/protos/steam/steammessages_siteserverui.proto +130 -130
  124. package/protos/steam/steammessages_steamtv.steamclient.proto +533 -533
  125. package/protos/steam/steammessages_store.steamclient.proto +404 -404
  126. package/protos/steam/steammessages_storebrowse.steamclient.proto +457 -457
  127. package/protos/steam/steammessages_timedtrial.steamclient.proto +40 -40
  128. package/protos/steam/steammessages_twofactor.steamclient.proto +157 -157
  129. package/protos/steam/steammessages_unified_base.steamclient.proto +45 -45
  130. package/protos/steam/steammessages_unified_test.steamclient.proto +51 -51
  131. package/protos/steam/steammessages_useraccount.steamclient.proto +211 -211
  132. package/protos/steam/steammessages_vac.steamclient.proto +37 -37
  133. package/protos/steam/steammessages_video.steamclient.proto +68 -68
  134. package/protos/steam/steammessages_virtualcontroller.proto +138 -138
  135. package/protos/steam/steammessages_workshop.steamclient.proto +19 -19
  136. package/protos/steam/steamnetworkingsockets_messages.proto +205 -205
  137. package/protos/steam/steamnetworkingsockets_messages_certs.proto +39 -39
  138. package/protos/steam/steamnetworkingsockets_messages_udp.proto +75 -75
  139. package/protos/steam/webuimessages_achievements.proto +29 -29
  140. package/protos/steam/webuimessages_base.proto +24 -24
  141. package/protos/steam/webuimessages_gamenotes.proto +21 -21
  142. package/protos/steam/webuimessages_gamescope.proto +57 -57
  143. package/protos/steam/webuimessages_steamengine.proto +41 -41
  144. package/protos/steam/webuimessages_steamos.proto +114 -114
  145. package/protos/steam/webuimessages_storagedevicemanager.proto +110 -110
  146. package/protos/steam/webuimessages_systemmanager.proto +17 -17
  147. package/protos/steam/webuimessages_transport.proto +22 -22
  148. package/protos/steam/webuimessages_transportvalidation.proto +111 -111
  149. package/protos/webui/common.proto +4024 -4024
  150. package/protos/webui/common_base.proto +27 -27
  151. package/protos/webui/service_accountcart.proto +153 -153
  152. package/protos/webui/service_accountlinking.proto +27 -27
  153. package/protos/webui/service_accountprivacy.proto +42 -42
  154. package/protos/webui/service_accountprivateapps.proto +34 -34
  155. package/protos/webui/service_auction.proto +97 -97
  156. package/protos/webui/service_authentication.proto +222 -222
  157. package/protos/webui/service_authenticationsupport.proto +74 -74
  158. package/protos/webui/service_broadcast.proto +562 -562
  159. package/protos/webui/service_chat.proto +11 -11
  160. package/protos/webui/service_chatroom.proto +810 -810
  161. package/protos/webui/service_chatusability.proto +107 -107
  162. package/protos/webui/service_checkout.proto +84 -84
  163. package/protos/webui/service_clan.proto +41 -41
  164. package/protos/webui/service_clanchatrooms.proto +25 -25
  165. package/protos/webui/service_clanfaqs.proto +202 -202
  166. package/protos/webui/service_clientcomm.proto +151 -151
  167. package/protos/webui/service_clientmetrics.proto +22 -22
  168. package/protos/webui/service_cloud.proto +222 -222
  169. package/protos/webui/service_cloudconfigstore.proto +51 -51
  170. package/protos/webui/service_cloudgaming.proto +30 -30
  171. package/protos/webui/service_community.proto +365 -365
  172. package/protos/webui/service_dailydeal.proto +89 -89
  173. package/protos/webui/service_econ.proto +134 -134
  174. package/protos/webui/service_embedded.proto +24 -24
  175. package/protos/webui/service_experimentservice.proto +6 -6
  176. package/protos/webui/service_familygroups.proto +355 -355
  177. package/protos/webui/service_fovasvideo.proto +15 -15
  178. package/protos/webui/service_friendmessages.proto +133 -133
  179. package/protos/webui/service_friendslist.proto +70 -70
  180. package/protos/webui/service_gamenotes.proto +15 -15
  181. package/protos/webui/service_gamerecording.proto +265 -265
  182. package/protos/webui/service_gamerecordingclip.proto +85 -85
  183. package/protos/webui/service_gamerecordingdebug.proto +52 -52
  184. package/protos/webui/service_helprequestlogs.proto +16 -16
  185. package/protos/webui/service_loyaltyrewards.proto +252 -252
  186. package/protos/webui/service_marketingmessages.proto +215 -215
  187. package/protos/webui/service_mobileapp.proto +18 -18
  188. package/protos/webui/service_mobileauth.proto +24 -24
  189. package/protos/webui/service_mobiledevice.proto +26 -26
  190. package/protos/webui/service_mobileperaccount.proto +31 -31
  191. package/protos/webui/service_news.proto +110 -110
  192. package/protos/webui/service_parental.proto +258 -258
  193. package/protos/webui/service_partnermembershipinvite.proto +34 -34
  194. package/protos/webui/service_partnerstorebrowse.proto +28 -28
  195. package/protos/webui/service_phone.proto +51 -51
  196. package/protos/webui/service_physicalgoods.proto +15 -15
  197. package/protos/webui/service_player.proto +918 -918
  198. package/protos/webui/service_promotioneventinvites.proto +109 -109
  199. package/protos/webui/service_promotionplanning.proto +186 -186
  200. package/protos/webui/service_promotionstats.proto +23 -23
  201. package/protos/webui/service_publishedfile.proto +714 -714
  202. package/protos/webui/service_publishing.proto +200 -200
  203. package/protos/webui/service_quest.proto +127 -127
  204. package/protos/webui/service_salefeature.proto +373 -373
  205. package/protos/webui/service_saleitemrewards.proto +54 -54
  206. package/protos/webui/service_shoppingcart.proto +152 -152
  207. package/protos/webui/service_steamawards.proto +76 -76
  208. package/protos/webui/service_steamcharts.proto +75 -75
  209. package/protos/webui/service_steamengine.proto +36 -36
  210. package/protos/webui/service_steamlearn.proto +876 -876
  211. package/protos/webui/service_steamnotification.proto +73 -73
  212. package/protos/webui/service_steamtv.proto +495 -495
  213. package/protos/webui/service_steamvrvoicechat.proto +67 -67
  214. package/protos/webui/service_steamvrwebrtc.proto +48 -48
  215. package/protos/webui/service_storagedevicemanager.proto +104 -104
  216. package/protos/webui/service_store.proto +359 -359
  217. package/protos/webui/service_storeappsimilarity.proto +76 -76
  218. package/protos/webui/service_storebrowse.proto +103 -103
  219. package/protos/webui/service_storemarketing.proto +44 -44
  220. package/protos/webui/service_storequery.proto +103 -103
  221. package/protos/webui/service_storesales.proto +87 -87
  222. package/protos/webui/service_storetopsellers.proto +44 -44
  223. package/protos/webui/service_systemmanager.proto +11 -11
  224. package/protos/webui/service_test_transporterror.proto +6 -6
  225. package/protos/webui/service_transportauth.proto +17 -17
  226. package/protos/webui/service_transportvalidation.proto +69 -69
  227. package/protos/webui/service_twofactor.proto +170 -170
  228. package/protos/webui/service_useraccount.proto +142 -142
  229. package/protos/webui/service_usergameactivity.proto +34 -34
  230. package/protos/webui/service_usergamenotes.proto +70 -70
  231. package/protos/webui/service_usernews.proto +68 -68
  232. package/protos/webui/service_userreviews.proto +97 -97
  233. package/protos/webui/service_video.proto +50 -50
  234. package/protos/webui/service_videoclip.proto +62 -62
  235. package/protos/webui/service_voicechat.proto +139 -139
  236. package/protos/webui/service_webrtc.proto +52 -52
  237. package/remote.js +5766 -5766
  238. package/.idea/codeStyles/Project.xml +0 -58
  239. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  240. package/test_steamclient.js +0 -20
package/SteamClient.js CHANGED
@@ -1,2437 +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
- 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
- };
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: "xxx",
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, //379243
1034
+ penalty_reason: 0, //4 You did too much damage to your teammates at round start ,5: abandoned
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
+ };