steamutils 1.5.21 → 1.5.23

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 (231) hide show
  1. package/.idea/codeStyles/Project.xml +1 -0
  2. package/.idea/deployment.xml +14 -0
  3. package/.prettierrc.json +3 -3
  4. package/_steamproto.js +39 -39
  5. package/axios.js +84 -84
  6. package/bufferHelpers.js +115 -115
  7. package/cheerio.js +103 -103
  8. package/const.js +1 -0
  9. package/create_proto.js +96 -96
  10. package/full_steamproto.js +39 -39
  11. package/helpers/protos.js +48 -48
  12. package/index.js +3 -4
  13. package/package.json +1 -1
  14. package/protos/csgo/base_gcmessages.proto +553 -553
  15. package/protos/csgo/base_gcmessages_csgo.proto +547 -547
  16. package/protos/csgo/c_peer2peer_netmessages.proto +55 -55
  17. package/protos/csgo/clientmessages.proto +48 -48
  18. package/protos/csgo/connectionless_netmessages.proto +17 -17
  19. package/protos/csgo/cs_gameevents.proto +35 -35
  20. package/protos/csgo/cs_usercmd.proto +34 -34
  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/enums_clientserver.proto +1529 -1529
  25. package/protos/csgo/fatdemo.proto +125 -125
  26. package/protos/csgo/gameevents.proto +120 -120
  27. package/protos/csgo/gcsdk_gcmessages.proto +323 -323
  28. package/protos/csgo/gcsystemmsgs.proto +243 -243
  29. package/protos/csgo/netmessages.proto +618 -618
  30. package/protos/csgo/networkbasetypes.proto +246 -246
  31. package/protos/csgo/networksystem_protomessages.proto +17 -17
  32. package/protos/csgo/steamdatagram_messages_auth.proto +65 -65
  33. package/protos/csgo/steamdatagram_messages_sdr.proto +534 -534
  34. package/protos/csgo/steammessages_cloud.steamworkssdk.proto +68 -68
  35. package/protos/csgo/steammessages_gamenetworkingui.proto +61 -61
  36. package/protos/csgo/steammessages_helprequest.steamworkssdk.proto +22 -22
  37. package/protos/csgo/steammessages_oauth.steamworkssdk.proto +18 -18
  38. package/protos/csgo/steammessages_player.steamworkssdk.proto +254 -254
  39. package/protos/csgo/steammessages_publishedfile.steamworkssdk.proto +233 -233
  40. package/protos/csgo/steamnetworkingsockets_messages.proto +205 -205
  41. package/protos/csgo/steamnetworkingsockets_messages_certs.proto +39 -39
  42. package/protos/csgo/steamnetworkingsockets_messages_udp.proto +75 -75
  43. package/protos/csgo/te.proto +259 -259
  44. package/protos/csgo/uifontfile_format.proto +13 -13
  45. package/protos/csgo/usercmd.proto +39 -39
  46. package/protos/csgo/usermessages.proto +752 -752
  47. package/protos/google/protobuf/descriptor.proto +281 -281
  48. package/protos/steam/clientmetrics.proto +45 -45
  49. package/protos/steam/content_manifest.proto +62 -62
  50. package/protos/steam/contenthubs.proto +41 -41
  51. package/protos/steam/encrypted_app_ticket.proto +10 -10
  52. package/protos/steam/enums.proto +501 -501
  53. package/protos/steam/enums_clientserver.proto +1508 -1508
  54. package/protos/steam/enums_productinfo.proto +14 -14
  55. package/protos/steam/htmlmessages.proto +1039 -1039
  56. package/protos/steam/offline_ticket.proto +8 -8
  57. package/protos/steam/steamdatagram_messages_auth.proto +65 -65
  58. package/protos/steam/steamdatagram_messages_sdr.proto +533 -533
  59. package/protos/steam/steammessages_accounthardware.steamclient.proto +167 -167
  60. package/protos/steam/steammessages_appoverview.proto +204 -204
  61. package/protos/steam/steammessages_auth.steamclient.proto +375 -375
  62. package/protos/steam/steammessages_broadcast.steamclient.proto +618 -618
  63. package/protos/steam/steammessages_chat.steamclient.proto +1070 -1070
  64. package/protos/steam/steammessages_client_objects.proto +649 -649
  65. package/protos/steam/steammessages_clientlanp2p.proto +43 -43
  66. package/protos/steam/steammessages_clientmetrics.steamclient.proto +192 -192
  67. package/protos/steam/steammessages_clientnotificationtypes.proto +250 -250
  68. package/protos/steam/steammessages_clientserver.proto +392 -392
  69. package/protos/steam/steammessages_clientserver_2.proto +771 -771
  70. package/protos/steam/steammessages_clientserver_appinfo.proto +131 -131
  71. package/protos/steam/steammessages_clientserver_friends.proto +260 -260
  72. package/protos/steam/steammessages_clientserver_gameservers.proto +159 -159
  73. package/protos/steam/steammessages_clientserver_lbs.proto +70 -70
  74. package/protos/steam/steammessages_clientserver_login.proto +167 -167
  75. package/protos/steam/steammessages_clientserver_mms.proto +233 -233
  76. package/protos/steam/steammessages_clientserver_ucm.proto +207 -207
  77. package/protos/steam/steammessages_clientserver_uds.proto +125 -125
  78. package/protos/steam/steammessages_clientserver_ufs.proto +45 -45
  79. package/protos/steam/steammessages_clientserver_userstats.proto +80 -80
  80. package/protos/steam/steammessages_cloud.steamclient.proto +422 -422
  81. package/protos/steam/steammessages_contentsystem.steamclient.proto +123 -123
  82. package/protos/steam/steammessages_credentials.steamclient.proto +96 -96
  83. package/protos/steam/steammessages_datapublisher.steamclient.proto +102 -102
  84. package/protos/steam/steammessages_depotbuilder.steamclient.proto +99 -99
  85. package/protos/steam/steammessages_deviceauth.steamclient.proto +169 -169
  86. package/protos/steam/steammessages_econ.steamclient.proto +137 -137
  87. package/protos/steam/steammessages_familygroups.steamclient.proto +441 -441
  88. package/protos/steam/steammessages_friendmessages.steamclient.proto +141 -141
  89. package/protos/steam/steammessages_gamenetworking.steamclient.proto +25 -25
  90. package/protos/steam/steammessages_gamenetworkingui.proto +61 -61
  91. package/protos/steam/steammessages_gamenotifications.steamclient.proto +131 -131
  92. package/protos/steam/steammessages_gameservers.steamclient.proto +136 -136
  93. package/protos/steam/steammessages_hiddevices.proto +157 -157
  94. package/protos/steam/steammessages_inventory.steamclient.proto +172 -172
  95. package/protos/steam/steammessages_linkfilter.steamclient.proto +39 -39
  96. package/protos/steam/steammessages_lobbymatchmaking.steamclient.proto +29 -29
  97. package/protos/steam/steammessages_market.steamclient.proto +22 -22
  98. package/protos/steam/steammessages_marketingmessages.steamclient.proto +273 -273
  99. package/protos/steam/steammessages_offline.steamclient.proto +33 -33
  100. package/protos/steam/steammessages_parental.steamclient.proto +262 -262
  101. package/protos/steam/steammessages_parties.steamclient.proto +75 -75
  102. package/protos/steam/steammessages_partnerapps.steamclient.proto +106 -106
  103. package/protos/steam/steammessages_player.steamclient.proto +915 -915
  104. package/protos/steam/steammessages_publishedfile.steamclient.proto +737 -737
  105. package/protos/steam/steammessages_qms.steamclient.proto +111 -111
  106. package/protos/steam/steammessages_remoteclient.proto +100 -100
  107. package/protos/steam/steammessages_remoteclient_discovery.proto +244 -244
  108. package/protos/steam/steammessages_remoteclient_service.steamclient.proto +31 -31
  109. package/protos/steam/steammessages_remoteclient_service_messages.proto +217 -217
  110. package/protos/steam/steammessages_remoteplay.proto +975 -975
  111. package/protos/steam/steammessages_secrets.steamclient.proto +35 -35
  112. package/protos/steam/steammessages_shader.steamclient.proto +89 -89
  113. package/protos/steam/steammessages_site_license.steamclient.proto +103 -103
  114. package/protos/steam/steammessages_sitelicenseclient.proto +38 -38
  115. package/protos/steam/steammessages_siteserverui.proto +130 -130
  116. package/protos/steam/steammessages_steamtv.steamclient.proto +533 -533
  117. package/protos/steam/steammessages_store.steamclient.proto +404 -404
  118. package/protos/steam/steammessages_storebrowse.steamclient.proto +457 -457
  119. package/protos/steam/steammessages_timedtrial.steamclient.proto +40 -40
  120. package/protos/steam/steammessages_twofactor.steamclient.proto +157 -157
  121. package/protos/steam/steammessages_unified_test.steamclient.proto +51 -51
  122. package/protos/steam/steammessages_useraccount.steamclient.proto +211 -211
  123. package/protos/steam/steammessages_vac.steamclient.proto +37 -37
  124. package/protos/steam/steammessages_video.steamclient.proto +68 -68
  125. package/protos/steam/steammessages_virtualcontroller.proto +138 -138
  126. package/protos/steam/steammessages_workshop.steamclient.proto +19 -19
  127. package/protos/steam/steamnetworkingsockets_messages.proto +205 -205
  128. package/protos/steam/steamnetworkingsockets_messages_certs.proto +39 -39
  129. package/protos/steam/steamnetworkingsockets_messages_udp.proto +75 -75
  130. package/protos/steam/webuimessages_achievements.proto +29 -29
  131. package/protos/steam/webuimessages_gamenotes.proto +21 -21
  132. package/protos/steam/webuimessages_gamescope.proto +57 -57
  133. package/protos/steam/webuimessages_steamengine.proto +41 -41
  134. package/protos/steam/webuimessages_steamos.proto +114 -114
  135. package/protos/steam/webuimessages_storagedevicemanager.proto +110 -110
  136. package/protos/steam/webuimessages_systemmanager.proto +17 -17
  137. package/protos/steam/webuimessages_transport.proto +22 -22
  138. package/protos/steam/webuimessages_transportvalidation.proto +111 -111
  139. package/protos/webui/common.proto +4024 -4024
  140. package/protos/webui/service_accountcart.proto +153 -153
  141. package/protos/webui/service_accountlinking.proto +27 -27
  142. package/protos/webui/service_accountprivacy.proto +42 -42
  143. package/protos/webui/service_accountprivateapps.proto +34 -34
  144. package/protos/webui/service_auction.proto +97 -97
  145. package/protos/webui/service_authentication.proto +222 -222
  146. package/protos/webui/service_authenticationsupport.proto +74 -74
  147. package/protos/webui/service_broadcast.proto +562 -562
  148. package/protos/webui/service_chat.proto +11 -11
  149. package/protos/webui/service_chatroom.proto +810 -810
  150. package/protos/webui/service_chatusability.proto +107 -107
  151. package/protos/webui/service_checkout.proto +84 -84
  152. package/protos/webui/service_clan.proto +41 -41
  153. package/protos/webui/service_clanchatrooms.proto +25 -25
  154. package/protos/webui/service_clanfaqs.proto +202 -202
  155. package/protos/webui/service_clientcomm.proto +151 -151
  156. package/protos/webui/service_clientmetrics.proto +22 -22
  157. package/protos/webui/service_cloud.proto +222 -222
  158. package/protos/webui/service_cloudconfigstore.proto +51 -51
  159. package/protos/webui/service_cloudgaming.proto +30 -30
  160. package/protos/webui/service_community.proto +365 -365
  161. package/protos/webui/service_dailydeal.proto +89 -89
  162. package/protos/webui/service_econ.proto +134 -134
  163. package/protos/webui/service_embedded.proto +24 -24
  164. package/protos/webui/service_experimentservice.proto +6 -6
  165. package/protos/webui/service_familygroups.proto +355 -355
  166. package/protos/webui/service_fovasvideo.proto +15 -15
  167. package/protos/webui/service_friendmessages.proto +133 -133
  168. package/protos/webui/service_friendslist.proto +70 -70
  169. package/protos/webui/service_gamenotes.proto +15 -15
  170. package/protos/webui/service_gamerecording.proto +265 -265
  171. package/protos/webui/service_gamerecordingclip.proto +85 -85
  172. package/protos/webui/service_gamerecordingdebug.proto +52 -52
  173. package/protos/webui/service_helprequestlogs.proto +16 -16
  174. package/protos/webui/service_loyaltyrewards.proto +252 -252
  175. package/protos/webui/service_marketingmessages.proto +215 -215
  176. package/protos/webui/service_mobileapp.proto +18 -18
  177. package/protos/webui/service_mobileauth.proto +24 -24
  178. package/protos/webui/service_mobiledevice.proto +26 -26
  179. package/protos/webui/service_mobileperaccount.proto +31 -31
  180. package/protos/webui/service_news.proto +110 -110
  181. package/protos/webui/service_parental.proto +258 -258
  182. package/protos/webui/service_partnermembershipinvite.proto +34 -34
  183. package/protos/webui/service_partnerstorebrowse.proto +28 -28
  184. package/protos/webui/service_phone.proto +51 -51
  185. package/protos/webui/service_physicalgoods.proto +15 -15
  186. package/protos/webui/service_player.proto +918 -918
  187. package/protos/webui/service_promotioneventinvites.proto +109 -109
  188. package/protos/webui/service_promotionplanning.proto +186 -186
  189. package/protos/webui/service_promotionstats.proto +23 -23
  190. package/protos/webui/service_publishedfile.proto +714 -714
  191. package/protos/webui/service_publishing.proto +200 -200
  192. package/protos/webui/service_quest.proto +127 -127
  193. package/protos/webui/service_salefeature.proto +373 -373
  194. package/protos/webui/service_saleitemrewards.proto +54 -54
  195. package/protos/webui/service_shoppingcart.proto +152 -152
  196. package/protos/webui/service_steamawards.proto +76 -76
  197. package/protos/webui/service_steamcharts.proto +75 -75
  198. package/protos/webui/service_steamengine.proto +36 -36
  199. package/protos/webui/service_steamlearn.proto +876 -876
  200. package/protos/webui/service_steamnotification.proto +73 -73
  201. package/protos/webui/service_steamtv.proto +495 -495
  202. package/protos/webui/service_steamvrvoicechat.proto +67 -67
  203. package/protos/webui/service_steamvrwebrtc.proto +48 -48
  204. package/protos/webui/service_storagedevicemanager.proto +104 -104
  205. package/protos/webui/service_store.proto +359 -359
  206. package/protos/webui/service_storeappsimilarity.proto +76 -76
  207. package/protos/webui/service_storebrowse.proto +103 -103
  208. package/protos/webui/service_storemarketing.proto +44 -44
  209. package/protos/webui/service_storequery.proto +103 -103
  210. package/protos/webui/service_storesales.proto +87 -87
  211. package/protos/webui/service_storetopsellers.proto +44 -44
  212. package/protos/webui/service_systemmanager.proto +11 -11
  213. package/protos/webui/service_test_transporterror.proto +6 -6
  214. package/protos/webui/service_transportauth.proto +17 -17
  215. package/protos/webui/service_transportvalidation.proto +69 -69
  216. package/protos/webui/service_twofactor.proto +170 -170
  217. package/protos/webui/service_useraccount.proto +142 -142
  218. package/protos/webui/service_usergameactivity.proto +34 -34
  219. package/protos/webui/service_usergamenotes.proto +70 -70
  220. package/protos/webui/service_usernews.proto +68 -68
  221. package/protos/webui/service_userreviews.proto +97 -97
  222. package/protos/webui/service_video.proto +50 -50
  223. package/protos/webui/service_videoclip.proto +62 -62
  224. package/protos/webui/service_voicechat.proto +139 -139
  225. package/protos/webui/service_webrtc.proto +52 -52
  226. package/steamproto.js +146 -146
  227. package/utils.js +1234 -1234
  228. package/.idea/gbrowser_project.xml +0 -11
  229. package/.idea/git_toolbox_blame.xml +0 -6
  230. package/.idea/git_toolbox_prj.xml +0 -15
  231. package/race.js +0 -2241
package/utils.js CHANGED
@@ -1,1234 +1,1234 @@
1
- import moment from "moment";
2
- import SteamTotp from "steam-totp";
3
- import { EAuthTokenPlatformType } from "./const.js";
4
- import fs from "fs";
5
- import axios from "axios";
6
- import readline from "readline";
7
- import https from "https";
8
- import { promisify } from "util";
9
- import { pipeline } from "stream";
10
- import _ from "lodash";
11
-
12
- const isBrowser = typeof window !== "undefined";
13
- const g_rgCurrencyData = {
14
- USD: {
15
- strCode: "USD",
16
- eCurrencyCode: 1,
17
- strSymbol: "$",
18
- bSymbolIsPrefix: true,
19
- bWholeUnitsOnly: false,
20
- strDecimalSymbol: ".",
21
- strThousandsSeparator: ",",
22
- strSymbolAndNumberSeparator: "",
23
- },
24
- GBP: {
25
- strCode: "GBP",
26
- eCurrencyCode: 2,
27
- strSymbol: "\u00a3",
28
- bSymbolIsPrefix: true,
29
- bWholeUnitsOnly: false,
30
- strDecimalSymbol: ".",
31
- strThousandsSeparator: ",",
32
- strSymbolAndNumberSeparator: "",
33
- },
34
- EUR: {
35
- strCode: "EUR",
36
- eCurrencyCode: 3,
37
- strSymbol: "\u20ac",
38
- bSymbolIsPrefix: false,
39
- bWholeUnitsOnly: false,
40
- strDecimalSymbol: ",",
41
- strThousandsSeparator: " ",
42
- strSymbolAndNumberSeparator: "",
43
- },
44
- CHF: {
45
- strCode: "CHF",
46
- eCurrencyCode: 4,
47
- strSymbol: "CHF",
48
- bSymbolIsPrefix: true,
49
- bWholeUnitsOnly: false,
50
- strDecimalSymbol: ".",
51
- strThousandsSeparator: " ",
52
- strSymbolAndNumberSeparator: " ",
53
- },
54
- RUB: {
55
- strCode: "RUB",
56
- eCurrencyCode: 5,
57
- strSymbol: "p\u0443\u0431.",
58
- bSymbolIsPrefix: false,
59
- bWholeUnitsOnly: true,
60
- strDecimalSymbol: ",",
61
- strThousandsSeparator: "",
62
- strSymbolAndNumberSeparator: " ",
63
- },
64
- BRL: {
65
- strCode: "BRL",
66
- eCurrencyCode: 7,
67
- strSymbol: "R$",
68
- bSymbolIsPrefix: true,
69
- bWholeUnitsOnly: false,
70
- strDecimalSymbol: ",",
71
- strThousandsSeparator: ".",
72
- strSymbolAndNumberSeparator: " ",
73
- },
74
- JPY: {
75
- strCode: "JPY",
76
- eCurrencyCode: 8,
77
- strSymbol: "\u00a5",
78
- bSymbolIsPrefix: true,
79
- bWholeUnitsOnly: true,
80
- strDecimalSymbol: ".",
81
- strThousandsSeparator: ",",
82
- strSymbolAndNumberSeparator: " ",
83
- },
84
- NOK: {
85
- strCode: "NOK",
86
- eCurrencyCode: 9,
87
- strSymbol: "kr",
88
- bSymbolIsPrefix: false,
89
- bWholeUnitsOnly: false,
90
- strDecimalSymbol: ",",
91
- strThousandsSeparator: ".",
92
- strSymbolAndNumberSeparator: " ",
93
- },
94
- IDR: {
95
- strCode: "IDR",
96
- eCurrencyCode: 10,
97
- strSymbol: "Rp",
98
- bSymbolIsPrefix: true,
99
- bWholeUnitsOnly: true,
100
- strDecimalSymbol: ".",
101
- strThousandsSeparator: " ",
102
- strSymbolAndNumberSeparator: " ",
103
- },
104
- MYR: {
105
- strCode: "MYR",
106
- eCurrencyCode: 11,
107
- strSymbol: "RM",
108
- bSymbolIsPrefix: true,
109
- bWholeUnitsOnly: false,
110
- strDecimalSymbol: ".",
111
- strThousandsSeparator: ",",
112
- strSymbolAndNumberSeparator: "",
113
- },
114
- PHP: {
115
- strCode: "PHP",
116
- eCurrencyCode: 12,
117
- strSymbol: "P",
118
- bSymbolIsPrefix: true,
119
- bWholeUnitsOnly: false,
120
- strDecimalSymbol: ".",
121
- strThousandsSeparator: ",",
122
- strSymbolAndNumberSeparator: "",
123
- },
124
- SGD: {
125
- strCode: "SGD",
126
- eCurrencyCode: 13,
127
- strSymbol: "S$",
128
- bSymbolIsPrefix: true,
129
- bWholeUnitsOnly: false,
130
- strDecimalSymbol: ".",
131
- strThousandsSeparator: ",",
132
- strSymbolAndNumberSeparator: "",
133
- },
134
- THB: {
135
- strCode: "THB",
136
- eCurrencyCode: 14,
137
- strSymbol: "\u0e3f",
138
- bSymbolIsPrefix: true,
139
- bWholeUnitsOnly: false,
140
- strDecimalSymbol: ".",
141
- strThousandsSeparator: ",",
142
- strSymbolAndNumberSeparator: "",
143
- },
144
- VND: {
145
- strCode: "VND",
146
- eCurrencyCode: 15,
147
- strSymbol: "\u20ab",
148
- bSymbolIsPrefix: false,
149
- bWholeUnitsOnly: true,
150
- strDecimalSymbol: ",",
151
- strThousandsSeparator: ".",
152
- strSymbolAndNumberSeparator: "",
153
- },
154
- KRW: {
155
- strCode: "KRW",
156
- eCurrencyCode: 16,
157
- strSymbol: "\u20a9",
158
- bSymbolIsPrefix: true,
159
- bWholeUnitsOnly: true,
160
- strDecimalSymbol: ".",
161
- strThousandsSeparator: ",",
162
- strSymbolAndNumberSeparator: " ",
163
- },
164
- TRY: {
165
- strCode: "TRY",
166
- eCurrencyCode: 17,
167
- strSymbol: "TL",
168
- bSymbolIsPrefix: false,
169
- bWholeUnitsOnly: false,
170
- strDecimalSymbol: ",",
171
- strThousandsSeparator: ".",
172
- strSymbolAndNumberSeparator: " ",
173
- },
174
- UAH: {
175
- strCode: "UAH",
176
- eCurrencyCode: 18,
177
- strSymbol: "\u20b4",
178
- bSymbolIsPrefix: false,
179
- bWholeUnitsOnly: true,
180
- strDecimalSymbol: ",",
181
- strThousandsSeparator: " ",
182
- strSymbolAndNumberSeparator: "",
183
- },
184
- MXN: {
185
- strCode: "MXN",
186
- eCurrencyCode: 19,
187
- strSymbol: "Mex$",
188
- bSymbolIsPrefix: true,
189
- bWholeUnitsOnly: false,
190
- strDecimalSymbol: ".",
191
- strThousandsSeparator: ",",
192
- strSymbolAndNumberSeparator: " ",
193
- },
194
- CAD: {
195
- strCode: "CAD",
196
- eCurrencyCode: 20,
197
- strSymbol: "CDN$",
198
- bSymbolIsPrefix: true,
199
- bWholeUnitsOnly: false,
200
- strDecimalSymbol: ".",
201
- strThousandsSeparator: ",",
202
- strSymbolAndNumberSeparator: " ",
203
- },
204
- AUD: {
205
- strCode: "AUD",
206
- eCurrencyCode: 21,
207
- strSymbol: "A$",
208
- bSymbolIsPrefix: true,
209
- bWholeUnitsOnly: false,
210
- strDecimalSymbol: ".",
211
- strThousandsSeparator: ",",
212
- strSymbolAndNumberSeparator: " ",
213
- },
214
- NZD: {
215
- strCode: "NZD",
216
- eCurrencyCode: 22,
217
- strSymbol: "NZ$",
218
- bSymbolIsPrefix: true,
219
- bWholeUnitsOnly: false,
220
- strDecimalSymbol: ".",
221
- strThousandsSeparator: ",",
222
- strSymbolAndNumberSeparator: " ",
223
- },
224
- PLN: {
225
- strCode: "PLN",
226
- eCurrencyCode: 6,
227
- strSymbol: "z\u0142",
228
- bSymbolIsPrefix: false,
229
- bWholeUnitsOnly: false,
230
- strDecimalSymbol: ",",
231
- strThousandsSeparator: " ",
232
- strSymbolAndNumberSeparator: "",
233
- },
234
- CNY: {
235
- strCode: "CNY",
236
- eCurrencyCode: 23,
237
- strSymbol: "\u00a5",
238
- bSymbolIsPrefix: true,
239
- bWholeUnitsOnly: false,
240
- strDecimalSymbol: ".",
241
- strThousandsSeparator: ",",
242
- strSymbolAndNumberSeparator: " ",
243
- },
244
- INR: {
245
- strCode: "INR",
246
- eCurrencyCode: 24,
247
- strSymbol: "\u20b9",
248
- bSymbolIsPrefix: true,
249
- bWholeUnitsOnly: true,
250
- strDecimalSymbol: ".",
251
- strThousandsSeparator: ",",
252
- strSymbolAndNumberSeparator: " ",
253
- },
254
- CLP: {
255
- strCode: "CLP",
256
- eCurrencyCode: 25,
257
- strSymbol: "CLP$",
258
- bSymbolIsPrefix: true,
259
- bWholeUnitsOnly: true,
260
- strDecimalSymbol: ",",
261
- strThousandsSeparator: ".",
262
- strSymbolAndNumberSeparator: " ",
263
- },
264
- PEN: {
265
- strCode: "PEN",
266
- eCurrencyCode: 26,
267
- strSymbol: "S/.",
268
- bSymbolIsPrefix: true,
269
- bWholeUnitsOnly: false,
270
- strDecimalSymbol: ".",
271
- strThousandsSeparator: ",",
272
- strSymbolAndNumberSeparator: "",
273
- },
274
- COP: {
275
- strCode: "COP",
276
- eCurrencyCode: 27,
277
- strSymbol: "COL$",
278
- bSymbolIsPrefix: true,
279
- bWholeUnitsOnly: true,
280
- strDecimalSymbol: ",",
281
- strThousandsSeparator: ".",
282
- strSymbolAndNumberSeparator: " ",
283
- },
284
- ZAR: {
285
- strCode: "ZAR",
286
- eCurrencyCode: 28,
287
- strSymbol: "R",
288
- bSymbolIsPrefix: true,
289
- bWholeUnitsOnly: false,
290
- strDecimalSymbol: ".",
291
- strThousandsSeparator: " ",
292
- strSymbolAndNumberSeparator: " ",
293
- },
294
- HKD: {
295
- strCode: "HKD",
296
- eCurrencyCode: 29,
297
- strSymbol: "HK$",
298
- bSymbolIsPrefix: true,
299
- bWholeUnitsOnly: false,
300
- strDecimalSymbol: ".",
301
- strThousandsSeparator: ",",
302
- strSymbolAndNumberSeparator: " ",
303
- },
304
- TWD: {
305
- strCode: "TWD",
306
- eCurrencyCode: 30,
307
- strSymbol: "NT$",
308
- bSymbolIsPrefix: true,
309
- bWholeUnitsOnly: true,
310
- strDecimalSymbol: ".",
311
- strThousandsSeparator: ",",
312
- strSymbolAndNumberSeparator: " ",
313
- },
314
- SAR: {
315
- strCode: "SAR",
316
- eCurrencyCode: 31,
317
- strSymbol: "SR",
318
- bSymbolIsPrefix: false,
319
- bWholeUnitsOnly: false,
320
- strDecimalSymbol: ".",
321
- strThousandsSeparator: ",",
322
- strSymbolAndNumberSeparator: " ",
323
- },
324
- AED: {
325
- strCode: "AED",
326
- eCurrencyCode: 32,
327
- strSymbol: "AED",
328
- bSymbolIsPrefix: false,
329
- bWholeUnitsOnly: false,
330
- strDecimalSymbol: ".",
331
- strThousandsSeparator: ",",
332
- strSymbolAndNumberSeparator: " ",
333
- },
334
- SEK: {
335
- strCode: "SEK",
336
- eCurrencyCode: 33,
337
- strSymbol: "kr",
338
- bSymbolIsPrefix: false,
339
- bWholeUnitsOnly: false,
340
- strDecimalSymbol: ".",
341
- strThousandsSeparator: ",",
342
- strSymbolAndNumberSeparator: " ",
343
- },
344
- ARS: {
345
- strCode: "ARS",
346
- eCurrencyCode: 34,
347
- strSymbol: "ARS$",
348
- bSymbolIsPrefix: true,
349
- bWholeUnitsOnly: false,
350
- strDecimalSymbol: ",",
351
- strThousandsSeparator: ".",
352
- strSymbolAndNumberSeparator: " ",
353
- },
354
- ILS: {
355
- strCode: "ILS",
356
- eCurrencyCode: 35,
357
- strSymbol: "\u20aa",
358
- bSymbolIsPrefix: true,
359
- bWholeUnitsOnly: false,
360
- strDecimalSymbol: ".",
361
- strThousandsSeparator: ",",
362
- strSymbolAndNumberSeparator: "",
363
- },
364
- BYN: {
365
- strCode: "BYN",
366
- eCurrencyCode: 36,
367
- strSymbol: "Br",
368
- bSymbolIsPrefix: true,
369
- bWholeUnitsOnly: false,
370
- strDecimalSymbol: ".",
371
- strThousandsSeparator: ",",
372
- strSymbolAndNumberSeparator: "",
373
- },
374
- KZT: {
375
- strCode: "KZT",
376
- eCurrencyCode: 37,
377
- strSymbol: "\u20b8",
378
- bSymbolIsPrefix: false,
379
- bWholeUnitsOnly: true,
380
- strDecimalSymbol: ",",
381
- strThousandsSeparator: " ",
382
- strSymbolAndNumberSeparator: "",
383
- },
384
- KWD: {
385
- strCode: "KWD",
386
- eCurrencyCode: 38,
387
- strSymbol: "KD",
388
- bSymbolIsPrefix: false,
389
- bWholeUnitsOnly: false,
390
- strDecimalSymbol: ".",
391
- strThousandsSeparator: ",",
392
- strSymbolAndNumberSeparator: " ",
393
- },
394
- QAR: {
395
- strCode: "QAR",
396
- eCurrencyCode: 39,
397
- strSymbol: "QR",
398
- bSymbolIsPrefix: false,
399
- bWholeUnitsOnly: false,
400
- strDecimalSymbol: ".",
401
- strThousandsSeparator: ",",
402
- strSymbolAndNumberSeparator: " ",
403
- },
404
- CRC: {
405
- strCode: "CRC",
406
- eCurrencyCode: 40,
407
- strSymbol: "\u20a1",
408
- bSymbolIsPrefix: true,
409
- bWholeUnitsOnly: true,
410
- strDecimalSymbol: ",",
411
- strThousandsSeparator: ".",
412
- strSymbolAndNumberSeparator: "",
413
- },
414
- UYU: {
415
- strCode: "UYU",
416
- eCurrencyCode: 41,
417
- strSymbol: "$U",
418
- bSymbolIsPrefix: true,
419
- bWholeUnitsOnly: true,
420
- strDecimalSymbol: ",",
421
- strThousandsSeparator: ".",
422
- strSymbolAndNumberSeparator: "",
423
- },
424
- BGN: {
425
- strCode: "BGN",
426
- eCurrencyCode: 42,
427
- strSymbol: "\u043b\u0432",
428
- bSymbolIsPrefix: false,
429
- bWholeUnitsOnly: false,
430
- strDecimalSymbol: ".",
431
- strThousandsSeparator: ",",
432
- strSymbolAndNumberSeparator: " ",
433
- },
434
- HRK: {
435
- strCode: "HRK",
436
- eCurrencyCode: 43,
437
- strSymbol: "kn",
438
- bSymbolIsPrefix: false,
439
- bWholeUnitsOnly: false,
440
- strDecimalSymbol: ".",
441
- strThousandsSeparator: ",",
442
- strSymbolAndNumberSeparator: " ",
443
- },
444
- CZK: {
445
- strCode: "CZK",
446
- eCurrencyCode: 44,
447
- strSymbol: "K\u010d",
448
- bSymbolIsPrefix: false,
449
- bWholeUnitsOnly: false,
450
- strDecimalSymbol: ".",
451
- strThousandsSeparator: ",",
452
- strSymbolAndNumberSeparator: " ",
453
- },
454
- DKK: {
455
- strCode: "DKK",
456
- eCurrencyCode: 45,
457
- strSymbol: "kr.",
458
- bSymbolIsPrefix: false,
459
- bWholeUnitsOnly: false,
460
- strDecimalSymbol: ".",
461
- strThousandsSeparator: ",",
462
- strSymbolAndNumberSeparator: " ",
463
- },
464
- HUF: {
465
- strCode: "HUF",
466
- eCurrencyCode: 46,
467
- strSymbol: "Ft",
468
- bSymbolIsPrefix: false,
469
- bWholeUnitsOnly: false,
470
- strDecimalSymbol: ".",
471
- strThousandsSeparator: ",",
472
- strSymbolAndNumberSeparator: " ",
473
- },
474
- RON: {
475
- strCode: "RON",
476
- eCurrencyCode: 47,
477
- strSymbol: "lei",
478
- bSymbolIsPrefix: false,
479
- bWholeUnitsOnly: false,
480
- strDecimalSymbol: ".",
481
- strThousandsSeparator: ",",
482
- strSymbolAndNumberSeparator: " ",
483
- },
484
- RMB: {
485
- strCode: "RMB",
486
- eCurrencyCode: 9000,
487
- strSymbol: "\u5200\u5e01",
488
- bSymbolIsPrefix: false,
489
- bWholeUnitsOnly: true,
490
- strDecimalSymbol: ".",
491
- strThousandsSeparator: "",
492
- strSymbolAndNumberSeparator: " ",
493
- },
494
- NXP: {
495
- strCode: "NXP",
496
- eCurrencyCode: 9001,
497
- strSymbol: "\uc6d0",
498
- bSymbolIsPrefix: false,
499
- bWholeUnitsOnly: true,
500
- strDecimalSymbol: ".",
501
- strThousandsSeparator: ",",
502
- strSymbolAndNumberSeparator: "",
503
- },
504
- };
505
- const g_rgWalletInfo = {
506
- wallet_currency: 15,
507
- wallet_country: "VN",
508
- wallet_state: "",
509
- wallet_fee: "1",
510
- wallet_fee_minimum: "1",
511
- wallet_fee_percent: "0.05",
512
- wallet_publisher_fee_percent_default: "0.10",
513
- wallet_fee_base: "0",
514
- wallet_balance: "6540490",
515
- wallet_delayed_balance: "0",
516
- wallet_max_balance: "4500000000",
517
- wallet_trade_max_balance: "4049999616",
518
- success: 1,
519
- rwgrsn: -2,
520
- };
521
-
522
- export const sleep = (ms) => {
523
- return new Promise((resolve) => {
524
- setTimeout(resolve, ms);
525
- });
526
- };
527
-
528
- export const sleepRandom = async (startMs, endMs) => {
529
- return await sleep(Math.random() * (endMs - startMs) + startMs);
530
- };
531
-
532
- /**
533
- * const audioTrack = stream.getAudioTracks()[0]
534
- * const videoStream = UserMedia.createBlankVideoTrack()
535
- * videoStream.addTrack(audioTrack)
536
- * stream = videoStream
537
- * **/
538
- export const createBlankVideoTrack = (opts = {}) => {
539
- const { width = 1920, height = 1080 } = opts;
540
-
541
- const canvas = Object.assign(document.createElement("canvas"), {
542
- width,
543
- height,
544
- });
545
-
546
- canvas.getContext("2d").fillRect(0, 0, width, height);
547
-
548
- return canvas.captureStream();
549
- };
550
-
551
- const minDate = new Date(0),
552
- maxDate = new Date(parseInt("ffffffff", 16) * 1000);
553
-
554
- export function objectIdFromDate(date) {
555
- if (date < minDate || date > maxDate) {
556
- return `Error: date must be between ${minDate.getFullYear()} and ${maxDate.getFullYear()}`;
557
- }
558
- var pad = "00000000";
559
- var hexSeconds = Math.floor(date.getTime() / 1000).toString(16);
560
- return `${pad.substring(0, pad.length - hexSeconds.length) + hexSeconds}0000000000000000`;
561
- }
562
-
563
- export function dateFromObjectId(objectId) {
564
- return new Date(parseInt(objectId.substring(0, 8), 16) * 1000);
565
- }
566
-
567
- export function console_log(...args) {
568
- const params = [];
569
- params.push(new Date().toUTCString());
570
- const errorStack = new Error().stack;
571
- const fnName = errorStack
572
- .split("\n")
573
- .map((e) => e?.trim())
574
- .filter((e) => e.startsWith("at") && !e.startsWith("at console_log") && !e.startsWith("at processTicksAndRejections"))[0]
575
- .substr(3);
576
- params.push(fnName);
577
- console.log(
578
- params
579
- .filter(Boolean)
580
- .map((p) => `[${p.trim()}]`)
581
- .join(" "),
582
- ...args,
583
- );
584
- }
585
-
586
- export function removeSpaceKeys(object) {
587
- //mutate object
588
- if (!object || Array.isArray(object)) {
589
- return object;
590
- }
591
-
592
- Object.entries(object).forEach(([key, value]) => {
593
- const newKey = key.replaceAll(/[^a-zA-Z0-9]/gi, "_");
594
- if (newKey !== key) {
595
- delete object[key];
596
- object[newKey] = value;
597
- }
598
- });
599
- return object;
600
- }
601
-
602
- export function getCleanObject(object) {
603
- //like removeSpaceKeys but not mutate object
604
- if (!object || Array.isArray(object)) {
605
- return object;
606
- }
607
-
608
- const newObject = {};
609
- Object.entries(object).forEach(([key, value]) => {
610
- const newKey = key.replaceAll(/[^a-zA-Z0-9]/gi, "_");
611
- newObject[newKey] = value;
612
- });
613
- return newObject;
614
- }
615
-
616
- export function JSON_parse(data) {
617
- try {
618
- return JSON.parse(data);
619
- } catch (e) {
620
- return null;
621
- }
622
- }
623
-
624
- export function JSON_stringify(data) {
625
- try {
626
- return JSON.stringify(data);
627
- } catch (e) {
628
- return null;
629
- }
630
- }
631
-
632
- export async function throttle(fn, delay) {
633
- let canFire = true;
634
- let queue = [];
635
-
636
- async function pop() {
637
- if (queue.length < 1) return;
638
-
639
- const [that, args] = queue.pop();
640
- await fn.apply(that, args);
641
- canFire = false;
642
- setTimeout(async () => {
643
- canFire = true;
644
- await pop();
645
- }, delay);
646
- }
647
-
648
- async function push() {
649
- queue.push([this, arguments]);
650
- if (canFire) {
651
- await pop();
652
- }
653
- }
654
-
655
- push.cancel = () => {
656
- queue = [];
657
- };
658
-
659
- return push;
660
- }
661
-
662
- export const secretAsBuffer = (sharedSecret) => {
663
- if (Buffer.isBuffer(sharedSecret)) {
664
- return sharedSecret;
665
- }
666
-
667
- if (sharedSecret.match(/^[0-9a-f]{40}$/i)) {
668
- // Looks like it's hex
669
- return Buffer.from(sharedSecret, "hex");
670
- }
671
-
672
- // It must be base64
673
- return Buffer.from(sharedSecret, "base64");
674
- };
675
-
676
- export function decodeLoginQrUrl(qrUrl) {
677
- if (!qrUrl || typeof qrUrl !== "string") {
678
- return null;
679
- }
680
- const match = qrUrl.match(/^https?:\/\/s\.team\/q\/(\d+)\/(\d+)(\?|$)/);
681
- if (!match) {
682
- console.log("Invalid QR code URL");
683
- return null;
684
- }
685
-
686
- return { clientId: match[2], version: parseInt(match[1], 10) };
687
- }
688
-
689
- export function decodeJwt(jwt) {
690
- try {
691
- const parts = jwt.split(".");
692
- if (parts.length !== 3) {
693
- console.err("decodeJwt Error", new Error("Invalid JWT"));
694
- return;
695
- }
696
-
697
- const standardBase64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
698
- return JSON.parse(Buffer.from(standardBase64, "base64").toString("utf8"));
699
- } catch (e) {
700
- console.error("decodeJwt Error", e);
701
- }
702
- }
703
-
704
- export async function renewRefreshToken({ refreshToken, accessToken }) {
705
- const steamId = arguments[0]?.steamId;
706
- try {
707
- const { aud } = decodeJwt(accessToken);
708
- let platformType = EAuthTokenPlatformType.SteamClient;
709
- if (aud.includes("mobile")) {
710
- platformType = EAuthTokenPlatformType.MobileApp;
711
- } else if (aud.includes("client")) {
712
- platformType = EAuthTokenPlatformType.SteamClient;
713
- } else if (aud.includes("web")) {
714
- platformType = EAuthTokenPlatformType.WebBrowser;
715
- }
716
-
717
- const { LoginSession } = await import("steam-session");
718
- const session = new LoginSession(platformType);
719
- session.refreshToken = refreshToken;
720
- await session.refreshAccessToken();
721
- const cookie = (await session.getWebCookies())?.join?.(";");
722
- return {
723
- cookie,
724
- accessToken: session.accessToken,
725
- accessTokenDecoded: decodeJwt(session.accessToken),
726
- };
727
- } catch (e) {
728
- console.error(`${steamId ? `[${steamId}] ` : ""}renewRefreshToken Error`, e);
729
- }
730
- }
731
-
732
- export async function approveLogin({ steamId, url, sharedSecret, accessToken, shouldApprove }) {
733
- try {
734
- const { LoginApprover } = await import("steam-session");
735
- const approver = new LoginApprover(accessToken, sharedSecret, {});
736
- const sessionInfo = await approver.getAuthSessionInfo(url);
737
- sessionInfo.steamId = steamId;
738
-
739
- if (typeof shouldApprove === "function" && !shouldApprove(sessionInfo)) {
740
- return;
741
- }
742
-
743
- await approver.approveAuthSession({
744
- qrChallengeUrl: url,
745
- approve: true,
746
- });
747
-
748
- return {
749
- steamId,
750
- sessionInfo,
751
- };
752
- } catch (error) {
753
- console.error(`[${steamId}] approveLogin Error`, error);
754
- return {
755
- steamId,
756
- error,
757
- };
758
- }
759
- }
760
-
761
- export function getBonusXpTimeRefresh() {
762
- let resetDay = moment.utc().startOf("isoWeek").add(2, "days").add(1, "hours");
763
- while (moment().isAfter(resetDay)) {
764
- resetDay = resetDay.add(7, "days");
765
- }
766
- if (moment().isBefore(resetDay)) {
767
- resetDay = resetDay.subtract(7, "days");
768
- }
769
- return resetDay;
770
- }
771
-
772
- export function estimateNextXp(currentXp, xpEarned) {
773
- //estimate next xp
774
- let bonusTime = 1;
775
- if (xpEarned < 4500) {
776
- bonusTime = 4;
777
- } else if (xpEarned < 7500) {
778
- bonusTime = 2;
779
- } else if (xpEarned < 11200) {
780
- bonusTime = 1;
781
- } else {
782
- bonusTime = 0.175;
783
- }
784
-
785
- const nextXp = 30 * 13 * bonusTime;
786
- return nextXp + currentXp;
787
- }
788
-
789
- export function formatMarketCurrency(valueInCents, currencyCode = getMarketCurrencyCode(g_rgWalletInfo.wallet_currency), countryCode) {
790
- if (!valueInCents && valueInCents !== 0) {
791
- return "";
792
- }
793
-
794
- let currencyFormat = (valueInCents / 100).toFixed(2);
795
-
796
- if (g_rgCurrencyData[currencyCode]) {
797
- const currencyData = g_rgCurrencyData[currencyCode];
798
- if (isCurrencyWholeUnits(currencyCode)) {
799
- currencyFormat = currencyFormat.replace(".00", "");
800
- }
801
-
802
- if (currencyData.strDecimalSymbol !== ".") {
803
- currencyFormat = currencyFormat.replace(".", currencyData.strDecimalSymbol);
804
- }
805
-
806
- const currencySymbol = getMarketCurrencySymbol(currencyCode);
807
- const currencyReturn = isCurrencySymbolBeforeValue(currencyCode) ? currencySymbol + currencyData.strSymbolAndNumberSeparator + currencyFormat : currencyFormat + currencyData.strSymbolAndNumberSeparator + currencySymbol;
808
-
809
- if (currencyCode === "USD" && typeof countryCode != "undefined" && countryCode != "US") {
810
- return `${currencyReturn} USD`;
811
- } else if (currencyCode === "EUR") {
812
- return currencyReturn.replace(",00", ",--");
813
- } else {
814
- return currencyReturn;
815
- }
816
- } else {
817
- return `${currencyFormat} ${currencyCode}`;
818
- }
819
- }
820
-
821
- export function getMarketPriceValueAsInt(strAmount) {
822
- let nAmount;
823
- if (!strAmount) {
824
- return 0;
825
- }
826
-
827
- // Users may enter either comma or period for the decimal mark and digit group separators.
828
- strAmount = strAmount.replace(/,/g, ".");
829
-
830
- // strip the currency symbol, set .-- to .00
831
- strAmount = strAmount.replace(getMarketCurrencySymbol(getMarketCurrencyCode(g_rgWalletInfo.wallet_currency)), "").replace(".--", ".00");
832
-
833
- // strip spaces
834
- strAmount = strAmount.replace(/ /g, "");
835
-
836
- // Remove all but the last period so that entries like "1,147.6" work
837
- if (strAmount.includes(".")) {
838
- var splitAmount = strAmount.split(".");
839
- var strLastSegment = splitAmount[splitAmount.length - 1];
840
-
841
- if (!isNaN(strLastSegment) && strLastSegment.length == 3 && splitAmount[splitAmount.length - 2] != "0") {
842
- // Looks like the user only entered thousands separators. Remove all commas and periods.
843
- // Ensures an entry like "1,147" is not treated as "1.147"
844
- //
845
- // Users may be surprised to find that "1.147" is treated as "1,147". "1.147" is either an error or the user
846
- // really did mean one thousand one hundred and forty seven since no currencies can be split into more than
847
- // hundredths. If it was an error, the user should notice in the next step of the dialog and can go back and
848
- // correct it. If they happen to not notice, it is better that we list the item at a higher price than
849
- // intended instead of lower than intended (which we would have done if we accepted the 1.147 value as is).
850
- strAmount = splitAmount.join("");
851
- } else {
852
- strAmount = `${splitAmount.slice(0, -1).join("")}.${strLastSegment}`;
853
- }
854
- }
855
-
856
- let flAmount = parseFloat(strAmount) * 100;
857
- nAmount = Math.floor(isNaN(flAmount) ? 0 : flAmount + 0.000001); // round down
858
-
859
- nAmount = Math.max(nAmount, 0);
860
- return nAmount;
861
- }
862
-
863
- export function isCurrencyWholeUnits(currencyCode) {
864
- return g_rgCurrencyData[currencyCode] && g_rgCurrencyData[currencyCode].bWholeUnitsOnly && currencyCode !== "RUB";
865
- }
866
-
867
- export function isCurrencySymbolBeforeValue(currencyCode) {
868
- return g_rgCurrencyData[currencyCode] && g_rgCurrencyData[currencyCode].bSymbolIsPrefix;
869
- }
870
-
871
- // Return the symbol to use for a currency
872
- export function getMarketCurrencySymbol(currencyCode) {
873
- return g_rgCurrencyData[currencyCode]?.strSymbol ?? currencyCode;
874
- }
875
-
876
- export function getMarketCurrencyCode(currencyId) {
877
- currencyId = parseInt(currencyId);
878
- for (const code in g_rgCurrencyData) {
879
- if (g_rgCurrencyData[code].eCurrencyCode === currencyId) {
880
- return code;
881
- }
882
- }
883
- return "Unknown";
884
- }
885
-
886
- export async function loginWithCredentials({ username, password, timeoutMs = 120000, sharedSecret, getMailSteamGuardCodes }) {
887
- if (!username) {
888
- return {
889
- error: "No username",
890
- };
891
- }
892
-
893
- if (!password) {
894
- return {
895
- error: "No password",
896
- };
897
- }
898
-
899
- const { LoginSession } = await import("steam-session");
900
- let authenticated = false;
901
- return new Promise((resolve) => {
902
- const timeout = setTimeout(function () {
903
- resolve({
904
- error: "Timed out",
905
- });
906
- }, timeoutMs);
907
-
908
- const session = new LoginSession(EAuthTokenPlatformType.MobileApp);
909
- session.on("authenticated", async () => {
910
- authenticated = true;
911
- const cookie = (await session.getWebCookies())?.join?.(";");
912
- return onResolve({
913
- cookie,
914
- accessToken: session.accessToken,
915
- refreshToken: session.refreshToken,
916
- accessTokenDecoded: decodeJwt(session.accessToken),
917
- });
918
- });
919
-
920
- session
921
- .startWithCredentials({
922
- accountName: username,
923
- password: password,
924
- steamGuardMachineToken: "",
925
- })
926
- .then(async function (startResult) {
927
- if (!startResult.actionRequired) {
928
- return;
929
- }
930
-
931
- if (sharedSecret) {
932
- let error = null;
933
- const maxRetry = 3;
934
- for (let i = 0; i < maxRetry; i++) {
935
- try {
936
- await session.submitSteamGuardCode(SteamTotp.generateAuthCode(sharedSecret));
937
- error = null;
938
- } catch (e) {
939
- error = e;
940
- }
941
- await sleep(1000);
942
- }
943
- if (error) {
944
- console.error(error);
945
- onResolve({ error });
946
- }
947
- } else {
948
- if (startResult.validActions.every((validAction) => validAction.type !== 2)) {
949
- console.error(startResult.validActions);
950
- return onResolve({
951
- error: "validActions",
952
- });
953
- }
954
-
955
- if (typeof getMailSteamGuardCodes === "function") {
956
- const codes = await getMailSteamGuardCodes();
957
- if (!Array.isArray(codes) || !codes.length) {
958
- return onResolve({
959
- error: "Can't find steam guard code",
960
- });
961
- }
962
-
963
- let error = null;
964
- for (const code of codes) {
965
- if (!authenticated) {
966
- try {
967
- await session.submitSteamGuardCode(code);
968
- error = null;
969
- } catch (e) {
970
- error = e;
971
- }
972
- await sleep(1000);
973
- }
974
- }
975
- if (!authenticated && error) {
976
- onResolve(error);
977
- }
978
- } else {
979
- return onResolve({
980
- error: "MailCodeError",
981
- });
982
- }
983
- }
984
- })
985
- .catch(function (e) {
986
- return onResolve(e);
987
- });
988
-
989
- function onResolve(data) {
990
- clearTimeout(timeout);
991
- return resolve(data);
992
- }
993
- });
994
- }
995
-
996
- export function calculateAccountXP(currentXp, xpEarnedThisWeek, xpEarned, nextXp) {
997
- return (
998
- (() => {
999
- if (typeof nextXp !== "number" || !Number.isFinite(nextXp)) {
1000
- return;
1001
- }
1002
-
1003
- currentXp = currentXp || 0;
1004
- if (currentXp === nextXp) {
1005
- return;
1006
- }
1007
-
1008
- const update = { currentXp: nextXp };
1009
- if (nextXp < currentXp) {
1010
- update.xpExceed = Date.now();
1011
- }
1012
- const resetDay = getBonusXpTimeRefresh().format("YYYY-MM-DD");
1013
- const isWeekReset = xpEarnedThisWeek !== resetDay;
1014
- let xpEarnedThisRank = nextXp - currentXp;
1015
- if (xpEarnedThisRank < 0) {
1016
- xpEarnedThisRank += 5000;
1017
- }
1018
- if (isWeekReset) {
1019
- update.xpEarnedThisWeek = resetDay;
1020
- update.xpEarned = xpEarnedThisRank;
1021
- } else {
1022
- update.xpEarned = (xpEarned || 0) + xpEarnedThisRank;
1023
- if (xpEarnedThisRank === 0) {
1024
- return;
1025
- }
1026
- }
1027
-
1028
- return update;
1029
- })() || {}
1030
- );
1031
- }
1032
-
1033
- export async function downloadImage(url, filePath) {
1034
- let response = null;
1035
- try {
1036
- response = await axios.get(url, {
1037
- responseType: "arraybuffer",
1038
- });
1039
- } catch (e) {
1040
- /* empty */
1041
- }
1042
-
1043
- if (!response || !response.data) {
1044
- return;
1045
- }
1046
-
1047
- return new Promise((resolve) => {
1048
- fs.writeFile(filePath, response.data, (err) => {
1049
- if (err) {
1050
- resolve();
1051
- }
1052
- resolve(filePath);
1053
- });
1054
- });
1055
- }
1056
-
1057
- export async function downloadLargeImage(url, filePath) {
1058
- try {
1059
- const response = await new Promise((resolve, reject) => {
1060
- https
1061
- .get(url, (res) => {
1062
- if (res.statusCode === 200) {
1063
- resolve(res);
1064
- } else {
1065
- reject(new Error(`Failed to get image, status code: ${res.statusCode}`));
1066
- }
1067
- })
1068
- .on("error", reject);
1069
- });
1070
-
1071
- const streamPipeline = promisify(pipeline);
1072
- await streamPipeline(response, fs.createWriteStream(filePath));
1073
- console.log("Download large image completed.");
1074
- return true;
1075
- } catch (error) {
1076
- console.error(`Error downloading large image: ${error.message}`);
1077
- return false;
1078
- }
1079
- }
1080
-
1081
- //from large text file
1082
- export function readRandomLine(filePath, isValidLine) {
1083
- return new Promise((resolve, reject) => {
1084
- const rl = readline.createInterface({
1085
- input: fs.createReadStream(filePath),
1086
- crlfDelay: Infinity,
1087
- });
1088
-
1089
- let resultLine = null;
1090
- let lineNumber = 0;
1091
-
1092
- rl.on("line", (line) => {
1093
- if (typeof isValidLine === "function" && !isValidLine(line)) {
1094
- return;
1095
- }
1096
-
1097
- lineNumber += 1;
1098
- // Choose this line with probability 1 / lineNumber
1099
- if (Math.random() < 1 / lineNumber) {
1100
- resultLine = line;
1101
- }
1102
- });
1103
-
1104
- rl.on("close", () => {
1105
- if (resultLine !== null) {
1106
- resolve(resultLine);
1107
- } else {
1108
- reject(new Error("File is empty"));
1109
- }
1110
- });
1111
-
1112
- rl.on("error", (err) => {
1113
- reject(err);
1114
- });
1115
- });
1116
- }
1117
-
1118
- export async function getImageSize(url) {
1119
- if (!url || typeof url !== "string") {
1120
- return;
1121
- }
1122
- let response = null;
1123
- try {
1124
- response = await axios.head(url);
1125
- } catch (e) {
1126
- /* empty */
1127
- }
1128
- if (!response) {
1129
- return;
1130
- }
1131
- const contentLength = response.headers?.["content-length"];
1132
- if (contentLength) {
1133
- const sizeInBytes = parseInt(contentLength, 10);
1134
- const sizeInMB = sizeInBytes / (1024 * 1024); // Convert to MB
1135
- return sizeInMB.toFixed(2); // Return size in MB with 2 decimal places
1136
- }
1137
- }
1138
-
1139
- export function getGreetMessage() {
1140
- return _.sample(["nha", "nhá", "nhé"]);
1141
- }
1142
-
1143
- export function logNow(...msg) {
1144
- const date = new Date();
1145
- const fmt = (n) => n.toString().padStart(2, "0");
1146
- const offset = 7 * 60;
1147
- const localDate = new Date(date.getTime() + offset * 60 * 1000);
1148
- const formattedDate = `${fmt(localDate.getUTCDate())}/${fmt(localDate.getUTCMonth() + 1)}/${localDate.getUTCFullYear()} ${fmt(localDate.getUTCHours())}:${fmt(localDate.getUTCMinutes())}:${fmt(localDate.getUTCSeconds())}`;
1149
- console.log(`[${formattedDate}]`, ...msg);
1150
- }
1151
-
1152
- export function formatFriendState(data) {
1153
- if (!data) {
1154
- return;
1155
- }
1156
-
1157
- function formatUndefined(value) {
1158
- if (value === "" || value === null || value === undefined || (typeof value === "number" && isNaN(value))) {
1159
- return null;
1160
- }
1161
- return value;
1162
- }
1163
-
1164
- const { player_name, gameid, persona_state, rich_presence = [] } = data;
1165
- const avatar_hash = data.avatar_hash ? (typeof data.avatar_hash === "string" ? data.avatar_hash : Buffer.from(data.avatar_hash).toString("hex")) : "fef49e7fa7e1997310d705b2a6158ff8dc1cdfeb";
1166
-
1167
- let onlineStatus = "offline";
1168
- let score = "";
1169
- const scoreDetails = rich_presence.find((r) => r.key === "game:score")?.value;
1170
- const mode = rich_presence.find((r) => r.key === "game:mode")?.value;
1171
- const map = rich_presence.find((r) => r.key === "game:map")?.value;
1172
- const numPlayers = formatUndefined(parseInt(rich_presence.find((r) => r.key === "members:numPlayers")?.value)); //include this friend, 2,3,4,5
1173
- const steam_player_group = formatUndefined(parseInt(rich_presence.find?.((r) => r.key === "steam_player_group")?.value));
1174
- const steam_player_group_size = formatUndefined(parseInt(rich_presence.find?.((r) => r.key === "steam_player_group_size")?.value));
1175
-
1176
- if (gameid !== null && gameid !== undefined && gameid !== "") {
1177
- if (gameid === 0 || gameid === "0") {
1178
- if ([1, 2, 3, 4].includes(persona_state)) {
1179
- onlineStatus = "online";
1180
- } else if (persona_state === 0) {
1181
- onlineStatus = "offline";
1182
- } else {
1183
- // console.log(data)
1184
- onlineStatus = "online";
1185
- }
1186
- } else {
1187
- onlineStatus = "ingame";
1188
- }
1189
-
1190
- if (rich_presence.some((r) => r.key === "game:state" && r.value === "lobby")) {
1191
- score = data.rich_presence_string || "In Lobby";
1192
- } else {
1193
- score = rich_presence.find?.((r) => r.key === "status")?.value || data.rich_presence_string || "";
1194
- }
1195
- if (score === "not found") {
1196
- score = "";
1197
- }
1198
- if (score.startsWith("Premier") && !score.startsWith("Premier Competitive") && data.rich_presence_string?.startsWith("Premier Competitive")) {
1199
- score = data.rich_presence_string;
1200
- }
1201
- } else if (persona_state === null && rich_presence.length === 0) {
1202
- onlineStatus = "offline";
1203
- }
1204
-
1205
- return {
1206
- onlineStatus,
1207
- score: formatUndefined(score),
1208
- scoreDetails: formatUndefined(scoreDetails),
1209
- mode: formatUndefined(mode),
1210
- map: formatUndefined(map),
1211
- player_name,
1212
- gameid: formatUndefined(parseInt(gameid)),
1213
- numPlayers,
1214
- steam_player_group,
1215
- steam_player_group_size,
1216
- avatar_hash,
1217
- rich_presence,
1218
- };
1219
- }
1220
-
1221
- export function getGameDetailScore(scoreString) {
1222
- if (typeof scoreString !== "string") {
1223
- return null;
1224
- }
1225
- const regex = /\[\s*(\d+)\s*:\s*(\d+)\s*\]/;
1226
- const matches = scoreString.match(regex);
1227
- if (matches) {
1228
- // The first capturing group (matches[1]) is the first score, the second (matches[2]) is the second score
1229
- const score1 = matches[1];
1230
- const score2 = matches[2];
1231
- return [score1, score2].map(Number);
1232
- }
1233
- // console.log("No match found", scoreString);
1234
- }
1
+ import moment from "moment";
2
+ import SteamTotp from "steam-totp";
3
+ import { EAuthTokenPlatformType } from "./const.js";
4
+ import fs from "fs";
5
+ import axios from "axios";
6
+ import readline from "readline";
7
+ import https from "https";
8
+ import { promisify } from "util";
9
+ import { pipeline } from "stream";
10
+ import _ from "lodash";
11
+
12
+ const isBrowser = typeof window !== "undefined";
13
+ const g_rgCurrencyData = {
14
+ USD: {
15
+ strCode: "USD",
16
+ eCurrencyCode: 1,
17
+ strSymbol: "$",
18
+ bSymbolIsPrefix: true,
19
+ bWholeUnitsOnly: false,
20
+ strDecimalSymbol: ".",
21
+ strThousandsSeparator: ",",
22
+ strSymbolAndNumberSeparator: "",
23
+ },
24
+ GBP: {
25
+ strCode: "GBP",
26
+ eCurrencyCode: 2,
27
+ strSymbol: "\u00a3",
28
+ bSymbolIsPrefix: true,
29
+ bWholeUnitsOnly: false,
30
+ strDecimalSymbol: ".",
31
+ strThousandsSeparator: ",",
32
+ strSymbolAndNumberSeparator: "",
33
+ },
34
+ EUR: {
35
+ strCode: "EUR",
36
+ eCurrencyCode: 3,
37
+ strSymbol: "\u20ac",
38
+ bSymbolIsPrefix: false,
39
+ bWholeUnitsOnly: false,
40
+ strDecimalSymbol: ",",
41
+ strThousandsSeparator: " ",
42
+ strSymbolAndNumberSeparator: "",
43
+ },
44
+ CHF: {
45
+ strCode: "CHF",
46
+ eCurrencyCode: 4,
47
+ strSymbol: "CHF",
48
+ bSymbolIsPrefix: true,
49
+ bWholeUnitsOnly: false,
50
+ strDecimalSymbol: ".",
51
+ strThousandsSeparator: " ",
52
+ strSymbolAndNumberSeparator: " ",
53
+ },
54
+ RUB: {
55
+ strCode: "RUB",
56
+ eCurrencyCode: 5,
57
+ strSymbol: "p\u0443\u0431.",
58
+ bSymbolIsPrefix: false,
59
+ bWholeUnitsOnly: true,
60
+ strDecimalSymbol: ",",
61
+ strThousandsSeparator: "",
62
+ strSymbolAndNumberSeparator: " ",
63
+ },
64
+ BRL: {
65
+ strCode: "BRL",
66
+ eCurrencyCode: 7,
67
+ strSymbol: "R$",
68
+ bSymbolIsPrefix: true,
69
+ bWholeUnitsOnly: false,
70
+ strDecimalSymbol: ",",
71
+ strThousandsSeparator: ".",
72
+ strSymbolAndNumberSeparator: " ",
73
+ },
74
+ JPY: {
75
+ strCode: "JPY",
76
+ eCurrencyCode: 8,
77
+ strSymbol: "\u00a5",
78
+ bSymbolIsPrefix: true,
79
+ bWholeUnitsOnly: true,
80
+ strDecimalSymbol: ".",
81
+ strThousandsSeparator: ",",
82
+ strSymbolAndNumberSeparator: " ",
83
+ },
84
+ NOK: {
85
+ strCode: "NOK",
86
+ eCurrencyCode: 9,
87
+ strSymbol: "kr",
88
+ bSymbolIsPrefix: false,
89
+ bWholeUnitsOnly: false,
90
+ strDecimalSymbol: ",",
91
+ strThousandsSeparator: ".",
92
+ strSymbolAndNumberSeparator: " ",
93
+ },
94
+ IDR: {
95
+ strCode: "IDR",
96
+ eCurrencyCode: 10,
97
+ strSymbol: "Rp",
98
+ bSymbolIsPrefix: true,
99
+ bWholeUnitsOnly: true,
100
+ strDecimalSymbol: ".",
101
+ strThousandsSeparator: " ",
102
+ strSymbolAndNumberSeparator: " ",
103
+ },
104
+ MYR: {
105
+ strCode: "MYR",
106
+ eCurrencyCode: 11,
107
+ strSymbol: "RM",
108
+ bSymbolIsPrefix: true,
109
+ bWholeUnitsOnly: false,
110
+ strDecimalSymbol: ".",
111
+ strThousandsSeparator: ",",
112
+ strSymbolAndNumberSeparator: "",
113
+ },
114
+ PHP: {
115
+ strCode: "PHP",
116
+ eCurrencyCode: 12,
117
+ strSymbol: "P",
118
+ bSymbolIsPrefix: true,
119
+ bWholeUnitsOnly: false,
120
+ strDecimalSymbol: ".",
121
+ strThousandsSeparator: ",",
122
+ strSymbolAndNumberSeparator: "",
123
+ },
124
+ SGD: {
125
+ strCode: "SGD",
126
+ eCurrencyCode: 13,
127
+ strSymbol: "S$",
128
+ bSymbolIsPrefix: true,
129
+ bWholeUnitsOnly: false,
130
+ strDecimalSymbol: ".",
131
+ strThousandsSeparator: ",",
132
+ strSymbolAndNumberSeparator: "",
133
+ },
134
+ THB: {
135
+ strCode: "THB",
136
+ eCurrencyCode: 14,
137
+ strSymbol: "\u0e3f",
138
+ bSymbolIsPrefix: true,
139
+ bWholeUnitsOnly: false,
140
+ strDecimalSymbol: ".",
141
+ strThousandsSeparator: ",",
142
+ strSymbolAndNumberSeparator: "",
143
+ },
144
+ VND: {
145
+ strCode: "VND",
146
+ eCurrencyCode: 15,
147
+ strSymbol: "\u20ab",
148
+ bSymbolIsPrefix: false,
149
+ bWholeUnitsOnly: true,
150
+ strDecimalSymbol: ",",
151
+ strThousandsSeparator: ".",
152
+ strSymbolAndNumberSeparator: "",
153
+ },
154
+ KRW: {
155
+ strCode: "KRW",
156
+ eCurrencyCode: 16,
157
+ strSymbol: "\u20a9",
158
+ bSymbolIsPrefix: true,
159
+ bWholeUnitsOnly: true,
160
+ strDecimalSymbol: ".",
161
+ strThousandsSeparator: ",",
162
+ strSymbolAndNumberSeparator: " ",
163
+ },
164
+ TRY: {
165
+ strCode: "TRY",
166
+ eCurrencyCode: 17,
167
+ strSymbol: "TL",
168
+ bSymbolIsPrefix: false,
169
+ bWholeUnitsOnly: false,
170
+ strDecimalSymbol: ",",
171
+ strThousandsSeparator: ".",
172
+ strSymbolAndNumberSeparator: " ",
173
+ },
174
+ UAH: {
175
+ strCode: "UAH",
176
+ eCurrencyCode: 18,
177
+ strSymbol: "\u20b4",
178
+ bSymbolIsPrefix: false,
179
+ bWholeUnitsOnly: true,
180
+ strDecimalSymbol: ",",
181
+ strThousandsSeparator: " ",
182
+ strSymbolAndNumberSeparator: "",
183
+ },
184
+ MXN: {
185
+ strCode: "MXN",
186
+ eCurrencyCode: 19,
187
+ strSymbol: "Mex$",
188
+ bSymbolIsPrefix: true,
189
+ bWholeUnitsOnly: false,
190
+ strDecimalSymbol: ".",
191
+ strThousandsSeparator: ",",
192
+ strSymbolAndNumberSeparator: " ",
193
+ },
194
+ CAD: {
195
+ strCode: "CAD",
196
+ eCurrencyCode: 20,
197
+ strSymbol: "CDN$",
198
+ bSymbolIsPrefix: true,
199
+ bWholeUnitsOnly: false,
200
+ strDecimalSymbol: ".",
201
+ strThousandsSeparator: ",",
202
+ strSymbolAndNumberSeparator: " ",
203
+ },
204
+ AUD: {
205
+ strCode: "AUD",
206
+ eCurrencyCode: 21,
207
+ strSymbol: "A$",
208
+ bSymbolIsPrefix: true,
209
+ bWholeUnitsOnly: false,
210
+ strDecimalSymbol: ".",
211
+ strThousandsSeparator: ",",
212
+ strSymbolAndNumberSeparator: " ",
213
+ },
214
+ NZD: {
215
+ strCode: "NZD",
216
+ eCurrencyCode: 22,
217
+ strSymbol: "NZ$",
218
+ bSymbolIsPrefix: true,
219
+ bWholeUnitsOnly: false,
220
+ strDecimalSymbol: ".",
221
+ strThousandsSeparator: ",",
222
+ strSymbolAndNumberSeparator: " ",
223
+ },
224
+ PLN: {
225
+ strCode: "PLN",
226
+ eCurrencyCode: 6,
227
+ strSymbol: "z\u0142",
228
+ bSymbolIsPrefix: false,
229
+ bWholeUnitsOnly: false,
230
+ strDecimalSymbol: ",",
231
+ strThousandsSeparator: " ",
232
+ strSymbolAndNumberSeparator: "",
233
+ },
234
+ CNY: {
235
+ strCode: "CNY",
236
+ eCurrencyCode: 23,
237
+ strSymbol: "\u00a5",
238
+ bSymbolIsPrefix: true,
239
+ bWholeUnitsOnly: false,
240
+ strDecimalSymbol: ".",
241
+ strThousandsSeparator: ",",
242
+ strSymbolAndNumberSeparator: " ",
243
+ },
244
+ INR: {
245
+ strCode: "INR",
246
+ eCurrencyCode: 24,
247
+ strSymbol: "\u20b9",
248
+ bSymbolIsPrefix: true,
249
+ bWholeUnitsOnly: true,
250
+ strDecimalSymbol: ".",
251
+ strThousandsSeparator: ",",
252
+ strSymbolAndNumberSeparator: " ",
253
+ },
254
+ CLP: {
255
+ strCode: "CLP",
256
+ eCurrencyCode: 25,
257
+ strSymbol: "CLP$",
258
+ bSymbolIsPrefix: true,
259
+ bWholeUnitsOnly: true,
260
+ strDecimalSymbol: ",",
261
+ strThousandsSeparator: ".",
262
+ strSymbolAndNumberSeparator: " ",
263
+ },
264
+ PEN: {
265
+ strCode: "PEN",
266
+ eCurrencyCode: 26,
267
+ strSymbol: "S/.",
268
+ bSymbolIsPrefix: true,
269
+ bWholeUnitsOnly: false,
270
+ strDecimalSymbol: ".",
271
+ strThousandsSeparator: ",",
272
+ strSymbolAndNumberSeparator: "",
273
+ },
274
+ COP: {
275
+ strCode: "COP",
276
+ eCurrencyCode: 27,
277
+ strSymbol: "COL$",
278
+ bSymbolIsPrefix: true,
279
+ bWholeUnitsOnly: true,
280
+ strDecimalSymbol: ",",
281
+ strThousandsSeparator: ".",
282
+ strSymbolAndNumberSeparator: " ",
283
+ },
284
+ ZAR: {
285
+ strCode: "ZAR",
286
+ eCurrencyCode: 28,
287
+ strSymbol: "R",
288
+ bSymbolIsPrefix: true,
289
+ bWholeUnitsOnly: false,
290
+ strDecimalSymbol: ".",
291
+ strThousandsSeparator: " ",
292
+ strSymbolAndNumberSeparator: " ",
293
+ },
294
+ HKD: {
295
+ strCode: "HKD",
296
+ eCurrencyCode: 29,
297
+ strSymbol: "HK$",
298
+ bSymbolIsPrefix: true,
299
+ bWholeUnitsOnly: false,
300
+ strDecimalSymbol: ".",
301
+ strThousandsSeparator: ",",
302
+ strSymbolAndNumberSeparator: " ",
303
+ },
304
+ TWD: {
305
+ strCode: "TWD",
306
+ eCurrencyCode: 30,
307
+ strSymbol: "NT$",
308
+ bSymbolIsPrefix: true,
309
+ bWholeUnitsOnly: true,
310
+ strDecimalSymbol: ".",
311
+ strThousandsSeparator: ",",
312
+ strSymbolAndNumberSeparator: " ",
313
+ },
314
+ SAR: {
315
+ strCode: "SAR",
316
+ eCurrencyCode: 31,
317
+ strSymbol: "SR",
318
+ bSymbolIsPrefix: false,
319
+ bWholeUnitsOnly: false,
320
+ strDecimalSymbol: ".",
321
+ strThousandsSeparator: ",",
322
+ strSymbolAndNumberSeparator: " ",
323
+ },
324
+ AED: {
325
+ strCode: "AED",
326
+ eCurrencyCode: 32,
327
+ strSymbol: "AED",
328
+ bSymbolIsPrefix: false,
329
+ bWholeUnitsOnly: false,
330
+ strDecimalSymbol: ".",
331
+ strThousandsSeparator: ",",
332
+ strSymbolAndNumberSeparator: " ",
333
+ },
334
+ SEK: {
335
+ strCode: "SEK",
336
+ eCurrencyCode: 33,
337
+ strSymbol: "kr",
338
+ bSymbolIsPrefix: false,
339
+ bWholeUnitsOnly: false,
340
+ strDecimalSymbol: ".",
341
+ strThousandsSeparator: ",",
342
+ strSymbolAndNumberSeparator: " ",
343
+ },
344
+ ARS: {
345
+ strCode: "ARS",
346
+ eCurrencyCode: 34,
347
+ strSymbol: "ARS$",
348
+ bSymbolIsPrefix: true,
349
+ bWholeUnitsOnly: false,
350
+ strDecimalSymbol: ",",
351
+ strThousandsSeparator: ".",
352
+ strSymbolAndNumberSeparator: " ",
353
+ },
354
+ ILS: {
355
+ strCode: "ILS",
356
+ eCurrencyCode: 35,
357
+ strSymbol: "\u20aa",
358
+ bSymbolIsPrefix: true,
359
+ bWholeUnitsOnly: false,
360
+ strDecimalSymbol: ".",
361
+ strThousandsSeparator: ",",
362
+ strSymbolAndNumberSeparator: "",
363
+ },
364
+ BYN: {
365
+ strCode: "BYN",
366
+ eCurrencyCode: 36,
367
+ strSymbol: "Br",
368
+ bSymbolIsPrefix: true,
369
+ bWholeUnitsOnly: false,
370
+ strDecimalSymbol: ".",
371
+ strThousandsSeparator: ",",
372
+ strSymbolAndNumberSeparator: "",
373
+ },
374
+ KZT: {
375
+ strCode: "KZT",
376
+ eCurrencyCode: 37,
377
+ strSymbol: "\u20b8",
378
+ bSymbolIsPrefix: false,
379
+ bWholeUnitsOnly: true,
380
+ strDecimalSymbol: ",",
381
+ strThousandsSeparator: " ",
382
+ strSymbolAndNumberSeparator: "",
383
+ },
384
+ KWD: {
385
+ strCode: "KWD",
386
+ eCurrencyCode: 38,
387
+ strSymbol: "KD",
388
+ bSymbolIsPrefix: false,
389
+ bWholeUnitsOnly: false,
390
+ strDecimalSymbol: ".",
391
+ strThousandsSeparator: ",",
392
+ strSymbolAndNumberSeparator: " ",
393
+ },
394
+ QAR: {
395
+ strCode: "QAR",
396
+ eCurrencyCode: 39,
397
+ strSymbol: "QR",
398
+ bSymbolIsPrefix: false,
399
+ bWholeUnitsOnly: false,
400
+ strDecimalSymbol: ".",
401
+ strThousandsSeparator: ",",
402
+ strSymbolAndNumberSeparator: " ",
403
+ },
404
+ CRC: {
405
+ strCode: "CRC",
406
+ eCurrencyCode: 40,
407
+ strSymbol: "\u20a1",
408
+ bSymbolIsPrefix: true,
409
+ bWholeUnitsOnly: true,
410
+ strDecimalSymbol: ",",
411
+ strThousandsSeparator: ".",
412
+ strSymbolAndNumberSeparator: "",
413
+ },
414
+ UYU: {
415
+ strCode: "UYU",
416
+ eCurrencyCode: 41,
417
+ strSymbol: "$U",
418
+ bSymbolIsPrefix: true,
419
+ bWholeUnitsOnly: true,
420
+ strDecimalSymbol: ",",
421
+ strThousandsSeparator: ".",
422
+ strSymbolAndNumberSeparator: "",
423
+ },
424
+ BGN: {
425
+ strCode: "BGN",
426
+ eCurrencyCode: 42,
427
+ strSymbol: "\u043b\u0432",
428
+ bSymbolIsPrefix: false,
429
+ bWholeUnitsOnly: false,
430
+ strDecimalSymbol: ".",
431
+ strThousandsSeparator: ",",
432
+ strSymbolAndNumberSeparator: " ",
433
+ },
434
+ HRK: {
435
+ strCode: "HRK",
436
+ eCurrencyCode: 43,
437
+ strSymbol: "kn",
438
+ bSymbolIsPrefix: false,
439
+ bWholeUnitsOnly: false,
440
+ strDecimalSymbol: ".",
441
+ strThousandsSeparator: ",",
442
+ strSymbolAndNumberSeparator: " ",
443
+ },
444
+ CZK: {
445
+ strCode: "CZK",
446
+ eCurrencyCode: 44,
447
+ strSymbol: "K\u010d",
448
+ bSymbolIsPrefix: false,
449
+ bWholeUnitsOnly: false,
450
+ strDecimalSymbol: ".",
451
+ strThousandsSeparator: ",",
452
+ strSymbolAndNumberSeparator: " ",
453
+ },
454
+ DKK: {
455
+ strCode: "DKK",
456
+ eCurrencyCode: 45,
457
+ strSymbol: "kr.",
458
+ bSymbolIsPrefix: false,
459
+ bWholeUnitsOnly: false,
460
+ strDecimalSymbol: ".",
461
+ strThousandsSeparator: ",",
462
+ strSymbolAndNumberSeparator: " ",
463
+ },
464
+ HUF: {
465
+ strCode: "HUF",
466
+ eCurrencyCode: 46,
467
+ strSymbol: "Ft",
468
+ bSymbolIsPrefix: false,
469
+ bWholeUnitsOnly: false,
470
+ strDecimalSymbol: ".",
471
+ strThousandsSeparator: ",",
472
+ strSymbolAndNumberSeparator: " ",
473
+ },
474
+ RON: {
475
+ strCode: "RON",
476
+ eCurrencyCode: 47,
477
+ strSymbol: "lei",
478
+ bSymbolIsPrefix: false,
479
+ bWholeUnitsOnly: false,
480
+ strDecimalSymbol: ".",
481
+ strThousandsSeparator: ",",
482
+ strSymbolAndNumberSeparator: " ",
483
+ },
484
+ RMB: {
485
+ strCode: "RMB",
486
+ eCurrencyCode: 9000,
487
+ strSymbol: "\u5200\u5e01",
488
+ bSymbolIsPrefix: false,
489
+ bWholeUnitsOnly: true,
490
+ strDecimalSymbol: ".",
491
+ strThousandsSeparator: "",
492
+ strSymbolAndNumberSeparator: " ",
493
+ },
494
+ NXP: {
495
+ strCode: "NXP",
496
+ eCurrencyCode: 9001,
497
+ strSymbol: "\uc6d0",
498
+ bSymbolIsPrefix: false,
499
+ bWholeUnitsOnly: true,
500
+ strDecimalSymbol: ".",
501
+ strThousandsSeparator: ",",
502
+ strSymbolAndNumberSeparator: "",
503
+ },
504
+ };
505
+ const g_rgWalletInfo = {
506
+ wallet_currency: 15,
507
+ wallet_country: "VN",
508
+ wallet_state: "",
509
+ wallet_fee: "1",
510
+ wallet_fee_minimum: "1",
511
+ wallet_fee_percent: "0.05",
512
+ wallet_publisher_fee_percent_default: "0.10",
513
+ wallet_fee_base: "0",
514
+ wallet_balance: "6540490",
515
+ wallet_delayed_balance: "0",
516
+ wallet_max_balance: "4500000000",
517
+ wallet_trade_max_balance: "4049999616",
518
+ success: 1,
519
+ rwgrsn: -2,
520
+ };
521
+
522
+ export const sleep = (ms) => {
523
+ return new Promise((resolve) => {
524
+ setTimeout(resolve, ms);
525
+ });
526
+ };
527
+
528
+ export const sleepRandom = async (startMs, endMs) => {
529
+ return await sleep(Math.random() * (endMs - startMs) + startMs);
530
+ };
531
+
532
+ /**
533
+ * const audioTrack = stream.getAudioTracks()[0]
534
+ * const videoStream = UserMedia.createBlankVideoTrack()
535
+ * videoStream.addTrack(audioTrack)
536
+ * stream = videoStream
537
+ * **/
538
+ export const createBlankVideoTrack = (opts = {}) => {
539
+ const { width = 1920, height = 1080 } = opts;
540
+
541
+ const canvas = Object.assign(document.createElement("canvas"), {
542
+ width,
543
+ height,
544
+ });
545
+
546
+ canvas.getContext("2d").fillRect(0, 0, width, height);
547
+
548
+ return canvas.captureStream();
549
+ };
550
+
551
+ const minDate = new Date(0),
552
+ maxDate = new Date(parseInt("ffffffff", 16) * 1000);
553
+
554
+ export function objectIdFromDate(date) {
555
+ if (date < minDate || date > maxDate) {
556
+ return `Error: date must be between ${minDate.getFullYear()} and ${maxDate.getFullYear()}`;
557
+ }
558
+ var pad = "00000000";
559
+ var hexSeconds = Math.floor(date.getTime() / 1000).toString(16);
560
+ return `${pad.substring(0, pad.length - hexSeconds.length) + hexSeconds}0000000000000000`;
561
+ }
562
+
563
+ export function dateFromObjectId(objectId) {
564
+ return new Date(parseInt(objectId.substring(0, 8), 16) * 1000);
565
+ }
566
+
567
+ export function console_log(...args) {
568
+ const params = [];
569
+ params.push(new Date().toUTCString());
570
+ const errorStack = new Error().stack;
571
+ const fnName = errorStack
572
+ .split("\n")
573
+ .map((e) => e?.trim())
574
+ .filter((e) => e.startsWith("at") && !e.startsWith("at console_log") && !e.startsWith("at processTicksAndRejections"))[0]
575
+ .substr(3);
576
+ params.push(fnName);
577
+ console.log(
578
+ params
579
+ .filter(Boolean)
580
+ .map((p) => `[${p.trim()}]`)
581
+ .join(" "),
582
+ ...args,
583
+ );
584
+ }
585
+
586
+ export function removeSpaceKeys(object) {
587
+ //mutate object
588
+ if (!object || Array.isArray(object)) {
589
+ return object;
590
+ }
591
+
592
+ Object.entries(object).forEach(([key, value]) => {
593
+ const newKey = key.replaceAll(/[^a-zA-Z0-9]/gi, "_");
594
+ if (newKey !== key) {
595
+ delete object[key];
596
+ object[newKey] = value;
597
+ }
598
+ });
599
+ return object;
600
+ }
601
+
602
+ export function getCleanObject(object) {
603
+ //like removeSpaceKeys but not mutate object
604
+ if (!object || Array.isArray(object)) {
605
+ return object;
606
+ }
607
+
608
+ const newObject = {};
609
+ Object.entries(object).forEach(([key, value]) => {
610
+ const newKey = key.replaceAll(/[^a-zA-Z0-9]/gi, "_");
611
+ newObject[newKey] = value;
612
+ });
613
+ return newObject;
614
+ }
615
+
616
+ export function JSON_parse(data) {
617
+ try {
618
+ return JSON.parse(data);
619
+ } catch (e) {
620
+ return null;
621
+ }
622
+ }
623
+
624
+ export function JSON_stringify(data) {
625
+ try {
626
+ return JSON.stringify(data);
627
+ } catch (e) {
628
+ return null;
629
+ }
630
+ }
631
+
632
+ export async function throttle(fn, delay) {
633
+ let canFire = true;
634
+ let queue = [];
635
+
636
+ async function pop() {
637
+ if (queue.length < 1) return;
638
+
639
+ const [that, args] = queue.pop();
640
+ await fn.apply(that, args);
641
+ canFire = false;
642
+ setTimeout(async () => {
643
+ canFire = true;
644
+ await pop();
645
+ }, delay);
646
+ }
647
+
648
+ async function push() {
649
+ queue.push([this, arguments]);
650
+ if (canFire) {
651
+ await pop();
652
+ }
653
+ }
654
+
655
+ push.cancel = () => {
656
+ queue = [];
657
+ };
658
+
659
+ return push;
660
+ }
661
+
662
+ export const secretAsBuffer = (sharedSecret) => {
663
+ if (Buffer.isBuffer(sharedSecret)) {
664
+ return sharedSecret;
665
+ }
666
+
667
+ if (sharedSecret.match(/^[0-9a-f]{40}$/i)) {
668
+ // Looks like it's hex
669
+ return Buffer.from(sharedSecret, "hex");
670
+ }
671
+
672
+ // It must be base64
673
+ return Buffer.from(sharedSecret, "base64");
674
+ };
675
+
676
+ export function decodeLoginQrUrl(qrUrl) {
677
+ if (!qrUrl || typeof qrUrl !== "string") {
678
+ return null;
679
+ }
680
+ const match = qrUrl.match(/^https?:\/\/s\.team\/q\/(\d+)\/(\d+)(\?|$)/);
681
+ if (!match) {
682
+ console.log("Invalid QR code URL");
683
+ return null;
684
+ }
685
+
686
+ return { clientId: match[2], version: parseInt(match[1], 10) };
687
+ }
688
+
689
+ export function decodeJwt(jwt) {
690
+ try {
691
+ const parts = jwt.split(".");
692
+ if (parts.length !== 3) {
693
+ console.err("decodeJwt Error", new Error("Invalid JWT"));
694
+ return;
695
+ }
696
+
697
+ const standardBase64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
698
+ return JSON.parse(Buffer.from(standardBase64, "base64").toString("utf8"));
699
+ } catch (e) {
700
+ console.error("decodeJwt Error", e);
701
+ }
702
+ }
703
+
704
+ export async function renewRefreshToken({ refreshToken, accessToken }) {
705
+ const steamId = arguments[0]?.steamId;
706
+ try {
707
+ const { aud } = decodeJwt(accessToken);
708
+ let platformType = EAuthTokenPlatformType.SteamClient;
709
+ if (aud.includes("mobile")) {
710
+ platformType = EAuthTokenPlatformType.MobileApp;
711
+ } else if (aud.includes("client")) {
712
+ platformType = EAuthTokenPlatformType.SteamClient;
713
+ } else if (aud.includes("web")) {
714
+ platformType = EAuthTokenPlatformType.WebBrowser;
715
+ }
716
+
717
+ const { LoginSession } = await import("steam-session");
718
+ const session = new LoginSession(platformType);
719
+ session.refreshToken = refreshToken;
720
+ await session.refreshAccessToken();
721
+ const cookie = (await session.getWebCookies())?.join?.(";");
722
+ return {
723
+ cookie,
724
+ accessToken: session.accessToken,
725
+ accessTokenDecoded: decodeJwt(session.accessToken),
726
+ };
727
+ } catch (e) {
728
+ console.error(`${steamId ? `[${steamId}] ` : ""}renewRefreshToken Error`, e);
729
+ }
730
+ }
731
+
732
+ export async function approveLogin({ steamId, url, sharedSecret, accessToken, shouldApprove }) {
733
+ try {
734
+ const { LoginApprover } = await import("steam-session");
735
+ const approver = new LoginApprover(accessToken, sharedSecret, {});
736
+ const sessionInfo = await approver.getAuthSessionInfo(url);
737
+ sessionInfo.steamId = steamId;
738
+
739
+ if (typeof shouldApprove === "function" && !shouldApprove(sessionInfo)) {
740
+ return;
741
+ }
742
+
743
+ await approver.approveAuthSession({
744
+ qrChallengeUrl: url,
745
+ approve: true,
746
+ });
747
+
748
+ return {
749
+ steamId,
750
+ sessionInfo,
751
+ };
752
+ } catch (error) {
753
+ console.error(`[${steamId}] approveLogin Error`, error);
754
+ return {
755
+ steamId,
756
+ error,
757
+ };
758
+ }
759
+ }
760
+
761
+ export function getBonusXpTimeRefresh() {
762
+ let resetDay = moment.utc().startOf("isoWeek").add(2, "days").add(1, "hours");
763
+ while (moment().isAfter(resetDay)) {
764
+ resetDay = resetDay.add(7, "days");
765
+ }
766
+ if (moment().isBefore(resetDay)) {
767
+ resetDay = resetDay.subtract(7, "days");
768
+ }
769
+ return resetDay;
770
+ }
771
+
772
+ export function estimateNextXp(currentXp, xpEarned) {
773
+ //estimate next xp
774
+ let bonusTime = 1;
775
+ if (xpEarned < 4500) {
776
+ bonusTime = 4;
777
+ } else if (xpEarned < 7500) {
778
+ bonusTime = 2;
779
+ } else if (xpEarned < 11200) {
780
+ bonusTime = 1;
781
+ } else {
782
+ bonusTime = 0.175;
783
+ }
784
+
785
+ const nextXp = 30 * 13 * bonusTime;
786
+ return nextXp + currentXp;
787
+ }
788
+
789
+ export function formatMarketCurrency(valueInCents, currencyCode = getMarketCurrencyCode(g_rgWalletInfo.wallet_currency), countryCode) {
790
+ if (!valueInCents && valueInCents !== 0) {
791
+ return "";
792
+ }
793
+
794
+ let currencyFormat = (valueInCents / 100).toFixed(2);
795
+
796
+ if (g_rgCurrencyData[currencyCode]) {
797
+ const currencyData = g_rgCurrencyData[currencyCode];
798
+ if (isCurrencyWholeUnits(currencyCode)) {
799
+ currencyFormat = currencyFormat.replace(".00", "");
800
+ }
801
+
802
+ if (currencyData.strDecimalSymbol !== ".") {
803
+ currencyFormat = currencyFormat.replace(".", currencyData.strDecimalSymbol);
804
+ }
805
+
806
+ const currencySymbol = getMarketCurrencySymbol(currencyCode);
807
+ const currencyReturn = isCurrencySymbolBeforeValue(currencyCode) ? currencySymbol + currencyData.strSymbolAndNumberSeparator + currencyFormat : currencyFormat + currencyData.strSymbolAndNumberSeparator + currencySymbol;
808
+
809
+ if (currencyCode === "USD" && typeof countryCode != "undefined" && countryCode != "US") {
810
+ return `${currencyReturn} USD`;
811
+ } else if (currencyCode === "EUR") {
812
+ return currencyReturn.replace(",00", ",--");
813
+ } else {
814
+ return currencyReturn;
815
+ }
816
+ } else {
817
+ return `${currencyFormat} ${currencyCode}`;
818
+ }
819
+ }
820
+
821
+ export function getMarketPriceValueAsInt(strAmount) {
822
+ let nAmount;
823
+ if (!strAmount) {
824
+ return 0;
825
+ }
826
+
827
+ // Users may enter either comma or period for the decimal mark and digit group separators.
828
+ strAmount = strAmount.replace(/,/g, ".");
829
+
830
+ // strip the currency symbol, set .-- to .00
831
+ strAmount = strAmount.replace(getMarketCurrencySymbol(getMarketCurrencyCode(g_rgWalletInfo.wallet_currency)), "").replace(".--", ".00");
832
+
833
+ // strip spaces
834
+ strAmount = strAmount.replace(/ /g, "");
835
+
836
+ // Remove all but the last period so that entries like "1,147.6" work
837
+ if (strAmount.includes(".")) {
838
+ var splitAmount = strAmount.split(".");
839
+ var strLastSegment = splitAmount[splitAmount.length - 1];
840
+
841
+ if (!isNaN(strLastSegment) && strLastSegment.length == 3 && splitAmount[splitAmount.length - 2] != "0") {
842
+ // Looks like the user only entered thousands separators. Remove all commas and periods.
843
+ // Ensures an entry like "1,147" is not treated as "1.147"
844
+ //
845
+ // Users may be surprised to find that "1.147" is treated as "1,147". "1.147" is either an error or the user
846
+ // really did mean one thousand one hundred and forty seven since no currencies can be split into more than
847
+ // hundredths. If it was an error, the user should notice in the next step of the dialog and can go back and
848
+ // correct it. If they happen to not notice, it is better that we list the item at a higher price than
849
+ // intended instead of lower than intended (which we would have done if we accepted the 1.147 value as is).
850
+ strAmount = splitAmount.join("");
851
+ } else {
852
+ strAmount = `${splitAmount.slice(0, -1).join("")}.${strLastSegment}`;
853
+ }
854
+ }
855
+
856
+ let flAmount = parseFloat(strAmount) * 100;
857
+ nAmount = Math.floor(isNaN(flAmount) ? 0 : flAmount + 0.000001); // round down
858
+
859
+ nAmount = Math.max(nAmount, 0);
860
+ return nAmount;
861
+ }
862
+
863
+ export function isCurrencyWholeUnits(currencyCode) {
864
+ return g_rgCurrencyData[currencyCode] && g_rgCurrencyData[currencyCode].bWholeUnitsOnly && currencyCode !== "RUB";
865
+ }
866
+
867
+ export function isCurrencySymbolBeforeValue(currencyCode) {
868
+ return g_rgCurrencyData[currencyCode] && g_rgCurrencyData[currencyCode].bSymbolIsPrefix;
869
+ }
870
+
871
+ // Return the symbol to use for a currency
872
+ export function getMarketCurrencySymbol(currencyCode) {
873
+ return g_rgCurrencyData[currencyCode]?.strSymbol ?? currencyCode;
874
+ }
875
+
876
+ export function getMarketCurrencyCode(currencyId) {
877
+ currencyId = parseInt(currencyId);
878
+ for (const code in g_rgCurrencyData) {
879
+ if (g_rgCurrencyData[code].eCurrencyCode === currencyId) {
880
+ return code;
881
+ }
882
+ }
883
+ return "Unknown";
884
+ }
885
+
886
+ export async function loginWithCredentials({ username, password, timeoutMs = 120000, sharedSecret, getMailSteamGuardCodes }) {
887
+ if (!username) {
888
+ return {
889
+ error: "No username",
890
+ };
891
+ }
892
+
893
+ if (!password) {
894
+ return {
895
+ error: "No password",
896
+ };
897
+ }
898
+
899
+ const { LoginSession } = await import("steam-session");
900
+ let authenticated = false;
901
+ return new Promise((resolve) => {
902
+ const timeout = setTimeout(function () {
903
+ resolve({
904
+ error: "Timed out",
905
+ });
906
+ }, timeoutMs);
907
+
908
+ const session = new LoginSession(EAuthTokenPlatformType.MobileApp);
909
+ session.on("authenticated", async () => {
910
+ authenticated = true;
911
+ const cookie = (await session.getWebCookies())?.join?.(";");
912
+ return onResolve({
913
+ cookie,
914
+ accessToken: session.accessToken,
915
+ refreshToken: session.refreshToken,
916
+ accessTokenDecoded: decodeJwt(session.accessToken),
917
+ });
918
+ });
919
+
920
+ session
921
+ .startWithCredentials({
922
+ accountName: username,
923
+ password: password,
924
+ steamGuardMachineToken: "",
925
+ })
926
+ .then(async function (startResult) {
927
+ if (!startResult.actionRequired) {
928
+ return;
929
+ }
930
+
931
+ if (sharedSecret) {
932
+ let error = null;
933
+ const maxRetry = 3;
934
+ for (let i = 0; i < maxRetry; i++) {
935
+ try {
936
+ await session.submitSteamGuardCode(SteamTotp.generateAuthCode(sharedSecret));
937
+ error = null;
938
+ } catch (e) {
939
+ error = e;
940
+ }
941
+ await sleep(1000);
942
+ }
943
+ if (error) {
944
+ console.error(error);
945
+ onResolve({ error });
946
+ }
947
+ } else {
948
+ if (startResult.validActions.every((validAction) => validAction.type !== 2)) {
949
+ console.error(startResult.validActions);
950
+ return onResolve({
951
+ error: "validActions",
952
+ });
953
+ }
954
+
955
+ if (typeof getMailSteamGuardCodes === "function") {
956
+ const codes = await getMailSteamGuardCodes();
957
+ if (!Array.isArray(codes) || !codes.length) {
958
+ return onResolve({
959
+ error: "Can't find steam guard code",
960
+ });
961
+ }
962
+
963
+ let error = null;
964
+ for (const code of codes) {
965
+ if (!authenticated) {
966
+ try {
967
+ await session.submitSteamGuardCode(code);
968
+ error = null;
969
+ } catch (e) {
970
+ error = e;
971
+ }
972
+ await sleep(1000);
973
+ }
974
+ }
975
+ if (!authenticated && error) {
976
+ onResolve(error);
977
+ }
978
+ } else {
979
+ return onResolve({
980
+ error: "MailCodeError",
981
+ });
982
+ }
983
+ }
984
+ })
985
+ .catch(function (e) {
986
+ return onResolve(e);
987
+ });
988
+
989
+ function onResolve(data) {
990
+ clearTimeout(timeout);
991
+ return resolve(data);
992
+ }
993
+ });
994
+ }
995
+
996
+ export function calculateAccountXP(currentXp, xpEarnedThisWeek, xpEarned, nextXp) {
997
+ return (
998
+ (() => {
999
+ if (typeof nextXp !== "number" || !Number.isFinite(nextXp)) {
1000
+ return;
1001
+ }
1002
+
1003
+ currentXp = currentXp || 0;
1004
+ if (currentXp === nextXp) {
1005
+ return;
1006
+ }
1007
+
1008
+ const update = { currentXp: nextXp };
1009
+ if (nextXp < currentXp) {
1010
+ update.xpExceed = Date.now();
1011
+ }
1012
+ const resetDay = getBonusXpTimeRefresh().format("YYYY-MM-DD");
1013
+ const isWeekReset = xpEarnedThisWeek !== resetDay;
1014
+ let xpEarnedThisRank = nextXp - currentXp;
1015
+ if (xpEarnedThisRank < 0) {
1016
+ xpEarnedThisRank += 5000;
1017
+ }
1018
+ if (isWeekReset) {
1019
+ update.xpEarnedThisWeek = resetDay;
1020
+ update.xpEarned = xpEarnedThisRank;
1021
+ } else {
1022
+ update.xpEarned = (xpEarned || 0) + xpEarnedThisRank;
1023
+ if (xpEarnedThisRank === 0) {
1024
+ return;
1025
+ }
1026
+ }
1027
+
1028
+ return update;
1029
+ })() || {}
1030
+ );
1031
+ }
1032
+
1033
+ export async function downloadImage(url, filePath) {
1034
+ let response = null;
1035
+ try {
1036
+ response = await axios.get(url, {
1037
+ responseType: "arraybuffer",
1038
+ });
1039
+ } catch (e) {
1040
+ /* empty */
1041
+ }
1042
+
1043
+ if (!response || !response.data) {
1044
+ return;
1045
+ }
1046
+
1047
+ return new Promise((resolve) => {
1048
+ fs.writeFile(filePath, response.data, (err) => {
1049
+ if (err) {
1050
+ resolve();
1051
+ }
1052
+ resolve(filePath);
1053
+ });
1054
+ });
1055
+ }
1056
+
1057
+ export async function downloadLargeImage(url, filePath) {
1058
+ try {
1059
+ const response = await new Promise((resolve, reject) => {
1060
+ https
1061
+ .get(url, (res) => {
1062
+ if (res.statusCode === 200) {
1063
+ resolve(res);
1064
+ } else {
1065
+ reject(new Error(`Failed to get image, status code: ${res.statusCode}`));
1066
+ }
1067
+ })
1068
+ .on("error", reject);
1069
+ });
1070
+
1071
+ const streamPipeline = promisify(pipeline);
1072
+ await streamPipeline(response, fs.createWriteStream(filePath));
1073
+ console.log("Download large image completed.");
1074
+ return true;
1075
+ } catch (error) {
1076
+ console.error(`Error downloading large image: ${error.message}`);
1077
+ return false;
1078
+ }
1079
+ }
1080
+
1081
+ //from large text file
1082
+ export function readRandomLine(filePath, isValidLine) {
1083
+ return new Promise((resolve, reject) => {
1084
+ const rl = readline.createInterface({
1085
+ input: fs.createReadStream(filePath),
1086
+ crlfDelay: Infinity,
1087
+ });
1088
+
1089
+ let resultLine = null;
1090
+ let lineNumber = 0;
1091
+
1092
+ rl.on("line", (line) => {
1093
+ if (typeof isValidLine === "function" && !isValidLine(line)) {
1094
+ return;
1095
+ }
1096
+
1097
+ lineNumber += 1;
1098
+ // Choose this line with probability 1 / lineNumber
1099
+ if (Math.random() < 1 / lineNumber) {
1100
+ resultLine = line;
1101
+ }
1102
+ });
1103
+
1104
+ rl.on("close", () => {
1105
+ if (resultLine !== null) {
1106
+ resolve(resultLine);
1107
+ } else {
1108
+ reject(new Error("File is empty"));
1109
+ }
1110
+ });
1111
+
1112
+ rl.on("error", (err) => {
1113
+ reject(err);
1114
+ });
1115
+ });
1116
+ }
1117
+
1118
+ export async function getImageSize(url) {
1119
+ if (!url || typeof url !== "string") {
1120
+ return;
1121
+ }
1122
+ let response = null;
1123
+ try {
1124
+ response = await axios.head(url);
1125
+ } catch (e) {
1126
+ /* empty */
1127
+ }
1128
+ if (!response) {
1129
+ return;
1130
+ }
1131
+ const contentLength = response.headers?.["content-length"];
1132
+ if (contentLength) {
1133
+ const sizeInBytes = parseInt(contentLength, 10);
1134
+ const sizeInMB = sizeInBytes / (1024 * 1024); // Convert to MB
1135
+ return sizeInMB.toFixed(2); // Return size in MB with 2 decimal places
1136
+ }
1137
+ }
1138
+
1139
+ export function getGreetMessage() {
1140
+ return _.sample(["nha", "nhá", "nhé"]);
1141
+ }
1142
+
1143
+ export function logNow(...msg) {
1144
+ const date = new Date();
1145
+ const fmt = (n) => n.toString().padStart(2, "0");
1146
+ const offset = 7 * 60;
1147
+ const localDate = new Date(date.getTime() + offset * 60 * 1000);
1148
+ const formattedDate = `${fmt(localDate.getUTCDate())}/${fmt(localDate.getUTCMonth() + 1)}/${localDate.getUTCFullYear()} ${fmt(localDate.getUTCHours())}:${fmt(localDate.getUTCMinutes())}:${fmt(localDate.getUTCSeconds())}`;
1149
+ console.log(`[${formattedDate}]`, ...msg);
1150
+ }
1151
+
1152
+ export function formatFriendState(data) {
1153
+ if (!data) {
1154
+ return;
1155
+ }
1156
+
1157
+ function formatUndefined(value) {
1158
+ if (value === "" || value === null || value === undefined || (typeof value === "number" && isNaN(value))) {
1159
+ return null;
1160
+ }
1161
+ return value;
1162
+ }
1163
+
1164
+ const { player_name, gameid, persona_state, rich_presence = [] } = data;
1165
+ const avatar_hash = data.avatar_hash ? (typeof data.avatar_hash === "string" ? data.avatar_hash : Buffer.from(data.avatar_hash).toString("hex")) : "fef49e7fa7e1997310d705b2a6158ff8dc1cdfeb";
1166
+
1167
+ let onlineStatus = "offline";
1168
+ let score = "";
1169
+ const scoreDetails = rich_presence.find((r) => r.key === "game:score")?.value;
1170
+ const mode = rich_presence.find((r) => r.key === "game:mode")?.value;
1171
+ const map = rich_presence.find((r) => r.key === "game:map")?.value;
1172
+ const numPlayers = formatUndefined(parseInt(rich_presence.find((r) => r.key === "members:numPlayers")?.value)); //include this friend, 2,3,4,5
1173
+ const steam_player_group = formatUndefined(parseInt(rich_presence.find?.((r) => r.key === "steam_player_group")?.value));
1174
+ const steam_player_group_size = formatUndefined(parseInt(rich_presence.find?.((r) => r.key === "steam_player_group_size")?.value));
1175
+
1176
+ if (gameid !== null && gameid !== undefined && gameid !== "") {
1177
+ if (gameid === 0 || gameid === "0") {
1178
+ if ([1, 2, 3, 4].includes(persona_state)) {
1179
+ onlineStatus = "online";
1180
+ } else if (persona_state === 0) {
1181
+ onlineStatus = "offline";
1182
+ } else {
1183
+ // console.log(data)
1184
+ onlineStatus = "online";
1185
+ }
1186
+ } else {
1187
+ onlineStatus = "ingame";
1188
+ }
1189
+
1190
+ if (rich_presence.some((r) => r.key === "game:state" && r.value === "lobby")) {
1191
+ score = data.rich_presence_string || "In Lobby";
1192
+ } else {
1193
+ score = rich_presence.find?.((r) => r.key === "status")?.value || data.rich_presence_string || "";
1194
+ }
1195
+ if (score === "not found") {
1196
+ score = "";
1197
+ }
1198
+ if (score.startsWith("Premier") && !score.startsWith("Premier Competitive") && data.rich_presence_string?.startsWith("Premier Competitive")) {
1199
+ score = data.rich_presence_string;
1200
+ }
1201
+ } else if (persona_state === null && rich_presence.length === 0) {
1202
+ onlineStatus = "offline";
1203
+ }
1204
+
1205
+ return {
1206
+ onlineStatus,
1207
+ score: formatUndefined(score),
1208
+ scoreDetails: formatUndefined(scoreDetails),
1209
+ mode: formatUndefined(mode),
1210
+ map: formatUndefined(map),
1211
+ player_name,
1212
+ gameid: formatUndefined(parseInt(gameid)),
1213
+ numPlayers,
1214
+ steam_player_group,
1215
+ steam_player_group_size,
1216
+ avatar_hash,
1217
+ rich_presence,
1218
+ };
1219
+ }
1220
+
1221
+ export function getGameDetailScore(scoreString) {
1222
+ if (typeof scoreString !== "string") {
1223
+ return null;
1224
+ }
1225
+ const regex = /\[\s*(\d+)\s*:\s*(\d+)\s*\]/;
1226
+ const matches = scoreString.match(regex);
1227
+ if (matches) {
1228
+ // The first capturing group (matches[1]) is the first score, the second (matches[2]) is the second score
1229
+ const score1 = matches[1];
1230
+ const score2 = matches[2];
1231
+ return [score1, score2].map(Number);
1232
+ }
1233
+ // console.log("No match found", scoreString);
1234
+ }