steamutils 1.5.10 → 1.5.11

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