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,225 @@
1
+ /**
2
+ * XHS Web 共用签名算法入口:mns.js + xs_common.js。
3
+ * Creator 0101 可显式传入服务端 DS 程序,在隔离 VM 中调用其 _dsf;
4
+ * 其余签名路径不依赖浏览器宿主。
5
+ * seccore_signv2 兼容版:内部对 (url + JSON.stringify(data)) 求 md5 作为 u 与 md5(url) 作为 p,
6
+ * 与浏览器 window.mnsv2 完全一致(逐字节对齐)。
7
+ *
8
+ * CLI: node sign.js @input.json ({api,data,cookie,version?,now?,seq?,tier?})
9
+ */
10
+ 'use strict';
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const crypto = require('crypto');
14
+ const vm = require('vm');
15
+ const { signTier, hexToBytes } = require('./mns.js');
16
+ const { xsCommon } = require('./xs_common.js');
17
+
18
+ const ALPHABET_XS = 'ZmserbBoHQtNP+wOcza/LpngG8yJq42KWYj0DSfdikx3VT16IlUAFM97hECvuRX5';
19
+ function encodeUtf8(e) {
20
+ const r = encodeURIComponent(e), a = [];
21
+ for (let i = 0; i < r.length; i++) { const c = r.charAt(i); if (c === '%') { a.push(parseInt(r.charAt(i + 1) + r.charAt(i + 2), 16)); i += 2; } else a.push(c.charCodeAt(0)); }
22
+ return a;
23
+ }
24
+ function b64XS(e) {
25
+ const a = e.length, c = a % 3, d = []; let u = 0; const l = a - c, s = 16383;
26
+ for (u = 0; u < l; u += s) { const end = u + s > l ? l : u + s; for (let k = u; k < end; k += 3) { const t = (e[k] << 16) + ((k + 1 < end ? e[k + 1] : 0) << 8) + (k + 2 < end ? e[k + 2] : 0); d.push(ALPHABET_XS[(t >> 18) & 63], ALPHABET_XS[(t >> 12) & 63], ALPHABET_XS[(t >> 6) & 63], ALPHABET_XS[t & 63]); } }
27
+ if (c === 1) { const t = e[a - 1]; d.push(ALPHABET_XS[t >> 2] + ALPHABET_XS[(t << 4) & 63] + '=='); }
28
+ else if (c === 2) { const t = (e[a - 2] << 8) + e[a - 1]; d.push(ALPHABET_XS[t >> 10] + ALPHABET_XS[(t >> 4) & 63] + ALPHABET_XS[(t << 2) & 63] + '='); }
29
+ return d.join('');
30
+ }
31
+
32
+ function parseWebSsk(value, appId) {
33
+ let storage = value;
34
+ if (typeof storage === 'string') {
35
+ if (!storage) return null;
36
+ try { storage = JSON.parse(storage); } catch (_) { return null; }
37
+ }
38
+ if (!storage || typeof storage !== 'object') return null;
39
+ const encoded = storage[appId];
40
+ if (typeof encoded !== 'string' || !encoded) return null;
41
+ const raw = Buffer.from(encoded, 'base64');
42
+ return raw.length >= 32 ? raw : null;
43
+ }
44
+
45
+ function buildEncSskSign(md5FullBytes, webSsk, appId, options = {}) {
46
+ const secret = parseWebSsk(webSsk, appId);
47
+ if (!secret) return null;
48
+ const nonce = Buffer.allocUnsafe(4);
49
+ const randomValue = options.sskRandom != null
50
+ ? (Number(options.sskRandom) >>> 0)
51
+ : crypto.randomBytes(4).readUInt32LE(0);
52
+ const timestamp = options.sskTimestamp != null
53
+ ? (Number(options.sskTimestamp) >>> 0)
54
+ : (Date.now() >>> 0);
55
+ nonce.writeUInt32LE((timestamp + randomValue) >>> 0, 0);
56
+ const digest = crypto.createHash('sha1').update(Buffer.concat([secret, nonce])).digest();
57
+ const encSsk = Buffer.concat([nonce, digest, secret.subarray(32)]);
58
+ const encSskSign = crypto.createHash('sha1')
59
+ .update(Buffer.concat([Buffer.from(md5FullBytes), encSsk]))
60
+ .digest('base64');
61
+ return {
62
+ encSskSign: { [appId]: encSskSign },
63
+ encSsk: { [appId]: encSsk.toString('base64') },
64
+ };
65
+ }
66
+
67
+ function encodeXs(x3, x4Value, options = {}) {
68
+ // Browser's seccore_signv2 always sets x4 = (data ? typeof data : '')
69
+ // For empty data (GET), x4 = ''; for object data, x4 = 'object'; for string data, x4 = 'string'
70
+ const signObj = {
71
+ x0: String(options.signVersion || '4.4.3'),
72
+ x1: String(options.appId || 'xhs-pc-web'),
73
+ x2: String(options.platform || 'Windows'),
74
+ x3,
75
+ x4: x4Value,
76
+ };
77
+ // Current PC envelopes append x5 and, after webSsk activation, x6/x7.
78
+ // Creator 4.3.6 envelopes stop at x4.
79
+ if (options.x5 != null) signObj.x5 = String(options.x5);
80
+ if (options.x6 != null) signObj.x6 = options.x6;
81
+ if (options.x7 != null) signObj.x7 = options.x7;
82
+ return 'XYS_' + b64XS(encodeUtf8(JSON.stringify(signObj)));
83
+ }
84
+
85
+ function runDsfProgram(program, inputBytes, timeoutMs = 10000) {
86
+ const source = String(program || '');
87
+ if (!source || (!source.includes('__$c') && !source.includes('_dsf'))) {
88
+ throw new Error('Creator DS program is missing or invalid');
89
+ }
90
+ const sandbox = {};
91
+ sandbox.global = sandbox;
92
+ vm.runInNewContext(source, sandbox, { timeout: Number(timeoutMs) });
93
+ if (typeof sandbox._dsf !== 'function') {
94
+ throw new Error('Creator DS program did not export _dsf');
95
+ }
96
+ const output = Array.from(sandbox._dsf(null, Array.from(inputBytes || [])) || []);
97
+ if (
98
+ output.length !== 16
99
+ || output.some(byte => !Number.isInteger(byte) || byte < 0 || byte > 255)
100
+ ) {
101
+ throw new Error('Creator _dsf output must be 16 bytes');
102
+ }
103
+ return output;
104
+ }
105
+
106
+ function signFull(input) {
107
+ input = input || {};
108
+ // 生产模式:cookie 必须从 CLI 传入;不再读磁盘兜底
109
+ if (!input.cookie) throw new Error('cookie required (must be passed via CLI JSON)');
110
+ const cookie = input.cookie;
111
+ const cookieMap = Object.fromEntries(cookie.split(/;\s*/).map((part) => {
112
+ const offset = part.indexOf('=');
113
+ return offset < 0 ? [part, ''] : [part.slice(0, offset), part.slice(offset + 1)];
114
+ }));
115
+ const a1 = (cookie.match(/a1=([^;]*)/) || [])[1] || '';
116
+ if (!a1) throw new Error('cookie a1 required');
117
+ const now = input.now != null ? Number(input.now) : Date.now();
118
+ const version = input.version != null ? (input.version >>> 0) : (Math.floor(Math.random() * 0x100000000) >>> 0);
119
+ const loadts = input.loadts != null ? Number(input.loadts) : Number(cookieMap.loadts);
120
+ if (!Number.isFinite(loadts)) throw new Error('loadts required (input.loadts or cookie loadts)');
121
+ if (input.seq == null) throw new Error('seq required from PcDeviceProfile session state');
122
+ if (input.envConst == null) throw new Error('envConst required from PcDeviceProfile stage state');
123
+ if (!Array.isArray(input.envFpTail) || input.envFpTail.length !== 14) {
124
+ throw new Error('envFpTail required from PcDeviceProfile stage state (14 bytes)');
125
+ }
126
+ // seccore_signv2 receives `data` as JS object or string (not stringified for u calc)
127
+ // c = url + JSON.stringify(data) for objects, or url + data for strings
128
+ const dataIn = input.data;
129
+ const dataStr = dataIn == null ? '' : (typeof dataIn === 'object' ? JSON.stringify(dataIn) : String(dataIn));
130
+ const c = String(input.api) + dataStr;
131
+ // x4 label per browser: object data → 'object', string data (non-empty) → 'string', else ''
132
+ const x4Label = dataIn == null || dataIn === '' ? '' : (typeof dataIn === 'object' ? 'object' : 'string');
133
+ const md5Full = hexToBytes(crypto.createHash('md5').update(c).digest('hex'));
134
+ const md5Url = hexToBytes(crypto.createHash('md5').update(String(input.api)).digest('hex'));
135
+ const fullLen = Buffer.byteLength(c, 'utf8');
136
+ const tier = input.tier || '0301';
137
+ const deviceTag = String(input.deviceTag || input.dsn || 'a3');
138
+ let dsSigBytes = input.dsSigBytes;
139
+ // Creator's Python adapter historically called this context field
140
+ // ``dsProgram`` while the standalone signer used ``dsfProgram``. Accept
141
+ // both spellings so the server-issued _dsf program is actually executed
142
+ // for mns0101/a1 requests instead of silently falling back to the static
143
+ // placeholder hash.
144
+ const dsfProgram = input.dsfProgram || input.dsProgram;
145
+ if (deviceTag !== 'nop' && !dsSigBytes && dsfProgram) {
146
+ const dsfInput = [];
147
+ let timestamp = BigInt(now);
148
+ for (let index = 0; index < 8; index++) {
149
+ dsfInput.push(Number(timestamp & 255n));
150
+ timestamp >>= 8n;
151
+ }
152
+ dsfInput.push(...md5Url);
153
+ dsSigBytes = runDsfProgram(dsfProgram, dsfInput, input.dsfTimeoutMs);
154
+ }
155
+ const x3 = signTier({
156
+ api: input.api,
157
+ data: dataStr,
158
+ a1,
159
+ appId: String(input.appId || 'xhs-pc-web'),
160
+ deviceTag,
161
+ dsSigBytes,
162
+ version,
163
+ ts: now,
164
+ loadts,
165
+ seq: input.seq,
166
+ envConst: input.envConst,
167
+ envFpTail: input.envFpTail,
168
+ md5FullBytes: md5Full,
169
+ md5UrlBytes: md5Url,
170
+ fullLen,
171
+ }, tier);
172
+ const xsOptions = { ...input };
173
+ const appId = String(input.appId || 'xhs-pc-web');
174
+ if (appId === 'xhs-pc-web') {
175
+ xsOptions.x5 = Buffer.from(md5Full).toString('hex');
176
+ const ssk = buildEncSskSign(md5Full, input.webSsk, appId, input);
177
+ if (ssk) {
178
+ xsOptions.x6 = ssk.encSskSign;
179
+ xsOptions.x7 = ssk.encSsk;
180
+ } else {
181
+ delete xsOptions.x6;
182
+ delete xsOptions.x7;
183
+ }
184
+ } else {
185
+ delete xsOptions.x5;
186
+ delete xsOptions.x6;
187
+ delete xsOptions.x7;
188
+ }
189
+ const xs = encodeXs(x3, x4Label, xsOptions);
190
+ // Browser builds MNS first, then samples Date.now() again for X-t.
191
+ const xt = input.xt != null ? String(input.xt) : String(Date.now());
192
+ const out = { x3, xs, xt, len: x3.length, prefix: x3.slice(0, 12), tier, pure: true };
193
+ // X-S-Common 纯算(需 b1 + dslPair)
194
+ const b1 = input.b1 == null ? '' : String(input.b1);
195
+ const dslPairRaw = input.dslPair == null ? input.dsl_pair : input.dslPair;
196
+ const dslPair = dslPairRaw == null ? '' : String(dslPairRaw);
197
+ if (dslPair) {
198
+ const webBuild = String(input.webBuild || cookieMap.webBuild || '');
199
+ if (!webBuild) throw new Error('webBuild required (input.webBuild or cookie webBuild)');
200
+ out.xs_common = xsCommon(a1, xt, xs, dslPair, b1, {
201
+ b1b1: input.b1b1,
202
+ signVersion: input.signVersion,
203
+ platform: input.platform,
204
+ appId: input.appId,
205
+ webBuild,
206
+ signCount: input.signCount,
207
+ });
208
+ }
209
+ return out;
210
+ }
211
+
212
+ function main() {
213
+ const arg = process.argv[2];
214
+ const raw = arg && arg.startsWith('@') ? fs.readFileSync(arg.slice(1), 'utf8') : arg;
215
+ const input = JSON.parse(raw);
216
+ process.stdout.write(JSON.stringify(signFull(input)) + '\n');
217
+ }
218
+
219
+ if (require.main === module) main();
220
+
221
+ module.exports = {
222
+ signFull, encodeXs, encodeUtf8, b64XS, runDsfProgram,
223
+ parseWebSsk, buildEncSskSign, main,
224
+ };
225
+
@@ -0,0 +1,220 @@
1
+ 'use strict';
2
+
3
+ const env = require('./websectiga_env');
4
+ const _process = process;
5
+ const _Buffer = Buffer;
6
+ const crypto = require('crypto');
7
+ const fs = require('fs');
8
+ const vm = require('vm');
9
+
10
+ const inputText = fs.readFileSync(0, 'utf8');
11
+ const input = JSON.parse(inputText || '{}');
12
+ const sourceCode = String(input.code || '');
13
+ if (sourceCode.length < 1000 || !/\w+\(\)\(window,\{/.test(sourceCode)) {
14
+ throw new Error('invalid scripting JSVMP code');
15
+ }
16
+ const UA = String(input.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36');
17
+ const PLATFORM = String(input.platform || 'Win32');
18
+ const PAGE_URL = String(input.pageUrl || 'https://www.xiaohongshu.com/explore?channel_id=homefeed_recommend');
19
+
20
+ function nativeInstance(name) {
21
+ const [Ctor, instance] = env.getNativeProto(name, {});
22
+ // Browser host objects expose their brand through the prototype, while
23
+ // Object.getOwnPropertyNames(instance) is empty for Navigator/Document.
24
+ delete instance.toString;
25
+ delete instance[Symbol.toStringTag];
26
+ Object.defineProperty(Ctor.prototype, Symbol.toStringTag, {
27
+ value: name,
28
+ configurable: true,
29
+ });
30
+ return [Ctor, instance];
31
+ }
32
+
33
+ function defineReadonly(proto, values) {
34
+ for (const [key, value] of Object.entries(values)) {
35
+ Object.defineProperty(proto, key, {
36
+ get: env.setFuncNative(function get() { return value; }, `get ${key}`, 0),
37
+ enumerable: true,
38
+ configurable: true,
39
+ });
40
+ }
41
+ }
42
+
43
+ const [Window, fakeWindow] = nativeInstance('Window');
44
+ const [Navigator, fakeNavigator] = nativeInstance('Navigator');
45
+ defineReadonly(Navigator.prototype, {
46
+ appCodeName: 'Mozilla',
47
+ appName: 'Netscape',
48
+ appVersion: UA.slice(8),
49
+ cookieEnabled: true,
50
+ hardwareConcurrency: 8,
51
+ language: 'zh-CN',
52
+ languages: Object.freeze(['zh-CN', 'zh', 'en']),
53
+ maxTouchPoints: 0,
54
+ platform: PLATFORM,
55
+ product: 'Gecko',
56
+ productSub: '20030107',
57
+ userAgent: UA,
58
+ vendor: 'Google Inc.',
59
+ webdriver: false,
60
+ });
61
+
62
+ const [Location, fakeLocation] = nativeInstance('Location');
63
+ const parsedUrl = new URL(PAGE_URL);
64
+ defineReadonly(Location.prototype, {
65
+ href: PAGE_URL,
66
+ protocol: parsedUrl.protocol,
67
+ host: parsedUrl.host,
68
+ hostname: parsedUrl.hostname,
69
+ port: parsedUrl.port,
70
+ pathname: parsedUrl.pathname,
71
+ search: parsedUrl.search,
72
+ hash: parsedUrl.hash,
73
+ origin: parsedUrl.origin,
74
+ });
75
+ Location.prototype.toString = env.setFuncNative(function toString() { return PAGE_URL; }, 'toString', 0);
76
+
77
+ const [HTMLDivElement] = nativeInstance('HTMLDivElement');
78
+ let appendCalls = 0;
79
+ let appendSelfCalls = 0;
80
+ HTMLDivElement.prototype.getAttribute = env.setFuncNative(function getAttribute() { return null; }, 'getAttribute', 1);
81
+ HTMLDivElement.prototype.setAttribute = env.setFuncNative(function setAttribute() {}, 'setAttribute', 2);
82
+ HTMLDivElement.prototype.appendChild = env.setFuncNative(function appendChild(child) {
83
+ appendCalls += 1;
84
+ if (child === this) appendSelfCalls += 1;
85
+ throw new TypeError('Illegal invocation');
86
+ }, 'appendChild', 1);
87
+ Object.defineProperty(HTMLDivElement.prototype, 'style', {
88
+ get: env.setFuncNative(function get() { return {}; }, 'get style', 0),
89
+ configurable: true,
90
+ });
91
+
92
+ const [HTMLHtmlElement, fakeDocumentElement] = nativeInstance('HTMLHtmlElement');
93
+ HTMLHtmlElement.prototype.getAttribute = env.setFuncNative(function getAttribute() { return null; }, 'getAttribute', 1);
94
+
95
+ const [HTMLBodyElement, fakeBody] = nativeInstance('HTMLBodyElement');
96
+ HTMLBodyElement.prototype.appendChild = env.setFuncNative(function appendChild(child) { return child; }, 'appendChild', 1);
97
+
98
+ const [HTMLDocument, fakeDocument] = nativeInstance('HTMLDocument');
99
+ HTMLDocument.prototype.createElement = env.setFuncNative(function createElement(tag) {
100
+ if (String(tag).toLowerCase() === 'div') return Object.create(HTMLDivElement.prototype);
101
+ return Object.create(HTMLDivElement.prototype);
102
+ }, 'createElement', 1);
103
+ HTMLDocument.prototype.addEventListener = env.setFuncNative(function addEventListener() {}, 'addEventListener', 2);
104
+ HTMLDocument.prototype.removeEventListener = env.setFuncNative(function removeEventListener() {}, 'removeEventListener', 2);
105
+ defineReadonly(HTMLDocument.prototype, {
106
+ body: fakeBody,
107
+ documentElement: fakeDocumentElement,
108
+ domain: 'xiaohongshu.com',
109
+ hidden: false,
110
+ referrer: '',
111
+ title: '',
112
+ URL: PAGE_URL,
113
+ visibilityState: 'visible',
114
+ });
115
+
116
+ const [External, fakeExternal] = nativeInstance('External');
117
+ External.prototype.toString = env.setFuncNative(function toString() { return '[object External]'; }, 'toString', 0);
118
+
119
+ const [HTMLImageElement] = nativeInstance('HTMLImageElement');
120
+ for (const key of [
121
+ 'alt', 'src', 'srcset', 'sizes', 'crossOrigin', 'useMap', 'isMap',
122
+ 'width', 'height', 'naturalWidth', 'naturalHeight', 'complete',
123
+ 'currentSrc', 'referrerPolicy',
124
+ ]) {
125
+ Object.defineProperty(HTMLImageElement.prototype, key, {
126
+ get: env.setFuncNative(function get() { return ''; }, `get ${key}`, 0),
127
+ set: env.setFuncNative(function set() {}, `set ${key}`, 1),
128
+ configurable: true,
129
+ enumerable: true,
130
+ });
131
+ }
132
+ const Image = env.setFuncNative(function Image() {
133
+ return Object.create(HTMLImageElement.prototype);
134
+ }, 'Image', 0);
135
+ Image.prototype = HTMLImageElement.prototype;
136
+
137
+ const [Screen, fakeScreen] = nativeInstance('Screen');
138
+ defineReadonly(Screen.prototype, {
139
+ width: 1920,
140
+ height: 1080,
141
+ availWidth: 1920,
142
+ availHeight: 1040,
143
+ colorDepth: 24,
144
+ pixelDepth: 24,
145
+ });
146
+
147
+ const [History, fakeHistory] = nativeInstance('History');
148
+ defineReadonly(History.prototype, { length: 1, state: null });
149
+
150
+ const nativeAtob = env.setFuncNative(function atob(value) {
151
+ return _Buffer.from(String(value), 'base64').toString('binary');
152
+ }, 'atob', 1);
153
+ const nativeBtoa = env.setFuncNative(function btoa(value) {
154
+ return _Buffer.from(String(value), 'binary').toString('base64');
155
+ }, 'btoa', 1);
156
+
157
+ Object.assign(fakeWindow, {
158
+ Array,
159
+ Boolean,
160
+ Date,
161
+ Function,
162
+ Image,
163
+ JSON,
164
+ Location,
165
+ Math,
166
+ Navigator,
167
+ Number,
168
+ Object,
169
+ RegExp,
170
+ String,
171
+ Window,
172
+ atob: nativeAtob,
173
+ btoa: nativeBtoa,
174
+ console,
175
+ document: fakeDocument,
176
+ escape,
177
+ external: fakeExternal,
178
+ frames: null,
179
+ history: fakeHistory,
180
+ location: fakeLocation,
181
+ navigator: fakeNavigator,
182
+ screen: fakeScreen,
183
+ encodeURIComponent,
184
+ setTimeout,
185
+ clearTimeout,
186
+ });
187
+ fakeWindow.window = fakeWindow;
188
+ fakeWindow.self = fakeWindow;
189
+ fakeWindow.top = fakeWindow;
190
+ fakeWindow.parent = fakeWindow;
191
+ fakeWindow.frames = [fakeWindow];
192
+
193
+ let result = '';
194
+ fakeWindow.seccallback = env.setFuncNative(function seccallback(value) {
195
+ result = String(value || '');
196
+ }, 'seccallback', 1);
197
+
198
+ env.init({
199
+ window: fakeWindow,
200
+ document: fakeDocument,
201
+ navigator: fakeNavigator,
202
+ location: fakeLocation,
203
+ });
204
+
205
+ vm.runInThisContext(sourceCode, {
206
+ filename: 'xhs-scripting-response.js',
207
+ timeout: Number(input.timeoutMs || 10000),
208
+ });
209
+
210
+ const summary = {
211
+ websectiga: result,
212
+ length: result.length,
213
+ hex: /^[0-9a-f]{64}$/i.test(result),
214
+ sha256Prefix: crypto.createHash('sha256').update(result).digest('hex').slice(0, 16),
215
+ };
216
+
217
+ _process.stdout.write(JSON.stringify(summary) + '\n');
218
+ // env_core keeps an exit-time diagnostic reporter for reverse work. The pure
219
+ // CLI has already emitted its machine-readable result, so suppress that noise.
220
+ console.log = function log() {};