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,221 @@
1
+ /**
2
+ * 设备画像、请求头与公共 query(上游 utils/fingerprint.py、builder/header.py、builder/params.py)。
3
+ * UA 是 Chrome 151(上游实录);wreq-js 最新的 TLS 画像是 chrome_149,与上游 curl_cffi 用 chrome150 画像配 151 UA 的做法一致。
4
+ */
5
+ const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36';
6
+ export const PROFILE = {
7
+ ua: UA,
8
+ secChUa: '"Not=A?Brand";v="99", "Google Chrome";v="151", "Chromium";v="151"',
9
+ secChUaPlatform: '"Windows"',
10
+ browserName: 'Chrome',
11
+ browserVersion: '151.0.0.0',
12
+ engineVersion: '151.0.0.0',
13
+ platform: 'Win32',
14
+ osVersion: '10',
15
+ cpuCoreNum: '20',
16
+ deviceMemory: '32',
17
+ screenWidth: '2560',
18
+ screenHeight: '1440',
19
+ webglVendor: 'Google Inc. (NVIDIA)',
20
+ webglRenderer: 'ANGLE (NVIDIA, NVIDIA GeForce RTX 5060 Ti (0x00002D04) Direct3D11 vs_5_0 ps_5_0, D3D11)',
21
+ acceptLanguage: 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7,ja;q=0.6',
22
+ /** inner w/h、outer w/h、avail w/h、screen w/h。 */
23
+ geo: [2560, 1215, 2560, 1392, 2560, 1392, 2560, 1440],
24
+ screenX: 0,
25
+ screenY: 0,
26
+ };
27
+ /** navigator.appVersion:UA 去掉 `Mozilla/` 前缀。 */
28
+ export const APP_VERSION = UA.replace('Mozilla/', '');
29
+ export const BROWSER = 'chrome_149';
30
+ export const WWW = 'https://www.douyin.com';
31
+ export const LIVE = 'https://live.douyin.com';
32
+ export const CREATOR = 'https://creator.douyin.com';
33
+ export const LOGIN = 'https://login.douyin.com';
34
+ /** 只在 www.douyin.com 上的 host-only cookie(上游 builder/auth.py ensure_http_session 的 www_only)。 */
35
+ export const WWW_ONLY = new Set([
36
+ 's_v_web_id',
37
+ '__ac_nonce',
38
+ '__ac_signature',
39
+ 'x-web-secsdk-uid',
40
+ 'dy_swidth',
41
+ 'dy_sheight',
42
+ 'device_web_cpu_core',
43
+ 'device_web_memory_size',
44
+ 'architecture',
45
+ 'fpk1',
46
+ 'fpk2',
47
+ ]);
48
+ // ---------------------------------------------------------------- 请求头
49
+ /** 有序请求头,对应上游 Header:改值不影响位置,新键追加到末尾。 */
50
+ export class Headers {
51
+ pairs = [];
52
+ set(key, value) {
53
+ const i = this.pairs.findIndex(([k]) => k === key);
54
+ if (i >= 0)
55
+ this.pairs[i] = [key, value];
56
+ else
57
+ this.pairs.push([key, value]);
58
+ return this;
59
+ }
60
+ get(key) {
61
+ return this.pairs.find(([k]) => k === key)?.[1];
62
+ }
63
+ referer(url) {
64
+ return this.set('referer', url);
65
+ }
66
+ remove(...keys) {
67
+ this.pairs = this.pairs.filter(([k]) => !keys.includes(k));
68
+ return this;
69
+ }
70
+ list() {
71
+ return this.pairs;
72
+ }
73
+ }
74
+ /** 上游 HeaderBuilder.build。 */
75
+ export function headers(type = 'GET') {
76
+ const h = new Headers();
77
+ if (type === 'DOC') {
78
+ for (const [k, v] of [
79
+ ['accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7'],
80
+ ['accept-language', PROFILE.acceptLanguage],
81
+ ['cache-control', 'no-cache'],
82
+ ['cookie', ''],
83
+ ['pragma', 'no-cache'],
84
+ ['priority', 'u=0, i'],
85
+ ['sec-ch-ua', PROFILE.secChUa],
86
+ ['sec-ch-ua-mobile', '?0'],
87
+ ['sec-ch-ua-platform', PROFILE.secChUaPlatform],
88
+ ['sec-fetch-dest', 'document'],
89
+ ['sec-fetch-mode', 'navigate'],
90
+ ['sec-fetch-site', 'none'],
91
+ ['sec-fetch-user', '?1'],
92
+ ['upgrade-insecure-requests', '1'],
93
+ ['user-agent', PROFILE.ua],
94
+ ])
95
+ h.set(k, v);
96
+ return h;
97
+ }
98
+ h.set('user-agent', PROFILE.ua);
99
+ if (type === 'POST')
100
+ h.set('accept', '*/*').set('content-type', 'application/json; charset=UTF-8');
101
+ else if (type === 'FORM')
102
+ h.set('accept', 'application/json, text/plain, */*').set('content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
103
+ else if (type === 'PROTOBUF')
104
+ h.set('accept', 'application/x-protobuf').set('content-type', 'application/x-protobuf');
105
+ else
106
+ h.set('accept', 'application/json, text/plain, */*');
107
+ h.set('sec-ch-ua', PROFILE.secChUa);
108
+ h.set('sec-ch-ua-mobile', '?0');
109
+ h.set('sec-ch-ua-platform', PROFILE.secChUaPlatform);
110
+ h.set('accept-language', PROFILE.acceptLanguage);
111
+ h.set('priority', 'u=1, i');
112
+ h.set('sec-fetch-dest', 'empty');
113
+ h.set('sec-fetch-mode', 'cors');
114
+ h.set('sec-fetch-site', 'same-origin');
115
+ return h;
116
+ }
117
+ // ---------------------------------------------------------------- query
118
+ /** 有序参数,对应上游 Params(一个 dict):已有的键原位改值,新键追加。 */
119
+ export class Params {
120
+ map = new Map();
121
+ add(key, value) {
122
+ this.map.set(key, value == null ? '' : String(value));
123
+ return this;
124
+ }
125
+ update(pairs) {
126
+ for (const [k, v] of pairs)
127
+ this.add(k, v);
128
+ return this;
129
+ }
130
+ has(key) {
131
+ return this.map.has(key);
132
+ }
133
+ pairs() {
134
+ return [...this.map];
135
+ }
136
+ /** 上游 toString:`k=v` 原样拼接,不编码。 */
137
+ raw() {
138
+ return this.pairs()
139
+ .map(([k, v]) => `${k}=${v}`)
140
+ .join('&');
141
+ }
142
+ }
143
+ /** www.douyin.com 的公共 query 组(上游 with_platform,不带 auth 的部分)。 */
144
+ export function platformParams(roundTripTime = '0', versionCode = '170400', versionName = '17.4.0') {
145
+ return [
146
+ ['device_platform', 'webapp'],
147
+ ['aid', '6383'],
148
+ ['channel', 'channel_pc_web'],
149
+ ['update_version_code', '170400'],
150
+ ['pc_client_type', '1'],
151
+ ['pc_libra_divert', 'Windows'],
152
+ ['support_h265', '1'],
153
+ ['support_dash', '1'],
154
+ ['cpu_core_num', PROFILE.cpuCoreNum],
155
+ ['version_code', versionCode],
156
+ ['version_name', versionName],
157
+ ['cookie_enabled', 'true'],
158
+ ['screen_width', PROFILE.screenWidth],
159
+ ['screen_height', PROFILE.screenHeight],
160
+ ['browser_language', 'zh-CN'],
161
+ ['browser_platform', 'Win32'],
162
+ ['browser_name', PROFILE.browserName],
163
+ ['browser_version', PROFILE.browserVersion],
164
+ ['browser_online', 'true'],
165
+ ['engine_name', 'Blink'],
166
+ ['engine_version', PROFILE.engineVersion],
167
+ ['os_name', 'Windows'],
168
+ ['os_version', '10'],
169
+ ['device_memory', PROFILE.deviceMemory],
170
+ ['platform', 'PC'],
171
+ ['downlink', '10'],
172
+ ['effective_type', '4g'],
173
+ ['round_trip_time', roundTripTime],
174
+ ];
175
+ }
176
+ /** live.douyin.com 电商接口的公共 query 组(上游 with_live_platform)。 */
177
+ export function livePlatformParams(roundTripTime = '50') {
178
+ return [
179
+ ['update_version_code', '170400'],
180
+ ['pc_client_type', '1'],
181
+ ['pc_libra_divert', 'Windows'],
182
+ ['support_h265', '1'],
183
+ ['support_dash', '0'],
184
+ ['cpu_core_num', PROFILE.cpuCoreNum],
185
+ ['version_code', '320100'],
186
+ ['version_name', '32.1.0'],
187
+ ['cookie_enabled', 'true'],
188
+ ['screen_width', PROFILE.screenWidth],
189
+ ['screen_height', PROFILE.screenHeight],
190
+ ['browser_language', 'zh-CN'],
191
+ ['browser_platform', 'Win32'],
192
+ ['browser_name', PROFILE.browserName],
193
+ ['browser_version', PROFILE.browserVersion],
194
+ ['browser_online', 'true'],
195
+ ['engine_name', 'Blink'],
196
+ ['engine_version', PROFILE.engineVersion],
197
+ ['os_name', 'Windows'],
198
+ ['os_version', '10'],
199
+ ['device_memory', PROFILE.deviceMemory],
200
+ ['platform', 'PC'],
201
+ ['downlink', '10'],
202
+ ['effective_type', '4g'],
203
+ ['round_trip_time', roundTripTime],
204
+ ];
205
+ }
206
+ /** creator.douyin.com 的固定 query 组(上游 with_creator_platform)。 */
207
+ export function creatorPlatformParams() {
208
+ return [
209
+ ['cookie_enabled', 'true'],
210
+ ['screen_width', PROFILE.screenWidth],
211
+ ['screen_height', PROFILE.screenHeight],
212
+ ['browser_language', 'zh-CN'],
213
+ ['browser_platform', 'Win32'],
214
+ ['browser_name', 'Mozilla'],
215
+ ['browser_version', APP_VERSION],
216
+ ['browser_online', 'true'],
217
+ ['timezone_name', 'Asia/Shanghai'],
218
+ ['aid', '1128'],
219
+ ['support_h265', '1'],
220
+ ];
221
+ }
@@ -0,0 +1,26 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { gunzipSync } from 'node:zlib';
3
+ import protobuf from 'protobufjs';
4
+ import { staticFile } from '../../../core/paths.js';
5
+ /** 上游 static/*.proto 原样复制在 static/douyin/ 下,用 protobufjs 按文本解析(字段名保持 snake_case)。 */
6
+ const roots = new Map();
7
+ export function type(file, name) {
8
+ let root = roots.get(file);
9
+ if (!root) {
10
+ root = protobuf.parse(readFileSync(staticFile('douyin', `${file}.proto`), 'utf8'), { keepCase: true }).root;
11
+ roots.set(file, root);
12
+ }
13
+ return root.lookupType(name);
14
+ }
15
+ export function encode(file, name, value) {
16
+ const t = type(file, name);
17
+ return t.encode(t.fromObject(value)).finish();
18
+ }
19
+ export function decode(file, name, data, options = {}) {
20
+ const t = type(file, name);
21
+ return t.toObject(t.decode(data), { longs: String, bytes: Buffer, defaults: false, ...options });
22
+ }
23
+ /** 直播推送帧的负载可能是 gzip。 */
24
+ export function inflate(payload) {
25
+ return payload[0] === 0x1f && payload[1] === 0x8b ? gunzipSync(payload) : payload;
26
+ }
@@ -0,0 +1,88 @@
1
+ import { SpecificAIError } from '../../../core/errors.js';
2
+ import * as api from './api.js';
3
+ import { LIVE } from './profile.js';
4
+ /** 参数归一化(AGENTS 4.8):ID、URL、分享短链、`me`。 */
5
+ const SHORT_RE = /^https?:\/\/(v\.douyin\.com|www\.iesdouyin\.com\/share)\//i;
6
+ /** 分享短链(v.douyin.com)跟一次跳转,取 Location。分享文案里夹着的链接也能认出来。 */
7
+ async function expand(d, input) {
8
+ const s = input.trim();
9
+ const link = /https?:\/\/v\.douyin\.com\/[\w-]+\/?/i.exec(s)?.[0] ?? s;
10
+ if (!SHORT_RE.test(link))
11
+ return s;
12
+ const res = await d.http.request({ url: link, redirect: 'manual', cookies: false, headers: [['user-agent', 'Mozilla/5.0']] });
13
+ return res.headers.get('location') ?? link;
14
+ }
15
+ /** 已展开的字符串里的作品 ID:作品页路径、modal_id= 等参数,或纯数字 ID。 */
16
+ function itemIdOf(s) {
17
+ return /\/(?:video|note|slides|share\/video|share\/note)\/(\d+)/.exec(s)?.[1] ?? /[?&](?:modal_id|aweme_id|item_id)=(\d+)/.exec(s)?.[1] ?? /^\d{8,}$/.exec(s)?.[0];
18
+ }
19
+ /** 已展开的字符串里的 sec_uid:主页路径、sec_uid= 参数,或 MS4w 开头的 sec_uid;/user/self 不算。 */
20
+ function secUidOf(s) {
21
+ const m = /\/(?:user|share\/user)\/([\w-]+)/.exec(s)?.[1] ?? /[?&]sec_uid=([\w-]+)/.exec(s)?.[1] ?? /^MS4w[\w-]+$/.exec(s)?.[0];
22
+ return m && m !== 'self' ? m : undefined;
23
+ }
24
+ /** 作品:aweme_id、作品页 URL(/video/、/note/、/slides/、modal_id=)或分享短链。 */
25
+ export async function resolveItem(d, input) {
26
+ const m = itemIdOf(await expand(d, input));
27
+ if (m)
28
+ return m;
29
+ throw new SpecificAIError('USAGE', `无法识别的作品:${input}`, { hint: '传作品 ID 或作品链接,例如 https://www.douyin.com/video/7433523124836060416' });
30
+ }
31
+ /** 用户:sec_uid、主页 URL、分享短链、`me`。 */
32
+ export async function resolveUser(d, input) {
33
+ if (input.trim() === 'me') {
34
+ const saved = d.credential.user?.id;
35
+ if (saved)
36
+ return saved;
37
+ if (!d.isLogin)
38
+ throw new SpecificAIError('AUTH_REQUIRED', 'me 表示当前账号,需要先登录', { hint: 'specific-ai douyin auth login' });
39
+ return (await api.mySecUid(d)).secUid;
40
+ }
41
+ const m = secUidOf(await expand(d, input));
42
+ if (m)
43
+ return m;
44
+ throw new SpecificAIError('USAGE', `无法识别的用户:${input}`, { hint: '传用户 sec_uid(MS4wLjAB 开头)或主页链接 https://www.douyin.com/user/<sec_uid>' });
45
+ }
46
+ /**
47
+ * `msg send --share` 的目标:作品(ID / 链接)、用户(sec_uid / 主页 / me)、其余 http(s) 链接当网页卡片。
48
+ * 先认作品:主页上点开的作品是 `/user/<sec_uid>?modal_id=<作品>`,与 resolveItem 一样当作品。
49
+ */
50
+ export async function resolveShare(d, input) {
51
+ if (input.trim() === 'me')
52
+ return { kind: 'user', secUid: await resolveUser(d, 'me') };
53
+ const s = await expand(d, input);
54
+ const item = itemIdOf(s);
55
+ if (item)
56
+ return { kind: 'item', id: item };
57
+ const user = secUidOf(s);
58
+ if (user)
59
+ return { kind: 'user', secUid: user };
60
+ if (/^https?:\/\//i.test(s))
61
+ return { kind: 'web', url: s };
62
+ throw new SpecificAIError('USAGE', `无法识别的分享目标:${input}`, { hint: '传作品 ID / 链接、用户 sec_uid / 主页链接,或一个网页链接' });
63
+ }
64
+ /** 直播间:直播间号(web_rid)或 live.douyin.com 链接。 */
65
+ export async function resolveRoom(d, input) {
66
+ const s = await expand(d, input);
67
+ const m = /live\.douyin\.com\/(\d+)/.exec(s)?.[1] ?? /^\d+$/.exec(s)?.[0];
68
+ if (m)
69
+ return m;
70
+ throw new SpecificAIError('USAGE', `无法识别的直播间:${input}`, { hint: `传直播间号或直播间链接 ${LIVE}/<直播间号>` });
71
+ }
72
+ /** 商品:promotion_id,或带 id / promotion_id / shop_id 参数的商品链接(live products 输出的 url)。 */
73
+ export function resolveProduct(input) {
74
+ const s = input.trim();
75
+ if (/^\d+$/.test(s))
76
+ return { promotionId: s, productId: null, shopId: null };
77
+ let q;
78
+ try {
79
+ q = new URL(s).searchParams;
80
+ }
81
+ catch {
82
+ throw new SpecificAIError('USAGE', `无法识别的商品:${input}`, { hint: '传商品 promotion_id,或 specific-ai douyin live products 输出的商品 url' });
83
+ }
84
+ const promotionId = q.get('promotion_id') ?? q.get('id');
85
+ if (!promotionId)
86
+ throw new SpecificAIError('USAGE', `商品链接里没有 id:${input}`);
87
+ return { promotionId, productId: q.get('product_id') ?? q.get('id'), shopId: q.get('shop_id') };
88
+ }