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,7 +1,7 @@
1
- import*as q from"node:fs";import*as k from"node:os";import*as V from"node:path";import{ArgumentError as A,AuthRequiredError as h,CommandExecutionError as I}from"@jackwener/opencli/errors";import{cli as C,Strategy as w}from"@jackwener/opencli/registry";const v="https://linux.do",y=86400000;let G=null,N=null,b=null,R=null,M=null;function F(Q){return Q.trim().replace(/\s+/g," ").toLowerCase()}function m(){return process.env.HOME||process.env.USERPROFILE||k.homedir()}function O(){return M??V.join(m(),".ppcli","cache","linux-do")}function S(Q){return V.join(O(),`${Q}.json`)}async function x(Q){try{const W=await q.promises.readFile(S(Q),"utf-8"),Y=JSON.parse(W);if(!Y||!Array.isArray(Y.data)||typeof Y.fetchedAt!=="string")return null;const $=new Date(Y.fetchedAt).getTime(),Z=Number.isFinite($)&&Date.now()-$<y;return{data:Y.data,fresh:Z}}catch{return null}}async function E(Q,W){try{const Y=O();await q.promises.mkdir(Y,{recursive:!0});const $={fetchedAt:new Date().toISOString(),data:W};await q.promises.writeFile(S(Q),JSON.stringify($,null,2)+`
2
- `)}catch{}}async function f(Q){if(!Q)throw new I("Browser page required");await Q.goto(v);await Q.wait(2)}export async function fetchLinuxDoJson(Q,W,Y={}){if(!Y.skipNavigate)await f(Q);if(!Q)throw new I("Browser page required");const $=JSON.stringify(W),Z=await Q.evaluate(`(async () => {
1
+ import*as _ from"node:fs";import*as R from"node:os";import*as C from"node:path";import{ArgumentError as S,AuthRequiredError as E,CommandExecutionError as f}from"@jackwener/opencli/errors";import{cli as U,Strategy as P}from"@jackwener/opencli/registry";const k="https://linux.do",q=86400000;let s=null,l=null,y=null,h=null,x=null;function m(t){return t.trim().replace(/\s+/g," ").toLowerCase()}function F(){return process.env.HOME||process.env.USERPROFILE||R.homedir()}function L(){return x??C.join(F(),".ppcli","cache","linux-do")}function A(t){return C.join(L(),`${t}.json`)}async function T(t){try{const e=await _.promises.readFile(A(t),"utf-8"),r=JSON.parse(e);if(!r||!Array.isArray(r.data)||typeof r.fetchedAt!=="string")return null;const i=new Date(r.fetchedAt).getTime(),n=Number.isFinite(i)&&Date.now()-i<q;return{data:r.data,fresh:n}}catch{return null}}async function D(t,e){try{const r=L();await _.promises.mkdir(r,{recursive:!0});const i={fetchedAt:new Date().toISOString(),data:e};await _.promises.writeFile(A(t),JSON.stringify(i,null,2)+`
2
+ `)}catch{}}async function b(t){if(!t)throw new f("Browser page required");await t.goto(k);await t.wait(2)}export async function fetchLinuxDoJson(t,e,r={}){if(!r.skipNavigate)await b(t);if(!t)throw new f("Browser page required");const i=JSON.stringify(e),n=await t.evaluate(`(async () => {
3
3
  try {
4
- const res = await fetch(${$}, { credentials: 'include' });
4
+ const res = await fetch(${i}, { credentials: 'include' });
5
5
  let data = null;
6
6
  try { data = await res.json(); } catch {}
7
7
  return {
@@ -16,4 +16,4 @@ import*as q from"node:fs";import*as k from"node:os";import*as V from"node:path";
16
16
  error: error instanceof Error ? error.message : String(error),
17
17
  };
18
18
  }
19
- })()`);if(!Z)throw new I("linux.do returned an empty browser response");if(Z.status===401||Z.status===403)throw new h("linux.do","linux.do requires an active signed-in browser session");if(!Z.ok)throw new I(Z.error||`linux.do request failed: HTTP ${Z.status??"unknown"}`);if(Z.error)throw new I(Z.error,"Please verify your linux.do session is still valid");return Z.data}function n(Q,W){const Y=W.trim(),$=F(W);return/^\d+$/.test(Y)?Q.find((Z)=>Z.id===Number(Y))??null:Q.find((Z)=>F(Z.name)===$)??Q.find((Z)=>F(Z.slug)===$)??null}function p(Q,W){const Y=W.trim(),$=F(W);return/^\d+$/.test(Y)?Q.find((Z)=>Z.id===Number(Y))??null:Q.find((Z)=>d(Z).includes($))??null}function d(Q){const W=[Q.name,Q.slug];if(Q.parent)W.push(`${Q.parent.name} / ${Q.name}`,`${Q.parent.name}/${Q.name}`,`${Q.parent.name}, ${Q.name}`);return W.map(F)}function P(Q,W){return{id:Q.id,name:Q.name??"",description:Q.description_text??Q.description??"",slug:Q.slug??"",parentCategoryId:W?.id??null,parent:W}}async function l(Q){if(b)return b;if(!G)G=(async()=>{const W=await x("tags");if(W?.fresh)return W.data;try{const Y=await fetchLinuxDoJson(Q,"/tags.json",{skipNavigate:!0}),$=(Array.isArray(Y?.tags)?Y.tags:[]).filter((Z)=>!!Z&&typeof Z.id==="number").map((Z)=>({id:Z.id,slug:Z.slug??`${Z.id}-tag`,name:Z.name??String(Z.id)}));await E("tags",$);return $}catch(Y){if(W)return W.data;G=null;throw Y}})().catch((W)=>{G=null;throw W});return G}async function u(Q){if(R)return R;if(!N)N=(async()=>{const W=await x("categories");if(W?.fresh)return W.data;try{const Y=await fetchLinuxDoJson(Q,"/categories.json",{skipNavigate:!0}),$=Array.isArray(Y?.category_list?.categories)?Y.category_list.categories:[],Z=$.map((B)=>P(B,null)),U=new Map(Z.map((B)=>[B.id,B])),X=await Promise.allSettled($.filter((B)=>Array.isArray(B.subcategory_ids)&&B.subcategory_ids.length>0).map(async(B)=>{const j=await fetchLinuxDoJson(Q,`/categories.json?parent_category_id=${B.id}`,{skipNavigate:!0}),J=Array.isArray(j?.category_list?.categories)?j.category_list.categories:[],z=U.get(B.id)??null;return J.map((H)=>P(H,z))})),K=[...Z,...X.flatMap((B)=>B.status==="fulfilled"?B.value:[])];await E("categories",K);return K}catch(Y){if(W)return W.data;throw Y}})().catch((W)=>{N=null;throw W});return N}function c(Q){if(!Q)return"";const W=new Date(Q);if(isNaN(W.getTime()))return Q;return W.toLocaleString()}function i(Q){return Math.max(0,(typeof Q==="number"?Q:1)-1)}function s(Q,W){return(Q?.topic_list?.topics??[]).slice(0,W).map(($)=>({title:$.fancy_title??$.title??"",replies:i($.posts_count),created:c($.created_at),likes:$.like_count??0,views:$.views??0,url:`https://linux.do/t/topic/${$.id}`}))}async function g(Q,W){const Y=n(await l(Q),W);if(Y)return Y;throw new A(`Unknown tag: ${W}`,'Use "ppcli linux-do tags" to list available tags')}async function o(Q,W){const Y=p(await u(Q),W);if(Y)return Y;throw new A(`Unknown category: ${W}`,'Use "ppcli linux-do categories" to list available categories')}async function D(Q,W){const Y=W.view||"latest",$=W.period||"weekly";if(W.period&&Y!=="top")throw new A("--period is only valid with --view top");const Z=new URLSearchParams;if(W.order&&W.order!=="default")Z.set("order",W.order);if(W.ascending)Z.set("ascending","true");if(W.limit)Z.set("per_page",String(W.limit));const U=typeof W.tag==="string"?W.tag.trim():"",X=typeof W.category==="string"?W.category.trim():"";if(!U&&!X){const _=new URLSearchParams(Z);if(Y==="top")_.set("period",$);const T=_.toString()?`?${_.toString()}`:"";return{url:`${Y==="latest"?"/latest.json":Y==="hot"?"/hot.json":"/top.json"}${T}`}}const K=U?await g(Q,U):null,B=X?await o(Q,X):null,j=B?(B.parent?[B.parent.slug,B.slug,String(B.id)]:[B.slug,String(B.id)]).map(encodeURIComponent).join("/"):"",J=K?`${encodeURIComponent(K.slug||`${K.id}-tag`)}/${K.id}`:"",z=B&&K?`/tags/c/${j}/${J}`:B?`/c/${j}`:`/tag/${J}`,H=new URLSearchParams(Z);if(Y==="top")H.set("period",$);const L=H.toString()?`?${H.toString()}`:"";return{url:`${z}${Y==="latest"?".json":`/l/${Y}.json`}${L}`}}export const LINUX_DO_FEED_ARGS=[{name:"view",type:"str",default:"latest",help:"View type",choices:["latest","hot","top"]},{name:"tag",type:"str",help:"Tag name, slug, or id"},{name:"category",type:"str",help:"Category name, slug, id, or parent/name path"},{name:"limit",type:"int",default:20,help:"Number of items (per_page)"},{name:"order",type:"str",default:"default",help:"Sort order",choices:["default","created","activity","views","posts","category","likes","op_likes","posters"]},{name:"ascending",type:"boolean",default:!1,help:"Sort ascending (default: desc)"},{name:"period",type:"str",help:"Time period (only for --view top)",choices:["all","daily","weekly","monthly","quarterly","yearly"]}];async function t(Q,W){const Y=W.limit||20;await f(Q);const $=await D(Q,W),Z=await fetchLinuxDoJson(Q,$.url,{skipNavigate:!0});return s(Z,Y)}C({site:"linux-do",name:"feed",access:"read",description:"linux.do 话题列表(需登录;支持全站、标签、分类)",domain:"linux.do",strategy:w.COOKIE,browser:!0,columns:["title","replies","created","likes","views","url"],args:LINUX_DO_FEED_ARGS,func:t});export const __test__={resetMetadataCaches(){G=null;N=null;b=null;R=null;M=null},setLiveMetadataForTests({tags:Q,categories:W}){G=null;N=null;b=Q??null;R=W??null},setCacheDirForTests(Q){M=Q},resolveFeedRequest:D};
19
+ })()`);if(!n)throw new f("linux.do returned an empty browser response");if(n.status===401||n.status===403)throw new E("linux.do","linux.do requires an active signed-in browser session");if(!n.ok)throw new f(n.error||`linux.do request failed: HTTP ${n.status??"unknown"}`);if(n.error)throw new f(n.error,"Please verify your linux.do session is still valid");return n.data}function I(t,e){const r=e.trim(),i=m(e);return/^\d+$/.test(r)?t.find((n)=>n.id===Number(r))??null:t.find((n)=>m(n.name)===i)??t.find((n)=>m(n.slug)===i)??null}function J(t,e){const r=e.trim(),i=m(e);return/^\d+$/.test(r)?t.find((n)=>n.id===Number(r))??null:t.find((n)=>H(n).includes(i))??null}function H(t){const e=[t.name,t.slug];if(t.parent)e.push(`${t.parent.name} / ${t.name}`,`${t.parent.name}/${t.name}`,`${t.parent.name}, ${t.name}`);return e.map(m)}function N(t,e){return{id:t.id,name:t.name??"",description:t.description_text??t.description??"",slug:t.slug??"",parentCategoryId:e?.id??null,parent:e}}async function z(t){if(y)return y;if(!s)s=(async()=>{const e=await T("tags");if(e?.fresh)return e.data;try{const r=await fetchLinuxDoJson(t,"/tags.json",{skipNavigate:!0}),i=(Array.isArray(r?.tags)?r.tags:[]).filter((n)=>!!n&&typeof n.id==="number").map((n)=>({id:n.id,slug:n.slug??`${n.id}-tag`,name:n.name??String(n.id)}));await D("tags",i);return i}catch(r){if(e)return e.data;s=null;throw r}})().catch((e)=>{s=null;throw e});return s}async function V(t){if(h)return h;if(!l)l=(async()=>{const e=await T("categories");if(e?.fresh)return e.data;try{const r=await fetchLinuxDoJson(t,"/categories.json",{skipNavigate:!0}),i=Array.isArray(r?.category_list?.categories)?r.category_list.categories:[],n=i.map((a)=>N(a,null)),c=new Map(n.map((a)=>[a.id,a])),u=await Promise.allSettled(i.filter((a)=>Array.isArray(a.subcategory_ids)&&a.subcategory_ids.length>0).map(async(a)=>{const d=await fetchLinuxDoJson(t,`/categories.json?parent_category_id=${a.id}`,{skipNavigate:!0}),g=Array.isArray(d?.category_list?.categories)?d.category_list.categories:[],w=c.get(a.id)??null;return g.map((p)=>N(p,w))})),o=[...n,...u.flatMap((a)=>a.status==="fulfilled"?a.value:[])];await D("categories",o);return o}catch(r){if(e)return e.data;throw r}})().catch((e)=>{l=null;throw e});return l}function B(t){if(!t)return"";const e=new Date(t);if(isNaN(e.getTime()))return t;return e.toLocaleString()}function X(t){return Math.max(0,(typeof t==="number"?t:1)-1)}function G(t,e){return(t?.topic_list?.topics??[]).slice(0,e).map((i)=>({title:i.fancy_title??i.title??"",replies:X(i.posts_count),created:B(i.created_at),likes:i.like_count??0,views:i.views??0,url:`https://linux.do/t/topic/${i.id}`}))}async function K(t,e){const r=I(await z(t),e);if(r)return r;throw new S(`Unknown tag: ${e}`,'Use "ppcli linux-do tags" to list available tags')}async function Q(t,e){const r=J(await V(t),e);if(r)return r;throw new S(`Unknown category: ${e}`,'Use "ppcli linux-do categories" to list available categories')}async function O(t,e){const r=e.view||"latest",i=e.period||"weekly";if(e.period&&r!=="top")throw new S("--period is only valid with --view top");const n=new URLSearchParams;if(e.order&&e.order!=="default")n.set("order",e.order);if(e.ascending)n.set("ascending","true");if(e.limit)n.set("per_page",String(e.limit));const c=typeof e.tag==="string"?e.tag.trim():"",u=typeof e.category==="string"?e.category.trim():"";if(!c&&!u){const v=new URLSearchParams(n);if(r==="top")v.set("period",i);const M=v.toString()?`?${v.toString()}`:"";return{url:`${r==="latest"?"/latest.json":r==="hot"?"/hot.json":"/top.json"}${M}`}}const o=c?await K(t,c):null,a=u?await Q(t,u):null,d=a?(a.parent?[a.parent.slug,a.slug,String(a.id)]:[a.slug,String(a.id)]).map(encodeURIComponent).join("/"):"",g=o?`${encodeURIComponent(o.slug||`${o.id}-tag`)}/${o.id}`:"",w=a&&o?`/tags/c/${d}/${g}`:a?`/c/${d}`:`/tag/${g}`,p=new URLSearchParams(n);if(r==="top")p.set("period",i);const j=p.toString()?`?${p.toString()}`:"";return{url:`${w}${r==="latest"?".json":`/l/${r}.json`}${j}`}}export const LINUX_DO_FEED_ARGS=[{name:"view",type:"str",default:"latest",help:"View type",choices:["latest","hot","top"]},{name:"tag",type:"str",help:"Tag name, slug, or id"},{name:"category",type:"str",help:"Category name, slug, id, or parent/name path"},{name:"limit",type:"int",default:20,help:"Number of items (per_page)"},{name:"order",type:"str",default:"default",help:"Sort order",choices:["default","created","activity","views","posts","category","likes","op_likes","posters"]},{name:"ascending",type:"boolean",default:!1,help:"Sort ascending (default: desc)"},{name:"period",type:"str",help:"Time period (only for --view top)",choices:["all","daily","weekly","monthly","quarterly","yearly"]}];async function W(t,e){const r=e.limit||20;await b(t);const i=await O(t,e),n=await fetchLinuxDoJson(t,i.url,{skipNavigate:!0});return G(n,r)}U({site:"linux-do",name:"feed",access:"read",description:"linux.do 话题列表(需登录;支持全站、标签、分类)",domain:"linux.do",strategy:P.COOKIE,browser:!0,columns:["title","replies","created","likes","views","url"],args:LINUX_DO_FEED_ARGS,func:W});export const __test__={resetMetadataCaches(){s=null;l=null;y=null;h=null;x=null},setLiveMetadataForTests({tags:t,categories:e}){s=null;l=null;y=t??null;h=e??null},setCacheDirForTests(t){x=t},resolveFeedRequest:O};
@@ -1,12 +1,12 @@
1
- import{AuthRequiredError as Y,CommandExecutionError as W,EmptyResultError as q}from"@jackwener/opencli/errors";import{cli as X,Strategy as h}from"@jackwener/opencli/registry";import{htmlToMarkdown as b,isRecord as $}from"@jackwener/opencli/utils";const H="linux.do",f="https://linux.do";function z(F){if(!F)return"";const G=new Date(F);return Number.isNaN(G.getTime())?F:G.toLocaleString()}function Q(F){if(!$(F))return null;const G=$(F.post_stream)?{posts:Array.isArray(F.post_stream.posts)?F.post_stream.posts.filter($).map((B)=>({post_number:typeof B.post_number==="number"?B.post_number:void 0,username:typeof B.username==="string"?B.username:void 0,raw:typeof B.raw==="string"?B.raw:void 0,cooked:typeof B.cooked==="string"?B.cooked:void 0,like_count:typeof B.like_count==="number"?B.like_count:void 0,created_at:typeof B.created_at==="string"?B.created_at:void 0})):void 0}:void 0;return{title:typeof F.title==="string"?F.title:void 0,post_stream:G}}function j(F){const G=[],B=[["title",F.title||void 0],["author",F.author||void 0],["likes",typeof F.likes==="number"&&Number.isFinite(F.likes)?F.likes:void 0],["createdAt",F.createdAt||void 0],["url",F.url||void 0]];for(const[J,K]of B){if(K===void 0)continue;if(typeof K==="number")G.push(`${J}: ${K}`);else{const Z=/[#{}[\],&*?|>!%@`'"]/.test(K)||/: /.test(K)||/:$/.test(K)||K.includes(`
2
- `);G.push(`${J}: ${Z?`'${K.replace(/'/g,"''")}'`:K}`)}}const V=G.join(`
3
- `);return[V?`---
4
- ${V}
5
- ---`:"",F.body.trim()].filter(Boolean).join(`
1
+ import{AuthRequiredError as c,CommandExecutionError as s,EmptyResultError as l}from"@jackwener/opencli/errors";import{cli as y,Strategy as _}from"@jackwener/opencli/registry";import{htmlToMarkdown as h,isRecord as a}from"@jackwener/opencli/utils";const d="linux.do",b="https://linux.do";function f(t){if(!t)return"";const n=new Date(t);return Number.isNaN(n.getTime())?t:n.toLocaleString()}function m(t){if(!a(t))return null;const n=a(t.post_stream)?{posts:Array.isArray(t.post_stream.posts)?t.post_stream.posts.filter(a).map((e)=>({post_number:typeof e.post_number==="number"?e.post_number:void 0,username:typeof e.username==="string"?e.username:void 0,raw:typeof e.raw==="string"?e.raw:void 0,cooked:typeof e.cooked==="string"?e.cooked:void 0,like_count:typeof e.like_count==="number"?e.like_count:void 0,created_at:typeof e.created_at==="string"?e.created_at:void 0})):void 0}:void 0;return{title:typeof t.title==="string"?t.title:void 0,post_stream:n}}function p(t){const n=[],e=[["title",t.title||void 0],["author",t.author||void 0],["likes",typeof t.likes==="number"&&Number.isFinite(t.likes)?t.likes:void 0],["createdAt",t.createdAt||void 0],["url",t.url||void 0]];for(const[r,o]of e){if(o===void 0)continue;if(typeof o==="number")n.push(`${r}: ${o}`);else{const u=/[#{}[\],&*?|>!%@`'"]/.test(o)||/: /.test(o)||/:$/.test(o)||o.includes(`
2
+ `);n.push(`${r}: ${u?`'${o.replace(/'/g,"''")}'`:o}`)}}const i=n.join(`
3
+ `);return[i?`---
4
+ ${i}
5
+ ---`:"",t.body.trim()].filter(Boolean).join(`
6
6
 
7
- `).trim()}function U(F,G){const B=Q(F);if(!B)throw new W("linux.do returned an unexpected topic payload");const J=(B.post_stream?.posts??[]).find((Z)=>Z.post_number===1);if(!J)throw new q("linux-do/topic-content",`Could not find the main post for topic ${G}.`);const K=typeof J.raw==="string"&&J.raw.trim()?J.raw.trim():b(J.cooked??"");if(!K)throw new q("linux-do/topic-content",`Topic ${G} does not contain a readable main post body.`);return{content:j({title:B.title?.trim()??"",author:J.username?.trim()??"",likes:typeof J.like_count==="number"?J.like_count:void 0,createdAt:z(J.created_at??""),url:`${f}/t/${G}`,body:K})}}async function A(F,G){const B=await F.evaluate(`(async () => {
7
+ `).trim()}function w(t,n){const e=m(t);if(!e)throw new s("linux.do returned an unexpected topic payload");const r=(e.post_stream?.posts??[]).find((u)=>u.post_number===1);if(!r)throw new l("linux-do/topic-content",`Could not find the main post for topic ${n}.`);const o=typeof r.raw==="string"&&r.raw.trim()?r.raw.trim():h(r.cooked??"");if(!o)throw new l("linux-do/topic-content",`Topic ${n} does not contain a readable main post body.`);return{content:p({title:e.title?.trim()??"",author:r.username?.trim()??"",likes:typeof r.like_count==="number"?r.like_count:void 0,createdAt:f(r.created_at??""),url:`${b}/t/${n}`,body:o})}}async function k(t,n){const e=await t.evaluate(`(async () => {
8
8
  try {
9
- const res = await fetch('/t/${G}.json?include_raw=true', { credentials: 'include' });
9
+ const res = await fetch('/t/${n}.json?include_raw=true', { credentials: 'include' });
10
10
  let data = null;
11
11
  try {
12
12
  data = await res.json();
@@ -25,4 +25,4 @@ ${V}
25
25
  error: error instanceof Error ? error.message : String(error),
26
26
  };
27
27
  }
28
- })()`);if(!B)throw new W("linux.do returned an empty browser response");if(B.status===401||B.status===403)throw new Y(H,"linux.do requires an active signed-in browser session");if(B.error==="Response is not valid JSON")throw new Y(H,"linux.do requires an active signed-in browser session");if(!B.ok)throw new W(B.error||`linux.do request failed: HTTP ${B.status??"unknown"}`);if(B.error)throw new W(B.error,"Please verify your linux.do session is still valid");return B.data}X({site:"linux-do",name:"topic-content",access:"read",description:"Get the main topic body as Markdown",domain:H,strategy:h.COOKIE,browser:!0,defaultFormat:"plain",args:[{name:"id",positional:!0,type:"int",required:!0,help:"Topic ID"}],columns:["content"],func:async(F,G)=>{const B=Number(G.id);if(!Number.isInteger(B)||B<=0)throw new W(`Invalid linux.do topic id: ${String(G.id??"")}`);const V=await A(F,B);return[U(V,B)]}});export const __test__={buildTopicMarkdownDocument:j,extractTopicContent:U,normalizeTopicPayload:Q,toLocalTime:z};
28
+ })()`);if(!e)throw new s("linux.do returned an empty browser response");if(e.status===401||e.status===403)throw new c(d,"linux.do requires an active signed-in browser session");if(e.error==="Response is not valid JSON")throw new c(d,"linux.do requires an active signed-in browser session");if(!e.ok)throw new s(e.error||`linux.do request failed: HTTP ${e.status??"unknown"}`);if(e.error)throw new s(e.error,"Please verify your linux.do session is still valid");return e.data}y({site:"linux-do",name:"topic-content",access:"read",description:"Get the main topic body as Markdown",domain:d,strategy:_.COOKIE,browser:!0,defaultFormat:"plain",args:[{name:"id",positional:!0,type:"int",required:!0,help:"Topic ID"}],columns:["content"],func:async(t,n)=>{const e=Number(n.id);if(!Number.isInteger(e)||e<=0)throw new s(`Invalid linux.do topic id: ${String(n.id??"")}`);const i=await k(t,e);return[w(i,e)]}});export const __test__={buildTopicMarkdownDocument:p,extractTopicContent:w,normalizeTopicPayload:m,toLocalTime:f};
@@ -1 +1 @@
1
- import{cli as d,Strategy as b}from"@jackwener/opencli/registry";import{ArgumentError as i,CommandExecutionError as m,EmptyResultError as u}from"@jackwener/opencli/errors";const h=/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)+$/i;function g(s){const e=String(s??"").trim().toLowerCase();if(!e)throw new i('lobsters domain is required (e.g. "github.com" or "arxiv.org")');if(!h.test(e))throw new i(`lobsters domain "${s}" is not a valid hostname`);return e}function f(s,e,n){const o=s??e,r=typeof o==="number"?o:Number(o);if(!Number.isInteger(r)||r<=0)throw new i("lobsters limit must be a positive integer");if(r>n)throw new i(`lobsters limit must be <= ${n}`);return r}d({site:"lobsters",name:"domain",access:"read",description:"Lobste.rs stories submitted from a specific domain",domain:"lobste.rs",strategy:b.PUBLIC,browser:!1,args:[{name:"domain",positional:!0,required:!0,help:"Source domain (e.g. github.com, arxiv.org, blog.cloudflare.com)"},{name:"limit",type:"int",default:20,help:"Number of stories (1-25 — single page)"}],columns:["rank","id","title","score","author","comments","created_at","tags","submission_url","comments_url"],func:async(s)=>{const e=g(s.domain),n=f(s.limit,20,25),o=`https://lobste.rs/domains/${encodeURIComponent(e)}.json`;let r;try{r=await fetch(o,{headers:{"user-agent":"opencli-lobsters-adapter (+https://github.com/jackwener/OpenCLI)"}})}catch(t){throw new m(`lobsters domain request failed: ${t?.message??t}`,"Check that lobste.rs is reachable from this network.")}if(r.status===404)throw new u("lobsters domain",`No Lobste.rs stories found for domain "${e}".`);if(!r.ok)throw new m(`lobsters domain returned HTTP ${r.status}`);let a;try{a=await r.json()}catch(t){throw new m(`lobsters domain returned malformed JSON: ${t?.message??t}`)}const l=Array.isArray(a)?a:[];if(!l.length)throw new u("lobsters domain",`No Lobste.rs stories found for domain "${e}".`);return l.slice(0,n).map((t,c)=>({rank:c+1,id:String(t.short_id??""),title:String(t.title??""),score:t.score!=null?Number(t.score):null,author:String(t.submitter_user??""),comments:t.comment_count!=null?Number(t.comment_count):null,created_at:String(t.created_at??"").slice(0,10),tags:Array.isArray(t.tags)?t.tags.join(", "):"",submission_url:String(t.url??""),comments_url:String(t.comments_url??"")}))}});
1
+ import{cli as d,Strategy as b}from"@jackwener/opencli/registry";import{ArgumentError as i,CommandExecutionError as m,EmptyResultError as u}from"@jackwener/opencli/errors";const g=/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)+$/i;function h(o){const e=String(o??"").trim().toLowerCase();if(!e)throw new i('lobsters domain is required (e.g. "github.com" or "arxiv.org")');if(!g.test(e))throw new i(`lobsters domain "${o}" is not a valid hostname`);return e}function f(o,e,n){const s=o??e,t=typeof s==="number"?s:Number(s);if(!Number.isInteger(t)||t<=0)throw new i("lobsters limit must be a positive integer");if(t>n)throw new i(`lobsters limit must be <= ${n}`);return t}d({site:"lobsters",name:"domain",access:"read",description:"Lobste.rs stories submitted from a specific domain",domain:"lobste.rs",strategy:b.PUBLIC,browser:!1,args:[{name:"domain",positional:!0,required:!0,help:"Source domain (e.g. github.com, arxiv.org, blog.cloudflare.com)"},{name:"limit",type:"int",default:20,help:"Number of stories (1-25 — single page)"}],columns:["rank","id","title","score","author","comments","created_at","tags","submission_url","comments_url"],func:async(o)=>{const e=h(o.domain),n=f(o.limit,20,25),s=`https://lobste.rs/domains/${encodeURIComponent(e)}.json`;let t;try{t=await fetch(s,{headers:{"user-agent":"opencli-lobsters-adapter (+https://github.com/jackwener/OpenCLI)"}})}catch(r){throw new m(`lobsters domain request failed: ${r?.message??r}`,"Check that lobste.rs is reachable from this network.")}if(t.status===404)throw new u("lobsters domain",`No Lobste.rs stories found for domain "${e}".`);if(!t.ok)throw new m(`lobsters domain returned HTTP ${t.status}`);let a;try{a=await t.json()}catch(r){throw new m(`lobsters domain returned malformed JSON: ${r?.message??r}`)}const l=Array.isArray(a)?a:[];if(!l.length)throw new u("lobsters domain",`No Lobste.rs stories found for domain "${e}".`);return l.slice(0,n).map((r,c)=>({rank:c+1,id:String(r.short_id??""),title:String(r.title??""),score:r.score!=null?Number(r.score):null,author:String(r.submitter_user??""),comments:r.comment_count!=null?Number(r.comment_count):null,created_at:String(r.created_at??"").slice(0,10),tags:Array.isArray(r.tags)?r.tags.join(", "):"",submission_url:String(r.url??""),comments_url:String(r.comments_url??"")}))}});
@@ -1,11 +1,11 @@
1
- import{cli as T,Strategy as E}from"@jackwener/opencli/registry";import{ArgumentError as Y,CommandExecutionError as w,EmptyResultError as P}from"@jackwener/opencli/errors";const R="https://lobste.rs/s";async function x(z){const F=await fetch(`${R}/${z}.json`);if(F.status===404)throw new P(`lobsters/${z}`,"Story not found");if(!F.ok)throw new w(`Lobsters API HTTP ${F.status} for story ${z}`,"Check the short id");return F.json()}function j(z,F){if(!Number.isInteger(z)||z<=0)throw new Y(`${F} must be a positive integer`);return z}function I(z,F,U){if(!Number.isInteger(z)||z<F)throw new Y(`${U} must be an integer >= ${F}`);return z}function k(z){if(!z)return"";return String(z).replace(/<p>/gi,`
1
+ import{cli as k,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentError as f,CommandExecutionError as A,EmptyResultError as T}from"@jackwener/opencli/errors";const B="https://lobste.rs/s";async function j(e){const t=await fetch(`${B}/${e}.json`);if(t.status===404)throw new T(`lobsters/${e}`,"Story not found");if(!t.ok)throw new A(`Lobsters API HTTP ${t.status} for story ${e}`,"Check the short id");return t.json()}function g(e,t){if(!Number.isInteger(e)||e<=0)throw new f(`${t} must be a positive integer`);return e}function q(e,t,c){if(!Number.isInteger(e)||e<t)throw new f(`${c} must be an integer >= ${t}`);return e}function R(e){if(!e)return"";return String(e).replace(/<p>/gi,`
2
2
 
3
3
  `).replace(/<\/p>/gi,"").replace(/<br\s*\/?>/gi,`
4
4
  `).replace(/<i>(.*?)<\/i>/gi,"$1").replace(/<em>(.*?)<\/em>/gi,"$1").replace(/<strong>(.*?)<\/strong>/gi,"$1").replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gi,"$2 ($1)").replace(/<pre><code>([\s\S]*?)<\/code><\/pre>/gi,`
5
5
  $1
6
- `).replace(/<code>(.*?)<\/code>/gi,"`$1`").replace(/<[^>]+>/g,"").replace(/&#x27;/g,"'").replace(/&apos;/g,"'").replace(/&quot;/g,'"').replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").replace(/&nbsp;/g," ").replace(/&#x2F;/g,"/").trim()}function v(z,F){if(F===0)return z;const X=`${" ".repeat(F)}> `;return z.split(`
7
- `).map((Z)=>X+Z).join(`
8
- `)}function B(z){return" ".repeat(z+1)}T({site:"lobsters",name:"read",access:"read",description:"Read a Lobste.rs story and its comment tree",domain:"lobste.rs",strategy:E.PUBLIC,browser:!1,args:[{name:"id",required:!0,positional:!0,help:"Lobste.rs short_id (e.g. 6cmh6h)"},{name:"limit",type:"int",default:25,help:"Max top-level comments"},{name:"depth",type:"int",default:2,help:"Max reply depth (1=no replies, 2=one level of replies, etc.)"},{name:"replies",type:"int",default:5,help:"Max replies shown per comment at each level"},{name:"max-length",type:"int",default:2000,help:"Max characters per comment body (min 100)"}],columns:["type","author","score","text"],func:async(z)=>{const F=String(z.id||"").trim();if(!/^[a-z0-9]+$/.test(F))throw new Y(`Invalid Lobsters short_id: ${z.id}`,"Pass a lowercase alphanumeric id like 6cmh6h");const U=j(z.limit??25,"lobsters read --limit"),X=j(z.depth??2,"lobsters read --depth"),Z=j(z.replies??5,"lobsters read --replies"),V=I(z["max-length"]??2000,100,"lobsters read --max-length"),J=await x(F);if(!J||!J.short_id)throw new P(`lobsters/${F}`,"Story not found");const K=[],$=(J.description_plain||k(J.description||"")).trim(),C=$.length>V?$.slice(0,V)+`
9
- ... [truncated]`:$,D=[J.title||""];if(C)D.push(`
10
- `+C);if(J.url)D.push(`
11
- `+J.url);K.push({type:"POST",author:J.submitter_user||"[deleted]",score:J.score??0,text:D.join("").trim()});const b=Array.isArray(J.comments)?J.comments:[],Q=new Map;for(const G of b){const H=G.parent_comment||null;if(!Q.has(H))Q.set(H,[]);Q.get(H).push(G)}function O(G,H){if(!G||G.is_deleted||G.is_moderated)return;const N=(G.comment_plain||k(G.comment||"")).trim(),L=N.length>V?N.slice(0,V)+"...":N;K.push({type:H===0?"L0":`L${H}`,author:G.commenting_user||"[deleted]",score:G.score??"",text:v(L,H)});const W=Q.get(G.short_id)||[];if(H+1>=X){if(W.length>0)K.push({type:`L${H+1}`,author:"",score:"",text:`${B(H)}[+${W.length} more replies]`});return}const A=W.slice(0,Z);for(const S of A)O(S,H+1);const M=W.length-A.length;if(M>0)K.push({type:`L${H+1}`,author:"",score:"",text:`${B(H)}[+${M} more replies]`})}const _=Q.get(null)||[],q=_.slice(0,U);for(const G of q)O(G,0);const f=_.length-q.length;if(f>0)K.push({type:"",author:"",score:"",text:`[+${f} more top-level comments]`});return K}});
6
+ `).replace(/<code>(.*?)<\/code>/gi,"`$1`").replace(/<[^>]+>/g,"").replace(/&#x27;/g,"'").replace(/&apos;/g,"'").replace(/&quot;/g,'"').replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").replace(/&nbsp;/g," ").replace(/&#x2F;/g,"/").trim()}function C(e,t){if(t===0)return e;const p=`${" ".repeat(t)}> `;return e.split(`
7
+ `).map((u)=>p+u).join(`
8
+ `)}function E(e){return" ".repeat(e+1)}k({site:"lobsters",name:"read",access:"read",description:"Read a Lobste.rs story and its comment tree",domain:"lobste.rs",strategy:v.PUBLIC,browser:!1,args:[{name:"id",required:!0,positional:!0,help:"Lobste.rs short_id (e.g. 6cmh6h)"},{name:"limit",type:"int",default:25,help:"Max top-level comments"},{name:"depth",type:"int",default:2,help:"Max reply depth (1=no replies, 2=one level of replies, etc.)"},{name:"replies",type:"int",default:5,help:"Max replies shown per comment at each level"},{name:"max-length",type:"int",default:2000,help:"Max characters per comment body (min 100)"}],columns:["type","author","score","text"],func:async(e)=>{const t=String(e.id||"").trim();if(!/^[a-z0-9]+$/.test(t))throw new f(`Invalid Lobsters short_id: ${e.id}`,"Pass a lowercase alphanumeric id like 6cmh6h");const c=g(e.limit??25,"lobsters read --limit"),p=g(e.depth??2,"lobsters read --depth"),u=g(e.replies??5,"lobsters read --replies"),l=q(e["max-length"]??2000,100,"lobsters read --max-length"),o=await j(t);if(!o||!o.short_id)throw new T(`lobsters/${t}`,"Story not found");const s=[],m=(o.description_plain||R(o.description||"")).trim(),y=m.length>l?m.slice(0,l)+`
9
+ ... [truncated]`:m,h=[o.title||""];if(y)h.push(`
10
+ `+y);if(o.url)h.push(`
11
+ `+o.url);s.push({type:"POST",author:o.submitter_user||"[deleted]",score:o.score??0,text:h.join("").trim()});const I=Array.isArray(o.comments)?o.comments:[],i=new Map;for(const r of I){const n=r.parent_comment||null;if(!i.has(n))i.set(n,[]);i.get(n).push(r)}function b(r,n){if(!r||r.is_deleted||r.is_moderated)return;const d=(r.comment_plain||R(r.comment||"")).trim(),M=d.length>l?d.slice(0,l)+"...":d;s.push({type:n===0?"L0":`L${n}`,author:r.commenting_user||"[deleted]",score:r.score??"",text:C(M,n)});const a=i.get(r.short_id)||[];if(n+1>=p){if(a.length>0)s.push({type:`L${n+1}`,author:"",score:"",text:`${E(n)}[+${a.length} more replies]`});return}const S=a.slice(0,u);for(const P of S)b(P,n+1);const _=a.length-S.length;if(_>0)s.push({type:`L${n+1}`,author:"",score:"",text:`${E(n)}[+${_} more replies]`})}const w=i.get(null)||[],x=w.slice(0,c);for(const r of x)b(r,0);const L=w.length-x.length;if(L>0)s.push({type:"",author:"",score:"",text:`[+${L} more top-level comments]`});return s}});
@@ -1,4 +1,4 @@
1
- import{AuthRequiredError as J,CommandExecutionError as F}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as K}from"../_shared/site-auth.js";const L=`(async () => {
1
+ import{AuthRequiredError as a,CommandExecutionError as e}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as n}from"../_shared/site-auth.js";const m=`(async () => {
2
2
  try {
3
3
  const scripts = Array.from(document.querySelectorAll('script')).map(s => s.textContent || '');
4
4
  let user = null;
@@ -16,4 +16,4 @@ import{AuthRequiredError as J,CommandExecutionError as F}from"@jackwener/opencli
16
16
  } catch (e) {
17
17
  return { kind: 'exception', detail: String(e && e.message || e) };
18
18
  }
19
- })()`;async function G(D){await D.goto("https://maimai.cn/");await D.wait(2);const z=await D.evaluate(L);if(z?.kind==="auth")throw new J("maimai.cn",z.detail);if(z?.kind==="http")throw new F(`HTTP ${z.httpStatus} from Maimai`);if(z?.kind==="exception")throw new F(`Maimai whoami failed: ${z.detail}`);if(!z?.ok)throw new F(`Unexpected Maimai probe: ${JSON.stringify(z)}`);return{user_id:z.user_id,name:z.name,company:z.company}}K({site:"maimai",domain:"maimai.cn",loginUrl:"https://maimai.cn/",columns:["user_id","name","company"],verify:G,poll:G});
19
+ })()`;async function r(t){await t.goto("https://maimai.cn/");await t.wait(2);const i=await t.evaluate(m);if(i?.kind==="auth")throw new a("maimai.cn",i.detail);if(i?.kind==="http")throw new e(`HTTP ${i.httpStatus} from Maimai`);if(i?.kind==="exception")throw new e(`Maimai whoami failed: ${i.detail}`);if(!i?.ok)throw new e(`Unexpected Maimai probe: ${JSON.stringify(i)}`);return{user_id:i.user_id,name:i.name,company:i.company}}n({site:"maimai",domain:"maimai.cn",loginUrl:"https://maimai.cn/",columns:["user_id","name","company"],verify:r,poll:r});
@@ -1,13 +1,13 @@
1
- import{cli as k,Strategy as C}from"@jackwener/opencli/registry";import{CommandExecutionError as T,EmptyResultError as y}from"@jackwener/opencli/errors";k({site:"maimai",name:"search-talents",access:"read",description:"Search for candidates on Maimai with multi-dimensional filters",domain:"maimai.cn",strategy:C.COOKIE,browser:!0,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g., "Java", "产品经理")'},{name:"page",type:"int",default:0,help:"Page number (0-based)"},{name:"size",type:"int",default:20,help:"Results per page"},{name:"positions",help:'Positions (e.g., "运营", "Java 开发工程师")'},{name:"companies",help:'Companies, comma-separated (e.g., "百度", "字节跳动,阿里巴巴")'},{name:"schools",help:'Schools, comma-separated (e.g., "北京大学", "清华大学,复旦大学")'},{name:"provinces",help:'Provinces (e.g., "北京", "上海")'},{name:"cities",help:'Cities (e.g., "北京市", "上海市")'},{name:"worktimes",help:"Work years: 1=1-3y, 2=3-5y, 3=5-10y, 4=10+y"},{name:"degrees",help:"Education: 1=大专,2=本科,3=硕士,4=博士,5=MBA"},{name:"professions",help:"Industries: 01=互联网,02=金融,03=电子,04=通信"},{name:"is_211",type:"int",help:"211 university: 0=any, 1=211"},{name:"is_985",type:"int",help:"985 university: 0=any, 1=985"},{name:"sortby",type:"int",default:0,help:"Sort: 0=relevance, 1=activity, 2=work_years, 3=education"},{name:"is_direct_chat",type:"int",default:0,help:"Direct chat: 0=any, 1=available"}],columns:["name","job_title","company","historical_companies","location","work_year","school","degree","active_status","age","tags","mutual_friends"],func:async(H,U)=>{const{query:M,page:V=0,size:W=20,positions:X="",companies:Z="",schools:$="",provinces:b="",cities:z="",worktimes:B="",degrees:N="",professions:R="",is_211:S=0,is_985:Y=0,sortby:j=0,is_direct_chat:q=0}=U;await H.goto("https://maimai.cn/ent/talents/discover/search_v2",{waitUntil:"networkidle"});await H.waitForTimeout(5000);const v="b92d0fb5-f3fd-1f4b-fcdc-"+Math.random().toString(16).slice(2,14),x="ae907d75-315c-8db7-2cc7-"+Math.random().toString(16).slice(2,14),I={search:{page:V,size:W,sessionid:v,deletesessionid:x,worktimes:B,degrees:N,professions:R,schools:$,positions:X,companyscope:0,sortby:j,is_direct_chat:q,query:M,cities:z,provinces:b,is_211:S,is_985:Y,allcompanies:Z}},F=(await H.getCookies({url:"https://maimai.cn"})).find((A)=>A.name==="csrftoken")?.value||"",G=await H.evaluate(`async () => {
1
+ import{cli as J,Strategy as L}from"@jackwener/opencli/registry";import{CommandExecutionError as m,EmptyResultError as N}from"@jackwener/opencli/errors";J({site:"maimai",name:"search-talents",access:"read",description:"Search for candidates on Maimai with multi-dimensional filters",domain:"maimai.cn",strategy:L.COOKIE,browser:!0,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g., "Java", "产品经理")'},{name:"page",type:"int",default:0,help:"Page number (0-based)"},{name:"size",type:"int",default:20,help:"Results per page"},{name:"positions",help:'Positions (e.g., "运营", "Java 开发工程师")'},{name:"companies",help:'Companies, comma-separated (e.g., "百度", "字节跳动,阿里巴巴")'},{name:"schools",help:'Schools, comma-separated (e.g., "北京大学", "清华大学,复旦大学")'},{name:"provinces",help:'Provinces (e.g., "北京", "上海")'},{name:"cities",help:'Cities (e.g., "北京市", "上海市")'},{name:"worktimes",help:"Work years: 1=1-3y, 2=3-5y, 3=5-10y, 4=10+y"},{name:"degrees",help:"Education: 1=大专,2=本科,3=硕士,4=博士,5=MBA"},{name:"professions",help:"Industries: 01=互联网,02=金融,03=电子,04=通信"},{name:"is_211",type:"int",help:"211 university: 0=any, 1=211"},{name:"is_985",type:"int",help:"985 university: 0=any, 1=985"},{name:"sortby",type:"int",default:0,help:"Sort: 0=relevance, 1=activity, 2=work_years, 3=education"},{name:"is_direct_chat",type:"int",default:0,help:"Direct chat: 0=any, 1=available"}],columns:["name","job_title","company","historical_companies","location","work_year","school","degree","active_status","age","tags","mutual_friends"],func:async(a,d)=>{const{query:n,page:p=0,size:h=20,positions:u="",companies:y="",schools:f="",provinces:_="",cities:g="",worktimes:w="",degrees:v="",professions:k="",is_211:b=0,is_985:C=0,sortby:S=0,is_direct_chat:A=0}=d;await a.goto("https://maimai.cn/ent/talents/discover/search_v2",{waitUntil:"networkidle"});await a.waitForTimeout(5000);const P="b92d0fb5-f3fd-1f4b-fcdc-"+Math.random().toString(16).slice(2,14),j="ae907d75-315c-8db7-2cc7-"+Math.random().toString(16).slice(2,14),E={search:{page:p,size:h,sessionid:P,deletesessionid:j,worktimes:w,degrees:v,professions:k,schools:f,positions:u,companyscope:0,sortby:S,is_direct_chat:A,query:n,cities:g,provinces:_,is_211:b,is_985:C,allcompanies:y}},O=(await a.getCookies({url:"https://maimai.cn"})).find((e)=>e.name==="csrftoken")?.value||"",s=await a.evaluate(`async () => {
2
2
  // Prefer cookie-derived csrftoken (hoisted from CDP); fall back to meta tag
3
- let csrftoken = ${JSON.stringify(F)};
3
+ let csrftoken = ${JSON.stringify(O)};
4
4
 
5
5
  if (!csrftoken) {
6
6
  const meta = document.querySelector('meta[name="csrf-token"]');
7
7
  if (meta) csrftoken = meta.getAttribute('content') || '';
8
8
  }
9
9
 
10
- const body = ${JSON.stringify(I)};
10
+ const body = ${JSON.stringify(E)};
11
11
 
12
12
  const res = await fetch('https://maimai.cn/api/ent/discover/search?channel=www&data_version=3.0&version=1.0.0', {
13
13
  method: 'POST',
@@ -34,4 +34,4 @@ import{cli as k,Strategy as C}from"@jackwener/opencli/registry";import{CommandEx
34
34
  }
35
35
 
36
36
  return result;
37
- }`);if(!G||typeof G!=="object"||Array.isArray(G))throw new T("Maimai search returned malformed API payload");const K=[G.data?.list,G.data?.talent_list,G.list,G.talent_list].find((A)=>Array.isArray(A));if(!K)throw new T("Maimai search API payload missing talent list");if(K.length===0)throw new y("maimai search-talents",`未找到匹配 "${M}" 的候选人`);return K.map((A)=>{const J=A.edu&&A.edu.length>0?A.edu[0]:{},L=A.work_time||A.worktime||"",O=A.company||"",_=(A.exp||[]).map((D)=>D.company).filter((D)=>D&&D.trim()!==""&&D!==O).filter((D,h,E)=>E.indexOf(D)===h).join(" / "),w=(A.tag_list||A.tags||[]).filter((D)=>D&&D.trim()!=="").join(", "),P=A.friends_cnt||A.common_friends_count||0,Q=(A.friends||A.common_friends||[]).map((D)=>D.name||D.user_name||D).slice(0,3).join(", ");return{name:A.name||"",job_title:A.position||A.job_title||"",company:O,historical_companies:_,location:(A.province||"")+(A.city?"·"+A.city:""),work_year:L,school:J.school||J.hover?.name||"",degree:J.sdegree||J.hover?.school_level||"",active_status:A.active_state_v2||A.active_state_v1||A.active_state||"",age:A.age||"",tags:w,mutual_friends:P>0?`${P}人${Q?" ("+Q+")":""}`:""}})}});
37
+ }`);if(!s||typeof s!=="object"||Array.isArray(s))throw new m("Maimai search returned malformed API payload");const i=[s.data?.list,s.data?.talent_list,s.list,s.talent_list].find((e)=>Array.isArray(e));if(!i)throw new m("Maimai search API payload missing talent list");if(i.length===0)throw new N("maimai search-talents",`未找到匹配 "${n}" 的候选人`);return i.map((e)=>{const o=e.edu&&e.edu.length>0?e.edu[0]:{},q=e.work_time||e.worktime||"",r=e.company||"",I=(e.exp||[]).map((t)=>t.company).filter((t)=>t&&t.trim()!==""&&t!==r).filter((t,x,F)=>F.indexOf(t)===x).join(" / "),M=(e.tag_list||e.tags||[]).filter((t)=>t&&t.trim()!=="").join(", "),c=e.friends_cnt||e.common_friends_count||0,l=(e.friends||e.common_friends||[]).map((t)=>t.name||t.user_name||t).slice(0,3).join(", ");return{name:e.name||"",job_title:e.position||e.job_title||"",company:r,historical_companies:I,location:(e.province||"")+(e.city?"·"+e.city:""),work_year:q,school:o.school||o.hover?.name||"",degree:o.sdegree||o.hover?.school_level||"",active_status:e.active_state_v2||e.active_state_v1||e.active_state||"",age:e.age||"",tags:M,mutual_friends:c>0?`${c}人${l?" ("+l+")":""}`:""}})}});
@@ -1,4 +1,4 @@
1
- import{ArgumentError as Q,AuthRequiredError as V,CommandExecutionError as K}from"@jackwener/opencli/errors";export const MANUS_DOMAIN="manus.im",MANUS_URL="https://manus.im/app",API_HOST="https://api.manus.im";export function isManusUrl(z){try{const G=new URL(String(z||"")),B=G.hostname.toLowerCase();return G.protocol==="https:"&&(B===MANUS_DOMAIN||B===`www.${MANUS_DOMAIN}`)}catch{return!1}}export function validatedLimit(z,G,B=1000){const J=z==null?G:Number(z);if(!Number.isFinite(J)||!Number.isInteger(J)||J<1||J>B)throw new Q("limit",`must be a positive integer ≤ ${B}`);return J}export function unwrapEvaluateResult(z){if(z&&typeof z==="object"&&!Array.isArray(z)&&Object.prototype.hasOwnProperty.call(z,"session")&&Object.prototype.hasOwnProperty.call(z,"data"))return z.data;return z}function W(z){if(!z||typeof z!=="object")return"";return[z.message,z.error,z.errorMessage,z.details].find((B)=>typeof B==="string"&&B.trim())?.trim()||""}export function requireObject(z,G){const B=unwrapEvaluateResult(z);if(B?.__authRequired)throw new V(MANUS_DOMAIN,B.message||"Authentication required — please sign in to Manus in the browser");if(B?.__httpError){const J=W(B);throw new K(J?`Manus ${G} failed (HTTP ${B.__httpError}): ${J}`:`Manus ${G} failed (HTTP ${B.__httpError})`)}if(B?.__error)throw new K(`Manus ${G} failed: ${B.message||B.__error}`);if(!B||typeof B!=="object"||Array.isArray(B))throw new K(`Manus ${G} returned a malformed API payload`);return B}export function requireArray(z,G){if(!Array.isArray(z))throw new K(`Manus ${G} returned a malformed API payload`);return z}export function requireString(z,G){const B=String(z??"").trim();if(!B)throw new K(`Manus ${G} returned a malformed API payload`);return B}export async function ensureOnManus(z){const G=unwrapEvaluateResult(await z.evaluate("window.location.href").catch(()=>""));if(isManusUrl(G))return;await z.goto(MANUS_URL);await z.wait(2)}export const MANUS_API_CALL_JS=`
1
+ import{ArgumentError as i,AuthRequiredError as s,CommandExecutionError as o}from"@jackwener/opencli/errors";export const MANUS_DOMAIN="manus.im",MANUS_URL="https://manus.im/app",API_HOST="https://api.manus.im";export function isManusUrl(r){try{const e=new URL(String(r||"")),t=e.hostname.toLowerCase();return e.protocol==="https:"&&(t===MANUS_DOMAIN||t===`www.${MANUS_DOMAIN}`)}catch{return!1}}export function validatedLimit(r,e,t=1000){const n=r==null?e:Number(r);if(!Number.isFinite(n)||!Number.isInteger(n)||n<1||n>t)throw new i("limit",`must be a positive integer ≤ ${t}`);return n}export function unwrapEvaluateResult(r){if(r&&typeof r==="object"&&!Array.isArray(r)&&Object.prototype.hasOwnProperty.call(r,"session")&&Object.prototype.hasOwnProperty.call(r,"data"))return r.data;return r}function a(r){if(!r||typeof r!=="object")return"";return[r.message,r.error,r.errorMessage,r.details].find((t)=>typeof t==="string"&&t.trim())?.trim()||""}export function requireObject(r,e){const t=unwrapEvaluateResult(r);if(t?.__authRequired)throw new s(MANUS_DOMAIN,t.message||"Authentication required — please sign in to Manus in the browser");if(t?.__httpError){const n=a(t);throw new o(n?`Manus ${e} failed (HTTP ${t.__httpError}): ${n}`:`Manus ${e} failed (HTTP ${t.__httpError})`)}if(t?.__error)throw new o(`Manus ${e} failed: ${t.message||t.__error}`);if(!t||typeof t!=="object"||Array.isArray(t))throw new o(`Manus ${e} returned a malformed API payload`);return t}export function requireArray(r,e){if(!Array.isArray(r))throw new o(`Manus ${e} returned a malformed API payload`);return r}export function requireString(r,e){const t=String(r??"").trim();if(!t)throw new o(`Manus ${e} returned a malformed API payload`);return t}export async function ensureOnManus(r){const e=unwrapEvaluateResult(await r.evaluate("window.location.href").catch(()=>""));if(isManusUrl(e))return;await r.goto(MANUS_URL);await r.wait(2)}export const MANUS_API_CALL_JS=`
2
2
  const callManusAPI = async (rpcPath, body) => {
3
3
  const jwt = document.cookie.split('session_id=')[1]?.split(';')[0];
4
4
  if (!jwt) return { __authRequired: true, message: 'session_id cookie missing' };
@@ -1 +1 @@
1
- import{cli as K,Strategy as P}from"@jackwener/opencli/registry";import{TimeoutError as Q}from"@jackwener/opencli/errors";import{readAccessToken as R,readCurrentAccessToken as V,resolveInstance as X}from"./shared.js";const H=300;async function z(f){if(typeof f?.closeWindow!=="function")return;try{await f.closeWindow()}catch{}}K({site:"mastodon",name:"login",access:"write",description:"打开指定 Mastodon 自部署实例的登录页并等待登录完成。用 --site 选择连接名称或实例网址。",domain:"mastodon.social",strategy:P.UI,browser:!0,navigateBefore:!1,defaultWindowMode:"foreground",siteSession:"persistent",args:[{name:"site",required:!1,help:"连接名称或实例网址;省略时使用默认站点"},{name:"instance",required:!1,help:"兼容旧版:实例网址(推荐改用 --site)"},{name:"timeout",type:"int",default:H,help:"等待用户完成登录的最长秒数"}],columns:["status","logged_in","site","instance"],func:async(f,B)=>{const q=X(B);try{await R(f,q.url);await z(f);return[{status:"already_logged_in",logged_in:!0,site:q.name,instance:q.url}]}catch(x){if(x?.code!=="AUTH_REQUIRED")throw x}await f.goto(`${q.url}/auth/sign_in`);const G=Number(B.timeout??H),J=Date.now()+G*1000;while(Date.now()<J){await f.wait(2);const x=await V(f);if(x?.ok&&x.token){await z(f);return[{status:"login_complete",logged_in:!0,site:q.name,instance:q.url}]}}await z(f);throw new Q("mastodon login",G,`请在打开的窗口里完成 ${q.url} 的登录后重试。`)}});
1
+ import{cli as c,Strategy as l}from"@jackwener/opencli/registry";import{TimeoutError as u}from"@jackwener/opencli/errors";import{readAccessToken as d,readCurrentAccessToken as m,resolveInstance as w}from"./shared.js";const r=300;async function o(t){if(typeof t?.closeWindow!=="function")return;try{await t.closeWindow()}catch{}}c({site:"mastodon",name:"login",access:"write",description:"打开指定 Mastodon 自部署实例的登录页并等待登录完成。用 --site 选择连接名称或实例网址。",domain:"mastodon.social",strategy:l.UI,browser:!0,navigateBefore:!1,defaultWindowMode:"foreground",siteSession:"persistent",args:[{name:"site",required:!1,help:"连接名称或实例网址;省略时使用默认站点"},{name:"instance",required:!1,help:"兼容旧版:实例网址(推荐改用 --site)"},{name:"timeout",type:"int",default:r,help:"等待用户完成登录的最长秒数"}],columns:["status","logged_in","site","instance"],func:async(t,i)=>{const e=w(i);try{await d(t,e.url);await o(t);return[{status:"already_logged_in",logged_in:!0,site:e.name,instance:e.url}]}catch(n){if(n?.code!=="AUTH_REQUIRED")throw n}await t.goto(`${e.url}/auth/sign_in`);const s=Number(i.timeout??r),a=Date.now()+s*1000;while(Date.now()<a){await t.wait(2);const n=await m(t);if(n?.ok&&n.token){await o(t);return[{status:"login_complete",logged_in:!0,site:e.name,instance:e.url}]}}await o(t);throw new u("mastodon login",s,`请在打开的窗口里完成 ${e.url} 的登录后重试。`)}});
@@ -1 +1 @@
1
- import*as v from"node:fs";import*as D from"node:path";import{randomUUID as U}from"node:crypto";import{cli as X,Strategy as B}from"@jackwener/opencli/registry";import{ArgumentError as $,CommandExecutionError as F}from"@jackwener/opencli/errors";import{assertLiteralContent as P}from"../_shared/content-guard.js";import{apiErrorText as Y,mastoFormRequest as y,readAccessToken as T,resolveInstance as _,uploadMedia as b}from"./shared.js";const C=4,V=["public","unlisted","private","direct"],L={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".mp4":"video/mp4",".mov":"video/quicktime",".m4v":"video/mp4"};function A(J){const z=String(J).split(",").map((K)=>K.trim()).filter(Boolean);if(z.length>C)throw new $(`媒体过多: ${z.length}(上限 ${C})`);return z.map((K)=>{const G=D.resolve(K),Q=D.extname(G).toLowerCase(),N=L[Q];if(!N)throw new $(`不支持的媒体格式 "${Q}"。支持: ${Object.keys(L).join(", ")}`);const W=v.statSync(G,{throwIfNoEntry:!1});if(!W||!W.isFile())throw new $(`不是有效文件: ${G}`);return{name:D.basename(G),mime:N,base64:v.readFileSync(G).toString("base64")}})}X({site:"mastodon",name:"post",access:"write",description:"发一条嘟文(status)到你登录的 Mastodon 实例。零配置:凭证从浏览器登录态自动获取,无需 API key。"+" 用 --site 选择已保存连接(也可直接传实例网址)。支持图片/视频、可见范围、内容警告、回复。",domain:"mastodon.social",strategy:B.UI,browser:!0,navigateBefore:!1,args:[{name:"status",type:"string",positional:!0,help:"嘟文正文(纯文本发帖必填;仅发媒体时可省)"},{name:"site",type:"string",required:!1,help:"连接名称或实例网址;省略时使用默认站点"},{name:"instance",type:"string",required:!1,help:"兼容旧版:实例网址(推荐改用 --site)"},{name:"media",type:"string",required:!1,help:"媒体路径,逗号分隔,最多 4 个(jpg/png/gif/webp/mp4/mov)"},{name:"visibility",type:"string",default:"public",choices:V,help:"可见范围(默认 public)"},{name:"spoiler",type:"string",required:!1,help:"内容警告文本(CW);设了会自动标记为敏感"},{name:"sensitive",type:"boolean",required:!1,help:"把媒体标记为敏感内容"},{name:"language",type:"string",required:!1,help:"ISO 639 语言码,如 zh、en"},{name:"reply-to",type:"string",required:!1,help:"回复的目标 status id(in_reply_to_id)"}],columns:["status","id","url","visibility"],func:async(J,z)=>{if(!J)throw new F("mastodon post 需要浏览器会话");const{url:K}=_(z),G=String(z.status??"").trim();P(G,{label:"嘟文正文"});const Q=z.media?A(z.media):[];if(!G&&Q.length===0)throw new $("嘟文为空:请传正文,或用 --media 附带媒体。");const N=String(z.visibility??"public");if(!V.includes(N))throw new $(`--visibility 只能是 ${V.join("/")}`);const{token:W}=await T(J,K),j=[];for(const O of Q){const{id:S}=await b(J,{token:W,file:O});j.push(S)}const H=[];if(G)H.push(["status",G]);H.push(["visibility",N]);for(const O of j)H.push(["media_ids[]",O]);if(z.spoiler)H.push(["spoiler_text",String(z.spoiler)]);if(z.sensitive||z.spoiler)H.push(["sensitive","true"]);if(z.language)H.push(["language",String(z.language)]);if(z["reply-to"])H.push(["in_reply_to_id",String(z["reply-to"])]);const Z=await y(J,{path:"/api/v1/statuses",method:"POST",token:W,form:H,headers:{"Idempotency-Key":U()}});if(!Z.ok){const O=Y(Z.json)||Z.text?.slice(0,200)||"";throw new F(`发嘟失败(HTTP ${Z.httpStatus})${O?": "+O:""}`)}const q=Z.json,R=String(q?.id??"").trim();if(!R)throw new F("发嘟响应缺少 status id;请回查后再决定是否重试。");return[{status:"success",id:R,url:q?.url??q?.uri??`${K}/@me/${R}`,visibility:q?.visibility??N}]}});
1
+ import*as y from"node:fs";import*as d from"node:path";import{randomUUID as w}from"node:crypto";import{cli as I,Strategy as _}from"@jackwener/opencli/registry";import{ArgumentError as m,CommandExecutionError as f}from"@jackwener/opencli/errors";import{assertLiteralContent as j}from"../_shared/content-guard.js";import{apiErrorText as q,mastoFormRequest as E,readAccessToken as x,resolveInstance as M,uploadMedia as T}from"./shared.js";const b=4,h=["public","unlisted","private","direct"],v={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".mp4":"video/mp4",".mov":"video/quicktime",".m4v":"video/mp4"};function A(s){const e=String(s).split(",").map((n)=>n.trim()).filter(Boolean);if(e.length>b)throw new m(`媒体过多: ${e.length}(上限 ${b})`);return e.map((n)=>{const t=d.resolve(n),a=d.extname(t).toLowerCase(),o=v[a];if(!o)throw new m(`不支持的媒体格式 "${a}"。支持: ${Object.keys(v).join(", ")}`);const l=y.statSync(t,{throwIfNoEntry:!1});if(!l||!l.isFile())throw new m(`不是有效文件: ${t}`);return{name:d.basename(t),mime:o,base64:y.readFileSync(t).toString("base64")}})}I({site:"mastodon",name:"post",access:"write",description:"发一条嘟文(status)到你登录的 Mastodon 实例。零配置:凭证从浏览器登录态自动获取,无需 API key。"+" 用 --site 选择已保存连接(也可直接传实例网址)。支持图片/视频、可见范围、内容警告、回复。",domain:"mastodon.social",strategy:_.UI,browser:!0,navigateBefore:!1,args:[{name:"status",type:"string",positional:!0,help:"嘟文正文(纯文本发帖必填;仅发媒体时可省)"},{name:"site",type:"string",required:!1,help:"连接名称或实例网址;省略时使用默认站点"},{name:"instance",type:"string",required:!1,help:"兼容旧版:实例网址(推荐改用 --site)"},{name:"media",type:"string",required:!1,help:"媒体路径,逗号分隔,最多 4 个(jpg/png/gif/webp/mp4/mov)"},{name:"visibility",type:"string",default:"public",choices:h,help:"可见范围(默认 public)"},{name:"spoiler",type:"string",required:!1,help:"内容警告文本(CW);设了会自动标记为敏感"},{name:"sensitive",type:"boolean",required:!1,help:"把媒体标记为敏感内容"},{name:"language",type:"string",required:!1,help:"ISO 639 语言码,如 zh、en"},{name:"reply-to",type:"string",required:!1,help:"回复的目标 status id(in_reply_to_id)"}],columns:["status","id","url","visibility"],func:async(s,e)=>{if(!s)throw new f("mastodon post 需要浏览器会话");const{url:n}=M(e),t=String(e.status??"").trim();j(t,{label:"嘟文正文"});const a=e.media?A(e.media):[];if(!t&&a.length===0)throw new m("嘟文为空:请传正文,或用 --media 附带媒体。");const o=String(e.visibility??"public");if(!h.includes(o))throw new m(`--visibility 只能是 ${h.join("/")}`);const{token:l}=await x(s,n),g=[];for(const r of a){const{id:S}=await T(s,{token:l,file:r});g.push(S)}const i=[];if(t)i.push(["status",t]);i.push(["visibility",o]);for(const r of g)i.push(["media_ids[]",r]);if(e.spoiler)i.push(["spoiler_text",String(e.spoiler)]);if(e.sensitive||e.spoiler)i.push(["sensitive","true"]);if(e.language)i.push(["language",String(e.language)]);if(e["reply-to"])i.push(["in_reply_to_id",String(e["reply-to"])]);const p=await E(s,{path:"/api/v1/statuses",method:"POST",token:l,form:i,headers:{"Idempotency-Key":w()}});if(!p.ok){const r=q(p.json)||p.text?.slice(0,200)||"";throw new f(`发嘟失败(HTTP ${p.httpStatus})${r?": "+r:""}`)}const u=p.json,c=String(u?.id??"").trim();if(!c)throw new f("发嘟响应缺少 status id;请回查后再决定是否重试。");return[{status:"success",id:c,url:u?.url??u?.uri??`${n}/@me/${c}`,visibility:u?.visibility??o}]}});
@@ -1,4 +1,4 @@
1
- import{AuthRequiredError as X,CommandExecutionError as W}from"@jackwener/opencli/errors";import{loadSiteConnections as $,normalizeSiteUrl as v,resolveSiteConnection as D}from"../_shared/self-hosted-sites.js";export function normalizeInstanceUrl(B){return v(B,{originOnly:!0,label:"Mastodon 实例网址"})}export function resolveInstance(B={}){return D("mastodon",B,{selector:"site",legacySelectors:["instance"],originOnly:!0})}export function configuredInstances(){return $("mastodon").sites}export async function readCurrentAccessToken(B){return B.evaluate(`(() => {
1
+ import{AuthRequiredError as l,CommandExecutionError as c}from"@jackwener/opencli/errors";import{loadSiteConnections as d,normalizeSiteUrl as h,resolveSiteConnection as S}from"../_shared/self-hosted-sites.js";export function normalizeInstanceUrl(t){return h(t,{originOnly:!0,label:"Mastodon 实例网址"})}export function resolveInstance(t={}){return S("mastodon",t,{selector:"site",legacySelectors:["instance"],originOnly:!0})}export function configuredInstances(){return d("mastodon").sites}export async function readCurrentAccessToken(t){return t.evaluate(`(() => {
2
2
  const el = document.getElementById('initial-state');
3
3
  if (!el) return { ok: false, error: 'no-initial-state' };
4
4
  let state;
@@ -8,13 +8,13 @@ import{AuthRequiredError as X,CommandExecutionError as W}from"@jackwener/opencli
8
8
  const token = meta && meta.access_token;
9
9
  if (!token) return { ok: false, error: 'no-access-token' };
10
10
  return { ok: true, token: token, version: (meta && meta.version) || null };
11
- })()`)}export async function readAccessToken(B,H){await B.goto(`${H}/home`,{waitUntil:"load",settleMs:800});const J=await readCurrentAccessToken(B);if(!J?.ok||!J.token)throw new X(H,`未在 ${H} 检测到登录态(${J?.error??"unknown"});请先在浏览器登录该实例。`);return{token:J.token,version:J.version??null}}export async function mastoFormRequest(B,{path:H,method:J="GET",token:L,form:G=[],headers:K={}}){const Q=G.length>0?new URLSearchParams(G).toString():"",V={Authorization:`Bearer ${L}`,Accept:"application/json",...Q?{"Content-Type":"application/x-www-form-urlencoded"}:{},...K};return O(B,{path:H,method:J,headers:V,body:Q||null})}export async function uploadMedia(B,{token:H,file:J,description:L}){const G=await I(B,{path:"/api/v2/media",token:H,file:J,description:L??null});if(G.httpStatus!==200&&G.httpStatus!==202)throw new W(`媒体上传失败(HTTP ${G.httpStatus}): ${apiErrorText(G.json)||G.text?.slice(0,200)||""}`);const K=String(G.json?.id??"").trim();if(!K)throw new W("媒体上传响应缺少 attachment id");if(G.httpStatus===200&&G.json?.url)return{id:K,url:G.json.url};const Q=1000,V=60000,Z=Date.now()+V;while(Date.now()<Z){await B.wait(1);const N=await mastoFormRequest(B,{path:`/api/v1/media/${K}`,method:"GET",token:H});if(N.httpStatus===200&&N.json?.url)return{id:K,url:N.json.url};if(N.httpStatus!==200&&N.httpStatus!==206)throw new W(`媒体处理查询失败(HTTP ${N.httpStatus})`)}return{id:K,url:null}}export function apiErrorText(B){if(!B||typeof B!=="object")return"";if(typeof B.error==="string")return B.error;if(B.error_description)return String(B.error_description);return""}async function O(B,{path:H,method:J,headers:L,body:G}){const K=await B.evaluate(`(async () => {
11
+ })()`)}export async function readAccessToken(t,n){await t.goto(`${n}/home`,{waitUntil:"load",settleMs:800});const r=await readCurrentAccessToken(t);if(!r?.ok||!r.token)throw new l(n,`未在 ${n} 检测到登录态(${r?.error??"unknown"});请先在浏览器登录该实例。`);return{token:r.token,version:r.version??null}}export async function mastoFormRequest(t,{path:n,method:r="GET",token:a,form:e=[],headers:o={}}){const s=e.length>0?new URLSearchParams(e).toString():"",u={Authorization:`Bearer ${a}`,Accept:"application/json",...s?{"Content-Type":"application/x-www-form-urlencoded"}:{},...o};return m(t,{path:n,method:r,headers:u,body:s||null})}export async function uploadMedia(t,{token:n,file:r,description:a}){const e=await y(t,{path:"/api/v2/media",token:n,file:r,description:a??null});if(e.httpStatus!==200&&e.httpStatus!==202)throw new c(`媒体上传失败(HTTP ${e.httpStatus}): ${apiErrorText(e.json)||e.text?.slice(0,200)||""}`);const o=String(e.json?.id??"").trim();if(!o)throw new c("媒体上传响应缺少 attachment id");if(e.httpStatus===200&&e.json?.url)return{id:o,url:e.json.url};const s=1000,u=60000,p=Date.now()+u;while(Date.now()<p){await t.wait(1);const i=await mastoFormRequest(t,{path:`/api/v1/media/${o}`,method:"GET",token:n});if(i.httpStatus===200&&i.json?.url)return{id:o,url:i.json.url};if(i.httpStatus!==200&&i.httpStatus!==206)throw new c(`媒体处理查询失败(HTTP ${i.httpStatus})`)}return{id:o,url:null}}export function apiErrorText(t){if(!t||typeof t!=="object")return"";if(typeof t.error==="string")return t.error;if(t.error_description)return String(t.error_description);return""}async function m(t,{path:n,method:r,headers:a,body:e}){const o=await t.evaluate(`(async () => {
12
12
  try {
13
- const r = await fetch(${JSON.stringify(H)}, {
14
- method: ${JSON.stringify(J)},
15
- headers: ${JSON.stringify(L)},
13
+ const r = await fetch(${JSON.stringify(n)}, {
14
+ method: ${JSON.stringify(r)},
15
+ headers: ${JSON.stringify(a)},
16
16
  credentials: 'include',
17
- body: ${G===null?"undefined":JSON.stringify(G)},
17
+ body: ${e===null?"undefined":JSON.stringify(e)},
18
18
  });
19
19
  const text = await r.text();
20
20
  let json = null;
@@ -23,18 +23,18 @@ import{AuthRequiredError as X,CommandExecutionError as W}from"@jackwener/opencli
23
23
  } catch (e) {
24
24
  return { httpStatus: 0, ok: false, json: null, text: String(e && e.message || e) };
25
25
  }
26
- })()`);return Y(K,H)}async function I(B,{path:H,token:J,file:L,description:G}){const K=await B.evaluate(`(async () => {
26
+ })()`);return f(o,n)}async function y(t,{path:n,token:r,file:a,description:e}){const o=await t.evaluate(`(async () => {
27
27
  try {
28
- const f = ${JSON.stringify(L)};
28
+ const f = ${JSON.stringify(a)};
29
29
  const bin = atob(f.base64);
30
30
  const bytes = new Uint8Array(bin.length);
31
31
  for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
32
32
  const fd = new FormData();
33
33
  fd.append('file', new File([bytes], f.name, { type: f.mime }), f.name);
34
- ${G?`fd.append('description', ${JSON.stringify(String(G))});`:""}
35
- const r = await fetch(${JSON.stringify(H)}, {
34
+ ${e?`fd.append('description', ${JSON.stringify(String(e))});`:""}
35
+ const r = await fetch(${JSON.stringify(n)}, {
36
36
  method: 'POST',
37
- headers: { 'Authorization': 'Bearer ' + ${JSON.stringify(J)}, 'Accept': 'application/json' },
37
+ headers: { 'Authorization': 'Bearer ' + ${JSON.stringify(r)}, 'Accept': 'application/json' },
38
38
  credentials: 'include',
39
39
  body: fd,
40
40
  });
@@ -45,4 +45,4 @@ import{AuthRequiredError as X,CommandExecutionError as W}from"@jackwener/opencli
45
45
  } catch (e) {
46
46
  return { httpStatus: 0, ok: false, json: null, text: String(e && e.message || e) };
47
47
  }
48
- })()`);return Y(K,H)}function Y(B,H){if(B?.httpStatus===401||B?.httpStatus===403)throw new X("mastodon",`Mastodon API ${H} 返回 HTTP ${B.httpStatus}(登录态失效或缺 write scope)`);return{httpStatus:B?.httpStatus??0,ok:!!B?.ok,json:B?.json??null,text:B?.text??""}}
48
+ })()`);return f(o,n)}function f(t,n){if(t?.httpStatus===401||t?.httpStatus===403)throw new l("mastodon",`Mastodon API ${n} 返回 HTTP ${t.httpStatus}(登录态失效或缺 write scope)`);return{httpStatus:t?.httpStatus??0,ok:!!t?.ok,json:t?.json??null,text:t?.text??""}}
@@ -1 +1 @@
1
- import{cli as r,Strategy as c}from"@jackwener/opencli/registry";import{AuthRequiredError as l}from"@jackwener/opencli/errors";import{configuredInstances as u,mastoFormRequest as m,readAccessToken as d,resolveInstance as f}from"./shared.js";async function g(t){const s=u();for(const e of s){const a=await t.getCookies({url:e.url});if(Array.isArray(a)&&a.some((n)=>n?.value&&n.name==="_mastodon_session"))return{logged_in:!0}}return{logged_in:!1}}r({site:"mastodon",name:"whoami",access:"read",description:"检测 Mastodon 实例的登录状态。用 --site 选择已保存连接(也可直接传实例网址)。",domain:"mastodon.social",strategy:c.UI,browser:!0,navigateBefore:!1,args:[{name:"site",type:"string",required:!1,help:"连接名称或实例网址;省略时使用默认站点"},{name:"instance",type:"string",required:!1,help:"兼容旧版:实例网址(推荐改用 --site)"}],columns:["logged_in","account","display_name","instance"],authStatus:{quickCheck:g},func:async(t,s)=>{const{url:e}=f(s);let a;try{({token:a}=await d(t,e))}catch(i){if(i instanceof l)return[{logged_in:!1,account:"",display_name:"",instance:e}];throw i}const n=await m(t,{path:"/api/v1/accounts/verify_credentials",method:"GET",token:a});if(!n.ok||!n.json?.username)return[{logged_in:!1,account:"",display_name:"",instance:e}];const o=n.json;return[{logged_in:!0,account:o.acct||o.username||"",display_name:o.display_name||"",instance:e}]}});
1
+ import{cli as i,Strategy as c}from"@jackwener/opencli/registry";import{AuthRequiredError as u}from"@jackwener/opencli/errors";import{configuredInstances as l,mastoFormRequest as m,readAccessToken as d,resolveInstance as f}from"./shared.js";async function g(t){const s=l();for(const e of s){const a=await t.getCookies({url:e.url});if(Array.isArray(a)&&a.some((n)=>n?.value&&n.name==="_mastodon_session"))return{logged_in:!0}}return{logged_in:!1}}i({site:"mastodon",name:"whoami",access:"read",description:"检测 Mastodon 实例的登录状态。用 --site 选择已保存连接(也可直接传实例网址)。",domain:"mastodon.social",strategy:c.UI,browser:!0,navigateBefore:!1,args:[{name:"site",type:"string",required:!1,help:"连接名称或实例网址;省略时使用默认站点"},{name:"instance",type:"string",required:!1,help:"兼容旧版:实例网址(推荐改用 --site)"}],columns:["logged_in","account","display_name","instance"],authStatus:{quickCheck:g},func:async(t,s)=>{const{url:e}=f(s);let a;try{({token:a}=await d(t,e))}catch(r){if(r instanceof u)return[{logged_in:!1,account:"",display_name:"",instance:e}];throw r}const n=await m(t,{path:"/api/v1/accounts/verify_credentials",method:"GET",token:a});if(!n.ok||!n.json?.username)return[{logged_in:!1,account:"",display_name:"",instance:e}];const o=n.json;return[{logged_in:!0,account:o.acct||o.username||"",display_name:o.display_name||"",instance:e}]}});
@@ -1 +1 @@
1
- import{cli as d,Strategy as m}from"@jackwener/opencli/registry";import{EmptyResultError as f}from"@jackwener/opencli/errors";import{MAVEN_BASE as v,mavenFetch as h,epochMsToIso as I,requireBoundedInt as $,requireCoord as y}from"./utils.js";d({site:"maven",name:"artifact",access:"read",description:"Fetch a Maven Central artifact's version history (groupId:artifactId[:version])",domain:"search.maven.org",strategy:m.PUBLIC,browser:!1,args:[{name:"coordinate",positional:!0,required:!0,help:'Maven coord "groupId:artifactId" or "groupId:artifactId:version"'},{name:"limit",type:"int",default:20,help:"Max versions (1-200, ignored when version is pinned)"}],columns:["groupId","artifactId","version","packaging","publishedAt","tags","url"],func:async(i)=>{const{groupId:t,artifactId:e,version:a}=y(i.coordinate),c=$(i.limit,20,200),o=[`g:${t}`,`a:${e}`];if(a)o.push(`v:${a}`);const p=o.join(" AND "),g=a?1:c,l=`${v}?q=${encodeURIComponent(p)}&core=gav&rows=${g}&wt=json`,n=await h(l,"maven artifact"),s=Array.isArray(n?.response?.docs)?n.response.docs:[],u=a?`${t}:${e}:${a}`:`${t}:${e}`;if(!s.length)throw new f("maven artifact",`Maven Central has no published versions for ${u}.`);return s.map((r)=>({groupId:String(r.g??t).trim(),artifactId:String(r.a??e).trim(),version:String(r.v??"").trim(),packaging:String(r.p??"").trim(),publishedAt:I(r.timestamp),tags:Array.isArray(r.tags)?r.tags.filter(Boolean).join(", "):"",url:`https://central.sonatype.com/artifact/${t}/${e}/${r.v??""}`.replace(/\/$/,"")}))}});
1
+ import{cli as l,Strategy as u}from"@jackwener/opencli/registry";import{EmptyResultError as f}from"@jackwener/opencli/errors";import{MAVEN_BASE as v,mavenFetch as h,epochMsToIso as I,requireBoundedInt as y,requireCoord as A}from"./utils.js";l({site:"maven",name:"artifact",access:"read",description:"Fetch a Maven Central artifact's version history (groupId:artifactId[:version])",domain:"search.maven.org",strategy:u.PUBLIC,browser:!1,args:[{name:"coordinate",positional:!0,required:!0,help:'Maven coord "groupId:artifactId" or "groupId:artifactId:version"'},{name:"limit",type:"int",default:20,help:"Max versions (1-200, ignored when version is pinned)"}],columns:["groupId","artifactId","version","packaging","publishedAt","tags","url"],func:async(a)=>{const{groupId:t,artifactId:o,version:e}=A(a.coordinate),c=y(a.limit,20,200),i=[`g:${t}`,`a:${o}`];if(e)i.push(`v:${e}`);const p=i.join(" AND "),m=e?1:c,d=`${v}?q=${encodeURIComponent(p)}&core=gav&rows=${m}&wt=json`,n=await h(d,"maven artifact"),s=Array.isArray(n?.response?.docs)?n.response.docs:[],g=e?`${t}:${o}:${e}`:`${t}:${o}`;if(!s.length)throw new f("maven artifact",`Maven Central has no published versions for ${g}.`);return s.map((r)=>({groupId:String(r.g??t).trim(),artifactId:String(r.a??o).trim(),version:String(r.v??"").trim(),packaging:String(r.p??"").trim(),publishedAt:I(r.timestamp),tags:Array.isArray(r.tags)?r.tags.filter(Boolean).join(", "):"",url:`https://central.sonatype.com/artifact/${t}/${o}/${r.v??""}`.replace(/\/$/,"")}))}});
@@ -1 +1 @@
1
- import{cli as u,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as g}from"@jackwener/opencli/errors";import{MAVEN_BASE as d,mavenFetch as h,epochMsToIso as y,requireBoundedInt as v,requireString as f}from"./utils.js";u({site:"maven",name:"search",access:"read",description:"Search Maven Central by keyword (artifact name, groupId, tag)",domain:"search.maven.org",strategy:p.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g. "jackson", "guava", "ai.koog")'},{name:"limit",type:"int",default:30,help:"Max artifacts (1-200)"}],columns:["rank","coordinate","groupId","artifactId","latestVersion","packaging","versions","lastPublished","repository","url"],func:async(a)=>{const o=f(a.query,"query"),n=v(a.limit,30,200),l=`${d}?q=${encodeURIComponent(o)}&rows=${n}&wt=json`,s=await h(l,"maven search"),i=Array.isArray(s?.response?.docs)?s.response.docs:[];if(!i.length)throw new g("maven search",`No Maven Central artifacts matched "${o}".`);return i.slice(0,n).map((r,m)=>{const t=String(r.g??"").trim(),e=String(r.a??"").trim(),c=t&&e?`${t}:${e}`:"";return{rank:m+1,coordinate:c,groupId:t,artifactId:e,latestVersion:String(r.latestVersion??"").trim(),packaging:String(r.p??"").trim(),versions:r.versionCount!=null?Number(r.versionCount):null,lastPublished:y(r.timestamp),repository:String(r.repositoryId??"").trim(),url:c?`https://central.sonatype.com/artifact/${t}/${e}`:""}})}});
1
+ import{cli as u,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as g}from"@jackwener/opencli/errors";import{MAVEN_BASE as d,mavenFetch as y,epochMsToIso as h,requireBoundedInt as f,requireString as v}from"./utils.js";u({site:"maven",name:"search",access:"read",description:"Search Maven Central by keyword (artifact name, groupId, tag)",domain:"search.maven.org",strategy:p.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g. "jackson", "guava", "ai.koog")'},{name:"limit",type:"int",default:30,help:"Max artifacts (1-200)"}],columns:["rank","coordinate","groupId","artifactId","latestVersion","packaging","versions","lastPublished","repository","url"],func:async(o)=>{const a=v(o.query,"query"),n=f(o.limit,30,200),m=`${d}?q=${encodeURIComponent(a)}&rows=${n}&wt=json`,s=await y(m,"maven search"),i=Array.isArray(s?.response?.docs)?s.response.docs:[];if(!i.length)throw new g("maven search",`No Maven Central artifacts matched "${a}".`);return i.slice(0,n).map((r,l)=>{const t=String(r.g??"").trim(),e=String(r.a??"").trim(),c=t&&e?`${t}:${e}`:"";return{rank:l+1,coordinate:c,groupId:t,artifactId:e,latestVersion:String(r.latestVersion??"").trim(),packaging:String(r.p??"").trim(),versions:r.versionCount!=null?Number(r.versionCount):null,lastPublished:h(r.timestamp),repository:String(r.repositoryId??"").trim(),url:c?`https://central.sonatype.com/artifact/${t}/${e}`:""}})}});
@@ -1 +1 @@
1
- import{ArgumentError as J,CommandExecutionError as L,EmptyResultError as Q}from"@jackwener/opencli/errors";export const MAVEN_BASE="https://search.maven.org/solrsearch/select",MAVEN_REPO_BASE="https://repo1.maven.org/maven2";const W="opencli-maven-adapter (+https://github.com/jackwener/OpenCLI)",P=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;export function requireString(B,q){const z=String(B??"").trim();if(!z)throw new J(`maven ${q} cannot be empty`);return z}export function requireBoundedInt(B,q,z,G="limit"){const F=B??q,H=typeof F==="number"?F:Number(F);if(!Number.isInteger(H)||H<=0)throw new J(`maven ${G} must be a positive integer`);if(H>z)throw new J(`maven ${G} must be <= ${z}`);return H}export function requireCoord(B){const q=String(B??"").trim();if(!q)throw new J('maven coordinate is required (e.g. "com.fasterxml.jackson.core:jackson-databind")');const z=q.split(":");if(z.length<2||z.length>3)throw new J(`maven coordinate "${B}" must be "groupId:artifactId" or "groupId:artifactId:version"`);const[G,F,H]=z;if(!G||!F)throw new J(`maven coordinate "${B}" is missing groupId or artifactId`);if(G.length>200||!P.test(G))throw new J(`maven groupId "${G}" is not a valid token`,'Use letters / digits / "_-." (max 200 chars), starting with a letter or digit.');if(F.length>200||!P.test(F))throw new J(`maven artifactId "${F}" is not a valid token`,'Use letters / digits / "_-." (max 200 chars), starting with a letter or digit.');if(H!=null&&H.length>200)throw new J(`maven version "${H}" is too long (max 200 chars).`);return{groupId:G,artifactId:F,version:H??null}}export async function mavenFetch(B,q){let z;try{z=await fetch(B,{headers:{"user-agent":W,accept:"application/json"}})}catch(F){throw new L(`${q} request failed: ${F?.message??F}`,"Check that search.maven.org is reachable from this network.")}if(z.status===404)throw new Q(q,`Maven Central returned 404 for ${B}.`);if(z.status===429)throw new L(`${q} returned HTTP 429 (rate limited)`,"Maven Central throttles bursts; wait a few seconds and retry.");if(!z.ok)throw new L(`${q} returned HTTP ${z.status}`);let G;try{G=await z.json()}catch(F){throw new L(`${q} returned malformed JSON: ${F?.message??F}`)}return G}export function epochMsToIso(B){if(B==null)return null;const q=typeof B==="number"?B:Number(B);if(!Number.isFinite(q)||q<=0)return null;return new Date(q).toISOString().replace(/\.\d+Z$/,"Z")}
1
+ import{ArgumentError as s,CommandExecutionError as a,EmptyResultError as m}from"@jackwener/opencli/errors";export const MAVEN_BASE="https://search.maven.org/solrsearch/select",MAVEN_REPO_BASE="https://repo1.maven.org/maven2";const u="opencli-maven-adapter (+https://github.com/jackwener/OpenCLI)",c=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;export function requireString(r,t){const e=String(r??"").trim();if(!e)throw new s(`maven ${t} cannot be empty`);return e}export function requireBoundedInt(r,t,e,o="limit"){const n=r??t,i=typeof n==="number"?n:Number(n);if(!Number.isInteger(i)||i<=0)throw new s(`maven ${o} must be a positive integer`);if(i>e)throw new s(`maven ${o} must be <= ${e}`);return i}export function requireCoord(r){const t=String(r??"").trim();if(!t)throw new s('maven coordinate is required (e.g. "com.fasterxml.jackson.core:jackson-databind")');const e=t.split(":");if(e.length<2||e.length>3)throw new s(`maven coordinate "${r}" must be "groupId:artifactId" or "groupId:artifactId:version"`);const[o,n,i]=e;if(!o||!n)throw new s(`maven coordinate "${r}" is missing groupId or artifactId`);if(o.length>200||!c.test(o))throw new s(`maven groupId "${o}" is not a valid token`,'Use letters / digits / "_-." (max 200 chars), starting with a letter or digit.');if(n.length>200||!c.test(n))throw new s(`maven artifactId "${n}" is not a valid token`,'Use letters / digits / "_-." (max 200 chars), starting with a letter or digit.');if(i!=null&&i.length>200)throw new s(`maven version "${i}" is too long (max 200 chars).`);return{groupId:o,artifactId:n,version:i??null}}export async function mavenFetch(r,t){let e;try{e=await fetch(r,{headers:{"user-agent":u,accept:"application/json"}})}catch(n){throw new a(`${t} request failed: ${n?.message??n}`,"Check that search.maven.org is reachable from this network.")}if(e.status===404)throw new m(t,`Maven Central returned 404 for ${r}.`);if(e.status===429)throw new a(`${t} returned HTTP 429 (rate limited)`,"Maven Central throttles bursts; wait a few seconds and retry.");if(!e.ok)throw new a(`${t} returned HTTP ${e.status}`);let o;try{o=await e.json()}catch(n){throw new a(`${t} returned malformed JSON: ${n?.message??n}`)}return o}export function epochMsToIso(r){if(r==null)return null;const t=typeof r==="number"?r:Number(r);if(!Number.isFinite(t)||t<=0)return null;return new Date(t).toISOString().replace(/\.\d+Z$/,"Z")}
@@ -1 +1 @@
1
- import{cli as p,Strategy as w}from"@jackwener/opencli/registry";import{ArgumentError as i,CommandExecutionError as l,EmptyResultError as f}from"@jackwener/opencli/errors";const u="https://developer.mozilla.org",y="opencli-mdn-adapter (+https://github.com/jackwener/OpenCLI)",d=new Set(["en-US","de","es","fr","ja","ko","pt-BR","ru","zh-CN","zh-TW"]);function g(r,t){const n=String(r??"").trim();if(!n)throw new i(`mdn ${t} cannot be empty`);return n}function S(r,t,n){const o=r??t,a=typeof o==="number"?o:Number(o);if(!Number.isInteger(a)||a<=0)throw new i("mdn limit must be a positive integer");if(a>n)throw new i(`mdn limit must be <= ${n}`);return a}function $(r){const t=String(r??"en-US").trim();if(!d.has(t))throw new i(`mdn locale "${r}" is not supported`,`Allowed locales: ${[...d].join(" / ")}`);return t}p({site:"mdn",name:"search",access:"read",description:"Search MDN Web Docs by keyword",domain:"developer.mozilla.org",strategy:w.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g. "fetch", "flexbox", "Array.prototype.map")'},{name:"limit",type:"int",default:10,help:"Max results (1-50)"},{name:"locale",default:"en-US",help:"Doc locale (en-US default; de / es / fr / ja / ko / pt-BR / ru / zh-CN / zh-TW)"}],columns:["rank","title","slug","locale","summary","url"],func:async(r)=>{const t=g(r.query,"query"),n=S(r.limit,10,50),o=$(r.locale),a=`${u}/api/v1/search?q=${encodeURIComponent(t)}&locale=${encodeURIComponent(o)}&size=${n}`;let s;try{s=await fetch(a,{headers:{"user-agent":y,accept:"application/json"}})}catch(e){throw new l(`mdn search request failed: ${e?.message??e}`)}if(s.status===429)throw new l("mdn search returned HTTP 429 (rate limited)","MDN throttles bursty traffic; wait a few seconds and retry.");if(!s.ok)throw new l(`mdn search returned HTTP ${s.status}`);let c;try{c=await s.json()}catch(e){throw new l(`mdn search returned malformed JSON: ${e?.message??e}`)}const m=Array.isArray(c?.documents)?c.documents:[];if(!m.length)throw new f("mdn search",`No MDN results matched "${t}" (locale ${o}).`);return m.slice(0,n).map((e,h)=>({rank:h+1,title:String(e.title??""),slug:String(e.slug??""),locale:String(e.locale??o),summary:String(e.summary??"").replace(/\s+/g," ").trim(),url:e.mdn_url?`${u}${e.mdn_url}`:""}))}});
1
+ import{cli as p,Strategy as w}from"@jackwener/opencli/registry";import{ArgumentError as i,CommandExecutionError as l,EmptyResultError as f}from"@jackwener/opencli/errors";const u="https://developer.mozilla.org",y="opencli-mdn-adapter (+https://github.com/jackwener/OpenCLI)",d=new Set(["en-US","de","es","fr","ja","ko","pt-BR","ru","zh-CN","zh-TW"]);function g(r,t){const n=String(r??"").trim();if(!n)throw new i(`mdn ${t} cannot be empty`);return n}function S(r,t,n){const o=r??t,a=typeof o==="number"?o:Number(o);if(!Number.isInteger(a)||a<=0)throw new i("mdn limit must be a positive integer");if(a>n)throw new i(`mdn limit must be <= ${n}`);return a}function b(r){const t=String(r??"en-US").trim();if(!d.has(t))throw new i(`mdn locale "${r}" is not supported`,`Allowed locales: ${[...d].join(" / ")}`);return t}p({site:"mdn",name:"search",access:"read",description:"Search MDN Web Docs by keyword",domain:"developer.mozilla.org",strategy:w.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g. "fetch", "flexbox", "Array.prototype.map")'},{name:"limit",type:"int",default:10,help:"Max results (1-50)"},{name:"locale",default:"en-US",help:"Doc locale (en-US default; de / es / fr / ja / ko / pt-BR / ru / zh-CN / zh-TW)"}],columns:["rank","title","slug","locale","summary","url"],func:async(r)=>{const t=g(r.query,"query"),n=S(r.limit,10,50),o=b(r.locale),a=`${u}/api/v1/search?q=${encodeURIComponent(t)}&locale=${encodeURIComponent(o)}&size=${n}`;let s;try{s=await fetch(a,{headers:{"user-agent":y,accept:"application/json"}})}catch(e){throw new l(`mdn search request failed: ${e?.message??e}`)}if(s.status===429)throw new l("mdn search returned HTTP 429 (rate limited)","MDN throttles bursty traffic; wait a few seconds and retry.");if(!s.ok)throw new l(`mdn search returned HTTP ${s.status}`);let c;try{c=await s.json()}catch(e){throw new l(`mdn search returned malformed JSON: ${e?.message??e}`)}const m=Array.isArray(c?.documents)?c.documents:[];if(!m.length)throw new f("mdn search",`No MDN results matched "${t}" (locale ${o}).`);return m.slice(0,n).map((e,h)=>({rank:h+1,title:String(e.title??""),slug:String(e.slug??""),locale:String(e.locale??o),summary:String(e.summary??"").replace(/\s+/g," ").trim(),url:e.mdn_url?`${u}${e.mdn_url}`:""}))}});
@@ -1,12 +1,12 @@
1
- import{cli as a,Strategy as zz}from"@jackwener/opencli/registry";import{CliError as L,CommandExecutionError as Gz}from"@jackwener/opencli/errors";import{readFile as Jz,stat as Kz}from"node:fs/promises";import{publishArticle as Qz}from"../_shared/article/publish.js";export const mediumProfile={home:"https://medium.com/new-story",outputFormat:"markdown",checkAuth:async(K)=>{try{const W=await(await fetch("https://medium.com/_/graphql",{method:"POST",credentials:"include",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({operationName:"ViewerQuery",query:"query ViewerQuery { viewer { id name username imageId } }",variables:{}})})).json(),$=W&&W.data&&W.data.viewer;if($&&$.id)return{isAuthenticated:!0,userId:$.id,username:$.username||$.name||"",avatar:$.imageId?"https://miro.medium.com/v2/resize:fill:96:96/"+$.imageId:""};return{isAuthenticated:!1}}catch(Q){return{isAuthenticated:!1,error:String(Q&&Q.message||Q)}}},publish:async(K,Q)=>{const W=(z)=>z.replace(/^\s*\]\)\}while\(1\);(<\/x>)?/,""),$=document.documentElement.outerHTML.match(/"xsrfToken":"([^"]+)"/),q=$?$[1]:null;if(!q)return{ok:!1,stage:"xsrf",message:"未能从编辑器页提取 xsrfToken(请确认已登录 medium.com 且停留在 /new-story)"};const P={accept:"application/json","x-requested-with":"XMLHttpRequest","x-xsrf-token":q},D=async(z,J,A)=>{const X=Object.assign({},P);if(A!==void 0)X["content-type"]="application/json";const Z=await fetch("https://medium.com"+z,{method:J||"GET",credentials:"include",headers:X,body:A!==void 0?JSON.stringify(A):void 0});let F=W(await Z.text()),G=null;try{G=JSON.parse(F)}catch(U){}return{status:Z.status,json:G,text:F}},H=(z)=>{const J=[];let A=0,X="";const Z=(F)=>{if(F)X+=F};while(A<z.length){const G=z.slice(A).match(/^(\[([^\]]+)\]\(([^)]+)\)|\*\*([^*]+)\*\*|`([^`]+)`|\*([^*]+)\*|(https?:\/\/[^\s<]+[^\s<.,;:!?")\]]))/);if(!G){Z(z[A]);A+=1;continue}const U=A+(G.index||0);if(U>A)Z(z.slice(A,U));const S=G[1],O=X.length;if(G[2]!==void 0&&G[3]!==void 0){Z(G[2]);J.push({type:3,start:O,end:X.length,href:G[3],title:"",rel:"nofollow",anchorType:0})}else if(G[4]!==void 0){Z(G[4]);J.push({type:1,start:O,end:X.length})}else if(G[5]!==void 0)Z(G[5]);else if(G[6]!==void 0){Z(G[6]);J.push({type:2,start:O,end:X.length})}else if(G[7]!==void 0){Z(G[7]);J.push({type:3,start:O,end:X.length,href:G[7],title:"",rel:"nofollow",anchorType:0})}else Z(S);A=U+S.length}return{text:X,markups:J}},x=(z)=>{const J={paragraph:1,h1:12,h2:2,h3:3,h4:13,blockquote:6,code:8,"ul-li":9,"ol-li":10},A=(z||"").replace(/\r\n/g,`
1
+ import{cli as tt,Strategy as et}from"@jackwener/opencli/registry";import{CliError as U,CommandExecutionError as at}from"@jackwener/opencli/errors";import{readFile as st,stat as it}from"node:fs/promises";import{publishArticle as nt}from"../_shared/article/publish.js";export const mediumProfile={home:"https://medium.com/new-story",outputFormat:"markdown",checkAuth:async(s)=>{try{const r=await(await fetch("https://medium.com/_/graphql",{method:"POST",credentials:"include",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({operationName:"ViewerQuery",query:"query ViewerQuery { viewer { id name username imageId } }",variables:{}})})).json(),c=r&&r.data&&r.data.viewer;if(c&&c.id)return{isAuthenticated:!0,userId:c.id,username:c.username||c.name||"",avatar:c.imageId?"https://miro.medium.com/v2/resize:fill:96:96/"+c.imageId:""};return{isAuthenticated:!1}}catch(i){return{isAuthenticated:!1,error:String(i&&i.message||i)}}},publish:async(s,i)=>{const r=(t)=>t.replace(/^\s*\]\)\}while\(1\);(<\/x>)?/,""),c=document.documentElement.outerHTML.match(/"xsrfToken":"([^"]+)"/),g=c?c[1]:null;if(!g)return{ok:!1,stage:"xsrf",message:"未能从编辑器页提取 xsrfToken(请确认已登录 medium.com 且停留在 /new-story)"};const _={accept:"application/json","x-requested-with":"XMLHttpRequest","x-xsrf-token":g},h=async(t,a,u)=>{const o=Object.assign({},_);if(u!==void 0)o["content-type"]="application/json";const l=await fetch("https://medium.com"+t,{method:a||"GET",credentials:"include",headers:o,body:u!==void 0?JSON.stringify(u):void 0});let m=r(await l.text()),e=null;try{e=JSON.parse(m)}catch(p){}return{status:l.status,json:e,text:m}},y=(t)=>{const a=[];let u=0,o="";const l=(m)=>{if(m)o+=m};while(u<t.length){const e=t.slice(u).match(/^(\[([^\]]+)\]\(([^)]+)\)|\*\*([^*]+)\*\*|`([^`]+)`|\*([^*]+)\*|(https?:\/\/[^\s<]+[^\s<.,;:!?")\]]))/);if(!e){l(t[u]);u+=1;continue}const p=u+(e.index||0);if(p>u)l(t.slice(u,p));const x=e[1],d=o.length;if(e[2]!==void 0&&e[3]!==void 0){l(e[2]);a.push({type:3,start:d,end:o.length,href:e[3],title:"",rel:"nofollow",anchorType:0})}else if(e[4]!==void 0){l(e[4]);a.push({type:1,start:d,end:o.length})}else if(e[5]!==void 0)l(e[5]);else if(e[6]!==void 0){l(e[6]);a.push({type:2,start:d,end:o.length})}else if(e[7]!==void 0){l(e[7]);a.push({type:3,start:d,end:o.length,href:e[7],title:"",rel:"nofollow",anchorType:0})}else l(x);u=p+x.length}return{text:o,markups:a}},O=(t)=>{const a={paragraph:1,h1:12,h2:2,h3:3,h4:13,blockquote:6,code:8,"ul-li":9,"ol-li":10},u=(t||"").replace(/\r\n/g,`
2
2
  `).split(`
3
- `),X=[];let Z=[],F,G=[],U=!1;const S=(V,T,N)=>{const Y=(V||"").trim();if(!Y)return;const B=J[T]||J.paragraph,l=B===J.code?{text:Y,markups:[]}:H(Y);X.push(Object.assign({type:B,text:l.text,markups:l.markups},N?{codeLang:N}:{}))},O=()=>{if(!Z.length)return;const V=Z.join(" ").trim();Z=[];if(!V)return;const T=V.match(/^(#{1,4})\s+(.*)$/);if(T){S(T[2].trim(),"h"+T[1].length);return}const N=V.match(/^>\s?(.*)$/);if(N){S(N[1].trim(),"blockquote");return}const Y=V.match(/^\d+\.\s+(.*)$/);if(Y){S(Y[1].trim(),"ol-li");return}const B=V.match(/^[-*]\s+(.*)$/);if(B){S(B[1].trim(),"ul-li");return}S(V,"paragraph")},o=()=>{if(!G.length){F=void 0;return}X.push(Object.assign({type:J.code,text:G.join(`
4
- `),markups:[]},F?{codeLang:F}:{}));G=[];F=void 0};for(const V of A){const T=V.trim().match(/^!\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)$/i),N=V.trim().match(/^<img\b[^>]*?\bsrc=["']([^"']+)["'][^>]*>$/i);if(T){O();X.push({image:!0,imageUrl:T[2],imageAlt:T[1]||""});continue}if(N){O();const B=V.match(/\balt=["']([^"']+)["']/i);X.push({image:!0,imageUrl:N[1],imageAlt:B&&B[1]||""});continue}const Y=V.match(/^```(\S+)?\s*$/);if(Y){if(U){o();U=!1}else{O();U=!0;F=Y[1]||void 0}continue}if(U){G.push(V);continue}if(!V.trim()){O();continue}if(/^(#{1,4})\s+/.test(V)||/^>\s?/.test(V)||/^\d+\.\s+/.test(V)||/^[-*]\s+/.test(V)){O();Z.push(V);O();continue}Z.push(V.trim())}O();if(U)o();return X},C=async(z)=>{let J,A="image.png";if(/^data:/i.test(z)){J=Q.dataUriToBlob(z);A="image."+(((J.type||"").split("/")[1]||"png").split("+")[0].split(";")[0]||"png")}else{const U=await fetch(z,{credentials:"omit"});if(!U.ok)throw Error("拉取图片失败 HTTP "+U.status);J=await U.blob();try{const O=new URL(z).pathname.split("/").filter(Boolean).pop()||"image.png";A=/\.[a-z0-9]+$/i.test(O)?O:O+".png"}catch(S){}}const X=new FormData;X.append("uploadedFile",J,A);const Z=await fetch("https://medium.com/_/upload?is2x=true",{method:"POST",credentials:"include",headers:{accept:"application/json","x-requested-with":"XMLHttpRequest","x-xsrf-token":q},body:X}),F=JSON.parse(W(await Z.text())),G=F&&F.payload&&F.payload.value||{};if(!G.fileId||!G.imgWidth||!G.imgHeight)throw Error("上传响应缺 fileId/尺寸");return{fileId:G.fileId,w:G.imgWidth,h:G.imgHeight}},j=[],M=[],y=await D("/new-story","POST",{}),w=y.json&&y.json.payload||{},_=w.id||w.value&&w.value.id;if(!_)return{ok:!1,stage:"create",status:y.status,message:"Medium 未返回草稿 postId:"+y.text.slice(0,160)};const n=await D("/_/api/posts/"+_+"/draft"),v=n.json&&n.json.payload||{},m=Array.isArray(v.normalizingDeltas)?v.normalizingDeltas:[],u=v.value&&typeof v.value.latestRev==="number"?v.value.latestRev:0;if(u<0&&m.length){const z=await D("/p/"+_+"/deltas","POST",{baseRev:u,deltas:m});if(z.status>=400)return{ok:!1,stage:"init",status:z.status,message:"初始化草稿失败"}}const b=await D("/_/api/posts/"+_),p=b.json&&b.json.payload&&b.json.payload.value||{},t=typeof p.latestRev==="number"?p.latestRev:0,R=K.params||{};let E=x(K.markdown||K.content||"");if(K.title&&E.length&&!E[0].image&&E[0].type===12&&(E[0].text||"").trim()===K.title.trim())E=E.slice(1);const c=[];if(K.title&&K.title.trim())c.push({type:3,text:K.title.trim(),markups:[]});if(R.subtitle&&String(R.subtitle).trim())c.push({type:4,text:String(R.subtitle).trim(),markups:[]});const r=c.concat(E),I=[];let h=0;for(const z of r){if(z.image){try{const J=await C(z.imageUrl);I.push({type:1,index:h,paragraph:{type:4,text:z.imageAlt||"",markups:[],layout:1,metadata:{id:J.fileId,originalWidth:J.w,originalHeight:J.h}}});j.push(z.imageUrl);h+=1}catch(J){M.push({src:z.imageUrl,error:String(J&&J.message||J)})}continue}I.push(Object.assign({type:1,index:h,paragraph:Object.assign({type:z.type,text:z.text,markups:z.markups||[]},z.codeLang?{codeLang:z.codeLang}:{})}));h+=1}if(!I.length)return{ok:!1,stage:"content",message:"正文为空,无可写入的段落"};const f=await D("/p/"+_+"/deltas","POST",{baseRev:t,deltas:I});if(f.status>=400)return{ok:!1,stage:"write",status:f.status,message:"写入正文失败:"+f.text.slice(0,160),uploaded:j,failed:M};const d=Array.isArray(R.tags)?R.tags.filter(Boolean).slice(0,5):[];if(d.length){const z=await D("/_/graphql","POST",{operationName:"SetPostTagsMutation",query:`mutation SetPostTagsMutation($targetPostId: ID!, $tagNames: [String!]!) {
3
+ `),o=[];let l=[],m,e=[],p=!1;const x=(n,b,N)=>{const I=(n||"").trim();if(!I)return;const S=a[b]||a.paragraph,X=S===a.code?{text:I,markups:[]}:y(I);o.push(Object.assign({type:S,text:X.text,markups:X.markups},N?{codeLang:N}:{}))},d=()=>{if(!l.length)return;const n=l.join(" ").trim();l=[];if(!n)return;const b=n.match(/^(#{1,4})\s+(.*)$/);if(b){x(b[2].trim(),"h"+b[1].length);return}const N=n.match(/^>\s?(.*)$/);if(N){x(N[1].trim(),"blockquote");return}const I=n.match(/^\d+\.\s+(.*)$/);if(I){x(I[1].trim(),"ol-li");return}const S=n.match(/^[-*]\s+(.*)$/);if(S){x(S[1].trim(),"ul-li");return}x(n,"paragraph")},Q=()=>{if(!e.length){m=void 0;return}o.push(Object.assign({type:a.code,text:e.join(`
4
+ `),markups:[]},m?{codeLang:m}:{}));e=[];m=void 0};for(const n of u){const b=n.trim().match(/^!\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)$/i),N=n.trim().match(/^<img\b[^>]*?\bsrc=["']([^"']+)["'][^>]*>$/i);if(b){d();o.push({image:!0,imageUrl:b[2],imageAlt:b[1]||""});continue}if(N){d();const S=n.match(/\balt=["']([^"']+)["']/i);o.push({image:!0,imageUrl:N[1],imageAlt:S&&S[1]||""});continue}const I=n.match(/^```(\S+)?\s*$/);if(I){if(p){Q();p=!1}else{d();p=!0;m=I[1]||void 0}continue}if(p){e.push(n);continue}if(!n.trim()){d();continue}if(/^(#{1,4})\s+/.test(n)||/^>\s?/.test(n)||/^\d+\.\s+/.test(n)||/^[-*]\s+/.test(n)){d();l.push(n);d();continue}l.push(n.trim())}d();if(p)Q();return o},k=async(t)=>{let a,u="image.png";if(/^data:/i.test(t)){a=i.dataUriToBlob(t);u="image."+(((a.type||"").split("/")[1]||"png").split("+")[0].split(";")[0]||"png")}else{const p=await fetch(t,{credentials:"omit"});if(!p.ok)throw Error("拉取图片失败 HTTP "+p.status);a=await p.blob();try{const d=new URL(t).pathname.split("/").filter(Boolean).pop()||"image.png";u=/\.[a-z0-9]+$/i.test(d)?d:d+".png"}catch(x){}}const o=new FormData;o.append("uploadedFile",a,u);const l=await fetch("https://medium.com/_/upload?is2x=true",{method:"POST",credentials:"include",headers:{accept:"application/json","x-requested-with":"XMLHttpRequest","x-xsrf-token":g},body:o}),m=JSON.parse(r(await l.text())),e=m&&m.payload&&m.payload.value||{};if(!e.fileId||!e.imgWidth||!e.imgHeight)throw Error("上传响应缺 fileId/尺寸");return{fileId:e.fileId,w:e.imgWidth,h:e.imgHeight}},P=[],w=[],j=await h("/new-story","POST",{}),M=j.json&&j.json.payload||{},f=M.id||M.value&&M.value.id;if(!f)return{ok:!1,stage:"create",status:j.status,message:"Medium 未返回草稿 postId:"+j.text.slice(0,160)};const H=await h("/_/api/posts/"+f+"/draft"),A=H.json&&H.json.payload||{},B=Array.isArray(A.normalizingDeltas)?A.normalizingDeltas:[],F=A.value&&typeof A.value.latestRev==="number"?A.value.latestRev:0;if(F<0&&B.length){const t=await h("/p/"+f+"/deltas","POST",{baseRev:F,deltas:B});if(t.status>=400)return{ok:!1,stage:"init",status:t.status,message:"初始化草稿失败"}}const D=await h("/_/api/posts/"+f),J=D.json&&D.json.payload&&D.json.payload.value||{},G=typeof J.latestRev==="number"?J.latestRev:0,T=s.params||{};let v=O(s.markdown||s.content||"");if(s.title&&v.length&&!v[0].image&&v[0].type===12&&(v[0].text||"").trim()===s.title.trim())v=v.slice(1);const R=[];if(s.title&&s.title.trim())R.push({type:3,text:s.title.trim(),markups:[]});if(T.subtitle&&String(T.subtitle).trim())R.push({type:4,text:String(T.subtitle).trim(),markups:[]});const K=R.concat(v),L=[];let q=0;for(const t of K){if(t.image){try{const a=await k(t.imageUrl);L.push({type:1,index:q,paragraph:{type:4,text:t.imageAlt||"",markups:[],layout:1,metadata:{id:a.fileId,originalWidth:a.w,originalHeight:a.h}}});P.push(t.imageUrl);q+=1}catch(a){w.push({src:t.imageUrl,error:String(a&&a.message||a)})}continue}L.push(Object.assign({type:1,index:q,paragraph:Object.assign({type:t.type,text:t.text,markups:t.markups||[]},t.codeLang?{codeLang:t.codeLang}:{})}));q+=1}if(!L.length)return{ok:!1,stage:"content",message:"正文为空,无可写入的段落"};const E=await h("/p/"+f+"/deltas","POST",{baseRev:G,deltas:L});if(E.status>=400)return{ok:!1,stage:"write",status:E.status,message:"写入正文失败:"+E.text.slice(0,160),uploaded:P,failed:w};const z=Array.isArray(T.tags)?T.tags.filter(Boolean).slice(0,5):[];if(z.length){const t=await h("/_/graphql","POST",{operationName:"SetPostTagsMutation",query:`mutation SetPostTagsMutation($targetPostId: ID!, $tagNames: [String!]!) {
5
5
  setPostTags(targetPostId: $targetPostId, tagNames: $tagNames) {
6
6
  id
7
7
  }
8
- }`,variables:{targetPostId:_,tagNames:d}});if(z.status>=400||z.json&&z.json.errors)M.push({src:"tags",error:"设置标签失败:"+(z.text||"").slice(0,120)})}if(R.canonicalUrl&&String(R.canonicalUrl).trim())await D("/_/graphql","POST",{operationName:"UpdateCanonicalUrl",query:`mutation UpdateCanonicalUrl($input: UpdateCanonicalUrlInput!) {
8
+ }`,variables:{targetPostId:f,tagNames:z}});if(t.status>=400||t.json&&t.json.errors)w.push({src:"tags",error:"设置标签失败:"+(t.text||"").slice(0,120)})}if(T.canonicalUrl&&String(T.canonicalUrl).trim())await h("/_/graphql","POST",{operationName:"UpdateCanonicalUrl",query:`mutation UpdateCanonicalUrl($input: UpdateCanonicalUrlInput!) {
9
9
  updateCanonicalUrl(input: $input) {
10
10
  __typename
11
11
  }
12
- }`,variables:{input:{postId:_,url:String(R.canonicalUrl).trim()}}});const s="https://medium.com/p/"+_+"/edit";if(K.draftOnly)return{ok:!0,id:_,url:s,draft:!0,uploaded:j,failed:M};const k=await D("/p/"+_+"/publish","POST",{});if(k.status>=400)return{ok:!1,stage:"publish",status:k.status,message:"发布失败:"+k.text.slice(0,200),uploaded:j,failed:M};const g=await D("/_/api/posts/"+_),i=g.json&&g.json.payload&&g.json.payload.value||{},e=i.mediumUrl||(i.uniqueSlug?"https://medium.com/p/"+_:"https://medium.com/p/"+_);return{ok:!0,id:_,url:e,draft:!1,uploaded:j,failed:M}}},mediumAuthProfile={home:"https://medium.com/",checkAuth:mediumProfile.checkAuth};function Vz(K){if(!K.execute)throw new L("INVALID_INPUT","此命令需要 --execute 参数才能执行写操作。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}async function Wz(K){const Q=typeof K.text==="string"?K.text:void 0,W=typeof K.file==="string"?K.file:void 0;if(Q&&W)throw new L("INVALID_INPUT","不能同时指定正文参数和 --file,请二选一");let $=Q??"";if(W){let q;try{q=await Kz(W)}catch{throw new L("INVALID_INPUT","文件不存在: "+W)}if(!q.isFile())throw new L("INVALID_INPUT","必须是可读的文本文件: "+W);let P;try{P=await Jz(W)}catch{throw new L("INVALID_INPUT","无法读取文件: "+W)}try{$=new TextDecoder("utf-8",{fatal:!0}).decode(P)}catch{throw new L("INVALID_INPUT","文件必须是 UTF-8 编码: "+W)}}if(!$.trim())throw new L("INVALID_INPUT","正文不能为空");return $}function Xz(K,Q,W,$,q={}){return[{status:"success",outcome:$,message:K,target_type:"article",target:Q,...q}]}a({site:"medium",name:"article",access:"write",description:"发布 Medium 文章(走 medium.com 内部编辑器端点,非官方 API)。默认正式发布;加 --draft 仅存草稿。正文 Markdown,图片自动转存 Medium 图床。可选 --tags/--subtitle/--canonical-url。",domain:"medium.com",strategy:zz.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题(作为 Medium 文章标题)"},{name:"text",positional:!0,help:"文章正文(Markdown)"},{name:"file",help:"正文文件路径(UTF-8,Markdown)"},{name:"tags",help:'Medium 话题标签,逗号分隔,最多 5 个(如 "AI,Programming,Open Source")'},{name:"subtitle",help:"副标题(可选,显示在标题下方)"},{name:"canonical-url",help:"原文规范链接(可选,内容首发别处时填,避免 SEO 重复)"},{name:"draft",type:"boolean",help:"仅保存草稿,不正式发布"},{name:"execute",type:"boolean",help:"确认执行写操作。不加此参数则拒绝写入。"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(K,Q)=>{if(!K)throw new Gz("Medium 文章发布需要浏览器会话");Vz(Q);const W=String(Q.title??"").trim();if(!W)throw new L("INVALID_INPUT","文章标题不能为空");const $=await Wz(Q),q=Boolean(Q.draft),D={tags:String(Q.tags??"").split(",").map((y)=>y.trim()).filter(Boolean),subtitle:typeof Q.subtitle==="string"?Q.subtitle:"",canonicalUrl:typeof Q["canonical-url"]==="string"?Q["canonical-url"]:""},H=await Qz(K,{title:W,body:$,format:"markdown",draftOnly:q,profile:mediumProfile,publishParams:D}),x=H.images.uploaded.length|0,C=H.images.failed.length|0;let j=H.draft?"Medium 草稿已保存(可在编辑器内手动发布)":"Medium 文章已正式发布";if(x||C)j+=";图片:"+x+" 张已转存"+(C?","+C+" 张失败(失败明细见 images_failed)":"");const M=Xz(j,"",H.url,H.draft?"draft":"publish",{created_target:"article:"+H.id,created_url:H.url});if(C){M[0].status="partial";M[0].images_failed=JSON.stringify(H.images.failed)}return M}});
12
+ }`,variables:{input:{postId:f,url:String(T.canonicalUrl).trim()}}});const Y="https://medium.com/p/"+f+"/edit";if(s.draftOnly)return{ok:!0,id:f,url:Y,draft:!0,uploaded:P,failed:w};const V=await h("/p/"+f+"/publish","POST",{});if(V.status>=400)return{ok:!1,stage:"publish",status:V.status,message:"发布失败:"+V.text.slice(0,200),uploaded:P,failed:w};const C=await h("/_/api/posts/"+f),W=C.json&&C.json.payload&&C.json.payload.value||{},Z=W.mediumUrl||(W.uniqueSlug?"https://medium.com/p/"+f:"https://medium.com/p/"+f);return{ok:!0,id:f,url:Z,draft:!1,uploaded:P,failed:w}}},mediumAuthProfile={home:"https://medium.com/",checkAuth:mediumProfile.checkAuth};function rt(s){if(!s.execute)throw new U("INVALID_INPUT","此命令需要 --execute 参数才能执行写操作。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}async function ot(s){const i=typeof s.text==="string"?s.text:void 0,r=typeof s.file==="string"?s.file:void 0;if(i&&r)throw new U("INVALID_INPUT","不能同时指定正文参数和 --file,请二选一");let c=i??"";if(r){let g;try{g=await it(r)}catch{throw new U("INVALID_INPUT","文件不存在: "+r)}if(!g.isFile())throw new U("INVALID_INPUT","必须是可读的文本文件: "+r);let _;try{_=await st(r)}catch{throw new U("INVALID_INPUT","无法读取文件: "+r)}try{c=new TextDecoder("utf-8",{fatal:!0}).decode(_)}catch{throw new U("INVALID_INPUT","文件必须是 UTF-8 编码: "+r)}}if(!c.trim())throw new U("INVALID_INPUT","正文不能为空");return c}function lt(s,i,r,c,g={}){return[{status:"success",outcome:c,message:s,target_type:"article",target:i,...g}]}tt({site:"medium",name:"article",access:"write",description:"发布 Medium 文章(走 medium.com 内部编辑器端点,非官方 API)。默认正式发布;加 --draft 仅存草稿。正文 Markdown,图片自动转存 Medium 图床。可选 --tags/--subtitle/--canonical-url。",domain:"medium.com",strategy:et.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题(作为 Medium 文章标题)"},{name:"text",positional:!0,help:"文章正文(Markdown)"},{name:"file",help:"正文文件路径(UTF-8,Markdown)"},{name:"tags",help:'Medium 话题标签,逗号分隔,最多 5 个(如 "AI,Programming,Open Source")'},{name:"subtitle",help:"副标题(可选,显示在标题下方)"},{name:"canonical-url",help:"原文规范链接(可选,内容首发别处时填,避免 SEO 重复)"},{name:"draft",type:"boolean",help:"仅保存草稿,不正式发布"},{name:"execute",type:"boolean",help:"确认执行写操作。不加此参数则拒绝写入。"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(s,i)=>{if(!s)throw new at("Medium 文章发布需要浏览器会话");rt(i);const r=String(i.title??"").trim();if(!r)throw new U("INVALID_INPUT","文章标题不能为空");const c=await ot(i),g=Boolean(i.draft),h={tags:String(i.tags??"").split(",").map((j)=>j.trim()).filter(Boolean),subtitle:typeof i.subtitle==="string"?i.subtitle:"",canonicalUrl:typeof i["canonical-url"]==="string"?i["canonical-url"]:""},y=await nt(s,{title:r,body:c,format:"markdown",draftOnly:g,profile:mediumProfile,publishParams:h}),O=y.images.uploaded.length|0,k=y.images.failed.length|0;let P=y.draft?"Medium 草稿已保存(可在编辑器内手动发布)":"Medium 文章已正式发布";if(O||k)P+=";图片:"+O+" 张已转存"+(k?","+k+" 张失败(失败明细见 images_failed)":"");const w=lt(P,"",y.url,y.draft?"draft":"publish",{created_target:"article:"+y.id,created_url:y.url});if(k){w[0].status="partial";w[0].images_failed=JSON.stringify(y.images.failed)}return w}});
@@ -1 +1 @@
1
- import{registerArticleLogin as k}from"../_shared/article/login.js";import{mediumAuthProfile as b}from"./article.js";k({site:"medium",domain:"medium.com",profile:{home:b.home,checkAuth:b.checkAuth},loginDescription:"打开 Medium 首页并等待浏览器完成登录(供桌面客户端引导登录)。"});
1
+ import{registerArticleLogin as e}from"../_shared/article/login.js";import{mediumAuthProfile as i}from"./article.js";e({site:"medium",domain:"medium.com",profile:{home:i.home,checkAuth:i.checkAuth},loginDescription:"打开 Medium 首页并等待浏览器完成登录(供桌面客户端引导登录)。"});