specific-ai-cli 0.0.0-stage → 0.1.1

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 (277) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +177 -0
  3. package/README.ja.md +177 -0
  4. package/README.ko.md +177 -0
  5. package/README.md +174 -2
  6. package/README.zh-TW.md +177 -0
  7. package/assets/banner.txt +3 -0
  8. package/dist/cli/argv.js +98 -0
  9. package/dist/cli/commands/auth.js +11 -0
  10. package/dist/cli/commands/config.js +23 -0
  11. package/dist/cli/commands/doctor.js +134 -0
  12. package/dist/cli/commands/platforms.js +24 -0
  13. package/dist/cli/commands/version.js +4 -0
  14. package/dist/cli/confirm.js +22 -0
  15. package/dist/cli/dispatch.js +440 -0
  16. package/dist/cli/help.js +223 -0
  17. package/dist/cli/hints.js +60 -0
  18. package/dist/cli/main.js +18 -0
  19. package/dist/cli/output.js +66 -0
  20. package/dist/core/auth-handlers.js +41 -0
  21. package/dist/core/auth-store.js +119 -0
  22. package/dist/core/capabilities.js +163 -0
  23. package/dist/core/config.js +121 -0
  24. package/dist/core/cookies.js +164 -0
  25. package/dist/core/errors.js +37 -0
  26. package/dist/core/files.js +89 -0
  27. package/dist/core/fsutil.js +52 -0
  28. package/dist/core/hash.js +4 -0
  29. package/dist/core/http.js +331 -0
  30. package/dist/core/image.js +280 -0
  31. package/dist/core/log.js +40 -0
  32. package/dist/core/login.js +191 -0
  33. package/dist/core/mp4.js +130 -0
  34. package/dist/core/normalize.js +207 -0
  35. package/dist/core/options.js +110 -0
  36. package/dist/core/paths.js +38 -0
  37. package/dist/core/pb.js +59 -0
  38. package/dist/core/py.js +181 -0
  39. package/dist/core/rand.js +131 -0
  40. package/dist/core/registry.js +129 -0
  41. package/dist/core/schemas.js +41 -0
  42. package/dist/core/stream.js +104 -0
  43. package/dist/core/toolkit.js +35 -0
  44. package/dist/core/vm.js +73 -0
  45. package/dist/core/vocab.js +157 -0
  46. package/dist/platforms/_shared/impaas.js +410 -0
  47. package/dist/platforms/bilibili/index.js +216 -0
  48. package/dist/platforms/bilibili/web/api.js +806 -0
  49. package/dist/platforms/bilibili/web/client.js +311 -0
  50. package/dist/platforms/bilibili/web/commands.js +783 -0
  51. package/dist/platforms/bilibili/web/ddddocr.js +342 -0
  52. package/dist/platforms/bilibili/web/gaia.js +130 -0
  53. package/dist/platforms/bilibili/web/geetest-manual.js +154 -0
  54. package/dist/platforms/bilibili/web/geetest-vision.js +232 -0
  55. package/dist/platforms/bilibili/web/geetest.js +450 -0
  56. package/dist/platforms/bilibili/web/normalize.js +234 -0
  57. package/dist/platforms/bilibili/web/profile.js +135 -0
  58. package/dist/platforms/bilibili/web/resolve.js +112 -0
  59. package/dist/platforms/bilibili/web/sign.js +223 -0
  60. package/dist/platforms/bilibili/web/upos.js +102 -0
  61. package/dist/platforms/douyin/index.js +142 -0
  62. package/dist/platforms/douyin/web/api.js +863 -0
  63. package/dist/platforms/douyin/web/client.js +413 -0
  64. package/dist/platforms/douyin/web/commands.js +712 -0
  65. package/dist/platforms/douyin/web/creator.js +601 -0
  66. package/dist/platforms/douyin/web/crypto.js +247 -0
  67. package/dist/platforms/douyin/web/dtrait.js +190 -0
  68. package/dist/platforms/douyin/web/im.js +502 -0
  69. package/dist/platforms/douyin/web/image.js +5 -0
  70. package/dist/platforms/douyin/web/live.js +225 -0
  71. package/dist/platforms/douyin/web/mssdk.js +148 -0
  72. package/dist/platforms/douyin/web/normalize.js +326 -0
  73. package/dist/platforms/douyin/web/passport.js +1247 -0
  74. package/dist/platforms/douyin/web/profile.js +221 -0
  75. package/dist/platforms/douyin/web/proto.js +26 -0
  76. package/dist/platforms/douyin/web/resolve.js +88 -0
  77. package/dist/platforms/douyin/web/sign.js +436 -0
  78. package/dist/platforms/douyin/web/tos.js +78 -0
  79. package/dist/platforms/index.js +17 -0
  80. package/dist/platforms/jd/index.js +67 -0
  81. package/dist/platforms/jd/web/aks.js +115 -0
  82. package/dist/platforms/jd/web/api.js +549 -0
  83. package/dist/platforms/jd/web/chat.js +132 -0
  84. package/dist/platforms/jd/web/client.js +470 -0
  85. package/dist/platforms/jd/web/commands.js +557 -0
  86. package/dist/platforms/jd/web/jcap/helper.js +90 -0
  87. package/dist/platforms/jd/web/jcap/host.js +107 -0
  88. package/dist/platforms/jd/web/jcap/lsd.js +300 -0
  89. package/dist/platforms/jd/web/jcap/solver.js +995 -0
  90. package/dist/platforms/jd/web/jcap.js +150 -0
  91. package/dist/platforms/jd/web/js.js +420 -0
  92. package/dist/platforms/jd/web/login.js +775 -0
  93. package/dist/platforms/jd/web/normalize.js +297 -0
  94. package/dist/platforms/jd/web/profile.js +256 -0
  95. package/dist/platforms/jd/web/util.js +175 -0
  96. package/dist/platforms/jd/web/webm.js +133 -0
  97. package/dist/platforms/kuaishou/index.js +98 -0
  98. package/dist/platforms/kuaishou/web/api.js +694 -0
  99. package/dist/platforms/kuaishou/web/captcha-crypto.js +134 -0
  100. package/dist/platforms/kuaishou/web/captcha-fp.js +180 -0
  101. package/dist/platforms/kuaishou/web/captcha.js +273 -0
  102. package/dist/platforms/kuaishou/web/client.js +487 -0
  103. package/dist/platforms/kuaishou/web/commands.js +863 -0
  104. package/dist/platforms/kuaishou/web/gap.js +144 -0
  105. package/dist/platforms/kuaishou/web/gdfp.js +376 -0
  106. package/dist/platforms/kuaishou/web/gql.js +11 -0
  107. package/dist/platforms/kuaishou/web/live.js +125 -0
  108. package/dist/platforms/kuaishou/web/normalize.js +241 -0
  109. package/dist/platforms/kuaishou/web/oracle.js +329 -0
  110. package/dist/platforms/kuaishou/web/profile.js +259 -0
  111. package/dist/platforms/kuaishou/web/resolve.js +84 -0
  112. package/dist/platforms/kuaishou/web/session.js +592 -0
  113. package/dist/platforms/kuaishou/web/sign.js +568 -0
  114. package/dist/platforms/taobao/index.js +56 -0
  115. package/dist/platforms/taobao/web/api.js +96 -0
  116. package/dist/platforms/taobao/web/client.js +102 -0
  117. package/dist/platforms/taobao/web/commands.js +172 -0
  118. package/dist/platforms/taobao/web/im.js +68 -0
  119. package/dist/platforms/taobao/web/normalize.js +103 -0
  120. package/dist/platforms/taobao/web/profile.js +85 -0
  121. package/dist/platforms/taobao/web/resolve.js +51 -0
  122. package/dist/platforms/taobao/web/sign.js +35 -0
  123. package/dist/platforms/tiktok/index.js +120 -0
  124. package/dist/platforms/tiktok/web/api.js +1234 -0
  125. package/dist/platforms/tiktok/web/client.js +362 -0
  126. package/dist/platforms/tiktok/web/commands.js +821 -0
  127. package/dist/platforms/tiktok/web/im.js +133 -0
  128. package/dist/platforms/tiktok/web/jsrun.js +126 -0
  129. package/dist/platforms/tiktok/web/normalize.js +286 -0
  130. package/dist/platforms/tiktok/web/profile.js +169 -0
  131. package/dist/platforms/tiktok/web/resolve.js +156 -0
  132. package/dist/platforms/tiktok/web/sign.js +585 -0
  133. package/dist/platforms/tiktok/web/upload.js +805 -0
  134. package/dist/platforms/tiktok/web/wire.js +490 -0
  135. package/dist/platforms/weibo/index.js +91 -0
  136. package/dist/platforms/weibo/web/api.js +206 -0
  137. package/dist/platforms/weibo/web/client.js +155 -0
  138. package/dist/platforms/weibo/web/commands.js +202 -0
  139. package/dist/platforms/weibo/web/normalize.js +137 -0
  140. package/dist/platforms/weibo/web/profile.js +246 -0
  141. package/dist/platforms/weibo/web/resolve.js +60 -0
  142. package/dist/platforms/weibo/web/sign.js +85 -0
  143. package/dist/platforms/x/index.js +107 -0
  144. package/dist/platforms/x/web/api.js +443 -0
  145. package/dist/platforms/x/web/article.js +212 -0
  146. package/dist/platforms/x/web/client.js +202 -0
  147. package/dist/platforms/x/web/commands.js +363 -0
  148. package/dist/platforms/x/web/graphql.js +108 -0
  149. package/dist/platforms/x/web/normalize.js +235 -0
  150. package/dist/platforms/x/web/profile.js +99 -0
  151. package/dist/platforms/x/web/resolve.js +44 -0
  152. package/dist/platforms/x/web/transaction.js +171 -0
  153. package/dist/platforms/xhs/index.js +101 -0
  154. package/dist/platforms/xhs/web/api.js +278 -0
  155. package/dist/platforms/xhs/web/client.js +540 -0
  156. package/dist/platforms/xhs/web/commands.js +1046 -0
  157. package/dist/platforms/xhs/web/creator-api.js +609 -0
  158. package/dist/platforms/xhs/web/creator.js +203 -0
  159. package/dist/platforms/xhs/web/js.js +194 -0
  160. package/dist/platforms/xhs/web/login.js +230 -0
  161. package/dist/platforms/xhs/web/normalize.js +166 -0
  162. package/dist/platforms/xhs/web/profile.js +127 -0
  163. package/dist/platforms/xhs/web/push.js +361 -0
  164. package/dist/platforms/xhs/web/resolve.js +69 -0
  165. package/dist/platforms/xhs/web/state.js +368 -0
  166. package/dist/platforms/xianyu/index.js +59 -0
  167. package/dist/platforms/xianyu/web/api.js +312 -0
  168. package/dist/platforms/xianyu/web/client.js +134 -0
  169. package/dist/platforms/xianyu/web/commands.js +305 -0
  170. package/dist/platforms/xianyu/web/im.js +73 -0
  171. package/dist/platforms/xianyu/web/normalize.js +123 -0
  172. package/dist/platforms/xianyu/web/profile.js +146 -0
  173. package/dist/platforms/xianyu/web/resolve.js +48 -0
  174. package/dist/platforms/xianyu/web/sign.js +79 -0
  175. package/package.json +77 -4
  176. package/static/douyin/Live.proto +194 -0
  177. package/static/douyin/Request.proto +89 -0
  178. package/static/douyin/Response.proto +46 -0
  179. package/static/douyin/acrawler_runtime/ac_vm.js +2 -0
  180. package/static/douyin/acrawler_runtime/browser_window_shape.json +1 -0
  181. package/static/douyin/acrawler_runtime/canvas_actual_exact.json +1 -0
  182. package/static/douyin/acrawler_runtime/run_ac_node.js +1005 -0
  183. package/static/douyin/acrawler_runtime/runner_window_keys_baseline.txt +240 -0
  184. package/static/douyin/challenge_profile.json +801 -0
  185. package/static/douyin/challenge_template_runner.js +217 -0
  186. package/static/douyin/dtrait_profile.json +66 -0
  187. package/static/douyin/mstoken_common_profile.json +1 -0
  188. package/static/douyin/mstoken_profile.json +214 -0
  189. package/static/jd/h5st5_env.js +750 -0
  190. package/static/jd/h5st5_lib.js +5 -0
  191. package/static/jd/h5st5_server.js +49 -0
  192. package/static/jd/jcap/env/env_core.js +512 -0
  193. package/static/jd/jcap/env/run.js +1307 -0
  194. package/static/jd/jcap/run/jcap_ujb96b.js +39 -0
  195. package/static/jd/package.json +4 -0
  196. package/static/jd/pc_tk_lib.js +1 -0
  197. package/static/jd/pc_tk_server.js +63 -0
  198. package/static/jd/summer_cryptico_runner.js +50 -0
  199. package/static/jd/webm/env/run.js +453 -0
  200. package/static/jd/webm/run/jdwebm-riskhandle.js +49 -0
  201. package/static/kuaishou/bundles/weapon/kwf-0.0.2.2cee19b4b7dec496.js +1 -0
  202. package/static/kuaishou/bundles/weapon/kws-0-0.0.1-obfuscated.4b7f3de1ab0ddcc2.js +1 -0
  203. package/static/kuaishou/bundles/weapon/kws-1-0.0.1-obfuscated.346ebdb1c78df316.js +1 -0
  204. package/static/kuaishou/bundles/weapon/kws-10-0.0.1-obfuscated.a33db41897b983af.js +1 -0
  205. package/static/kuaishou/bundles/weapon/kws-11-0.0.1-obfuscated.5e0a90af726d8a7e.js +1 -0
  206. package/static/kuaishou/bundles/weapon/kws-12-0.0.1-obfuscated.20ea29345706ec8c.js +1 -0
  207. package/static/kuaishou/bundles/weapon/kws-13-0.0.1-obfuscated.6b74e9640ff18648.js +1 -0
  208. package/static/kuaishou/bundles/weapon/kws-14-0.0.1-obfuscated.551e4429d156bf66.js +1 -0
  209. package/static/kuaishou/bundles/weapon/kws-15-0.0.1-obfuscated.8625b087aaba4a60.js +1 -0
  210. package/static/kuaishou/bundles/weapon/kws-16-0.0.1-obfuscated.d5ffa4020f3be99a.js +1 -0
  211. package/static/kuaishou/bundles/weapon/kws-17-0.0.1-obfuscated.6d13e19b22f50a80.js +1 -0
  212. package/static/kuaishou/bundles/weapon/kws-18-0.0.1-obfuscated.6d31405044166289.js +1 -0
  213. package/static/kuaishou/bundles/weapon/kws-19-0.0.1-obfuscated.a9a8d925942f19e4.js +1 -0
  214. package/static/kuaishou/bundles/weapon/kws-2-0.0.1-obfuscated.b849a136ae4a6b3e.js +1 -0
  215. package/static/kuaishou/bundles/weapon/kws-3-0.0.1-obfuscated.f9e77ebf6186e2ac.js +1 -0
  216. package/static/kuaishou/bundles/weapon/kws-4-0.0.1-obfuscated.2c3c155aa52ceb0e.js +1 -0
  217. package/static/kuaishou/bundles/weapon/kws-5-0.0.1-obfuscated.4e553d17691b3c5a.js +1 -0
  218. package/static/kuaishou/bundles/weapon/kws-6-0.0.1-obfuscated.f73ddd3ff13e1217.js +1 -0
  219. package/static/kuaishou/bundles/weapon/kws-7-0.0.1-obfuscated.1628b8729beaab7e.js +1 -0
  220. package/static/kuaishou/bundles/weapon/kws-8-0.0.1-obfuscated.6da6baef7aa81fff.js +1 -0
  221. package/static/kuaishou/bundles/weapon/kws-9-0.0.1-obfuscated.8645d55e5323b743.js +1 -0
  222. package/static/kuaishou/fixtures/current_follow_script_813.network-response +2 -0
  223. package/static/kuaishou/fixtures/live_ws_maps.json +61 -0
  224. package/static/kuaishou/fixtures/live_ws_proto.json +1342 -0
  225. package/static/kuaishou/js/cp-kwf.js +1 -0
  226. package/static/kuaishou/tools/kwf_oracle.js +799 -0
  227. package/static/kuaishou/tools/kws_oracle.js +885 -0
  228. package/static/kuaishou/tools/like_token_oracle.js +70 -0
  229. package/static/taobao/taobao_js_20260407.js +570 -0
  230. package/static/tiktok/Tiktok_Request.json +597 -0
  231. package/static/tiktok/package.json +3 -0
  232. package/static/tiktok/shop_bsid/core.js +1 -0
  233. package/static/tiktok/shop_bsid/env_core.js +512 -0
  234. package/static/tiktok/shop_bsid/loader.js +1 -0
  235. package/static/tiktok/shop_bsid/run.js +753 -0
  236. package/static/tiktok/shop_bsid/sign.js +100 -0
  237. package/static/tiktok/shop_bsid/webmssdk.js +1 -0
  238. package/static/tiktok/shop_bsid/webmssdk_ex.js +1 -0
  239. package/static/tiktok/signing/env/env_core.js +512 -0
  240. package/static/tiktok/signing/env/sign.js +455 -0
  241. package/static/tiktok/signing/sdk_config.json +230 -0
  242. package/static/tiktok/signing/source/webmssdk.js +1 -0
  243. package/static/tiktok/signing/source/webmssdk_ex.js +1 -0
  244. package/static/tiktok/signing/source/webmssdk_legacy.js +1 -0
  245. package/static/x/graphql.json +7777 -0
  246. package/static/x/transaction_l1.json +12 -0
  247. package/static/xhs/package.json +3 -0
  248. package/static/xhs/xhs_core/js/b1.js +210 -0
  249. package/static/xhs/xhs_core/js/mns.js +340 -0
  250. package/static/xhs/xhs_core/js/mns_0101_keystream.json +5 -0
  251. package/static/xhs/xhs_core/js/mns_keystreams.json +1 -0
  252. package/static/xhs/xhs_core/js/sign.js +225 -0
  253. package/static/xhs/xhs_core/js/websectiga_cli.js +220 -0
  254. package/static/xhs/xhs_core/js/websectiga_env.js +512 -0
  255. package/static/xhs/xhs_core/js/xs_common.js +79 -0
  256. package/static/xhs/xhs_creator/js/profile.js +115 -0
  257. package/static/xhs/xhs_creator/js/rap_fingerprint_creator.json +6 -0
  258. package/static/xhs/xhs_creator/js/reference_profile.json +282 -0
  259. package/static/xhs/xhs_creator/js/xhs_creator_sign.js +29 -0
  260. package/static/xhs/xhs_creator/js/xhs_creator_signature.js +23 -0
  261. package/static/xhs/xhs_pc/js/aes_decrypt.js +22 -0
  262. package/static/xhs/xhs_pc/js/aes_encrypt.js +30 -0
  263. package/static/xhs/xhs_pc/js/b1.js +9 -0
  264. package/static/xhs/xhs_pc/js/deflate.js +320 -0
  265. package/static/xhs/xhs_pc/js/mns.js +4 -0
  266. package/static/xhs/xhs_pc/js/profile.js +141 -0
  267. package/static/xhs/xhs_pc/js/rap.js +173 -0
  268. package/static/xhs/xhs_pc/js/rap_cli.js +30 -0
  269. package/static/xhs/xhs_pc/js/rap_crypto.js +73 -0
  270. package/static/xhs/xhs_pc/js/rap_fingerprint_template.json +8 -0
  271. package/static/xhs/xhs_pc/js/reference_profile.json +262 -0
  272. package/static/xhs/xhs_pc/js/sign.js +6 -0
  273. package/static/xhs/xhs_pc/js/web_ssk.js +82 -0
  274. package/static/xhs/xhs_pc/js/xs_common.js +4 -0
  275. package/static/xianyu/et_f.js +2 -0
  276. package/static/xianyu/gen_tfstk.js +410 -0
  277. package/static/xianyu/goofish_js_version_2.js +568 -0
@@ -0,0 +1,410 @@
1
+ // utils/gen_tfstk.js
2
+ // node 补环境生成 tfstk。核心策略:
3
+ // 1. vm.createContext + 深度 Proxy 记录 SDK 每一个属性访问
4
+ // 2. crypto.subtle 同步化(绕 VMP setTimeout race)
5
+ // 3. 缺失属性从 env_snapshot.json(真浏览器 dump)回填
6
+ //
7
+ // 用法:
8
+ // node utils/gen_tfstk.js → stdout 输出 tfstk
9
+ // node utils/gen_tfstk.js --probe → 输出 SDK 访问日志(用于定位缺失环境)
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const vm = require('vm');
14
+ const nodeCrypto = require('crypto');
15
+
16
+ const PROBE = process.argv.includes('--probe');
17
+ const ET_PATH = path.join(__dirname, 'et_f.js');
18
+
19
+ // ═══════════ 1. 同步化 crypto.subtle ═══════════
20
+ function syncThenable(v) {
21
+ return {
22
+ then(ok, fail) {
23
+ try { const r = ok ? ok(v) : v; return (r && typeof r.then === 'function') ? r : syncThenable(r); }
24
+ catch (e) { return fail ? syncThenable(fail(e)) : syncThenable(undefined); }
25
+ },
26
+ catch(f) { return this; },
27
+ finally(f) { try { f && f(); } catch(e) {} return this; },
28
+ };
29
+ }
30
+ function fakeCryptoKey(raw, algo, usages) {
31
+ return { _raw: Buffer.from(raw), algorithm: typeof algo === 'string' ? {name:algo} : algo, type:'secret', extractable:true, usages };
32
+ }
33
+ function toBuf(x) {
34
+ if (Buffer.isBuffer(x)) return x;
35
+ if (x instanceof ArrayBuffer) return Buffer.from(x);
36
+ if (ArrayBuffer.isView(x)) return Buffer.from(x.buffer, x.byteOffset, x.byteLength);
37
+ return Buffer.from(x || '');
38
+ }
39
+ function toAB(buf) { return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); }
40
+ function cipherName(algo, keyLen) {
41
+ const n = (algo.name||algo).replace(/-/g,'').toLowerCase();
42
+ const bits = keyLen * 8;
43
+ if (n === 'aescbc') return `aes-${bits}-cbc`;
44
+ if (n === 'aesgcm') return `aes-${bits}-gcm`;
45
+ if (n === 'aesctr') return `aes-${bits}-ctr`;
46
+ throw new Error('unsupported: ' + n);
47
+ }
48
+ function hashAlg(a) { return (typeof a==='string'?a:a.name||'').replace('-','').toLowerCase(); }
49
+
50
+ const syncSubtle = {
51
+ importKey(fmt, key, algo, ext, usages) { return syncThenable(fakeCryptoKey(toBuf(key), algo, usages)); },
52
+ exportKey(fmt, key) { return syncThenable(toAB(key._raw)); },
53
+ encrypt(algo, key, data) {
54
+ try { const c=nodeCrypto.createCipheriv(cipherName(algo,key._raw.length),key._raw,toBuf(algo.iv));
55
+ return syncThenable(toAB(Buffer.concat([c.update(toBuf(data)),c.final()]))); }
56
+ catch(e){ return syncThenable(undefined); }
57
+ },
58
+ decrypt(algo, key, data) {
59
+ try { const d=nodeCrypto.createDecipheriv(cipherName(algo,key._raw.length),key._raw,toBuf(algo.iv));
60
+ return syncThenable(toAB(Buffer.concat([d.update(toBuf(data)),d.final()]))); }
61
+ catch(e){ return syncThenable(undefined); }
62
+ },
63
+ digest(algo, data) {
64
+ try { const h=nodeCrypto.createHash(hashAlg(algo)); h.update(toBuf(data));
65
+ return syncThenable(toAB(h.digest())); }
66
+ catch(e){ return syncThenable(undefined); }
67
+ },
68
+ sign(algo,key,data) {
69
+ try { const h=nodeCrypto.createHmac(hashAlg(algo.hash||'sha256'),key._raw); h.update(toBuf(data));
70
+ return syncThenable(toAB(h.digest())); }
71
+ catch(e){ return syncThenable(undefined); }
72
+ },
73
+ generateKey(algo,ext,u) { return syncThenable(fakeCryptoKey(nodeCrypto.randomBytes((algo.length||128)/8),algo,u)); },
74
+ deriveBits() { return syncThenable(toAB(nodeCrypto.randomBytes(32))); },
75
+ deriveKey(a,b,d,e,u) { return syncThenable(fakeCryptoKey(nodeCrypto.randomBytes((d.length||128)/8),d,u)); },
76
+ verify() { return syncThenable(true); },
77
+ };
78
+ const syncCrypto = {
79
+ subtle: syncSubtle,
80
+ getRandomValues(a) { nodeCrypto.randomFillSync(a); return a; },
81
+ randomUUID() { return nodeCrypto.randomUUID(); },
82
+ };
83
+
84
+ // ═══════════ 2. Proxy 环境框架 ═══════════
85
+ const accessLog = []; // [{path, type:'get'|'set'|'call', val?}]
86
+ const cookieWrites = [];
87
+ let cookieJar = '';
88
+
89
+ // 尝试加载真浏览器 dump 的环境快照
90
+ let envSnapshot = {};
91
+ const SNAP_PATH = path.join(__dirname, 'env_snapshot.json');
92
+ if (fs.existsSync(SNAP_PATH)) {
93
+ try { envSnapshot = JSON.parse(fs.readFileSync(SNAP_PATH, 'utf8')); } catch(e) {}
94
+ }
95
+
96
+ function lookupSnapshot(pathStr) {
97
+ if (pathStr in envSnapshot) return { found: true, val: envSnapshot[pathStr] };
98
+ return { found: false };
99
+ }
100
+
101
+ function deepProxy(target, prefix, depth) {
102
+ if (depth > 8) return target;
103
+ if (target === null || target === undefined) return target;
104
+ if (typeof target !== 'object' && typeof target !== 'function') return target;
105
+ // 避免重复 Proxy
106
+ if (target.__isProxy) return target;
107
+
108
+ return new Proxy(target, {
109
+ get(t, prop) {
110
+ if (prop === '__isProxy') return true;
111
+ if (typeof prop === 'symbol') return Reflect.get(t, prop);
112
+ const fp = prefix ? `${prefix}.${prop}` : String(prop);
113
+
114
+ let v;
115
+ try { v = Reflect.get(t, prop); } catch(e) { v = undefined; }
116
+
117
+ // 优先用真值快照
118
+ if (v === undefined || v === null) {
119
+ const snap = lookupSnapshot(fp);
120
+ if (snap.found) {
121
+ if (PROBE) accessLog.push({ path: fp, type: 'get', source: 'snapshot' });
122
+ return snap.val;
123
+ }
124
+ }
125
+
126
+ if (PROBE) {
127
+ const desc = v === undefined ? '[undefined]' : v === null ? '[null]' :
128
+ typeof v === 'function' ? '[fn]' : typeof v === 'object' ? '[obj]' : String(v).slice(0,60);
129
+ accessLog.push({ path: fp, type: 'get', val: desc });
130
+ }
131
+
132
+ if (v && (typeof v === 'object' || typeof v === 'function')) {
133
+ return deepProxy(v, fp, depth + 1);
134
+ }
135
+ return v;
136
+ },
137
+ set(t, prop, val) {
138
+ const fp = prefix ? `${prefix}.${prop}` : String(prop);
139
+ if (PROBE) accessLog.push({ path: fp, type: 'set', val: typeof val });
140
+ // 捕获 cookie 写入
141
+ if (prop === 'cookie' && (prefix === 'document' || prefix.endsWith('.document'))) {
142
+ const s = String(val);
143
+ const name = s.split('=')[0].trim();
144
+ const v2 = (s.split('=')[1]||'').split(';')[0];
145
+ cookieWrites.push({ t: Date.now(), name, val: v2 });
146
+ cookieJar = s; // 简化:只保留最后写入
147
+ }
148
+ try { Reflect.set(t, prop, val); } catch(e) {}
149
+ return true;
150
+ },
151
+ apply(t, thisArg, args) {
152
+ if (PROBE) accessLog.push({ path: prefix, type: 'call' });
153
+ try { return Reflect.apply(t, thisArg, args); } catch(e) { return undefined; }
154
+ },
155
+ construct(t, args) {
156
+ if (PROBE) accessLog.push({ path: `new ${prefix}`, type: 'call' });
157
+ try { return Reflect.construct(t, args); } catch(e) { return {}; }
158
+ },
159
+ });
160
+ }
161
+
162
+ // ═══════════ 3. 构造假 window ═══════════
163
+ // 提供 SDK 实际需要的最小表面
164
+ const fakeDoc = {
165
+ cookie: '',
166
+ referrer: 'https://www.goofish.com/',
167
+ title: '闲鱼 - 闲不住?上闲鱼!',
168
+ URL: 'https://www.goofish.com/',
169
+ characterSet: 'UTF-8',
170
+ documentElement: { style: {}, getAttribute(){ return ''; } },
171
+ head: { appendChild(){}, removeChild(){} },
172
+ body: { appendChild(){}, removeChild(){}, style: {} },
173
+ createElement(tag) {
174
+ if (tag === 'canvas') return {
175
+ width: 300, height: 150,
176
+ getContext() {
177
+ return {
178
+ canvas: this, fillStyle: '', strokeStyle: '', font: '', textBaseline: 'alphabetic',
179
+ globalCompositeOperation: 'source-over', shadowBlur: 0, shadowColor: 'rgba(0,0,0,0)',
180
+ fillText(){}, strokeText(){}, fillRect(){}, strokeRect(){}, clearRect(){},
181
+ beginPath(){}, closePath(){}, arc(){}, fill(){}, stroke(){}, rect(){},
182
+ moveTo(){}, lineTo(){}, bezierCurveTo(){}, quadraticCurveTo(){},
183
+ save(){}, restore(){}, translate(){}, rotate(){}, scale(){}, transform(){}, setTransform(){},
184
+ drawImage(){}, createImageData(w,h){ return {data:new Uint8Array(w*h*4)}; },
185
+ getImageData(x,y,w,h){ return {data:new Uint8Array(w*h*4)}; },
186
+ putImageData(){},
187
+ measureText(t){ return {width: (t||'').length * 7}; },
188
+ // webgl stubs
189
+ getParameter(p){ return typeof p==='number' ? 'WebGL GLSL ES 1.0' : ''; },
190
+ getExtension(){ return null; },
191
+ getSupportedExtensions(){ return []; },
192
+ createBuffer(){return{};}, createShader(){return{};}, createProgram(){return{};},
193
+ bindBuffer(){}, bufferData(){}, shaderSource(){}, compileShader(){},
194
+ attachShader(){}, linkProgram(){}, useProgram(){},
195
+ getAttribLocation(){return 0;}, getUniformLocation(){return{};},
196
+ enableVertexAttribArray(){}, vertexAttribPointer(){}, drawArrays(){},
197
+ readPixels(){}, viewport(){}, clearColor(){}, clear(){}, enable(){}, disable(){},
198
+ };
199
+ },
200
+ toDataURL(){ return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=='; },
201
+ };
202
+ if (tag === 'input') return { name:'', value:'', type:'hidden', setAttribute(){}, getAttribute(){ return ''; } };
203
+ if (tag === 'div' || tag === 'span') return { style:{}, innerHTML:'', appendChild(){}, setAttribute(){} };
204
+ return { style:{}, setAttribute(){}, getAttribute(){ return ''; }, appendChild(){}, removeChild(){} };
205
+ },
206
+ getElementById(){ return null; },
207
+ getElementsByTagName(tag) {
208
+ if (tag === 'script') return [{src:'https://g.alicdn.com/AWSC/et/1.83.41/et_f.js'}];
209
+ if (tag === 'head') return [fakeDoc.head];
210
+ return [];
211
+ },
212
+ querySelectorAll(){ return []; },
213
+ querySelector(){ return null; },
214
+ addEventListener(){}, removeEventListener(){},
215
+ };
216
+
217
+ // 让 document.cookie 的 getter/setter 走我们的 hook
218
+ Object.defineProperty(fakeDoc, 'cookie', {
219
+ get() { return cookieJar; },
220
+ set(v) {
221
+ const s = String(v);
222
+ const name = s.split('=')[0].trim();
223
+ const val = (s.split('=')[1]||'').split(';')[0];
224
+ cookieWrites.push({ t: Date.now(), name, val });
225
+ cookieJar = s;
226
+ },
227
+ configurable: true, enumerable: true,
228
+ });
229
+
230
+ const fakeLoc = {
231
+ href: 'https://www.goofish.com/',
232
+ origin: 'https://www.goofish.com',
233
+ protocol: 'https:',
234
+ host: 'www.goofish.com',
235
+ hostname: 'www.goofish.com',
236
+ port: '',
237
+ pathname: '/',
238
+ search: '',
239
+ hash: '',
240
+ toString() { return this.href; },
241
+ assign(){}, replace(){}, reload(){},
242
+ };
243
+
244
+ const fakeNav = {
245
+ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36',
246
+ appCodeName: 'Mozilla', appName: 'Netscape', appVersion: '5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36',
247
+ platform: 'Win32', vendor: 'Google Inc.', vendorSub: '', product: 'Gecko', productSub: '20030107',
248
+ language: 'zh-CN', languages: ['zh-CN','zh','en'],
249
+ cookieEnabled: true, doNotTrack: null, onLine: true,
250
+ hardwareConcurrency: 8, deviceMemory: 8, maxTouchPoints: 0,
251
+ webdriver: false,
252
+ plugins: { length: 3, 0:{name:'PDF Viewer'}, 1:{name:'Chrome PDF Viewer'}, 2:{name:'Chromium PDF Viewer'} },
253
+ mimeTypes: { length: 2, 0:{type:'application/pdf'}, 1:{type:'text/pdf'} },
254
+ connection: { effectiveType:'4g', downlink:10, rtt:50, saveData:false, type:'wifi' },
255
+ geolocation: {}, mediaDevices: {},
256
+ getBattery() { return syncThenable({charging:true,chargingTime:0,dischargingTime:Infinity,level:1}); },
257
+ sendBeacon(){ return true; },
258
+ };
259
+
260
+ const fakeScreen = { width:1920, height:1080, availWidth:1920, availHeight:1040, colorDepth:24, pixelDepth:24,
261
+ orientation: {type:'landscape-primary', angle:0} };
262
+
263
+ const fakeStorage = (() => {
264
+ const m = {};
265
+ return { getItem(k){return k in m ? m[k] : null;}, setItem(k,v){m[k]=String(v);},
266
+ removeItem(k){delete m[k];}, clear(){for(const k in m)delete m[k];},
267
+ key(i){return Object.keys(m)[i]||null;}, get length(){return Object.keys(m).length;} };
268
+ })();
269
+
270
+ const fakeWin = {
271
+ // 自引用
272
+ get window() { return proxied; }, get self() { return proxied; },
273
+ get top() { return proxied; }, get parent() { return proxied; },
274
+ get globalThis() { return proxied; }, get frames() { return proxied; },
275
+
276
+ document: fakeDoc,
277
+ navigator: fakeNav,
278
+ location: fakeLoc,
279
+ screen: fakeScreen,
280
+ history: { length:1, state:null, go(){}, back(){}, forward(){}, pushState(){}, replaceState(){} },
281
+ localStorage: fakeStorage,
282
+ sessionStorage: fakeStorage,
283
+ performance: { now(){ return Date.now(); }, timing:{}, navigation:{type:0}, getEntriesByType(){return[];} },
284
+
285
+ innerWidth: 1920, innerHeight: 947, outerWidth: 1920, outerHeight: 1040,
286
+ scrollX: 0, scrollY: 0, pageXOffset: 0, pageYOffset: 0,
287
+ devicePixelRatio: 1, visualViewport: { width:1920, height:947 },
288
+
289
+ chrome: { runtime:{}, app:{installState:()=>{}}, csi:()=>({}), loadTimes:()=>({}) },
290
+ crypto: syncCrypto,
291
+
292
+ // Image:立即触发 onload
293
+ Image: function FakeImage() {
294
+ const img = {};
295
+ Object.defineProperty(img, 'src', {
296
+ set(v) { this._src = v; setTimeout(() => { try { img.onload && img.onload({}); } catch(e){} }, 1); },
297
+ get() { return this._src || ''; },
298
+ });
299
+ img.width = 0; img.height = 0;
300
+ return img;
301
+ },
302
+ XMLHttpRequest: function() {
303
+ return { open(){}, send(){}, setRequestHeader(){}, addEventListener(){}, abort(){},
304
+ readyState:4, status:200, responseText:'{}', response:'{}',
305
+ getResponseHeader(){ return ''; }, getAllResponseHeaders(){ return ''; } };
306
+ },
307
+ fetch: () => syncThenable({ ok:true, status:200, text:()=>syncThenable(''), json:()=>syncThenable({}) }),
308
+ WebSocket: function(){ return { send(){}, close(){}, addEventListener(){} }; },
309
+
310
+ setTimeout, clearTimeout, setInterval, clearInterval, queueMicrotask,
311
+ requestAnimationFrame: (cb) => setTimeout(cb, 16),
312
+ cancelAnimationFrame: clearTimeout,
313
+
314
+ Promise, Date, Math, JSON, Number, String, Object, Array, RegExp, Error,
315
+ TypeError, RangeError, SyntaxError, URIError, ReferenceError, EvalError,
316
+ Function, Symbol, Proxy, Reflect, WeakRef, FinalizationRegistry,
317
+ parseInt, parseFloat, isNaN, isFinite, NaN, Infinity, undefined,
318
+ encodeURIComponent, decodeURIComponent, encodeURI, decodeURI,
319
+ escape, unescape,
320
+ btoa: s => Buffer.from(String(s), 'binary').toString('base64'),
321
+ atob: s => Buffer.from(String(s), 'base64').toString('binary'),
322
+
323
+ Uint8Array, Uint16Array, Uint32Array, Uint8ClampedArray,
324
+ Int8Array, Int16Array, Int32Array,
325
+ Float32Array, Float64Array, BigInt64Array, BigUint64Array,
326
+ ArrayBuffer, SharedArrayBuffer, DataView, TextEncoder, TextDecoder,
327
+ Map, Set, WeakMap, WeakSet, BigInt,
328
+
329
+ console,
330
+ alert(){}, confirm(){ return true; }, prompt(){ return ''; },
331
+ getComputedStyle(){ return { getPropertyValue(){ return ''; } }; },
332
+ matchMedia(q){ return { matches: false, media: q, addEventListener(){} }; },
333
+ addEventListener(){}, removeEventListener(){}, dispatchEvent(){},
334
+ postMessage(){}, open(){ return null; }, close(){},
335
+ MutationObserver: function(){ return { observe(){}, disconnect(){}, takeRecords(){return[];} }; },
336
+ ResizeObserver: function(){ return { observe(){}, disconnect(){} }; },
337
+ IntersectionObserver: function(){ return { observe(){}, disconnect(){} }; },
338
+ DOMParser: function(){ return { parseFromString(){ return fakeDoc; } }; },
339
+ };
340
+
341
+ const proxied = deepProxy(fakeWin, '', 0);
342
+
343
+ // ═══════════ 4. 跑 SDK ═══════════
344
+ const sandbox = vm.createContext(new Proxy(Object.create(null), {
345
+ has(_, key) { return true; }, // 让任何变量引用都不抛 ReferenceError
346
+ get(_, key) {
347
+ if (typeof key === 'symbol') return undefined;
348
+ if (key === 'globalThis' || key === 'window' || key === 'self' || key === 'top' || key === 'parent' || key === 'frames')
349
+ return proxied;
350
+ const k = String(key);
351
+ if (k in fakeWin) return deepProxy(fakeWin[k], k, 0);
352
+ // 不在 fakeWin 里的:先查快照,再返回 undefined
353
+ const snap = lookupSnapshot(k);
354
+ if (snap.found) return snap.val;
355
+ if (PROBE) accessLog.push({ path: k, type: 'get', val: '[undefined-global]' });
356
+ return undefined;
357
+ },
358
+ set(_, key, val) {
359
+ fakeWin[key] = val;
360
+ return true;
361
+ },
362
+ }));
363
+
364
+ async function run() {
365
+ const code = fs.readFileSync(ET_PATH, 'utf8');
366
+ try { vm.runInContext(code, sandbox, { filename: 'et_f.js', timeout: 8000 }); }
367
+ catch (e) { console.error('[gen_tfstk] eval err:', e.message); }
368
+
369
+ // 等 setTimeout 链完成
370
+ for (let i = 0; i < 30; i++) {
371
+ await new Promise(r => setTimeout(r, 200));
372
+ // 查看是否拿到真值
373
+ const good = [...cookieWrites].reverse().find(w => w.name === 'tfstk' && w.val && w.val !== 'undefined');
374
+ if (good) {
375
+ if (!PROBE) process.stdout.write(good.val);
376
+ else console.error('[gen_tfstk] GOT tfstk at iter', i, 'val=', good.val.slice(0, 80) + '...');
377
+ return good.val;
378
+ }
379
+ // 主动调 getETToken
380
+ try {
381
+ vm.runInContext(`
382
+ try { var m = __awsc_et__ || (typeof __etModule!=='undefined' && __etModule);
383
+ if (m && typeof m.getETToken==='function') m.getETToken({appkey:'XIANYU'}); } catch(e){}
384
+ `, sandbox, { timeout: 2000 });
385
+ } catch(e) {}
386
+ }
387
+
388
+ // ═══════════ 5. probe 模式:输出访问日志 ═══════════
389
+ if (PROBE) {
390
+ // 去重 + 排序
391
+ const seen = new Map();
392
+ for (const e of accessLog) {
393
+ const k = e.path + '|' + e.type;
394
+ if (!seen.has(k)) seen.set(k, e);
395
+ }
396
+ const report = {
397
+ cookieWrites,
398
+ accessedPaths: [...seen.values()].filter(e => e.type === 'get').map(e => ({ path: e.path, val: e.val })),
399
+ writtenPaths: [...seen.values()].filter(e => e.type === 'set').map(e => e.path),
400
+ calledPaths: [...seen.values()].filter(e => e.type === 'call').map(e => e.path),
401
+ undefinedGlobals: [...seen.values()].filter(e => e.val === '[undefined-global]').map(e => e.path),
402
+ };
403
+ console.log(JSON.stringify(report, null, 2));
404
+ } else {
405
+ console.error('[gen_tfstk] timeout. writes:', JSON.stringify(cookieWrites));
406
+ }
407
+ return '';
408
+ }
409
+
410
+ run().then(v => { if (!v) process.exit(1); }).catch(e => { console.error(e); process.exit(2); });