@jackwener/opencli 1.5.5 → 1.5.7

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 (540) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +31 -4
  3. package/README.zh-CN.md +40 -5
  4. package/SKILL.md +1 -1
  5. package/dist/browser/cdp.d.ts +1 -0
  6. package/dist/browser/cdp.js +30 -27
  7. package/dist/browser/daemon-client.d.ts +11 -1
  8. package/dist/browser/daemon-client.js +3 -0
  9. package/dist/browser/dom-helpers.js +1 -0
  10. package/dist/browser/dom-helpers.test.js +14 -1
  11. package/dist/browser/mcp.js +18 -13
  12. package/dist/browser/page.d.ts +6 -0
  13. package/dist/browser/page.js +37 -2
  14. package/dist/browser/page.test.d.ts +1 -0
  15. package/dist/browser/page.test.js +44 -0
  16. package/dist/browser/stealth.js +198 -0
  17. package/dist/browser/stealth.test.d.ts +1 -0
  18. package/dist/browser/stealth.test.js +134 -0
  19. package/dist/browser.test.js +1 -1
  20. package/dist/build-manifest.d.ts +1 -0
  21. package/dist/build-manifest.js +5 -1
  22. package/dist/build-manifest.test.js +2 -0
  23. package/dist/cli-manifest.json +1821 -252
  24. package/dist/cli.js +20 -3
  25. package/dist/clis/antigravity/serve.d.ts +1 -1
  26. package/dist/clis/antigravity/serve.js +5 -8
  27. package/dist/clis/band/bands.d.ts +1 -0
  28. package/dist/clis/band/bands.js +72 -0
  29. package/dist/clis/band/mentions.d.ts +1 -0
  30. package/dist/clis/band/mentions.js +127 -0
  31. package/dist/clis/band/post.d.ts +1 -0
  32. package/dist/clis/band/post.js +175 -0
  33. package/dist/clis/band/posts.d.ts +1 -0
  34. package/dist/clis/band/posts.js +94 -0
  35. package/dist/clis/bilibili/subtitle.js +4 -0
  36. package/dist/clis/bilibili/subtitle.test.d.ts +1 -0
  37. package/dist/clis/bilibili/subtitle.test.js +48 -0
  38. package/dist/clis/chatwise/ask.js +0 -2
  39. package/dist/clis/chatwise/export.js +0 -2
  40. package/dist/clis/chatwise/history.js +0 -2
  41. package/dist/clis/chatwise/model.js +0 -2
  42. package/dist/clis/chatwise/new.js +1 -2
  43. package/dist/clis/chatwise/read.js +0 -2
  44. package/dist/clis/chatwise/screenshot.js +1 -2
  45. package/dist/clis/chatwise/send.js +0 -2
  46. package/dist/clis/chatwise/status.js +1 -2
  47. package/dist/clis/ctrip/search.d.ts +13 -0
  48. package/dist/clis/ctrip/search.js +73 -48
  49. package/dist/clis/ctrip/search.test.d.ts +1 -0
  50. package/dist/clis/ctrip/search.test.js +64 -0
  51. package/dist/clis/doubao/detail.d.ts +1 -0
  52. package/dist/clis/doubao/detail.js +33 -0
  53. package/dist/clis/doubao/detail.test.d.ts +1 -0
  54. package/dist/clis/doubao/detail.test.js +42 -0
  55. package/dist/clis/doubao/history.d.ts +1 -0
  56. package/dist/clis/doubao/history.js +28 -0
  57. package/dist/clis/doubao/history.test.d.ts +1 -0
  58. package/dist/clis/doubao/history.test.js +37 -0
  59. package/dist/clis/doubao/meeting-summary.d.ts +1 -0
  60. package/dist/clis/doubao/meeting-summary.js +39 -0
  61. package/dist/clis/doubao/meeting-transcript.d.ts +1 -0
  62. package/dist/clis/doubao/meeting-transcript.js +36 -0
  63. package/dist/clis/doubao/utils.d.ts +27 -0
  64. package/dist/clis/doubao/utils.js +317 -0
  65. package/dist/clis/doubao/utils.test.d.ts +1 -0
  66. package/dist/clis/doubao/utils.test.js +24 -0
  67. package/dist/clis/douyin/_shared/public-api.d.ts +33 -0
  68. package/dist/clis/douyin/_shared/public-api.js +29 -0
  69. package/dist/clis/douyin/_shared/sts2.js +8 -2
  70. package/dist/clis/douyin/_shared/sts2.test.d.ts +1 -0
  71. package/dist/clis/douyin/_shared/sts2.test.js +27 -0
  72. package/dist/clis/douyin/activities.js +4 -2
  73. package/dist/clis/douyin/activities.test.js +34 -1
  74. package/dist/clis/douyin/collections.js +1 -1
  75. package/dist/clis/douyin/collections.test.js +24 -2
  76. package/dist/clis/douyin/draft.d.ts +8 -11
  77. package/dist/clis/douyin/draft.js +302 -185
  78. package/dist/clis/douyin/draft.test.d.ts +1 -1
  79. package/dist/clis/douyin/draft.test.js +357 -2
  80. package/dist/clis/douyin/hashtag.js +9 -2
  81. package/dist/clis/douyin/hashtag.test.js +35 -2
  82. package/dist/clis/douyin/profile.js +1 -1
  83. package/dist/clis/douyin/profile.test.js +36 -1
  84. package/dist/clis/douyin/user-videos.d.ts +5 -0
  85. package/dist/clis/douyin/user-videos.js +74 -0
  86. package/dist/clis/douyin/user-videos.test.d.ts +1 -0
  87. package/dist/clis/douyin/user-videos.test.js +108 -0
  88. package/dist/clis/douyin/videos.js +22 -5
  89. package/dist/clis/douyin/videos.test.js +45 -2
  90. package/dist/clis/facebook/search.test.d.ts +5 -0
  91. package/dist/clis/facebook/search.test.js +60 -0
  92. package/dist/clis/facebook/search.yaml +4 -3
  93. package/dist/clis/instagram/download.d.ts +16 -0
  94. package/dist/clis/instagram/download.js +225 -0
  95. package/dist/clis/instagram/download.test.d.ts +1 -0
  96. package/dist/clis/instagram/download.test.js +118 -0
  97. package/dist/clis/notebooklm/bind-current.d.ts +1 -0
  98. package/dist/clis/notebooklm/bind-current.js +29 -0
  99. package/dist/clis/notebooklm/bind-current.test.d.ts +1 -0
  100. package/dist/clis/notebooklm/bind-current.test.js +35 -0
  101. package/dist/clis/notebooklm/binding.test.d.ts +1 -0
  102. package/dist/clis/notebooklm/binding.test.js +44 -0
  103. package/dist/clis/notebooklm/compat.test.d.ts +3 -0
  104. package/dist/clis/notebooklm/compat.test.js +16 -0
  105. package/dist/clis/notebooklm/current.d.ts +1 -0
  106. package/dist/clis/notebooklm/current.js +28 -0
  107. package/dist/clis/notebooklm/get.d.ts +1 -0
  108. package/dist/clis/notebooklm/get.js +37 -0
  109. package/dist/clis/notebooklm/history.d.ts +1 -0
  110. package/dist/clis/notebooklm/history.js +25 -0
  111. package/dist/clis/notebooklm/history.test.d.ts +1 -0
  112. package/dist/clis/notebooklm/history.test.js +58 -0
  113. package/dist/clis/notebooklm/list.d.ts +1 -0
  114. package/dist/clis/notebooklm/list.js +35 -0
  115. package/dist/clis/notebooklm/note-list.d.ts +1 -0
  116. package/dist/clis/notebooklm/note-list.js +28 -0
  117. package/dist/clis/notebooklm/note-list.test.d.ts +1 -0
  118. package/dist/clis/notebooklm/note-list.test.js +56 -0
  119. package/dist/clis/notebooklm/notes-get.d.ts +1 -0
  120. package/dist/clis/notebooklm/notes-get.js +47 -0
  121. package/dist/clis/notebooklm/notes-get.test.d.ts +1 -0
  122. package/dist/clis/notebooklm/notes-get.test.js +72 -0
  123. package/dist/clis/notebooklm/rpc.d.ts +36 -0
  124. package/dist/clis/notebooklm/rpc.js +189 -0
  125. package/dist/clis/notebooklm/rpc.test.d.ts +1 -0
  126. package/dist/clis/notebooklm/rpc.test.js +105 -0
  127. package/dist/clis/notebooklm/shared.d.ts +87 -0
  128. package/dist/clis/notebooklm/shared.js +3 -0
  129. package/dist/clis/notebooklm/source-fulltext.d.ts +1 -0
  130. package/dist/clis/notebooklm/source-fulltext.js +44 -0
  131. package/dist/clis/notebooklm/source-fulltext.test.d.ts +1 -0
  132. package/dist/clis/notebooklm/source-fulltext.test.js +106 -0
  133. package/dist/clis/notebooklm/source-get.d.ts +1 -0
  134. package/dist/clis/notebooklm/source-get.js +40 -0
  135. package/dist/clis/notebooklm/source-get.test.d.ts +1 -0
  136. package/dist/clis/notebooklm/source-get.test.js +84 -0
  137. package/dist/clis/notebooklm/source-guide.d.ts +1 -0
  138. package/dist/clis/notebooklm/source-guide.js +44 -0
  139. package/dist/clis/notebooklm/source-guide.test.d.ts +1 -0
  140. package/dist/clis/notebooklm/source-guide.test.js +104 -0
  141. package/dist/clis/notebooklm/source-list.d.ts +1 -0
  142. package/dist/clis/notebooklm/source-list.js +30 -0
  143. package/dist/clis/notebooklm/status.d.ts +1 -0
  144. package/dist/clis/notebooklm/status.js +31 -0
  145. package/dist/clis/notebooklm/summary.d.ts +1 -0
  146. package/dist/clis/notebooklm/summary.js +30 -0
  147. package/dist/clis/notebooklm/summary.test.d.ts +1 -0
  148. package/dist/clis/notebooklm/summary.test.js +78 -0
  149. package/dist/clis/notebooklm/utils.d.ts +37 -0
  150. package/dist/clis/notebooklm/utils.js +739 -0
  151. package/dist/clis/notebooklm/utils.test.d.ts +1 -0
  152. package/dist/clis/notebooklm/utils.test.js +390 -0
  153. package/dist/clis/ones/common.d.ts +32 -0
  154. package/dist/clis/ones/common.js +144 -0
  155. package/dist/clis/ones/enrich-tasks.d.ts +5 -0
  156. package/dist/clis/ones/enrich-tasks.js +37 -0
  157. package/dist/clis/ones/login.d.ts +1 -0
  158. package/dist/clis/ones/login.js +80 -0
  159. package/dist/clis/ones/logout.d.ts +1 -0
  160. package/dist/clis/ones/logout.js +17 -0
  161. package/dist/clis/ones/me.d.ts +1 -0
  162. package/dist/clis/ones/me.js +30 -0
  163. package/dist/clis/ones/my-tasks.d.ts +1 -0
  164. package/dist/clis/ones/my-tasks.js +120 -0
  165. package/dist/clis/ones/resolve-labels.d.ts +10 -0
  166. package/dist/clis/ones/resolve-labels.js +64 -0
  167. package/dist/clis/ones/task-helpers.d.ts +29 -0
  168. package/dist/clis/ones/task-helpers.js +212 -0
  169. package/dist/clis/ones/task-helpers.test.d.ts +1 -0
  170. package/dist/clis/ones/task-helpers.test.js +12 -0
  171. package/dist/clis/ones/task.d.ts +1 -0
  172. package/dist/clis/ones/task.js +66 -0
  173. package/dist/clis/ones/tasks.d.ts +1 -0
  174. package/dist/clis/ones/tasks.js +79 -0
  175. package/dist/clis/ones/token-info.d.ts +1 -0
  176. package/dist/clis/ones/token-info.js +42 -0
  177. package/dist/clis/ones/worklog.d.ts +11 -0
  178. package/dist/clis/ones/worklog.js +267 -0
  179. package/dist/clis/ones/worklog.test.d.ts +1 -0
  180. package/dist/clis/ones/worklog.test.js +20 -0
  181. package/dist/clis/spotify/spotify.d.ts +1 -0
  182. package/dist/clis/spotify/spotify.js +316 -0
  183. package/dist/clis/spotify/utils.d.ts +21 -0
  184. package/dist/clis/spotify/utils.js +66 -0
  185. package/dist/clis/spotify/utils.test.d.ts +1 -0
  186. package/dist/clis/spotify/utils.test.js +67 -0
  187. package/dist/clis/substack/utils.d.ts +4 -0
  188. package/dist/clis/substack/utils.js +8 -2
  189. package/dist/clis/substack/utils.test.d.ts +1 -0
  190. package/dist/clis/substack/utils.test.js +46 -0
  191. package/dist/clis/tieba/commands.test.d.ts +4 -0
  192. package/dist/clis/tieba/commands.test.js +79 -0
  193. package/dist/clis/tieba/hot.d.ts +1 -0
  194. package/dist/clis/tieba/hot.js +48 -0
  195. package/dist/clis/tieba/posts.d.ts +1 -0
  196. package/dist/clis/tieba/posts.js +85 -0
  197. package/dist/clis/tieba/read.d.ts +1 -0
  198. package/dist/clis/tieba/read.js +140 -0
  199. package/dist/clis/tieba/search.d.ts +1 -0
  200. package/dist/clis/tieba/search.js +108 -0
  201. package/dist/clis/tieba/utils.d.ts +101 -0
  202. package/dist/clis/tieba/utils.js +240 -0
  203. package/dist/clis/tieba/utils.test.d.ts +1 -0
  204. package/dist/clis/tieba/utils.test.js +290 -0
  205. package/dist/clis/v2ex/hot.yaml +4 -1
  206. package/dist/clis/v2ex/latest.yaml +4 -1
  207. package/dist/clis/v2ex/topic.yaml +6 -1
  208. package/dist/clis/weixin/download.d.ts +9 -0
  209. package/dist/clis/weixin/download.js +76 -6
  210. package/dist/clis/weread/book.js +206 -13
  211. package/dist/clis/weread/commands.test.js +331 -0
  212. package/dist/clis/weread/private-api-regression.test.d.ts +1 -0
  213. package/dist/{weread-private-api-regression.test.js → clis/weread/private-api-regression.test.js} +92 -30
  214. package/dist/clis/weread/search-regression.test.d.ts +1 -0
  215. package/dist/clis/weread/search-regression.test.js +407 -0
  216. package/dist/clis/weread/search.js +143 -7
  217. package/dist/clis/weread/shelf.js +13 -95
  218. package/dist/clis/weread/utils.d.ts +56 -0
  219. package/dist/clis/weread/utils.js +234 -7
  220. package/dist/clis/weread/utils.test.js +71 -1
  221. package/dist/clis/xiaohongshu/comments.d.ts +3 -0
  222. package/dist/clis/xiaohongshu/comments.js +76 -17
  223. package/dist/clis/xiaohongshu/comments.test.js +70 -9
  224. package/dist/clis/xiaohongshu/download.d.ts +4 -1
  225. package/dist/clis/xiaohongshu/download.js +83 -22
  226. package/dist/clis/xiaohongshu/download.test.d.ts +1 -0
  227. package/dist/clis/xiaohongshu/download.test.js +75 -0
  228. package/dist/clis/xiaohongshu/note-helpers.d.ts +12 -0
  229. package/dist/clis/xiaohongshu/note-helpers.js +23 -0
  230. package/dist/clis/xiaohongshu/note.d.ts +7 -0
  231. package/dist/clis/xiaohongshu/note.js +76 -0
  232. package/dist/clis/xiaohongshu/note.test.d.ts +1 -0
  233. package/dist/clis/xiaohongshu/note.test.js +136 -0
  234. package/dist/clis/xiaohongshu/publish.d.ts +1 -1
  235. package/dist/clis/xiaohongshu/publish.js +78 -31
  236. package/dist/clis/xiaohongshu/publish.test.js +66 -1
  237. package/dist/clis/xiaohongshu/search.js +9 -0
  238. package/dist/clis/xiaohongshu/search.test.js +10 -4
  239. package/dist/clis/xiaohongshu/user-helpers.d.ts +1 -0
  240. package/dist/clis/xiaohongshu/user-helpers.js +2 -0
  241. package/dist/clis/xiaohongshu/user-helpers.test.js +18 -0
  242. package/dist/clis/xueqiu/comments.d.ts +118 -0
  243. package/dist/clis/xueqiu/comments.js +354 -0
  244. package/dist/clis/xueqiu/comments.test.d.ts +1 -0
  245. package/dist/clis/xueqiu/comments.test.js +696 -0
  246. package/dist/clis/youtube/search.js +57 -17
  247. package/dist/clis/youtube/transcript.js +2 -4
  248. package/dist/clis/youtube/utils.d.ts +9 -0
  249. package/dist/clis/youtube/utils.js +67 -3
  250. package/dist/clis/youtube/utils.test.d.ts +1 -0
  251. package/dist/clis/youtube/utils.test.js +37 -0
  252. package/dist/clis/youtube/video.js +16 -15
  253. package/dist/clis/zhihu/question.js +19 -17
  254. package/dist/clis/zhihu/question.test.d.ts +1 -0
  255. package/dist/clis/zhihu/question.test.js +54 -0
  256. package/dist/clis/zsxq/dynamics.d.ts +1 -0
  257. package/dist/clis/zsxq/dynamics.js +47 -0
  258. package/dist/clis/zsxq/groups.d.ts +1 -0
  259. package/dist/clis/zsxq/groups.js +32 -0
  260. package/dist/clis/zsxq/search.d.ts +1 -0
  261. package/dist/clis/zsxq/search.js +43 -0
  262. package/dist/clis/zsxq/search.test.d.ts +1 -0
  263. package/dist/clis/zsxq/search.test.js +24 -0
  264. package/dist/clis/zsxq/topic.d.ts +1 -0
  265. package/dist/clis/zsxq/topic.js +47 -0
  266. package/dist/clis/zsxq/topic.test.d.ts +1 -0
  267. package/dist/clis/zsxq/topic.test.js +29 -0
  268. package/dist/clis/zsxq/topics.d.ts +1 -0
  269. package/dist/clis/zsxq/topics.js +25 -0
  270. package/dist/clis/zsxq/topics.test.d.ts +1 -0
  271. package/dist/clis/zsxq/topics.test.js +24 -0
  272. package/dist/clis/zsxq/utils.d.ts +97 -0
  273. package/dist/clis/zsxq/utils.js +230 -0
  274. package/dist/commanderAdapter.js +10 -1
  275. package/dist/commanderAdapter.test.js +64 -0
  276. package/dist/commands/daemon.d.ts +9 -0
  277. package/dist/commands/daemon.js +124 -0
  278. package/dist/commands/daemon.test.d.ts +1 -0
  279. package/dist/commands/daemon.test.js +185 -0
  280. package/dist/completion.js +3 -1
  281. package/dist/constants.d.ts +2 -0
  282. package/dist/constants.js +2 -0
  283. package/dist/daemon.d.ts +1 -1
  284. package/dist/daemon.js +25 -14
  285. package/dist/daemon.test.d.ts +1 -0
  286. package/dist/daemon.test.js +65 -0
  287. package/dist/discovery.d.ts +9 -0
  288. package/dist/discovery.js +47 -2
  289. package/dist/electron-apps.d.ts +29 -0
  290. package/dist/electron-apps.js +65 -0
  291. package/dist/electron-apps.test.d.ts +1 -0
  292. package/dist/electron-apps.test.js +43 -0
  293. package/dist/engine.test.js +41 -9
  294. package/dist/execution.js +20 -16
  295. package/dist/external-clis.yaml +17 -0
  296. package/dist/idle-manager.d.ts +19 -0
  297. package/dist/idle-manager.js +54 -0
  298. package/dist/launcher.d.ts +36 -0
  299. package/dist/launcher.js +152 -0
  300. package/dist/launcher.test.d.ts +1 -0
  301. package/dist/launcher.test.js +57 -0
  302. package/dist/main.js +3 -3
  303. package/dist/registry.d.ts +1 -0
  304. package/dist/registry.js +31 -3
  305. package/dist/registry.test.js +13 -0
  306. package/dist/runtime.d.ts +5 -3
  307. package/dist/runtime.js +12 -5
  308. package/dist/serialization.d.ts +1 -0
  309. package/dist/serialization.js +3 -0
  310. package/dist/serialization.test.js +17 -1
  311. package/dist/tui.d.ts +7 -0
  312. package/dist/tui.js +52 -0
  313. package/dist/tui.test.d.ts +1 -0
  314. package/dist/tui.test.js +19 -0
  315. package/dist/types.d.ts +5 -0
  316. package/dist/weixin-download.test.js +14 -0
  317. package/docs/.vitepress/config.mts +4 -0
  318. package/docs/adapters/browser/band.md +63 -0
  319. package/docs/adapters/browser/notebooklm.md +69 -0
  320. package/docs/adapters/browser/ones.md +59 -0
  321. package/docs/adapters/browser/spotify.md +62 -0
  322. package/docs/adapters/browser/tieba.md +45 -0
  323. package/docs/adapters/browser/xiaohongshu.md +19 -10
  324. package/docs/adapters/browser/xueqiu.md +5 -0
  325. package/docs/adapters/browser/zsxq.md +49 -0
  326. package/docs/adapters/index.md +67 -63
  327. package/docs/adapters-doc/ones.md +32 -0
  328. package/docs/guide/browser-bridge.md +12 -0
  329. package/docs/guide/troubleshooting.md +9 -4
  330. package/docs/superpowers/plans/2026-03-31-daemon-lifecycle-redesign.md +857 -0
  331. package/docs/superpowers/specs/2026-03-31-daemon-lifecycle-redesign.md +208 -0
  332. package/docs/zh/guide/browser-bridge.md +12 -0
  333. package/extension/dist/background.js +794 -513
  334. package/extension/src/background.test.ts +202 -2
  335. package/extension/src/background.ts +189 -10
  336. package/extension/src/cdp.ts +54 -0
  337. package/extension/src/protocol.ts +11 -5
  338. package/package.json +1 -1
  339. package/scripts/postinstall.js +16 -0
  340. package/src/browser/cdp.ts +24 -17
  341. package/src/browser/daemon-client.ts +11 -1
  342. package/src/browser/dom-helpers.test.ts +15 -1
  343. package/src/browser/dom-helpers.ts +1 -0
  344. package/src/browser/mcp.ts +18 -13
  345. package/src/browser/page.test.ts +58 -0
  346. package/src/browser/page.ts +34 -2
  347. package/src/browser/stealth.test.ts +153 -0
  348. package/src/browser/stealth.ts +198 -0
  349. package/src/browser.test.ts +1 -1
  350. package/src/build-manifest.test.ts +2 -0
  351. package/src/build-manifest.ts +6 -1
  352. package/src/cli.ts +21 -3
  353. package/src/clis/antigravity/SKILL.md +3 -12
  354. package/src/clis/antigravity/serve.ts +5 -10
  355. package/src/clis/band/bands.ts +76 -0
  356. package/src/clis/band/mentions.ts +134 -0
  357. package/src/clis/band/post.ts +187 -0
  358. package/src/clis/band/posts.ts +106 -0
  359. package/src/clis/bilibili/subtitle.test.ts +60 -0
  360. package/src/clis/bilibili/subtitle.ts +4 -0
  361. package/src/clis/chatwise/ask.ts +0 -2
  362. package/src/clis/chatwise/export.ts +0 -2
  363. package/src/clis/chatwise/history.ts +0 -2
  364. package/src/clis/chatwise/model.ts +0 -2
  365. package/src/clis/chatwise/new.ts +1 -2
  366. package/src/clis/chatwise/read.ts +0 -2
  367. package/src/clis/chatwise/screenshot.ts +1 -2
  368. package/src/clis/chatwise/send.ts +0 -2
  369. package/src/clis/chatwise/status.ts +1 -2
  370. package/src/clis/ctrip/search.test.ts +73 -0
  371. package/src/clis/ctrip/search.ts +97 -47
  372. package/src/clis/doubao/detail.test.ts +53 -0
  373. package/src/clis/doubao/detail.ts +41 -0
  374. package/src/clis/doubao/history.test.ts +45 -0
  375. package/src/clis/doubao/history.ts +32 -0
  376. package/src/clis/doubao/meeting-summary.ts +53 -0
  377. package/src/clis/doubao/meeting-transcript.ts +48 -0
  378. package/src/clis/doubao/utils.test.ts +45 -0
  379. package/src/clis/doubao/utils.ts +371 -0
  380. package/src/clis/douyin/_shared/public-api.ts +84 -0
  381. package/src/clis/douyin/_shared/sts2.test.ts +31 -0
  382. package/src/clis/douyin/_shared/sts2.ts +11 -3
  383. package/src/clis/douyin/activities.test.ts +41 -1
  384. package/src/clis/douyin/activities.ts +12 -3
  385. package/src/clis/douyin/collections.test.ts +35 -2
  386. package/src/clis/douyin/collections.ts +1 -1
  387. package/src/clis/douyin/draft.test.ts +444 -2
  388. package/src/clis/douyin/draft.ts +382 -218
  389. package/src/clis/douyin/hashtag.test.ts +42 -2
  390. package/src/clis/douyin/hashtag.ts +11 -3
  391. package/src/clis/douyin/profile.test.ts +43 -1
  392. package/src/clis/douyin/profile.ts +9 -2
  393. package/src/clis/douyin/user-videos.test.ts +122 -0
  394. package/src/clis/douyin/user-videos.ts +101 -0
  395. package/src/clis/douyin/videos.test.ts +52 -2
  396. package/src/clis/douyin/videos.ts +49 -15
  397. package/src/clis/facebook/search.test.ts +70 -0
  398. package/src/clis/facebook/search.yaml +4 -3
  399. package/src/clis/instagram/download.test.ts +159 -0
  400. package/src/clis/instagram/download.ts +286 -0
  401. package/src/clis/notebooklm/bind-current.test.ts +43 -0
  402. package/src/clis/notebooklm/bind-current.ts +36 -0
  403. package/src/clis/notebooklm/binding.test.ts +53 -0
  404. package/src/clis/notebooklm/compat.test.ts +19 -0
  405. package/src/clis/notebooklm/current.ts +38 -0
  406. package/src/clis/notebooklm/get.ts +53 -0
  407. package/src/clis/notebooklm/history.test.ts +70 -0
  408. package/src/clis/notebooklm/history.ts +36 -0
  409. package/src/clis/notebooklm/list.ts +40 -0
  410. package/src/clis/notebooklm/note-list.test.ts +64 -0
  411. package/src/clis/notebooklm/note-list.ts +42 -0
  412. package/src/clis/notebooklm/notes-get.test.ts +88 -0
  413. package/src/clis/notebooklm/notes-get.ts +67 -0
  414. package/src/clis/notebooklm/rpc.test.ts +126 -0
  415. package/src/clis/notebooklm/rpc.ts +286 -0
  416. package/src/clis/notebooklm/shared.ts +98 -0
  417. package/src/clis/notebooklm/source-fulltext.test.ts +123 -0
  418. package/src/clis/notebooklm/source-fulltext.ts +69 -0
  419. package/src/clis/notebooklm/source-get.test.ts +100 -0
  420. package/src/clis/notebooklm/source-get.ts +60 -0
  421. package/src/clis/notebooklm/source-guide.test.ts +121 -0
  422. package/src/clis/notebooklm/source-guide.ts +69 -0
  423. package/src/clis/notebooklm/source-list.ts +45 -0
  424. package/src/clis/notebooklm/status.ts +34 -0
  425. package/src/clis/notebooklm/summary.test.ts +94 -0
  426. package/src/clis/notebooklm/summary.ts +45 -0
  427. package/src/clis/notebooklm/utils.test.ts +446 -0
  428. package/src/clis/notebooklm/utils.ts +893 -0
  429. package/src/clis/ones/common.ts +187 -0
  430. package/src/clis/ones/enrich-tasks.ts +47 -0
  431. package/src/clis/ones/login.ts +103 -0
  432. package/src/clis/ones/logout.ts +19 -0
  433. package/src/clis/ones/me.ts +34 -0
  434. package/src/clis/ones/my-tasks.ts +148 -0
  435. package/src/clis/ones/resolve-labels.ts +80 -0
  436. package/src/clis/ones/task-helpers.test.ts +14 -0
  437. package/src/clis/ones/task-helpers.ts +214 -0
  438. package/src/clis/ones/task.ts +79 -0
  439. package/src/clis/ones/tasks.ts +92 -0
  440. package/src/clis/ones/token-info.ts +46 -0
  441. package/src/clis/ones/worklog.test.ts +24 -0
  442. package/src/clis/ones/worklog.ts +306 -0
  443. package/src/clis/spotify/spotify.ts +328 -0
  444. package/src/clis/spotify/utils.test.ts +87 -0
  445. package/src/clis/spotify/utils.ts +92 -0
  446. package/src/clis/substack/utils.test.ts +54 -0
  447. package/src/clis/substack/utils.ts +10 -2
  448. package/src/clis/tieba/commands.test.ts +86 -0
  449. package/src/clis/tieba/hot.ts +52 -0
  450. package/src/clis/tieba/posts.ts +108 -0
  451. package/src/clis/tieba/read.ts +158 -0
  452. package/src/clis/tieba/search.ts +119 -0
  453. package/src/clis/tieba/utils.test.ts +322 -0
  454. package/src/clis/tieba/utils.ts +348 -0
  455. package/src/clis/v2ex/hot.yaml +4 -1
  456. package/src/clis/v2ex/latest.yaml +4 -1
  457. package/src/clis/v2ex/topic.yaml +6 -1
  458. package/src/clis/weixin/download.ts +95 -6
  459. package/src/clis/weread/book.ts +256 -13
  460. package/src/clis/weread/commands.test.ts +409 -0
  461. package/src/{weread-private-api-regression.test.ts → clis/weread/private-api-regression.test.ts} +108 -30
  462. package/src/clis/weread/search-regression.test.ts +440 -0
  463. package/src/clis/weread/search.ts +189 -9
  464. package/src/clis/weread/shelf.ts +20 -122
  465. package/src/clis/weread/utils.test.ts +81 -1
  466. package/src/clis/weread/utils.ts +293 -7
  467. package/src/clis/xiaohongshu/comments.test.ts +85 -9
  468. package/src/clis/xiaohongshu/comments.ts +76 -17
  469. package/src/clis/xiaohongshu/download.test.ts +96 -0
  470. package/src/clis/xiaohongshu/download.ts +83 -22
  471. package/src/clis/xiaohongshu/note-helpers.ts +25 -0
  472. package/src/clis/xiaohongshu/note.test.ts +164 -0
  473. package/src/clis/xiaohongshu/note.ts +86 -0
  474. package/src/clis/xiaohongshu/publish.test.ts +79 -1
  475. package/src/clis/xiaohongshu/publish.ts +84 -30
  476. package/src/clis/xiaohongshu/search.test.ts +11 -4
  477. package/src/clis/xiaohongshu/search.ts +13 -0
  478. package/src/clis/xiaohongshu/user-helpers.test.ts +23 -0
  479. package/src/clis/xiaohongshu/user-helpers.ts +4 -0
  480. package/src/clis/xueqiu/comments.test.ts +823 -0
  481. package/src/clis/xueqiu/comments.ts +461 -0
  482. package/src/clis/youtube/search.ts +57 -17
  483. package/src/clis/youtube/transcript.ts +2 -4
  484. package/src/clis/youtube/utils.test.ts +43 -0
  485. package/src/clis/youtube/utils.ts +69 -0
  486. package/src/clis/youtube/video.ts +16 -15
  487. package/src/clis/zhihu/question.test.ts +71 -0
  488. package/src/clis/zhihu/question.ts +27 -15
  489. package/src/clis/zsxq/dynamics.ts +60 -0
  490. package/src/clis/zsxq/groups.ts +41 -0
  491. package/src/clis/zsxq/search.test.ts +29 -0
  492. package/src/clis/zsxq/search.ts +54 -0
  493. package/src/clis/zsxq/topic.test.ts +34 -0
  494. package/src/clis/zsxq/topic.ts +68 -0
  495. package/src/clis/zsxq/topics.test.ts +29 -0
  496. package/src/clis/zsxq/topics.ts +36 -0
  497. package/src/clis/zsxq/utils.ts +351 -0
  498. package/src/commanderAdapter.test.ts +77 -0
  499. package/src/commanderAdapter.ts +8 -1
  500. package/src/commands/daemon.test.ts +238 -0
  501. package/src/commands/daemon.ts +135 -0
  502. package/src/completion.ts +2 -1
  503. package/src/constants.ts +3 -0
  504. package/src/daemon.test.ts +88 -0
  505. package/src/daemon.ts +26 -14
  506. package/src/discovery.ts +52 -2
  507. package/src/electron-apps.test.ts +50 -0
  508. package/src/electron-apps.ts +89 -0
  509. package/src/engine.test.ts +45 -9
  510. package/src/execution.ts +24 -19
  511. package/src/external-clis.yaml +17 -0
  512. package/src/idle-manager.ts +60 -0
  513. package/src/launcher.test.ts +67 -0
  514. package/src/launcher.ts +185 -0
  515. package/src/main.ts +3 -2
  516. package/src/registry.test.ts +15 -0
  517. package/src/registry.ts +32 -3
  518. package/src/runtime.ts +13 -7
  519. package/src/serialization.test.ts +19 -1
  520. package/src/serialization.ts +2 -0
  521. package/src/tui.test.ts +23 -0
  522. package/src/tui.ts +65 -0
  523. package/src/types.ts +5 -0
  524. package/src/weixin-download.test.ts +27 -0
  525. package/tests/e2e/band-auth.test.ts +20 -0
  526. package/tests/e2e/browser-auth-helpers.ts +18 -0
  527. package/tests/e2e/browser-auth.test.ts +35 -47
  528. package/tests/e2e/browser-public-extended.test.ts +6 -2
  529. package/tests/e2e/browser-public.test.ts +288 -0
  530. package/tests/e2e/management.test.ts +1 -1
  531. package/tests/e2e/plugin-management.test.ts +1 -1
  532. package/vitest.config.ts +1 -0
  533. package/chatwise-opencli.ps1 +0 -82
  534. package/dist/clis/chatwise/shared.d.ts +0 -2
  535. package/dist/clis/chatwise/shared.js +0 -6
  536. package/dist/weread-private-api-regression.test.d.ts +0 -1
  537. package/dist/weread-search-regression.test.d.ts +0 -1
  538. package/dist/weread-search-regression.test.js +0 -39
  539. package/src/clis/chatwise/shared.ts +0 -8
  540. package/src/weread-search-regression.test.ts +0 -44
@@ -0,0 +1,48 @@
1
+ import { EmptyResultError } from '../../errors.js';
2
+ import { cli, Strategy } from '../../registry.js';
3
+ import { normalizeTiebaLimit } from './utils.js';
4
+ cli({
5
+ site: 'tieba',
6
+ name: 'hot',
7
+ description: 'Tieba hot topics',
8
+ domain: 'tieba.baidu.com',
9
+ strategy: Strategy.PUBLIC,
10
+ browser: true,
11
+ navigateBefore: false,
12
+ args: [
13
+ { name: 'limit', type: 'int', default: 20, help: 'Number of items to return' },
14
+ ],
15
+ columns: ['rank', 'title', 'discussions', 'description'],
16
+ func: async (page, kwargs) => {
17
+ const limit = normalizeTiebaLimit(kwargs.limit);
18
+ // Use the default browser settle path so we do not scrape the previous page.
19
+ await page.goto('https://tieba.baidu.com/hottopic/browse/topicList?res_type=1');
20
+ const raw = await page.evaluate(`(() => {
21
+ const items = document.querySelectorAll('li.topic-top-item');
22
+ return Array.from(items).map((item) => {
23
+ const titleEl = item.querySelector('a.topic-text');
24
+ const numEl = item.querySelector('span.topic-num');
25
+ const descEl = item.querySelector('p.topic-top-item-desc');
26
+ const href = titleEl?.getAttribute('href') || '';
27
+
28
+ return {
29
+ title: titleEl?.textContent?.trim() || '',
30
+ discussions: numEl?.textContent?.trim() || '',
31
+ description: descEl?.textContent?.trim() || '',
32
+ url: href.startsWith('http') ? href : 'https://tieba.baidu.com' + href,
33
+ };
34
+ }).filter((item) => item.title).slice(0, ${limit});
35
+ })()`);
36
+ const items = Array.isArray(raw) ? raw : [];
37
+ if (!items.length) {
38
+ throw new EmptyResultError('tieba hot', 'Tieba may have blocked the hot page, or the DOM structure may have changed');
39
+ }
40
+ return items.map((item, index) => ({
41
+ rank: index + 1,
42
+ title: item.title || '',
43
+ discussions: item.discussions || '',
44
+ description: item.description || '',
45
+ url: item.url || '',
46
+ }));
47
+ },
48
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,85 @@
1
+ import { EmptyResultError } from '../../errors.js';
2
+ import { cli, Strategy } from '../../registry.js';
3
+ import { buildTiebaPostCardsFromPagePc, buildTiebaPostItems, normalizeTiebaLimit, signTiebaPcParams, } from './utils.js';
4
+ function getForumPageNumber(kwargs) {
5
+ return Math.max(1, Number(kwargs.page || 1));
6
+ }
7
+ function getForumUrl(kwargs) {
8
+ const forum = String(kwargs.forum || '');
9
+ return `https://tieba.baidu.com/f?kw=${encodeURIComponent(forum)}&ie=utf-8&pn=${(getForumPageNumber(kwargs) - 1) * 50}`;
10
+ }
11
+ /**
12
+ * Rebuild the signed page_pc request instead of scraping only the visible thread cards.
13
+ */
14
+ function buildTiebaPagePcParams(kwargs, limit) {
15
+ return {
16
+ kw: encodeURIComponent(String(kwargs.forum || '')),
17
+ pn: String(getForumPageNumber(kwargs)),
18
+ sort_type: '-1',
19
+ is_newfrs: '1',
20
+ is_newfeed: '1',
21
+ rn: '30',
22
+ rn_need: String(Math.min(Math.max(limit + 10, 10), 30)),
23
+ tbs: '',
24
+ subapp_type: 'pc',
25
+ _client_type: '20',
26
+ };
27
+ }
28
+ /**
29
+ * Tieba expects the signed forum-list request to be replayed with the browser's cookies.
30
+ */
31
+ async function fetchTiebaPagePc(page, kwargs, limit) {
32
+ await page.goto(getForumUrl(kwargs), { waitUntil: 'none' });
33
+ await page.wait(2);
34
+ const params = buildTiebaPagePcParams(kwargs, limit);
35
+ const cookies = await page.getCookies({ domain: 'tieba.baidu.com' });
36
+ const cookieHeader = cookies.map((item) => `${item.name}=${item.value}`).join('; ');
37
+ const body = new URLSearchParams({
38
+ ...params,
39
+ sign: signTiebaPcParams(params),
40
+ }).toString();
41
+ const response = await fetch('https://tieba.baidu.com/c/f/frs/page_pc', {
42
+ method: 'POST',
43
+ headers: {
44
+ 'content-type': 'application/x-www-form-urlencoded;charset=UTF-8',
45
+ cookie: cookieHeader,
46
+ 'x-requested-with': 'XMLHttpRequest',
47
+ referer: getForumUrl(kwargs),
48
+ 'user-agent': 'Mozilla/5.0',
49
+ },
50
+ body,
51
+ });
52
+ const text = await response.text();
53
+ try {
54
+ return JSON.parse(text);
55
+ }
56
+ catch {
57
+ return {};
58
+ }
59
+ }
60
+ cli({
61
+ site: 'tieba',
62
+ name: 'posts',
63
+ description: 'Browse posts in a tieba forum',
64
+ domain: 'tieba.baidu.com',
65
+ strategy: Strategy.COOKIE,
66
+ browser: true,
67
+ navigateBefore: false,
68
+ args: [
69
+ { name: 'forum', positional: true, required: true, type: 'string', help: 'Forum name in Chinese' },
70
+ { name: 'page', type: 'int', default: 1, help: 'Page number' },
71
+ { name: 'limit', type: 'int', default: 20, help: 'Number of items to return' },
72
+ ],
73
+ columns: ['rank', 'title', 'author', 'replies'],
74
+ func: async (page, kwargs) => {
75
+ const limit = normalizeTiebaLimit(kwargs.limit);
76
+ const payload = await fetchTiebaPagePc(page, kwargs, limit);
77
+ const rawFeeds = Array.isArray(payload.page_data?.feed_list) ? payload.page_data.feed_list : [];
78
+ const rawCards = buildTiebaPostCardsFromPagePc(rawFeeds);
79
+ const items = buildTiebaPostItems(rawCards, limit);
80
+ if (!items.length || payload.error_code) {
81
+ throw new EmptyResultError('tieba posts', 'Tieba may have blocked the forum page, or the DOM structure may have changed');
82
+ }
83
+ return items;
84
+ },
85
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,140 @@
1
+ import { EmptyResultError } from '../../errors.js';
2
+ import { cli, Strategy } from '../../registry.js';
3
+ import { buildTiebaReadItems } from './utils.js';
4
+ function getThreadUrl(kwargs) {
5
+ const threadId = String(kwargs.id || '');
6
+ const pageNumber = Math.max(1, Number(kwargs.page || 1));
7
+ return `https://tieba.baidu.com/p/${encodeURIComponent(threadId)}?pn=${pageNumber}`;
8
+ }
9
+ /**
10
+ * Ensure the browser actually landed on the requested thread page before we trust the DOM.
11
+ */
12
+ function assertTiebaReadTargetPage(raw, kwargs) {
13
+ const expectedThreadId = String(kwargs.id || '').trim();
14
+ const expectedPageNumber = Math.max(1, Number(kwargs.page || 1));
15
+ const pathname = String(raw.pageMeta?.pathname || '').trim();
16
+ const actualThreadId = pathname.match(/^\/p\/(\d+)/)?.[1] || '';
17
+ const actualPn = String(raw.pageMeta?.pn || '').trim();
18
+ if (!actualThreadId || actualThreadId !== expectedThreadId) {
19
+ throw new EmptyResultError('tieba read', 'Tieba did not land on the requested thread page');
20
+ }
21
+ if (expectedPageNumber > 1 && actualPn !== String(expectedPageNumber)) {
22
+ throw new EmptyResultError('tieba read', 'Tieba did not land on the requested page');
23
+ }
24
+ }
25
+ function buildExtractReadEvaluate() {
26
+ return `
27
+ (async () => {
28
+ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
29
+ const waitFor = async (predicate, timeoutMs = 4000) => {
30
+ const start = Date.now();
31
+ while (Date.now() - start < timeoutMs) {
32
+ if (predicate()) return true;
33
+ await wait(100);
34
+ }
35
+ return false;
36
+ };
37
+ const normalizeText = (value) => (value || '').replace(/\\s+/g, ' ').trim();
38
+ const getVueProps = (element) => {
39
+ const vue = element && element.__vue__ ? element.__vue__ : null;
40
+ return vue ? (vue._props || vue.$props || {}) : {};
41
+ };
42
+ const extractStructuredText = (content) => {
43
+ if (!Array.isArray(content)) return '';
44
+ return content
45
+ .map((part) => (part && typeof part === 'object' && typeof part.text === 'string') ? part.text : '')
46
+ .join('')
47
+ .replace(/\\s+/g, ' ')
48
+ .trim();
49
+ };
50
+ const parseFloor = (text) => {
51
+ const match = (text || '').match(/第(\\d+)楼/);
52
+ return match ? parseInt(match[1], 10) : 0;
53
+ };
54
+
55
+ await waitFor(() => {
56
+ const hasMainTree = document.querySelector('.pb-title-wrap.pc-pb-title') || document.querySelector('.pb-content-wrap');
57
+ return Boolean(hasMainTree || document.querySelector('.pb-comment-item'));
58
+ });
59
+
60
+ const titleNode = document.querySelector('.pb-title-wrap.pc-pb-title');
61
+ const titleProps = getVueProps(titleNode);
62
+ const mainUser = document.querySelector('.head-line.user-info:not(.no-extra-margin)');
63
+ const mainUserProps = getVueProps(mainUser);
64
+ const contentWrap = document.querySelector('.pb-content-wrap');
65
+ const contentProps = getVueProps(contentWrap);
66
+ const structuredContent = Array.isArray(contentProps.content) ? contentProps.content : [];
67
+ const visibleContent = normalizeText(
68
+ contentWrap?.querySelector('.pb-content-item .text')?.textContent
69
+ || contentWrap?.querySelector('.text')?.textContent
70
+ || contentWrap?.textContent
71
+ );
72
+
73
+ return {
74
+ pageMeta: {
75
+ pathname: window.location.pathname || '',
76
+ pn: new URLSearchParams(window.location.search).get('pn') || '',
77
+ },
78
+ mainPost: {
79
+ title: typeof titleProps.title === 'string' && titleProps.title.trim()
80
+ ? titleProps.title.trim()
81
+ : normalizeText(titleNode?.textContent).replace(/-百度贴吧$/, '').trim(),
82
+ author: normalizeText(
83
+ mainUser?.querySelector('.head-name')?.textContent
84
+ || mainUser?.querySelector('.name-info .head-name')?.textContent
85
+ || ''
86
+ ),
87
+ fallbackAuthor: mainUserProps?.userShowInfo?.[0]?.text?.text || '',
88
+ contentText: visibleContent,
89
+ structuredText: extractStructuredText(structuredContent),
90
+ visibleTime: (() => {
91
+ const userText = normalizeText(mainUser?.textContent);
92
+ const match = userText.match(/(刚刚|昨天|前天|\\d+\\s*(?:分钟|小时|天)前|\\d{2}-\\d{2}(?:\\s+\\d{2}:\\d{2})?|\\d{4}-\\d{2}-\\d{2}(?:\\s+\\d{2}:\\d{2})?)/);
93
+ return match ? match[1].trim() : '';
94
+ })(),
95
+ structuredTime: mainUserProps?.descInfo?.time || 0,
96
+ hasMedia: structuredContent.length > 0 && !extractStructuredText(structuredContent),
97
+ },
98
+ replies: Array.from(document.querySelectorAll('.pb-comment-item')).map((item) => {
99
+ const meta = item.querySelector('.comment-desc-left')?.textContent?.replace(/\\s+/g, ' ').trim() || '';
100
+ return {
101
+ floor: parseFloor(meta),
102
+ author: item.querySelector('.head-name')?.textContent?.trim() || '',
103
+ content: item.querySelector('.comment-content .pb-content-item .text')?.textContent?.replace(/\\s+/g, ' ').trim() || '',
104
+ time: meta,
105
+ };
106
+ }),
107
+ };
108
+ })()
109
+ `;
110
+ }
111
+ cli({
112
+ site: 'tieba',
113
+ name: 'read',
114
+ description: 'Read a tieba thread',
115
+ domain: 'tieba.baidu.com',
116
+ strategy: Strategy.COOKIE,
117
+ browser: true,
118
+ navigateBefore: false,
119
+ args: [
120
+ { name: 'id', positional: true, required: true, type: 'string', help: 'Thread ID' },
121
+ { name: 'page', type: 'int', default: 1, help: 'Page number' },
122
+ { name: 'limit', type: 'int', default: 30, help: 'Number of replies to return' },
123
+ ],
124
+ columns: ['floor', 'author', 'content', 'time'],
125
+ func: async (page, kwargs) => {
126
+ const pageNumber = Math.max(1, Number(kwargs.page || 1));
127
+ // Use the browser's normal settle path so we do not scrape stale DOM from the previous tab state.
128
+ await page.goto(getThreadUrl(kwargs));
129
+ const raw = (await page.evaluate(buildExtractReadEvaluate()) || {});
130
+ assertTiebaReadTargetPage(raw, kwargs);
131
+ const items = buildTiebaReadItems(raw, {
132
+ limit: kwargs.limit,
133
+ includeMainPost: pageNumber === 1,
134
+ });
135
+ if (!items.length) {
136
+ throw new EmptyResultError('tieba read', 'Tieba may have blocked the thread page, or the DOM structure may have changed');
137
+ }
138
+ return items;
139
+ },
140
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,108 @@
1
+ import { ArgumentError, EmptyResultError } from '../../errors.js';
2
+ import { cli, Strategy } from '../../registry.js';
3
+ import { buildTiebaSearchItems, normalizeTiebaLimit } from './utils.js';
4
+ const MAX_SUPPORTED_PAGE = '1';
5
+ /**
6
+ * Extract search result cards from tieba's current desktop search page.
7
+ */
8
+ function buildExtractSearchResultsEvaluate(limit) {
9
+ return `
10
+ (async () => {
11
+ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
12
+ const waitFor = async (predicate, timeoutMs = 5000) => {
13
+ const start = Date.now();
14
+ while (Date.now() - start < timeoutMs) {
15
+ if (predicate()) return true;
16
+ await wait(100);
17
+ }
18
+ return false;
19
+ };
20
+ const getVueProps = (element) => {
21
+ const vue = element && element.__vue__ ? element.__vue__ : null;
22
+ return vue ? (vue._props || vue.$props || {}) : {};
23
+ };
24
+ await waitFor(() => {
25
+ const bodyText = document.body?.innerText || '';
26
+ return Boolean(
27
+ document.querySelector('.threadcardclass.thread-new3.index-feed-cards')
28
+ || document.querySelector('.search-no-result, .search-nodata, .no-result')
29
+ || /百度安全验证|安全验证|请完成验证/.test(bodyText)
30
+ );
31
+ });
32
+ const items = document.querySelectorAll('.threadcardclass.thread-new3.index-feed-cards');
33
+ return Array.from(items).slice(0, ${limit}).map((item) => {
34
+ const forum = item.querySelector('.forum-name-text, .forum-name')?.textContent?.trim() || '';
35
+ const meta = item.querySelector('.user-forum-info')?.textContent?.replace(/\\s+/g, ' ').trim() || '';
36
+ const metaWithoutForum = forum && meta.startsWith(forum)
37
+ ? meta.slice(forum.length).trim()
38
+ : meta;
39
+ const metaMatch = metaWithoutForum.match(/^(.*?)\\s*发布于\\s*(.+)$/);
40
+ const actionBar = item.querySelector('.action-bar-container.search-action-bar');
41
+ const businessInfo = getVueProps(actionBar).businessInfo || {};
42
+ const href = item.querySelector('a[href*="/p/"]')?.href || '';
43
+ const threadId = String(businessInfo.thread_id || '').trim();
44
+ const title = item.querySelector('.title-wrap')?.textContent?.trim()
45
+ || item.querySelector('.title-content-wrap')?.textContent?.trim()
46
+ || '';
47
+ const snippet = item.querySelector('.title-content-wrap')?.textContent?.trim()
48
+ || item.querySelector('.abstract-wrap')?.textContent?.trim()
49
+ || '';
50
+
51
+ return {
52
+ title,
53
+ forum,
54
+ author: metaMatch ? metaMatch[1].trim() : metaWithoutForum,
55
+ time: metaMatch ? metaMatch[2].trim() : '',
56
+ snippet: snippet.substring(0, 200),
57
+ id: threadId,
58
+ url: href || (threadId ? 'https://tieba.baidu.com/p/' + threadId : ''),
59
+ };
60
+ }).filter((item) => item.title);
61
+ })()
62
+ `;
63
+ }
64
+ /**
65
+ * Normalize CLI args into the concrete search page URL.
66
+ */
67
+ function getSearchUrl(kwargs) {
68
+ const keyword = String(kwargs.keyword || '');
69
+ const pageNumber = Number(kwargs.page || 1);
70
+ return `https://tieba.baidu.com/f/search/res?qw=${encodeURIComponent(keyword)}&ie=utf-8&pn=${pageNumber}`;
71
+ }
72
+ /**
73
+ * Tieba's current desktop search UI no longer exposes a reliable browser-page transition.
74
+ */
75
+ function assertSupportedPage(kwargs) {
76
+ const pageNumber = String(kwargs.page || 1);
77
+ if (pageNumber === MAX_SUPPORTED_PAGE)
78
+ return;
79
+ throw new ArgumentError(`tieba search currently only supports --page ${MAX_SUPPORTED_PAGE}`, `Baidu Tieba search no longer exposes stable browser pagination; omit --page or use --page ${MAX_SUPPORTED_PAGE}`);
80
+ }
81
+ cli({
82
+ site: 'tieba',
83
+ name: 'search',
84
+ description: 'Search posts across tieba',
85
+ domain: 'tieba.baidu.com',
86
+ strategy: Strategy.COOKIE,
87
+ browser: true,
88
+ navigateBefore: false,
89
+ args: [
90
+ { name: 'keyword', positional: true, required: true, type: 'string', help: 'Search keyword' },
91
+ // Restrict unsupported pages before the browser session starts.
92
+ { name: 'page', type: 'int', default: 1, choices: ['1'], help: 'Page number (currently only 1 is supported)' },
93
+ { name: 'limit', type: 'int', default: 20, help: 'Number of items to return' },
94
+ ],
95
+ columns: ['rank', 'title', 'forum', 'author', 'time'],
96
+ func: async (page, kwargs) => {
97
+ assertSupportedPage(kwargs);
98
+ const limit = normalizeTiebaLimit(kwargs.limit);
99
+ // Use the default browser settle path so we do not read a stale page.
100
+ await page.goto(getSearchUrl(kwargs));
101
+ const raw = await page.evaluate(buildExtractSearchResultsEvaluate(limit));
102
+ const items = buildTiebaSearchItems(Array.isArray(raw) ? raw : [], limit);
103
+ if (!items.length) {
104
+ throw new EmptyResultError('tieba search', 'Tieba may have blocked the result page, or the DOM structure may have changed');
105
+ }
106
+ return items;
107
+ },
108
+ });
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Shared Tieba parsing helpers used by the browser adapters.
3
+ */
4
+ export declare const MAX_TIEBA_LIMIT = 20;
5
+ export interface RawTiebaPostCard {
6
+ title?: string;
7
+ author?: string;
8
+ descInfo?: string;
9
+ actionTexts?: string[];
10
+ commentCount?: unknown;
11
+ threadId?: unknown;
12
+ url?: unknown;
13
+ }
14
+ export interface RawTiebaPagePcFeedEntry {
15
+ layout?: string;
16
+ feed?: {
17
+ schema?: unknown;
18
+ log_param?: Array<{
19
+ key?: unknown;
20
+ value?: unknown;
21
+ }>;
22
+ business_info_map?: Record<string, unknown>;
23
+ components?: Array<Record<string, unknown>>;
24
+ };
25
+ }
26
+ export interface TiebaPostItem {
27
+ rank: number;
28
+ title: string;
29
+ author: string;
30
+ replies: number;
31
+ last_reply: string;
32
+ id: string;
33
+ url: string;
34
+ }
35
+ export interface RawTiebaSearchItem {
36
+ title?: string;
37
+ forum?: string;
38
+ author?: string;
39
+ time?: string;
40
+ snippet?: string;
41
+ id?: string;
42
+ url?: string;
43
+ }
44
+ export interface TiebaSearchItem {
45
+ rank: number;
46
+ title: string;
47
+ forum: string;
48
+ author: string;
49
+ time: string;
50
+ snippet: string;
51
+ id: string;
52
+ url: string;
53
+ }
54
+ export interface RawTiebaMainPost {
55
+ title?: string;
56
+ author?: string;
57
+ fallbackAuthor?: string;
58
+ contentText?: string;
59
+ structuredText?: string;
60
+ visibleTime?: string;
61
+ structuredTime?: unknown;
62
+ hasMedia?: boolean;
63
+ }
64
+ export interface RawTiebaReply {
65
+ floor?: unknown;
66
+ author?: string;
67
+ content?: string;
68
+ time?: string;
69
+ }
70
+ export interface RawTiebaReadPayload {
71
+ mainPost?: RawTiebaMainPost | null;
72
+ replies?: RawTiebaReply[];
73
+ }
74
+ export interface TiebaReadItem {
75
+ floor: number;
76
+ author: string;
77
+ content: string;
78
+ time: string;
79
+ }
80
+ export interface TiebaReadBuildOptions {
81
+ limit?: unknown;
82
+ includeMainPost?: boolean;
83
+ }
84
+ /**
85
+ * Keep the public CLI limit contract aligned with the real implementation.
86
+ */
87
+ export declare function normalizeTiebaLimit(value: unknown, fallback?: number): number;
88
+ export declare function normalizeText(value: unknown): string;
89
+ /**
90
+ * Match Tieba PC's signed request contract so forum list fetching stays stable.
91
+ */
92
+ export declare function signTiebaPcParams(params: Record<string, string>): string;
93
+ export declare function parseTiebaCount(text: string): number;
94
+ export declare function parseTiebaLastReply(text: string): string;
95
+ /**
96
+ * Convert Tieba's signed `page_pc` feed entries into the stable card shape used by the CLI.
97
+ */
98
+ export declare function buildTiebaPostCardsFromPagePc(rawFeeds: RawTiebaPagePcFeedEntry[]): RawTiebaPostCard[];
99
+ export declare function buildTiebaPostItems(rawCards: RawTiebaPostCard[], requestedLimit: unknown): TiebaPostItem[];
100
+ export declare function buildTiebaSearchItems(rawItems: RawTiebaSearchItem[], requestedLimit: unknown): TiebaSearchItem[];
101
+ export declare function buildTiebaReadItems(payload: RawTiebaReadPayload, options?: TiebaReadBuildOptions): TiebaReadItem[];