publishport-opencli 1.0.20 → 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 (1041) hide show
  1. package/clis/12306/me.js +2 -2
  2. package/clis/12306/orders.js +3 -3
  3. package/clis/12306/passengers.js +3 -3
  4. package/clis/12306/price.js +1 -1
  5. package/clis/12306/stations.js +1 -1
  6. package/clis/12306/train.js +1 -1
  7. package/clis/12306/trains.js +1 -1
  8. package/clis/12306/utils.js +1 -1
  9. package/clis/1688/download.js +1 -1
  10. package/clis/1688/item.js +4 -4
  11. package/clis/1688/search.js +4 -4
  12. package/clis/1688/store.js +4 -4
  13. package/clis/1point3acres/forum.js +1 -1
  14. package/clis/1point3acres/forums.js +1 -1
  15. package/clis/1point3acres/notifications.js +1 -1
  16. package/clis/1point3acres/search.js +1 -1
  17. package/clis/1point3acres/thread.js +2 -2
  18. package/clis/1point3acres/user.js +1 -1
  19. package/clis/1point3acres/utils.js +2 -2
  20. package/clis/36kr/article.js +2 -2
  21. package/clis/36kr/hot.js +2 -2
  22. package/clis/36kr/news.js +1 -1
  23. package/clis/36kr/search.js +2 -2
  24. package/clis/51job/company.js +2 -2
  25. package/clis/51job/detail.js +2 -2
  26. package/clis/51job/hot.js +1 -1
  27. package/clis/51job/search.js +1 -1
  28. package/clis/51job/utils.js +7 -7
  29. package/clis/_atlassian/shared.js +9 -9
  30. package/clis/_shared/article/auth.js +4 -4
  31. package/clis/_shared/article/douban-md2draft.js +4 -4
  32. package/clis/_shared/article/format.js +1 -1
  33. package/clis/_shared/article/images.js +7 -7
  34. package/clis/_shared/article/login.js +1 -1
  35. package/clis/_shared/article/publish.js +11 -11
  36. package/clis/_shared/common.js +1 -1
  37. package/clis/_shared/content-guard.js +1 -1
  38. package/clis/_shared/desktop-commands.js +1 -1
  39. package/clis/_shared/file-inject.js +12 -12
  40. package/clis/_shared/self-hosted-sites.js +2 -2
  41. package/clis/_shared/site-auth.js +1 -1
  42. package/clis/_shared/token-auth.js +2 -2
  43. package/clis/_shared/video-publish.js +9 -9
  44. package/clis/amazon/offer.js +3 -3
  45. package/clis/amazon/product.js +5 -5
  46. package/clis/amazon/shared.js +6 -6
  47. package/clis/antigravity/_actions.js +13 -13
  48. package/clis/antigravity/audit-extras.js +10 -10
  49. package/clis/antigravity/delete.js +1 -1
  50. package/clis/antigravity/model.js +6 -6
  51. package/clis/antigravity/new.js +2 -2
  52. package/clis/antigravity/read.js +2 -2
  53. package/clis/antigravity/rename.js +1 -1
  54. package/clis/antigravity/send.js +3 -3
  55. package/clis/antigravity/serve.js +17 -17
  56. package/clis/antigravity/storage.js +6 -6
  57. package/clis/antigravity/watch.js +2 -2
  58. package/clis/apple-podcasts/episodes.js +1 -1
  59. package/clis/apple-podcasts/top.js +1 -1
  60. package/clis/apple-podcasts/utils.js +1 -1
  61. package/clis/archive/item.js +1 -1
  62. package/clis/archive/search.js +1 -1
  63. package/clis/archive/snapshots.js +1 -1
  64. package/clis/archive/wayback.js +1 -1
  65. package/clis/arxiv/author.js +1 -1
  66. package/clis/arxiv/utils.js +1 -1
  67. package/clis/autohome/brand.js +1 -1
  68. package/clis/autohome/score.js +1 -1
  69. package/clis/autohome/utils.js +1 -1
  70. package/clis/baijiahao/article.js +1 -1
  71. package/clis/baijiahao/lists.js +1 -1
  72. package/clis/baijiahao/login.js +1 -1
  73. package/clis/baijiahao/publish.js +9 -9
  74. package/clis/baijiahao/stats.js +1 -1
  75. package/clis/baijiahao/whoami.js +1 -1
  76. package/clis/band/bands.js +2 -2
  77. package/clis/band/mentions.js +2 -2
  78. package/clis/band/post.js +4 -4
  79. package/clis/band/posts.js +3 -3
  80. package/clis/barchart/flow.js +3 -3
  81. package/clis/barchart/greeks.js +2 -2
  82. package/clis/barchart/quote.js +3 -3
  83. package/clis/bbc/news.js +1 -1
  84. package/clis/bbc/topic.js +1 -1
  85. package/clis/bbc/utils.js +1 -1
  86. package/clis/bilibili/article.js +1 -1
  87. package/clis/bilibili/categories.js +1 -1
  88. package/clis/bilibili/coin.js +1 -1
  89. package/clis/bilibili/comment-del.js +1 -1
  90. package/clis/bilibili/comment-like.js +1 -1
  91. package/clis/bilibili/comment.js +1 -1
  92. package/clis/bilibili/comments.js +1 -1
  93. package/clis/bilibili/dm-list.js +1 -1
  94. package/clis/bilibili/dm-read.js +1 -1
  95. package/clis/bilibili/dm-send.js +1 -1
  96. package/clis/bilibili/download.js +2 -2
  97. package/clis/bilibili/drafts.js +1 -1
  98. package/clis/bilibili/dynamic-post.js +3 -3
  99. package/clis/bilibili/favorite-add.js +1 -1
  100. package/clis/bilibili/favorite.js +1 -1
  101. package/clis/bilibili/feed.js +2 -2
  102. package/clis/bilibili/follow.js +1 -1
  103. package/clis/bilibili/following.js +1 -1
  104. package/clis/bilibili/like.js +1 -1
  105. package/clis/bilibili/partitions.js +1 -1
  106. package/clis/bilibili/stats.js +1 -1
  107. package/clis/bilibili/subtitle.js +3 -3
  108. package/clis/bilibili/summary.js +1 -1
  109. package/clis/bilibili/topics.js +1 -1
  110. package/clis/bilibili/unfollow.js +1 -1
  111. package/clis/bilibili/upload.js +1 -1
  112. package/clis/bilibili/utils.js +10 -10
  113. package/clis/bilibili/video-drafts.js +1 -1
  114. package/clis/bilibili/video.js +1 -1
  115. package/clis/bloomberg/businessweek.js +4 -4
  116. package/clis/bloomberg/news.js +2 -2
  117. package/clis/bloomberg/utils.js +13 -13
  118. package/clis/bluesky/post.js +1 -1
  119. package/clis/bluesky/shared.js +11 -11
  120. package/clis/bluesky/whoami.js +1 -1
  121. package/clis/booking/search.js +2 -2
  122. package/clis/boss/accept.js +1 -1
  123. package/clis/boss/applied.js +1 -1
  124. package/clis/boss/auth.js +1 -1
  125. package/clis/boss/batchgreet.js +1 -1
  126. package/clis/boss/bossinfo.js +1 -1
  127. package/clis/boss/chatlist.js +1 -1
  128. package/clis/boss/chatmsg.js +1 -1
  129. package/clis/boss/cities.js +1 -1
  130. package/clis/boss/detail.js +1 -1
  131. package/clis/boss/exchange.js +1 -1
  132. package/clis/boss/greet.js +1 -1
  133. package/clis/boss/interviews.js +1 -1
  134. package/clis/boss/invite.js +1 -1
  135. package/clis/boss/joblist.js +1 -1
  136. package/clis/boss/mark.js +1 -1
  137. package/clis/boss/me.js +2 -2
  138. package/clis/boss/recommend.js +1 -1
  139. package/clis/boss/resumedelete.js +1 -1
  140. package/clis/boss/resumelist.js +1 -1
  141. package/clis/boss/resumeupload.js +11 -11
  142. package/clis/boss/search.js +1 -1
  143. package/clis/boss/send.js +1 -1
  144. package/clis/boss/sendresume.js +1 -1
  145. package/clis/boss/stats.js +1 -1
  146. package/clis/boss/unread.js +1 -1
  147. package/clis/boss/utils.js +13 -13
  148. package/clis/chaoxing/assignments.js +1 -1
  149. package/clis/chaoxing/exams.js +1 -1
  150. package/clis/chaoxing/utils.js +9 -9
  151. package/clis/chatgpt/ask.js +1 -1
  152. package/clis/chatgpt/auth.js +2 -2
  153. package/clis/chatgpt/detail.js +1 -1
  154. package/clis/chatgpt/image.js +1 -1
  155. package/clis/chatgpt/read.js +1 -1
  156. package/clis/chatgpt/send.js +1 -1
  157. package/clis/chatgpt/utils.js +59 -59
  158. package/clis/chatgpt-app/ask.js +1 -1
  159. package/clis/chatgpt-app/send.js +1 -1
  160. package/clis/chatwise/model.js +6 -6
  161. package/clis/chess/analyze.js +1 -1
  162. package/clis/chess/game.js +1 -1
  163. package/clis/chess/games.js +1 -1
  164. package/clis/chess/stats.js +1 -1
  165. package/clis/chess/utils.js +1 -1
  166. package/clis/claude/ask.js +2 -2
  167. package/clis/claude/detail.js +1 -1
  168. package/clis/claude/new.js +1 -1
  169. package/clis/claude/read.js +1 -1
  170. package/clis/claude/send.js +1 -1
  171. package/clis/claude/utils.js +23 -23
  172. package/clis/cnblogs/article.js +1 -1
  173. package/clis/cnblogs/login.js +1 -1
  174. package/clis/cnblogs/stats.js +7 -7
  175. package/clis/cnblogs/whoami.js +1 -1
  176. package/clis/codex/_actions.js +3 -3
  177. package/clis/codex/archive.js +1 -1
  178. package/clis/codex/ask.js +6 -6
  179. package/clis/codex/model.js +8 -8
  180. package/clis/codex/pin.js +1 -1
  181. package/clis/codex/rename.js +4 -4
  182. package/clis/codex/send.js +3 -3
  183. package/clis/codex/sidebar.js +1 -1
  184. package/clis/coingecko/categories.js +1 -1
  185. package/clis/coingecko/coin.js +1 -1
  186. package/clis/coingecko/derivatives.js +1 -1
  187. package/clis/coingecko/exchanges.js +1 -1
  188. package/clis/coingecko/global.js +1 -1
  189. package/clis/coingecko/trending.js +1 -1
  190. package/clis/confluence/search.js +1 -1
  191. package/clis/coupang/product.js +3 -3
  192. package/clis/coupang/utils.js +1 -1
  193. package/clis/crates/crate.js +1 -1
  194. package/clis/crates/search.js +1 -1
  195. package/clis/crates/utils.js +1 -1
  196. package/clis/csdn/article.js +13 -13
  197. package/clis/csdn/columns.js +1 -1
  198. package/clis/csdn/login.js +1 -1
  199. package/clis/csdn/stats.js +4 -4
  200. package/clis/csdn/whoami.js +1 -1
  201. package/clis/cto51/article.js +1 -1
  202. package/clis/cto51/whoami.js +1 -1
  203. package/clis/ctrip/flight.js +2 -2
  204. package/clis/ctrip/hotel-search.js +3 -3
  205. package/clis/ctrip/hotel-suggest.js +1 -1
  206. package/clis/ctrip/search.js +1 -1
  207. package/clis/ctrip/utils.js +6 -6
  208. package/clis/cursor/ask.js +5 -5
  209. package/clis/cursor/composer.js +2 -2
  210. package/clis/cursor/model.js +4 -4
  211. package/clis/cursor/send.js +2 -2
  212. package/clis/dblp/author.js +1 -1
  213. package/clis/dblp/paper.js +1 -1
  214. package/clis/dblp/search.js +1 -1
  215. package/clis/dblp/utils.js +1 -1
  216. package/clis/dblp/venue.js +1 -1
  217. package/clis/deepseek/ask.js +1 -1
  218. package/clis/deepseek/auth.js +2 -2
  219. package/clis/deepseek/detail.js +1 -1
  220. package/clis/deepseek/new.js +1 -1
  221. package/clis/deepseek/read.js +1 -1
  222. package/clis/deepseek/send.js +7 -7
  223. package/clis/deepseek/utils.js +25 -25
  224. package/clis/defillama/protocol.js +1 -1
  225. package/clis/defillama/protocols.js +1 -1
  226. package/clis/defillama/utils.js +1 -1
  227. package/clis/devto/auth.js +2 -2
  228. package/clis/devto/latest.js +1 -1
  229. package/clis/devto/publish.js +5 -5
  230. package/clis/devto/read.js +2 -2
  231. package/clis/devto/stats.js +3 -3
  232. package/clis/dianping/auth.js +2 -2
  233. package/clis/dianping/cityResolver.js +2 -2
  234. package/clis/dianping/search.js +1 -1
  235. package/clis/dianping/shop.js +1 -1
  236. package/clis/dianping/utils.js +1 -1
  237. package/clis/discord-app/delete.js +3 -3
  238. package/clis/discord-app/read.js +1 -1
  239. package/clis/discord-app/thread-read.js +1 -1
  240. package/clis/discord-web/auth.js +2 -2
  241. package/clis/discord-web/send.js +5 -5
  242. package/clis/dockerhub/image.js +1 -1
  243. package/clis/dockerhub/search.js +1 -1
  244. package/clis/dockerhub/utils.js +1 -1
  245. package/clis/dongchedi/koubei.js +1 -1
  246. package/clis/dongchedi/models.js +1 -1
  247. package/clis/dongchedi/score.js +1 -1
  248. package/clis/dongchedi/search.js +1 -1
  249. package/clis/dongchedi/series.js +1 -1
  250. package/clis/dongchedi/specs.js +1 -1
  251. package/clis/dongchedi/utils.js +1 -1
  252. package/clis/douban/article.js +3 -3
  253. package/clis/douban/auth.js +2 -2
  254. package/clis/douban/download.js +1 -1
  255. package/clis/douban/utils.js +23 -23
  256. package/clis/doubao/auth.js +3 -3
  257. package/clis/doubao/utils.js +39 -39
  258. package/clis/doubao-app/ask.js +1 -1
  259. package/clis/doubao-app/utils.js +4 -4
  260. package/clis/douyin/_shared/browser-fetch.js +7 -7
  261. package/clis/douyin/_shared/draft-cache.js +1 -1
  262. package/clis/douyin/_shared/imagex-upload.js +1 -1
  263. package/clis/douyin/_shared/sts2.js +1 -1
  264. package/clis/douyin/_shared/text-extra.js +1 -1
  265. package/clis/douyin/_shared/tos-upload.js +4 -4
  266. package/clis/douyin/_shared/transcode.js +1 -1
  267. package/clis/douyin/_shared/vod-upload.js +4 -4
  268. package/clis/douyin/draft.js +18 -18
  269. package/clis/douyin/drafts.js +1 -1
  270. package/clis/douyin/publish-image.js +12 -12
  271. package/clis/douyin/publish.js +9 -9
  272. package/clis/douyin/search.js +3 -3
  273. package/clis/douyin/videos.js +1 -1
  274. package/clis/eastmoney/_secid.js +1 -1
  275. package/clis/eastmoney/announcement.js +1 -1
  276. package/clis/eastmoney/article.js +1 -1
  277. package/clis/eastmoney/convertible.js +1 -1
  278. package/clis/eastmoney/etf.js +1 -1
  279. package/clis/eastmoney/holders.js +1 -1
  280. package/clis/eastmoney/index-board.js +1 -1
  281. package/clis/eastmoney/kline.js +1 -1
  282. package/clis/eastmoney/kuaixun.js +1 -1
  283. package/clis/eastmoney/longhu.js +1 -1
  284. package/clis/eastmoney/money-flow.js +1 -1
  285. package/clis/eastmoney/northbound.js +1 -1
  286. package/clis/eastmoney/quote.js +1 -1
  287. package/clis/eastmoney/rank.js +1 -1
  288. package/clis/eastmoney/sectors.js +1 -1
  289. package/clis/endoflife/product.js +1 -1
  290. package/clis/endoflife/utils.js +1 -1
  291. package/clis/facebook/comment.js +8 -8
  292. package/clis/facebook/feed.js +4 -4
  293. package/clis/facebook/like.js +5 -5
  294. package/clis/facebook/notifications.js +3 -3
  295. package/clis/facebook/post.js +11 -11
  296. package/clis/facebook/search.js +3 -3
  297. package/clis/flathub/app.js +1 -1
  298. package/clis/flathub/search.js +1 -1
  299. package/clis/flathub/utils.js +1 -1
  300. package/clis/flomo/memos.js +1 -1
  301. package/clis/gemini/deep-research-result.js +4 -4
  302. package/clis/gemini/deep-research.js +1 -1
  303. package/clis/gemini/detail.js +1 -1
  304. package/clis/gemini/history.js +1 -1
  305. package/clis/gemini/image.js +2 -2
  306. package/clis/gemini/status.js +1 -1
  307. package/clis/gemini/utils.js +43 -43
  308. package/clis/geogebra/hexagon.js +1 -1
  309. package/clis/geogebra/info.js +3 -3
  310. package/clis/geogebra/triangle.js +1 -1
  311. package/clis/geogebra/utils.js +11 -11
  312. package/clis/ghost/login.js +1 -1
  313. package/clis/ghost/shared.js +2 -2
  314. package/clis/gitee/auth.js +2 -2
  315. package/clis/github-trending/repos.js +1 -1
  316. package/clis/google/news.js +1 -1
  317. package/clis/google/search.js +2 -2
  318. package/clis/google/suggest.js +1 -1
  319. package/clis/google/trends.js +1 -1
  320. package/clis/google/utils.js +1 -1
  321. package/clis/goproxy/module.js +1 -1
  322. package/clis/goproxy/utils.js +1 -1
  323. package/clis/goproxy/versions.js +1 -1
  324. package/clis/gov-policy/recent.js +2 -2
  325. package/clis/gov-policy/search.js +2 -2
  326. package/clis/grok/ask.js +1 -1
  327. package/clis/grok/detail.js +1 -1
  328. package/clis/grok/image.js +8 -8
  329. package/clis/grok/pin.js +1 -1
  330. package/clis/grok/send.js +1 -1
  331. package/clis/grok/status.js +1 -1
  332. package/clis/grok/utils.js +21 -21
  333. package/clis/guazi/browse.js +1 -1
  334. package/clis/guazi/car.js +1 -1
  335. package/clis/guazi/utils.js +1 -1
  336. package/clis/hackernews/auth.js +2 -2
  337. package/clis/hackernews/comment.js +8 -8
  338. package/clis/hackernews/read.js +7 -7
  339. package/clis/hackernews/submit.js +7 -7
  340. package/clis/hashnode/auth.js +3 -3
  341. package/clis/hashnode/publish.js +14 -14
  342. package/clis/hf/auth.js +2 -2
  343. package/clis/hf/models.js +1 -1
  344. package/clis/hf/paper.js +1 -1
  345. package/clis/hf/spaces.js +1 -1
  346. package/clis/hf/top.js +1 -1
  347. package/clis/homebrew/cask.js +1 -1
  348. package/clis/homebrew/formula.js +1 -1
  349. package/clis/homebrew/popular.js +1 -1
  350. package/clis/homebrew/utils.js +1 -1
  351. package/clis/huodongxing/events.js +1 -1
  352. package/clis/hupu/detail.js +4 -4
  353. package/clis/hupu/hot.js +3 -3
  354. package/clis/hupu/reply.js +1 -1
  355. package/clis/hupu/search.js +1 -1
  356. package/clis/hupu/unlike.js +1 -1
  357. package/clis/hupu/utils.js +10 -10
  358. package/clis/imdb/person.js +2 -2
  359. package/clis/imdb/reviews.js +3 -3
  360. package/clis/imdb/search.js +2 -2
  361. package/clis/imdb/title.js +1 -1
  362. package/clis/imdb/top.js +1 -1
  363. package/clis/imdb/trending.js +1 -1
  364. package/clis/imdb/utils.js +13 -13
  365. package/clis/imooc/article.js +6 -6
  366. package/clis/imooc/login.js +1 -1
  367. package/clis/imooc/whoami.js +1 -1
  368. package/clis/indeed/job.js +2 -2
  369. package/clis/indeed/search.js +2 -2
  370. package/clis/indeed/utils.js +1 -1
  371. package/clis/infoq/article.js +2 -2
  372. package/clis/infoq/login.js +1 -1
  373. package/clis/infoq/whoami.js +1 -1
  374. package/clis/instagram/_shared/private-publish.js +4 -4
  375. package/clis/instagram/_shared/protocol-capture.js +9 -9
  376. package/clis/instagram/detail.js +3 -3
  377. package/clis/instagram/post.js +25 -25
  378. package/clis/instagram/reel.js +18 -18
  379. package/clis/instagram/story.js +4 -4
  380. package/clis/instagram/user.js +2 -2
  381. package/clis/jd/item.js +65 -65
  382. package/clis/jianshu/article.js +1 -1
  383. package/clis/jianshu/login.js +1 -1
  384. package/clis/jianshu/notebooks.js +1 -1
  385. package/clis/jianshu/whoami.js +1 -1
  386. package/clis/jianyu/search.js +6 -6
  387. package/clis/jianyu/shared/procurement-contract.js +1 -1
  388. package/clis/jike/api.js +6 -6
  389. package/clis/jike/auth.js +3 -3
  390. package/clis/jike/comment.js +1 -1
  391. package/clis/jike/create.js +6 -6
  392. package/clis/jike/feed.js +3 -3
  393. package/clis/jike/like.js +1 -1
  394. package/clis/jike/notifications.js +3 -3
  395. package/clis/jike/repost.js +13 -13
  396. package/clis/jike/search.js +3 -3
  397. package/clis/jimeng/auth.js +2 -2
  398. package/clis/jimeng/generate.js +10 -10
  399. package/clis/jira/shared.js +1 -1
  400. package/clis/juejin/article.js +4 -4
  401. package/clis/juejin/categories.js +1 -1
  402. package/clis/juejin/hot.js +1 -1
  403. package/clis/juejin/login.js +1 -1
  404. package/clis/juejin/recommend.js +1 -1
  405. package/clis/juejin/stats.js +3 -3
  406. package/clis/juejin/tags.js +1 -1
  407. package/clis/juejin/utils.js +1 -1
  408. package/clis/juejin/whoami.js +1 -1
  409. package/clis/ke/utils.js +4 -4
  410. package/clis/kimi/_utils.js +7 -7
  411. package/clis/kimi/audit-extras.js +14 -14
  412. package/clis/kimi/auth.js +3 -3
  413. package/clis/kimi/chat.js +15 -15
  414. package/clis/kimi/storage.js +5 -5
  415. package/clis/kimi/ui.js +13 -13
  416. package/clis/kimi/usage.js +3 -3
  417. package/clis/kuaishou/auth.js +1 -1
  418. package/clis/kuaishou/publish.js +6 -6
  419. package/clis/lesswrong/_helpers.js +5 -5
  420. package/clis/lesswrong/comments.js +5 -5
  421. package/clis/lichess/top.js +1 -1
  422. package/clis/lichess/user.js +1 -1
  423. package/clis/lichess/utils.js +1 -1
  424. package/clis/linkedin/comment.js +1 -1
  425. package/clis/linkedin/connect.js +11 -11
  426. package/clis/linkedin/create.js +5 -5
  427. package/clis/linkedin/follow.js +1 -1
  428. package/clis/linkedin/inbox.js +1 -1
  429. package/clis/linkedin/job-detail.js +3 -3
  430. package/clis/linkedin/like.js +1 -1
  431. package/clis/linkedin/notifications.js +1 -1
  432. package/clis/linkedin/people-search.js +1 -1
  433. package/clis/linkedin/post-comments.js +1 -1
  434. package/clis/linkedin/post-detail.js +1 -1
  435. package/clis/linkedin/profile-analytics.js +1 -1
  436. package/clis/linkedin/profile-api.js +13 -13
  437. package/clis/linkedin/profile-experience.js +1 -1
  438. package/clis/linkedin/profile-projects.js +1 -1
  439. package/clis/linkedin/profile-read.js +3 -3
  440. package/clis/linkedin/reply.js +1 -1
  441. package/clis/linkedin/repost.js +1 -1
  442. package/clis/linkedin/safe-send.js +8 -8
  443. package/clis/linkedin/salesnav-inbox.js +5 -5
  444. package/clis/linkedin/salesnav-message.js +3 -3
  445. package/clis/linkedin/salesnav-search.js +4 -4
  446. package/clis/linkedin/salesnav-thread.js +1 -1
  447. package/clis/linkedin/search-api.js +3 -3
  448. package/clis/linkedin/search.js +8 -8
  449. package/clis/linkedin/social-api.js +31 -31
  450. package/clis/linkedin/timeline.js +3 -3
  451. package/clis/linkedin-learning/search.js +2 -2
  452. package/clis/linkedin-learning/trending.js +2 -2
  453. package/clis/linux-do/feed.js +4 -4
  454. package/clis/linux-do/topic-content.js +8 -8
  455. package/clis/lobsters/domain.js +1 -1
  456. package/clis/lobsters/read.js +7 -7
  457. package/clis/maimai/auth.js +2 -2
  458. package/clis/maimai/search-talents.js +4 -4
  459. package/clis/manus/_utils.js +1 -1
  460. package/clis/mastodon/login.js +1 -1
  461. package/clis/mastodon/post.js +1 -1
  462. package/clis/mastodon/shared.js +12 -12
  463. package/clis/mastodon/whoami.js +1 -1
  464. package/clis/maven/artifact.js +1 -1
  465. package/clis/maven/search.js +1 -1
  466. package/clis/maven/utils.js +1 -1
  467. package/clis/mdn/search.js +1 -1
  468. package/clis/medium/article.js +5 -5
  469. package/clis/medium/login.js +1 -1
  470. package/clis/medium/stats.js +3 -3
  471. package/clis/medium/tag.js +1 -1
  472. package/clis/medium/whoami.js +1 -1
  473. package/clis/mubu/notes.js +1 -1
  474. package/clis/mubu/utils.js +15 -15
  475. package/clis/note/auth.js +2 -2
  476. package/clis/note/note-utils.js +2 -2
  477. package/clis/note/publish.js +8 -8
  478. package/clis/notebooklm/add-source.js +8 -8
  479. package/clis/notebooklm/create.js +1 -1
  480. package/clis/notebooklm/generate-slides.js +1 -1
  481. package/clis/notebooklm/notes-get.js +1 -1
  482. package/clis/notebooklm/rpc.js +8 -8
  483. package/clis/notebooklm/source-fulltext.js +1 -1
  484. package/clis/notebooklm/utils.js +10 -10
  485. package/clis/nowcoder/auth.js +2 -2
  486. package/clis/nowcoder/comment.js +1 -1
  487. package/clis/nowcoder/comments.js +1 -1
  488. package/clis/nowcoder/dm-list.js +1 -1
  489. package/clis/nowcoder/dm-read.js +1 -1
  490. package/clis/nowcoder/dm-send.js +1 -1
  491. package/clis/nowcoder/drafts.js +1 -1
  492. package/clis/nowcoder/inbox.js +1 -1
  493. package/clis/nowcoder/like.js +1 -1
  494. package/clis/nowcoder/my.js +1 -1
  495. package/clis/nowcoder/post.js +1 -1
  496. package/clis/nowcoder/utils.js +13 -13
  497. package/clis/npm/downloads.js +1 -1
  498. package/clis/npm/package.js +1 -1
  499. package/clis/npm/search.js +1 -1
  500. package/clis/npm/utils.js +1 -1
  501. package/clis/nuget/package.js +1 -1
  502. package/clis/nuget/search.js +1 -1
  503. package/clis/nuget/utils.js +1 -1
  504. package/clis/nvd/cve.js +1 -1
  505. package/clis/oeis/search.js +1 -1
  506. package/clis/oeis/sequence.js +1 -1
  507. package/clis/oeis/utils.js +1 -1
  508. package/clis/ones/common.js +6 -6
  509. package/clis/ones/enrich-tasks.js +1 -1
  510. package/clis/ones/my-tasks.js +1 -1
  511. package/clis/ones/resolve-labels.js +1 -1
  512. package/clis/ones/task-helpers.js +1 -1
  513. package/clis/ones/task.js +1 -1
  514. package/clis/ones/worklog.js +7 -7
  515. package/clis/openalex/search.js +1 -1
  516. package/clis/openalex/utils.js +1 -1
  517. package/clis/openalex/work.js +1 -1
  518. package/clis/openfda/drug-label.js +1 -1
  519. package/clis/openfda/food-recall.js +1 -1
  520. package/clis/openfda/utils.js +1 -1
  521. package/clis/openreview/author.js +1 -1
  522. package/clis/openreview/paper.js +1 -1
  523. package/clis/openreview/reviews.js +3 -3
  524. package/clis/openreview/search.js +1 -1
  525. package/clis/openreview/utils.js +1 -1
  526. package/clis/openreview/venue.js +1 -1
  527. package/clis/oschina/article.js +1 -1
  528. package/clis/oschina/catalogs.js +1 -1
  529. package/clis/oschina/login.js +1 -1
  530. package/clis/oschina/stats.js +6 -6
  531. package/clis/oschina/whoami.js +1 -1
  532. package/clis/osv/query.js +1 -1
  533. package/clis/osv/utils.js +1 -1
  534. package/clis/osv/vulnerability.js +1 -1
  535. package/clis/packagist/package.js +1 -1
  536. package/clis/packagist/search.js +1 -1
  537. package/clis/packagist/utils.js +1 -1
  538. package/clis/pinterest/api.js +1 -1
  539. package/clis/pinterest/auth.js +1 -1
  540. package/clis/pinterest/boards.js +1 -1
  541. package/clis/pinterest/client.js +6 -6
  542. package/clis/pinterest/publish.js +5 -5
  543. package/clis/pixiv/auth.js +2 -2
  544. package/clis/pixiv/download.js +1 -1
  545. package/clis/pixiv/illusts.js +1 -1
  546. package/clis/pixiv/search.js +1 -1
  547. package/clis/pixiv/utils.js +3 -3
  548. package/clis/powerchina/auth.js +2 -2
  549. package/clis/powerchina/search.js +1 -1
  550. package/clis/producthunt/browse.js +2 -2
  551. package/clis/producthunt/hot.js +2 -2
  552. package/clis/producthunt/posts.js +1 -1
  553. package/clis/producthunt/today.js +1 -1
  554. package/clis/producthunt/utils.js +1 -1
  555. package/clis/pypi/downloads.js +1 -1
  556. package/clis/pypi/package.js +1 -1
  557. package/clis/pypi/utils.js +1 -1
  558. package/clis/qiita/auth.js +1 -1
  559. package/clis/qiita/gql.js +6 -6
  560. package/clis/qiita/publish.js +4 -4
  561. package/clis/qiita/stats.js +4 -4
  562. package/clis/qoder/_utils.js +16 -16
  563. package/clis/qoder/composer.js +1 -1
  564. package/clis/qoder/quest.js +1 -1
  565. package/clis/qoder/ui.js +14 -14
  566. package/clis/quark/auth.js +2 -2
  567. package/clis/quark/utils.js +2 -2
  568. package/clis/quora/answer-comments.js +3 -3
  569. package/clis/quora/create-answer.js +4 -4
  570. package/clis/quora/create-question.js +3 -3
  571. package/clis/quora/shared.js +17 -17
  572. package/clis/quora/whoami.js +1 -1
  573. package/clis/qwen/ask.js +1 -1
  574. package/clis/qwen/auth.js +3 -3
  575. package/clis/qwen/detail.js +1 -1
  576. package/clis/qwen/image.js +5 -5
  577. package/clis/qwen/status.js +1 -1
  578. package/clis/qwen/utils.js +16 -16
  579. package/clis/reddit/home.js +3 -3
  580. package/clis/reddit/read.js +10 -10
  581. package/clis/reddit/reply.js +4 -4
  582. package/clis/reddit/submit.js +11 -11
  583. package/clis/reddit/subreddit-info.js +3 -3
  584. package/clis/reddit/subscribed.js +4 -4
  585. package/clis/reddit/whoami.js +2 -2
  586. package/clis/rednote/comments.js +1 -1
  587. package/clis/rednote/download.js +1 -1
  588. package/clis/rednote/feed.js +1 -1
  589. package/clis/rednote/note.js +1 -1
  590. package/clis/rednote/notifications.js +2 -2
  591. package/clis/rednote/search.js +2 -2
  592. package/clis/rest-countries/country.js +1 -1
  593. package/clis/rest-countries/region.js +1 -1
  594. package/clis/rest-countries/utils.js +1 -1
  595. package/clis/reuters/article-detail.js +1 -1
  596. package/clis/reuters/auth.js +3 -3
  597. package/clis/reuters/search.js +1 -1
  598. package/clis/reuters/utils.js +4 -4
  599. package/clis/rfc/rfc.js +1 -1
  600. package/clis/rfc/utils.js +1 -1
  601. package/clis/rubygems/gem.js +1 -1
  602. package/clis/rubygems/search.js +1 -1
  603. package/clis/rubygems/utils.js +1 -1
  604. package/clis/segmentfault/article.js +3 -3
  605. package/clis/segmentfault/channels.js +1 -1
  606. package/clis/segmentfault/login.js +1 -1
  607. package/clis/segmentfault/stats.js +4 -4
  608. package/clis/segmentfault/tags.js +1 -1
  609. package/clis/segmentfault/whoami.js +1 -1
  610. package/clis/semanticscholar/citations.js +1 -1
  611. package/clis/semanticscholar/paper.js +1 -1
  612. package/clis/semanticscholar/recommendations.js +1 -1
  613. package/clis/semanticscholar/search.js +1 -1
  614. package/clis/semanticscholar/utils.js +1 -1
  615. package/clis/sinafinance/news.js +1 -1
  616. package/clis/sinafinance/stock-rank.js +1 -1
  617. package/clis/sinafinance/stock.js +1 -1
  618. package/clis/slock/attachment-download.js +1 -1
  619. package/clis/slock/attachment-upload.js +7 -7
  620. package/clis/slock/attachment-url.js +1 -1
  621. package/clis/slock/auth-verify.js +1 -1
  622. package/clis/slock/bookmark-add.js +1 -1
  623. package/clis/slock/bookmark-remove.js +1 -1
  624. package/clis/slock/channel-action.js +1 -1
  625. package/clis/slock/channel-create.js +1 -1
  626. package/clis/slock/channel-files.js +1 -1
  627. package/clis/slock/channel-list.js +1 -1
  628. package/clis/slock/channel-mark.js +1 -1
  629. package/clis/slock/channel-members.js +1 -1
  630. package/clis/slock/channel-unarchive.js +1 -1
  631. package/clis/slock/dm-list.js +1 -1
  632. package/clis/slock/errors.js +1 -1
  633. package/clis/slock/in-page.js +28 -28
  634. package/clis/slock/inbox-done.js +5 -5
  635. package/clis/slock/inbox.js +1 -1
  636. package/clis/slock/message-read.js +22 -22
  637. package/clis/slock/message-search.js +10 -10
  638. package/clis/slock/message-send.js +25 -25
  639. package/clis/slock/reaction-add.js +1 -1
  640. package/clis/slock/reaction-remove.js +1 -1
  641. package/clis/slock/resolve.js +1 -1
  642. package/clis/slock/server-list.js +2 -2
  643. package/clis/slock/task-claim.js +4 -4
  644. package/clis/slock/task-convert.js +13 -13
  645. package/clis/slock/task-create.js +1 -1
  646. package/clis/slock/task-delete.js +5 -5
  647. package/clis/slock/task-get.js +5 -5
  648. package/clis/slock/task-list-server.js +4 -4
  649. package/clis/slock/task-list.js +5 -5
  650. package/clis/slock/task-status.js +3 -3
  651. package/clis/slock/task-unclaim.js +3 -3
  652. package/clis/slock/thread-follow.js +1 -1
  653. package/clis/slock/thread-state.js +1 -1
  654. package/clis/slock/unread-summary.js +5 -5
  655. package/clis/slock/whoami.js +1 -1
  656. package/clis/smzdm/search.js +3 -3
  657. package/clis/sohu/article.js +1 -1
  658. package/clis/sohu/attributes.js +1 -1
  659. package/clis/sohu/categories.js +1 -1
  660. package/clis/sohu/channels.js +1 -1
  661. package/clis/sohu/columns.js +1 -1
  662. package/clis/sohu/login.js +1 -1
  663. package/clis/sohu/stats.js +3 -3
  664. package/clis/sohu/topics.js +1 -1
  665. package/clis/sohu/whoami.js +1 -1
  666. package/clis/spotify/spotify.js +1 -1
  667. package/clis/stackoverflow/read.js +6 -6
  668. package/clis/stackoverflow/related.js +1 -1
  669. package/clis/stackoverflow/tag.js +1 -1
  670. package/clis/stackoverflow/user.js +1 -1
  671. package/clis/stackoverflow/utils.js +1 -1
  672. package/clis/steam/app.js +1 -1
  673. package/clis/steam/search.js +1 -1
  674. package/clis/steam/utils.js +1 -1
  675. package/clis/substack/auth.js +2 -2
  676. package/clis/substack/post-utils.js +2 -2
  677. package/clis/substack/publish.js +5 -5
  678. package/clis/suno/auth.js +2 -2
  679. package/clis/suno/download.js +5 -5
  680. package/clis/suno/generate.js +3 -3
  681. package/clis/suno/list.js +1 -1
  682. package/clis/suno/status.js +1 -1
  683. package/clis/suno/utils.js +29 -29
  684. package/clis/telegram/send.js +7 -7
  685. package/clis/telegram/shared.js +2 -2
  686. package/clis/telegram/whoami.js +1 -1
  687. package/clis/test-utils.js +1 -1
  688. package/clis/threads/post.js +23 -23
  689. package/clis/threads/shared.js +3 -3
  690. package/clis/threads/whoami.js +1 -1
  691. package/clis/tieba/hot.js +3 -3
  692. package/clis/tieba/posts.js +1 -1
  693. package/clis/tieba/read.js +2 -2
  694. package/clis/tieba/search.js +3 -3
  695. package/clis/tieba/utils.js +1 -1
  696. package/clis/tiktok/comment.js +2 -2
  697. package/clis/tiktok/creator-videos.js +3 -3
  698. package/clis/tiktok/explore.js +3 -3
  699. package/clis/tiktok/follow.js +8 -8
  700. package/clis/tiktok/following.js +4 -4
  701. package/clis/tiktok/friends.js +7 -7
  702. package/clis/tiktok/live.js +3 -3
  703. package/clis/tiktok/notifications.js +6 -6
  704. package/clis/tiktok/publish.js +17 -17
  705. package/clis/tiktok/unfollow.js +4 -4
  706. package/clis/tiktok/user.js +2 -2
  707. package/clis/tiktok/utils.js +1 -1
  708. package/clis/toutiao/article.js +1 -1
  709. package/clis/toutiao/articles.js +2 -2
  710. package/clis/toutiao/auth.js +2 -2
  711. package/clis/toutiao/hot.js +1 -1
  712. package/clis/toutiao/recommend.js +1 -1
  713. package/clis/toutiao/utils.js +2 -2
  714. package/clis/trae-solo/_actions.js +4 -4
  715. package/clis/trae-solo/_fs.js +5 -5
  716. package/clis/trae-solo/_state.js +2 -2
  717. package/clis/trae-solo/automation.js +4 -4
  718. package/clis/trae-solo/mode.js +4 -4
  719. package/clis/trae-solo/model.js +4 -4
  720. package/clis/trae-solo/renderer-storage.js +4 -4
  721. package/clis/trae-solo/settings.js +1 -1
  722. package/clis/trae-solo/skill-fs.js +1 -1
  723. package/clis/trae-solo/skill.js +12 -12
  724. package/clis/trae-solo/state-fs.js +2 -2
  725. package/clis/trae-solo/task-fs.js +5 -5
  726. package/clis/trae-solo/workspaces-fs.js +1 -1
  727. package/clis/tumblr/auth.js +2 -2
  728. package/clis/tumblr/publish.js +3 -3
  729. package/clis/tvmaze/search.js +1 -1
  730. package/clis/tvmaze/show.js +1 -1
  731. package/clis/tvmaze/utils.js +1 -1
  732. package/clis/twitter/accept.js +7 -7
  733. package/clis/twitter/article.js +7 -7
  734. package/clis/twitter/bookmark-folder.js +3 -3
  735. package/clis/twitter/bookmark-folders.js +3 -3
  736. package/clis/twitter/bookmarks.js +4 -4
  737. package/clis/twitter/delete.js +5 -5
  738. package/clis/twitter/device-follow.js +3 -3
  739. package/clis/twitter/dm-list.js +1 -1
  740. package/clis/twitter/dm-read.js +1 -1
  741. package/clis/twitter/dm-send.js +5 -5
  742. package/clis/twitter/dm-shared.js +3 -3
  743. package/clis/twitter/download.js +6 -6
  744. package/clis/twitter/followers.js +5 -5
  745. package/clis/twitter/following.js +2 -2
  746. package/clis/twitter/like.js +3 -3
  747. package/clis/twitter/likes.js +8 -8
  748. package/clis/twitter/list-add-core.js +9 -9
  749. package/clis/twitter/list-create.js +5 -5
  750. package/clis/twitter/list-remove-core.js +9 -9
  751. package/clis/twitter/list-tweets.js +7 -7
  752. package/clis/twitter/lists.js +6 -6
  753. package/clis/twitter/notifications.js +2 -2
  754. package/clis/twitter/post.js +24 -24
  755. package/clis/twitter/profile.js +7 -7
  756. package/clis/twitter/quote.js +7 -7
  757. package/clis/twitter/reply-dm.js +7 -7
  758. package/clis/twitter/reply.js +12 -12
  759. package/clis/twitter/retweet.js +3 -3
  760. package/clis/twitter/scheduled-delete.js +3 -3
  761. package/clis/twitter/scheduled-list.js +2 -2
  762. package/clis/twitter/scheduled-utils.js +3 -3
  763. package/clis/twitter/search.js +5 -5
  764. package/clis/twitter/shared.js +6 -6
  765. package/clis/twitter/thread.js +4 -4
  766. package/clis/twitter/timeline.js +3 -3
  767. package/clis/twitter/trending.js +2 -2
  768. package/clis/twitter/tweets.js +11 -11
  769. package/clis/twitter/unlike.js +3 -3
  770. package/clis/twitter/unretweet.js +3 -3
  771. package/clis/twitter/utils.js +6 -6
  772. package/clis/upwork/detail.js +2 -2
  773. package/clis/upwork/feed.js +2 -2
  774. package/clis/upwork/search.js +2 -2
  775. package/clis/upwork/utils.js +1 -1
  776. package/clis/v2ex/auth.js +2 -2
  777. package/clis/v2ex/daily.js +3 -3
  778. package/clis/v2ex/me.js +2 -2
  779. package/clis/v2ex/notifications.js +2 -2
  780. package/clis/vk/post.js +1 -1
  781. package/clis/vk/shared.js +2 -2
  782. package/clis/vk/whoami.js +1 -1
  783. package/clis/web/read.js +8 -8
  784. package/clis/wechat-channels/auth.js +2 -2
  785. package/clis/wechat-channels/publish.js +30 -30
  786. package/clis/weibo/article.js +1 -1
  787. package/clis/weibo/auth.js +3 -3
  788. package/clis/weibo/comments.js +1 -1
  789. package/clis/weibo/delete.js +2 -2
  790. package/clis/weibo/feed.js +3 -3
  791. package/clis/weibo/hot.js +1 -1
  792. package/clis/weibo/publish.js +10 -10
  793. package/clis/weibo/search.js +2 -2
  794. package/clis/weibo/user-posts.js +3 -3
  795. package/clis/weibo/user.js +2 -2
  796. package/clis/weibo/utils.js +3 -3
  797. package/clis/weixin/article.js +1 -1
  798. package/clis/weixin/create-draft.js +26 -26
  799. package/clis/weixin/download.js +2 -2
  800. package/clis/weixin/login.js +1 -1
  801. package/clis/weixin/search.js +2 -2
  802. package/clis/weixin/stats.js +3 -3
  803. package/clis/weixin/whoami.js +1 -1
  804. package/clis/weread/ai-outline.js +2 -2
  805. package/clis/weread/book-search.js +2 -2
  806. package/clis/weread/book.js +2 -2
  807. package/clis/weread/notebooks.js +1 -1
  808. package/clis/weread/search.js +1 -1
  809. package/clis/weread/shelf.js +1 -1
  810. package/clis/weread/utils.js +6 -6
  811. package/clis/weread-official/book.js +1 -1
  812. package/clis/weread-official/discover.js +1 -1
  813. package/clis/weread-official/list-apis.js +1 -1
  814. package/clis/weread-official/notes.js +1 -1
  815. package/clis/weread-official/readdata.js +1 -1
  816. package/clis/weread-official/review.js +1 -1
  817. package/clis/weread-official/search.js +1 -1
  818. package/clis/weread-official/shelf.js +1 -1
  819. package/clis/weread-official/utils.js +1 -1
  820. package/clis/wikidata/entity.js +1 -1
  821. package/clis/wikidata/search.js +1 -1
  822. package/clis/wikidata/utils.js +1 -1
  823. package/clis/wikipedia/page.js +1 -1
  824. package/clis/wikipedia/trending.js +1 -1
  825. package/clis/wikipedia/utils.js +1 -1
  826. package/clis/wordpress/login.js +1 -1
  827. package/clis/wordpress/publish.js +1 -1
  828. package/clis/wordpress/shared.js +3 -3
  829. package/clis/wordpress/whoami.js +1 -1
  830. package/clis/woshipm/article.js +1 -1
  831. package/clis/woshipm/login.js +1 -1
  832. package/clis/woshipm/stats.js +4 -4
  833. package/clis/woshipm/whoami.js +1 -1
  834. package/clis/wttr/current.js +1 -1
  835. package/clis/wttr/forecast.js +1 -1
  836. package/clis/wttr/utils.js +1 -1
  837. package/clis/xianyu/collect.js +1 -1
  838. package/clis/xianyu/inbox.js +1 -1
  839. package/clis/xianyu/item-stats.js +2 -2
  840. package/clis/xianyu/location.js +1 -1
  841. package/clis/xianyu/manage.js +1 -1
  842. package/clis/xianyu/messages.js +1 -1
  843. package/clis/xianyu/mtop.js +5 -5
  844. package/clis/xianyu/order.js +1 -1
  845. package/clis/xianyu/promote-stats.js +2 -2
  846. package/clis/xianyu/publish.js +17 -17
  847. package/clis/xianyu/rate.js +1 -1
  848. package/clis/xianyu/reply.js +1 -1
  849. package/clis/xianyu/search.js +8 -8
  850. package/clis/xianyu/seller-data.js +1 -1
  851. package/clis/xianyu/seller-list.js +1 -1
  852. package/clis/xianyu/user.js +1 -1
  853. package/clis/xiaoe/catalog.js +2 -2
  854. package/clis/xiaoe/content.js +2 -2
  855. package/clis/xiaoe/courses.js +2 -2
  856. package/clis/xiaohongshu/ask.js +6 -6
  857. package/clis/xiaohongshu/comments.js +6 -6
  858. package/clis/xiaohongshu/creator-note-detail.js +7 -7
  859. package/clis/xiaohongshu/creator-notes-summary.js +1 -1
  860. package/clis/xiaohongshu/creator-notes.js +13 -13
  861. package/clis/xiaohongshu/creator-profile.js +2 -2
  862. package/clis/xiaohongshu/creator-stats.js +2 -2
  863. package/clis/xiaohongshu/delete-note.js +7 -7
  864. package/clis/xiaohongshu/download.js +4 -4
  865. package/clis/xiaohongshu/feed.js +2 -2
  866. package/clis/xiaohongshu/follow.js +3 -3
  867. package/clis/xiaohongshu/human.js +3 -3
  868. package/clis/xiaohongshu/note-helpers.js +1 -1
  869. package/clis/xiaohongshu/note.js +2 -2
  870. package/clis/xiaohongshu/notifications.js +1 -1
  871. package/clis/xiaohongshu/publish-video.js +8 -8
  872. package/clis/xiaohongshu/publish.js +59 -59
  873. package/clis/xiaohongshu/search.js +8 -8
  874. package/clis/xiaohongshu/unfollow.js +4 -4
  875. package/clis/xiaohongshu/user-helpers.js +1 -1
  876. package/clis/xiaohongshu/user.js +2 -2
  877. package/clis/xiaoyuzhou/auth.js +3 -3
  878. package/clis/xiaoyuzhou/download.js +1 -1
  879. package/clis/xiaoyuzhou/utils.js +1 -1
  880. package/clis/xueqiu/article.js +4 -4
  881. package/clis/xueqiu/comments.js +4 -4
  882. package/clis/xueqiu/danjuan-utils.js +4 -4
  883. package/clis/xueqiu/earnings-date.js +1 -1
  884. package/clis/xueqiu/events.js +3 -3
  885. package/clis/xueqiu/hashtags.js +3 -3
  886. package/clis/xueqiu/stocks.js +3 -3
  887. package/clis/xueqiu/users.js +3 -3
  888. package/clis/xueqiu/utils.js +3 -3
  889. package/clis/yahoo-finance/quote.js +1 -1
  890. package/clis/yollomi/background.js +1 -1
  891. package/clis/yollomi/edit.js +1 -1
  892. package/clis/yollomi/face-swap.js +1 -1
  893. package/clis/yollomi/generate.js +1 -1
  894. package/clis/yollomi/object-remover.js +1 -1
  895. package/clis/yollomi/remove-bg.js +1 -1
  896. package/clis/yollomi/restore.js +1 -1
  897. package/clis/yollomi/try-on.js +1 -1
  898. package/clis/yollomi/upload.js +4 -4
  899. package/clis/yollomi/upscale.js +1 -1
  900. package/clis/yollomi/utils.js +4 -4
  901. package/clis/yollomi/video.js +1 -1
  902. package/clis/youtube/channel.js +4 -4
  903. package/clis/youtube/feed.js +2 -2
  904. package/clis/youtube/like.js +5 -5
  905. package/clis/youtube/playlist.js +7 -7
  906. package/clis/youtube/publish.js +11 -11
  907. package/clis/youtube/search.js +3 -3
  908. package/clis/youtube/subscribe.js +7 -7
  909. package/clis/youtube/subscriptions.js +1 -1
  910. package/clis/youtube/transcript-group.js +2 -2
  911. package/clis/youtube/transcript.js +13 -13
  912. package/clis/youtube/unlike.js +5 -5
  913. package/clis/youtube/unsubscribe.js +7 -7
  914. package/clis/youtube/utils.js +3 -3
  915. package/clis/youtube/video.js +4 -4
  916. package/clis/youtube/watch-later.js +2 -2
  917. package/clis/yuanbao/ask.js +18 -18
  918. package/clis/yuanbao/detail.js +1 -1
  919. package/clis/yuanbao/read.js +1 -1
  920. package/clis/yuanbao/shared.js +9 -9
  921. package/clis/yuanbao/status.js +1 -1
  922. package/clis/yuque/article.js +1 -1
  923. package/clis/yuque/whoami.js +1 -1
  924. package/clis/zhihu/answer-comments.js +2 -2
  925. package/clis/zhihu/answer-detail.js +3 -3
  926. package/clis/zhihu/answer.js +1 -1
  927. package/clis/zhihu/article-transform.js +1 -1
  928. package/clis/zhihu/article.js +1 -1
  929. package/clis/zhihu/auth.js +2 -2
  930. package/clis/zhihu/collection.js +3 -3
  931. package/clis/zhihu/collections.js +3 -3
  932. package/clis/zhihu/download.js +2 -2
  933. package/clis/zhihu/image-profile.js +6 -6
  934. package/clis/zhihu/paginate.js +3 -3
  935. package/clis/zhihu/pin.js +4 -4
  936. package/clis/zhihu/question.js +3 -3
  937. package/clis/zhihu/recommend.js +3 -3
  938. package/clis/zhihu/search.js +3 -3
  939. package/clis/zhihu/stats.js +3 -3
  940. package/clis/zhihu/user-arg.js +1 -1
  941. package/clis/zhihu/write-shared.js +7 -7
  942. package/clis/zlibrary/utils.js +6 -6
  943. package/clis/zsxq/auth.js +3 -3
  944. package/clis/zsxq/search.js +1 -1
  945. package/clis/zsxq/topic.js +1 -1
  946. package/clis/zsxq/utils.js +5 -5
  947. package/dist/src/adapter-source.js +1 -1
  948. package/dist/src/browser/analyze.js +1 -1
  949. package/dist/src/browser/article-extract.js +2 -2
  950. package/dist/src/browser/ax-snapshot.js +2 -2
  951. package/dist/src/browser/base-page.js +25 -25
  952. package/dist/src/browser/bridge.js +1 -1
  953. package/dist/src/browser/cdp.js +1 -1
  954. package/dist/src/browser/daemon-client.js +1 -1
  955. package/dist/src/browser/daemon-lifecycle.js +7 -7
  956. package/dist/src/browser/dom-helpers.js +35 -35
  957. package/dist/src/browser/dom-snapshot.js +19 -19
  958. package/dist/src/browser/errors.js +3 -3
  959. package/dist/src/browser/extract.js +5 -5
  960. package/dist/src/browser/find.js +13 -13
  961. package/dist/src/browser/fingerprint.js +2 -2
  962. package/dist/src/browser/html-tree.js +6 -6
  963. package/dist/src/browser/managed-chrome.js +1 -1
  964. package/dist/src/browser/network-cache.js +1 -1
  965. package/dist/src/browser/network-key.js +1 -1
  966. package/dist/src/browser/page.js +7 -7
  967. package/dist/src/browser/profile.js +2 -2
  968. package/dist/src/browser/proxy-test.js +8 -8
  969. package/dist/src/browser/shape-filter.js +1 -1
  970. package/dist/src/browser/shape.js +1 -1
  971. package/dist/src/browser/stealth.js +3 -3
  972. package/dist/src/browser/tabs.js +2 -2
  973. package/dist/src/browser/target-errors.js +1 -1
  974. package/dist/src/browser/target-resolver.js +23 -23
  975. package/dist/src/browser/trace.js +2 -2
  976. package/dist/src/browser/utils.js +1 -1
  977. package/dist/src/browser/verify-fixture.js +2 -2
  978. package/dist/src/browser-session-lock.js +1 -1
  979. package/dist/src/build-manifest.js +11 -11
  980. package/dist/src/capabilityRouting.js +1 -1
  981. package/dist/src/cli-argv-preprocess.js +1 -1
  982. package/dist/src/cli.js +32 -32
  983. package/dist/src/commanderAdapter.js +3 -3
  984. package/dist/src/commands/auth.js +3 -3
  985. package/dist/src/commands/daemon.js +1 -1
  986. package/dist/src/completion-fast.js +1 -1
  987. package/dist/src/completion.js +1 -1
  988. package/dist/src/constants.js +1 -1
  989. package/dist/src/convention-audit.js +2 -2
  990. package/dist/src/daemon-utils.js +1 -1
  991. package/dist/src/daemon.js +1 -1
  992. package/dist/src/discovery.js +2 -2
  993. package/dist/src/doctor.js +9 -9
  994. package/dist/src/download/article-download.js +15 -15
  995. package/dist/src/download/index.js +4 -4
  996. package/dist/src/download/media-download.js +1 -1
  997. package/dist/src/download/progress.js +3 -3
  998. package/dist/src/electron-apps.js +1 -1
  999. package/dist/src/errors.js +2 -2
  1000. package/dist/src/execution.js +2 -2
  1001. package/dist/src/external.js +1 -1
  1002. package/dist/src/help.js +8 -8
  1003. package/dist/src/hooks.js +1 -1
  1004. package/dist/src/interceptor.js +21 -21
  1005. package/dist/src/launcher.js +7 -7
  1006. package/dist/src/logger.js +8 -8
  1007. package/dist/src/main.js +7 -7
  1008. package/dist/src/observation/artifact.js +5 -5
  1009. package/dist/src/observation/retention.js +1 -1
  1010. package/dist/src/output.js +2 -2
  1011. package/dist/src/package-paths.js +1 -1
  1012. package/dist/src/pipeline/executor.js +1 -1
  1013. package/dist/src/pipeline/registry.js +1 -1
  1014. package/dist/src/pipeline/steps/browser.js +1 -1
  1015. package/dist/src/pipeline/steps/download.js +1 -1
  1016. package/dist/src/pipeline/steps/fetch.js +6 -6
  1017. package/dist/src/pipeline/steps/intercept.js +1 -1
  1018. package/dist/src/pipeline/steps/tap.js +17 -17
  1019. package/dist/src/pipeline/steps/transform.js +1 -1
  1020. package/dist/src/pipeline/template.js +1 -1
  1021. package/dist/src/plugin-manifest.js +1 -1
  1022. package/dist/src/plugin-scaffold.js +19 -19
  1023. package/dist/src/plugin.js +12 -12
  1024. package/dist/src/rate-limit.js +1 -1
  1025. package/dist/src/registry.js +1 -1
  1026. package/dist/src/runtime-detect.js +1 -1
  1027. package/dist/src/runtime.js +1 -1
  1028. package/dist/src/scripts/framework.js +1 -1
  1029. package/dist/src/scripts/interact.js +1 -1
  1030. package/dist/src/scripts/store.js +1 -1
  1031. package/dist/src/serialization.js +2 -2
  1032. package/dist/src/session-lease.js +1 -1
  1033. package/dist/src/snapshotFormatter.js +2 -2
  1034. package/dist/src/tui.js +12 -12
  1035. package/dist/src/user-runtime.js +1 -1
  1036. package/dist/src/utils.d.ts +12 -0
  1037. package/dist/src/utils.js +4 -4
  1038. package/dist/src/validate.js +2 -2
  1039. package/dist/src/verify.js +2 -2
  1040. package/dist/src/version.js +1 -1
  1041. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import{cli as c,Strategy as m}from"@jackwener/opencli/registry";import{BROWSER_HELPERS as l,BUTTON_WALKER_HELPERS as u,RETRYABLE_HINTS as d,parseTikTokVideoUrl as p,requireCommentText as T,throwButtonWalkerError as h}from"./utils.js";function a(e){return`
1
+ import{cli as s,Strategy as m}from"@jackwener/opencli/registry";import{BROWSER_HELPERS as l,BUTTON_WALKER_HELPERS as u,RETRYABLE_HINTS as d,parseTikTokVideoUrl as p,requireCommentText as T,throwButtonWalkerError as w}from"./utils.js";function a(e){return`
2
2
  (async () => {
3
3
  const commentText = ${JSON.stringify(e)};
4
4
 
@@ -66,4 +66,4 @@ import{cli as c,Strategy as m}from"@jackwener/opencli/registry";import{BROWSER_H
66
66
  result: 'posted',
67
67
  }];
68
68
  })()
69
- `}async function w(e,r){const{url:o}=p(r.url),s=T(r.text),i=(n)=>h(n,{authMessage:"TikTok requires login to post comments",failureMessage:`Failed to post comment on ${o}`,retryableHint:d.commentFailure});let t;try{await e.goto(o,{waitUntil:"load",settleMs:6000});t=await e.evaluate(a(s))}catch(n){i(n)}if(!Array.isArray(t)||t.length===0)i(Error(`STATE_VERIFY_FAIL: comment returned no row for ${o}`));return t}export const commentCommand=c({site:"tiktok",name:"comment",access:"write",description:"Post a comment on a TikTok video",domain:"www.tiktok.com",strategy:m.COOKIE,browser:!0,args:[{name:"url",required:!0,positional:!0,help:"TikTok video URL (https://www.tiktok.com/@user/video/<id>)"},{name:"text",fromFile:!0,required:!0,positional:!0,help:"Comment text (≤150 chars)"}],columns:["url","text","result"],func:w}),__test__={buildCommentScript:a};
69
+ `}async function h(e,r){const{url:o}=p(r.url),c=T(r.text),i=(n)=>w(n,{authMessage:"TikTok requires login to post comments",failureMessage:`Failed to post comment on ${o}`,retryableHint:d.commentFailure});let t;try{await e.goto(o,{waitUntil:"load",settleMs:6000});t=await e.evaluate(a(c))}catch(n){i(n)}if(!Array.isArray(t)||t.length===0)i(Error(`STATE_VERIFY_FAIL: comment returned no row for ${o}`));return t}export const commentCommand=s({site:"tiktok",name:"comment",access:"write",description:"Post a comment on a TikTok video",domain:"www.tiktok.com",strategy:m.COOKIE,browser:!0,args:[{name:"url",required:!0,positional:!0,help:"TikTok video URL (https://www.tiktok.com/@user/video/<id>)"},{name:"text",fromFile:!0,required:!0,positional:!0,help:"Comment text (≤150 chars)"}],columns:["url","text","result"],func:h}),__test__={buildCommentScript:a};
@@ -1,6 +1,6 @@
1
- import{cli as V,Strategy as R}from"@jackwener/opencli/registry";import{ArgumentError as j,AuthRequiredError as G,CommandExecutionError as $,EmptyResultError as T,getErrorMessage as _}from"@jackwener/opencli/errors";const F="https://www.tiktok.com/tiktokstudio/content",A="/tiktok/creator/manage/item_list/v1/",y=20,N=250,P=50;function U(B,J,W,Q){const Z=Number(B??W);if(!Number.isInteger(Z)||Z<=0)throw new j(`${J} must be a positive integer`,`Example: ppcli tiktok creator-videos --${J} ${W}`);if(Z>Q)throw new j(`${J} must be <= ${Q}`,`Example: ppcli tiktok creator-videos --${J} ${Q}`);return Z}function O(B){const W=String(B??"0").trim();if(!/^\d+$/.test(W))throw new j("cursor must be a non-negative integer string","Example: ppcli tiktok creator-videos --cursor 0");const Q=Number(W);if(!Number.isSafeInteger(Q))throw new j("cursor must be a safe integer","Example: ppcli tiktok creator-videos --cursor 0");return Q}function h(B,J){return{cursor:B,size:J,query:{conditions:[],sort_orders:[{field_name:"create_time",order:2}]}}}function q(B){const J={url:`${A}?aid=1988`,body:B};return`
1
+ import{cli as N,Strategy as A}from"@jackwener/opencli/registry";import{ArgumentError as c,AuthRequiredError as d,CommandExecutionError as n,EmptyResultError as q,getErrorMessage as C}from"@jackwener/opencli/errors";const p="https://www.tiktok.com/tiktokstudio/content",M="/tiktok/creator/manage/item_list/v1/",h=20,_=250,g=50;function T(t,e,o,r){const s=Number(t??o);if(!Number.isInteger(s)||s<=0)throw new c(`${e} must be a positive integer`,`Example: ppcli tiktok creator-videos --${e} ${o}`);if(s>r)throw new c(`${e} must be <= ${r}`,`Example: ppcli tiktok creator-videos --${e} ${r}`);return s}function l(t){const o=String(t??"0").trim();if(!/^\d+$/.test(o))throw new c("cursor must be a non-negative integer string","Example: ppcli tiktok creator-videos --cursor 0");const r=Number(o);if(!Number.isSafeInteger(r))throw new c("cursor must be a safe integer","Example: ppcli tiktok creator-videos --cursor 0");return r}function S(t,e){return{cursor:t,size:e,query:{conditions:[],sort_orders:[{field_name:"create_time",order:2}]}}}function y(t){const e={url:`${M}?aid=1988`,body:t};return`
2
2
  (async () => {
3
- const request = ${JSON.stringify(J)};
3
+ const request = ${JSON.stringify(e)};
4
4
  try {
5
5
  const res = await fetch(request.url, {
6
6
  method: 'POST',
@@ -42,4 +42,4 @@ import{cli as V,Strategy as R}from"@jackwener/opencli/registry";import{ArgumentE
42
42
  };
43
43
  }
44
44
  })()
45
- `}function S(B){return/\b(auth|login|log in|permission|unauthori[sz]ed|forbidden)\b/i.test(B)}function M(B){if(!B||typeof B!=="object")throw new $("TikTok Studio item_list returned an empty response");return B.data&&typeof B.data==="object"?B.data:B}function b(B){const J=B.status_code??B.statusCode,W=String(B.status_msg??B.statusMsg??"").trim();if(J!==void 0&&Number(J)!==0){if(S(W))throw new G("www.tiktok.com",`TikTok Studio item_list requires login: ${W||J}`);throw new $(`TikTok Studio item_list failed: ${W||J}`)}if(W&&!/^(success|ok)$/i.test(W)){if(S(W))throw new G("www.tiktok.com",`TikTok Studio item_list requires login: ${W}`);throw new $(`TikTok Studio item_list failed: ${W}`)}}function H(B){const J=Number(B);return Number.isFinite(J)?J:0}function C(B){const J=Number(B);if(!Number.isFinite(J)||J<=0)return"";return new Date(J*1000).toLocaleString("zh-CN",{timeZone:"Asia/Shanghai",hour12:!1})}function v(B){const J=B.author?.unique_id??B.author?.uniqueId??B.author_unique_id??B.authorUniqueId??B.user_name??B.username;if(J)return String(J);const W=[...Array.isArray(B.play_addr)?B.play_addr:[],...B.download_info&&Array.isArray(B.download_info.download_urls)?B.download_info.download_urls:[]];for(const Q of W)try{const Y=String(Q).match(/[?&]user_text=([^&]+)/);if(Y)return decodeURIComponent(Y[1])}catch{}return""}function z(B){if(!B||typeof B!=="object")return null;const J=String(B.item_id??B.id??"").trim();if(!J)return null;const W=v(B),Q=W?`https://www.tiktok.com/@${encodeURIComponent(W)}/video/${encodeURIComponent(J)}`:"";return{video_id:J,title:String(B.desc??B.title??"").replace(/\s+/g," ").trim(),date:C(B.post_time??B.create_time??B.schedule_time),views:H(B.play_count),likes:H(B.like_count),comments:H(B.comment_count),saves:H(B.favorite_count),shares:H(B.share_count),url:Q}}async function x(B,J,W){const Q=await B.evaluate(q(h(J,W))).catch((Z)=>{throw new $(`Failed to fetch TikTok Studio item_list: ${_(Z)}`)});if(!Q||typeof Q!=="object")throw new $("TikTok Studio item_list returned an unreadable response");if(Q.networkError)throw new $(`TikTok Studio item_list network failure: ${Q.networkError}`);if(Q.status===401||Q.status===403)throw new G("www.tiktok.com",`TikTok Studio item_list requires login (HTTP ${Q.status})`);if(!Q.ok){const Z=Q.parseError?`invalid JSON (${Q.parseError})`:`HTTP ${Q.status||0}${Q.statusText?` ${Q.statusText}`:""}`;throw new $(`TikTok Studio item_list failed: ${Z}`,Q.text?`Response preview: ${Q.text}`:void 0)}const Y=M(Q.data);b(Y);return Y}async function I(B,J){const W=U(J.limit,"limit",y,N);let Q=O(J.cursor);const Y=[];let Z=0;const X=W>P?P:W,w=Math.ceil(W/X);await B.goto(F,{waitUntil:"load",settleMs:6000});for(let D=0;D<w&&Y.length<W;D+=1){const K=await x(B,Q,X),f=Array.isArray(K.item_list)?K.item_list:[];for(const L of f){const k=z(L);if(!k){Z+=1;continue}Y.push(k);if(Y.length>=W)break}if(!K.has_more||f.length===0)break;Q=O(K.cursor);await B.wait(250)}if(Y.length===0&&Z>0)throw new $("TikTok Studio item_list returned videos without stable video_id");if(Y.length===0)throw new T("tiktok creator-videos","No creator videos were returned. Confirm the current Chrome profile is logged in to TikTok Studio and has published content.");return Y.slice(0,W)}export const creatorVideosCommand=V({site:"tiktok",name:"creator-videos",access:"read",description:"TikTok Studio creator content list (views/likes/comments/saves/shares)",domain:"www.tiktok.com",strategy:R.COOKIE,browser:!0,navigateBefore:F,args:[{name:"limit",type:"int",default:y,help:`Number of creator videos to return (max ${N})`},{name:"cursor",type:"string",default:"0",help:"Non-negative TikTok Studio pagination cursor"}],columns:["video_id","title","date","views","likes","comments","saves","shares","url"],func:I}),__test__={buildFetchItemListScript:q,buildItemListRequest:h,extractUsername:v,normalizeRow:z,requireCursor:O,requirePositiveInt:U};
45
+ `}function b(t){return/\b(auth|login|log in|permission|unauthori[sz]ed|forbidden)\b/i.test(t)}function R(t){if(!t||typeof t!=="object")throw new n("TikTok Studio item_list returned an empty response");return t.data&&typeof t.data==="object"?t.data:t}function P(t){const e=t.status_code??t.statusCode,o=String(t.status_msg??t.statusMsg??"").trim();if(e!==void 0&&Number(e)!==0){if(b(o))throw new d("www.tiktok.com",`TikTok Studio item_list requires login: ${o||e}`);throw new n(`TikTok Studio item_list failed: ${o||e}`)}if(o&&!/^(success|ok)$/i.test(o)){if(b(o))throw new d("www.tiktok.com",`TikTok Studio item_list requires login: ${o}`);throw new n(`TikTok Studio item_list failed: ${o}`)}}function a(t){const e=Number(t);return Number.isFinite(e)?e:0}function O(t){const e=Number(t);if(!Number.isFinite(e)||e<=0)return"";return new Date(e*1000).toLocaleString("zh-CN",{timeZone:"Asia/Shanghai",hour12:!1})}function v(t){const e=t.author?.unique_id??t.author?.uniqueId??t.author_unique_id??t.authorUniqueId??t.user_name??t.username;if(e)return String(e);const o=[...Array.isArray(t.play_addr)?t.play_addr:[],...t.download_info&&Array.isArray(t.download_info.download_urls)?t.download_info.download_urls:[]];for(const r of o)try{const i=String(r).match(/[?&]user_text=([^&]+)/);if(i)return decodeURIComponent(i[1])}catch{}return""}function x(t){if(!t||typeof t!=="object")return null;const e=String(t.item_id??t.id??"").trim();if(!e)return null;const o=v(t),r=o?`https://www.tiktok.com/@${encodeURIComponent(o)}/video/${encodeURIComponent(e)}`:"";return{video_id:e,title:String(t.desc??t.title??"").replace(/\s+/g," ").trim(),date:O(t.post_time??t.create_time??t.schedule_time),views:a(t.play_count),likes:a(t.like_count),comments:a(t.comment_count),saves:a(t.favorite_count),shares:a(t.share_count),url:r}}async function U(t,e,o){const r=await t.evaluate(y(S(e,o))).catch((s)=>{throw new n(`Failed to fetch TikTok Studio item_list: ${C(s)}`)});if(!r||typeof r!=="object")throw new n("TikTok Studio item_list returned an unreadable response");if(r.networkError)throw new n(`TikTok Studio item_list network failure: ${r.networkError}`);if(r.status===401||r.status===403)throw new d("www.tiktok.com",`TikTok Studio item_list requires login (HTTP ${r.status})`);if(!r.ok){const s=r.parseError?`invalid JSON (${r.parseError})`:`HTTP ${r.status||0}${r.statusText?` ${r.statusText}`:""}`;throw new n(`TikTok Studio item_list failed: ${s}`,r.text?`Response preview: ${r.text}`:void 0)}const i=R(r.data);P(i);return i}async function L(t,e){const o=T(e.limit,"limit",h,_);let r=l(e.cursor);const i=[];let s=0;const w=o>g?g:o,E=Math.ceil(o/w);await t.goto(p,{waitUntil:"load",settleMs:6000});for(let m=0;m<E&&i.length<o;m+=1){const u=await U(t,r,w),f=Array.isArray(u.item_list)?u.item_list:[];for(const I of f){const k=x(I);if(!k){s+=1;continue}i.push(k);if(i.length>=o)break}if(!u.has_more||f.length===0)break;r=l(u.cursor);await t.wait(250)}if(i.length===0&&s>0)throw new n("TikTok Studio item_list returned videos without stable video_id");if(i.length===0)throw new q("tiktok creator-videos","No creator videos were returned. Confirm the current Chrome profile is logged in to TikTok Studio and has published content.");return i.slice(0,o)}export const creatorVideosCommand=N({site:"tiktok",name:"creator-videos",access:"read",description:"TikTok Studio creator content list (views/likes/comments/saves/shares)",domain:"www.tiktok.com",strategy:A.COOKIE,browser:!0,navigateBefore:p,args:[{name:"limit",type:"int",default:h,help:`Number of creator videos to return (max ${_})`},{name:"cursor",type:"string",default:"0",help:"Non-negative TikTok Studio pagination cursor"}],columns:["video_id","title","date","views","likes","comments","saves","shares","url"],func:L}),__test__={buildFetchItemListScript:y,buildItemListRequest:S,extractUsername:v,normalizeRow:x,requireCursor:l,requirePositiveInt:T};
@@ -1,4 +1,4 @@
1
- import{cli as m,Strategy as l}from"@jackwener/opencli/registry";import{EmptyResultError as d}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as c,MAX_PAGES as u,SERVER_PAGE_MAX as p,TIKTOK_AID as f,requireLimit as w,throwTikTokPageContextError as k,VIDEO_ITEM_NORMALIZER as g}from"./utils.js";const r=20,o=120;function i(e){return`
1
+ import{cli as m,Strategy as d}from"@jackwener/opencli/registry";import{EmptyResultError as c}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as l,MAX_PAGES as u,SERVER_PAGE_MAX as p,TIKTOK_AID as f,requireLimit as w,throwTikTokPageContextError as k,VIDEO_ITEM_NORMALIZER as g}from"./utils.js";const r=20,o=120;function i(e){return`
2
2
  (async () => {
3
3
  const limit = ${Number(e)};
4
4
  const maxPages = ${u};
@@ -8,7 +8,7 @@ import{cli as m,Strategy as l}from"@jackwener/opencli/registry";import{EmptyResu
8
8
  const pageSize = limit < SERVER_PAGE_MAX ? limit : SERVER_PAGE_MAX;
9
9
  const aid = ${JSON.stringify(f)};
10
10
 
11
- ${c}
11
+ ${l}
12
12
  ${g}
13
13
 
14
14
  function collectFromState(root) {
@@ -73,4 +73,4 @@ import{cli as m,Strategy as l}from"@jackwener/opencli/registry";import{EmptyResu
73
73
  }
74
74
  return rows;
75
75
  })()
76
- `}async function A(e,s){const a=w(s.limit,{fallback:r,max:o});await e.goto("https://www.tiktok.com/explore",{waitUntil:"load",settleMs:5000});let t;try{t=await e.evaluate(i(a))}catch(n){k(n,{authMessage:"TikTok requires browser access to load the explore feed",emptyPattern:/No videos found/,emptyTarget:"tiktok explore",failureMessage:"Failed to load TikTok explore feed"})}if(!Array.isArray(t)||t.length===0)throw new d("tiktok explore","TikTok returned an empty recommend feed");return t}export const exploreCommand=m({site:"tiktok",name:"explore",access:"read",description:"Get trending TikTok videos from the recommend feed via page-context APIs",domain:"www.tiktok.com",strategy:l.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:r,help:`Number of videos to return (max ${o})`}],columns:["index","id","author","url","cover","title","desc","plays","likes","comments","shares","createTime"],func:A}),__test__={buildExploreScript:i,DEFAULT_LIMIT:r,MAX_LIMIT:o};
76
+ `}async function A(e,s){const a=w(s.limit,{fallback:r,max:o});await e.goto("https://www.tiktok.com/explore",{waitUntil:"load",settleMs:5000});let t;try{t=await e.evaluate(i(a))}catch(n){k(n,{authMessage:"TikTok requires browser access to load the explore feed",emptyPattern:/No videos found/,emptyTarget:"tiktok explore",failureMessage:"Failed to load TikTok explore feed"})}if(!Array.isArray(t)||t.length===0)throw new c("tiktok explore","TikTok returned an empty recommend feed");return t}export const exploreCommand=m({site:"tiktok",name:"explore",access:"read",description:"Get trending TikTok videos from the recommend feed via page-context APIs",domain:"www.tiktok.com",strategy:d.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:r,help:`Number of videos to return (max ${o})`}],columns:["index","id","author","url","cover","title","desc","plays","likes","comments","shares","createTime"],func:A}),__test__={buildExploreScript:i,DEFAULT_LIMIT:r,MAX_LIMIT:o};
@@ -1,9 +1,9 @@
1
- import{cli as V,Strategy as X}from"@jackwener/opencli/registry";import{BROWSER_HELPERS as Z,BUTTON_WALKER_HELPERS as $,RETRYABLE_HINTS as v,TIKTOK_HOST as D,normalizeUsername as z,throwButtonWalkerError as Y}from"./utils.js";function M(q){return`
1
+ import{cli as a,Strategy as u}from"@jackwener/opencli/registry";import{BROWSER_HELPERS as c,BUTTON_WALKER_HELPERS as w,RETRYABLE_HINTS as f,TIKTOK_HOST as r,normalizeUsername as L,throwButtonWalkerError as m}from"./utils.js";function i(t){return`
2
2
  (async () => {
3
- const username = ${JSON.stringify(q)};
3
+ const username = ${JSON.stringify(t)};
4
4
 
5
- ${Z}
6
- ${$}
5
+ ${c}
6
+ ${w}
7
7
 
8
8
  ensureLoggedInOrThrow();
9
9
  ensureNoRateLimitOrThrow();
@@ -15,10 +15,10 @@ import{cli as V,Strategy as X}from"@jackwener/opencli/registry";import{BROWSER_H
15
15
 
16
16
  // Idempotent fast path: already in target state.
17
17
  if (buttonExists(FRIENDS_LABELS)) {
18
- return [{ username, url: ${JSON.stringify(D)} + '/@' + encodeURIComponent(username), result: 'already-friends' }];
18
+ return [{ username, url: ${JSON.stringify(r)} + '/@' + encodeURIComponent(username), result: 'already-friends' }];
19
19
  }
20
20
  if (buttonExists(FOLLOWING_LABELS)) {
21
- return [{ username, url: ${JSON.stringify(D)} + '/@' + encodeURIComponent(username), result: 'already-following' }];
21
+ return [{ username, url: ${JSON.stringify(r)} + '/@' + encodeURIComponent(username), result: 'already-following' }];
22
22
  }
23
23
 
24
24
  const followBtn = findButtonByText(FOLLOW_LABELS);
@@ -42,8 +42,8 @@ import{cli as V,Strategy as X}from"@jackwener/opencli/registry";import{BROWSER_H
42
42
 
43
43
  return [{
44
44
  username,
45
- url: ${JSON.stringify(D)} + '/@' + encodeURIComponent(username),
45
+ url: ${JSON.stringify(r)} + '/@' + encodeURIComponent(username),
46
46
  result: 'followed',
47
47
  }];
48
48
  })()
49
- `}async function b(q,Q){const x=z(Q.username),J=(G)=>Y(G,{authMessage:"TikTok requires login to follow users",failureMessage:`Failed to follow @${x}`,retryableHint:v.relationFailure});let C;try{await q.goto(`${D}/@${encodeURIComponent(x)}`,{waitUntil:"load",settleMs:5000});C=await q.evaluate(M(x))}catch(G){J(G)}if(!Array.isArray(C)||C.length===0)J(Error(`STATE_VERIFY_FAIL: follow returned no row for @${x}`));return C}export const followCommand=V({site:"tiktok",name:"follow",access:"write",description:"Follow a TikTok user by username",domain:"www.tiktok.com",strategy:X.COOKIE,browser:!0,args:[{name:"username",required:!0,positional:!0,help:"TikTok username (without @)"}],columns:["username","url","result"],func:b}),__test__={buildFollowScript:M};
49
+ `}async function E(t,s){const e=L(s.username),l=(n)=>m(n,{authMessage:"TikTok requires login to follow users",failureMessage:`Failed to follow @${e}`,retryableHint:f.relationFailure});let o;try{await t.goto(`${r}/@${encodeURIComponent(e)}`,{waitUntil:"load",settleMs:5000});o=await t.evaluate(i(e))}catch(n){l(n)}if(!Array.isArray(o)||o.length===0)l(Error(`STATE_VERIFY_FAIL: follow returned no row for @${e}`));return o}export const followCommand=a({site:"tiktok",name:"follow",access:"write",description:"Follow a TikTok user by username",domain:"www.tiktok.com",strategy:u.COOKIE,browser:!0,args:[{name:"username",required:!0,positional:!0,help:"TikTok username (without @)"}],columns:["username","url","result"],func:E}),__test__={buildFollowScript:i};
@@ -1,10 +1,10 @@
1
- import{cli as c,Strategy as d}from"@jackwener/opencli/registry";import{EmptyResultError as l}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as u,MAX_PAGES as f,SERVER_PAGE_MAX as w,TIKTOK_AID as m,USER_ITEM_NORMALIZER as p,requireLimit as g,throwTikTokPageContextError as _}from"./utils.js";const i=20,t=200;function o(e){return`
1
+ import{cli as c,Strategy as d}from"@jackwener/opencli/registry";import{EmptyResultError as l}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as u,MAX_PAGES as f,SERVER_PAGE_MAX as m,TIKTOK_AID as w,USER_ITEM_NORMALIZER as p,requireLimit as g,throwTikTokPageContextError as U}from"./utils.js";const i=20,t=200;function o(e){return`
2
2
  (async () => {
3
3
  const limit = ${Number(e)};
4
4
  const maxPages = ${f*2};
5
- const SERVER_PAGE_MAX = ${w};
5
+ const SERVER_PAGE_MAX = ${m};
6
6
  const pageSize = limit < SERVER_PAGE_MAX ? limit : SERVER_PAGE_MAX;
7
- const aid = ${JSON.stringify(m)};
7
+ const aid = ${JSON.stringify(w)};
8
8
 
9
9
  ${u}
10
10
  ${p}
@@ -100,4 +100,4 @@ import{cli as c,Strategy as d}from"@jackwener/opencli/registry";import{EmptyResu
100
100
  }
101
101
  return rows;
102
102
  })()
103
- `}async function U(e,s){const n=g(s.limit,{fallback:i,max:t});await e.goto("https://www.tiktok.com/following",{waitUntil:"load",settleMs:5000});let r;try{r=await e.evaluate(o(n))}catch(a){_(a,{authMessage:"TikTok requires login to read your following list",emptyPattern:/No following entries/,emptyTarget:"tiktok following",failureMessage:"Failed to load TikTok following list"})}if(!Array.isArray(r)||r.length===0)throw new l("tiktok following","TikTok returned no following entries");return r}export const followingCommand=c({site:"tiktok",name:"following",access:"read",description:"List accounts the logged-in user follows on TikTok via page-context APIs",domain:"www.tiktok.com",strategy:d.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"limit",type:"int",default:i,help:`Number of accounts (max ${t})`}],columns:["index","username","name","secUid","verified","followers","following","url"],func:U}),__test__={buildFollowingScript:o,DEFAULT_LIMIT:i,MAX_LIMIT:t};
103
+ `}async function _(e,s){const n=g(s.limit,{fallback:i,max:t});await e.goto("https://www.tiktok.com/following",{waitUntil:"load",settleMs:5000});let r;try{r=await e.evaluate(o(n))}catch(a){U(a,{authMessage:"TikTok requires login to read your following list",emptyPattern:/No following entries/,emptyTarget:"tiktok following",failureMessage:"Failed to load TikTok following list"})}if(!Array.isArray(r)||r.length===0)throw new l("tiktok following","TikTok returned no following entries");return r}export const followingCommand=c({site:"tiktok",name:"following",access:"read",description:"List accounts the logged-in user follows on TikTok via page-context APIs",domain:"www.tiktok.com",strategy:d.COOKIE,browser:!0,siteSession:"persistent",args:[{name:"limit",type:"int",default:i,help:`Number of accounts (max ${t})`}],columns:["index","username","name","secUid","verified","followers","following","url"],func:_}),__test__={buildFollowingScript:o,DEFAULT_LIMIT:i,MAX_LIMIT:t};
@@ -1,13 +1,13 @@
1
- import{cli as u,Strategy as l}from"@jackwener/opencli/registry";import{EmptyResultError as c}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as d,MAX_PAGES as f,SERVER_PAGE_MAX as m,TIKTOK_AID as g,USER_ITEM_NORMALIZER as p,requireLimit as w,throwTikTokPageContextError as k}from"./utils.js";const t=20,s=100;function o(e){return`
1
+ import{cli as u,Strategy as d}from"@jackwener/opencli/registry";import{EmptyResultError as c}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as l,MAX_PAGES as m,SERVER_PAGE_MAX as f,TIKTOK_AID as g,USER_ITEM_NORMALIZER as w,requireLimit as p,throwTikTokPageContextError as k}from"./utils.js";const t=20,s=100;function o(r){return`
2
2
  (async () => {
3
- const limit = ${Number(e)};
4
- const maxPages = ${f};
5
- const SERVER_PAGE_MAX = ${m};
3
+ const limit = ${Number(r)};
4
+ const maxPages = ${m};
5
+ const SERVER_PAGE_MAX = ${f};
6
6
  const pageSize = limit < SERVER_PAGE_MAX ? limit : SERVER_PAGE_MAX;
7
7
  const aid = ${JSON.stringify(g)};
8
8
 
9
- ${d}
10
- ${p}
9
+ ${l}
10
+ ${w}
11
11
 
12
12
  function collectUsersFromState(root) {
13
13
  if (!root) return [];
@@ -76,4 +76,4 @@ import{cli as u,Strategy as l}from"@jackwener/opencli/registry";import{EmptyResu
76
76
  }
77
77
  return rows;
78
78
  })()
79
- `}async function y(e,i){const a=w(i.limit,{fallback:t,max:s});await e.goto("https://www.tiktok.com/friends",{waitUntil:"load",settleMs:5000});let r;try{r=await e.evaluate(o(a))}catch(n){k(n,{authMessage:"TikTok requires browser access to load friend suggestions",emptyPattern:/No friend suggestions/,emptyTarget:"tiktok friends",failureMessage:"Failed to load TikTok friend suggestions"})}if(!Array.isArray(r)||r.length===0)throw new c("tiktok friends","TikTok returned no friend suggestions");return r}export const friendsCommand=u({site:"tiktok",name:"friends",access:"read",description:"Get TikTok friend / who-to-follow suggestions via page-context APIs",domain:"www.tiktok.com",strategy:l.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:t,help:`Number of suggestions (max ${s})`}],columns:["index","username","name","secUid","verified","followers","following","url"],func:y}),__test__={buildFriendsScript:o,DEFAULT_LIMIT:t,MAX_LIMIT:s};
79
+ `}async function y(r,i){const n=p(i.limit,{fallback:t,max:s});await r.goto("https://www.tiktok.com/friends",{waitUntil:"load",settleMs:5000});let e;try{e=await r.evaluate(o(n))}catch(a){k(a,{authMessage:"TikTok requires browser access to load friend suggestions",emptyPattern:/No friend suggestions/,emptyTarget:"tiktok friends",failureMessage:"Failed to load TikTok friend suggestions"})}if(!Array.isArray(e)||e.length===0)throw new c("tiktok friends","TikTok returned no friend suggestions");return e}export const friendsCommand=u({site:"tiktok",name:"friends",access:"read",description:"Get TikTok friend / who-to-follow suggestions via page-context APIs",domain:"www.tiktok.com",strategy:d.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:t,help:`Number of suggestions (max ${s})`}],columns:["index","username","name","secUid","verified","followers","following","url"],func:y}),__test__={buildFriendsScript:o,DEFAULT_LIMIT:t,MAX_LIMIT:s};
@@ -1,9 +1,9 @@
1
- import{cli as l,Strategy as c}from"@jackwener/opencli/registry";import{EmptyResultError as d}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as m,LIVE_ITEM_NORMALIZER as u,SERVER_PAGE_MAX as f,TIKTOK_AID as v,requireLimit as p,throwTikTokPageContextError as y}from"./utils.js";const r=10,i=60;function o(e){return`
1
+ import{cli as l,Strategy as c}from"@jackwener/opencli/registry";import{EmptyResultError as d}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as m,LIVE_ITEM_NORMALIZER as u,SERVER_PAGE_MAX as f,TIKTOK_AID as y,requireLimit as k,throwTikTokPageContextError as p}from"./utils.js";const t=10,i=60;function o(e){return`
2
2
  (async () => {
3
3
  const limit = ${Number(e)};
4
4
  const SERVER_PAGE_MAX = ${f};
5
5
  const pageSize = limit < SERVER_PAGE_MAX ? limit : SERVER_PAGE_MAX;
6
- const aid = ${JSON.stringify(v)};
6
+ const aid = ${JSON.stringify(y)};
7
7
 
8
8
  ${m}
9
9
  ${u}
@@ -76,4 +76,4 @@ import{cli as l,Strategy as c}from"@jackwener/opencli/registry";import{EmptyResu
76
76
  }
77
77
  return rows;
78
78
  })()
79
- `}async function k(e,s){const a=p(s.limit,{fallback:r,max:i});await e.goto("https://www.tiktok.com/live",{waitUntil:"load",settleMs:5000});let t;try{t=await e.evaluate(o(a))}catch(n){y(n,{authMessage:"TikTok requires browser access to load live streams",emptyPattern:/No live streams returned/,emptyTarget:"tiktok live",failureMessage:"Failed to load TikTok live streams"})}if(!Array.isArray(t)||t.length===0)throw new d("tiktok live","TikTok returned no live streams");return t}export const liveCommand=l({site:"tiktok",name:"live",access:"read",description:"Browse TikTok live streams via page-context APIs",domain:"www.tiktok.com",strategy:c.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:r,help:`Number of streams (max ${i})`}],columns:["index","streamer","name","title","viewers","likes","secUid","url"],func:k}),__test__={buildLiveScript:o,DEFAULT_LIMIT:r,MAX_LIMIT:i};
79
+ `}async function v(e,s){const a=k(s.limit,{fallback:t,max:i});await e.goto("https://www.tiktok.com/live",{waitUntil:"load",settleMs:5000});let r;try{r=await e.evaluate(o(a))}catch(n){p(n,{authMessage:"TikTok requires browser access to load live streams",emptyPattern:/No live streams returned/,emptyTarget:"tiktok live",failureMessage:"Failed to load TikTok live streams"})}if(!Array.isArray(r)||r.length===0)throw new d("tiktok live","TikTok returned no live streams");return r}export const liveCommand=l({site:"tiktok",name:"live",access:"read",description:"Browse TikTok live streams via page-context APIs",domain:"www.tiktok.com",strategy:c.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:t,help:`Number of streams (max ${i})`}],columns:["index","streamer","name","title","viewers","likes","secUid","url"],func:v}),__test__={buildLiveScript:o,DEFAULT_LIMIT:t,MAX_LIMIT:i};
@@ -1,12 +1,12 @@
1
- import{cli as m,Strategy as d}from"@jackwener/opencli/registry";import{EmptyResultError as f}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as u,MAX_PAGES as p,NOTIFICATION_NORMALIZER as y,NOTIFICATION_TYPES as n,SERVER_PAGE_MAX as k,TIKTOK_AID as T,requireLimit as w,requireNotificationType as A,throwTikTokPageContextError as g}from"./utils.js";const r=15,a=100;function s(t,e){const i=n[e];return`
1
+ import{cli as m,Strategy as f}from"@jackwener/opencli/registry";import{EmptyResultError as d}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as u,MAX_PAGES as p,NOTIFICATION_NORMALIZER as y,NOTIFICATION_TYPES as n,SERVER_PAGE_MAX as T,TIKTOK_AID as w,requireLimit as k,requireNotificationType as A,throwTikTokPageContextError as _}from"./utils.js";const r=15,a=100;function s(t,i){const e=n[i];return`
2
2
  (async () => {
3
3
  const limit = ${Number(t)};
4
4
  const maxPages = ${p};
5
- const SERVER_PAGE_MAX = ${k};
5
+ const SERVER_PAGE_MAX = ${T};
6
6
  const pageSize = limit < SERVER_PAGE_MAX ? limit : SERVER_PAGE_MAX;
7
- const noticeType = ${Number(i.code)};
8
- const noticeLabel = ${JSON.stringify(i.label)};
9
- const aid = ${JSON.stringify(T)};
7
+ const noticeType = ${Number(e.code)};
8
+ const noticeLabel = ${JSON.stringify(e.label)};
9
+ const aid = ${JSON.stringify(w)};
10
10
 
11
11
  ${u}
12
12
  ${y}
@@ -74,4 +74,4 @@ import{cli as m,Strategy as d}from"@jackwener/opencli/registry";import{EmptyResu
74
74
  }
75
75
  return rows;
76
76
  })()
77
- `}async function _(t,e){const i=w(e.limit,{fallback:r,max:a}),c=A(e.type);await t.goto("https://www.tiktok.com/foryou",{waitUntil:"load",settleMs:5000});let o;try{o=await t.evaluate(s(i,c))}catch(l){g(l,{authMessage:"TikTok requires login to read notifications",emptyPattern:/No notifications returned/,emptyTarget:"tiktok notifications",failureMessage:"Failed to load TikTok notifications"})}if(!Array.isArray(o)||o.length===0)throw new f("tiktok notifications","TikTok returned no notifications");return o}export const notificationsCommand=m({site:"tiktok",name:"notifications",access:"read",description:"Read TikTok inbox notifications (likes, comments, mentions, followers) via page-context APIs",domain:"www.tiktok.com",strategy:d.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:r,help:`Number of notifications (max ${a})`},{name:"type",default:"all",help:"Notification type",choices:Object.keys(n)}],columns:["index","id","from","text","createTime"],func:_}),__test__={buildNotificationsScript:s,DEFAULT_LIMIT:r,MAX_LIMIT:a};
77
+ `}async function g(t,i){const e=k(i.limit,{fallback:r,max:a}),c=A(i.type);await t.goto("https://www.tiktok.com/foryou",{waitUntil:"load",settleMs:5000});let o;try{o=await t.evaluate(s(e,c))}catch(l){_(l,{authMessage:"TikTok requires login to read notifications",emptyPattern:/No notifications returned/,emptyTarget:"tiktok notifications",failureMessage:"Failed to load TikTok notifications"})}if(!Array.isArray(o)||o.length===0)throw new d("tiktok notifications","TikTok returned no notifications");return o}export const notificationsCommand=m({site:"tiktok",name:"notifications",access:"read",description:"Read TikTok inbox notifications (likes, comments, mentions, followers) via page-context APIs",domain:"www.tiktok.com",strategy:f.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:r,help:`Number of notifications (max ${a})`},{name:"type",default:"all",help:"Notification type",choices:Object.keys(n)}],columns:["index","id","from","text","createTime"],func:g}),__test__={buildNotificationsScript:s,DEFAULT_LIMIT:r,MAX_LIMIT:a};
@@ -1,10 +1,10 @@
1
- import{cli as V,Strategy as N}from"@jackwener/opencli/registry";import{ArgumentError as v,CommandExecutionError as Q}from"@jackwener/opencli/errors";import{resolveVideoFile as F,setVideoInput as j,unwrap as Z,parseScheduleDate as I,waitForUrlIncludes as x,waitForSelector as G,videoTimeoutArg as D}from"../_shared/video-publish.js";const P="https://www.tiktok.com/creator-center/upload",B=['input[type="file"][accept*="video"]','input[type="file"]'],M="div.public-DraftEditor-content",b="div.btn-post",y="#\\:r9\\:";async function f(q,z){return Boolean(Z(await q.evaluate(`((s) => !!document.querySelector(s))(${JSON.stringify(z)})`)))}async function U(q,z,H){await q.click(M);await q.pressKey("End");await q.pressKey("Control+a");await q.pressKey("Delete");await q.pressKey("End");await q.wait({time:1});await q.insertText(z);await q.wait({time:1});await q.pressKey("End");await q.pressKey("Enter");for(const J of H){await q.pressKey("End");await q.wait({time:1});await q.insertText(`#${J} `);await q.pressKey("Space");await q.wait({time:1});await q.pressKey("Backspace");await q.pressKey("End")}}async function L(q,z){const H=Date.now()+1800000;while(Date.now()<H){if(Z(await q.evaluate(`
1
+ import{cli as b,Strategy as p}from"@jackwener/opencli/registry";import{ArgumentError as T,CommandExecutionError as o}from"@jackwener/opencli/errors";import{resolveVideoFile as v,setVideoInput as m,unwrap as l,parseScheduleDate as x,waitForUrlIncludes as E,waitForSelector as w,videoTimeoutArg as q}from"../_shared/video-publish.js";const O="https://www.tiktok.com/creator-center/upload",h=['input[type="file"][accept*="video"]','input[type="file"]'],k="div.public-DraftEditor-content",f="div.btn-post",S="#\\:r9\\:";async function u(t,e){return Boolean(l(await t.evaluate(`((s) => !!document.querySelector(s))(${JSON.stringify(e)})`)))}async function D(t,e,i){await t.click(k);await t.pressKey("End");await t.pressKey("Control+a");await t.pressKey("Delete");await t.pressKey("End");await t.wait({time:1});await t.insertText(e);await t.wait({time:1});await t.pressKey("End");await t.pressKey("Enter");for(const r of i){await t.pressKey("End");await t.wait({time:1});await t.insertText(`#${r} `);await t.pressKey("Space");await t.wait({time:1});await t.pressKey("Backspace");await t.pressKey("End")}}async function _(t,e){const i=Date.now()+1800000;while(Date.now()<i){if(l(await t.evaluate(`
2
2
  (() => {
3
- const btn = document.querySelector('${b} > button');
3
+ const btn = document.querySelector('${f} > button');
4
4
  if (!btn) return null;
5
5
  return btn.getAttribute('disabled') === null;
6
6
  })()
7
- `))===!0)return;if(await f(q,'button[aria-label="Select file"]'))await j(q,['button[aria-label="Select file"] ~ input[type="file"]',...B],[z]);await q.wait({time:2})}throw new Q("TikTok 视频上传超时")}async function k(q,z){if(!Boolean(Z(await q.evaluate(`
7
+ `))===!0)return;if(await u(t,'button[aria-label="Select file"]'))await m(t,['button[aria-label="Select file"] ~ input[type="file"]',...h],[e]);await t.wait({time:2})}throw new o("TikTok 视频上传超时")}async function A(t,e){if(!Boolean(l(await t.evaluate(`
8
8
  (() => {
9
9
  const norm = (v) => (v || '').replace(/\\s+/g, ' ').trim();
10
10
  // get_by_label('Schedule')
@@ -18,7 +18,7 @@ import{cli as V,Strategy as N}from"@jackwener/opencli/registry";import{ArgumentE
18
18
  el.click();
19
19
  return true;
20
20
  })()
21
- `))))throw new Q("找不到 TikTok 定时发布开关 (Schedule)");await q.wait({time:1});const J=(Y)=>String(Y).padStart(2,"0"),$=z.getDate(),K=z.getMonth()+1,W=J(z.getHours()),A=J(Math.floor(z.getMinutes()/5)),X=Z(await q.evaluate(`
21
+ `))))throw new o("找不到 TikTok 定时发布开关 (Schedule)");await t.wait({time:1});const r=(d)=>String(d).padStart(2,"0"),c=e.getDate(),a=e.getMonth()+1,s=r(e.getHours()),y=r(Math.floor(e.getMinutes()/5)),n=l(await t.evaluate(`
22
22
  ((targetDay, targetMonth) => {
23
23
  const picker = document.querySelector('div.scheduled-picker');
24
24
  if (!picker) return { ok: false, reason: 'no scheduled-picker' };
@@ -29,54 +29,54 @@ import{cli as V,Strategy as N}from"@jackwener/opencli/registry";import{ArgumentE
29
29
  const MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];
30
30
  let curMonth = monthTitle ? (MONTHS.indexOf((monthTitle.innerText || '').trim()) + 1) : 0;
31
31
  return { ok: true, curMonth };
32
- })(${$}, ${K})
33
- `));if(!X?.ok)throw new Q(`TikTok 定时选择器异常: ${X?.reason||"unknown"}`);if(X.curMonth&&X.curMonth!==K){const Y=X.curMonth<K?"last":"first";await q.evaluate(`
32
+ })(${c}, ${a})
33
+ `));if(!n?.ok)throw new o(`TikTok 定时选择器异常: ${n?.reason||"unknown"}`);if(n.curMonth&&n.curMonth!==a){const d=n.curMonth<a?"last":"first";await t.evaluate(`
34
34
  (() => {
35
35
  const arrows = document.querySelectorAll('div.calendar-wrapper span.arrow');
36
36
  if (!arrows.length) return false;
37
- const a = ${Y==="last"?"arrows[arrows.length - 1]":"arrows[0]"};
37
+ const a = ${d==="last"?"arrows[arrows.length - 1]":"arrows[0]"};
38
38
  a.click();
39
39
  return true;
40
40
  })()
41
- `);await q.wait({time:0.5})}await q.evaluate(`
41
+ `);await t.wait({time:0.5})}await t.evaluate(`
42
42
  ((wantDay) => {
43
43
  const days = document.querySelectorAll('div.calendar-wrapper span.day.valid');
44
44
  for (const d of days) {
45
45
  if ((d.innerText || '').trim() === String(wantDay)) { d.click(); return true; }
46
46
  }
47
47
  return false;
48
- })(${$})
49
- `);await q.evaluate(`
48
+ })(${c})
49
+ `);await t.evaluate(`
50
50
  (() => {
51
51
  const picker = document.querySelector('div.scheduled-picker');
52
52
  const boxes = picker ? picker.querySelectorAll('div.TUXInputBox') : [];
53
53
  if (boxes[0]) boxes[0].click();
54
54
  })()
55
- `);await q.evaluate(`
55
+ `);await t.evaluate(`
56
56
  ((hourStr) => {
57
57
  for (const el of document.querySelectorAll('span.tiktok-timepicker-left')) {
58
58
  if ((el.innerText || '').includes(hourStr)) { el.click(); return true; }
59
59
  }
60
60
  return false;
61
- })(${JSON.stringify(W)})
62
- `);await q.wait({time:1});await q.evaluate(`
61
+ })(${JSON.stringify(s)})
62
+ `);await t.wait({time:1});await t.evaluate(`
63
63
  (() => {
64
64
  const picker = document.querySelector('div.scheduled-picker');
65
65
  const boxes = picker ? picker.querySelectorAll('div.TUXInputBox') : [];
66
66
  if (boxes[0]) boxes[0].click();
67
67
  })()
68
- `);await q.evaluate(`
68
+ `);await t.evaluate(`
69
69
  ((minuteStr) => {
70
70
  for (const el of document.querySelectorAll('span.tiktok-timepicker-right')) {
71
71
  if ((el.innerText || '').includes(minuteStr)) { el.click(); return true; }
72
72
  }
73
73
  return false;
74
- })(${JSON.stringify(A)})
75
- `);await q.evaluate(`
74
+ })(${JSON.stringify(y)})
75
+ `);await t.evaluate(`
76
76
  (() => {
77
77
  for (const h of document.querySelectorAll('h1')) {
78
78
  if ((h.innerText || '').includes('Upload video')) { h.click(); return true; }
79
79
  }
80
80
  return false;
81
81
  })()
82
- `)}async function R(q){const z=Date.now()+300000;while(Date.now()<z){if(await f(q,b))await q.evaluate(`(() => { const b = document.querySelector('${b}'); if (b) b.click(); })()`);await q.wait({time:1});if(await f(q,y))return;await q.wait({time:0.5})}if(await f(q,y))return;throw new Q("TikTok 发布未确认成功(未出现成功标识)")}V({site:"tiktok",name:"publish",access:"write",description:"Publish a video to TikTok (one command: upload + caption + publish; optional schedule)",domain:"www.tiktok.com",strategy:N.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"video",required:!0,positional:!0,help:"Video file path"},{name:"title",required:!0,help:"Caption / title text"},{name:"tags",default:"",help:"Comma-separated hashtags (without #)"},{name:"schedule",default:"",help:"Scheduled publish time (ISO8601 or Unix seconds); omit to post now"},D()],columns:["status","title","url"],func:async(q,z)=>{const H=String(z.title??"").trim();if(!H)throw new v("--title is required");const J=F(z.video),$=z.tags?String(z.tags).split(",").map((W)=>W.trim()).filter(Boolean):[],K=I(z.schedule);await q.goto(P);if(!await x(q,"tiktokstudio/upload",30000))throw new Q("未能进入 TikTok Studio 上传页(登录态可能失效,请先 ppcli tiktok login)");await G(q,'iframe[data-tt="Upload_index_iframe"], div.upload-container',1e4);await G(q,'input[type="file"]',15000);await j(q,B,[J]);if(!await G(q,M,60000))throw new Q("TikTok 文案编辑器未出现");await U(q,H,$);await L(q,J);if(K)await k(q,K);await R(q);return[{status:K?"✅ Scheduled":"✅ Published",title:H,url:await q.evaluate("() => location.href").then(Z)}]}});
82
+ `)}async function C(t){const e=Date.now()+300000;while(Date.now()<e){if(await u(t,f))await t.evaluate(`(() => { const b = document.querySelector('${f}'); if (b) b.click(); })()`);await t.wait({time:1});if(await u(t,S))return;await t.wait({time:0.5})}if(await u(t,S))return;throw new o("TikTok 发布未确认成功(未出现成功标识)")}b({site:"tiktok",name:"publish",access:"write",description:"Publish a video to TikTok (one command: upload + caption + publish; optional schedule)",domain:"www.tiktok.com",strategy:p.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"video",required:!0,positional:!0,help:"Video file path"},{name:"title",required:!0,help:"Caption / title text"},{name:"tags",default:"",help:"Comma-separated hashtags (without #)"},{name:"schedule",default:"",help:"Scheduled publish time (ISO8601 or Unix seconds); omit to post now"},q()],columns:["status","title","url"],func:async(t,e)=>{const i=String(e.title??"").trim();if(!i)throw new T("--title is required");const r=v(e.video),c=e.tags?String(e.tags).split(",").map((s)=>s.trim()).filter(Boolean):[],a=x(e.schedule);await t.goto(O);if(!await E(t,"tiktokstudio/upload",30000))throw new o("未能进入 TikTok Studio 上传页(登录态可能失效,请先 ppcli tiktok login)");await w(t,'iframe[data-tt="Upload_index_iframe"], div.upload-container',1e4);await w(t,'input[type="file"]',15000);await m(t,h,[r]);if(!await w(t,k,60000))throw new o("TikTok 文案编辑器未出现");await D(t,i,c);await _(t,r);if(a)await A(t,a);await C(t);return[{status:a?"✅ Scheduled":"✅ Published",title:i,url:await t.evaluate("() => location.href").then(l)}]}});
@@ -1,4 +1,4 @@
1
- import{cli as a,Strategy as u}from"@jackwener/opencli/registry";import{BROWSER_HELPERS as c,BUTTON_WALKER_HELPERS as w,RETRYABLE_HINTS as f,TIKTOK_HOST as n,normalizeUsername as d,throwButtonWalkerError as m}from"./utils.js";function l(o){return`
1
+ import{cli as a,Strategy as u}from"@jackwener/opencli/registry";import{BROWSER_HELPERS as c,BUTTON_WALKER_HELPERS as w,RETRYABLE_HINTS as L,TIKTOK_HOST as r,normalizeUsername as f,throwButtonWalkerError as E}from"./utils.js";function l(o){return`
2
2
  (async () => {
3
3
  const username = ${JSON.stringify(o)};
4
4
 
@@ -16,7 +16,7 @@ import{cli as a,Strategy as u}from"@jackwener/opencli/registry";import{BROWSER_H
16
16
 
17
17
  // Idempotent fast path: not currently following.
18
18
  if (!buttonExists(RELATION_LABELS) && buttonExists(FOLLOW_LABELS)) {
19
- return [{ username, url: ${JSON.stringify(n)} + '/@' + encodeURIComponent(username), result: 'already-not-following' }];
19
+ return [{ username, url: ${JSON.stringify(r)} + '/@' + encodeURIComponent(username), result: 'already-not-following' }];
20
20
  }
21
21
 
22
22
  const relationBtn = findButtonByText(RELATION_LABELS);
@@ -52,8 +52,8 @@ import{cli as a,Strategy as u}from"@jackwener/opencli/registry";import{BROWSER_H
52
52
 
53
53
  return [{
54
54
  username,
55
- url: ${JSON.stringify(n)} + '/@' + encodeURIComponent(username),
55
+ url: ${JSON.stringify(r)} + '/@' + encodeURIComponent(username),
56
56
  result: 'unfollowed',
57
57
  }];
58
58
  })()
59
- `}async function L(o,s){const e=d(s.username),i=(r)=>m(r,{authMessage:"TikTok requires login to unfollow users",failureMessage:`Failed to unfollow @${e}`,retryableHint:f.relationFailure});let t;try{await o.goto(`${n}/@${encodeURIComponent(e)}`,{waitUntil:"load",settleMs:5000});t=await o.evaluate(l(e))}catch(r){i(r)}if(!Array.isArray(t)||t.length===0)i(Error(`STATE_VERIFY_FAIL: unfollow returned no row for @${e}`));return t}export const unfollowCommand=a({site:"tiktok",name:"unfollow",access:"write",description:"Unfollow a TikTok user by username",domain:"www.tiktok.com",strategy:u.COOKIE,browser:!0,args:[{name:"username",required:!0,positional:!0,help:"TikTok username (without @)"}],columns:["username","url","result"],func:L}),__test__={buildUnfollowScript:l};
59
+ `}async function d(o,s){const t=f(s.username),i=(n)=>E(n,{authMessage:"TikTok requires login to unfollow users",failureMessage:`Failed to unfollow @${t}`,retryableHint:L.relationFailure});let e;try{await o.goto(`${r}/@${encodeURIComponent(t)}`,{waitUntil:"load",settleMs:5000});e=await o.evaluate(l(t))}catch(n){i(n)}if(!Array.isArray(e)||e.length===0)i(Error(`STATE_VERIFY_FAIL: unfollow returned no row for @${t}`));return e}export const unfollowCommand=a({site:"tiktok",name:"unfollow",access:"write",description:"Unfollow a TikTok user by username",domain:"www.tiktok.com",strategy:u.COOKIE,browser:!0,args:[{name:"username",required:!0,positional:!0,help:"TikTok username (without @)"}],columns:["username","url","result"],func:d}),__test__={buildUnfollowScript:l};
@@ -1,4 +1,4 @@
1
- import{cli as c,Strategy as d}from"@jackwener/opencli/registry";import{EmptyResultError as m}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as l,MAX_PAGES as f,SERVER_PAGE_MAX as p,TIKTOK_AID as h,VIDEO_ITEM_NORMALIZER as k,normalizeUsername as w,requireLimit as g,throwTikTokPageContextError as y}from"./utils.js";const i=20,s=120;function a(e,r){return`
1
+ import{cli as d,Strategy as c}from"@jackwener/opencli/registry";import{EmptyResultError as m}from"@jackwener/opencli/errors";import{BROWSER_HELPERS as l,MAX_PAGES as f,SERVER_PAGE_MAX as p,TIKTOK_AID as h,VIDEO_ITEM_NORMALIZER as k,normalizeUsername as w,requireLimit as g,throwTikTokPageContextError as y}from"./utils.js";const i=20,s=120;function a(e,r){return`
2
2
  (async () => {
3
3
  const username = ${JSON.stringify(e)};
4
4
  const usernameLower = username.toLowerCase();
@@ -140,4 +140,4 @@ import{cli as c,Strategy as d}from"@jackwener/opencli/registry";import{EmptyResu
140
140
  }
141
141
  return rows;
142
142
  })()
143
- `}async function T(e,r){const o=w(r.username),n=g(r.limit,{fallback:i,max:s});await e.goto(`https://www.tiktok.com/@${encodeURIComponent(o)}`,{waitUntil:"load",settleMs:6000});let t;try{t=await e.evaluate(a(o,n))}catch(u){y(u,{authMessage:"TikTok requires browser access to load user videos",emptyPattern:/No videos found/,emptyTarget:"tiktok user",failureMessage:"Failed to fetch TikTok user videos"})}if(!Array.isArray(t)||t.length===0)throw new m("tiktok user",`No videos found for @${o}`);return t}export const userCommand=c({site:"tiktok",name:"user",access:"read",description:"Get recent videos from a TikTok user via page-context APIs",domain:"www.tiktok.com",strategy:d.COOKIE,browser:!0,args:[{name:"username",required:!0,positional:!0,help:"TikTok username (without @)"},{name:"limit",type:"int",default:i,help:`Number of videos to return (max ${s})`}],columns:["index","id","source","author","url","cover","title","desc","plays","likes","comments","shares","createTime"],func:T}),__test__={buildUserScript:a,DEFAULT_LIMIT:i,MAX_LIMIT:s};
143
+ `}async function S(e,r){const o=w(r.username),n=g(r.limit,{fallback:i,max:s});await e.goto(`https://www.tiktok.com/@${encodeURIComponent(o)}`,{waitUntil:"load",settleMs:6000});let t;try{t=await e.evaluate(a(o,n))}catch(u){y(u,{authMessage:"TikTok requires browser access to load user videos",emptyPattern:/No videos found/,emptyTarget:"tiktok user",failureMessage:"Failed to fetch TikTok user videos"})}if(!Array.isArray(t)||t.length===0)throw new m("tiktok user",`No videos found for @${o}`);return t}export const userCommand=d({site:"tiktok",name:"user",access:"read",description:"Get recent videos from a TikTok user via page-context APIs",domain:"www.tiktok.com",strategy:c.COOKIE,browser:!0,args:[{name:"username",required:!0,positional:!0,help:"TikTok username (without @)"},{name:"limit",type:"int",default:i,help:`Number of videos to return (max ${s})`}],columns:["index","id","source","author","url","cover","title","desc","plays","likes","comments","shares","createTime"],func:S}),__test__={buildUserScript:a,DEFAULT_LIMIT:i,MAX_LIMIT:s};
@@ -1,4 +1,4 @@
1
- import{ArgumentError as L,AuthRequiredError as W,CommandExecutionError as V,EmptyResultError as $,getErrorMessage as Z}from"@jackwener/opencli/errors";export const TIKTOK_AID="1988",TIKTOK_HOST="https://www.tiktok.com",SERVER_PAGE_MAX=30,MAX_PAGES=4;export function requireLimit(B,{fallback:z,max:D,name:G="limit"}){const J=Number(B??z);if(!Number.isInteger(J)||J<=0)throw new L(`${G} must be a positive integer`,`Example: --${G} ${z}`);if(J>D)throw new L(`${G} must be <= ${D}`,`Example: --${G} ${D}`);return J}export function normalizeUsername(B){const z=String(B??"").trim().replace(/^@+/,"");if(!z)throw new L("username is required","Example: ppcli tiktok following <username>");if(!/^[A-Za-z0-9._-]+$/.test(z))throw new L("username contains unsupported characters","Pass the TikTok handle without @, for example: dictogo");return z}export const NOTIFICATION_TYPES={all:{code:0,label:"all"},likes:{code:3,label:"likes"},comments:{code:7,label:"comments"},mentions:{code:6,label:"mentions"},followers:{code:4,label:"followers"}};export function requireNotificationType(B){const z=String(B??"all").trim().toLowerCase();if(!Object.prototype.hasOwnProperty.call(NOTIFICATION_TYPES,z))throw new L(`unsupported notification type: ${B}`,`Allowed: ${Object.keys(NOTIFICATION_TYPES).join(", ")}`);return z}export const COMMENT_TEXT_MAX=150;export function requireCommentText(B){const z=String(B??"").trim();if(!z)throw new L("comment text is required",'Example: ppcli tiktok comment <url> "great video"');if(z.length>COMMENT_TEXT_MAX)throw new L(`comment text must be <= ${COMMENT_TEXT_MAX} characters (got ${z.length})`,"TikTok rejects long comments at submit time; trim before retrying");return z}export function parseTikTokVideoUrl(B){const z=String(B??"").trim();if(!z)throw new L("video URL is required",'Example: ppcli tiktok comment https://www.tiktok.com/@user/video/1234567890 "..."');let D;try{D=new URL(z)}catch{throw new L(`invalid video URL: ${z}`,"Example: https://www.tiktok.com/@user/video/1234567890")}if(!/(^|\.)tiktok\.com$/i.test(D.hostname))throw new L(`URL must be on tiktok.com (got ${D.hostname})`,"Example: https://www.tiktok.com/@user/video/1234567890");const G=D.pathname.match(/^\/@([A-Za-z0-9._-]+)\/video\/(\d+)\/?$/);if(!G)throw new L("URL must follow /@<username>/video/<id> format","Example: https://www.tiktok.com/@user/video/1234567890");return{url:D.toString(),username:G[1],videoId:G[2]}}export function looksTikTokAuthFailure(B){return/\bAUTH_REQUIRED\b|\b(auth|captcha|login|log in|permission|unauthori[sz]ed|forbidden)\b|HTTP\s+(401|403)\b/i.test(String(B||""))}export function looksTikTokUpstreamFailure(B){return/\b(API failed|HTTP\s+\d+|invalid JSON|Failed to fetch|network|fetch)\b/i.test(String(B||""))}export function throwTikTokPageContextError(B,{authMessage:z,emptyPattern:D,emptyTarget:G,failureMessage:Q}){const J=Z(B);if(looksTikTokAuthFailure(J))throw new W("tiktok.com",z);if(looksTikTokUpstreamFailure(J))throw new V(`${Q}: ${J}`);if(D.test(J))throw new $(G,J);throw new V(`${Q}: ${J}`)}export const BUTTON_WALKER_SENTINELS={AUTH_REQUIRED:"AUTH_REQUIRED",BUTTON_NOT_FOUND:"BUTTON_NOT_FOUND",STATE_VERIFY_FAIL:"STATE_VERIFY_FAIL",RATE_LIMITED:"RATE_LIMITED"},RETRYABLE_HINTS={commentFailure:"retryable=false reason=server-fan-out — TikTok may have accepted the comment but state verification timed out; do NOT auto-retry",relationFailure:"retryable=true reason=idempotent — TikTok dedupes follow/unfollow on retry; safe to re-run"};export function throwButtonWalkerError(B,{authMessage:z,failureMessage:D,retryableHint:G}){const Q=Z(B);if(/\bRATE_LIMITED\b|\b(captcha|too many requests|rate limit|try again later|slow down)\b/i.test(Q))throw new V(`${D}: ${Q}`,G);if(looksTikTokAuthFailure(Q))throw new W("tiktok.com",z);throw new V(`${D}: ${Q}`,G)}export const BROWSER_HELPERS=`
1
+ import{ArgumentError as i,AuthRequiredError as u,CommandExecutionError as a,EmptyResultError as m,getErrorMessage as c}from"@jackwener/opencli/errors";export const TIKTOK_AID="1988",TIKTOK_HOST="https://www.tiktok.com",SERVER_PAGE_MAX=30,MAX_PAGES=4;export function requireLimit(t,{fallback:e,max:r,name:o="limit"}){const n=Number(t??e);if(!Number.isInteger(n)||n<=0)throw new i(`${o} must be a positive integer`,`Example: --${o} ${e}`);if(n>r)throw new i(`${o} must be <= ${r}`,`Example: --${o} ${r}`);return n}export function normalizeUsername(t){const e=String(t??"").trim().replace(/^@+/,"");if(!e)throw new i("username is required","Example: ppcli tiktok following <username>");if(!/^[A-Za-z0-9._-]+$/.test(e))throw new i("username contains unsupported characters","Pass the TikTok handle without @, for example: dictogo");return e}export const NOTIFICATION_TYPES={all:{code:0,label:"all"},likes:{code:3,label:"likes"},comments:{code:7,label:"comments"},mentions:{code:6,label:"mentions"},followers:{code:4,label:"followers"}};export function requireNotificationType(t){const e=String(t??"all").trim().toLowerCase();if(!Object.prototype.hasOwnProperty.call(NOTIFICATION_TYPES,e))throw new i(`unsupported notification type: ${t}`,`Allowed: ${Object.keys(NOTIFICATION_TYPES).join(", ")}`);return e}export const COMMENT_TEXT_MAX=150;export function requireCommentText(t){const e=String(t??"").trim();if(!e)throw new i("comment text is required",'Example: ppcli tiktok comment <url> "great video"');if(e.length>COMMENT_TEXT_MAX)throw new i(`comment text must be <= ${COMMENT_TEXT_MAX} characters (got ${e.length})`,"TikTok rejects long comments at submit time; trim before retrying");return e}export function parseTikTokVideoUrl(t){const e=String(t??"").trim();if(!e)throw new i("video URL is required",'Example: ppcli tiktok comment https://www.tiktok.com/@user/video/1234567890 "..."');let r;try{r=new URL(e)}catch{throw new i(`invalid video URL: ${e}`,"Example: https://www.tiktok.com/@user/video/1234567890")}if(!/(^|\.)tiktok\.com$/i.test(r.hostname))throw new i(`URL must be on tiktok.com (got ${r.hostname})`,"Example: https://www.tiktok.com/@user/video/1234567890");const o=r.pathname.match(/^\/@([A-Za-z0-9._-]+)\/video\/(\d+)\/?$/);if(!o)throw new i("URL must follow /@<username>/video/<id> format","Example: https://www.tiktok.com/@user/video/1234567890");return{url:r.toString(),username:o[1],videoId:o[2]}}export function looksTikTokAuthFailure(t){return/\bAUTH_REQUIRED\b|\b(auth|captcha|login|log in|permission|unauthori[sz]ed|forbidden)\b|HTTP\s+(401|403)\b/i.test(String(t||""))}export function looksTikTokUpstreamFailure(t){return/\b(API failed|HTTP\s+\d+|invalid JSON|Failed to fetch|network|fetch)\b/i.test(String(t||""))}export function throwTikTokPageContextError(t,{authMessage:e,emptyPattern:r,emptyTarget:o,failureMessage:s}){const n=c(t);if(looksTikTokAuthFailure(n))throw new u("tiktok.com",e);if(looksTikTokUpstreamFailure(n))throw new a(`${s}: ${n}`);if(r.test(n))throw new m(o,n);throw new a(`${s}: ${n}`)}export const BUTTON_WALKER_SENTINELS={AUTH_REQUIRED:"AUTH_REQUIRED",BUTTON_NOT_FOUND:"BUTTON_NOT_FOUND",STATE_VERIFY_FAIL:"STATE_VERIFY_FAIL",RATE_LIMITED:"RATE_LIMITED"},RETRYABLE_HINTS={commentFailure:"retryable=false reason=server-fan-out — TikTok may have accepted the comment but state verification timed out; do NOT auto-retry",relationFailure:"retryable=true reason=idempotent — TikTok dedupes follow/unfollow on retry; safe to re-run"};export function throwButtonWalkerError(t,{authMessage:e,failureMessage:r,retryableHint:o}){const s=c(t);if(/\bRATE_LIMITED\b|\b(captcha|too many requests|rate limit|try again later|slow down)\b/i.test(s))throw new a(`${r}: ${s}`,o);if(looksTikTokAuthFailure(s))throw new u("tiktok.com",e);throw new a(`${r}: ${s}`,o)}export const BROWSER_HELPERS=`
2
2
  function asNumber(value) {
3
3
  if (value === null || value === undefined || value === '') return null;
4
4
  const n = Number(value);
@@ -1 +1 @@
1
- import{CliError as W,CommandExecutionError as v}from"@jackwener/opencli/errors";import{cli as j,Strategy as k}from"@jackwener/opencli/registry";import{publishArticle as w}from"../_shared/article/publish.js";import{readFile as n,stat as f}from"node:fs/promises";function p(L){if(!L.execute)throw new W("INVALID_INPUT","此头条号写操作需要 --execute 参数才能真正发布。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}async function m(L){const J=typeof L.text==="string"?L.text:void 0,B=typeof L.file==="string"?L.file:void 0;if(J&&B)throw new W("INVALID_INPUT","正文和 --file 只能选一个");let D=J??"";if(B){let V;try{V=await f(B)}catch{throw new W("INVALID_INPUT",`找不到文件: ${B}`)}if(!V.isFile())throw new W("INVALID_INPUT",`--file 必须是可读文本文件: ${B}`);let Y;try{Y=await n(B)}catch{throw new W("INVALID_INPUT",`文件无法读取: ${B}`)}try{D=new TextDecoder("utf-8",{fatal:!0}).decode(Y)}catch{throw new W("INVALID_INPUT",`文件必须是 UTF-8 编码: ${B}`)}}if(!D.trim())throw new W("INVALID_INPUT","正文不能为空");return D}function u(L,J,B,D,V={}){return[{status:"success",outcome:D,message:L,target_type:J,target:B,...V}]}export const toutiaoProfile={home:"https://mp.toutiao.com/profile_v3/graphic/publish",outputFormat:"html",preprocessConfig:{},publish:async(L,J)=>{const B=L.params||{},D=[],V=[];async function Y(z,O){const M="/spice/image?upload_source="+O+"&need_enhance=true&aid=1231&device_platform=web",G=new FormData;let H;if(/^https?:/i.test(z)){G.append("imageUrl",z);H=await fetch(M+"&scene=paste",{method:"POST",credentials:"include",body:G})}else{const F=await fetch(z,{credentials:"omit"});if(!F.ok)throw Error("图片下载失败 HTTP "+F.status+":"+z.slice(0,80));const x=await F.blob(),I=((x.type||"").split("/")[1]||"jpg").split("+")[0].split(";")[0]||"jpg";G.append("image",x,"image."+I);H=await fetch(M,{method:"POST",credentials:"include",body:G})}const Q=await H.json(),A=Q&&Q.data;if(!Q||Q.code!==0||!A||!A.image_uri)throw Error((Q&&Q.message||"图片上传失败")+(Q&&Q.code!=null?"(接口 code "+Q.code+")":""));return{uri:A.image_uri,url:A.image_url,width:A.image_width,height:A.image_height}}async function R(z){const O=new FormData;O.append("imageUrl",z);const G=await(await fetch("/spice/image?upload_source=20020003&aid=1231&device_platform=web&need_cover_url=1",{method:"POST",credentials:"include",body:O})).json(),H=G&&G.data;if(!G||G.code!==0||!H||!H.image_uri)throw Error((G&&G.message||"封面图生成失败")+(G&&G.code!=null?"(接口 code "+G.code+")":""));return{uri:H.image_uri,url:H.image_url,width:H.image_width,height:H.image_height}}const Z=document.createElement("div");Z.innerHTML=L.content;const q=Array.prototype.slice.call(Z.querySelectorAll("img"));let X=null;for(const z of q){const O=z.getAttribute("src")||"";if(!O){z.remove();continue}let M;try{M=await Y(O,20020002)}catch(F){V.push({src:O.slice(0,120),error:String(F&&F.message||F)});z.remove();continue}D.push({src:O.slice(0,120),url:M.url});if(!X)X=M;const G=document.createElement("div");G.className="pgc-img";const H=document.createElement("img");H.setAttribute("src",M.url);H.setAttribute("class","");H.setAttribute("image_type","");H.setAttribute("mime_type","");H.setAttribute("web_uri",M.uri);H.setAttribute("img_width",String(M.width));H.setAttribute("img_height",String(M.height));const Q=document.createElement("p");Q.className="pgc-img-caption";G.appendChild(H);G.appendChild(Q);(z.parentElement||Z).replaceChild(G,z)}const y=Z.innerHTML,U=[];let $=null,T="";if(B.cover&&String(B.cover).trim())try{$=await Y(String(B.cover),20020002)}catch(z){return{ok:!1,stage:"cover",message:"封面图转存失败:"+String(z&&z.message||z),uploaded:D,failed:V}}else if(X){$=X;T=X.uri}if($){let z;try{z=await R($.url)}catch(M){return{ok:!1,stage:"cover",message:"封面图生成失败:"+String(M&&M.message||M),uploaded:D,failed:V}}const O={url:z.url,uri:z.uri,width:z.width,height:z.height,thumb_width:z.width,thumb_height:z.height,natural_width:$.width,natural_height:$.height,back_up_url:$.url,need_check:!1,paste:!1,auto_upload:!1,show_optimize_icon:!1,ic:!1,id:0,pos:0};if(T)O.extra={from_content:"1",from_content_uri:T};U.push(O)}await fetch("https://mp.toutiao.com/profile_v4/graphic/publish",{credentials:"include"});function b(){const z=document.cookie.match(/passport_csrf_token=([^;]+)/);return z?z[1]:""}const _=b(),S=new URLSearchParams({title:L.title,article_ad_type:"2",article_type:"0",from_diagnosis:"0",origin_debut_check_pgc_normal:"0",tree_plan_article:"0",save:"1",pgc_id:"0",content:y,pgc_feed_covers:JSON.stringify(U)}),h={"Content-Type":"application/x-www-form-urlencoded"};if(_)h["X-CSRFToken"]=_;const P=await fetch("https://mp.toutiao.com/mp/agw/article/publish?source=mp&type=article&aid=1231",{method:"POST",credentials:"include",headers:h,body:S});let K=null;try{K=await P.json()}catch(z){}const E=K&&(K.code===0||K.err_no===0),N=K&&K.data&&K.data.pgc_id;if(!E||!N||String(N)==="0"){let z=K&&(K.message||K.reason)||"头条号发布失败";if(K&&(K.code===7112||K.err_no===7112))z+="(code 7112「图片URI异常」:正文图或封面图不是头条编辑器图床里的资源。"+"若本次有图片转存失败(见 failed 列表),先解决那张图再发)";if(K&&(K.code===7050||K.err_no===7050))z+="(code 7050「保存失败」:内容可能被风控拦截或账号被平台限制发文,"+"请登录 mp.toutiao.com 查看站内通知)";return{ok:!1,stage:"publish",status:P.status,message:z,detail:K,uploaded:D,failed:V}}const C="https://www.toutiao.com/article/"+String(N)+"/";return{ok:!0,id:String(N),url:C,editUrl:"https://mp.toutiao.com/profile_v4/graphic/publish?pgc_id="+String(N),draft:!1,uploaded:D,failed:V}},checkAuth:async(L)=>{try{const B=await(await fetch("https://mp.toutiao.com/mp/agw/media/get_media_info",{credentials:"include"})).json(),D=B&&B.data&&B.data.user;if(B&&B.code===0&&D&&D.id)return{isAuthenticated:!0,userId:String(D.id),username:D.screen_name||D.name||"",avatar:D.https_avatar_url||D.avatar_url||""};return{isAuthenticated:!1}}catch(J){return{isAuthenticated:!1,error:String(J&&J.message||J)}}}};j({site:"toutiao",name:"article",access:"write",description:"正式发布头条号图文文章(会立即公开,头条无可靠的存草稿接口,故不支持草稿)。正文默认 Markdown,图片自动转存到头条图床。标题需 2~30 字;封面可选(--cover,不传则头条自动从正文图选封面)。",domain:"mp.toutiao.com",strategy:k.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题(2~30 字)"},{name:"text",positional:!0,help:"文章正文(默认 Markdown;传 --html 则视为原始 HTML)"},{name:"file",help:"正文文件路径(UTF-8,默认 Markdown)"},{name:"html",type:"boolean",help:"将正文视为原始 HTML 而非 Markdown"},{name:"cover",help:"封面图 URL 或本机路径(可选;会先转存到头条图床)"},{name:"execute",type:"boolean",help:"真正执行写操作。不加此参数时命令拒绝写入。"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(L,J)=>{if(!L)throw new v("头条号文章发布需要浏览器会话");p(J);const B=String(J.title??"").trim();if(!B)throw new W("INVALID_INPUT","文章标题不能为空");if(B.length<2||B.length>30)throw new W("INVALID_INPUT",`头条号标题需 2~30 字,当前 ${B.length} 字`);const D=await m(J),Y={cover:typeof J.cover==="string"?J.cover.trim():""},R=await w(L,{title:B,body:D,format:J.html?"html":"markdown",profile:toutiaoProfile,publishParams:Y}),Z=R.images.uploaded.length|0,q=R.images.failed.length|0;let X="已正式发布头条号文章";if(Z||q)X+=`(图片:${Z} 张已转存${q?`,${q} 张失败`:""})`;return u(X,"article","","created",{created_target:"article:"+R.id,created_url:R.url})}});
1
+ import{CliError as m,CommandExecutionError as D}from"@jackwener/opencli/errors";import{cli as j,Strategy as V}from"@jackwener/opencli/registry";import{publishArticle as F}from"../_shared/article/publish.js";import{readFile as M,stat as O}from"node:fs/promises";function R(c){if(!c.execute)throw new m("INVALID_INPUT","此头条号写操作需要 --execute 参数才能真正发布。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}async function H(c){const a=typeof c.text==="string"?c.text:void 0,t=typeof c.file==="string"?c.file:void 0;if(a&&t)throw new m("INVALID_INPUT","正文和 --file 只能选一个");let i=a??"";if(t){let d;try{d=await O(t)}catch{throw new m("INVALID_INPUT",`找不到文件: ${t}`)}if(!d.isFile())throw new m("INVALID_INPUT",`--file 必须是可读文本文件: ${t}`);let p;try{p=await M(t)}catch{throw new m("INVALID_INPUT",`文件无法读取: ${t}`)}try{i=new TextDecoder("utf-8",{fatal:!0}).decode(p)}catch{throw new m("INVALID_INPUT",`文件必须是 UTF-8 编码: ${t}`)}}if(!i.trim())throw new m("INVALID_INPUT","正文不能为空");return i}function q(c,a,t,i,d={}){return[{status:"success",outcome:i,message:c,target_type:a,target:t,...d}]}export const toutiaoProfile={home:"https://mp.toutiao.com/profile_v3/graphic/publish",outputFormat:"html",preprocessConfig:{},publish:async(c,a)=>{const t=c.params||{},i=[],d=[];async function p(e,l){const s="/spice/image?upload_source="+l+"&need_enhance=true&aid=1231&device_platform=web",r=new FormData;let o;if(/^https?:/i.test(e)){r.append("imageUrl",e);o=await fetch(s+"&scene=paste",{method:"POST",credentials:"include",body:r})}else{const w=await fetch(e,{credentials:"omit"});if(!w.ok)throw Error("图片下载失败 HTTP "+w.status+":"+e.slice(0,80));const P=await w.blob(),k=((P.type||"").split("/")[1]||"jpg").split("+")[0].split(";")[0]||"jpg";r.append("image",P,"image."+k);o=await fetch(s,{method:"POST",credentials:"include",body:r})}const u=await o.json(),_=u&&u.data;if(!u||u.code!==0||!_||!_.image_uri)throw Error((u&&u.message||"图片上传失败")+(u&&u.code!=null?"(接口 code "+u.code+")":""));return{uri:_.image_uri,url:_.image_url,width:_.image_width,height:_.image_height}}async function y(e){const l=new FormData;l.append("imageUrl",e);const r=await(await fetch("/spice/image?upload_source=20020003&aid=1231&device_platform=web&need_cover_url=1",{method:"POST",credentials:"include",body:l})).json(),o=r&&r.data;if(!r||r.code!==0||!o||!o.image_uri)throw Error((r&&r.message||"封面图生成失败")+(r&&r.code!=null?"(接口 code "+r.code+")":""));return{uri:o.image_uri,url:o.image_url,width:o.image_width,height:o.image_height}}const g=document.createElement("div");g.innerHTML=c.content;const b=Array.prototype.slice.call(g.querySelectorAll("img"));let h=null;for(const e of b){const l=e.getAttribute("src")||"";if(!l){e.remove();continue}let s;try{s=await p(l,20020002)}catch(w){d.push({src:l.slice(0,120),error:String(w&&w.message||w)});e.remove();continue}i.push({src:l.slice(0,120),url:s.url});if(!h)h=s;const r=document.createElement("div");r.className="pgc-img";const o=document.createElement("img");o.setAttribute("src",s.url);o.setAttribute("class","");o.setAttribute("image_type","");o.setAttribute("mime_type","");o.setAttribute("web_uri",s.uri);o.setAttribute("img_width",String(s.width));o.setAttribute("img_height",String(s.height));const u=document.createElement("p");u.className="pgc-img-caption";r.appendChild(o);r.appendChild(u);(e.parentElement||g).replaceChild(r,e)}const U=g.innerHTML,T=[];let f=null,I="";if(t.cover&&String(t.cover).trim())try{f=await p(String(t.cover),20020002)}catch(e){return{ok:!1,stage:"cover",message:"封面图转存失败:"+String(e&&e.message||e),uploaded:i,failed:d}}else if(h){f=h;I=h.uri}if(f){let e;try{e=await y(f.url)}catch(s){return{ok:!1,stage:"cover",message:"封面图生成失败:"+String(s&&s.message||s),uploaded:i,failed:d}}const l={url:e.url,uri:e.uri,width:e.width,height:e.height,thumb_width:e.width,thumb_height:e.height,natural_width:f.width,natural_height:f.height,back_up_url:f.url,need_check:!1,paste:!1,auto_upload:!1,show_optimize_icon:!1,ic:!1,id:0,pos:0};if(I)l.extra={from_content:"1",from_content_uri:I};T.push(l)}await fetch("https://mp.toutiao.com/profile_v4/graphic/publish",{credentials:"include"});function x(){const e=document.cookie.match(/passport_csrf_token=([^;]+)/);return e?e[1]:""}const S=x(),L=new URLSearchParams({title:c.title,article_ad_type:"2",article_type:"0",from_diagnosis:"0",origin_debut_check_pgc_normal:"0",tree_plan_article:"0",save:"1",pgc_id:"0",content:U,pgc_feed_covers:JSON.stringify(T)}),A={"Content-Type":"application/x-www-form-urlencoded"};if(S)A["X-CSRFToken"]=S;const N=await fetch("https://mp.toutiao.com/mp/agw/article/publish?source=mp&type=article&aid=1231",{method:"POST",credentials:"include",headers:A,body:L});let n=null;try{n=await N.json()}catch(e){}const C=n&&(n.code===0||n.err_no===0),v=n&&n.data&&n.data.pgc_id;if(!C||!v||String(v)==="0"){let e=n&&(n.message||n.reason)||"头条号发布失败";if(n&&(n.code===7112||n.err_no===7112))e+="(code 7112「图片URI异常」:正文图或封面图不是头条编辑器图床里的资源。"+"若本次有图片转存失败(见 failed 列表),先解决那张图再发)";if(n&&(n.code===7050||n.err_no===7050))e+="(code 7050「保存失败」:内容可能被风控拦截或账号被平台限制发文,"+"请登录 mp.toutiao.com 查看站内通知)";return{ok:!1,stage:"publish",status:N.status,message:e,detail:n,uploaded:i,failed:d}}const E="https://www.toutiao.com/article/"+String(v)+"/";return{ok:!0,id:String(v),url:E,editUrl:"https://mp.toutiao.com/profile_v4/graphic/publish?pgc_id="+String(v),draft:!1,uploaded:i,failed:d}},checkAuth:async(c)=>{try{const t=await(await fetch("https://mp.toutiao.com/mp/agw/media/get_media_info",{credentials:"include"})).json(),i=t&&t.data&&t.data.user;if(t&&t.code===0&&i&&i.id)return{isAuthenticated:!0,userId:String(i.id),username:i.screen_name||i.name||"",avatar:i.https_avatar_url||i.avatar_url||""};return{isAuthenticated:!1}}catch(a){return{isAuthenticated:!1,error:String(a&&a.message||a)}}}};j({site:"toutiao",name:"article",access:"write",description:"正式发布头条号图文文章(会立即公开,头条无可靠的存草稿接口,故不支持草稿)。正文默认 Markdown,图片自动转存到头条图床。标题需 2~30 字;封面可选(--cover,不传则头条自动从正文图选封面)。",domain:"mp.toutiao.com",strategy:V.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题(2~30 字)"},{name:"text",positional:!0,help:"文章正文(默认 Markdown;传 --html 则视为原始 HTML)"},{name:"file",help:"正文文件路径(UTF-8,默认 Markdown)"},{name:"html",type:"boolean",help:"将正文视为原始 HTML 而非 Markdown"},{name:"cover",help:"封面图 URL 或本机路径(可选;会先转存到头条图床)"},{name:"execute",type:"boolean",help:"真正执行写操作。不加此参数时命令拒绝写入。"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(c,a)=>{if(!c)throw new D("头条号文章发布需要浏览器会话");R(a);const t=String(a.title??"").trim();if(!t)throw new m("INVALID_INPUT","文章标题不能为空");if(t.length<2||t.length>30)throw new m("INVALID_INPUT",`头条号标题需 2~30 字,当前 ${t.length} 字`);const i=await H(a),p={cover:typeof a.cover==="string"?a.cover.trim():""},y=await F(c,{title:t,body:i,format:a.html?"html":"markdown",profile:toutiaoProfile,publishParams:p}),g=y.images.uploaded.length|0,b=y.images.failed.length|0;let h="已正式发布头条号文章";if(g||b)h+=`(图片:${g} 张已转存${b?`,${b} 张失败`:""})`;return q(h,"article","","created",{created_target:"article:"+y.id,created_url:y.url})}});
@@ -1,4 +1,4 @@
1
- import{cli as L,Strategy as M}from"@jackwener/opencli/registry";import{AuthRequiredError as N,CommandExecutionError as O,EmptyResultError as Q}from"@jackwener/opencli/errors";import{looksToutiaoAuthWallUrl as V,parseArticlesPage as H,parseToutiaoArticlesText}from"./utils.js";L({site:"toutiao",name:"articles",access:"read",description:"获取头条号创作者后台文章列表及数据",domain:"mp.toutiao.com",strategy:M.COOKIE,browser:!0,args:[{name:"page",type:"int",default:1,help:"页码 (1-4)"}],columns:["title","date","status","展现","阅读","点赞","评论"],func:async(z,I)=>{const B=H(I.page,1);let v;try{await z.goto(`https://mp.toutiao.com/profile_v4/manage/content/all?page=${B}`);await z.wait("networkidle");await z.wait(3);v=await z.evaluate(`
1
+ import{cli as l,Strategy as m}from"@jackwener/opencli/registry";import{AuthRequiredError as d,CommandExecutionError as p,EmptyResultError as h}from"@jackwener/opencli/errors";import{looksToutiaoAuthWallUrl as f,parseArticlesPage as s,parseToutiaoArticlesText}from"./utils.js";l({site:"toutiao",name:"articles",access:"read",description:"获取头条号创作者后台文章列表及数据",domain:"mp.toutiao.com",strategy:m.COOKIE,browser:!0,args:[{name:"page",type:"int",default:1,help:"页码 (1-4)"}],columns:["title","date","status","展现","阅读","点赞","评论"],func:async(e,n)=>{const a=s(n.page,1);let t;try{await e.goto(`https://mp.toutiao.com/profile_v4/manage/content/all?page=${a}`);await e.wait("networkidle");await e.wait(3);t=await e.evaluate(`
2
2
  (async () => {
3
3
  await new Promise(r => setTimeout(r, 2000));
4
4
  var href = ''; try { href = location.href; } catch (e) {}
@@ -12,4 +12,4 @@ import{cli as L,Strategy as M}from"@jackwener/opencli/registry";import{AuthRequi
12
12
  } catch (e) {}
13
13
  return { href: href, text: document.body.innerText || '', authed: authed };
14
14
  })()
15
- `)}catch(G){throw new O(`toutiao articles render failed: ${G?.message||G}`)}const J=typeof v==="string"?v:v?.text||"",K=typeof v==="string"?"":v?.href||"",D=typeof v==="string"?null:v?.authed??null;if(V(K)||D===!1)throw new N("mp.toutiao.com","Toutiao creator articles require a logged-in mp.toutiao.com browser session");const F=parseToutiaoArticlesText(J);if(F.length===0)throw new Q("toutiao articles",D===!0?`账号登录态已通过接口确认有效,但未抓取到创作者后台文章 (page=${B}):该页可能确实没有文章,或页面尚未渲染完成。这不是登录问题,不要据此判断会话失效。`:`未抓取到创作者后台文章 (page=${B})。可能页面尚未完成渲染或无文章。`);return F}});export{parseToutiaoArticlesText};export const __test__={parseToutiaoArticlesText,parseArticlesPage:H};
15
+ `)}catch(i){throw new p(`toutiao articles render failed: ${i?.message||i}`)}const u=typeof t==="string"?t:t?.text||"",c=typeof t==="string"?"":t?.href||"",o=typeof t==="string"?null:t?.authed??null;if(f(c)||o===!1)throw new d("mp.toutiao.com","Toutiao creator articles require a logged-in mp.toutiao.com browser session");const r=parseToutiaoArticlesText(u);if(r.length===0)throw new h("toutiao articles",o===!0?`账号登录态已通过接口确认有效,但未抓取到创作者后台文章 (page=${a}):该页可能确实没有文章,或页面尚未渲染完成。这不是登录问题,不要据此判断会话失效。`:`未抓取到创作者后台文章 (page=${a})。可能页面尚未完成渲染或无文章。`);return r}});export{parseToutiaoArticlesText};export const __test__={parseToutiaoArticlesText,parseArticlesPage:s};
@@ -1,4 +1,4 @@
1
- import{AuthRequiredError as D,CommandExecutionError as J}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as K}from"../_shared/site-auth.js";async function F(z){return(await z.getCookies({url:"https://mp.toutiao.com"})).some((G)=>G.name==="sessionid"&&G.value)}async function H(z){if(!await F(z))throw new D("toutiao.com","Toutiao sessionid cookie missing");await z.goto("https://mp.toutiao.com/");await z.wait(2);const B=await z.evaluate(`
1
+ import{AuthRequiredError as t,CommandExecutionError as a}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as u}from"../_shared/site-auth.js";async function i(e){return(await e.getCookies({url:"https://mp.toutiao.com"})).some((n)=>n.name==="sessionid"&&n.value)}async function s(e){if(!await i(e))throw new t("toutiao.com","Toutiao sessionid cookie missing");await e.goto("https://mp.toutiao.com/");await e.wait(2);const o=await e.evaluate(`
2
2
  (async () => {
3
3
  if (/\\/auth\\/page\\/login/.test(location.href)) {
4
4
  return { kind: 'auth', detail: 'mp.toutiao.com redirected to /auth/page/login — anonymous' };
@@ -47,4 +47,4 @@ import{AuthRequiredError as D,CommandExecutionError as J}from"@jackwener/opencli
47
47
  }
48
48
  return { ok: true, user_id: userId, nickname };
49
49
  })()
50
- `);if(B?.kind==="auth"||B?.kind==="maybe-auth")throw new D("toutiao.com",B.detail);if(!B?.ok)throw new J(`Unexpected Toutiao probe: ${JSON.stringify(B)}`);return{user_id:B.user_id,nickname:B.nickname}}K({site:"toutiao",domain:"toutiao.com",loginUrl:"https://mp.toutiao.com/auth/page/login",columns:["user_id","nickname"],quickCheck:F,verify:H,poll:async(z)=>{if(!await F(z))throw new D("toutiao.com","Waiting for Toutiao sessionid cookie");return H(z)}});
50
+ `);if(o?.kind==="auth"||o?.kind==="maybe-auth")throw new t("toutiao.com",o.detail);if(!o?.ok)throw new a(`Unexpected Toutiao probe: ${JSON.stringify(o)}`);return{user_id:o.user_id,nickname:o.nickname}}u({site:"toutiao",domain:"toutiao.com",loginUrl:"https://mp.toutiao.com/auth/page/login",columns:["user_id","nickname"],quickCheck:i,verify:s,poll:async(e)=>{if(!await i(e))throw new t("toutiao.com","Waiting for Toutiao sessionid cookie");return s(e)}});
@@ -1 +1 @@
1
- import{cli as M,Strategy as P}from"@jackwener/opencli/registry";import{CommandExecutionError as z,EmptyResultError as Q}from"@jackwener/opencli/errors";import{HOT_BOARD_URL as V,mapHotRow as W,parseHotLimit as X}from"./utils.js";M({site:"toutiao",name:"hot",access:"read",description:"今日头条首页热榜(公开 API,无需登录)",domain:"www.toutiao.com",strategy:P.PUBLIC,browser:!1,args:[{name:"limit",type:"int",default:30,help:"返回条数 (1-50)"}],columns:["rank","group_id","title","query","hot_value","label","url","image_url"],func:async(I)=>{const J=X(I?.limit,30);let F;try{F=await fetch(V,{headers:{"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",Accept:"application/json",Referer:"https://www.toutiao.com/"}})}catch(q){throw new z(`toutiao hot-board request failed: ${q?.message||q}`)}if(!F.ok)throw new z(`toutiao hot-board failed: HTTP ${F.status}`);let b;try{b=await F.json()}catch(q){throw new z(`toutiao hot-board returned malformed JSON: ${q?.message||q}`)}if(b?.status&&b.status!=="success")throw new z(`toutiao hot-board returned status=${b.status}`);if(b?.error||b?.message)throw new z(`toutiao hot-board returned error: ${b.error||b.message}`);const G=(Array.isArray(b?.data)?b.data:[]).map(W).filter(Boolean).slice(0,J);if(G.length===0)throw new Q("toutiao hot","上游 hot-board 返回空列表。");return G.map((q,K)=>({...q,rank:K+1}))}});
1
+ import{cli as n,Strategy as m}from"@jackwener/opencli/registry";import{CommandExecutionError as r,EmptyResultError as u}from"@jackwener/opencli/errors";import{HOT_BOARD_URL as c,mapHotRow as h,parseHotLimit as w}from"./utils.js";n({site:"toutiao",name:"hot",access:"read",description:"今日头条首页热榜(公开 API,无需登录)",domain:"www.toutiao.com",strategy:m.PUBLIC,browser:!1,args:[{name:"limit",type:"int",default:30,help:"返回条数 (1-50)"}],columns:["rank","group_id","title","query","hot_value","label","url","image_url"],func:async(i)=>{const s=w(i?.limit,30);let e;try{e=await fetch(c,{headers:{"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",Accept:"application/json",Referer:"https://www.toutiao.com/"}})}catch(o){throw new r(`toutiao hot-board request failed: ${o?.message||o}`)}if(!e.ok)throw new r(`toutiao hot-board failed: HTTP ${e.status}`);let t;try{t=await e.json()}catch(o){throw new r(`toutiao hot-board returned malformed JSON: ${o?.message||o}`)}if(t?.status&&t.status!=="success")throw new r(`toutiao hot-board returned status=${t.status}`);if(t?.error||t?.message)throw new r(`toutiao hot-board returned error: ${t.error||t.message}`);const a=(Array.isArray(t?.data)?t.data:[]).map(h).filter(Boolean).slice(0,s);if(a.length===0)throw new u("toutiao hot","上游 hot-board 返回空列表。");return a.map((o,l)=>({...o,rank:l+1}))}});
@@ -1 +1 @@
1
- import{cli as V,Strategy as W}from"@jackwener/opencli/registry";import{CommandExecutionError as z,EmptyResultError as X}from"@jackwener/opencli/errors";import{RECOMMEND_CATEGORIES as Y,RECOMMEND_URL as Z,mapRecommendRow as $,parseRecommendCategory as h,parseRecommendLimit as v}from"./utils.js";V({site:"toutiao",name:"recommend",access:"read",description:"今日头条频道推荐流(公开 API,无需登录)",domain:"www.toutiao.com",strategy:W.PUBLIC,browser:!1,args:[{name:"category",type:"string",default:"__all__",help:`频道 (${Y.join(", ")})`},{name:"limit",type:"int",default:20,help:"返回条数 (1-50)"}],columns:["rank","group_id","title","abstract","source","tag","comments","published_at","url","image_url"],func:async(F)=>{const H=h(F?.category,"__all__"),K=v(F?.limit,20),P=`${Z}?category=${encodeURIComponent(H)}`;let B;try{B=await fetch(P,{headers:{"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",Accept:"application/json",Referer:"https://www.toutiao.com/"}})}catch(b){throw new z(`toutiao recommend request failed: ${b?.message||b}`)}if(!B.ok)throw new z(`toutiao recommend failed: HTTP ${B.status}`);let q;try{q=await B.json()}catch(b){throw new z(`toutiao recommend returned malformed JSON: ${b?.message||b}`)}if(q?.message&&q.message!=="success")throw new z(`toutiao recommend returned message=${q.message}`);if(!Array.isArray(q?.data))throw new z("toutiao recommend returned a non-array data field");const J=q.data.map($).filter(Boolean).slice(0,K);if(J.length===0)throw new X("toutiao recommend",`频道 ${H} 返回空列表。`);return J.map((b,Q)=>({...b,rank:Q+1}))}});
1
+ import{cli as l,Strategy as d}from"@jackwener/opencli/registry";import{CommandExecutionError as o,EmptyResultError as u}from"@jackwener/opencli/errors";import{RECOMMEND_CATEGORIES as p,RECOMMEND_URL as w,mapRecommendRow as f,parseRecommendCategory as g,parseRecommendLimit as h}from"./utils.js";l({site:"toutiao",name:"recommend",access:"read",description:"今日头条频道推荐流(公开 API,无需登录)",domain:"www.toutiao.com",strategy:d.PUBLIC,browser:!1,args:[{name:"category",type:"string",default:"__all__",help:`频道 (${p.join(", ")})`},{name:"limit",type:"int",default:20,help:"返回条数 (1-50)"}],columns:["rank","group_id","title","abstract","source","tag","comments","published_at","url","image_url"],func:async(a)=>{const m=g(a?.category,"__all__"),i=h(a?.limit,20),s=`${w}?category=${encodeURIComponent(m)}`;let r;try{r=await fetch(s,{headers:{"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",Accept:"application/json",Referer:"https://www.toutiao.com/"}})}catch(e){throw new o(`toutiao recommend request failed: ${e?.message||e}`)}if(!r.ok)throw new o(`toutiao recommend failed: HTTP ${r.status}`);let t;try{t=await r.json()}catch(e){throw new o(`toutiao recommend returned malformed JSON: ${e?.message||e}`)}if(t?.message&&t.message!=="success")throw new o(`toutiao recommend returned message=${t.message}`);if(!Array.isArray(t?.data))throw new o("toutiao recommend returned a non-array data field");const n=t.data.map(f).filter(Boolean).slice(0,i);if(n.length===0)throw new u("toutiao recommend",`频道 ${m} 返回空列表。`);return n.map((e,c)=>({...e,rank:c+1}))}});