publishport-opencli 1.0.19 → 1.0.21

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 (1042) hide show
  1. package/cli-manifest.json +35 -0
  2. package/clis/12306/me.js +2 -2
  3. package/clis/12306/orders.js +3 -3
  4. package/clis/12306/passengers.js +3 -3
  5. package/clis/12306/price.js +1 -1
  6. package/clis/12306/stations.js +1 -1
  7. package/clis/12306/train.js +1 -1
  8. package/clis/12306/trains.js +1 -1
  9. package/clis/12306/utils.js +1 -1
  10. package/clis/1688/download.js +1 -1
  11. package/clis/1688/item.js +4 -4
  12. package/clis/1688/search.js +4 -4
  13. package/clis/1688/store.js +4 -4
  14. package/clis/1point3acres/forum.js +1 -1
  15. package/clis/1point3acres/forums.js +1 -1
  16. package/clis/1point3acres/notifications.js +1 -1
  17. package/clis/1point3acres/search.js +1 -1
  18. package/clis/1point3acres/thread.js +2 -2
  19. package/clis/1point3acres/user.js +1 -1
  20. package/clis/1point3acres/utils.js +2 -2
  21. package/clis/36kr/article.js +2 -2
  22. package/clis/36kr/hot.js +2 -2
  23. package/clis/36kr/news.js +1 -1
  24. package/clis/36kr/search.js +2 -2
  25. package/clis/51job/company.js +2 -2
  26. package/clis/51job/detail.js +2 -2
  27. package/clis/51job/hot.js +1 -1
  28. package/clis/51job/search.js +1 -1
  29. package/clis/51job/utils.js +7 -7
  30. package/clis/_atlassian/shared.js +9 -9
  31. package/clis/_shared/article/auth.js +4 -4
  32. package/clis/_shared/article/douban-md2draft.js +4 -4
  33. package/clis/_shared/article/format.js +1 -1
  34. package/clis/_shared/article/images.js +7 -7
  35. package/clis/_shared/article/login.js +1 -1
  36. package/clis/_shared/article/publish.js +11 -11
  37. package/clis/_shared/common.js +1 -1
  38. package/clis/_shared/content-guard.js +1 -1
  39. package/clis/_shared/desktop-commands.js +1 -1
  40. package/clis/_shared/file-inject.js +12 -12
  41. package/clis/_shared/self-hosted-sites.js +2 -2
  42. package/clis/_shared/site-auth.js +1 -1
  43. package/clis/_shared/token-auth.js +2 -2
  44. package/clis/_shared/video-publish.js +9 -9
  45. package/clis/amazon/offer.js +3 -3
  46. package/clis/amazon/product.js +5 -5
  47. package/clis/amazon/shared.js +6 -6
  48. package/clis/antigravity/_actions.js +13 -13
  49. package/clis/antigravity/audit-extras.js +10 -10
  50. package/clis/antigravity/delete.js +1 -1
  51. package/clis/antigravity/model.js +6 -6
  52. package/clis/antigravity/new.js +2 -2
  53. package/clis/antigravity/read.js +2 -2
  54. package/clis/antigravity/rename.js +1 -1
  55. package/clis/antigravity/send.js +3 -3
  56. package/clis/antigravity/serve.js +17 -17
  57. package/clis/antigravity/storage.js +6 -6
  58. package/clis/antigravity/watch.js +2 -2
  59. package/clis/apple-podcasts/episodes.js +1 -1
  60. package/clis/apple-podcasts/top.js +1 -1
  61. package/clis/apple-podcasts/utils.js +1 -1
  62. package/clis/archive/item.js +1 -1
  63. package/clis/archive/search.js +1 -1
  64. package/clis/archive/snapshots.js +1 -1
  65. package/clis/archive/wayback.js +1 -1
  66. package/clis/arxiv/author.js +1 -1
  67. package/clis/arxiv/utils.js +1 -1
  68. package/clis/autohome/brand.js +1 -1
  69. package/clis/autohome/score.js +1 -1
  70. package/clis/autohome/utils.js +1 -1
  71. package/clis/baijiahao/article.js +1 -1
  72. package/clis/baijiahao/lists.js +1 -1
  73. package/clis/baijiahao/login.js +1 -1
  74. package/clis/baijiahao/publish.js +9 -9
  75. package/clis/baijiahao/stats.js +1 -1
  76. package/clis/baijiahao/whoami.js +1 -1
  77. package/clis/band/bands.js +2 -2
  78. package/clis/band/mentions.js +2 -2
  79. package/clis/band/post.js +4 -4
  80. package/clis/band/posts.js +3 -3
  81. package/clis/barchart/flow.js +3 -3
  82. package/clis/barchart/greeks.js +2 -2
  83. package/clis/barchart/quote.js +3 -3
  84. package/clis/bbc/news.js +1 -1
  85. package/clis/bbc/topic.js +1 -1
  86. package/clis/bbc/utils.js +1 -1
  87. package/clis/bilibili/article.js +1 -1
  88. package/clis/bilibili/categories.js +1 -1
  89. package/clis/bilibili/coin.js +1 -1
  90. package/clis/bilibili/comment-del.js +1 -1
  91. package/clis/bilibili/comment-like.js +1 -1
  92. package/clis/bilibili/comment.js +1 -1
  93. package/clis/bilibili/comments.js +1 -1
  94. package/clis/bilibili/dm-list.js +1 -1
  95. package/clis/bilibili/dm-read.js +1 -1
  96. package/clis/bilibili/dm-send.js +1 -1
  97. package/clis/bilibili/download.js +2 -2
  98. package/clis/bilibili/drafts.js +1 -1
  99. package/clis/bilibili/dynamic-post.js +3 -3
  100. package/clis/bilibili/favorite-add.js +1 -1
  101. package/clis/bilibili/favorite.js +1 -1
  102. package/clis/bilibili/feed.js +2 -2
  103. package/clis/bilibili/follow.js +1 -1
  104. package/clis/bilibili/following.js +1 -1
  105. package/clis/bilibili/like.js +1 -1
  106. package/clis/bilibili/partitions.js +1 -1
  107. package/clis/bilibili/stats.js +1 -1
  108. package/clis/bilibili/subtitle.js +3 -3
  109. package/clis/bilibili/summary.js +1 -1
  110. package/clis/bilibili/topics.js +1 -1
  111. package/clis/bilibili/unfollow.js +1 -1
  112. package/clis/bilibili/upload.js +1 -1
  113. package/clis/bilibili/utils.js +10 -10
  114. package/clis/bilibili/video-drafts.js +1 -1
  115. package/clis/bilibili/video.js +1 -1
  116. package/clis/bloomberg/businessweek.js +4 -4
  117. package/clis/bloomberg/news.js +2 -2
  118. package/clis/bloomberg/utils.js +13 -13
  119. package/clis/bluesky/post.js +1 -1
  120. package/clis/bluesky/shared.js +11 -11
  121. package/clis/bluesky/whoami.js +1 -1
  122. package/clis/booking/search.js +2 -2
  123. package/clis/boss/accept.js +1 -1
  124. package/clis/boss/applied.js +1 -1
  125. package/clis/boss/auth.js +1 -1
  126. package/clis/boss/batchgreet.js +1 -1
  127. package/clis/boss/bossinfo.js +1 -1
  128. package/clis/boss/chatlist.js +1 -1
  129. package/clis/boss/chatmsg.js +1 -1
  130. package/clis/boss/cities.js +1 -1
  131. package/clis/boss/detail.js +1 -1
  132. package/clis/boss/exchange.js +1 -1
  133. package/clis/boss/greet.js +1 -1
  134. package/clis/boss/interviews.js +1 -1
  135. package/clis/boss/invite.js +1 -1
  136. package/clis/boss/joblist.js +1 -1
  137. package/clis/boss/mark.js +1 -1
  138. package/clis/boss/me.js +2 -2
  139. package/clis/boss/recommend.js +1 -1
  140. package/clis/boss/resumedelete.js +1 -1
  141. package/clis/boss/resumelist.js +1 -1
  142. package/clis/boss/resumeupload.js +11 -11
  143. package/clis/boss/search.js +1 -1
  144. package/clis/boss/send.js +1 -1
  145. package/clis/boss/sendresume.js +1 -1
  146. package/clis/boss/stats.js +1 -1
  147. package/clis/boss/unread.js +1 -1
  148. package/clis/boss/utils.js +13 -13
  149. package/clis/chaoxing/assignments.js +1 -1
  150. package/clis/chaoxing/exams.js +1 -1
  151. package/clis/chaoxing/utils.js +9 -9
  152. package/clis/chatgpt/ask.js +1 -1
  153. package/clis/chatgpt/auth.js +2 -2
  154. package/clis/chatgpt/detail.js +1 -1
  155. package/clis/chatgpt/image.js +1 -1
  156. package/clis/chatgpt/read.js +1 -1
  157. package/clis/chatgpt/send.js +1 -1
  158. package/clis/chatgpt/utils.js +59 -59
  159. package/clis/chatgpt-app/ask.js +1 -1
  160. package/clis/chatgpt-app/send.js +1 -1
  161. package/clis/chatwise/model.js +6 -6
  162. package/clis/chess/analyze.js +1 -1
  163. package/clis/chess/game.js +1 -1
  164. package/clis/chess/games.js +1 -1
  165. package/clis/chess/stats.js +1 -1
  166. package/clis/chess/utils.js +1 -1
  167. package/clis/claude/ask.js +2 -2
  168. package/clis/claude/detail.js +1 -1
  169. package/clis/claude/new.js +1 -1
  170. package/clis/claude/read.js +1 -1
  171. package/clis/claude/send.js +1 -1
  172. package/clis/claude/utils.js +23 -23
  173. package/clis/cnblogs/article.js +1 -1
  174. package/clis/cnblogs/login.js +1 -1
  175. package/clis/cnblogs/stats.js +7 -7
  176. package/clis/cnblogs/whoami.js +1 -1
  177. package/clis/codex/_actions.js +3 -3
  178. package/clis/codex/archive.js +1 -1
  179. package/clis/codex/ask.js +6 -6
  180. package/clis/codex/model.js +8 -8
  181. package/clis/codex/pin.js +1 -1
  182. package/clis/codex/rename.js +4 -4
  183. package/clis/codex/send.js +3 -3
  184. package/clis/codex/sidebar.js +1 -1
  185. package/clis/coingecko/categories.js +1 -1
  186. package/clis/coingecko/coin.js +1 -1
  187. package/clis/coingecko/derivatives.js +1 -1
  188. package/clis/coingecko/exchanges.js +1 -1
  189. package/clis/coingecko/global.js +1 -1
  190. package/clis/coingecko/trending.js +1 -1
  191. package/clis/confluence/search.js +1 -1
  192. package/clis/coupang/product.js +3 -3
  193. package/clis/coupang/utils.js +1 -1
  194. package/clis/crates/crate.js +1 -1
  195. package/clis/crates/search.js +1 -1
  196. package/clis/crates/utils.js +1 -1
  197. package/clis/csdn/article.js +13 -13
  198. package/clis/csdn/columns.js +1 -1
  199. package/clis/csdn/login.js +1 -1
  200. package/clis/csdn/stats.js +4 -4
  201. package/clis/csdn/whoami.js +1 -1
  202. package/clis/cto51/article.js +1 -1
  203. package/clis/cto51/whoami.js +1 -1
  204. package/clis/ctrip/flight.js +2 -2
  205. package/clis/ctrip/hotel-search.js +3 -3
  206. package/clis/ctrip/hotel-suggest.js +1 -1
  207. package/clis/ctrip/search.js +1 -1
  208. package/clis/ctrip/utils.js +6 -6
  209. package/clis/cursor/ask.js +5 -5
  210. package/clis/cursor/composer.js +2 -2
  211. package/clis/cursor/model.js +4 -4
  212. package/clis/cursor/send.js +2 -2
  213. package/clis/dblp/author.js +1 -1
  214. package/clis/dblp/paper.js +1 -1
  215. package/clis/dblp/search.js +1 -1
  216. package/clis/dblp/utils.js +1 -1
  217. package/clis/dblp/venue.js +1 -1
  218. package/clis/deepseek/ask.js +1 -1
  219. package/clis/deepseek/auth.js +2 -2
  220. package/clis/deepseek/detail.js +1 -1
  221. package/clis/deepseek/new.js +1 -1
  222. package/clis/deepseek/read.js +1 -1
  223. package/clis/deepseek/send.js +7 -7
  224. package/clis/deepseek/utils.js +25 -25
  225. package/clis/defillama/protocol.js +1 -1
  226. package/clis/defillama/protocols.js +1 -1
  227. package/clis/defillama/utils.js +1 -1
  228. package/clis/devto/auth.js +2 -2
  229. package/clis/devto/latest.js +1 -1
  230. package/clis/devto/publish.js +5 -5
  231. package/clis/devto/read.js +2 -2
  232. package/clis/devto/stats.js +3 -3
  233. package/clis/dianping/auth.js +2 -2
  234. package/clis/dianping/cityResolver.js +2 -2
  235. package/clis/dianping/search.js +1 -1
  236. package/clis/dianping/shop.js +1 -1
  237. package/clis/dianping/utils.js +1 -1
  238. package/clis/discord-app/delete.js +3 -3
  239. package/clis/discord-app/read.js +1 -1
  240. package/clis/discord-app/thread-read.js +1 -1
  241. package/clis/discord-web/auth.js +2 -2
  242. package/clis/discord-web/send.js +5 -5
  243. package/clis/dockerhub/image.js +1 -1
  244. package/clis/dockerhub/search.js +1 -1
  245. package/clis/dockerhub/utils.js +1 -1
  246. package/clis/dongchedi/koubei.js +1 -1
  247. package/clis/dongchedi/models.js +1 -1
  248. package/clis/dongchedi/score.js +1 -1
  249. package/clis/dongchedi/search.js +1 -1
  250. package/clis/dongchedi/series.js +1 -1
  251. package/clis/dongchedi/specs.js +1 -1
  252. package/clis/dongchedi/utils.js +1 -1
  253. package/clis/douban/article.js +3 -3
  254. package/clis/douban/auth.js +2 -2
  255. package/clis/douban/download.js +1 -1
  256. package/clis/douban/utils.js +23 -23
  257. package/clis/doubao/auth.js +3 -3
  258. package/clis/doubao/utils.js +39 -39
  259. package/clis/doubao-app/ask.js +1 -1
  260. package/clis/doubao-app/utils.js +4 -4
  261. package/clis/douyin/_shared/browser-fetch.js +7 -7
  262. package/clis/douyin/_shared/draft-cache.js +1 -1
  263. package/clis/douyin/_shared/imagex-upload.js +1 -1
  264. package/clis/douyin/_shared/sts2.js +1 -1
  265. package/clis/douyin/_shared/text-extra.js +1 -1
  266. package/clis/douyin/_shared/tos-upload.js +4 -4
  267. package/clis/douyin/_shared/transcode.js +1 -1
  268. package/clis/douyin/_shared/vod-upload.js +4 -4
  269. package/clis/douyin/draft.js +18 -18
  270. package/clis/douyin/drafts.js +1 -1
  271. package/clis/douyin/publish-image.js +12 -12
  272. package/clis/douyin/publish.js +9 -9
  273. package/clis/douyin/search.js +3 -3
  274. package/clis/douyin/videos.js +1 -1
  275. package/clis/eastmoney/_secid.js +1 -1
  276. package/clis/eastmoney/announcement.js +1 -1
  277. package/clis/eastmoney/article.js +1 -1
  278. package/clis/eastmoney/convertible.js +1 -1
  279. package/clis/eastmoney/etf.js +1 -1
  280. package/clis/eastmoney/holders.js +1 -1
  281. package/clis/eastmoney/index-board.js +1 -1
  282. package/clis/eastmoney/kline.js +1 -1
  283. package/clis/eastmoney/kuaixun.js +1 -1
  284. package/clis/eastmoney/longhu.js +1 -1
  285. package/clis/eastmoney/money-flow.js +1 -1
  286. package/clis/eastmoney/northbound.js +1 -1
  287. package/clis/eastmoney/quote.js +1 -1
  288. package/clis/eastmoney/rank.js +1 -1
  289. package/clis/eastmoney/sectors.js +1 -1
  290. package/clis/endoflife/product.js +1 -1
  291. package/clis/endoflife/utils.js +1 -1
  292. package/clis/facebook/comment.js +8 -8
  293. package/clis/facebook/feed.js +4 -4
  294. package/clis/facebook/like.js +5 -5
  295. package/clis/facebook/notifications.js +3 -3
  296. package/clis/facebook/post.js +11 -11
  297. package/clis/facebook/search.js +3 -3
  298. package/clis/flathub/app.js +1 -1
  299. package/clis/flathub/search.js +1 -1
  300. package/clis/flathub/utils.js +1 -1
  301. package/clis/flomo/memos.js +1 -1
  302. package/clis/gemini/deep-research-result.js +4 -4
  303. package/clis/gemini/deep-research.js +1 -1
  304. package/clis/gemini/detail.js +1 -1
  305. package/clis/gemini/history.js +1 -1
  306. package/clis/gemini/image.js +2 -2
  307. package/clis/gemini/status.js +1 -1
  308. package/clis/gemini/utils.js +43 -43
  309. package/clis/geogebra/hexagon.js +1 -1
  310. package/clis/geogebra/info.js +3 -3
  311. package/clis/geogebra/triangle.js +1 -1
  312. package/clis/geogebra/utils.js +11 -11
  313. package/clis/ghost/login.js +1 -1
  314. package/clis/ghost/shared.js +2 -2
  315. package/clis/gitee/auth.js +2 -2
  316. package/clis/github-trending/repos.js +1 -1
  317. package/clis/google/news.js +1 -1
  318. package/clis/google/search.js +2 -2
  319. package/clis/google/suggest.js +1 -1
  320. package/clis/google/trends.js +1 -1
  321. package/clis/google/utils.js +1 -1
  322. package/clis/goproxy/module.js +1 -1
  323. package/clis/goproxy/utils.js +1 -1
  324. package/clis/goproxy/versions.js +1 -1
  325. package/clis/gov-policy/recent.js +2 -2
  326. package/clis/gov-policy/search.js +2 -2
  327. package/clis/grok/ask.js +1 -1
  328. package/clis/grok/detail.js +1 -1
  329. package/clis/grok/image.js +8 -8
  330. package/clis/grok/pin.js +1 -1
  331. package/clis/grok/send.js +1 -1
  332. package/clis/grok/status.js +1 -1
  333. package/clis/grok/utils.js +21 -21
  334. package/clis/guazi/browse.js +1 -1
  335. package/clis/guazi/car.js +1 -1
  336. package/clis/guazi/utils.js +1 -1
  337. package/clis/hackernews/auth.js +2 -2
  338. package/clis/hackernews/comment.js +8 -8
  339. package/clis/hackernews/read.js +7 -7
  340. package/clis/hackernews/submit.js +7 -7
  341. package/clis/hashnode/auth.js +3 -3
  342. package/clis/hashnode/publish.js +14 -14
  343. package/clis/hf/auth.js +2 -2
  344. package/clis/hf/models.js +1 -1
  345. package/clis/hf/paper.js +1 -1
  346. package/clis/hf/spaces.js +1 -1
  347. package/clis/hf/top.js +1 -1
  348. package/clis/homebrew/cask.js +1 -1
  349. package/clis/homebrew/formula.js +1 -1
  350. package/clis/homebrew/popular.js +1 -1
  351. package/clis/homebrew/utils.js +1 -1
  352. package/clis/huodongxing/events.js +1 -1
  353. package/clis/hupu/detail.js +4 -4
  354. package/clis/hupu/hot.js +3 -3
  355. package/clis/hupu/reply.js +1 -1
  356. package/clis/hupu/search.js +1 -1
  357. package/clis/hupu/unlike.js +1 -1
  358. package/clis/hupu/utils.js +10 -10
  359. package/clis/imdb/person.js +2 -2
  360. package/clis/imdb/reviews.js +3 -3
  361. package/clis/imdb/search.js +2 -2
  362. package/clis/imdb/title.js +1 -1
  363. package/clis/imdb/top.js +1 -1
  364. package/clis/imdb/trending.js +1 -1
  365. package/clis/imdb/utils.js +13 -13
  366. package/clis/imooc/article.js +6 -6
  367. package/clis/imooc/login.js +1 -1
  368. package/clis/imooc/whoami.js +1 -1
  369. package/clis/indeed/job.js +2 -2
  370. package/clis/indeed/search.js +2 -2
  371. package/clis/indeed/utils.js +1 -1
  372. package/clis/infoq/article.js +2 -2
  373. package/clis/infoq/login.js +1 -1
  374. package/clis/infoq/whoami.js +1 -1
  375. package/clis/instagram/_shared/private-publish.js +4 -4
  376. package/clis/instagram/_shared/protocol-capture.js +9 -9
  377. package/clis/instagram/detail.js +3 -3
  378. package/clis/instagram/post.js +25 -25
  379. package/clis/instagram/reel.js +18 -18
  380. package/clis/instagram/story.js +4 -4
  381. package/clis/instagram/user.js +2 -2
  382. package/clis/jd/item.js +65 -65
  383. package/clis/jianshu/article.js +1 -1
  384. package/clis/jianshu/login.js +1 -1
  385. package/clis/jianshu/notebooks.js +1 -1
  386. package/clis/jianshu/whoami.js +1 -1
  387. package/clis/jianyu/search.js +6 -6
  388. package/clis/jianyu/shared/procurement-contract.js +1 -1
  389. package/clis/jike/api.js +6 -6
  390. package/clis/jike/auth.js +3 -3
  391. package/clis/jike/comment.js +1 -1
  392. package/clis/jike/create.js +6 -6
  393. package/clis/jike/feed.js +3 -3
  394. package/clis/jike/like.js +1 -1
  395. package/clis/jike/notifications.js +3 -3
  396. package/clis/jike/repost.js +13 -13
  397. package/clis/jike/search.js +3 -3
  398. package/clis/jimeng/auth.js +2 -2
  399. package/clis/jimeng/generate.js +10 -10
  400. package/clis/jira/shared.js +1 -1
  401. package/clis/juejin/article.js +4 -4
  402. package/clis/juejin/categories.js +1 -1
  403. package/clis/juejin/hot.js +1 -1
  404. package/clis/juejin/login.js +1 -1
  405. package/clis/juejin/recommend.js +1 -1
  406. package/clis/juejin/stats.js +3 -3
  407. package/clis/juejin/tags.js +1 -1
  408. package/clis/juejin/utils.js +1 -1
  409. package/clis/juejin/whoami.js +1 -1
  410. package/clis/ke/utils.js +4 -4
  411. package/clis/kimi/_utils.js +7 -7
  412. package/clis/kimi/audit-extras.js +14 -14
  413. package/clis/kimi/auth.js +3 -3
  414. package/clis/kimi/chat.js +15 -15
  415. package/clis/kimi/storage.js +5 -5
  416. package/clis/kimi/ui.js +13 -13
  417. package/clis/kimi/usage.js +3 -3
  418. package/clis/kuaishou/auth.js +1 -1
  419. package/clis/kuaishou/publish.js +6 -6
  420. package/clis/lesswrong/_helpers.js +5 -5
  421. package/clis/lesswrong/comments.js +5 -5
  422. package/clis/lichess/top.js +1 -1
  423. package/clis/lichess/user.js +1 -1
  424. package/clis/lichess/utils.js +1 -1
  425. package/clis/linkedin/comment.js +1 -1
  426. package/clis/linkedin/connect.js +11 -11
  427. package/clis/linkedin/create.js +5 -5
  428. package/clis/linkedin/follow.js +1 -1
  429. package/clis/linkedin/inbox.js +1 -1
  430. package/clis/linkedin/job-detail.js +3 -3
  431. package/clis/linkedin/like.js +1 -1
  432. package/clis/linkedin/notifications.js +1 -1
  433. package/clis/linkedin/people-search.js +1 -1
  434. package/clis/linkedin/post-comments.js +1 -1
  435. package/clis/linkedin/post-detail.js +1 -1
  436. package/clis/linkedin/profile-analytics.js +1 -1
  437. package/clis/linkedin/profile-api.js +13 -13
  438. package/clis/linkedin/profile-experience.js +1 -1
  439. package/clis/linkedin/profile-projects.js +1 -1
  440. package/clis/linkedin/profile-read.js +3 -3
  441. package/clis/linkedin/reply.js +1 -1
  442. package/clis/linkedin/repost.js +1 -1
  443. package/clis/linkedin/safe-send.js +8 -8
  444. package/clis/linkedin/salesnav-inbox.js +5 -5
  445. package/clis/linkedin/salesnav-message.js +3 -3
  446. package/clis/linkedin/salesnav-search.js +4 -4
  447. package/clis/linkedin/salesnav-thread.js +1 -1
  448. package/clis/linkedin/search-api.js +3 -3
  449. package/clis/linkedin/search.js +8 -8
  450. package/clis/linkedin/social-api.js +31 -31
  451. package/clis/linkedin/timeline.js +3 -3
  452. package/clis/linkedin-learning/search.js +2 -2
  453. package/clis/linkedin-learning/trending.js +2 -2
  454. package/clis/linux-do/feed.js +4 -4
  455. package/clis/linux-do/topic-content.js +8 -8
  456. package/clis/lobsters/domain.js +1 -1
  457. package/clis/lobsters/read.js +7 -7
  458. package/clis/maimai/auth.js +2 -2
  459. package/clis/maimai/search-talents.js +4 -4
  460. package/clis/manus/_utils.js +1 -1
  461. package/clis/mastodon/login.js +1 -1
  462. package/clis/mastodon/post.js +1 -1
  463. package/clis/mastodon/shared.js +12 -12
  464. package/clis/mastodon/whoami.js +1 -1
  465. package/clis/maven/artifact.js +1 -1
  466. package/clis/maven/search.js +1 -1
  467. package/clis/maven/utils.js +1 -1
  468. package/clis/mdn/search.js +1 -1
  469. package/clis/medium/article.js +5 -5
  470. package/clis/medium/login.js +1 -1
  471. package/clis/medium/stats.js +3 -3
  472. package/clis/medium/tag.js +1 -1
  473. package/clis/medium/whoami.js +1 -1
  474. package/clis/mubu/notes.js +1 -1
  475. package/clis/mubu/utils.js +15 -15
  476. package/clis/note/auth.js +2 -2
  477. package/clis/note/note-utils.js +2 -2
  478. package/clis/note/publish.js +8 -8
  479. package/clis/notebooklm/add-source.js +8 -8
  480. package/clis/notebooklm/create.js +1 -1
  481. package/clis/notebooklm/generate-slides.js +1 -1
  482. package/clis/notebooklm/notes-get.js +1 -1
  483. package/clis/notebooklm/rpc.js +8 -8
  484. package/clis/notebooklm/source-fulltext.js +1 -1
  485. package/clis/notebooklm/utils.js +10 -10
  486. package/clis/nowcoder/auth.js +2 -2
  487. package/clis/nowcoder/comment.js +1 -1
  488. package/clis/nowcoder/comments.js +1 -1
  489. package/clis/nowcoder/dm-list.js +1 -1
  490. package/clis/nowcoder/dm-read.js +1 -1
  491. package/clis/nowcoder/dm-send.js +1 -1
  492. package/clis/nowcoder/drafts.js +1 -1
  493. package/clis/nowcoder/inbox.js +1 -1
  494. package/clis/nowcoder/like.js +1 -1
  495. package/clis/nowcoder/my.js +1 -1
  496. package/clis/nowcoder/post.js +1 -1
  497. package/clis/nowcoder/utils.js +13 -13
  498. package/clis/npm/downloads.js +1 -1
  499. package/clis/npm/package.js +1 -1
  500. package/clis/npm/search.js +1 -1
  501. package/clis/npm/utils.js +1 -1
  502. package/clis/nuget/package.js +1 -1
  503. package/clis/nuget/search.js +1 -1
  504. package/clis/nuget/utils.js +1 -1
  505. package/clis/nvd/cve.js +1 -1
  506. package/clis/oeis/search.js +1 -1
  507. package/clis/oeis/sequence.js +1 -1
  508. package/clis/oeis/utils.js +1 -1
  509. package/clis/ones/common.js +6 -6
  510. package/clis/ones/enrich-tasks.js +1 -1
  511. package/clis/ones/my-tasks.js +1 -1
  512. package/clis/ones/resolve-labels.js +1 -1
  513. package/clis/ones/task-helpers.js +1 -1
  514. package/clis/ones/task.js +1 -1
  515. package/clis/ones/worklog.js +7 -7
  516. package/clis/openalex/search.js +1 -1
  517. package/clis/openalex/utils.js +1 -1
  518. package/clis/openalex/work.js +1 -1
  519. package/clis/openfda/drug-label.js +1 -1
  520. package/clis/openfda/food-recall.js +1 -1
  521. package/clis/openfda/utils.js +1 -1
  522. package/clis/openreview/author.js +1 -1
  523. package/clis/openreview/paper.js +1 -1
  524. package/clis/openreview/reviews.js +3 -3
  525. package/clis/openreview/search.js +1 -1
  526. package/clis/openreview/utils.js +1 -1
  527. package/clis/openreview/venue.js +1 -1
  528. package/clis/oschina/article.js +1 -1
  529. package/clis/oschina/catalogs.js +1 -1
  530. package/clis/oschina/login.js +1 -1
  531. package/clis/oschina/stats.js +6 -6
  532. package/clis/oschina/whoami.js +1 -1
  533. package/clis/osv/query.js +1 -1
  534. package/clis/osv/utils.js +1 -1
  535. package/clis/osv/vulnerability.js +1 -1
  536. package/clis/packagist/package.js +1 -1
  537. package/clis/packagist/search.js +1 -1
  538. package/clis/packagist/utils.js +1 -1
  539. package/clis/pinterest/api.js +1 -1
  540. package/clis/pinterest/auth.js +1 -1
  541. package/clis/pinterest/boards.js +1 -1
  542. package/clis/pinterest/client.js +6 -6
  543. package/clis/pinterest/publish.js +5 -5
  544. package/clis/pixiv/auth.js +2 -2
  545. package/clis/pixiv/download.js +1 -1
  546. package/clis/pixiv/illusts.js +1 -1
  547. package/clis/pixiv/search.js +1 -1
  548. package/clis/pixiv/utils.js +3 -3
  549. package/clis/powerchina/auth.js +2 -2
  550. package/clis/powerchina/search.js +1 -1
  551. package/clis/producthunt/browse.js +2 -2
  552. package/clis/producthunt/hot.js +2 -2
  553. package/clis/producthunt/posts.js +1 -1
  554. package/clis/producthunt/today.js +1 -1
  555. package/clis/producthunt/utils.js +1 -1
  556. package/clis/pypi/downloads.js +1 -1
  557. package/clis/pypi/package.js +1 -1
  558. package/clis/pypi/utils.js +1 -1
  559. package/clis/qiita/auth.js +1 -1
  560. package/clis/qiita/gql.js +6 -6
  561. package/clis/qiita/publish.js +4 -4
  562. package/clis/qiita/stats.js +4 -4
  563. package/clis/qoder/_utils.js +16 -16
  564. package/clis/qoder/composer.js +1 -1
  565. package/clis/qoder/quest.js +1 -1
  566. package/clis/qoder/ui.js +14 -14
  567. package/clis/quark/auth.js +2 -2
  568. package/clis/quark/utils.js +2 -2
  569. package/clis/quora/answer-comments.js +3 -3
  570. package/clis/quora/create-answer.js +4 -4
  571. package/clis/quora/create-question.js +3 -3
  572. package/clis/quora/shared.js +17 -17
  573. package/clis/quora/whoami.js +1 -1
  574. package/clis/qwen/ask.js +1 -1
  575. package/clis/qwen/auth.js +3 -3
  576. package/clis/qwen/detail.js +1 -1
  577. package/clis/qwen/image.js +5 -5
  578. package/clis/qwen/status.js +1 -1
  579. package/clis/qwen/utils.js +16 -16
  580. package/clis/reddit/home.js +3 -3
  581. package/clis/reddit/read.js +10 -10
  582. package/clis/reddit/reply.js +4 -4
  583. package/clis/reddit/submit.js +11 -11
  584. package/clis/reddit/subreddit-info.js +3 -3
  585. package/clis/reddit/subscribed.js +4 -4
  586. package/clis/reddit/whoami.js +2 -2
  587. package/clis/rednote/comments.js +1 -1
  588. package/clis/rednote/download.js +1 -1
  589. package/clis/rednote/feed.js +1 -1
  590. package/clis/rednote/note.js +1 -1
  591. package/clis/rednote/notifications.js +2 -2
  592. package/clis/rednote/search.js +2 -2
  593. package/clis/rest-countries/country.js +1 -1
  594. package/clis/rest-countries/region.js +1 -1
  595. package/clis/rest-countries/utils.js +1 -1
  596. package/clis/reuters/article-detail.js +1 -1
  597. package/clis/reuters/auth.js +3 -3
  598. package/clis/reuters/search.js +1 -1
  599. package/clis/reuters/utils.js +4 -4
  600. package/clis/rfc/rfc.js +1 -1
  601. package/clis/rfc/utils.js +1 -1
  602. package/clis/rubygems/gem.js +1 -1
  603. package/clis/rubygems/search.js +1 -1
  604. package/clis/rubygems/utils.js +1 -1
  605. package/clis/segmentfault/article.js +3 -3
  606. package/clis/segmentfault/channels.js +1 -1
  607. package/clis/segmentfault/login.js +1 -1
  608. package/clis/segmentfault/stats.js +4 -4
  609. package/clis/segmentfault/tags.js +1 -1
  610. package/clis/segmentfault/whoami.js +1 -1
  611. package/clis/semanticscholar/citations.js +1 -1
  612. package/clis/semanticscholar/paper.js +1 -1
  613. package/clis/semanticscholar/recommendations.js +1 -1
  614. package/clis/semanticscholar/search.js +1 -1
  615. package/clis/semanticscholar/utils.js +1 -1
  616. package/clis/sinafinance/news.js +1 -1
  617. package/clis/sinafinance/stock-rank.js +1 -1
  618. package/clis/sinafinance/stock.js +1 -1
  619. package/clis/slock/attachment-download.js +1 -1
  620. package/clis/slock/attachment-upload.js +7 -7
  621. package/clis/slock/attachment-url.js +1 -1
  622. package/clis/slock/auth-verify.js +1 -1
  623. package/clis/slock/bookmark-add.js +1 -1
  624. package/clis/slock/bookmark-remove.js +1 -1
  625. package/clis/slock/channel-action.js +1 -1
  626. package/clis/slock/channel-create.js +1 -1
  627. package/clis/slock/channel-files.js +1 -1
  628. package/clis/slock/channel-list.js +1 -1
  629. package/clis/slock/channel-mark.js +1 -1
  630. package/clis/slock/channel-members.js +1 -1
  631. package/clis/slock/channel-unarchive.js +1 -1
  632. package/clis/slock/dm-list.js +1 -1
  633. package/clis/slock/errors.js +1 -1
  634. package/clis/slock/in-page.js +28 -28
  635. package/clis/slock/inbox-done.js +5 -5
  636. package/clis/slock/inbox.js +1 -1
  637. package/clis/slock/message-read.js +22 -22
  638. package/clis/slock/message-search.js +10 -10
  639. package/clis/slock/message-send.js +25 -25
  640. package/clis/slock/reaction-add.js +1 -1
  641. package/clis/slock/reaction-remove.js +1 -1
  642. package/clis/slock/resolve.js +1 -1
  643. package/clis/slock/server-list.js +2 -2
  644. package/clis/slock/task-claim.js +4 -4
  645. package/clis/slock/task-convert.js +13 -13
  646. package/clis/slock/task-create.js +1 -1
  647. package/clis/slock/task-delete.js +5 -5
  648. package/clis/slock/task-get.js +5 -5
  649. package/clis/slock/task-list-server.js +4 -4
  650. package/clis/slock/task-list.js +5 -5
  651. package/clis/slock/task-status.js +3 -3
  652. package/clis/slock/task-unclaim.js +3 -3
  653. package/clis/slock/thread-follow.js +1 -1
  654. package/clis/slock/thread-state.js +1 -1
  655. package/clis/slock/unread-summary.js +5 -5
  656. package/clis/slock/whoami.js +1 -1
  657. package/clis/smzdm/search.js +3 -3
  658. package/clis/sohu/article.js +1 -1
  659. package/clis/sohu/attributes.js +1 -1
  660. package/clis/sohu/categories.js +1 -1
  661. package/clis/sohu/channels.js +1 -1
  662. package/clis/sohu/columns.js +1 -1
  663. package/clis/sohu/login.js +1 -1
  664. package/clis/sohu/stats.js +3 -3
  665. package/clis/sohu/topics.js +1 -1
  666. package/clis/sohu/whoami.js +1 -1
  667. package/clis/spotify/spotify.js +1 -1
  668. package/clis/stackoverflow/read.js +6 -6
  669. package/clis/stackoverflow/related.js +1 -1
  670. package/clis/stackoverflow/tag.js +1 -1
  671. package/clis/stackoverflow/user.js +1 -1
  672. package/clis/stackoverflow/utils.js +1 -1
  673. package/clis/steam/app.js +1 -1
  674. package/clis/steam/search.js +1 -1
  675. package/clis/steam/utils.js +1 -1
  676. package/clis/substack/auth.js +2 -2
  677. package/clis/substack/post-utils.js +2 -2
  678. package/clis/substack/publish.js +5 -5
  679. package/clis/suno/auth.js +2 -2
  680. package/clis/suno/download.js +5 -5
  681. package/clis/suno/generate.js +3 -3
  682. package/clis/suno/list.js +1 -1
  683. package/clis/suno/status.js +1 -1
  684. package/clis/suno/utils.js +29 -29
  685. package/clis/telegram/send.js +7 -7
  686. package/clis/telegram/shared.js +2 -2
  687. package/clis/telegram/whoami.js +1 -1
  688. package/clis/test-utils.js +1 -1
  689. package/clis/threads/post.js +23 -23
  690. package/clis/threads/shared.js +3 -3
  691. package/clis/threads/whoami.js +1 -1
  692. package/clis/tieba/hot.js +3 -3
  693. package/clis/tieba/posts.js +1 -1
  694. package/clis/tieba/read.js +2 -2
  695. package/clis/tieba/search.js +3 -3
  696. package/clis/tieba/utils.js +1 -1
  697. package/clis/tiktok/comment.js +2 -2
  698. package/clis/tiktok/creator-videos.js +3 -3
  699. package/clis/tiktok/explore.js +3 -3
  700. package/clis/tiktok/follow.js +8 -8
  701. package/clis/tiktok/following.js +4 -4
  702. package/clis/tiktok/friends.js +7 -7
  703. package/clis/tiktok/live.js +3 -3
  704. package/clis/tiktok/notifications.js +6 -6
  705. package/clis/tiktok/publish.js +16 -16
  706. package/clis/tiktok/unfollow.js +4 -4
  707. package/clis/tiktok/user.js +2 -2
  708. package/clis/tiktok/utils.js +1 -1
  709. package/clis/toutiao/article.js +1 -1
  710. package/clis/toutiao/articles.js +2 -2
  711. package/clis/toutiao/auth.js +2 -2
  712. package/clis/toutiao/hot.js +1 -1
  713. package/clis/toutiao/recommend.js +1 -1
  714. package/clis/toutiao/utils.js +2 -2
  715. package/clis/trae-solo/_actions.js +4 -4
  716. package/clis/trae-solo/_fs.js +5 -5
  717. package/clis/trae-solo/_state.js +2 -2
  718. package/clis/trae-solo/automation.js +4 -4
  719. package/clis/trae-solo/mode.js +4 -4
  720. package/clis/trae-solo/model.js +4 -4
  721. package/clis/trae-solo/renderer-storage.js +4 -4
  722. package/clis/trae-solo/settings.js +1 -1
  723. package/clis/trae-solo/skill-fs.js +1 -1
  724. package/clis/trae-solo/skill.js +12 -12
  725. package/clis/trae-solo/state-fs.js +2 -2
  726. package/clis/trae-solo/task-fs.js +5 -5
  727. package/clis/trae-solo/workspaces-fs.js +1 -1
  728. package/clis/tumblr/auth.js +2 -2
  729. package/clis/tumblr/publish.js +3 -3
  730. package/clis/tvmaze/search.js +1 -1
  731. package/clis/tvmaze/show.js +1 -1
  732. package/clis/tvmaze/utils.js +1 -1
  733. package/clis/twitter/accept.js +7 -7
  734. package/clis/twitter/article.js +7 -7
  735. package/clis/twitter/bookmark-folder.js +3 -3
  736. package/clis/twitter/bookmark-folders.js +3 -3
  737. package/clis/twitter/bookmarks.js +4 -4
  738. package/clis/twitter/delete.js +5 -5
  739. package/clis/twitter/device-follow.js +3 -3
  740. package/clis/twitter/dm-list.js +1 -1
  741. package/clis/twitter/dm-read.js +1 -1
  742. package/clis/twitter/dm-send.js +5 -5
  743. package/clis/twitter/dm-shared.js +3 -3
  744. package/clis/twitter/download.js +6 -6
  745. package/clis/twitter/followers.js +5 -5
  746. package/clis/twitter/following.js +2 -2
  747. package/clis/twitter/like.js +3 -3
  748. package/clis/twitter/likes.js +8 -8
  749. package/clis/twitter/list-add-core.js +9 -9
  750. package/clis/twitter/list-create.js +5 -5
  751. package/clis/twitter/list-remove-core.js +9 -9
  752. package/clis/twitter/list-tweets.js +7 -7
  753. package/clis/twitter/lists.js +6 -6
  754. package/clis/twitter/notifications.js +2 -2
  755. package/clis/twitter/post.js +24 -24
  756. package/clis/twitter/profile.js +7 -7
  757. package/clis/twitter/quote.js +7 -7
  758. package/clis/twitter/reply-dm.js +7 -7
  759. package/clis/twitter/reply.js +12 -12
  760. package/clis/twitter/retweet.js +3 -3
  761. package/clis/twitter/scheduled-delete.js +3 -3
  762. package/clis/twitter/scheduled-list.js +2 -2
  763. package/clis/twitter/scheduled-utils.js +3 -3
  764. package/clis/twitter/search.js +5 -5
  765. package/clis/twitter/shared.js +6 -6
  766. package/clis/twitter/thread.js +4 -4
  767. package/clis/twitter/timeline.js +3 -3
  768. package/clis/twitter/trending.js +2 -2
  769. package/clis/twitter/tweets.js +11 -11
  770. package/clis/twitter/unlike.js +3 -3
  771. package/clis/twitter/unretweet.js +3 -3
  772. package/clis/twitter/utils.js +6 -6
  773. package/clis/upwork/detail.js +2 -2
  774. package/clis/upwork/feed.js +2 -2
  775. package/clis/upwork/search.js +2 -2
  776. package/clis/upwork/utils.js +1 -1
  777. package/clis/v2ex/auth.js +2 -2
  778. package/clis/v2ex/daily.js +3 -3
  779. package/clis/v2ex/me.js +2 -2
  780. package/clis/v2ex/notifications.js +2 -2
  781. package/clis/vk/post.js +1 -1
  782. package/clis/vk/shared.js +2 -2
  783. package/clis/vk/whoami.js +1 -1
  784. package/clis/web/read.js +8 -8
  785. package/clis/wechat-channels/auth.js +2 -2
  786. package/clis/wechat-channels/publish.js +30 -30
  787. package/clis/weibo/article.js +1 -1
  788. package/clis/weibo/auth.js +3 -3
  789. package/clis/weibo/comments.js +1 -1
  790. package/clis/weibo/delete.js +2 -2
  791. package/clis/weibo/feed.js +3 -3
  792. package/clis/weibo/hot.js +1 -1
  793. package/clis/weibo/publish.js +10 -10
  794. package/clis/weibo/search.js +2 -2
  795. package/clis/weibo/user-posts.js +3 -3
  796. package/clis/weibo/user.js +2 -2
  797. package/clis/weibo/utils.js +3 -3
  798. package/clis/weixin/article.js +1 -1
  799. package/clis/weixin/create-draft.js +26 -26
  800. package/clis/weixin/download.js +2 -2
  801. package/clis/weixin/login.js +1 -1
  802. package/clis/weixin/search.js +2 -2
  803. package/clis/weixin/stats.js +3 -3
  804. package/clis/weixin/whoami.js +1 -1
  805. package/clis/weread/ai-outline.js +2 -2
  806. package/clis/weread/book-search.js +2 -2
  807. package/clis/weread/book.js +2 -2
  808. package/clis/weread/notebooks.js +1 -1
  809. package/clis/weread/search.js +1 -1
  810. package/clis/weread/shelf.js +1 -1
  811. package/clis/weread/utils.js +6 -6
  812. package/clis/weread-official/book.js +1 -1
  813. package/clis/weread-official/discover.js +1 -1
  814. package/clis/weread-official/list-apis.js +1 -1
  815. package/clis/weread-official/notes.js +1 -1
  816. package/clis/weread-official/readdata.js +1 -1
  817. package/clis/weread-official/review.js +1 -1
  818. package/clis/weread-official/search.js +1 -1
  819. package/clis/weread-official/shelf.js +1 -1
  820. package/clis/weread-official/utils.js +1 -1
  821. package/clis/wikidata/entity.js +1 -1
  822. package/clis/wikidata/search.js +1 -1
  823. package/clis/wikidata/utils.js +1 -1
  824. package/clis/wikipedia/page.js +1 -1
  825. package/clis/wikipedia/trending.js +1 -1
  826. package/clis/wikipedia/utils.js +1 -1
  827. package/clis/wordpress/login.js +1 -1
  828. package/clis/wordpress/publish.js +1 -1
  829. package/clis/wordpress/shared.js +3 -3
  830. package/clis/wordpress/whoami.js +1 -1
  831. package/clis/woshipm/article.js +1 -1
  832. package/clis/woshipm/login.js +1 -1
  833. package/clis/woshipm/stats.js +4 -4
  834. package/clis/woshipm/whoami.js +1 -1
  835. package/clis/wttr/current.js +1 -1
  836. package/clis/wttr/forecast.js +1 -1
  837. package/clis/wttr/utils.js +1 -1
  838. package/clis/xianyu/collect.js +1 -1
  839. package/clis/xianyu/inbox.js +1 -1
  840. package/clis/xianyu/item-stats.js +2 -2
  841. package/clis/xianyu/location.js +1 -1
  842. package/clis/xianyu/manage.js +1 -1
  843. package/clis/xianyu/messages.js +1 -1
  844. package/clis/xianyu/mtop.js +5 -5
  845. package/clis/xianyu/order.js +1 -1
  846. package/clis/xianyu/promote-stats.js +2 -2
  847. package/clis/xianyu/publish.js +17 -17
  848. package/clis/xianyu/rate.js +1 -1
  849. package/clis/xianyu/reply.js +1 -1
  850. package/clis/xianyu/search.js +8 -8
  851. package/clis/xianyu/seller-data.js +1 -1
  852. package/clis/xianyu/seller-list.js +1 -1
  853. package/clis/xianyu/user.js +1 -1
  854. package/clis/xiaoe/catalog.js +2 -2
  855. package/clis/xiaoe/content.js +2 -2
  856. package/clis/xiaoe/courses.js +2 -2
  857. package/clis/xiaohongshu/ask.js +6 -6
  858. package/clis/xiaohongshu/comments.js +6 -6
  859. package/clis/xiaohongshu/creator-note-detail.js +7 -7
  860. package/clis/xiaohongshu/creator-notes-summary.js +1 -1
  861. package/clis/xiaohongshu/creator-notes.js +13 -13
  862. package/clis/xiaohongshu/creator-profile.js +2 -2
  863. package/clis/xiaohongshu/creator-stats.js +2 -2
  864. package/clis/xiaohongshu/delete-note.js +7 -7
  865. package/clis/xiaohongshu/download.js +4 -4
  866. package/clis/xiaohongshu/feed.js +2 -2
  867. package/clis/xiaohongshu/follow.js +3 -3
  868. package/clis/xiaohongshu/human.js +3 -3
  869. package/clis/xiaohongshu/note-helpers.js +1 -1
  870. package/clis/xiaohongshu/note.js +2 -2
  871. package/clis/xiaohongshu/notifications.js +1 -1
  872. package/clis/xiaohongshu/publish-video.js +8 -8
  873. package/clis/xiaohongshu/publish.js +59 -59
  874. package/clis/xiaohongshu/search.js +8 -8
  875. package/clis/xiaohongshu/unfollow.js +4 -4
  876. package/clis/xiaohongshu/user-helpers.js +1 -1
  877. package/clis/xiaohongshu/user.js +2 -2
  878. package/clis/xiaoyuzhou/auth.js +3 -3
  879. package/clis/xiaoyuzhou/download.js +1 -1
  880. package/clis/xiaoyuzhou/utils.js +1 -1
  881. package/clis/xueqiu/article.js +4 -4
  882. package/clis/xueqiu/comments.js +4 -4
  883. package/clis/xueqiu/danjuan-utils.js +4 -4
  884. package/clis/xueqiu/earnings-date.js +1 -1
  885. package/clis/xueqiu/events.js +3 -3
  886. package/clis/xueqiu/hashtags.js +3 -3
  887. package/clis/xueqiu/stocks.js +3 -3
  888. package/clis/xueqiu/users.js +3 -3
  889. package/clis/xueqiu/utils.js +3 -3
  890. package/clis/yahoo-finance/quote.js +1 -1
  891. package/clis/yollomi/background.js +1 -1
  892. package/clis/yollomi/edit.js +1 -1
  893. package/clis/yollomi/face-swap.js +1 -1
  894. package/clis/yollomi/generate.js +1 -1
  895. package/clis/yollomi/object-remover.js +1 -1
  896. package/clis/yollomi/remove-bg.js +1 -1
  897. package/clis/yollomi/restore.js +1 -1
  898. package/clis/yollomi/try-on.js +1 -1
  899. package/clis/yollomi/upload.js +4 -4
  900. package/clis/yollomi/upscale.js +1 -1
  901. package/clis/yollomi/utils.js +4 -4
  902. package/clis/yollomi/video.js +1 -1
  903. package/clis/youtube/channel.js +4 -4
  904. package/clis/youtube/feed.js +2 -2
  905. package/clis/youtube/like.js +5 -5
  906. package/clis/youtube/playlist.js +7 -7
  907. package/clis/youtube/publish.js +11 -11
  908. package/clis/youtube/search.js +3 -3
  909. package/clis/youtube/subscribe.js +7 -7
  910. package/clis/youtube/subscriptions.js +1 -1
  911. package/clis/youtube/transcript-group.js +2 -2
  912. package/clis/youtube/transcript.js +13 -13
  913. package/clis/youtube/unlike.js +5 -5
  914. package/clis/youtube/unsubscribe.js +7 -7
  915. package/clis/youtube/utils.js +3 -3
  916. package/clis/youtube/video.js +4 -4
  917. package/clis/youtube/watch-later.js +2 -2
  918. package/clis/yuanbao/ask.js +18 -18
  919. package/clis/yuanbao/detail.js +1 -1
  920. package/clis/yuanbao/read.js +1 -1
  921. package/clis/yuanbao/shared.js +9 -9
  922. package/clis/yuanbao/status.js +1 -1
  923. package/clis/yuque/article.js +1 -1
  924. package/clis/yuque/whoami.js +1 -1
  925. package/clis/zhihu/answer-comments.js +2 -2
  926. package/clis/zhihu/answer-detail.js +3 -3
  927. package/clis/zhihu/answer.js +1 -1
  928. package/clis/zhihu/article-transform.js +1 -1
  929. package/clis/zhihu/article.js +1 -1
  930. package/clis/zhihu/auth.js +2 -2
  931. package/clis/zhihu/collection.js +3 -3
  932. package/clis/zhihu/collections.js +3 -3
  933. package/clis/zhihu/download.js +2 -2
  934. package/clis/zhihu/image-profile.js +6 -6
  935. package/clis/zhihu/paginate.js +3 -3
  936. package/clis/zhihu/pin.js +4 -4
  937. package/clis/zhihu/question.js +3 -3
  938. package/clis/zhihu/recommend.js +3 -3
  939. package/clis/zhihu/search.js +3 -3
  940. package/clis/zhihu/stats.js +3 -3
  941. package/clis/zhihu/user-arg.js +1 -1
  942. package/clis/zhihu/write-shared.js +7 -7
  943. package/clis/zlibrary/utils.js +6 -6
  944. package/clis/zsxq/auth.js +3 -3
  945. package/clis/zsxq/search.js +1 -1
  946. package/clis/zsxq/topic.js +1 -1
  947. package/clis/zsxq/utils.js +5 -5
  948. package/dist/src/adapter-source.js +1 -1
  949. package/dist/src/browser/analyze.js +1 -1
  950. package/dist/src/browser/article-extract.js +2 -2
  951. package/dist/src/browser/ax-snapshot.js +2 -2
  952. package/dist/src/browser/base-page.js +25 -25
  953. package/dist/src/browser/bridge.js +1 -1
  954. package/dist/src/browser/cdp.js +1 -1
  955. package/dist/src/browser/daemon-client.js +1 -1
  956. package/dist/src/browser/daemon-lifecycle.js +7 -7
  957. package/dist/src/browser/dom-helpers.js +35 -35
  958. package/dist/src/browser/dom-snapshot.js +19 -19
  959. package/dist/src/browser/errors.js +3 -3
  960. package/dist/src/browser/extract.js +5 -5
  961. package/dist/src/browser/find.js +13 -13
  962. package/dist/src/browser/fingerprint.js +2 -2
  963. package/dist/src/browser/html-tree.js +6 -6
  964. package/dist/src/browser/managed-chrome.js +1 -1
  965. package/dist/src/browser/network-cache.js +1 -1
  966. package/dist/src/browser/network-key.js +1 -1
  967. package/dist/src/browser/page.js +7 -7
  968. package/dist/src/browser/profile.js +2 -2
  969. package/dist/src/browser/proxy-test.js +8 -8
  970. package/dist/src/browser/shape-filter.js +1 -1
  971. package/dist/src/browser/shape.js +1 -1
  972. package/dist/src/browser/stealth.js +3 -3
  973. package/dist/src/browser/tabs.js +2 -2
  974. package/dist/src/browser/target-errors.js +1 -1
  975. package/dist/src/browser/target-resolver.js +23 -23
  976. package/dist/src/browser/trace.js +2 -2
  977. package/dist/src/browser/utils.js +1 -1
  978. package/dist/src/browser/verify-fixture.js +2 -2
  979. package/dist/src/browser-session-lock.js +1 -1
  980. package/dist/src/build-manifest.js +11 -11
  981. package/dist/src/capabilityRouting.js +1 -1
  982. package/dist/src/cli-argv-preprocess.js +1 -1
  983. package/dist/src/cli.js +32 -32
  984. package/dist/src/commanderAdapter.js +3 -3
  985. package/dist/src/commands/auth.js +3 -3
  986. package/dist/src/commands/daemon.js +1 -1
  987. package/dist/src/completion-fast.js +1 -1
  988. package/dist/src/completion.js +1 -1
  989. package/dist/src/constants.js +1 -1
  990. package/dist/src/convention-audit.js +2 -2
  991. package/dist/src/daemon-utils.js +1 -1
  992. package/dist/src/daemon.js +1 -1
  993. package/dist/src/discovery.js +2 -2
  994. package/dist/src/doctor.js +9 -9
  995. package/dist/src/download/article-download.js +15 -15
  996. package/dist/src/download/index.js +4 -4
  997. package/dist/src/download/media-download.js +1 -1
  998. package/dist/src/download/progress.js +3 -3
  999. package/dist/src/electron-apps.js +1 -1
  1000. package/dist/src/errors.js +2 -2
  1001. package/dist/src/execution.js +2 -2
  1002. package/dist/src/external.js +1 -1
  1003. package/dist/src/help.js +8 -8
  1004. package/dist/src/hooks.js +1 -1
  1005. package/dist/src/interceptor.js +21 -21
  1006. package/dist/src/launcher.js +7 -7
  1007. package/dist/src/logger.js +8 -8
  1008. package/dist/src/main.js +7 -7
  1009. package/dist/src/observation/artifact.js +5 -5
  1010. package/dist/src/observation/retention.js +1 -1
  1011. package/dist/src/output.js +2 -2
  1012. package/dist/src/package-paths.js +1 -1
  1013. package/dist/src/pipeline/executor.js +1 -1
  1014. package/dist/src/pipeline/registry.js +1 -1
  1015. package/dist/src/pipeline/steps/browser.js +1 -1
  1016. package/dist/src/pipeline/steps/download.js +1 -1
  1017. package/dist/src/pipeline/steps/fetch.js +6 -6
  1018. package/dist/src/pipeline/steps/intercept.js +1 -1
  1019. package/dist/src/pipeline/steps/tap.js +17 -17
  1020. package/dist/src/pipeline/steps/transform.js +1 -1
  1021. package/dist/src/pipeline/template.js +1 -1
  1022. package/dist/src/plugin-manifest.js +1 -1
  1023. package/dist/src/plugin-scaffold.js +19 -19
  1024. package/dist/src/plugin.js +12 -12
  1025. package/dist/src/rate-limit.js +1 -1
  1026. package/dist/src/registry.js +1 -1
  1027. package/dist/src/runtime-detect.js +1 -1
  1028. package/dist/src/runtime.js +1 -1
  1029. package/dist/src/scripts/framework.js +1 -1
  1030. package/dist/src/scripts/interact.js +1 -1
  1031. package/dist/src/scripts/store.js +1 -1
  1032. package/dist/src/serialization.js +2 -2
  1033. package/dist/src/session-lease.js +1 -1
  1034. package/dist/src/snapshotFormatter.js +2 -2
  1035. package/dist/src/tui.js +12 -12
  1036. package/dist/src/user-runtime.js +1 -1
  1037. package/dist/src/utils.d.ts +12 -0
  1038. package/dist/src/utils.js +4 -4
  1039. package/dist/src/validate.js +2 -2
  1040. package/dist/src/verify.js +2 -2
  1041. package/dist/src/version.js +1 -1
  1042. package/package.json +1 -1
@@ -1,11 +1,11 @@
1
- import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy as f}from"@jackwener/opencli/registry";import{ArgumentError as N,CommandExecutionError as $}from"@jackwener/opencli/errors";import{setInputFiles as U}from"../_shared/file-inject.js";const j={public:"公开",friends:"好友可见",private:"仅自己可见"},R="https://creator.douyin.com/creator-micro/content/upload",D=120,F=20,O=20,y=200;async function B(q){await q.evaluate(`() => {
1
+ import*as f from"node:fs";import*as s from"node:path";import{cli as w,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentError as c,CommandExecutionError as l}from"@jackwener/opencli/errors";import{setInputFiles as p}from"../_shared/file-inject.js";const m={public:"公开",friends:"好友可见",private:"仅自己可见"},h="https://creator.douyin.com/creator-micro/content/upload",T=120,A=20,x=20,E=200;async function b(t){await t.evaluate(`() => {
2
2
  const targets = ['我知道了', '知道了', '关闭'];
3
3
  for (const text of targets) {
4
4
  const btn = Array.from(document.querySelectorAll('button,[role="button"]'))
5
5
  .find((el) => (el.textContent || '').trim() === text);
6
6
  if (btn instanceof HTMLElement) btn.click();
7
7
  }
8
- }`)}async function b(q){let G={href:"",ready:!1,bodyText:""};for(let z=0;z<D;z+=1){G=await q.evaluate(`() => ({
8
+ }`)}async function S(t){let n={href:"",ready:!1,bodyText:""};for(let e=0;e<T;e+=1){n=await t.evaluate(`() => ({
9
9
  href: location.href,
10
10
  ready: !!Array.from(document.querySelectorAll('input')).find(
11
11
  (el) => (el.placeholder || '').includes('填写作品标题')
@@ -13,7 +13,7 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
13
13
  (el) => (el.textContent || '').includes('暂存离开')
14
14
  ),
15
15
  bodyText: document.body?.innerText || ''
16
- })`);if(G.ready)return;await q.wait({time:0.5})}throw new $("等待抖音草稿编辑页超时",`当前页面: ${G.href||"unknown"}`)}async function x(q,G){for(let z=0;z<y;z+=1){const H=await q.evaluate(`() => {
16
+ })`);if(n.ready)return;await t.wait({time:0.5})}throw new l("等待抖音草稿编辑页超时",`当前页面: ${n.href||"unknown"}`)}async function I(t,n){for(let e=0;e<E;e+=1){const i=await t.evaluate(`() => {
17
17
  const text = document.body?.innerText || '';
18
18
  const uploading = /上传中|上传\\s*\\d+%|视频上传中|处理中/.test(text);
19
19
  const saveBtn = Array.from(document.querySelectorAll('button')).find(
@@ -24,10 +24,10 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
24
24
  : false;
25
25
  const hasCaptionEditor = !!document.querySelector('[contenteditable="true"]');
26
26
  const hasVisibility = !!Array.from(document.querySelectorAll('label')).find(
27
- (el) => (el.textContent || '').includes(${JSON.stringify(G)})
27
+ (el) => (el.textContent || '').includes(${JSON.stringify(n)})
28
28
  );
29
29
  return { uploading, saveEnabled, hasSaveBtn: !!saveBtn, hasCaptionEditor, hasVisibility };
30
- }`);if(H.hasSaveBtn&&H.saveEnabled&&H.hasCaptionEditor&&H.hasVisibility&&!H.uploading)return;await q.wait({time:0.5})}}async function w(q,G){const z=60;let H=!1;for(let X=0;X<z;X+=1){H=await q.evaluate(`() => {
30
+ }`);if(i.hasSaveBtn&&i.saveEnabled&&i.hasCaptionEditor&&i.hasVisibility&&!i.uploading)return;await t.wait({time:0.5})}}async function k(t,n){const e=60;let i=!1;for(let o=0;o<e;o+=1){i=await t.evaluate(`() => {
31
31
  const titleInput = Array.from(document.querySelectorAll('input')).find(
32
32
  (el) => (el.placeholder || '').includes('填写作品标题')
33
33
  );
@@ -36,12 +36,12 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
36
36
  const props = propKey ? titleInput[propKey] : null;
37
37
  if (props?.onChange) {
38
38
  props.onChange({
39
- target: { value: ${JSON.stringify(G.title)} },
40
- currentTarget: { value: ${JSON.stringify(G.title)} },
39
+ target: { value: ${JSON.stringify(n.title)} },
40
+ currentTarget: { value: ${JSON.stringify(n.title)} },
41
41
  });
42
42
  } else {
43
43
  titleInput.focus();
44
- titleInput.value = ${JSON.stringify(G.title)};
44
+ titleInput.value = ${JSON.stringify(n.title)};
45
45
  titleInput.dispatchEvent(new Event('input', { bubbles: true }));
46
46
  titleInput.dispatchEvent(new Event('change', { bubbles: true }));
47
47
  }
@@ -55,23 +55,23 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
55
55
  titleInput.dispatchEvent(new Event('blur', { bubbles: true }));
56
56
  }
57
57
  return true;
58
- }`);if(H)break;await q.wait({time:0.5})}if(!H)throw new $("填写抖音草稿表单失败: title-input-missing");if(G.caption){let X=!1;for(let Z=0;Z<z;Z+=1){X=await q.evaluate(`() => {
58
+ }`);if(i)break;await t.wait({time:0.5})}if(!i)throw new l("填写抖音草稿表单失败: title-input-missing");if(n.caption){let o=!1;for(let a=0;a<e;a+=1){o=await t.evaluate(`() => {
59
59
  const editor = document.querySelector('[contenteditable="true"]');
60
60
  if (!(editor instanceof HTMLElement)) return false;
61
61
  editor.focus();
62
62
  editor.textContent = '';
63
63
  document.execCommand('selectAll', false);
64
- document.execCommand('insertText', false, ${JSON.stringify(G.caption)});
64
+ document.execCommand('insertText', false, ${JSON.stringify(n.caption)});
65
65
  editor.dispatchEvent(new Event('input', { bubbles: true }));
66
66
  return true;
67
- }`);if(X)break;await q.wait({time:0.5})}if(!X)throw new $("填写抖音草稿表单失败: caption-editor-missing")}let Q=!1;for(let X=0;X<z;X+=1){Q=await q.evaluate(`() => {
67
+ }`);if(o)break;await t.wait({time:0.5})}if(!o)throw new l("填写抖音草稿表单失败: caption-editor-missing")}let r=!1;for(let o=0;o<e;o+=1){r=await t.evaluate(`() => {
68
68
  const visibility = Array.from(document.querySelectorAll('label')).find(
69
- (el) => (el.textContent || '').includes(${JSON.stringify(G.visibilityLabel)})
69
+ (el) => (el.textContent || '').includes(${JSON.stringify(n.visibilityLabel)})
70
70
  );
71
71
  if (!(visibility instanceof HTMLElement)) return false;
72
72
  visibility.click();
73
73
  return true;
74
- }`);if(Q)break;await q.wait({time:0.5})}if(!Q)throw new $("填写抖音草稿表单失败: visibility-missing")}async function h(q){let G="cover-input-missing";const z=await q.evaluate(`() => Array.from(document.querySelectorAll('input[type="file"]')).length`);for(let H=0;H<F;H+=1){const Q=await q.evaluate(`() => {
74
+ }`);if(r)break;await t.wait({time:0.5})}if(!r)throw new l("填写抖音草稿表单失败: visibility-missing")}async function C(t){let n="cover-input-missing";const e=await t.evaluate(`() => Array.from(document.querySelectorAll('input[type="file"]')).length`);for(let i=0;i<A;i+=1){const r=await t.evaluate(`() => {
75
75
  const coverLabel = Array.from(document.querySelectorAll('label')).find(
76
76
  (el) => (el.textContent || '').includes('上传新封面')
77
77
  );
@@ -81,7 +81,7 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
81
81
 
82
82
  const inputs = Array.from(document.querySelectorAll('input[type="file"]'));
83
83
  const target = inputs
84
- .slice(${JSON.stringify(z)})
84
+ .slice(${JSON.stringify(e)})
85
85
  .find((el) => el instanceof HTMLInputElement && !el.disabled);
86
86
  if (!(target instanceof HTMLInputElement)) {
87
87
  return { ok: false, reason: 'cover-input-pending' };
@@ -92,7 +92,7 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
92
92
  .forEach((el) => el.removeAttribute('data-opencli-cover-input'));
93
93
  target.setAttribute('data-opencli-cover-input', '1');
94
94
  return { ok: true, selector: '[data-opencli-cover-input="1"]' };
95
- }`);if(Q?.ok&&Q.selector)return Q.selector;G=Q?.reason||G;await q.wait({time:0.5})}throw new $(`准备抖音自定义封面输入框失败: ${G}`)}export function buildCoverCheckPanelTextJs(){return`() => {
95
+ }`);if(r?.ok&&r.selector)return r.selector;n=r?.reason||n;await t.wait({time:0.5})}throw new l(`准备抖音自定义封面输入框失败: ${n}`)}export function buildCoverCheckPanelTextJs(){return`() => {
96
96
  const normalize = (value) => (value || '').replace(/\\s+/g, ' ').trim();
97
97
  const stateTexts = ['检测', '检测中', '封面检测中', '重新检测', '横/竖双封面缺失'];
98
98
  const marker = Array.from(document.querySelectorAll('div,span,p,button')).find(
@@ -110,7 +110,7 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
110
110
  root = root.parentElement;
111
111
  }
112
112
  return '';
113
- }`}async function L(q){return await q.evaluate(buildCoverCheckPanelTextJs())||""}async function k(q){let G="",z=!1;for(let H=0;H<O;H+=1){const Q=await L(q),X=Q.includes("检测中"),Z=Q.includes("重新检测")||Q.includes("横/竖双封面缺失");if(X)z=!0;if(z&&Z&&!X)return;G=Q;await q.wait({time:0.5})}throw new $("等待抖音封面处理完成超时",G||"unknown")}async function S(q){const G=60;let z=null;for(let H=0;H<G;H+=1){z=await q.evaluate(`() => {
113
+ }`}async function _(t){return await t.evaluate(buildCoverCheckPanelTextJs())||""}async function g(t){let n="",e=!1;for(let i=0;i<x;i+=1){const r=await _(t),o=r.includes("检测中"),a=r.includes("重新检测")||r.includes("横/竖双封面缺失");if(o)e=!0;if(e&&a&&!o)return;n=r;await t.wait({time:0.5})}throw new l("等待抖音封面处理完成超时",n||"unknown")}async function L(t){const n=60;let e=null;for(let i=0;i<n;i+=1){e=await t.evaluate(`() => {
114
114
  const extractCreationId = () => {
115
115
  const titleInput = Array.from(document.querySelectorAll('input')).find(
116
116
  (el) => (el.placeholder || '').includes('填写作品标题')
@@ -160,7 +160,7 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
160
160
  text: (btn.textContent || '').trim(),
161
161
  creationId,
162
162
  };
163
- }`);if(z?.ok)break;await q.wait({time:0.5})}if(!z?.ok)throw new $(`点击草稿按钮失败: ${z?.reason||"unknown"}`);if(!z.creationId)throw new $("点击草稿按钮失败: creation-id-missing");return{text:z.text||"暂存离开",creationId:z.creationId}}async function _(q,G){let z={href:"",bodyText:""};for(let H=0;H<40;H+=1){z=await q.evaluate(`() => ({
163
+ }`);if(e?.ok)break;await t.wait({time:0.5})}if(!e?.ok)throw new l(`点击草稿按钮失败: ${e?.reason||"unknown"}`);if(!e.creationId)throw new l("点击草稿按钮失败: creation-id-missing");return{text:e.text||"暂存离开",creationId:e.creationId}}async function M(t,n){let e={href:"",bodyText:""};for(let i=0;i<40;i+=1){e=await t.evaluate(`() => ({
164
164
  href: location.href,
165
165
  bodyText: document.body?.innerText || ''
166
- })`);const Q=z.href||"",X=z.bodyText||"",Z=Q.includes("/creator-micro/content/upload")&&/继续编辑/.test(X),K=/草稿保存成功|已保存到草稿|存草稿成功|保存成功/.test(X),Y=/\/creator-micro\/content\/(manage|drafts|works)/.test(Q)||/创作中心/.test(X)&&!Q.includes("/content/upload");if(Z||K||Y)return G;await q.wait({time:1})}throw new $("未检测到抖音草稿保存确认",`当前页面: ${z.href||"unknown"}`)}M({site:"douyin",name:"draft",access:"write",description:"上传视频并保存为草稿",domain:"creator.douyin.com",strategy:f.COOKIE,navigateBefore:!1,defaultWindowMode:"foreground",args:[{name:"video",required:!0,positional:!0,help:"视频文件路径"},{name:"title",required:!0,help:"视频标题(≤30字)"},{name:"caption",fromFile:!0,default:"",help:"正文内容(≤1000字,支持 #话题)"},{name:"cover",default:"",help:"封面图片路径"},{name:"visibility",default:"public",choices:["public","friends","private"]},{name:"timeout",type:"int",default:180,help:"命令超时(秒),视频上传/转码慢时可调大"}],columns:["status","draft_id"],func:async(q,G)=>{const z=J.resolve(G.video);if(!W.existsSync(z))throw new N(`视频文件不存在: ${z}`);const H=J.extname(z).toLowerCase();if(![".mp4",".mov",".avi",".webm"].includes(H))throw new N(`不支持的视频格式: ${H}(支持 mp4/mov/avi/webm)`);const Q=G.title;if(Q.length>30)throw new N("标题不能超过 30 字");const X=G.caption||"";if(X.length>1000)throw new N("正文不能超过 1000 字");const Z=G.cover;if(Z){if(!W.existsSync(J.resolve(Z)))throw new N(`封面文件不存在: ${J.resolve(Z)}`)}const K=j[G.visibility]??j.public;await q.goto(R);await q.wait({selector:'input[type="file"]',timeout:20});await B(q);await U(q,'input[type="file"]',[z]);await b(q);await x(q,K);await B(q);if(Z){const V=await h(q);await U(q,V,[J.resolve(Z)]);await k(q)}await w(q,{title:Q,caption:X,visibilityLabel:K});await q.wait({time:1});const Y=await S(q);return[{status:"✅ 草稿已保存,可在创作中心继续编辑",draft_id:await _(q,Y.creationId)}]}});
166
+ })`);const r=e.href||"",o=e.bodyText||"",a=r.includes("/creator-micro/content/upload")&&/继续编辑/.test(o),u=/草稿保存成功|已保存到草稿|存草稿成功|保存成功/.test(o),d=/\/creator-micro\/content\/(manage|drafts|works)/.test(r)||/创作中心/.test(o)&&!r.includes("/content/upload");if(a||u||d)return n;await t.wait({time:1})}throw new l("未检测到抖音草稿保存确认",`当前页面: ${e.href||"unknown"}`)}w({site:"douyin",name:"draft",access:"write",description:"上传视频并保存为草稿",domain:"creator.douyin.com",strategy:v.COOKIE,navigateBefore:!1,defaultWindowMode:"foreground",args:[{name:"video",required:!0,positional:!0,help:"视频文件路径"},{name:"title",required:!0,help:"视频标题(≤30字)"},{name:"caption",fromFile:!0,default:"",help:"正文内容(≤1000字,支持 #话题)"},{name:"cover",default:"",help:"封面图片路径"},{name:"visibility",default:"public",choices:["public","friends","private"]},{name:"timeout",type:"int",default:180,help:"命令超时(秒),视频上传/转码慢时可调大"}],columns:["status","draft_id"],func:async(t,n)=>{const e=s.resolve(n.video);if(!f.existsSync(e))throw new c(`视频文件不存在: ${e}`);const i=s.extname(e).toLowerCase();if(![".mp4",".mov",".avi",".webm"].includes(i))throw new c(`不支持的视频格式: ${i}(支持 mp4/mov/avi/webm)`);const r=n.title;if(r.length>30)throw new c("标题不能超过 30 字");const o=n.caption||"";if(o.length>1000)throw new c("正文不能超过 1000 字");const a=n.cover;if(a){if(!f.existsSync(s.resolve(a)))throw new c(`封面文件不存在: ${s.resolve(a)}`)}const u=m[n.visibility]??m.public;await t.goto(h);await t.wait({selector:'input[type="file"]',timeout:20});await b(t);await p(t,'input[type="file"]',[e]);await S(t);await I(t,u);await b(t);if(a){const y=await C(t);await p(t,y,[s.resolve(a)]);await g(t)}await k(t,{title:r,caption:o,visibilityLabel:u});await t.wait({time:1});const d=await L(t);return[{status:"✅ 草稿已保存,可在创作中心继续编辑",draft_id:await M(t,d.creationId)}]}});
@@ -1 +1 @@
1
- import{cli as B,Strategy as C}from"@jackwener/opencli/registry";import{READ_IMAGE_DRAFT_JS as H,matchImageDraft as K}from"./_shared/draft-cache.js";B({site:"douyin",name:"drafts",access:"read",description:"列出本机浏览器里暂存的图文草稿(抖音图文草稿只存在本地浏览器,换设备/清缓存即失效)",domain:"creator.douyin.com",strategy:C.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:20}],columns:["title","text","images","scope"],func:async(q,x)=>{await q.goto("https://creator.douyin.com/creator-micro/content/upload?default-tab=3");const z=await q.evaluate(H),u=[];for(const v of z||[]){let b=null;try{b=JSON.parse(v.value||"")}catch{continue}if(!b)continue;u.push({title:b.title||"",text:String(b.text||"").slice(0,120),images:Array.isArray(b.files)?b.files.length:0,scope:v.key})}return u.slice(0,x.limit)}});export const __test__={matchImageDraft:K};
1
+ import{cli as s,Strategy as c}from"@jackwener/opencli/registry";import{READ_IMAGE_DRAFT_JS as n,matchImageDraft as l}from"./_shared/draft-cache.js";s({site:"douyin",name:"drafts",access:"read",description:"列出本机浏览器里暂存的图文草稿(抖音图文草稿只存在本地浏览器,换设备/清缓存即失效)",domain:"creator.douyin.com",strategy:c.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:20}],columns:["title","text","images","scope"],func:async(e,i)=>{await e.goto("https://creator.douyin.com/creator-micro/content/upload?default-tab=3");const o=await e.evaluate(n),a=[];for(const r of o||[]){let t=null;try{t=JSON.parse(r.value||"")}catch{continue}if(!t)continue;a.push({title:t.title||"",text:String(t.text||"").slice(0,120),images:Array.isArray(t.files)?t.files.length:0,scope:r.key})}return a.slice(0,i.limit)}});export const __test__={matchImageDraft:l};
@@ -1,18 +1,18 @@
1
- import*as v from"node:fs";import*as N from"node:path";import{cli as h,Strategy as d}from"@jackwener/opencli/registry";import{ArgumentError as $,CommandExecutionError as W}from"@jackwener/opencli/errors";import{assertLiteralContent as u}from"../_shared/content-guard.js";import{setInputFiles as T}from"../_shared/file-inject.js";import{browserFetch as m}from"./_shared/browser-fetch.js";import{READ_IMAGE_DRAFT_JS as c,matchImageDraft as E}from"./_shared/draft-cache.js";const l="https://creator.douyin.com/creator-micro/content/upload?default-tab=3",x=35,L=20,w=1000,n=2500,o={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".bmp":"image/bmp",".webp":"image/webp",".tif":"image/tiff",".tiff":"image/tiff"},M='input[type="file"][accept*="image"]',C=['input[placeholder="添加作品标题"]','input[placeholder*="标题"]'],i='input[placeholder="添加作品标题"]',P='.zone-container[contenteditable="true"]';function p(q){return q.map((K)=>{const z=N.resolve(K);if(!v.existsSync(z))throw new $(`图片文件不存在: ${z}`);const Z=N.extname(z).toLowerCase();if(!o[Z])throw new $(`不支持的图片格式 "${Z}",支持: jpg, png, bmp, webp, tif`);return z})}async function s(q,K=15000){const z=500,Z=Math.max(1,Math.ceil(K/z));for(let V=0;V<Z;V++){if(await q.evaluate(`(() => !!document.querySelector(${JSON.stringify(M)}))()`))return!0;if(V<Z-1)await q.wait({time:z/1000})}return!1}async function g(q,K){if(!await s(q))return{ok:!1,error:"上传页未渲染出图片输入框(等待 15s 超时)"};try{await T(q,M,K);return{ok:!0}}catch(Z){return{ok:!1,error:Z instanceof Error?Z.message:String(Z)}}}async function r(q,K=20000){const z=500,Z=Math.ceil(K/z);for(let V=0;V<Z;V++){if(await q.evaluate(`(() => {
1
+ import*as b from"node:fs";import*as y from"node:path";import{cli as k,Strategy as q}from"@jackwener/opencli/registry";import{ArgumentError as a,CommandExecutionError as u}from"@jackwener/opencli/errors";import{assertLiteralContent as j}from"../_shared/content-guard.js";import{setInputFiles as B}from"../_shared/file-inject.js";import{browserFetch as F}from"./_shared/browser-fetch.js";import{READ_IMAGE_DRAFT_JS as D,matchImageDraft as J}from"./_shared/draft-cache.js";const G="https://creator.douyin.com/creator-micro/content/upload?default-tab=3",A=35,C=20,L=1000,X=2500,V={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".bmp":"image/bmp",".webp":"image/webp",".tif":"image/tiff",".tiff":"image/tiff"},O='input[type="file"][accept*="image"]',R=['input[placeholder="添加作品标题"]','input[placeholder*="标题"]'],z='input[placeholder="添加作品标题"]',I='.zone-container[contenteditable="true"]';function Y(t){return t.map((n)=>{const e=y.resolve(n);if(!b.existsSync(e))throw new a(`图片文件不存在: ${e}`);const r=y.extname(e).toLowerCase();if(!V[r])throw new a(`不支持的图片格式 "${r}",支持: jpg, png, bmp, webp, tif`);return e})}async function H(t,n=15000){const e=500,r=Math.max(1,Math.ceil(n/e));for(let o=0;o<r;o++){if(await t.evaluate(`(() => !!document.querySelector(${JSON.stringify(O)}))()`))return!0;if(o<r-1)await t.wait({time:e/1000})}return!1}async function K(t,n){if(!await H(t))return{ok:!1,error:"上传页未渲染出图片输入框(等待 15s 超时)"};try{await B(t,O,n);return{ok:!0}}catch(r){return{ok:!1,error:r instanceof Error?r.message:String(r)}}}async function W(t,n=20000){const e=500,r=Math.ceil(n/e);for(let o=0;o<r;o++){if(await t.evaluate(`(() => {
2
2
  const onEditor = location.href.includes('/content/post/image');
3
- const titleReady = ${JSON.stringify(C)}.some((s) => !!document.querySelector(s));
3
+ const titleReady = ${JSON.stringify(R)}.some((s) => !!document.querySelector(s));
4
4
  return onEditor && titleReady;
5
- })()`))return!0;await q.wait({time:z/1000})}return!1}async function t(q,K){await q.typeText(i,K);await q.wait({time:0.3});const z=await q.evaluate(`
5
+ })()`))return!0;await t.wait({time:e/1000})}return!1}async function Q(t,n){await t.typeText(z,n);await t.wait({time:0.3});const e=await t.evaluate(`
6
6
  ((selectors) => {
7
7
  const el = selectors.map((s) => document.querySelector(s)).find(Boolean);
8
8
  return el ? (el.value || '') : '';
9
- })(${JSON.stringify(C)})
10
- `);if(z.trim()!==K){await q.screenshot({path:"/tmp/douyin_image_title_debug.png"});throw new W(`填写标题失败,期望 "${K}",实际 "${z}"。截图: /tmp/douyin_image_title_debug.png`)}}async function e(q,K){await q.typeText(P,K);await q.wait({time:0.5});const z=await q.evaluate(`
9
+ })(${JSON.stringify(R)})
10
+ `);if(e.trim()!==n){await t.screenshot({path:"/tmp/douyin_image_title_debug.png"});throw new u(`填写标题失败,期望 "${n}",实际 "${e}"。截图: /tmp/douyin_image_title_debug.png`)}}async function Z(t,n){await t.typeText(I,n);await t.wait({time:0.5});const e=await t.evaluate(`
11
11
  ((selector) => {
12
12
  const el = Array.from(document.querySelectorAll(selector)).find((n) => n && n.offsetParent !== null);
13
13
  return el ? (el.innerText || el.textContent || '').replace(/\\u200b/g, '').trim() : '';
14
- })(${JSON.stringify(P)})
15
- `),Z=K.split("#")[0].replace(/\s+/g,"").trim(),V=z.replace(/\s+/g,"");if(Z&&!V.includes(Z.slice(0,Math.min(Z.length,20)))){await q.screenshot({path:"/tmp/douyin_image_body_debug.png"});throw new W(`正文写入校验失败,实际读到 "${z.slice(0,80)}"。截图: /tmp/douyin_image_body_debug.png`)}}async function a(q,K){const z=K?["暂存离开"]:["发布"];return await q.evaluate(`
14
+ })(${JSON.stringify(I)})
15
+ `),r=n.split("#")[0].replace(/\s+/g,"").trim(),o=e.replace(/\s+/g,"");if(r&&!o.includes(r.slice(0,Math.min(r.length,20)))){await t.screenshot({path:"/tmp/douyin_image_body_debug.png"});throw new u(`正文写入校验失败,实际读到 "${e.slice(0,80)}"。截图: /tmp/douyin_image_body_debug.png`)}}async function tt(t,n){const e=n?["暂存离开"]:["发布"];return await t.evaluate(`
16
16
  ((labels) => {
17
17
  const isVisible = (el) => {
18
18
  if (!el || el.offsetParent === null) return false;
@@ -27,8 +27,8 @@ import*as v from"node:fs";import*as N from"node:path";import{cli as h,Strategy a
27
27
  if (btn) { btn.click(); return { ok: true, text: label }; }
28
28
  }
29
29
  return { ok: false, seen: btns.filter(isVisible).map((b) => norm(b.innerText || b.textContent)).filter(Boolean).slice(0, 12) };
30
- })(${JSON.stringify(z)})
31
- `)}h({site:"douyin",name:"publish-image",access:"write",description:"发布图文(图集)到抖音(UI 自动化,最多 35 张图;话题以 #词 写进正文)",domain:"creator.douyin.com",strategy:d.COOKIE,browser:!0,navigateBefore:!1,defaultWindowMode:"foreground",args:[{name:"content",required:!1,positional:!0,help:"正文(字面文本,不展开 @文件 引用;长正文用 --file)"},{name:"file",required:!1,help:"从本机文件读取正文(UTF-8),与位置参数 <content> 二选一"},{name:"title",required:!0,help:"作品标题(≤20字)"},{name:"images",required:!0,help:"图片路径,逗号分隔,最多35张 (jpg/png/bmp/webp/tif)"},{name:"topics",required:!1,help:"话题标签,逗号分隔,不含 # 号"},{name:"draft",type:"bool",default:!1,help:"暂存为草稿,不直接发布"}],columns:["status","detail"],func:async(q,K)=>{if(!q)throw Error("Browser page required");const z=String(K.title??"").trim(),Z=K.file?String(K.file).trim():"";let V=String(K.content??"").trim();if(Z){if(V)throw new $("正文位置参数和 --file 只能二选一");const Q=N.resolve(Z);if(!v.existsSync(Q))throw new $(`--file 指向的文件不存在: ${Q}`);V=v.readFileSync(Q,"utf-8").trim();if(!V)throw new $(`--file 指向的文件内容为空: ${Q}`)}const G=String(K.images??"").split(",").map((Q)=>Q.trim()).filter(Boolean),X=K.topics?String(K.topics).split(",").map((Q)=>Q.trim().replace(/^#/,"")).filter(Boolean):[],B=Boolean(K.draft);if(!z)throw new $("--title 必填");if(z.length>L)throw new $(`标题 ${z.length} 字,需 ≤ ${L} 字`);if(!V)throw new $("缺少正文:给位置参数 <content>,或用 --file <本机文件路径>");u(V,{fileFlag:"--file"});if(V.length>w)throw new $(`正文 ${V.length} 字,需 ≤ ${w} 字`);if(G.length===0)throw new $("至少提供 1 张图片(--images)");if(G.length>x)throw new $(`图片过多: ${G.length}(最多 ${x} 张)`);const O=p(G),b=X.length?`${V} ${X.map((Q)=>`#${Q}`).join(" ")} `:V;await q.goto(l);let j="";for(let Q=0;Q<30;Q++){await q.wait({time:0.5});j=await q.evaluate("() => location.href");if(j.includes("creator.douyin.com/creator-micro/content"))break}if(!j.includes("creator.douyin.com")){await q.screenshot({path:"/tmp/douyin_image_redirect_debug.png"});throw new W(`被重定向离开创作者中心(当前 ${j})——登录态可能已过期。`+"用 ppcli douyin login 重新登录。截图: /tmp/douyin_image_redirect_debug.png")}const D=await g(q,O);if(!D.ok){await q.screenshot({path:"/tmp/douyin_image_upload_debug.png"});throw new W(`图片上传失败: ${D.error??"unknown"}。截图: /tmp/douyin_image_upload_debug.png`)}if(!await r(q)){await q.screenshot({path:"/tmp/douyin_image_form_debug.png"});throw new W("上传后编辑页未就绪(标题输入框未出现),页面结构可能变化。截图: /tmp/douyin_image_form_debug.png")}await q.wait({time:n/1000});await t(q,z);await q.wait({time:0.4});await e(q,b);await q.wait({time:0.6});const U=await a(q,B);if(!U?.ok){await q.screenshot({path:"/tmp/douyin_image_submit_debug.png"});throw new W(`找不到「${B?"暂存离开":"发布"}」按钮。可见按钮: ${(U?.seen||[]).join(" | ")||"无"}。截图: /tmp/douyin_image_submit_debug.png`)}const A=B?["暂存成功","保存成功","存入草稿"]:["发布成功","提交成功"];let Y=j,F=!1,y="";for(let Q=0;Q<24;Q++){await q.wait({time:0.5});const J=await q.evaluate(`
30
+ })(${JSON.stringify(e)})
31
+ `)}k({site:"douyin",name:"publish-image",access:"write",description:"发布图文(图集)到抖音(UI 自动化,最多 35 张图;话题以 #词 写进正文)",domain:"creator.douyin.com",strategy:q.COOKIE,browser:!0,navigateBefore:!1,defaultWindowMode:"foreground",args:[{name:"content",required:!1,positional:!0,help:"正文(字面文本,不展开 @文件 引用;长正文用 --file)"},{name:"file",required:!1,help:"从本机文件读取正文(UTF-8),与位置参数 <content> 二选一"},{name:"title",required:!0,help:"作品标题(≤20字)"},{name:"images",required:!0,help:"图片路径,逗号分隔,最多35张 (jpg/png/bmp/webp/tif)"},{name:"topics",required:!1,help:"话题标签,逗号分隔,不含 # 号"},{name:"draft",type:"bool",default:!1,help:"暂存为草稿,不直接发布"}],columns:["status","detail"],func:async(t,n)=>{if(!t)throw Error("Browser page required");const e=String(n.title??"").trim(),r=n.file?String(n.file).trim():"";let o=String(n.content??"").trim();if(r){if(o)throw new a("正文位置参数和 --file 只能二选一");const i=y.resolve(r);if(!b.existsSync(i))throw new a(`--file 指向的文件不存在: ${i}`);o=b.readFileSync(i,"utf-8").trim();if(!o)throw new a(`--file 指向的文件内容为空: ${i}`)}const m=String(n.images??"").split(",").map((i)=>i.trim()).filter(Boolean),p=n.topics?String(n.topics).split(",").map((i)=>i.trim().replace(/^#/,"")).filter(Boolean):[],c=Boolean(n.draft);if(!e)throw new a("--title 必填");if(e.length>C)throw new a(`标题 ${e.length} 字,需 ≤ ${C} 字`);if(!o)throw new a("缺少正文:给位置参数 <content>,或用 --file <本机文件路径>");j(o,{fileFlag:"--file"});if(o.length>L)throw new a(`正文 ${o.length} 字,需 ≤ ${L} 字`);if(m.length===0)throw new a("至少提供 1 张图片(--images)");if(m.length>A)throw new a(`图片过多: ${m.length}(最多 ${A} 张)`);const _=Y(m),M=p.length?`${o} ${p.map((i)=>`#${i}`).join(" ")} `:o;await t.goto(G);let d="";for(let i=0;i<30;i++){await t.wait({time:0.5});d=await t.evaluate("() => location.href");if(d.includes("creator.douyin.com/creator-micro/content"))break}if(!d.includes("creator.douyin.com")){await t.screenshot({path:"/tmp/douyin_image_redirect_debug.png"});throw new u(`被重定向离开创作者中心(当前 ${d})——登录态可能已过期。`+"用 ppcli douyin login 重新登录。截图: /tmp/douyin_image_redirect_debug.png")}const S=await K(t,_);if(!S.ok){await t.screenshot({path:"/tmp/douyin_image_upload_debug.png"});throw new u(`图片上传失败: ${S.error??"unknown"}。截图: /tmp/douyin_image_upload_debug.png`)}if(!await W(t)){await t.screenshot({path:"/tmp/douyin_image_form_debug.png"});throw new u("上传后编辑页未就绪(标题输入框未出现),页面结构可能变化。截图: /tmp/douyin_image_form_debug.png")}await t.wait({time:X/1000});await Q(t,e);await t.wait({time:0.4});await Z(t,M);await t.wait({time:0.6});const E=await tt(t,c);if(!E?.ok){await t.screenshot({path:"/tmp/douyin_image_submit_debug.png"});throw new u(`找不到「${c?"暂存离开":"发布"}」按钮。可见按钮: ${(E?.seen||[]).join(" | ")||"无"}。截图: /tmp/douyin_image_submit_debug.png`)}const N=c?["暂存成功","保存成功","存入草稿"]:["发布成功","提交成功"];let l=d,w=!1,g="";for(let i=0;i<24;i++){await t.wait({time:0.5});const s=await t.evaluate(`
32
32
  ((markers) => {
33
33
  const url = location.href;
34
34
  let toast = '';
@@ -39,7 +39,7 @@ import*as v from"node:fs";import*as N from"node:path";import{cli as h,Strategy a
39
39
  if (text && text.length <= 40 && markers.some((m) => text.includes(m))) { toast = text; break; }
40
40
  }
41
41
  return { url, toast };
42
- })(${JSON.stringify(A)})
43
- `);Y=J?.url??Y;if(J?.toast){y=J.toast;break}if(Y.includes("/content/manage")||B&&Y.includes("/content/draft")){F=!0;break}}let H=null;if(!F&&!y&&Y.includes("creator.douyin.com"))try{if(B){const Q=await q.evaluate(c),J=E(Q,{title:z,content:V});H=J.hit?J:null}else{const J=await m(q,"GET","https://creator.douyin.com/janus/douyin/creator/pc/work_list?page_size=20&page_num=1&status=0"),f=J.aweme_list??J.data?.work_list??[],k=V.replace(/\s+/g,"").slice(0,20),_=Date.now()/1000;H=f.find((R)=>{const I=String(R.desc??R.title??"").replace(/\s+/g,""),S=Number(R.create_time??0);return S>0&&_-S<900&&(I.includes(z.replace(/\s+/g,""))||k&&I.includes(k))})??null}}catch{}if(!F&&!y&&!H){await q.screenshot({path:"/tmp/douyin_image_verify_debug.png"});throw new W(B?"暂存结果无法确认:未见成功提示,本机草稿缓存里也没找到本次内容——大概率没存下,重试是安全的。"+`当前 URL: ${Y}。截图: /tmp/douyin_image_verify_debug.png`:"发布结果无法确认:未跳转作品管理页、未见成功提示,作品列表回查也没找到本次内容。"+`
42
+ })(${JSON.stringify(N)})
43
+ `);l=s?.url??l;if(s?.toast){g=s.toast;break}if(l.includes("/content/manage")||c&&l.includes("/content/draft")){w=!0;break}}let f=null;if(!w&&!g&&l.includes("creator.douyin.com"))try{if(c){const i=await t.evaluate(D),s=J(i,{title:e,content:o});f=s.hit?s:null}else{const s=await F(t,"GET","https://creator.douyin.com/janus/douyin/creator/pc/work_list?page_size=20&page_num=1&status=0"),P=s.aweme_list??s.data?.work_list??[],T=o.replace(/\s+/g,"").slice(0,20),U=Date.now()/1000;f=P.find((h)=>{const x=String(h.desc??h.title??"").replace(/\s+/g,""),v=Number(h.create_time??0);return v>0&&U-v<900&&(x.includes(e.replace(/\s+/g,""))||T&&x.includes(T))})??null}}catch{}if(!w&&!g&&!f){await t.screenshot({path:"/tmp/douyin_image_verify_debug.png"});throw new u(c?"暂存结果无法确认:未见成功提示,本机草稿缓存里也没找到本次内容——大概率没存下,重试是安全的。"+`当前 URL: ${l}。截图: /tmp/douyin_image_verify_debug.png`:"发布结果无法确认:未跳转作品管理页、未见成功提示,作品列表回查也没找到本次内容。"+`
44
44
  ⚠️ 禁止直接重试——发布请求可能已经打到抖音,重试会发出重复作品。`+"\n正确做法:先用 `ppcli douyin videos` 按标题回查最近作品,确认没有再重发。"+`
45
- 当前 URL: ${Y}。截图: /tmp/douyin_image_verify_debug.png`)}return[{status:`✅ ${B?"暂存成功":"发布成功"}`,detail:[`"${z}"`,`${O.length}张图片`,X.length?`话题: ${X.map((Q)=>`#${Q}`).join(" ")}`:"",H?H.aweme_id?`aweme_id: ${H.aweme_id}(作品列表回查坐实)`:"本机草稿缓存回查坐实":"",F?Y:y].filter(Boolean).join(" · ")}]}});
45
+ 当前 URL: ${l}。截图: /tmp/douyin_image_verify_debug.png`)}return[{status:`✅ ${c?"暂存成功":"发布成功"}`,detail:[`"${e}"`,`${_.length}张图片`,p.length?`话题: ${p.map((i)=>`#${i}`).join(" ")}`:"",f?f.aweme_id?`aweme_id: ${f.aweme_id}(作品列表回查坐实)`:"本机草稿缓存回查坐实":"",w?l:g].filter(Boolean).join(" · ")}]}});
@@ -1,14 +1,14 @@
1
- import*as f from"node:fs";import*as M from"node:path";import{cli as a,Strategy as r}from"@jackwener/opencli/registry";import{ArgumentError as B,CommandExecutionError as G}from"@jackwener/opencli/errors";import{getUploadAuthV5Credentials as e,applyVideoUploadInner as KK,commitVideoUploadInner as QK}from"./_shared/vod-upload.js";import{tosUpload as ZK}from"./_shared/tos-upload.js";import{imagexUpload as $K}from"./_shared/imagex-upload.js";import{browserFetch as u}from"./_shared/browser-fetch.js";import{requireObjectEvaluateResult as k}from"./_shared/evaluate-result.js";import{generateCreationId as zK}from"./_shared/creation-id.js";import{validateTiming as YK,toUnixSeconds as qK}from"./_shared/timing.js";import{parseTextExtra as JK,extractHashtagNames as LK}from"./_shared/text-extra.js";const NK={public:0,friends:1,private:2},w="https://imagex.bytedanceapi.com",c="1147",WK="aid=1128&cookie_enabled=true&screen_width=1512&screen_height=982&browser_language=zh-CN&browser_platform=MacIntel&browser_name=Mozilla&browser_online=true&timezone_name=Asia%2FTokyo&support_h265=1",GK=JSON.stringify({video_cover_source:2,cover_timestamp:0,recommend_timestamp:0,is_cover_edit:0,is_cover_template:0,cover_template_id:"",is_text_template:0,text_template_id:"",text_template_content:"",is_text:0,text_num:0,text_content:"",is_use_sticker:0,sticker_id:"",is_use_filter:0,filter_id:"",is_cover_modify:0,to_status:0,cover_type:0,initial_cover_uri:"",cut_coordinate:""});function HK(Z){const K=Z instanceof Error?Z.message:String(Z);return K.includes("post_assistant/fast_detect")&&(K.includes("Empty response")||K.includes("404")||K.includes("Not Found")||K.includes("Timeout")||K.includes("timed out")||K.includes("Failed to fetch"))}function x(Z){return new Promise((K)=>setTimeout(K,Z))}function h(Z,K){const q=K?.ResponseMetadata?.Error??K?.Error;if(q)throw new G(`${Z}失败: ${JSON.stringify(q)}`)}async function n(Z,K,q,D){let O;for(let Y=1;Y<=3;Y+=1)try{return{ok:!0,value:await u(Z,K,q,D)}}catch($){if(!HK($))throw $;O=$;if(Y<3)await x(500*Y)}return{ok:!1,error:O}}a({site:"douyin",name:"publish",access:"write",description:"定时发布视频到抖音(必须设置 2h ~ 14天后的发布时间)",domain:"creator.douyin.com",strategy:r.COOKIE,defaultWindowMode:"foreground",args:[{name:"video",required:!0,positional:!0,help:"视频文件路径"},{name:"title",required:!0,help:"视频标题(≤30字)"},{name:"schedule",required:!0,help:"定时发布时间(ISO8601 或 Unix 秒,2h ~ 14天后)"},{name:"caption",fromFile:!0,default:"",help:"正文内容(≤1000字,支持 #话题)"},{name:"cover",default:"",help:"封面图片路径(不提供时使用视频截帧)"},{name:"visibility",default:"public",choices:["public","friends","private"]},{name:"allow_download",type:"bool",default:!1,help:"允许下载"},{name:"collection",default:"",help:"合集 ID"},{name:"activity",default:"",help:"活动 ID"},{name:"poi_id",default:"",help:"地理位置 ID"},{name:"poi_name",default:"",help:"地理位置名称"},{name:"hotspot",default:"",help:"关联热点词"},{name:"no_safety_check",type:"bool",default:!1,help:"跳过内容安全检测"},{name:"sync_toutiao",type:"bool",default:!1,help:"同步发布到头条"}],columns:["status","aweme_id","url","publish_time"],func:async(Z,K)=>{const q=M.resolve(K.video);if(!f.existsSync(q))throw new B(`视频文件不存在: ${q}`);const D=M.extname(q).toLowerCase();if(![".mp4",".mov",".avi",".webm"].includes(D))throw new B(`不支持的视频格式: ${D}(支持 mp4/mov/avi/webm)`);const O=f.statSync(q).size,Y=K.title;if(Y.length>30)throw new B("标题不能超过 30 字");const $=K.caption||"";if($.length>1000)throw new B("正文不能超过 1000 字");const V=qK(K.schedule);YK(V);const m=NK[K.visibility]??0,A=K.cover;if(A){if(!f.existsSync(M.resolve(A)))throw new B(`封面文件不存在: ${M.resolve(A)}`)}const S=await e(Z),U=await KK(O,S);let j="",_=720,b=1280;await ZK({filePath:q,uploadInfo:U,credentials:S,onProgress:(Q,z)=>{const J=Math.round(Q/z*100);process.stderr.write(`\r 上传进度: ${J}%`)}});process.stderr.write(`
1
+ import*as T from"node:fs";import*as u from"node:path";import{cli as Z,Strategy as Q}from"@jackwener/opencli/registry";import{ArgumentError as f,CommandExecutionError as m}from"@jackwener/opencli/errors";import{getUploadAuthV5Credentials as ee,applyVideoUploadInner as te,commitVideoUploadInner as oe}from"./_shared/vod-upload.js";import{tosUpload as ie}from"./_shared/tos-upload.js";import{imagexUpload as se}from"./_shared/imagex-upload.js";import{browserFetch as R}from"./_shared/browser-fetch.js";import{requireObjectEvaluateResult as V}from"./_shared/evaluate-result.js";import{generateCreationId as re}from"./_shared/creation-id.js";import{validateTiming as ne,toUnixSeconds as ae}from"./_shared/timing.js";import{parseTextExtra as ce,extractHashtagNames as le}from"./_shared/text-extra.js";const de={public:0,friends:1,private:2},M="https://imagex.bytedanceapi.com",z="1147",me="aid=1128&cookie_enabled=true&screen_width=1512&screen_height=982&browser_language=zh-CN&browser_platform=MacIntel&browser_name=Mozilla&browser_online=true&timezone_name=Asia%2FTokyo&support_h265=1",pe=JSON.stringify({video_cover_source:2,cover_timestamp:0,recommend_timestamp:0,is_cover_edit:0,is_cover_template:0,cover_template_id:"",is_text_template:0,text_template_id:"",text_template_content:"",is_text:0,text_num:0,text_content:"",is_use_sticker:0,sticker_id:"",is_use_filter:0,filter_id:"",is_cover_modify:0,to_status:0,cover_type:0,initial_cover_uri:"",cut_coordinate:""});function _e(o){const e=o instanceof Error?o.message:String(o);return e.includes("post_assistant/fast_detect")&&(e.includes("Empty response")||e.includes("404")||e.includes("Not Found")||e.includes("Timeout")||e.includes("timed out")||e.includes("Failed to fetch"))}function A(o){return new Promise((e)=>setTimeout(e,o))}function j(o,e){const n=e?.ResponseMetadata?.Error??e?.Error;if(n)throw new m(`${o}失败: ${JSON.stringify(n)}`)}async function B(o,e,n,h){let y;for(let r=1;r<=3;r+=1)try{return{ok:!0,value:await R(o,e,n,h)}}catch(i){if(!_e(i))throw i;y=i;if(r<3)await A(500*r)}return{ok:!1,error:y}}Z({site:"douyin",name:"publish",access:"write",description:"定时发布视频到抖音(必须设置 2h ~ 14天后的发布时间)",domain:"creator.douyin.com",strategy:Q.COOKIE,defaultWindowMode:"foreground",args:[{name:"video",required:!0,positional:!0,help:"视频文件路径"},{name:"title",required:!0,help:"视频标题(≤30字)"},{name:"schedule",required:!0,help:"定时发布时间(ISO8601 或 Unix 秒,2h ~ 14天后)"},{name:"caption",fromFile:!0,default:"",help:"正文内容(≤1000字,支持 #话题)"},{name:"cover",default:"",help:"封面图片路径(不提供时使用视频截帧)"},{name:"visibility",default:"public",choices:["public","friends","private"]},{name:"allow_download",type:"bool",default:!1,help:"允许下载"},{name:"collection",default:"",help:"合集 ID"},{name:"activity",default:"",help:"活动 ID"},{name:"poi_id",default:"",help:"地理位置 ID"},{name:"poi_name",default:"",help:"地理位置名称"},{name:"hotspot",default:"",help:"关联热点词"},{name:"no_safety_check",type:"bool",default:!1,help:"跳过内容安全检测"},{name:"sync_toutiao",type:"bool",default:!1,help:"同步发布到头条"}],columns:["status","aweme_id","url","publish_time"],func:async(o,e)=>{const n=u.resolve(e.video);if(!T.existsSync(n))throw new f(`视频文件不存在: ${n}`);const h=u.extname(n).toLowerCase();if(![".mp4",".mov",".avi",".webm"].includes(h))throw new f(`不支持的视频格式: ${h}(支持 mp4/mov/avi/webm)`);const y=T.statSync(n).size,r=e.title;if(r.length>30)throw new f("标题不能超过 30 字");const i=e.caption||"";if(i.length>1000)throw new f("正文不能超过 1000 字");const g=ae(e.schedule);ne(g);const H=de[e.visibility]??0,x=e.cover;if(x){if(!T.existsSync(u.resolve(x)))throw new f(`封面文件不存在: ${u.resolve(x)}`)}const I=await ee(o),C=await te(y,I);let v="",U=720,O=1280;await ie({filePath:n,uploadInfo:C,credentials:I,onProgress:(t,s)=>{const a=Math.round(t/s*100);process.stderr.write(`\r 上传进度: ${a}%`)}});process.stderr.write(`
2
2
  `);process.stderr.write(` 提交上传...
3
- `);const H=await QK(U,S),C=H.video_id;process.stderr.write(` 上传已提交: ${C}
4
- `);_=H.width||_;b=H.height||b;if(!j&&H.poster_uri)j=H.poster_uri;if(K.cover){const Q=M.resolve(K.cover),z=`${w}/?Action=ApplyImageUpload&ServiceId=${c}&Version=2018-08-01&UploadNum=1`,J=`fetch(${JSON.stringify(z)}, { credentials: 'include' }).then(r => r.json())`,X=k(await Z.evaluate(J),"抖音封面申请上传地址响应异常");h("抖音封面申请上传地址",X);const L=X.Result?.UploadAddress?.StoreInfos?.[0];if(!L?.UploadHost||!L?.StoreUri)throw new G(`抖音封面申请上传地址响应缺少 UploadHost/StoreUri: ${JSON.stringify(X).slice(0,500)}`);const P=`https://${L.UploadHost}/${L.StoreUri}`,N=await $K(Q,{upload_url:P,store_uri:L.StoreUri}),T=`${w}/?Action=CommitImageUpload&ServiceId=${c}&Version=2018-08-01`,W=JSON.stringify({SuccessObjKeys:[N]}),o=`
5
- fetch(${JSON.stringify(T)}, {
3
+ `);const p=await oe(C,I),E=p.video_id;process.stderr.write(` 上传已提交: ${E}
4
+ `);U=p.width||U;O=p.height||O;if(!v&&p.poster_uri)v=p.poster_uri;if(e.cover){const t=u.resolve(e.cover),s=`${M}/?Action=ApplyImageUpload&ServiceId=${z}&Version=2018-08-01&UploadNum=1`,a=`fetch(${JSON.stringify(s)}, { credentials: 'include' }).then(r => r.json())`,_=V(await o.evaluate(a),"抖音封面申请上传地址响应异常");j("抖音封面申请上传地址",_);const c=_.Result?.UploadAddress?.StoreInfos?.[0];if(!c?.UploadHost||!c?.StoreUri)throw new m(`抖音封面申请上传地址响应缺少 UploadHost/StoreUri: ${JSON.stringify(_).slice(0,500)}`);const S=`https://${c.UploadHost}/${c.StoreUri}`,l=await se(t,{upload_url:S,store_uri:c.StoreUri}),b=`${M}/?Action=CommitImageUpload&ServiceId=${z}&Version=2018-08-01`,d=JSON.stringify({SuccessObjKeys:[l]}),X=`
5
+ fetch(${JSON.stringify(b)}, {
6
6
  method: 'POST',
7
7
  credentials: 'include',
8
8
  headers: { 'Content-Type': 'application/json' },
9
- body: ${JSON.stringify(W)}
9
+ body: ${JSON.stringify(d)}
10
10
  }).then(r => r.json())
11
- `,t=k(await Z.evaluate(o),"抖音封面提交上传响应异常");h("抖音封面提交上传",t);j=N}if(!K.no_safety_check){const Q="https://creator.douyin.com/aweme/v1/post_assistant/fast_detect/pre_check",z={video_id:C,title:Y,desc:$},J=await n(Z,"POST",Q,{body:z});if(!J.ok)process.stderr.write(` 内容安全预检接口无响应,继续轮询检测结果。
12
- `);const X="https://creator.douyin.com/aweme/v1/post_assistant/fast_detect/poll",L=Date.now()+30000;let P=!1,N=0;while(Date.now()<L){const T=await n(Z,"POST",X,{body:z});if(!T.ok){N+=1;if(!J.ok&&N>=3)break;await x(2000);continue}N=0;const W=T.value;if(W.status===0||W.has_done===!0&&W.detect_result?.reason_code===0&&(W.detect_list?.length??0)===0){P=!0;break}if(W.status===1)throw new G("内容安全检测不通过,请修改后重试","使用 --no_safety_check 跳过");await x(2000)}if(!P)if(!J.ok&&N>=3)process.stderr.write(` 内容安全预检持续无响应,跳过本地预检,交由 create_v2 后的平台审核。
13
- `);else throw new G("内容安全检测超时(30s),请稍后重试","如确认要跳过本地预检,可使用 --no_safety_check;提交后仍会走抖音平台审核")}const d=LK($),y=[];let I=0;for(const Q of d){const z=$.indexOf(`#${Q}`,I);if(z===-1)continue;y.push({name:Q,id:0,start:z,end:z+Q.length+1});I=z+Q.length+1}const v=$?`${Y} ${$}`:Y,E=$?Y.length+1:0,g=JK(v,y.map((Q)=>({...Q,start:Q.start+E,end:Q.end+E}))),p={item:{common:{text:v,caption:$,item_title:Y,activity:JSON.stringify(K.activity?[K.activity]:[]),text_extra:JSON.stringify(g),challenges:"[]",mentions:"[]",hashtag_source:"",hot_sentence:K.hotspot||"",interaction_stickers:"[]",visibility_type:m,download:K.allow_download?1:0,timing:V,creation_id:zK(),media_type:4,video_id:C,music_source:0,music_id:null,...K.poi_id?{poi_id:K.poi_id,poi_name:K.poi_name}:{}},cover:{poster:j,custom_cover_image_height:b,custom_cover_image_width:_,poster_delay:0,cover_tools_info:GK,cover_tools_extend_info:"{}"},mix:K.collection?{mix_id:K.collection,mix_order:0}:{},chapter:{chapter:JSON.stringify({chapter_abstract:"",chapter_details:[],chapter_type:0})},anchor:{},sync:{should_sync:!1,sync_to_toutiao:K.sync_toutiao?1:0},open_platform:{},assistant:{is_preview:0,is_post_assistant:1},declare:{user_declare_info:"{}"}}},l=`https://creator.douyin.com/web/api/media/aweme/create_v2/?read_aid=2906&${WK}`;process.stderr.write(` 创建定时发布...
14
- `);let F;try{F=await u(Z,"POST",l,{body:p})}catch(Q){if((Q instanceof Error?Q.message:String(Q)).includes("Failed to fetch"))throw new G("提交定时发布请求被浏览器侧拦截(疑似字节安全组件 secsdk)","不要直接重试:先用 `ppcli douyin videos` / 创作者中心确认作品是否已创建,避免重复投稿。"+"确认未创建后,用 `--window foreground` 前台窗口重试(视频已上传成功的部分无需重传)。");throw Q}const R=F.aweme_id??F.item_id;if(!R)throw new G(`发布成功但未返回 aweme_id/item_id: ${JSON.stringify(F)}`);const i=`https://www.douyin.com/video/${R}`,s=new Date(V*1000).toLocaleString("zh-CN",{timeZone:"Asia/Tokyo"});return[{status:"✅ 定时发布成功!",aweme_id:R,url:i,publish_time:s}]}});
11
+ `,Y=V(await o.evaluate(X),"抖音封面提交上传响应异常");j("抖音封面提交上传",Y);v=l}if(!e.no_safety_check){const t="https://creator.douyin.com/aweme/v1/post_assistant/fast_detect/pre_check",s={video_id:E,title:r,desc:i},a=await B(o,"POST",t,{body:s});if(!a.ok)process.stderr.write(` 内容安全预检接口无响应,继续轮询检测结果。
12
+ `);const _="https://creator.douyin.com/aweme/v1/post_assistant/fast_detect/poll",c=Date.now()+30000;let S=!1,l=0;while(Date.now()<c){const b=await B(o,"POST",_,{body:s});if(!b.ok){l+=1;if(!a.ok&&l>=3)break;await A(2000);continue}l=0;const d=b.value;if(d.status===0||d.has_done===!0&&d.detect_result?.reason_code===0&&(d.detect_list?.length??0)===0){S=!0;break}if(d.status===1)throw new m("内容安全检测不通过,请修改后重试","使用 --no_safety_check 跳过");await A(2000)}if(!S)if(!a.ok&&l>=3)process.stderr.write(` 内容安全预检持续无响应,跳过本地预检,交由 create_v2 后的平台审核。
13
+ `);else throw new m("内容安全检测超时(30s),请稍后重试","如确认要跳过本地预检,可使用 --no_safety_check;提交后仍会走抖音平台审核")}const L=le(i),J=[];let P=0;for(const t of L){const s=i.indexOf(`#${t}`,P);if(s===-1)continue;J.push({name:t,id:0,start:s,end:s+t.length+1});P=s+t.length+1}const F=i?`${r} ${i}`:r,D=i?r.length+1:0,q=ce(F,J.map((t)=>({...t,start:t.start+D,end:t.end+D}))),k={item:{common:{text:F,caption:i,item_title:r,activity:JSON.stringify(e.activity?[e.activity]:[]),text_extra:JSON.stringify(q),challenges:"[]",mentions:"[]",hashtag_source:"",hot_sentence:e.hotspot||"",interaction_stickers:"[]",visibility_type:H,download:e.allow_download?1:0,timing:g,creation_id:re(),media_type:4,video_id:E,music_source:0,music_id:null,...e.poi_id?{poi_id:e.poi_id,poi_name:e.poi_name}:{}},cover:{poster:v,custom_cover_image_height:O,custom_cover_image_width:U,poster_delay:0,cover_tools_info:pe,cover_tools_extend_info:"{}"},mix:e.collection?{mix_id:e.collection,mix_order:0}:{},chapter:{chapter:JSON.stringify({chapter_abstract:"",chapter_details:[],chapter_type:0})},anchor:{},sync:{should_sync:!1,sync_to_toutiao:e.sync_toutiao?1:0},open_platform:{},assistant:{is_preview:0,is_post_assistant:1},declare:{user_declare_info:"{}"}}},G=`https://creator.douyin.com/web/api/media/aweme/create_v2/?read_aid=2906&${me}`;process.stderr.write(` 创建定时发布...
14
+ `);let w;try{w=await R(o,"POST",G,{body:k})}catch(t){if((t instanceof Error?t.message:String(t)).includes("Failed to fetch"))throw new m("提交定时发布请求被浏览器侧拦截(疑似字节安全组件 secsdk)","不要直接重试:先用 `ppcli douyin videos` / 创作者中心确认作品是否已创建,避免重复投稿。"+"确认未创建后,用 `--window foreground` 前台窗口重试(视频已上传成功的部分无需重传)。");throw t}const N=w.aweme_id??w.item_id;if(!N)throw new m(`发布成功但未返回 aweme_id/item_id: ${JSON.stringify(w)}`);const K=`https://www.douyin.com/video/${N}`,W=new Date(g*1000).toLocaleString("zh-CN",{timeZone:"Asia/Tokyo"});return[{status:"✅ 定时发布成功!",aweme_id:N,url:K,publish_time:W}]}});
@@ -1,4 +1,4 @@
1
- import{cli as O,Strategy as H}from"@jackwener/opencli/registry";import{ArgumentError as v,AuthRequiredError as N,CommandExecutionError as J,EmptyResultError as P}from"@jackwener/opencli/errors";export const MAX_SEARCH_LIMIT=30,RENDER_TIMEOUT_MS=15000;export function parseSearchLimit(B){const F=Number(B??10);if(!Number.isFinite(F)||!Number.isInteger(F))throw new v(`--limit must be an integer between 1 and ${MAX_SEARCH_LIMIT}, got ${JSON.stringify(B)}`);if(F<1||F>MAX_SEARCH_LIMIT)throw new v(`--limit must be between 1 and ${MAX_SEARCH_LIMIT}, got ${F}`);return F}export function parseDouyinCount(B){if(typeof B!=="string")return 0;const F=B.replace(/\s/g,"").match(/^(\d+(?:\.\d+)?)([万亿])?$/);if(!F){const G=Number(B.replace(/[,\s]/g,""));return Number.isFinite(G)?Math.round(G):0}const Q=Number(F[1]);if(!Number.isFinite(Q))return 0;if(F[2]==="万")return Math.round(Q*1e4);if(F[2]==="亿")return Math.round(Q*1e8);return Math.round(Q)}export function extractDouyinVideoId(B){if(typeof B!=="string"||!B)return"";let F=B;if(F.startsWith("//"))F="https:"+F;else if(F.startsWith("/"))F="https://www.douyin.com"+F;try{const Q=new URL(F);if(!/(^|\.)douyin\.com$/.test(Q.hostname))return"";return Q.pathname.match(/^\/video\/(\d+)$/)?.[1]??""}catch{return""}}export function normalizeDouyinVideoUrl(B){const F=extractDouyinVideoId(B);return F?`https://www.douyin.com/video/${F}`:""}function L(B){if(!B)return!0;if(/^\d{1,2}:\d{2}(?::\d{2})?$/.test(B))return!0;if(/^\d+(?:\.\d+)?[万亿]?$/.test(B))return!0;if(/^(合集|视频|作者)$/.test(B))return!0;if(/^(刚刚|今天|昨天|前天)$/.test(B))return!0;if(/^\d+\s*(秒|分钟|小时|天|周|个月|月|年)前$/.test(B))return!0;if(/^\d{4}[-/.年]\d{1,2}(?:[-/.月]\d{1,2}日?)?$/.test(B))return!0;return!1}export function projectCard(B,F){const Q=normalizeDouyinVideoUrl(B?.url??B?.href),G=Array.isArray(B?.leafTexts)?B.leafTexts.map((z)=>String(z??"").trim()).filter(Boolean):[],K=/^\d{1,2}:\d{2}(?::\d{2})?$/,Y=/^\d+(?:\.\d+)?[万亿]?$/;let Z=0,q="",b="";for(let z=0;z<G.length;z++){const $=G[z];if(K.test($))continue;if(!Z&&Y.test($)){Z=parseDouyinCount($);continue}if($==="@"&&!q){q=(G[z+1]??"").trim();continue}if($===q)continue;if(L($))continue;if($.length>b.length)b=$}let W=b;if(q&&W.startsWith("@"+q))W=W.slice(q.length+1).trim();return{rank:F+1,desc:W,author:q,url:Q,plays:0,likes:Z,comments:0,shares:0}}function V(B){return Boolean(B?.url&&B?.desc)}export function projectSearchCards(B,F){const G=(Array.isArray(B)?B.slice(0,F):[]).map((Y,Z)=>projectCard(Y,Z)),K=G.filter((Y)=>!V(Y)).length;return{rows:G.filter(V),invalidCount:K}}const X=(B)=>`
1
+ import{cli as w,Strategy as p}from"@jackwener/opencli/registry";import{ArgumentError as h,AuthRequiredError as g,CommandExecutionError as l,EmptyResultError as m}from"@jackwener/opencli/errors";export const MAX_SEARCH_LIMIT=30,RENDER_TIMEOUT_MS=15000;export function parseSearchLimit(e){const t=Number(e??10);if(!Number.isFinite(t)||!Number.isInteger(t))throw new h(`--limit must be an integer between 1 and ${MAX_SEARCH_LIMIT}, got ${JSON.stringify(e)}`);if(t<1||t>MAX_SEARCH_LIMIT)throw new h(`--limit must be between 1 and ${MAX_SEARCH_LIMIT}, got ${t}`);return t}export function parseDouyinCount(e){if(typeof e!=="string")return 0;const t=e.replace(/\s/g,"").match(/^(\d+(?:\.\d+)?)([万亿])?$/);if(!t){const r=Number(e.replace(/[,\s]/g,""));return Number.isFinite(r)?Math.round(r):0}const o=Number(t[1]);if(!Number.isFinite(o))return 0;if(t[2]==="万")return Math.round(o*1e4);if(t[2]==="亿")return Math.round(o*1e8);return Math.round(o)}export function extractDouyinVideoId(e){if(typeof e!=="string"||!e)return"";let t=e;if(t.startsWith("//"))t="https:"+t;else if(t.startsWith("/"))t="https://www.douyin.com"+t;try{const o=new URL(t);if(!/(^|\.)douyin\.com$/.test(o.hostname))return"";return o.pathname.match(/^\/video\/(\d+)$/)?.[1]??""}catch{return""}}export function normalizeDouyinVideoUrl(e){const t=extractDouyinVideoId(e);return t?`https://www.douyin.com/video/${t}`:""}function b(e){if(!e)return!0;if(/^\d{1,2}:\d{2}(?::\d{2})?$/.test(e))return!0;if(/^\d+(?:\.\d+)?[万亿]?$/.test(e))return!0;if(/^(合集|视频|作者)$/.test(e))return!0;if(/^(刚刚|今天|昨天|前天)$/.test(e))return!0;if(/^\d+\s*(秒|分钟|小时|天|周|个月|月|年)前$/.test(e))return!0;if(/^\d{4}[-/.年]\d{1,2}(?:[-/.月]\d{1,2}日?)?$/.test(e))return!0;return!1}export function projectCard(e,t){const o=normalizeDouyinVideoUrl(e?.url??e?.href),r=Array.isArray(e?.leafTexts)?e.leafTexts.map((u)=>String(u??"").trim()).filter(Boolean):[],n=/^\d{1,2}:\d{2}(?::\d{2})?$/,i=/^\d+(?:\.\d+)?[万亿]?$/;let s=0,c="",f="";for(let u=0;u<r.length;u++){const a=r[u];if(n.test(a))continue;if(!s&&i.test(a)){s=parseDouyinCount(a);continue}if(a==="@"&&!c){c=(r[u+1]??"").trim();continue}if(a===c)continue;if(b(a))continue;if(a.length>f.length)f=a}let d=f;if(c&&d.startsWith("@"+c))d=d.slice(c.length+1).trim();return{rank:t+1,desc:d,author:c,url:o,plays:0,likes:s,comments:0,shares:0}}function y(e){return Boolean(e?.url&&e?.desc)}export function projectSearchCards(e,t){const r=(Array.isArray(e)?e.slice(0,t):[]).map((i,s)=>projectCard(i,s)),n=r.filter((i)=>!y(i)).length;return{rows:r.filter(y),invalidCount:n}}const v=(e)=>`
2
2
  new Promise((resolve) => {
3
3
  const collectCards = () => {
4
4
  const cards = [];
@@ -46,6 +46,6 @@ import{cli as O,Strategy as H}from"@jackwener/opencli/registry";import{ArgumentE
46
46
  observer.disconnect();
47
47
  const fallback = detectState();
48
48
  resolve(fallback ?? { state: 'timeout' });
49
- }, ${B});
49
+ }, ${e});
50
50
  })
51
- `;function D(B){if(B&&!Array.isArray(B)&&typeof B==="object"&&"session"in B&&"data"in B)return B.data;return B}O({site:"douyin",name:"search",access:"read",description:"关键词搜索抖音视频",domain:"www.douyin.com",strategy:H.COOKIE,args:[{name:"query",required:!0,positional:!0,help:"搜索关键词"},{name:"limit",type:"int",default:10,help:`结果数量 (1-${MAX_SEARCH_LIMIT})`}],columns:["rank","desc","author","url","plays","likes","comments","shares"],func:async(B,F)=>{const Q=parseSearchLimit(F.limit),G=String(F.query??"").trim();if(!G)throw new v("douyin search 需要 <query> 关键词");await B.goto(`https://www.douyin.com/search/${encodeURIComponent(G)}?type=video`);let K;try{K=D(await B.evaluate(X(RENDER_TIMEOUT_MS)))}catch(Z){throw new J(`Douyin search extraction failed: ${Z instanceof Error?Z.message:String(Z)}`)}if(!K||typeof K!=="object")throw new J("Douyin search: unexpected evaluator payload shape");if(K.state==="login_wall")throw new N("www.douyin.com","Douyin search results are blocked behind a login wall — log in at https://www.douyin.com in Chrome first.");if(K.state==="empty")throw new P("douyin search",`No Douyin videos matched "${G}".`);if(K.state==="timeout")throw new J("Douyin search did not render result cards within the timeout. Open the same search in Chrome and verify login/security state before retrying.");if(!Array.isArray(K.cards))throw new J("Douyin search: evaluator returned malformed cards payload");if(K.cards.length===0)throw new P("douyin search",`No Douyin videos matched "${G}".`);const Y=projectSearchCards(K.cards,Q);if(Y.invalidCount>0)throw new J("Douyin search parser found result cards without stable video url or description");if(Y.rows.length===0)throw new P("douyin search",`No Douyin videos matched "${G}".`);return Y.rows}});
51
+ `;function A(e){if(e&&!Array.isArray(e)&&typeof e==="object"&&"session"in e&&"data"in e)return e.data;return e}w({site:"douyin",name:"search",access:"read",description:"关键词搜索抖音视频",domain:"www.douyin.com",strategy:p.COOKIE,args:[{name:"query",required:!0,positional:!0,help:"搜索关键词"},{name:"limit",type:"int",default:10,help:`结果数量 (1-${MAX_SEARCH_LIMIT})`}],columns:["rank","desc","author","url","plays","likes","comments","shares"],func:async(e,t)=>{const o=parseSearchLimit(t.limit),r=String(t.query??"").trim();if(!r)throw new h("douyin search 需要 <query> 关键词");await e.goto(`https://www.douyin.com/search/${encodeURIComponent(r)}?type=video`);let n;try{n=A(await e.evaluate(v(RENDER_TIMEOUT_MS)))}catch(s){throw new l(`Douyin search extraction failed: ${s instanceof Error?s.message:String(s)}`)}if(!n||typeof n!=="object")throw new l("Douyin search: unexpected evaluator payload shape");if(n.state==="login_wall")throw new g("www.douyin.com","Douyin search results are blocked behind a login wall — log in at https://www.douyin.com in Chrome first.");if(n.state==="empty")throw new m("douyin search",`No Douyin videos matched "${r}".`);if(n.state==="timeout")throw new l("Douyin search did not render result cards within the timeout. Open the same search in Chrome and verify login/security state before retrying.");if(!Array.isArray(n.cards))throw new l("Douyin search: evaluator returned malformed cards payload");if(n.cards.length===0)throw new m("douyin search",`No Douyin videos matched "${r}".`);const i=projectSearchCards(n.cards,o);if(i.invalidCount>0)throw new l("Douyin search parser found result cards without stable video url or description");if(i.rows.length===0)throw new m("douyin search",`No Douyin videos matched "${r}".`);return i.rows}});
@@ -1 +1 @@
1
- import{cli as H,Strategy as J}from"@jackwener/opencli/registry";import{browserFetch as K}from"./_shared/browser-fetch.js";function L(x,B){if(typeof x==="number")return x;if(!x)return B&&B>Date.now()/1000?"scheduled":"published";if(x.is_delete)return"deleted";if(x.is_prohibited)return"prohibited";if(x.in_reviewing)return"reviewing";if(x.is_private)return"private";if(B&&B>Date.now()/1000)return"scheduled";return"published"}H({site:"douyin",name:"videos",access:"read",description:"获取作品列表",domain:"creator.douyin.com",strategy:J.COOKIE,args:[{name:"limit",type:"int",default:20,help:"每页数量"},{name:"page",type:"int",default:1,help:"页码"},{name:"status",default:"all",choices:["all","published","reviewing","scheduled"]}],columns:["aweme_id","title","status","play_count","digg_count","create_time"],func:async(x,B)=>{const E={all:0,published:1,reviewing:3,scheduled:0}[B.status]??0,G=`https://creator.douyin.com/janus/douyin/creator/pc/work_list?page_size=${B.limit}&page_num=${B.page}&status=${E}`,D=await K(x,"GET",G);let C=D.data?.work_list??D.aweme_list??[];if(B.status==="scheduled")C=C.filter((q)=>(q.public_time??0)>Date.now()/1000);return C.map((q)=>({aweme_id:q.aweme_id,title:q.desc??"",status:L(q.status,q.public_time),play_count:q.statistics?.play_count??0,digg_count:q.statistics?.digg_count??0,create_time:new Date((q.create_time??q.public_time??0)*1000).toLocaleString("zh-CN",{timeZone:"Asia/Tokyo"})}))}});
1
+ import{cli as o,Strategy as u}from"@jackwener/opencli/registry";import{browserFetch as c}from"./_shared/browser-fetch.js";function d(t,i){if(typeof t==="number")return t;if(!t)return i&&i>Date.now()/1000?"scheduled":"published";if(t.is_delete)return"deleted";if(t.is_prohibited)return"prohibited";if(t.in_reviewing)return"reviewing";if(t.is_private)return"private";if(i&&i>Date.now()/1000)return"scheduled";return"published"}o({site:"douyin",name:"videos",access:"read",description:"获取作品列表",domain:"creator.douyin.com",strategy:u.COOKIE,args:[{name:"limit",type:"int",default:20,help:"每页数量"},{name:"page",type:"int",default:1,help:"页码"},{name:"status",default:"all",choices:["all","published","reviewing","scheduled"]}],columns:["aweme_id","title","status","play_count","digg_count","create_time"],func:async(t,i)=>{const r={all:0,published:1,reviewing:3,scheduled:0}[i.status]??0,s=`https://creator.douyin.com/janus/douyin/creator/pc/work_list?page_size=${i.limit}&page_num=${i.page}&status=${r}`,n=await c(t,"GET",s);let a=n.data?.work_list??n.aweme_list??[];if(i.status==="scheduled")a=a.filter((e)=>(e.public_time??0)>Date.now()/1000);return a.map((e)=>({aweme_id:e.aweme_id,title:e.desc??"",status:d(e.status,e.public_time),play_count:e.statistics?.play_count??0,digg_count:e.statistics?.digg_count??0,create_time:new Date((e.create_time??e.public_time??0)*1000).toLocaleString("zh-CN",{timeZone:"Asia/Tokyo"})}))}});
@@ -1 +1 @@
1
- const V=(q)=>{if(/^(60|68|90|113|900)/.test(q))return"1";if(/^(00|30|20)/.test(q))return"0";if(/^(4|8|920|83|87)/.test(q))return"0";return"0"},Y=new Set(["0","1","100","105","106","107","116","140","150","151","152","155","156"]);export function resolveSecid(q){const j=String(q||"").trim();if(!j)throw Error("empty symbol");const G=j.match(/^(\d{1,3})\.([A-Za-z0-9]+)$/);if(G&&Y.has(G[1]))return j;const v=j.toLowerCase(),H=v.match(/^(sh|sz|bj)(\d{6})$/);if(H){const[,Q,U]=H;return(Q==="sh"?"1":"0")+"."+U}const J=v.match(/^hk(\d{4,5})$/)||v.match(/^(\d{4,5})\.hk$/);if(J)return"116."+J[1].padStart(5,"0");const B=v.match(/^([a-z.\-]+)\.([no])$/);if(B)return(B[2]==="n"?"106":"105")+"."+B[1].toUpperCase();const L=v.match(/^us\.([a-z.\-]+)$/);if(L)return"105."+L[1].toUpperCase();if(/^\d{6}$/.test(j))return V(j)+"."+j;if(/^[A-Z.\-]{1,8}$/.test(j))return"105."+j;throw Error(`Unrecognized symbol: ${q}`)}export function splitSymbols(q){return String(q||"").split(/[,,\s]+/).map((j)=>j.trim()).filter(Boolean)}
1
+ const u=(r)=>{if(/^(60|68|90|113|900)/.test(r))return"1";if(/^(00|30|20)/.test(r))return"0";if(/^(4|8|920|83|87)/.test(r))return"0";return"0"},h=new Set(["0","1","100","105","106","107","116","140","150","151","152","155","156"]);export function resolveSecid(r){const t=String(r||"").trim();if(!t)throw Error("empty symbol");const o=t.match(/^(\d{1,3})\.([A-Za-z0-9]+)$/);if(o&&h.has(o[1]))return t;const e=t.toLowerCase(),s=e.match(/^(sh|sz|bj)(\d{6})$/);if(s){const[,a,f]=s;return(a==="sh"?"1":"0")+"."+f}const i=e.match(/^hk(\d{4,5})$/)||e.match(/^(\d{4,5})\.hk$/);if(i)return"116."+i[1].padStart(5,"0");const n=e.match(/^([a-z.\-]+)\.([no])$/);if(n)return(n[2]==="n"?"106":"105")+"."+n[1].toUpperCase();const c=e.match(/^us\.([a-z.\-]+)$/);if(c)return"105."+c[1].toUpperCase();if(/^\d{6}$/.test(t))return u(t)+"."+t;if(/^[A-Z.\-]{1,8}$/.test(t))return"105."+t;throw Error(`Unrecognized symbol: ${r}`)}export function splitSymbols(r){return String(r||"").split(/[,,\s]+/).map((t)=>t.trim()).filter(Boolean)}
@@ -1 +1 @@
1
- import{cli as d,Strategy as y}from"@jackwener/opencli/registry";import{CliError as m}from"@jackwener/opencli/errors";d({site:"eastmoney",name:"announcement",access:"read",description:"上市公司公告(按交易所筛选)",domain:"np-anotice-stock.eastmoney.com",strategy:y.PUBLIC,browser:!1,args:[{name:"market",type:"string",default:"SHA,SZA,BJA",help:"交易所:SHA (沪) / SZA (深) / BJA (北) 可逗号分隔"},{name:"limit",type:"int",default:20,help:"返回数量 (max 100)"}],columns:["time","code","name","title","category","url"],func:async(s)=>{const i=String(s.market??"SHA,SZA,BJA").trim()||"SHA,SZA,BJA",r=Math.max(1,Math.min(Number(s.limit)||20,100)),t=new URL("https://np-anotice-stock.eastmoney.com/api/security/ann");t.searchParams.set("page_size",String(r));t.searchParams.set("page_index","1");t.searchParams.set("ann_type",i);t.searchParams.set("client_source","web");t.searchParams.set("f_node","0");t.searchParams.set("s_node","0");const a=await fetch(t,{headers:{"User-Agent":"Mozilla/5.0"}});if(!a.ok)throw new m("HTTP_ERROR",`announcement failed: HTTP ${a.status}`);const o=await a.json(),c=Array.isArray(o?.data?.list)?o.data.list:[];if(c.length===0)throw new m("NO_DATA","eastmoney returned no announcement data");return c.slice(0,r).map((e)=>{const n=Array.isArray(e.codes)&&e.codes.length>0?e.codes[0]:{},l=Array.isArray(e.columns)&&e.columns.length>0?e.columns[0]?.column_name:"";return{time:String(e.notice_date||e.display_time||"").slice(0,19),code:n.stock_code||"",name:n.short_name||"",title:e.title||e.title_ch||"",category:l||"",url:`https://data.eastmoney.com/notices/detail/${n.stock_code||""}/${e.art_code||""}.html`}})}});
1
+ import{cli as d,Strategy as h}from"@jackwener/opencli/registry";import{CliError as m}from"@jackwener/opencli/errors";d({site:"eastmoney",name:"announcement",access:"read",description:"上市公司公告(按交易所筛选)",domain:"np-anotice-stock.eastmoney.com",strategy:h.PUBLIC,browser:!1,args:[{name:"market",type:"string",default:"SHA,SZA,BJA",help:"交易所:SHA (沪) / SZA (深) / BJA (北) 可逗号分隔"},{name:"limit",type:"int",default:20,help:"返回数量 (max 100)"}],columns:["time","code","name","title","category","url"],func:async(n)=>{const i=String(n.market??"SHA,SZA,BJA").trim()||"SHA,SZA,BJA",r=Math.max(1,Math.min(Number(n.limit)||20,100)),t=new URL("https://np-anotice-stock.eastmoney.com/api/security/ann");t.searchParams.set("page_size",String(r));t.searchParams.set("page_index","1");t.searchParams.set("ann_type",i);t.searchParams.set("client_source","web");t.searchParams.set("f_node","0");t.searchParams.set("s_node","0");const a=await fetch(t,{headers:{"User-Agent":"Mozilla/5.0"}});if(!a.ok)throw new m("HTTP_ERROR",`announcement failed: HTTP ${a.status}`);const o=await a.json(),c=Array.isArray(o?.data?.list)?o.data.list:[];if(c.length===0)throw new m("NO_DATA","eastmoney returned no announcement data");return c.slice(0,r).map((e)=>{const s=Array.isArray(e.codes)&&e.codes.length>0?e.codes[0]:{},l=Array.isArray(e.columns)&&e.columns.length>0?e.columns[0]?.column_name:"";return{time:String(e.notice_date||e.display_time||"").slice(0,19),code:s.stock_code||"",name:s.short_name||"",title:e.title||e.title_ch||"",category:l||"",url:`https://data.eastmoney.com/notices/detail/${s.stock_code||""}/${e.art_code||""}.html`}})}});
@@ -1 +1 @@
1
- import{CliError as X,CommandExecutionError as v}from"@jackwener/opencli/errors";import{cli as N,Strategy as h}from"@jackwener/opencli/registry";import{publishArticle as S}from"../_shared/article/publish.js";import{checkLogin as P}from"../_shared/article/auth.js";export const authProfile={home:"https://mp.eastmoney.com",checkAuth:async(B)=>{const H=B.cookie("ct"),z=B.cookie("ut");if(!H||!z)return{isAuthenticated:!1,error:"未检测到登录 cookie(ct/ut),请先登录东方财富"};try{const G=await fetch(`https://caifuhaoapi.eastmoney.com/api/v2/getauthorinfo?platform=&ctoken=${encodeURIComponent(H)}&utoken=${encodeURIComponent(z)}`,{method:"GET",credentials:"include",headers:{"x-requested-with":"fetch"}});if(!G.ok)return{isAuthenticated:!1,error:`账号接口 HTTP ${G.status}`};const J=await G.json();if(J.Success===1&&J.Result&&J.Result.accountId)return{isAuthenticated:!0,userId:String(J.Result.accountId),username:J.Result.accountName||"",avatar:J.Result.portrait||""};return{isAuthenticated:!1}}catch(G){return{isAuthenticated:!1,error:String(G&&G.message||G)}}}};const x={home:"https://mp.eastmoney.com",outputFormat:"html",preprocessConfig:{removeComments:!0,removeSpecialTags:!0,processCodeBlocks:!0,convertSectionToDiv:!0,removeEmptyLines:!0,removeEmptyDivs:!0,removeNestedEmptyContainers:!0,unwrapSingleChildContainers:!0,unwrapNestedFigures:!0,removeTrailingBr:!0,removeDataAttributes:!0,removeSrcset:!0,removeSizes:!0,compactHtml:!0},image:{skip:["gbres.dfcfw.com"],uploadFn:async(B,H)=>{const z=H.cookie("ct"),G=H.cookie("ut");if(!z||!G)throw Error("东方财富图片上传失败:未检测到登录 cookie(ct/ut),请先登录");if(B.indexOf("data:")===0){const Q=B.split(","),Y=(Q[0].match(/:(.*?);/)||[])[1]||"image/png",Z=Y.split("/")[1]||"png",V=atob(Q[1]),T=new Uint8Array(V.length);for(let $=0;$<V.length;$++)T[$]=V.charCodeAt($);const U=new Blob([T],{type:Y}),_=Date.now()+"."+Z,K=new FormData;K.append("file",U,_);K.append("noinlist","1");K.append("utoken",G);K.append("ctoken",z);const W=await(await fetch("https://gbapi.eastmoney.com/iimage/image?platform=",{method:"POST",credentials:"include",body:K})).json();if(W.code===200&&W.data&&W.data.url)return{url:W.data.url};throw Error("东方财富图片二进制上传失败:"+(W.message||"未知错误")+" (code: "+W.code+")")}const J=new URLSearchParams({noinlist:"1",linkUrl:B,ctoken:z,utoken:G}),L=await(await fetch("https://gbapi.eastmoney.com/iimage/image/byLink?platform=",{method:"PUT",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:J.toString()})).json();if(L.code===200&&L.data&&L.data.url)return{url:L.data.url};throw Error("东方财富图片链接上传失败:"+(L.message||"未知错误")+" (code: "+L.code+")")}},publish:async(B,H)=>{const z=H.cookie("ct"),G=H.cookie("ut");if(!z||!G)return{ok:!1,stage:"auth",status:401,message:"未检测到登录 cookie(ct/ut),请先登录东方财富"};const J=new Uint8Array(16);crypto.getRandomValues(J);const M=Array.from(J).map(function(K){return K.toString(16).padStart(2,"0").toUpperCase()}).join("");function L(K){return[{ip:"$IP$"},{deviceid:M},{version:"100"},{plat:"web"},{product:"CFH"},{ctoken:z},{utoken:G},{draftid:K.draftid||""},{drafttype:"0"},{type:"0"},{title:encodeURIComponent(K.title)},{text:encodeURIComponent(K.text)},{columns:"2"},{cover:""},{issimplevideo:"0"},{videos:""},{vods:""},{isoriginal:"0"},{tgProduct:""},{spcolumns:""},{textsource:"0"},{replyauthority:""},{modules:encodeURIComponent("[]")}]}async function Q(K,A){const W=A?"https://mp.eastmoney.com/collect/pc_article/index.html#/?id="+A:"https://mp.eastmoney.com/collect/pc_article/index.html#/",$=JSON.stringify({pageUrl:W,path:"draft/api/Article/SaveDraft",parm:JSON.stringify(K)}),F=await fetch("https://emfront.eastmoney.com/apifront/Tran/GetData?platform=",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:$});if(!F.ok)return{ok:!1,stage:"draft_api",status:F.status,message:"草稿 API 请求失败: "+F.status};let q;try{q=await F.json()}catch(j){return{ok:!1,stage:"draft_api",status:F.status,message:"草稿 API 响应不是有效 JSON"}}if(!q.RRquestSuccess||q.RCode!==200)return{ok:!1,stage:"draft_api",status:q.RCode,message:"草稿 API 错误: "+(q.RMsg||"未知错误")};let O;try{O=JSON.parse(q.RData)}catch(j){return{ok:!1,stage:"draft_parse",status:200,message:"无法解析草稿响应数据"}}if(O.error_code!==0)return{ok:!1,stage:"draft_business",status:O.error_code,message:"草稿业务错误: "+(O.me||"未知错误")};return{ok:!0,data:O}}const Y=L({title:B.title,text:'<div class="xeditor_content cfh_web"></div>'}),Z=await Q(Y);if(!Z.ok)return Z;const V=Z.data&&Z.data.draft_id;if(!V)return{ok:!1,stage:"create",status:200,message:"创建草稿失败:响应缺少 draft_id"};const T=L({draftid:V,title:B.title,text:'<div class="xeditor_content cfh_web">'+B.content+"</div>"}),U=await Q(T,V);if(!U.ok)return U;const _="https://mp.eastmoney.com/collect/pc_article/index.html#/?id="+V;return{ok:!0,draft:!0,id:V,url:_}}};import{readFile as R,stat as C}from"node:fs/promises";function E(B){if(!B.execute)throw new X("INVALID_INPUT","此命令需要 --execute 参数才能实际写入。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}async function D(B){const H=typeof B.text==="string"?B.text:void 0,z=typeof B.file==="string"?B.file:void 0;if(H&&z)throw new X("INVALID_INPUT","正文和 --file 只能二选一");let G=H??"";if(z){let J;try{J=await C(z)}catch{throw new X("INVALID_INPUT",`文件不存在:${z}`)}if(!J.isFile())throw new X("INVALID_INPUT",`必须是可读文本文件:${z}`);let M;try{M=await R(z)}catch{throw new X("INVALID_INPUT",`文件无法读取:${z}`)}try{G=new TextDecoder("utf-8",{fatal:!0}).decode(M)}catch{throw new X("INVALID_INPUT",`文件无法以 UTF-8 解码:${z}`)}}if(!G.trim())throw new X("INVALID_INPUT","正文不能为空");return G}function y(B,H,z,G,J={}){return[{status:"success",outcome:G,message:B,target_type:H,target:z,...J}]}N({site:"eastmoney",name:"article",access:"write",description:"发布东方财富财富号文章(草稿)。正文默认 Markdown;图片自动转存到东方财富图床。",domain:"mp.eastmoney.com",strategy:h.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题"},{name:"text",positional:!0,help:"文章正文(默认 Markdown;--html 表示 HTML)"},{name:"file",help:"正文文件路径(UTF-8,默认 Markdown)"},{name:"html",type:"boolean",help:"正文格式为 HTML 而非 Markdown"},{name:"draft",type:"boolean",help:"仅保存草稿(东方财富 mp 端目前仅支持草稿,默认即草稿)"},{name:"execute",type:"boolean",help:"确认实际写入,不带此参数时拒绝写操作"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(B,H)=>{if(!B)throw new v("东方财富文章发布需要浏览器会话(browser session required)");E(H);const z=String(H.title??"").trim();if(!z)throw new X("INVALID_INPUT","文章标题不能为空");const G=await D(H),J=!0,M=await S(B,{title:z,body:G,format:H.html?"html":"markdown",draftOnly:J,profile:x}),L=M.images.uploaded.length|0,Q=M.images.failed.length|0;let Y="已保存东方财富草稿";if(L||Q)Y+=`(图片:${L} 张已转存${Q?`,${Q} 张失败`:""})`;return y(Y,"article","","draft",{created_target:"article:"+M.id,created_url:M.url})}});
1
+ import{CliError as d,CommandExecutionError as v}from"@jackwener/opencli/errors";import{cli as x,Strategy as A}from"@jackwener/opencli/registry";import{publishArticle as N}from"../_shared/article/publish.js";import{checkLogin as F}from"../_shared/article/auth.js";export const authProfile={home:"https://mp.eastmoney.com",checkAuth:async(e)=>{const r=e.cookie("ct"),t=e.cookie("ut");if(!r||!t)return{isAuthenticated:!1,error:"未检测到登录 cookie(ct/ut),请先登录东方财富"};try{const o=await fetch(`https://caifuhaoapi.eastmoney.com/api/v2/getauthorinfo?platform=&ctoken=${encodeURIComponent(r)}&utoken=${encodeURIComponent(t)}`,{method:"GET",credentials:"include",headers:{"x-requested-with":"fetch"}});if(!o.ok)return{isAuthenticated:!1,error:`账号接口 HTTP ${o.status}`};const a=await o.json();if(a.Success===1&&a.Result&&a.Result.accountId)return{isAuthenticated:!0,userId:String(a.Result.accountId),username:a.Result.accountName||"",avatar:a.Result.portrait||""};return{isAuthenticated:!1}}catch(o){return{isAuthenticated:!1,error:String(o&&o.message||o)}}}};const T={home:"https://mp.eastmoney.com",outputFormat:"html",preprocessConfig:{removeComments:!0,removeSpecialTags:!0,processCodeBlocks:!0,convertSectionToDiv:!0,removeEmptyLines:!0,removeEmptyDivs:!0,removeNestedEmptyContainers:!0,unwrapSingleChildContainers:!0,unwrapNestedFigures:!0,removeTrailingBr:!0,removeDataAttributes:!0,removeSrcset:!0,removeSizes:!0,compactHtml:!0},image:{skip:["gbres.dfcfw.com"],uploadFn:async(e,r)=>{const t=r.cookie("ct"),o=r.cookie("ut");if(!t||!o)throw Error("东方财富图片上传失败:未检测到登录 cookie(ct/ut),请先登录");if(e.indexOf("data:")===0){const c=e.split(","),m=(c[0].match(/:(.*?);/)||[])[1]||"image/png",p=m.split("/")[1]||"png",u=atob(c[1]),g=new Uint8Array(u.length);for(let f=0;f<u.length;f++)g[f]=u.charCodeAt(f);const k=new Blob([g],{type:m}),I=Date.now()+"."+p,n=new FormData;n.append("file",k,I);n.append("noinlist","1");n.append("utoken",o);n.append("ctoken",t);const l=await(await fetch("https://gbapi.eastmoney.com/iimage/image?platform=",{method:"POST",credentials:"include",body:n})).json();if(l.code===200&&l.data&&l.data.url)return{url:l.data.url};throw Error("东方财富图片二进制上传失败:"+(l.message||"未知错误")+" (code: "+l.code+")")}const a=new URLSearchParams({noinlist:"1",linkUrl:e,ctoken:t,utoken:o}),s=await(await fetch("https://gbapi.eastmoney.com/iimage/image/byLink?platform=",{method:"PUT",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:a.toString()})).json();if(s.code===200&&s.data&&s.data.url)return{url:s.data.url};throw Error("东方财富图片链接上传失败:"+(s.message||"未知错误")+" (code: "+s.code+")")}},publish:async(e,r)=>{const t=r.cookie("ct"),o=r.cookie("ut");if(!t||!o)return{ok:!1,stage:"auth",status:401,message:"未检测到登录 cookie(ct/ut),请先登录东方财富"};const a=new Uint8Array(16);crypto.getRandomValues(a);const i=Array.from(a).map(function(n){return n.toString(16).padStart(2,"0").toUpperCase()}).join("");function s(n){return[{ip:"$IP$"},{deviceid:i},{version:"100"},{plat:"web"},{product:"CFH"},{ctoken:t},{utoken:o},{draftid:n.draftid||""},{drafttype:"0"},{type:"0"},{title:encodeURIComponent(n.title)},{text:encodeURIComponent(n.text)},{columns:"2"},{cover:""},{issimplevideo:"0"},{videos:""},{vods:""},{isoriginal:"0"},{tgProduct:""},{spcolumns:""},{textsource:"0"},{replyauthority:""},{modules:encodeURIComponent("[]")}]}async function c(n,b){const l=b?"https://mp.eastmoney.com/collect/pc_article/index.html#/?id="+b:"https://mp.eastmoney.com/collect/pc_article/index.html#/",f=JSON.stringify({pageUrl:l,path:"draft/api/Article/SaveDraft",parm:JSON.stringify(n)}),y=await fetch("https://emfront.eastmoney.com/apifront/Tran/GetData?platform=",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:f});if(!y.ok)return{ok:!1,stage:"draft_api",status:y.status,message:"草稿 API 请求失败: "+y.status};let h;try{h=await y.json()}catch(_){return{ok:!1,stage:"draft_api",status:y.status,message:"草稿 API 响应不是有效 JSON"}}if(!h.RRquestSuccess||h.RCode!==200)return{ok:!1,stage:"draft_api",status:h.RCode,message:"草稿 API 错误: "+(h.RMsg||"未知错误")};let w;try{w=JSON.parse(h.RData)}catch(_){return{ok:!1,stage:"draft_parse",status:200,message:"无法解析草稿响应数据"}}if(w.error_code!==0)return{ok:!1,stage:"draft_business",status:w.error_code,message:"草稿业务错误: "+(w.me||"未知错误")};return{ok:!0,data:w}}const m=s({title:e.title,text:'<div class="xeditor_content cfh_web"></div>'}),p=await c(m);if(!p.ok)return p;const u=p.data&&p.data.draft_id;if(!u)return{ok:!1,stage:"create",status:200,message:"创建草稿失败:响应缺少 draft_id"};const g=s({draftid:u,title:e.title,text:'<div class="xeditor_content cfh_web">'+e.content+"</div>"}),k=await c(g,u);if(!k.ok)return k;const I="https://mp.eastmoney.com/collect/pc_article/index.html#/?id="+u;return{ok:!0,draft:!0,id:u,url:I}}};import{readFile as S,stat as U}from"node:fs/promises";function R(e){if(!e.execute)throw new d("INVALID_INPUT","此命令需要 --execute 参数才能实际写入。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}async function C(e){const r=typeof e.text==="string"?e.text:void 0,t=typeof e.file==="string"?e.file:void 0;if(r&&t)throw new d("INVALID_INPUT","正文和 --file 只能二选一");let o=r??"";if(t){let a;try{a=await U(t)}catch{throw new d("INVALID_INPUT",`文件不存在:${t}`)}if(!a.isFile())throw new d("INVALID_INPUT",`必须是可读文本文件:${t}`);let i;try{i=await S(t)}catch{throw new d("INVALID_INPUT",`文件无法读取:${t}`)}try{o=new TextDecoder("utf-8",{fatal:!0}).decode(i)}catch{throw new d("INVALID_INPUT",`文件无法以 UTF-8 解码:${t}`)}}if(!o.trim())throw new d("INVALID_INPUT","正文不能为空");return o}function D(e,r,t,o,a={}){return[{status:"success",outcome:o,message:e,target_type:r,target:t,...a}]}x({site:"eastmoney",name:"article",access:"write",description:"发布东方财富财富号文章(草稿)。正文默认 Markdown;图片自动转存到东方财富图床。",domain:"mp.eastmoney.com",strategy:A.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题"},{name:"text",positional:!0,help:"文章正文(默认 Markdown;--html 表示 HTML)"},{name:"file",help:"正文文件路径(UTF-8,默认 Markdown)"},{name:"html",type:"boolean",help:"正文格式为 HTML 而非 Markdown"},{name:"draft",type:"boolean",help:"仅保存草稿(东方财富 mp 端目前仅支持草稿,默认即草稿)"},{name:"execute",type:"boolean",help:"确认实际写入,不带此参数时拒绝写操作"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(e,r)=>{if(!e)throw new v("东方财富文章发布需要浏览器会话(browser session required)");R(r);const t=String(r.title??"").trim();if(!t)throw new d("INVALID_INPUT","文章标题不能为空");const o=await C(r),a=!0,i=await N(e,{title:t,body:o,format:r.html?"html":"markdown",draftOnly:a,profile:T}),s=i.images.uploaded.length|0,c=i.images.failed.length|0;let m="已保存东方财富草稿";if(s||c)m+=`(图片:${s} 张已转存${c?`,${c} 张失败`:""})`;return D(m,"article","","draft",{created_target:"article:"+i.id,created_url:i.url})}});
@@ -1 +1 @@
1
- import{cli as l,Strategy as h}from"@jackwener/opencli/registry";import{CliError as s}from"@jackwener/opencli/errors";const d={change:{fid:"f3",order:"desc"},drop:{fid:"f3",order:"asc"},turnover:{fid:"f6",order:"desc"},price:{fid:"f2",order:"desc"},premium:{fid:"f237",order:"desc"},value:{fid:"f236",order:"desc"},ytm:{fid:"f239",order:"desc"}};l({site:"eastmoney",name:"convertible",access:"read",description:"可转债行情列表(默认按成交额排序)",domain:"push2.eastmoney.com",strategy:h.PUBLIC,browser:!1,args:[{name:"sort",type:"string",default:"turnover",help:"排序:turnover / change / drop / price / premium"},{name:"limit",type:"int",default:20,help:"返回数量 (max 100)"}],columns:["rank","bondCode","bondName","bondPrice","bondChangePct","stockCode","stockName","stockPrice","stockChangePct","convPrice","convValue","convPremiumPct","remainingYears","ytm","listDate"],func:async(o)=>{const n=String(o.sort??"turnover").toLowerCase(),t=d[n];if(!t)throw new s("INVALID_ARGUMENT",`Unknown sort "${n}". Valid: ${Object.keys(d).join(", ")}`);const c=Math.max(1,Math.min(Number(o.limit)||20,100)),r=new URL("https://push2.eastmoney.com/api/qt/clist/get");r.searchParams.set("pn","1");r.searchParams.set("pz",String(c));r.searchParams.set("po",t.order==="desc"?"1":"0");r.searchParams.set("np","1");r.searchParams.set("fltt","2");r.searchParams.set("invt","2");r.searchParams.set("fid",t.fid);r.searchParams.set("fs","b:MK0354");r.searchParams.set("fields","f12,f14,f2,f3,f6,f229,f230,f232,f234,f235,f236,f237,f238,f239,f243");r.searchParams.set("ut","bd1d9ddb04089700cf9c27f6f7426281");const a=await fetch(r,{headers:{"User-Agent":"Mozilla/5.0"}});if(!a.ok)throw new s("HTTP_ERROR",`convertible failed: HTTP ${a.status}`);const f=await a.json(),i=Array.isArray(f?.data?.diff)?f.data.diff:[];if(i.length===0)throw new s("NO_DATA","eastmoney returned no convertible data");return i.slice(0,c).map((e,m)=>({rank:m+1,bondCode:e.f12,bondName:e.f14,bondPrice:e.f2,bondChangePct:e.f3,stockCode:e.f232,stockName:e.f234,stockPrice:e.f229,stockChangePct:e.f230,convPrice:e.f235,convValue:e.f236,convPremiumPct:e.f237,remainingYears:e.f238,ytm:e.f239,listDate:String(e.f243??"")}))}});
1
+ import{cli as h,Strategy as l}from"@jackwener/opencli/registry";import{CliError as t}from"@jackwener/opencli/errors";const i={change:{fid:"f3",order:"desc"},drop:{fid:"f3",order:"asc"},turnover:{fid:"f6",order:"desc"},price:{fid:"f2",order:"desc"},premium:{fid:"f237",order:"desc"},value:{fid:"f236",order:"desc"},ytm:{fid:"f239",order:"desc"}};h({site:"eastmoney",name:"convertible",access:"read",description:"可转债行情列表(默认按成交额排序)",domain:"push2.eastmoney.com",strategy:l.PUBLIC,browser:!1,args:[{name:"sort",type:"string",default:"turnover",help:"排序:turnover / change / drop / price / premium"},{name:"limit",type:"int",default:20,help:"返回数量 (max 100)"}],columns:["rank","bondCode","bondName","bondPrice","bondChangePct","stockCode","stockName","stockPrice","stockChangePct","convPrice","convValue","convPremiumPct","remainingYears","ytm","listDate"],func:async(o)=>{const n=String(o.sort??"turnover").toLowerCase(),a=i[n];if(!a)throw new t("INVALID_ARGUMENT",`Unknown sort "${n}". Valid: ${Object.keys(i).join(", ")}`);const c=Math.max(1,Math.min(Number(o.limit)||20,100)),r=new URL("https://push2.eastmoney.com/api/qt/clist/get");r.searchParams.set("pn","1");r.searchParams.set("pz",String(c));r.searchParams.set("po",a.order==="desc"?"1":"0");r.searchParams.set("np","1");r.searchParams.set("fltt","2");r.searchParams.set("invt","2");r.searchParams.set("fid",a.fid);r.searchParams.set("fs","b:MK0354");r.searchParams.set("fields","f12,f14,f2,f3,f6,f229,f230,f232,f234,f235,f236,f237,f238,f239,f243");r.searchParams.set("ut","bd1d9ddb04089700cf9c27f6f7426281");const s=await fetch(r,{headers:{"User-Agent":"Mozilla/5.0"}});if(!s.ok)throw new t("HTTP_ERROR",`convertible failed: HTTP ${s.status}`);const f=await s.json(),d=Array.isArray(f?.data?.diff)?f.data.diff:[];if(d.length===0)throw new t("NO_DATA","eastmoney returned no convertible data");return d.slice(0,c).map((e,m)=>({rank:m+1,bondCode:e.f12,bondName:e.f14,bondPrice:e.f2,bondChangePct:e.f3,stockCode:e.f232,stockName:e.f234,stockPrice:e.f229,stockChangePct:e.f230,convPrice:e.f235,convValue:e.f236,convPremiumPct:e.f237,remainingYears:e.f238,ytm:e.f239,listDate:String(e.f243??"")}))}});
@@ -1 +1 @@
1
- import{cli as h,Strategy as l}from"@jackwener/opencli/registry";import{CliError as s}from"@jackwener/opencli/errors";const d={turnover:{fid:"f6",order:"desc"},change:{fid:"f3",order:"desc"},drop:{fid:"f3",order:"asc"},volume:{fid:"f5",order:"desc"},rate:{fid:"f8",order:"desc"}};h({site:"eastmoney",name:"etf",access:"read",description:"ETF 列表按成交额/涨跌幅排行",domain:"push2.eastmoney.com",strategy:l.PUBLIC,browser:!1,args:[{name:"sort",type:"string",default:"turnover",help:"排序:turnover / change / drop / volume / rate"},{name:"limit",type:"int",default:20,help:"返回数量 (max 100)"}],columns:["rank","code","name","price","changePercent","change","turnover","volume","turnoverRate"],func:async(n)=>{const o=String(n.sort??"turnover").toLowerCase(),a=d[o];if(!a)throw new s("INVALID_ARGUMENT",`Unknown sort "${o}". Valid: ${Object.keys(d).join(", ")}`);const f=Math.max(1,Math.min(Number(n.limit)||20,100)),e=new URL("https://push2.eastmoney.com/api/qt/clist/get");e.searchParams.set("pn","1");e.searchParams.set("pz",String(f));e.searchParams.set("po",a.order==="desc"?"1":"0");e.searchParams.set("np","1");e.searchParams.set("fltt","2");e.searchParams.set("invt","2");e.searchParams.set("fid",a.fid);e.searchParams.set("fs","b:MK0021");e.searchParams.set("fields","f12,f14,f2,f3,f4,f5,f6,f8");e.searchParams.set("ut","bd1d9ddb04089700cf9c27f6f7426281");const t=await fetch(e,{headers:{"User-Agent":"Mozilla/5.0"}});if(!t.ok)throw new s("HTTP_ERROR",`etf failed: HTTP ${t.status}`);const c=await t.json(),i=Array.isArray(c?.data?.diff)?c.data.diff:[];if(i.length===0)throw new s("NO_DATA","eastmoney returned no ETF data");return i.slice(0,f).map((r,m)=>({rank:m+1,code:r.f12,name:r.f14,price:r.f2,changePercent:r.f3,change:r.f4,turnover:r.f6,volume:r.f5,turnoverRate:r.f8}))}});
1
+ import{cli as h,Strategy as l}from"@jackwener/opencli/registry";import{CliError as s}from"@jackwener/opencli/errors";const i={turnover:{fid:"f6",order:"desc"},change:{fid:"f3",order:"desc"},drop:{fid:"f3",order:"asc"},volume:{fid:"f5",order:"desc"},rate:{fid:"f8",order:"desc"}};h({site:"eastmoney",name:"etf",access:"read",description:"ETF 列表按成交额/涨跌幅排行",domain:"push2.eastmoney.com",strategy:l.PUBLIC,browser:!1,args:[{name:"sort",type:"string",default:"turnover",help:"排序:turnover / change / drop / volume / rate"},{name:"limit",type:"int",default:20,help:"返回数量 (max 100)"}],columns:["rank","code","name","price","changePercent","change","turnover","volume","turnoverRate"],func:async(n)=>{const o=String(n.sort??"turnover").toLowerCase(),a=i[o];if(!a)throw new s("INVALID_ARGUMENT",`Unknown sort "${o}". Valid: ${Object.keys(i).join(", ")}`);const f=Math.max(1,Math.min(Number(n.limit)||20,100)),e=new URL("https://push2.eastmoney.com/api/qt/clist/get");e.searchParams.set("pn","1");e.searchParams.set("pz",String(f));e.searchParams.set("po",a.order==="desc"?"1":"0");e.searchParams.set("np","1");e.searchParams.set("fltt","2");e.searchParams.set("invt","2");e.searchParams.set("fid",a.fid);e.searchParams.set("fs","b:MK0021");e.searchParams.set("fields","f12,f14,f2,f3,f4,f5,f6,f8");e.searchParams.set("ut","bd1d9ddb04089700cf9c27f6f7426281");const t=await fetch(e,{headers:{"User-Agent":"Mozilla/5.0"}});if(!t.ok)throw new s("HTTP_ERROR",`etf failed: HTTP ${t.status}`);const c=await t.json(),d=Array.isArray(c?.data?.diff)?c.data.diff:[];if(d.length===0)throw new s("NO_DATA","eastmoney returned no ETF data");return d.slice(0,f).map((r,m)=>({rank:m+1,code:r.f12,name:r.f14,price:r.f2,changePercent:r.f3,change:r.f4,turnover:r.f6,volume:r.f5,turnoverRate:r.f8}))}});
@@ -1 +1 @@
1
- import{cli as H,Strategy as I}from"@jackwener/opencli/registry";import{CliError as D}from"@jackwener/opencli/errors";function J(z){const b=String(z||"").trim().toUpperCase();if(/^\d{6}\.(SH|SZ|BJ)$/.test(b))return b;const x=b.match(/^(SH|SZ|BJ)(\d{6})$/);if(x)return`${x[2]}.${x[1]}`;if(/^\d{6}$/.test(b)){if(/^(60|68|90|113|900)/.test(b))return`${b}.SH`;if(/^(4|8|920|83|87)/.test(b))return`${b}.BJ`;return`${b}.SZ`}throw Error(`Unrecognized A-share symbol: ${z}`)}H({site:"eastmoney",name:"holders",access:"read",description:"十大流通股东(A股 F10 数据)",domain:"datacenter-web.eastmoney.com",strategy:I.PUBLIC,browser:!1,args:[{name:"symbol",required:!0,positional:!0,help:"A股代码(600519 / sh600519 等)"},{name:"limit",type:"int",default:10,help:"返回股东数(默认十大流通股东)"}],columns:["rank","reportDate","name","holdNum","floatRatio","change"],func:async(z)=>{let b;try{b=J(z.symbol)}catch(q){throw new D("INVALID_ARGUMENT",`${q instanceof Error?q.message:q}`)}const x=Math.max(1,Math.min(Number(z.limit)||10,50)),v=new URL("https://datacenter-web.eastmoney.com/api/data/v1/get");v.searchParams.set("sortColumns","END_DATE,HOLDER_RANK");v.searchParams.set("sortTypes","-1,1");v.searchParams.set("pageSize",String(Math.max(x,10)));v.searchParams.set("pageNumber","1");v.searchParams.set("reportName","RPT_F10_EH_FREEHOLDERS");v.searchParams.set("columns","SECUCODE,SECURITY_CODE,END_DATE,HOLDER_RANK,HOLDER_NAME,HOLD_NUM,FREE_HOLDNUM_RATIO,HOLD_NUM_CHANGE");v.searchParams.set("source","HSF10");v.searchParams.set("client","PC");v.searchParams.set("filter",`(SECUCODE="${b}")`);const A=await fetch(v,{headers:{"User-Agent":"Mozilla/5.0"}});if(!A.ok)throw new D("HTTP_ERROR",`holders failed: HTTP ${A.status}`);const F=await A.json(),B=Array.isArray(F?.result?.data)?F.result.data:[];if(B.length===0)throw new D("NO_DATA",`No shareholder data for ${b}`);const G=String(B[0].END_DATE||"").slice(0,10);return B.filter((q)=>String(q.END_DATE||"").slice(0,10)===G).slice(0,x).map((q)=>({rank:q.HOLDER_RANK,reportDate:G,name:q.HOLDER_NAME,holdNum:q.HOLD_NUM,floatRatio:q.FREE_HOLDNUM_RATIO,change:q.HOLD_NUM_CHANGE}))}});
1
+ import{cli as l,Strategy as E}from"@jackwener/opencli/registry";import{CliError as c}from"@jackwener/opencli/errors";function h(s){const e=String(s||"").trim().toUpperCase();if(/^\d{6}\.(SH|SZ|BJ)$/.test(e))return e;const a=e.match(/^(SH|SZ|BJ)(\d{6})$/);if(a)return`${a[2]}.${a[1]}`;if(/^\d{6}$/.test(e)){if(/^(60|68|90|113|900)/.test(e))return`${e}.SH`;if(/^(4|8|920|83|87)/.test(e))return`${e}.BJ`;return`${e}.SZ`}throw Error(`Unrecognized A-share symbol: ${s}`)}l({site:"eastmoney",name:"holders",access:"read",description:"十大流通股东(A股 F10 数据)",domain:"datacenter-web.eastmoney.com",strategy:E.PUBLIC,browser:!1,args:[{name:"symbol",required:!0,positional:!0,help:"A股代码(600519 / sh600519 等)"},{name:"limit",type:"int",default:10,help:"返回股东数(默认十大流通股东)"}],columns:["rank","reportDate","name","holdNum","floatRatio","change"],func:async(s)=>{let e;try{e=h(s.symbol)}catch(r){throw new c("INVALID_ARGUMENT",`${r instanceof Error?r.message:r}`)}const a=Math.max(1,Math.min(Number(s.limit)||10,50)),t=new URL("https://datacenter-web.eastmoney.com/api/data/v1/get");t.searchParams.set("sortColumns","END_DATE,HOLDER_RANK");t.searchParams.set("sortTypes","-1,1");t.searchParams.set("pageSize",String(Math.max(a,10)));t.searchParams.set("pageNumber","1");t.searchParams.set("reportName","RPT_F10_EH_FREEHOLDERS");t.searchParams.set("columns","SECUCODE,SECURITY_CODE,END_DATE,HOLDER_RANK,HOLDER_NAME,HOLD_NUM,FREE_HOLDNUM_RATIO,HOLD_NUM_CHANGE");t.searchParams.set("source","HSF10");t.searchParams.set("client","PC");t.searchParams.set("filter",`(SECUCODE="${e}")`);const o=await fetch(t,{headers:{"User-Agent":"Mozilla/5.0"}});if(!o.ok)throw new c("HTTP_ERROR",`holders failed: HTTP ${o.status}`);const m=await o.json(),n=Array.isArray(m?.result?.data)?m.result.data:[];if(n.length===0)throw new c("NO_DATA",`No shareholder data for ${e}`);const i=String(n[0].END_DATE||"").slice(0,10);return n.filter((r)=>String(r.END_DATE||"").slice(0,10)===i).slice(0,a).map((r)=>({rank:r.HOLDER_RANK,reportDate:i,name:r.HOLDER_NAME,holdNum:r.HOLD_NUM,floatRatio:r.FREE_HOLDNUM_RATIO,change:r.HOLD_NUM_CHANGE}))}});
@@ -1 +1 @@
1
- import{cli as h,Strategy as v}from"@jackwener/opencli/registry";import{CliError as M}from"@jackwener/opencli/errors";const B={main:[["1.000001","上证指数"],["0.399001","深证成指"],["0.399006","创业板指"],["1.000688","科创50"],["1.000300","沪深300"],["1.000905","中证500"]],hk:[["100.HSI","恒生指数"],["100.HSCEI","恒生国企"],["100.HSTECH","恒生科技"]],us:[["100.DJIA","道琼斯"],["100.SPX","标普500"],["100.NDX","纳斯达克100"],["100.IXIC","纳斯达克综指"]]},A="f2,f3,f4,f12,f13,f14,f15,f16,f17,f18";h({site:"eastmoney",name:"index-board",access:"read",description:"主要市场指数行情(A股 / 港股 / 美股)",domain:"push2.eastmoney.com",strategy:v.PUBLIC,browser:!1,args:[{name:"group",type:"string",default:"main",help:"指数分组:main (A股主要), hk (港股), us (美股), all"}],columns:["code","name","price","changePercent","change","open","high","low","prevClose"],func:async(W)=>{const H=String(W.group??"main").toLowerCase();let J;if(H==="all")J=[...B.main,...B.hk,...B.us];else if(B[H])J=B[H];else throw new M("INVALID_ARGUMENT",`Unknown group "${H}". Valid: main, hk, us, all`);const Y=J.map(([x])=>x).join(","),z=new URL("https://push2.eastmoney.com/api/qt/ulist.np/get");z.searchParams.set("secids",Y);z.searchParams.set("fltt","2");z.searchParams.set("fields",A);z.searchParams.set("ut","bd1d9ddb04089700cf9c27f6f7426281");const K=await fetch(z,{headers:{"User-Agent":"Mozilla/5.0",Accept:"application/json"}});if(!K.ok)throw new M("HTTP_ERROR",`eastmoney index-board failed: HTTP ${K.status}`);const Q=await K.json(),T=Array.isArray(Q?.data?.diff)?Q.data.diff:[];if(T.length===0)throw new M("NO_DATA","eastmoney returned no index data");const Z=new Map(T.map((x)=>[String(x.f12),x]));return J.map(([x,$])=>{const V=x.split(".")[1],q=Z.get(V);if(!q)return null;return{code:V,name:q.f14||$,price:q.f2,changePercent:q.f3,change:q.f4,open:q.f17,high:q.f15,low:q.f16,prevClose:q.f18}}).filter(Boolean)}});
1
+ import{cli as u,Strategy as g}from"@jackwener/opencli/registry";import{CliError as i}from"@jackwener/opencli/errors";const n={main:[["1.000001","上证指数"],["0.399001","深证成指"],["0.399006","创业板指"],["1.000688","科创50"],["1.000300","沪深300"],["1.000905","中证500"]],hk:[["100.HSI","恒生指数"],["100.HSCEI","恒生国企"],["100.HSTECH","恒生科技"]],us:[["100.DJIA","道琼斯"],["100.SPX","标普500"],["100.NDX","纳斯达克100"],["100.IXIC","纳斯达克综指"]]},w="f2,f3,f4,f12,f13,f14,f15,f16,f17,f18";u({site:"eastmoney",name:"index-board",access:"read",description:"主要市场指数行情(A股 / 港股 / 美股)",domain:"push2.eastmoney.com",strategy:g.PUBLIC,browser:!1,args:[{name:"group",type:"string",default:"main",help:"指数分组:main (A股主要), hk (港股), us (美股), all"}],columns:["code","name","price","changePercent","change","open","high","low","prevClose"],func:async(d)=>{const s=String(d.group??"main").toLowerCase();let r;if(s==="all")r=[...n.main,...n.hk,...n.us];else if(n[s])r=n[s];else throw new i("INVALID_ARGUMENT",`Unknown group "${s}". Valid: main, hk, us, all`);const m=r.map(([a])=>a).join(","),t=new URL("https://push2.eastmoney.com/api/qt/ulist.np/get");t.searchParams.set("secids",m);t.searchParams.set("fltt","2");t.searchParams.set("fields",w);t.searchParams.set("ut","bd1d9ddb04089700cf9c27f6f7426281");const o=await fetch(t,{headers:{"User-Agent":"Mozilla/5.0",Accept:"application/json"}});if(!o.ok)throw new i("HTTP_ERROR",`eastmoney index-board failed: HTTP ${o.status}`);const f=await o.json(),c=Array.isArray(f?.data?.diff)?f.data.diff:[];if(c.length===0)throw new i("NO_DATA","eastmoney returned no index data");const p=new Map(c.map((a)=>[String(a.f12),a]));return r.map(([a,h])=>{const l=a.split(".")[1],e=p.get(l);if(!e)return null;return{code:l,name:e.f14||h,price:e.f2,changePercent:e.f3,change:e.f4,open:e.f17,high:e.f15,low:e.f16,prevClose:e.f18}}).filter(Boolean)}});
@@ -1 +1 @@
1
- import{cli as R,Strategy as S}from"@jackwener/opencli/registry";import{CliError as a}from"@jackwener/opencli/errors";import{resolveSecid as T}from"./_secid.js";const c={"1m":1,"5m":5,"15m":15,"30m":30,"60m":60,minute:1,hour:60,day:101,daily:101,week:102,weekly:102,month:103,monthly:103},U={none:0,no:0,off:0,forward:1,front:1,pre:1,backward:2,back:2,post:2};R({site:"eastmoney",name:"kline",access:"read",description:"K线历史数据(分/日/周/月/前复权/后复权)",domain:"push2his.eastmoney.com",strategy:S.PUBLIC,browser:!1,args:[{name:"symbol",required:!0,positional:!0,help:"股票代码(A/HK/US 均可)"},{name:"period",type:"string",default:"day",help:"周期:1m/5m/15m/30m/60m/day/week/month"},{name:"adjust",type:"string",default:"forward",help:"复权:none / forward / backward"},{name:"limit",type:"int",default:30,help:"返回最近 N 根(末尾)"}],columns:["date","open","close","high","low","volume","turnover","amplitude","changePercent","change","turnoverRate"],func:async(t)=>{const d=T(t.symbol),o=String(t.period??"day").toLowerCase(),n=c[o];if(n==null)throw new a("INVALID_ARGUMENT",`Unknown period "${o}". Valid: ${Object.keys(c).join(", ")}`);const s=String(t.adjust??"forward").toLowerCase(),i=U[s];if(i==null)throw new a("INVALID_ARGUMENT",`Unknown adjust "${s}". Valid: none / forward / backward`);const u=Math.max(1,Math.min(Number(t.limit)||30,1000)),e=new URL("https://push2his.eastmoney.com/api/qt/stock/kline/get");e.searchParams.set("secid",d);e.searchParams.set("klt",String(n));e.searchParams.set("fqt",String(i));e.searchParams.set("beg","0");e.searchParams.set("end","20500101");e.searchParams.set("fields1","f1,f2,f3,f4,f5,f6");e.searchParams.set("fields2","f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61");e.searchParams.set("ut","b2884a393a59ad64002292a3e90d46a5");const r=await fetch(e,{headers:{"User-Agent":"Mozilla/5.0"}});if(!r.ok)throw new a("HTTP_ERROR",`eastmoney kline failed: HTTP ${r.status}`);const m=await r.json(),l=Array.isArray(m?.data?.klines)?m.data.klines:[];if(l.length===0)throw new a("NO_DATA",`No kline data for ${t.symbol}`);return l.slice(-u).map((f)=>{const[h,p,w,y,k,b,N,g,P,A,v]=f.split(",");return{date:h,open:Number(p),close:Number(w),high:Number(y),low:Number(k),volume:Number(b),turnover:Number(N),amplitude:Number(g),changePercent:Number(P),change:Number(A),turnoverRate:Number(v)}})}});
1
+ import{cli as R,Strategy as U}from"@jackwener/opencli/registry";import{CliError as a}from"@jackwener/opencli/errors";import{resolveSecid as S}from"./_secid.js";const c={"1m":1,"5m":5,"15m":15,"30m":30,"60m":60,minute:1,hour:60,day:101,daily:101,week:102,weekly:102,month:103,monthly:103},T={none:0,no:0,off:0,forward:1,front:1,pre:1,backward:2,back:2,post:2};R({site:"eastmoney",name:"kline",access:"read",description:"K线历史数据(分/日/周/月/前复权/后复权)",domain:"push2his.eastmoney.com",strategy:U.PUBLIC,browser:!1,args:[{name:"symbol",required:!0,positional:!0,help:"股票代码(A/HK/US 均可)"},{name:"period",type:"string",default:"day",help:"周期:1m/5m/15m/30m/60m/day/week/month"},{name:"adjust",type:"string",default:"forward",help:"复权:none / forward / backward"},{name:"limit",type:"int",default:30,help:"返回最近 N 根(末尾)"}],columns:["date","open","close","high","low","volume","turnover","amplitude","changePercent","change","turnoverRate"],func:async(t)=>{const d=S(t.symbol),n=String(t.period??"day").toLowerCase(),o=c[n];if(o==null)throw new a("INVALID_ARGUMENT",`Unknown period "${n}". Valid: ${Object.keys(c).join(", ")}`);const s=String(t.adjust??"forward").toLowerCase(),m=T[s];if(m==null)throw new a("INVALID_ARGUMENT",`Unknown adjust "${s}". Valid: none / forward / backward`);const u=Math.max(1,Math.min(Number(t.limit)||30,1000)),e=new URL("https://push2his.eastmoney.com/api/qt/stock/kline/get");e.searchParams.set("secid",d);e.searchParams.set("klt",String(o));e.searchParams.set("fqt",String(m));e.searchParams.set("beg","0");e.searchParams.set("end","20500101");e.searchParams.set("fields1","f1,f2,f3,f4,f5,f6");e.searchParams.set("fields2","f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61");e.searchParams.set("ut","b2884a393a59ad64002292a3e90d46a5");const r=await fetch(e,{headers:{"User-Agent":"Mozilla/5.0"}});if(!r.ok)throw new a("HTTP_ERROR",`eastmoney kline failed: HTTP ${r.status}`);const i=await r.json(),l=Array.isArray(i?.data?.klines)?i.data.klines:[];if(l.length===0)throw new a("NO_DATA",`No kline data for ${t.symbol}`);return l.slice(-u).map((f)=>{const[h,p,w,y,b,k,g,N,P,A,v]=f.split(",");return{date:h,open:Number(p),close:Number(w),high:Number(y),low:Number(b),volume:Number(k),turnover:Number(g),amplitude:Number(N),changePercent:Number(P),change:Number(A),turnoverRate:Number(v)}})}});