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,799 @@
1
+ /**
2
+ * kwf 预言机:在 Node 里跑真实的 kwf 脚本,拿到 window.kwpsec.getData()
3
+ * 的 218 字符指纹,并记录它到底读了哪些环境属性。
4
+ *
5
+ * 用途:给纯 Python 移植做对拍基准,同时摸清必须自造的环境面。
6
+ *
7
+ * 用法:
8
+ * node reverse/tools/kwf_oracle.js 出指纹 + 打印访问过的属性
9
+ * node reverse/tools/kwf_oracle.js quiet 只出指纹
10
+ */
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const vm = require('vm');
14
+ let createCanvas = null;
15
+ try { ({ createCanvas } = require('@napi-rs/canvas')); } catch (_) {}
16
+
17
+ const defaultScript = path.join(__dirname, '..', 'bundles', 'weapon',
18
+ 'kwf-0.0.2.2cee19b4b7dec496.js');
19
+ const requestedScript = process.env.KS_KWF_SCRIPT || '';
20
+ const SCRIPT = requestedScript
21
+ ? (path.isAbsolute(requestedScript) ? requestedScript
22
+ : path.join(__dirname, '..', '..', requestedScript))
23
+ : defaultScript;
24
+
25
+ const touched = [];
26
+ const caughtErrors = [];
27
+ const recentVmSteps = [];
28
+ const badReferences = [];
29
+ const missingProperties = [];
30
+ const jsonCalls = [];
31
+ const cookieRegexCalls = [];
32
+ const cookieWrites = [];
33
+ const propertyAssignments = [];
34
+ const propertyReads = [];
35
+ const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
36
+ + '(KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36';
37
+
38
+ // 记录属性访问的 Proxy。深度包一层,未知属性返回 undefined 而不是抛错。
39
+ function watch(target, label) {
40
+ return new Proxy(target, {
41
+ get(obj, prop) {
42
+ if (typeof prop === 'string') touched.push(`${label}.${prop}`);
43
+ const v = obj[prop];
44
+ if (v && typeof v === 'object' && !Array.isArray(v)
45
+ && !(v instanceof Date) && label.split('.').length < 3) {
46
+ return watch(v, `${label}.${String(prop)}`);
47
+ }
48
+ return v;
49
+ },
50
+ has(obj, prop) {
51
+ if (typeof prop === 'string') touched.push(`${label} in:${prop}`);
52
+ return prop in obj;
53
+ },
54
+ });
55
+ }
56
+
57
+ // 一套自洽的固定环境(纯算的目标就是把这套值喂进去而不依赖真浏览器)
58
+ // localStorage is persistent browser state. The old oracle recreated it for
59
+ // every Node process, silently resetting kwfcv1 to null and therefore always
60
+ // producing the 174-character branch. Accept and return both values so the
61
+ // Python session can carry the same state across calls.
62
+ const store = {
63
+ kwfv1: process.env.KS_KWFV1 || null,
64
+ kwfcv1: process.env.KS_KWFCV1 || null,
65
+ };
66
+ const requestedHref = process.env.KS_HREF || 'https://www.kuaishou.com/new-reco';
67
+ const requestedHost = process.env.KS_HOSTNAME || 'www.kuaishou.com';
68
+ const requestedCookie = process.env.KS_COOKIE || '';
69
+ const requestedHardwareConcurrency = Number(process.env.KS_HARDWARE_CONCURRENCY || 20);
70
+ const cookieJar = new Map();
71
+ for (const part of requestedCookie.split(';')) {
72
+ const item = part.trim();
73
+ if (!item) continue;
74
+ const equal = item.indexOf('=');
75
+ if (equal <= 0) continue;
76
+ cookieJar.set(item.slice(0, equal).trim(), item.slice(equal + 1));
77
+ }
78
+
79
+ // Chrome 151 / Windows WebGL values observed on the same CP page that emitted
80
+ // the authoritative /s/w/p request. Keep this deliberately narrow: unknown
81
+ // parameters are recorded and return null instead of being invented.
82
+ function WebGLRenderingContext() {}
83
+ Object.defineProperty(WebGLRenderingContext.prototype, Symbol.toStringTag, {
84
+ value: 'WebGLRenderingContext', configurable: true,
85
+ });
86
+ const WEBGL_PARAMETER_VALUES = new Map([
87
+ [3379, 16384],
88
+ [3386, [32767, 32767]],
89
+ [7936, 'WebKit'],
90
+ [7937, 'WebKit WebGL'],
91
+ [7938, 'WebGL 1.0 (OpenGL ES 2.0 Chromium)'],
92
+ [34024, 16384],
93
+ [34076, 16384],
94
+ [34921, 16],
95
+ [34930, 16],
96
+ [35660, 16],
97
+ [35661, 32],
98
+ [35724, 'WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)'],
99
+ [36183, null],
100
+ [36347, 4095],
101
+ [36348, 30],
102
+ [36349, 1024],
103
+ [37445, 'Google Inc. (NVIDIA)'],
104
+ [37446, 'ANGLE (NVIDIA, NVIDIA GeForce RTX 5060 Ti (0x00002D04) Direct3D11 vs_5_0 ps_5_0, D3D11)'],
105
+ ]);
106
+ const WEBGL_EXTENSIONS = [
107
+ 'ANGLE_instanced_arrays', 'EXT_blend_minmax', 'EXT_clip_control',
108
+ 'EXT_color_buffer_half_float', 'EXT_depth_clamp',
109
+ 'EXT_disjoint_timer_query', 'EXT_float_blend', 'EXT_frag_depth',
110
+ 'EXT_polygon_offset_clamp', 'EXT_shader_texture_lod',
111
+ 'EXT_texture_compression_bptc', 'EXT_texture_compression_rgtc',
112
+ 'EXT_texture_filter_anisotropic', 'EXT_texture_mirror_clamp_to_edge',
113
+ 'EXT_sRGB', 'KHR_parallel_shader_compile', 'OES_element_index_uint',
114
+ 'OES_fbo_render_mipmap', 'OES_standard_derivatives', 'OES_texture_float',
115
+ 'OES_texture_float_linear', 'OES_texture_half_float',
116
+ 'OES_texture_half_float_linear', 'OES_vertex_array_object',
117
+ 'WEBGL_blend_func_extended', 'WEBGL_color_buffer_float',
118
+ 'WEBGL_compressed_texture_s3tc', 'WEBGL_compressed_texture_s3tc_srgb',
119
+ 'WEBGL_debug_renderer_info', 'WEBGL_debug_shaders', 'WEBGL_depth_texture',
120
+ 'WEBGL_draw_buffers', 'WEBGL_lose_context', 'WEBGL_multi_draw',
121
+ 'WEBGL_polygon_mode',
122
+ ];
123
+ function makeWebGLContext() {
124
+ const gl = Object.create(WebGLRenderingContext.prototype);
125
+ Object.assign(gl, {
126
+ MAX_TEXTURE_SIZE: 3379,
127
+ MAX_VIEWPORT_DIMS: 3386,
128
+ VENDOR: 7936,
129
+ RENDERER: 7937,
130
+ VERSION: 7938,
131
+ MAX_RENDERBUFFER_SIZE: 34024,
132
+ MAX_CUBE_MAP_TEXTURE_SIZE: 34076,
133
+ MAX_VERTEX_ATTRIBS: 34921,
134
+ MAX_TEXTURE_IMAGE_UNITS: 34930,
135
+ VERTEX_SHADER: 35633,
136
+ FRAGMENT_SHADER: 35632,
137
+ MAX_VERTEX_TEXTURE_IMAGE_UNITS: 35660,
138
+ MAX_COMBINED_TEXTURE_IMAGE_UNITS: 35661,
139
+ SHADING_LANGUAGE_VERSION: 35724,
140
+ MAX_SAMPLES: 36183,
141
+ LOW_FLOAT: 36336,
142
+ MEDIUM_FLOAT: 36337,
143
+ HIGH_FLOAT: 36338,
144
+ LOW_INT: 36339,
145
+ MEDIUM_INT: 36340,
146
+ HIGH_INT: 36341,
147
+ MAX_VERTEX_UNIFORM_VECTORS: 36347,
148
+ MAX_VARYING_VECTORS: 36348,
149
+ MAX_FRAGMENT_UNIFORM_VECTORS: 36349,
150
+ });
151
+ gl.getParameter = (parameter) => {
152
+ const p = Number(parameter);
153
+ touched.push(`webgl.getParameter:${p}`);
154
+ if (!WEBGL_PARAMETER_VALUES.has(p)) {
155
+ touched.push(`webgl.getParameter.unobserved:${p}`);
156
+ return null;
157
+ }
158
+ const value = WEBGL_PARAMETER_VALUES.get(p);
159
+ return Array.isArray(value) ? new Int32Array(value) : value;
160
+ };
161
+ gl.getSupportedExtensions = () => {
162
+ touched.push('webgl.getSupportedExtensions');
163
+ return WEBGL_EXTENSIONS.slice();
164
+ };
165
+ gl.getExtension = (name) => {
166
+ const extension = String(name || '');
167
+ touched.push(`webgl.getExtension:${extension}`);
168
+ if (!WEBGL_EXTENSIONS.includes(extension)) return null;
169
+ if (extension === 'WEBGL_debug_renderer_info') {
170
+ return { UNMASKED_VENDOR_WEBGL: 37445, UNMASKED_RENDERER_WEBGL: 37446 };
171
+ }
172
+ if (extension === 'WEBGL_lose_context') {
173
+ const lose = {
174
+ loseContext() { touched.push('webgl.WEBGL_lose_context.loseContext'); },
175
+ restoreContext() { touched.push('webgl.WEBGL_lose_context.restoreContext'); },
176
+ };
177
+ try { Object.defineProperty(lose, Symbol.toStringTag, {
178
+ value: 'WebGLLoseContext', configurable: true,
179
+ }); } catch (_) {}
180
+ return lose;
181
+ }
182
+ return {};
183
+ };
184
+ gl.getContextAttributes = () => {
185
+ touched.push('webgl.getContextAttributes');
186
+ return {
187
+ alpha: true, antialias: true, depth: true, desynchronized: false,
188
+ failIfMajorPerformanceCaveat: false, powerPreference: 'default',
189
+ premultipliedAlpha: true, preserveDrawingBuffer: false,
190
+ stencil: false, xrCompatible: false,
191
+ };
192
+ };
193
+ gl.getShaderPrecisionFormat = (shaderType, precisionType) => {
194
+ const p = Number(precisionType);
195
+ touched.push(`webgl.getShaderPrecisionFormat:${Number(shaderType)}:${p}`);
196
+ const isFloat = p === 36336 || p === 36337 || p === 36338;
197
+ const isInt = p === 36339 || p === 36340 || p === 36341;
198
+ if (!isFloat && !isInt) return null;
199
+ const value = isFloat
200
+ ? { rangeMin: 127, rangeMax: 127, precision: 23 }
201
+ : { rangeMin: 31, rangeMax: 30, precision: 0 };
202
+ try { Object.defineProperty(value, Symbol.toStringTag, {
203
+ value: 'WebGLShaderPrecisionFormat', configurable: true,
204
+ }); } catch (_) {}
205
+ return value;
206
+ };
207
+ return gl;
208
+ }
209
+ function MimeType(type, plugin) {
210
+ this.type = type;
211
+ this.suffixes = 'pdf';
212
+ this.description = 'Portable Document Format';
213
+ this.enabledPlugin = plugin;
214
+ }
215
+ Object.defineProperty(MimeType.prototype, Symbol.toStringTag, {
216
+ value: 'MimeType', configurable: true,
217
+ });
218
+ function Plugin(name) {
219
+ this.name = name;
220
+ this.filename = 'internal-pdf-viewer';
221
+ this.description = 'Portable Document Format';
222
+ this[0] = new MimeType('application/pdf', this);
223
+ this[1] = new MimeType('text/pdf', this);
224
+ this.length = 2;
225
+ }
226
+ Object.defineProperty(Plugin.prototype, Symbol.toStringTag, {
227
+ value: 'Plugin', configurable: true,
228
+ });
229
+ const pdfPlugins = [
230
+ 'PDF Viewer', 'Chrome PDF Viewer', 'Chromium PDF Viewer',
231
+ 'Microsoft Edge PDF Viewer', 'WebKit built-in PDF',
232
+ ].map((name) => new Plugin(name));
233
+ const pluginArray = Object.assign({}, pdfPlugins, { length: pdfPlugins.length });
234
+ Object.defineProperty(pluginArray, Symbol.toStringTag, {
235
+ value: 'PluginArray', configurable: true,
236
+ });
237
+ const mimeTypeArray = Object.assign({}, {
238
+ 0: pdfPlugins[0][0], 1: pdfPlugins[0][1], length: 2,
239
+ });
240
+ Object.defineProperty(mimeTypeArray, Symbol.toStringTag, {
241
+ value: 'MimeTypeArray', configurable: true,
242
+ });
243
+ const navigatorPrototype = {};
244
+ Object.defineProperty(navigatorPrototype, Symbol.toStringTag, {
245
+ value: 'Navigator', configurable: true,
246
+ });
247
+ Object.defineProperty(navigatorPrototype, 'webdriver', {
248
+ get() { return false; }, configurable: true,
249
+ });
250
+ function Navigator() {}
251
+ Navigator.prototype = navigatorPrototype;
252
+ Object.defineProperty(navigatorPrototype, 'constructor', {
253
+ value: Navigator, writable: true, configurable: true,
254
+ });
255
+ const navigator = Object.assign(Object.create(navigatorPrototype), {
256
+ userAgent: UA,
257
+ appVersion: UA.slice('Mozilla/'.length),
258
+ platform: 'Win32',
259
+ language: 'zh-CN',
260
+ languages: ['zh-CN', 'zh', 'en', 'zh-TW', 'ja'],
261
+ vendor: 'Google Inc.',
262
+ hardwareConcurrency: requestedHardwareConcurrency,
263
+ deviceMemory: 8,
264
+ maxTouchPoints: 0,
265
+ cookieEnabled: true,
266
+ doNotTrack: null,
267
+ pdfViewerEnabled: true,
268
+ plugins: pluginArray,
269
+ mimeTypes: mimeTypeArray,
270
+ product: 'Gecko',
271
+ productSub: '20030107',
272
+ appName: 'Netscape',
273
+ appCodeName: 'Mozilla',
274
+ onLine: true,
275
+ vibrate() { return true; },
276
+ });
277
+ function Screen() {}
278
+ Object.defineProperty(Screen.prototype, Symbol.toStringTag, {
279
+ value: 'Screen', configurable: true,
280
+ });
281
+ const screenObj = {
282
+ width: 1920, height: 1080, availWidth: 1920, availHeight: 1032,
283
+ colorDepth: 24, pixelDepth: 24, availLeft: 0, availTop: 0,
284
+ };
285
+ Object.setPrototypeOf(screenObj, Screen.prototype);
286
+ const bodyChildren = [];
287
+ function markMounted(el, mounted) {
288
+ if (!el) return;
289
+ el.__mounted = mounted;
290
+ for (const child of el.children || []) markMounted(child, mounted);
291
+ }
292
+ const bodyObj = {
293
+ clientWidth: 1920, clientHeight: 947,
294
+ appendChild(el) { touched.push('body.appendChild'); if (el) { markMounted(el, true); bodyChildren.push(el); } return el; },
295
+ removeChild(el) { touched.push('body.removeChild'); const i = bodyChildren.indexOf(el); if (i >= 0) bodyChildren.splice(i, 1); markMounted(el, false); return el; },
296
+ };
297
+ const documentObj = {
298
+ get cookie() {
299
+ touched.push('document.cookie');
300
+ return [...cookieJar.entries()].map(([name, value]) => `${name}=${value}`).join('; ');
301
+ },
302
+ set cookie(raw) {
303
+ touched.push('document.cookie=');
304
+ const parts = String(raw || '').split(';').map((item) => item.trim());
305
+ const pair = parts[0] || '';
306
+ const equal = pair.indexOf('=');
307
+ if (equal <= 0) return;
308
+ const name = pair.slice(0, equal).trim();
309
+ const value = pair.slice(equal + 1);
310
+ cookieWrites.push({
311
+ name,
312
+ valueLength: value.length,
313
+ attributes: parts.slice(1).map((attr) => attr.split('=', 1)[0].toLowerCase()),
314
+ });
315
+ const expired = parts.slice(1).some((attr) => {
316
+ const lower = attr.toLowerCase();
317
+ if (lower.startsWith('max-age=')) return Number(lower.slice(8)) <= 0;
318
+ if (!lower.startsWith('expires=')) return false;
319
+ const when = Date.parse(attr.slice(attr.indexOf('=') + 1));
320
+ return Number.isFinite(when) && when <= Date.now();
321
+ });
322
+ if (expired) cookieJar.delete(name);
323
+ else cookieJar.set(name, value);
324
+ },
325
+ referrer: '',
326
+ title: '快手',
327
+ characterSet: 'UTF-8',
328
+ // getAttribute 必须有:脚本会查 documentElement 上的 webdriver/selenium 标记,
329
+ // 缺了它调用直接抛异常,getData() 就返回 null。
330
+ documentElement: {
331
+ clientWidth: 1920, clientHeight: 947, lang: 'zh-CN',
332
+ getAttribute() { return null; },
333
+ hasAttribute() { return false; },
334
+ },
335
+ body: bodyObj,
336
+ scripts: { length: 12 },
337
+ createElement(tag) {
338
+ if (String(tag || '').toLowerCase() === 'canvas' && createCanvas) {
339
+ touched.push('document.createElement:canvas:napi');
340
+ const canvas = createCanvas(300, 150);
341
+ try { Object.defineProperty(canvas, Symbol.toStringTag, { value: 'HTMLCanvasElement', configurable: true }); } catch (_) {}
342
+ canvas.style = {};
343
+ canvas.setAttribute = () => {};
344
+ canvas.appendChild = () => {};
345
+ canvas.getBoundingClientRect = () => ({ width: canvas.width, height: canvas.height, top: 0, left: 0 });
346
+ const rawGetContext = canvas.getContext.bind(canvas);
347
+ canvas.getContext = (...args) => {
348
+ touched.push(`canvas.getContext:${args[0]}`);
349
+ if (/^(experimental-)?webgl$/i.test(String(args[0] || ''))) {
350
+ return makeWebGLContext();
351
+ }
352
+ let ctx;
353
+ try { ctx = rawGetContext(...args); } catch (err) {
354
+ touched.push(`canvas.getContext.error:${err}`);
355
+ throw err;
356
+ }
357
+ try { Object.defineProperty(ctx, Symbol.toStringTag, { value: 'CanvasRenderingContext2D', configurable: true }); } catch (_) {}
358
+ return ctx;
359
+ };
360
+ const rawToDataURL = canvas.toDataURL.bind(canvas);
361
+ canvas.toDataURL = (...args) => {
362
+ touched.push(`canvas.toDataURL:${args.join(':')}`);
363
+ try { const out = rawToDataURL(...args); touched.push(`canvas.toDataURL.length:${String(out).length}`); return out; }
364
+ catch (err) { touched.push(`canvas.toDataURL.error:${err}`); throw err; }
365
+ };
366
+ return canvas;
367
+ }
368
+ const tagName = String(tag || '').toLowerCase();
369
+ const children = [];
370
+ const el = {
371
+ tagName: tagName.toUpperCase(), nodeName: tagName.toUpperCase(),
372
+ getContext() { return null; },
373
+ style: {}, setAttribute() {},
374
+ appendChild(child) { children.push(child); if (child) child.__parent = el; return child; },
375
+ removeChild(child) { const i = children.indexOf(child); if (i >= 0) children.splice(i, 1); return child; },
376
+ children, childNodes: children,
377
+ getBoundingClientRect() { return { width: 0, height: 0, top: 0, left: 0 }; },
378
+ };
379
+ if (tagName === 'iframe') {
380
+ el.srcdoc = '';
381
+ Object.defineProperty(el, 'contentWindow', {
382
+ value: null, enumerable: true, configurable: true,
383
+ });
384
+ Object.defineProperty(el, 'contentDocument', {
385
+ value: null, enumerable: true, configurable: true,
386
+ });
387
+ try { Object.defineProperty(el, Symbol.toStringTag, {
388
+ value: 'HTMLIFrameElement', configurable: true,
389
+ }); } catch (_) {}
390
+ }
391
+ const fontDimensions = () => {
392
+ const family = String(el.style.fontFamily || '');
393
+ if (/Microsoft YaHei/i.test(family)) return { width: 732, height: 105 };
394
+ if (/^(Helvetica|Arial)(,|$)/i.test(family)) return { width: 648, height: 105 };
395
+ if (/monospace/i.test(family)) return { width: 468, height: 82 };
396
+ if (/sans-serif/i.test(family)) return { width: 727, height: 105 };
397
+ if (/serif/i.test(family)) return { width: 773, height: 104 };
398
+ return { width: 0, height: 0 };
399
+ };
400
+ Object.defineProperty(el, 'offsetHeight', {
401
+ get() {
402
+ touched.push(`element.${tagName}.offsetHeight`);
403
+ if (!el.__mounted) return 0;
404
+ if (el.style.height === '20px') return 20;
405
+ return tagName === 'span' ? fontDimensions().height : 0;
406
+ },
407
+ });
408
+ Object.defineProperty(el, 'offsetWidth', {
409
+ get() {
410
+ touched.push(`element.${tagName}.offsetWidth`);
411
+ return el.__mounted && tagName === 'span' ? fontDimensions().width : 0;
412
+ },
413
+ });
414
+ if (process.env.KS_KWF_TRACE_ERRORS !== '1') return el;
415
+ return new Proxy(el, {
416
+ get(target, prop) {
417
+ if (typeof prop === 'string') {
418
+ touched.push(`element.${tagName}.get:${prop}${prop in target ? '' : ':undefined'}`);
419
+ }
420
+ return target[prop];
421
+ },
422
+ set(target, prop, value) {
423
+ if (typeof prop === 'string') touched.push(`element.${tagName}.set:${prop}`);
424
+ target[prop] = value;
425
+ return true;
426
+ },
427
+ });
428
+ },
429
+ getElementsByTagName(tag) {
430
+ touched.push(`document.getElementsByTagName:${tag}`);
431
+ return String(tag).toLowerCase() === 'body' ? [bodyObj] : { length: 0 };
432
+ },
433
+ getElementById(id) {
434
+ touched.push(`document.getElementById:${String(id || '')}`);
435
+ return null;
436
+ },
437
+ createEvent(type) {
438
+ touched.push(`document.createEvent:${type}`);
439
+ // Current Chrome 151 on this Windows page throws for legacy TouchEvent;
440
+ // the SDK uses that exception as the feature-detection result.
441
+ if (String(type) === 'TouchEvent') {
442
+ const err = new Error("The provided event type ('TouchEvent') is invalid.");
443
+ err.name = 'NotSupportedError';
444
+ throw err;
445
+ }
446
+ return {
447
+ type: String(type || ''),
448
+ initEvent(name) { touched.push(`event.initEvent:${name}`); this.type = String(name || ''); },
449
+ preventDefault() {}, stopPropagation() {},
450
+ };
451
+ },
452
+ addEventListener() {},
453
+ querySelector() { return null; },
454
+ };
455
+ const documentAll = {
456
+ length: 337,
457
+ item() { return null; },
458
+ namedItem() { return null; },
459
+ };
460
+ Object.defineProperty(documentAll, Symbol.toStringTag, {
461
+ value: 'HTMLAllCollection', configurable: true,
462
+ });
463
+ documentObj.all = documentAll;
464
+ let parsedLocation;
465
+ try { parsedLocation = new URL(requestedHref); } catch (_) {
466
+ parsedLocation = new URL(`https://${requestedHost}/`);
467
+ }
468
+ const locationObj = {
469
+ href: requestedHref,
470
+ origin: parsedLocation.origin,
471
+ protocol: parsedLocation.protocol,
472
+ host: parsedLocation.host,
473
+ hostname: parsedLocation.hostname,
474
+ pathname: parsedLocation.pathname,
475
+ search: parsedLocation.search,
476
+ hash: parsedLocation.hash,
477
+ };
478
+
479
+ const sandbox = {};
480
+ sandbox.window = sandbox;
481
+ sandbox.self = sandbox;
482
+ sandbox.globalThis = sandbox;
483
+ sandbox.navigator = watch(navigator, 'navigator');
484
+ sandbox.screen = watch(screenObj, 'screen');
485
+ sandbox.document = watch(documentObj, 'document');
486
+ sandbox.location = watch(locationObj, 'location');
487
+ sandbox.localStorage = {
488
+ getItem(k) { touched.push(`localStorage.getItem:${k}`); return store[k] ?? null; },
489
+ setItem(k, v) { touched.push(`localStorage.setItem:${k}`); store[k] = String(v); },
490
+ removeItem(k) { delete store[k]; },
491
+ };
492
+ sandbox.sessionStorage = sandbox.localStorage;
493
+ sandbox.console = { log() {}, warn() {}, error() {}, debug() {}, info() {} };
494
+ sandbox.performance = {
495
+ now: () => 1234.5,
496
+ timeOrigin: 1786867000000,
497
+ getEntriesByType(type) {
498
+ if (String(type) !== 'navigation') return [];
499
+ return [{
500
+ name: requestedHref, entryType: 'navigation', startTime: 0,
501
+ duration: 292.39999997615814, initiatorType: 'navigation',
502
+ nextHopProtocol: 'http/1.1',
503
+ }];
504
+ },
505
+ };
506
+ sandbox.chrome = { runtime: {} };
507
+ sandbox.history = {
508
+ length: Number(process.env.KS_HISTORY_LENGTH || 5),
509
+ state: { key: '208.700' },
510
+ scrollRestoration: 'manual',
511
+ back() {}, forward() {}, go() {}, pushState() {}, replaceState() {},
512
+ };
513
+ try { Object.defineProperty(sandbox.history, Symbol.toStringTag, {
514
+ value: 'History', configurable: true,
515
+ }); } catch (_) {}
516
+ sandbox.matchMedia = (query) => {
517
+ const media = String(query || '');
518
+ const result = {
519
+ media,
520
+ matches: media !== '(-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2), (min-resolution: 192dpi)',
521
+ onchange: null,
522
+ addListener() {}, removeListener() {},
523
+ };
524
+ try { Object.defineProperty(result, Symbol.toStringTag, {
525
+ value: 'MediaQueryList', configurable: true,
526
+ }); } catch (_) {}
527
+ return result;
528
+ };
529
+ function Element() {}
530
+ function Window() {}
531
+ function MouseEvent() {}
532
+ function XPathResult() {}
533
+ function RTCPeerConnection() {}
534
+ for (const [ctor, tag] of [
535
+ [Element, 'Element'], [Window, 'Window'], [MouseEvent, 'MouseEvent'],
536
+ [XPathResult, 'XPathResult'], [RTCPeerConnection, 'RTCPeerConnection'],
537
+ ]) {
538
+ try { Object.defineProperty(ctor.prototype, Symbol.toStringTag, {
539
+ value: tag, configurable: true,
540
+ }); } catch (_) {}
541
+ }
542
+ function Image(width, height) {
543
+ const image = documentObj.createElement('img');
544
+ if (width !== undefined) image.width = Number(width);
545
+ if (height !== undefined) image.height = Number(height);
546
+ return image;
547
+ }
548
+ const indexedDB = {};
549
+ Object.defineProperty(indexedDB, Symbol.toStringTag, {
550
+ value: 'IDBFactory', configurable: true,
551
+ });
552
+ const external = {};
553
+ Object.defineProperty(external, Symbol.toStringTag, {
554
+ value: 'External', configurable: true,
555
+ });
556
+ sandbox.Element = Element;
557
+ sandbox.Image = Image;
558
+ sandbox.MouseEvent = MouseEvent;
559
+ sandbox.Navigator = Navigator;
560
+ sandbox.Screen = Screen;
561
+ sandbox.Window = Window;
562
+ sandbox.XPathResult = XPathResult;
563
+ sandbox.webkitRTCPeerConnection = RTCPeerConnection;
564
+ sandbox.indexedDB = indexedDB;
565
+ sandbox.external = external;
566
+ sandbox.top = sandbox;
567
+ sandbox.WebGLRenderingContext = WebGLRenderingContext;
568
+ sandbox.devicePixelRatio = 1;
569
+ sandbox.innerWidth = 1920;
570
+ sandbox.innerHeight = 947;
571
+ sandbox.outerWidth = 1920;
572
+ sandbox.outerHeight = 1032;
573
+ sandbox.screenX = 0;
574
+ sandbox.screenY = 0;
575
+ sandbox.setTimeout = (fn) => { if (typeof fn === 'function') fn(); return 0; };
576
+ sandbox.setInterval = () => 0;
577
+ sandbox.clearTimeout = () => {};
578
+ sandbox.clearInterval = () => {};
579
+ sandbox.addEventListener = () => {};
580
+ sandbox.atob = (s) => Buffer.from(s, 'base64').toString('binary');
581
+ sandbox.btoa = (s) => Buffer.from(s, 'binary').toString('base64');
582
+ sandbox.__kwfCaught = (err) => {
583
+ caughtErrors.push({
584
+ name: String(err && err.name || ''),
585
+ message: String(err && err.message || err || ''),
586
+ stack: String(err && err.stack || '').split('\n').slice(0, 4).join('\n'),
587
+ recentTouches: touched.slice(-18),
588
+ recentVmSteps: recentVmSteps.slice(-12),
589
+ });
590
+ };
591
+ sandbox.__kwfStep = (pc, instruction, stack) => {
592
+ const unwrap = (wrapped) => {
593
+ if (!wrapped || typeof wrapped !== 'object') return wrapped;
594
+ try {
595
+ return wrapped._sabo_85623
596
+ ? wrapped._sabo_83517[wrapped._sabo_8226a]
597
+ : wrapped._sabo_8961;
598
+ } catch (_) { return '[unreadable]'; }
599
+ };
600
+ const preview = (value) => {
601
+ if (value === undefined) return { type: 'undefined' };
602
+ if (value === null) return { type: 'null' };
603
+ const type = typeof value;
604
+ if (type === 'string') return { type, length: value.length, value: value.slice(0, 80) };
605
+ if (type === 'number' || type === 'boolean') return { type, value };
606
+ if (type === 'function') return { type, name: String(value.name || '') };
607
+ let tag = '';
608
+ let keys = [];
609
+ try { tag = Object.prototype.toString.call(value); } catch (_) {}
610
+ try { keys = Object.keys(value).slice(0, 12); } catch (_) {}
611
+ return { type, tag, keys };
612
+ };
613
+ recentVmSteps.push({
614
+ pc: Number(pc),
615
+ instruction: Array.isArray(instruction) ? instruction.slice() : instruction,
616
+ stackDepth: Array.isArray(stack) ? stack.length : -1,
617
+ stackTop: Array.isArray(stack) ? stack.slice(-5).map((item) => preview(unwrap(item))) : [],
618
+ });
619
+ if (recentVmSteps.length > 16) recentVmSteps.shift();
620
+ };
621
+ sandbox.__kwfBadRef = (key) => {
622
+ badReferences.push({ key: String(key), recentVmSteps: recentVmSteps.slice(-12), recentTouches: touched.slice(-18) });
623
+ };
624
+ sandbox.__kwfRefBase = (base, key) => {
625
+ let value;
626
+ try { value = base == null ? undefined : base[key]; } catch (_) { return base; }
627
+ let tag = '';
628
+ try { tag = Object.prototype.toString.call(base); } catch (_) {}
629
+ propertyReads.push({
630
+ key: String(key),
631
+ baseType: base === null ? 'null' : typeof base,
632
+ baseTag: tag,
633
+ valueType: value === null ? 'null' : typeof value,
634
+ valueLength: typeof value === 'string' ? value.length : undefined,
635
+ equalsDid: value === process.env.KS_DID,
636
+ });
637
+ if (propertyReads.length > 80) propertyReads.shift();
638
+ if (value === undefined) {
639
+ let keys = [];
640
+ try { keys = Object.keys(base).slice(0, 20); } catch (_) {}
641
+ missingProperties.push({
642
+ key: String(key), baseType: base === null ? 'null' : typeof base,
643
+ baseTag: tag, baseKeys: keys, recentTouches: touched.slice(-12),
644
+ });
645
+ if (missingProperties.length > 500) missingProperties.shift();
646
+ }
647
+ return base;
648
+ };
649
+ sandbox.__kwfAssigned = (base, key, value) => {
650
+ const name = String(key);
651
+ if (/^k(?:1|2|34|60)$/.test(name)) {
652
+ propertyAssignments.push({
653
+ key: name,
654
+ valueType: value === null ? 'null' : typeof value,
655
+ valueLength: typeof value === 'string' ? value.length : undefined,
656
+ equalsDid: name === 'k1' ? value === process.env.KS_DID : undefined,
657
+ recentTouches: touched.slice(-20),
658
+ recentVmSteps: recentVmSteps.slice(-12),
659
+ recentPropertyReads: propertyReads.slice(-30),
660
+ });
661
+ }
662
+ return value;
663
+ };
664
+
665
+ const ctx = vm.createContext(sandbox);
666
+ if (process.env.KS_KWF_TRACE_JSON === '1') {
667
+ sandbox.__kwfJsonCapture = (value) => {
668
+ let serialized = '';
669
+ let keys = [];
670
+ let fieldLengths = {};
671
+ try {
672
+ serialized = JSON.stringify(value);
673
+ if (value && typeof value === 'object') {
674
+ keys = Object.keys(value);
675
+ for (const key of keys) {
676
+ try { fieldLengths[key] = JSON.stringify(value[key]).length; } catch (_) {}
677
+ }
678
+ }
679
+ } catch (_) {}
680
+ jsonCalls.push({
681
+ length: serialized.length, keys, fieldLengths,
682
+ identityChecks: value && typeof value === 'object' ? {
683
+ k1EqualsDid: value.k1 === process.env.KS_DID,
684
+ k2EqualsCpProduct: value.k2 === 'onvideo-cp',
685
+ k1Type: typeof value.k1,
686
+ k2Type: typeof value.k2,
687
+ } : {},
688
+ });
689
+ };
690
+ vm.runInContext(`
691
+ (() => {
692
+ const rawStringify = JSON.stringify;
693
+ JSON.stringify = function(value, ...args) {
694
+ try { __kwfJsonCapture(value); } catch (_) {}
695
+ return rawStringify.call(JSON, value, ...args);
696
+ };
697
+ })();
698
+ `, ctx);
699
+ }
700
+ if (process.env.KS_KWF_TRACE_COOKIE === '1') {
701
+ sandbox.__kwfCookieRegexCapture = (source, input, result) => {
702
+ cookieRegexCalls.push({
703
+ source: String(source),
704
+ inputLength: String(input || '').length,
705
+ matched: !!result,
706
+ groupLengths: result ? Array.from(result).map((item) => String(item == null ? '' : item).length) : [],
707
+ });
708
+ };
709
+ vm.runInContext(`
710
+ (() => {
711
+ const rawExec = RegExp.prototype.exec;
712
+ RegExp.prototype.exec = function(input) {
713
+ const result = rawExec.call(this, input);
714
+ try {
715
+ if (String(input).includes('did=')) __kwfCookieRegexCapture(this.source, input, result);
716
+ } catch (_) {}
717
+ return result;
718
+ };
719
+ })();
720
+ `, ctx);
721
+ }
722
+ let src = fs.readFileSync(SCRIPT, 'utf8');
723
+ if (process.env.KS_KWF_TRACE_ERRORS === '1') {
724
+ const catchNeedle = '} catch (e) {';
725
+ const catchReplacement = '} catch (e) { try { __kwfCaught(e); } catch (_) {} ';
726
+ if (src.includes(catchNeedle)) src = src.replace(catchNeedle, catchReplacement);
727
+ const stepNeedle = 'var _sabo_2618c = _sabo_9d187[x[_sabo_29074]];_sabo_9e222 = _sabo_2618c';
728
+ const stepReplacement = 'var _sabo_2618c = _sabo_9d187[x[_sabo_29074]];try { __kwfStep(_sabo_9e222, x, _sabo_16c96); } catch (_) {} _sabo_9e222 = _sabo_2618c';
729
+ if (src.includes(stepNeedle)) src = src.replace(stepNeedle, stepReplacement);
730
+ const topStepNeedle = 'var _sabo_2618c = _sabo_9d187[_sabo_c4071[_sabo_29074]];_sabo_e4807 = _sabo_2618c';
731
+ const topStepReplacement = 'var _sabo_2618c = _sabo_9d187[_sabo_c4071[_sabo_29074]];try { __kwfStep(_sabo_e4807, _sabo_c4071, _sabo_16c96); } catch (_) {} _sabo_e4807 = _sabo_2618c';
732
+ if (src.includes(topStepNeedle)) src = src.replace(topStepNeedle, topStepReplacement);
733
+ const unwrapNeedle = '_sabo_aa8a7 = function (_sabo_7d331) {return _sabo_7d331._sabo_85623 ?';
734
+ const unwrapReplacement = '_sabo_aa8a7 = function (_sabo_7d331) {if (_sabo_7d331 && _sabo_7d331._sabo_85623 && _sabo_7d331._sabo_83517 == null) { try { __kwfBadRef(_sabo_7d331._sabo_8226a); } catch (_) {} } return _sabo_7d331._sabo_85623 ?';
735
+ if (src.includes(unwrapNeedle)) src = src.replace(unwrapNeedle, unwrapReplacement);
736
+ const refNeedle = '_sabo_e0404(0, _sabo_aa8a7(_sabo_40893(p0, p1)), _sabo_eb693(p2, p3), 1);return ++p4;';
737
+ const refReplacement = '_sabo_e0404(0, __kwfRefBase(_sabo_aa8a7(_sabo_40893(p0, p1)), _sabo_eb693(p2, p3)), _sabo_eb693(p2, p3), 1);return ++p4;';
738
+ if (src.includes(refNeedle)) src = src.replace(refNeedle, refReplacement);
739
+ const setNeedle = '_sabo_eb003._sabo_83517[_sabo_eb003._sabo_8226a] = _sabo_0dbe7';
740
+ const setReplacement = '_sabo_eb003._sabo_83517[_sabo_eb003._sabo_8226a] = __kwfAssigned(_sabo_eb003._sabo_83517, _sabo_eb003._sabo_8226a, _sabo_0dbe7)';
741
+ src = src.split(setNeedle).join(setReplacement);
742
+ }
743
+ try {
744
+ vm.runInContext(src, ctx, { timeout: 20000 });
745
+ } catch (err) {
746
+ console.error('脚本执行出错:', err && err.message);
747
+ console.error((err && err.stack || '').split('\n').slice(0, 6).join('\n'));
748
+ process.exit(1);
749
+ }
750
+
751
+ const quiet = process.argv[2] === 'quiet';
752
+ const jsonMode = process.argv[2] === '--json';
753
+ const kwpsec = sandbox.kwpsec;
754
+ if (!kwpsec) {
755
+ console.error('脚本跑完了但没挂出 window.kwpsec;已访问的属性:');
756
+ console.error([...new Set(touched)].slice(0, 60).join('\n'));
757
+ process.exit(2);
758
+ }
759
+
760
+ let out;
761
+ try {
762
+ const reportMode = process.env.KS_KWF_REPORT_MODE;
763
+ out = reportMode === undefined ? kwpsec.getData() : kwpsec.getData(Number(reportMode));
764
+ } catch (err) {
765
+ console.error('getData() 出错:', err && err.message);
766
+ process.exit(3);
767
+ }
768
+
769
+ if (jsonMode) {
770
+ console.log(JSON.stringify({
771
+ value: out, kwfv1: store.kwfv1, kwfcv1: store.kwfcv1,
772
+ caughtErrors: process.env.KS_KWF_TRACE_ERRORS === '1' ? caughtErrors : undefined,
773
+ badReferences: process.env.KS_KWF_TRACE_ERRORS === '1' ? badReferences : undefined,
774
+ missingProperties: process.env.KS_KWF_TRACE_ERRORS === '1' ? missingProperties : undefined,
775
+ jsonCalls: process.env.KS_KWF_TRACE_JSON === '1' ? jsonCalls : undefined,
776
+ cookieRegexCalls: process.env.KS_KWF_TRACE_COOKIE === '1' ? cookieRegexCalls : undefined,
777
+ cookieWrites: process.env.KS_KWF_TRACE_COOKIE === '1' ? cookieWrites : undefined,
778
+ propertyAssignments: process.env.KS_KWF_TRACE_ERRORS === '1' ? propertyAssignments : undefined,
779
+ }));
780
+ } else if (quiet) {
781
+ console.log(out);
782
+ } else {
783
+ console.log('=== window.kwpsec 的形态 ===');
784
+ console.log(' 键:', Object.keys(kwpsec).join(', ') || '(无自有键)');
785
+ console.log(' 方法:', Object.getOwnPropertyNames(Object.getPrototypeOf(kwpsec) || {})
786
+ .join(', ') || '(直接挂在对象上)');
787
+ console.log('\n=== getData() 输出 ===');
788
+ console.log(` 长度 ${String(out).length}`);
789
+ console.log(` 值 ${out}`);
790
+ console.log(` 字符集 ${[...new Set(String(out))].sort().join('')}`);
791
+ console.log('\n=== 写进 localStorage 的东西 ===');
792
+ console.log(' ' + JSON.stringify(store, null, 2).replace(/\n/g, '\n '));
793
+ console.log('\n=== 访问过的环境属性(去重)===');
794
+ for (const k of [...new Set(touched)]) console.log(' ' + k);
795
+ console.log('\n=== 连续两次调用是否相同(看有没有随机/时间成分)===');
796
+ const a = kwpsec.getData();
797
+ const b = kwpsec.getData();
798
+ console.log(` 两次等长: ${a.length === b.length} 逐字符相同: ${a === b}`);
799
+ }