publishport-opencli 1.0.19 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1042) hide show
  1. package/cli-manifest.json +35 -0
  2. package/clis/12306/me.js +2 -2
  3. package/clis/12306/orders.js +3 -3
  4. package/clis/12306/passengers.js +3 -3
  5. package/clis/12306/price.js +1 -1
  6. package/clis/12306/stations.js +1 -1
  7. package/clis/12306/train.js +1 -1
  8. package/clis/12306/trains.js +1 -1
  9. package/clis/12306/utils.js +1 -1
  10. package/clis/1688/download.js +1 -1
  11. package/clis/1688/item.js +4 -4
  12. package/clis/1688/search.js +4 -4
  13. package/clis/1688/store.js +4 -4
  14. package/clis/1point3acres/forum.js +1 -1
  15. package/clis/1point3acres/forums.js +1 -1
  16. package/clis/1point3acres/notifications.js +1 -1
  17. package/clis/1point3acres/search.js +1 -1
  18. package/clis/1point3acres/thread.js +2 -2
  19. package/clis/1point3acres/user.js +1 -1
  20. package/clis/1point3acres/utils.js +2 -2
  21. package/clis/36kr/article.js +2 -2
  22. package/clis/36kr/hot.js +2 -2
  23. package/clis/36kr/news.js +1 -1
  24. package/clis/36kr/search.js +2 -2
  25. package/clis/51job/company.js +2 -2
  26. package/clis/51job/detail.js +2 -2
  27. package/clis/51job/hot.js +1 -1
  28. package/clis/51job/search.js +1 -1
  29. package/clis/51job/utils.js +7 -7
  30. package/clis/_atlassian/shared.js +9 -9
  31. package/clis/_shared/article/auth.js +4 -4
  32. package/clis/_shared/article/douban-md2draft.js +4 -4
  33. package/clis/_shared/article/format.js +1 -1
  34. package/clis/_shared/article/images.js +7 -7
  35. package/clis/_shared/article/login.js +1 -1
  36. package/clis/_shared/article/publish.js +11 -11
  37. package/clis/_shared/common.js +1 -1
  38. package/clis/_shared/content-guard.js +1 -1
  39. package/clis/_shared/desktop-commands.js +1 -1
  40. package/clis/_shared/file-inject.js +12 -12
  41. package/clis/_shared/self-hosted-sites.js +2 -2
  42. package/clis/_shared/site-auth.js +1 -1
  43. package/clis/_shared/token-auth.js +2 -2
  44. package/clis/_shared/video-publish.js +9 -9
  45. package/clis/amazon/offer.js +3 -3
  46. package/clis/amazon/product.js +5 -5
  47. package/clis/amazon/shared.js +6 -6
  48. package/clis/antigravity/_actions.js +13 -13
  49. package/clis/antigravity/audit-extras.js +10 -10
  50. package/clis/antigravity/delete.js +1 -1
  51. package/clis/antigravity/model.js +6 -6
  52. package/clis/antigravity/new.js +2 -2
  53. package/clis/antigravity/read.js +2 -2
  54. package/clis/antigravity/rename.js +1 -1
  55. package/clis/antigravity/send.js +3 -3
  56. package/clis/antigravity/serve.js +17 -17
  57. package/clis/antigravity/storage.js +6 -6
  58. package/clis/antigravity/watch.js +2 -2
  59. package/clis/apple-podcasts/episodes.js +1 -1
  60. package/clis/apple-podcasts/top.js +1 -1
  61. package/clis/apple-podcasts/utils.js +1 -1
  62. package/clis/archive/item.js +1 -1
  63. package/clis/archive/search.js +1 -1
  64. package/clis/archive/snapshots.js +1 -1
  65. package/clis/archive/wayback.js +1 -1
  66. package/clis/arxiv/author.js +1 -1
  67. package/clis/arxiv/utils.js +1 -1
  68. package/clis/autohome/brand.js +1 -1
  69. package/clis/autohome/score.js +1 -1
  70. package/clis/autohome/utils.js +1 -1
  71. package/clis/baijiahao/article.js +1 -1
  72. package/clis/baijiahao/lists.js +1 -1
  73. package/clis/baijiahao/login.js +1 -1
  74. package/clis/baijiahao/publish.js +9 -9
  75. package/clis/baijiahao/stats.js +1 -1
  76. package/clis/baijiahao/whoami.js +1 -1
  77. package/clis/band/bands.js +2 -2
  78. package/clis/band/mentions.js +2 -2
  79. package/clis/band/post.js +4 -4
  80. package/clis/band/posts.js +3 -3
  81. package/clis/barchart/flow.js +3 -3
  82. package/clis/barchart/greeks.js +2 -2
  83. package/clis/barchart/quote.js +3 -3
  84. package/clis/bbc/news.js +1 -1
  85. package/clis/bbc/topic.js +1 -1
  86. package/clis/bbc/utils.js +1 -1
  87. package/clis/bilibili/article.js +1 -1
  88. package/clis/bilibili/categories.js +1 -1
  89. package/clis/bilibili/coin.js +1 -1
  90. package/clis/bilibili/comment-del.js +1 -1
  91. package/clis/bilibili/comment-like.js +1 -1
  92. package/clis/bilibili/comment.js +1 -1
  93. package/clis/bilibili/comments.js +1 -1
  94. package/clis/bilibili/dm-list.js +1 -1
  95. package/clis/bilibili/dm-read.js +1 -1
  96. package/clis/bilibili/dm-send.js +1 -1
  97. package/clis/bilibili/download.js +2 -2
  98. package/clis/bilibili/drafts.js +1 -1
  99. package/clis/bilibili/dynamic-post.js +3 -3
  100. package/clis/bilibili/favorite-add.js +1 -1
  101. package/clis/bilibili/favorite.js +1 -1
  102. package/clis/bilibili/feed.js +2 -2
  103. package/clis/bilibili/follow.js +1 -1
  104. package/clis/bilibili/following.js +1 -1
  105. package/clis/bilibili/like.js +1 -1
  106. package/clis/bilibili/partitions.js +1 -1
  107. package/clis/bilibili/stats.js +1 -1
  108. package/clis/bilibili/subtitle.js +3 -3
  109. package/clis/bilibili/summary.js +1 -1
  110. package/clis/bilibili/topics.js +1 -1
  111. package/clis/bilibili/unfollow.js +1 -1
  112. package/clis/bilibili/upload.js +1 -1
  113. package/clis/bilibili/utils.js +10 -10
  114. package/clis/bilibili/video-drafts.js +1 -1
  115. package/clis/bilibili/video.js +1 -1
  116. package/clis/bloomberg/businessweek.js +4 -4
  117. package/clis/bloomberg/news.js +2 -2
  118. package/clis/bloomberg/utils.js +13 -13
  119. package/clis/bluesky/post.js +1 -1
  120. package/clis/bluesky/shared.js +11 -11
  121. package/clis/bluesky/whoami.js +1 -1
  122. package/clis/booking/search.js +2 -2
  123. package/clis/boss/accept.js +1 -1
  124. package/clis/boss/applied.js +1 -1
  125. package/clis/boss/auth.js +1 -1
  126. package/clis/boss/batchgreet.js +1 -1
  127. package/clis/boss/bossinfo.js +1 -1
  128. package/clis/boss/chatlist.js +1 -1
  129. package/clis/boss/chatmsg.js +1 -1
  130. package/clis/boss/cities.js +1 -1
  131. package/clis/boss/detail.js +1 -1
  132. package/clis/boss/exchange.js +1 -1
  133. package/clis/boss/greet.js +1 -1
  134. package/clis/boss/interviews.js +1 -1
  135. package/clis/boss/invite.js +1 -1
  136. package/clis/boss/joblist.js +1 -1
  137. package/clis/boss/mark.js +1 -1
  138. package/clis/boss/me.js +2 -2
  139. package/clis/boss/recommend.js +1 -1
  140. package/clis/boss/resumedelete.js +1 -1
  141. package/clis/boss/resumelist.js +1 -1
  142. package/clis/boss/resumeupload.js +11 -11
  143. package/clis/boss/search.js +1 -1
  144. package/clis/boss/send.js +1 -1
  145. package/clis/boss/sendresume.js +1 -1
  146. package/clis/boss/stats.js +1 -1
  147. package/clis/boss/unread.js +1 -1
  148. package/clis/boss/utils.js +13 -13
  149. package/clis/chaoxing/assignments.js +1 -1
  150. package/clis/chaoxing/exams.js +1 -1
  151. package/clis/chaoxing/utils.js +9 -9
  152. package/clis/chatgpt/ask.js +1 -1
  153. package/clis/chatgpt/auth.js +2 -2
  154. package/clis/chatgpt/detail.js +1 -1
  155. package/clis/chatgpt/image.js +1 -1
  156. package/clis/chatgpt/read.js +1 -1
  157. package/clis/chatgpt/send.js +1 -1
  158. package/clis/chatgpt/utils.js +59 -59
  159. package/clis/chatgpt-app/ask.js +1 -1
  160. package/clis/chatgpt-app/send.js +1 -1
  161. package/clis/chatwise/model.js +6 -6
  162. package/clis/chess/analyze.js +1 -1
  163. package/clis/chess/game.js +1 -1
  164. package/clis/chess/games.js +1 -1
  165. package/clis/chess/stats.js +1 -1
  166. package/clis/chess/utils.js +1 -1
  167. package/clis/claude/ask.js +2 -2
  168. package/clis/claude/detail.js +1 -1
  169. package/clis/claude/new.js +1 -1
  170. package/clis/claude/read.js +1 -1
  171. package/clis/claude/send.js +1 -1
  172. package/clis/claude/utils.js +23 -23
  173. package/clis/cnblogs/article.js +1 -1
  174. package/clis/cnblogs/login.js +1 -1
  175. package/clis/cnblogs/stats.js +7 -7
  176. package/clis/cnblogs/whoami.js +1 -1
  177. package/clis/codex/_actions.js +3 -3
  178. package/clis/codex/archive.js +1 -1
  179. package/clis/codex/ask.js +6 -6
  180. package/clis/codex/model.js +8 -8
  181. package/clis/codex/pin.js +1 -1
  182. package/clis/codex/rename.js +4 -4
  183. package/clis/codex/send.js +3 -3
  184. package/clis/codex/sidebar.js +1 -1
  185. package/clis/coingecko/categories.js +1 -1
  186. package/clis/coingecko/coin.js +1 -1
  187. package/clis/coingecko/derivatives.js +1 -1
  188. package/clis/coingecko/exchanges.js +1 -1
  189. package/clis/coingecko/global.js +1 -1
  190. package/clis/coingecko/trending.js +1 -1
  191. package/clis/confluence/search.js +1 -1
  192. package/clis/coupang/product.js +3 -3
  193. package/clis/coupang/utils.js +1 -1
  194. package/clis/crates/crate.js +1 -1
  195. package/clis/crates/search.js +1 -1
  196. package/clis/crates/utils.js +1 -1
  197. package/clis/csdn/article.js +13 -13
  198. package/clis/csdn/columns.js +1 -1
  199. package/clis/csdn/login.js +1 -1
  200. package/clis/csdn/stats.js +4 -4
  201. package/clis/csdn/whoami.js +1 -1
  202. package/clis/cto51/article.js +1 -1
  203. package/clis/cto51/whoami.js +1 -1
  204. package/clis/ctrip/flight.js +2 -2
  205. package/clis/ctrip/hotel-search.js +3 -3
  206. package/clis/ctrip/hotel-suggest.js +1 -1
  207. package/clis/ctrip/search.js +1 -1
  208. package/clis/ctrip/utils.js +6 -6
  209. package/clis/cursor/ask.js +5 -5
  210. package/clis/cursor/composer.js +2 -2
  211. package/clis/cursor/model.js +4 -4
  212. package/clis/cursor/send.js +2 -2
  213. package/clis/dblp/author.js +1 -1
  214. package/clis/dblp/paper.js +1 -1
  215. package/clis/dblp/search.js +1 -1
  216. package/clis/dblp/utils.js +1 -1
  217. package/clis/dblp/venue.js +1 -1
  218. package/clis/deepseek/ask.js +1 -1
  219. package/clis/deepseek/auth.js +2 -2
  220. package/clis/deepseek/detail.js +1 -1
  221. package/clis/deepseek/new.js +1 -1
  222. package/clis/deepseek/read.js +1 -1
  223. package/clis/deepseek/send.js +7 -7
  224. package/clis/deepseek/utils.js +25 -25
  225. package/clis/defillama/protocol.js +1 -1
  226. package/clis/defillama/protocols.js +1 -1
  227. package/clis/defillama/utils.js +1 -1
  228. package/clis/devto/auth.js +2 -2
  229. package/clis/devto/latest.js +1 -1
  230. package/clis/devto/publish.js +5 -5
  231. package/clis/devto/read.js +2 -2
  232. package/clis/devto/stats.js +3 -3
  233. package/clis/dianping/auth.js +2 -2
  234. package/clis/dianping/cityResolver.js +2 -2
  235. package/clis/dianping/search.js +1 -1
  236. package/clis/dianping/shop.js +1 -1
  237. package/clis/dianping/utils.js +1 -1
  238. package/clis/discord-app/delete.js +3 -3
  239. package/clis/discord-app/read.js +1 -1
  240. package/clis/discord-app/thread-read.js +1 -1
  241. package/clis/discord-web/auth.js +2 -2
  242. package/clis/discord-web/send.js +5 -5
  243. package/clis/dockerhub/image.js +1 -1
  244. package/clis/dockerhub/search.js +1 -1
  245. package/clis/dockerhub/utils.js +1 -1
  246. package/clis/dongchedi/koubei.js +1 -1
  247. package/clis/dongchedi/models.js +1 -1
  248. package/clis/dongchedi/score.js +1 -1
  249. package/clis/dongchedi/search.js +1 -1
  250. package/clis/dongchedi/series.js +1 -1
  251. package/clis/dongchedi/specs.js +1 -1
  252. package/clis/dongchedi/utils.js +1 -1
  253. package/clis/douban/article.js +3 -3
  254. package/clis/douban/auth.js +2 -2
  255. package/clis/douban/download.js +1 -1
  256. package/clis/douban/utils.js +23 -23
  257. package/clis/doubao/auth.js +3 -3
  258. package/clis/doubao/utils.js +39 -39
  259. package/clis/doubao-app/ask.js +1 -1
  260. package/clis/doubao-app/utils.js +4 -4
  261. package/clis/douyin/_shared/browser-fetch.js +7 -7
  262. package/clis/douyin/_shared/draft-cache.js +1 -1
  263. package/clis/douyin/_shared/imagex-upload.js +1 -1
  264. package/clis/douyin/_shared/sts2.js +1 -1
  265. package/clis/douyin/_shared/text-extra.js +1 -1
  266. package/clis/douyin/_shared/tos-upload.js +4 -4
  267. package/clis/douyin/_shared/transcode.js +1 -1
  268. package/clis/douyin/_shared/vod-upload.js +4 -4
  269. package/clis/douyin/draft.js +18 -18
  270. package/clis/douyin/drafts.js +1 -1
  271. package/clis/douyin/publish-image.js +12 -12
  272. package/clis/douyin/publish.js +9 -9
  273. package/clis/douyin/search.js +3 -3
  274. package/clis/douyin/videos.js +1 -1
  275. package/clis/eastmoney/_secid.js +1 -1
  276. package/clis/eastmoney/announcement.js +1 -1
  277. package/clis/eastmoney/article.js +1 -1
  278. package/clis/eastmoney/convertible.js +1 -1
  279. package/clis/eastmoney/etf.js +1 -1
  280. package/clis/eastmoney/holders.js +1 -1
  281. package/clis/eastmoney/index-board.js +1 -1
  282. package/clis/eastmoney/kline.js +1 -1
  283. package/clis/eastmoney/kuaixun.js +1 -1
  284. package/clis/eastmoney/longhu.js +1 -1
  285. package/clis/eastmoney/money-flow.js +1 -1
  286. package/clis/eastmoney/northbound.js +1 -1
  287. package/clis/eastmoney/quote.js +1 -1
  288. package/clis/eastmoney/rank.js +1 -1
  289. package/clis/eastmoney/sectors.js +1 -1
  290. package/clis/endoflife/product.js +1 -1
  291. package/clis/endoflife/utils.js +1 -1
  292. package/clis/facebook/comment.js +8 -8
  293. package/clis/facebook/feed.js +4 -4
  294. package/clis/facebook/like.js +5 -5
  295. package/clis/facebook/notifications.js +3 -3
  296. package/clis/facebook/post.js +11 -11
  297. package/clis/facebook/search.js +3 -3
  298. package/clis/flathub/app.js +1 -1
  299. package/clis/flathub/search.js +1 -1
  300. package/clis/flathub/utils.js +1 -1
  301. package/clis/flomo/memos.js +1 -1
  302. package/clis/gemini/deep-research-result.js +4 -4
  303. package/clis/gemini/deep-research.js +1 -1
  304. package/clis/gemini/detail.js +1 -1
  305. package/clis/gemini/history.js +1 -1
  306. package/clis/gemini/image.js +2 -2
  307. package/clis/gemini/status.js +1 -1
  308. package/clis/gemini/utils.js +43 -43
  309. package/clis/geogebra/hexagon.js +1 -1
  310. package/clis/geogebra/info.js +3 -3
  311. package/clis/geogebra/triangle.js +1 -1
  312. package/clis/geogebra/utils.js +11 -11
  313. package/clis/ghost/login.js +1 -1
  314. package/clis/ghost/shared.js +2 -2
  315. package/clis/gitee/auth.js +2 -2
  316. package/clis/github-trending/repos.js +1 -1
  317. package/clis/google/news.js +1 -1
  318. package/clis/google/search.js +2 -2
  319. package/clis/google/suggest.js +1 -1
  320. package/clis/google/trends.js +1 -1
  321. package/clis/google/utils.js +1 -1
  322. package/clis/goproxy/module.js +1 -1
  323. package/clis/goproxy/utils.js +1 -1
  324. package/clis/goproxy/versions.js +1 -1
  325. package/clis/gov-policy/recent.js +2 -2
  326. package/clis/gov-policy/search.js +2 -2
  327. package/clis/grok/ask.js +1 -1
  328. package/clis/grok/detail.js +1 -1
  329. package/clis/grok/image.js +8 -8
  330. package/clis/grok/pin.js +1 -1
  331. package/clis/grok/send.js +1 -1
  332. package/clis/grok/status.js +1 -1
  333. package/clis/grok/utils.js +21 -21
  334. package/clis/guazi/browse.js +1 -1
  335. package/clis/guazi/car.js +1 -1
  336. package/clis/guazi/utils.js +1 -1
  337. package/clis/hackernews/auth.js +2 -2
  338. package/clis/hackernews/comment.js +8 -8
  339. package/clis/hackernews/read.js +7 -7
  340. package/clis/hackernews/submit.js +7 -7
  341. package/clis/hashnode/auth.js +3 -3
  342. package/clis/hashnode/publish.js +14 -14
  343. package/clis/hf/auth.js +2 -2
  344. package/clis/hf/models.js +1 -1
  345. package/clis/hf/paper.js +1 -1
  346. package/clis/hf/spaces.js +1 -1
  347. package/clis/hf/top.js +1 -1
  348. package/clis/homebrew/cask.js +1 -1
  349. package/clis/homebrew/formula.js +1 -1
  350. package/clis/homebrew/popular.js +1 -1
  351. package/clis/homebrew/utils.js +1 -1
  352. package/clis/huodongxing/events.js +1 -1
  353. package/clis/hupu/detail.js +4 -4
  354. package/clis/hupu/hot.js +3 -3
  355. package/clis/hupu/reply.js +1 -1
  356. package/clis/hupu/search.js +1 -1
  357. package/clis/hupu/unlike.js +1 -1
  358. package/clis/hupu/utils.js +10 -10
  359. package/clis/imdb/person.js +2 -2
  360. package/clis/imdb/reviews.js +3 -3
  361. package/clis/imdb/search.js +2 -2
  362. package/clis/imdb/title.js +1 -1
  363. package/clis/imdb/top.js +1 -1
  364. package/clis/imdb/trending.js +1 -1
  365. package/clis/imdb/utils.js +13 -13
  366. package/clis/imooc/article.js +6 -6
  367. package/clis/imooc/login.js +1 -1
  368. package/clis/imooc/whoami.js +1 -1
  369. package/clis/indeed/job.js +2 -2
  370. package/clis/indeed/search.js +2 -2
  371. package/clis/indeed/utils.js +1 -1
  372. package/clis/infoq/article.js +2 -2
  373. package/clis/infoq/login.js +1 -1
  374. package/clis/infoq/whoami.js +1 -1
  375. package/clis/instagram/_shared/private-publish.js +4 -4
  376. package/clis/instagram/_shared/protocol-capture.js +9 -9
  377. package/clis/instagram/detail.js +3 -3
  378. package/clis/instagram/post.js +25 -25
  379. package/clis/instagram/reel.js +18 -18
  380. package/clis/instagram/story.js +4 -4
  381. package/clis/instagram/user.js +2 -2
  382. package/clis/jd/item.js +65 -65
  383. package/clis/jianshu/article.js +1 -1
  384. package/clis/jianshu/login.js +1 -1
  385. package/clis/jianshu/notebooks.js +1 -1
  386. package/clis/jianshu/whoami.js +1 -1
  387. package/clis/jianyu/search.js +6 -6
  388. package/clis/jianyu/shared/procurement-contract.js +1 -1
  389. package/clis/jike/api.js +6 -6
  390. package/clis/jike/auth.js +3 -3
  391. package/clis/jike/comment.js +1 -1
  392. package/clis/jike/create.js +6 -6
  393. package/clis/jike/feed.js +3 -3
  394. package/clis/jike/like.js +1 -1
  395. package/clis/jike/notifications.js +3 -3
  396. package/clis/jike/repost.js +13 -13
  397. package/clis/jike/search.js +3 -3
  398. package/clis/jimeng/auth.js +2 -2
  399. package/clis/jimeng/generate.js +10 -10
  400. package/clis/jira/shared.js +1 -1
  401. package/clis/juejin/article.js +4 -4
  402. package/clis/juejin/categories.js +1 -1
  403. package/clis/juejin/hot.js +1 -1
  404. package/clis/juejin/login.js +1 -1
  405. package/clis/juejin/recommend.js +1 -1
  406. package/clis/juejin/stats.js +3 -3
  407. package/clis/juejin/tags.js +1 -1
  408. package/clis/juejin/utils.js +1 -1
  409. package/clis/juejin/whoami.js +1 -1
  410. package/clis/ke/utils.js +4 -4
  411. package/clis/kimi/_utils.js +7 -7
  412. package/clis/kimi/audit-extras.js +14 -14
  413. package/clis/kimi/auth.js +3 -3
  414. package/clis/kimi/chat.js +15 -15
  415. package/clis/kimi/storage.js +5 -5
  416. package/clis/kimi/ui.js +13 -13
  417. package/clis/kimi/usage.js +3 -3
  418. package/clis/kuaishou/auth.js +1 -1
  419. package/clis/kuaishou/publish.js +6 -6
  420. package/clis/lesswrong/_helpers.js +5 -5
  421. package/clis/lesswrong/comments.js +5 -5
  422. package/clis/lichess/top.js +1 -1
  423. package/clis/lichess/user.js +1 -1
  424. package/clis/lichess/utils.js +1 -1
  425. package/clis/linkedin/comment.js +1 -1
  426. package/clis/linkedin/connect.js +11 -11
  427. package/clis/linkedin/create.js +5 -5
  428. package/clis/linkedin/follow.js +1 -1
  429. package/clis/linkedin/inbox.js +1 -1
  430. package/clis/linkedin/job-detail.js +3 -3
  431. package/clis/linkedin/like.js +1 -1
  432. package/clis/linkedin/notifications.js +1 -1
  433. package/clis/linkedin/people-search.js +1 -1
  434. package/clis/linkedin/post-comments.js +1 -1
  435. package/clis/linkedin/post-detail.js +1 -1
  436. package/clis/linkedin/profile-analytics.js +1 -1
  437. package/clis/linkedin/profile-api.js +13 -13
  438. package/clis/linkedin/profile-experience.js +1 -1
  439. package/clis/linkedin/profile-projects.js +1 -1
  440. package/clis/linkedin/profile-read.js +3 -3
  441. package/clis/linkedin/reply.js +1 -1
  442. package/clis/linkedin/repost.js +1 -1
  443. package/clis/linkedin/safe-send.js +8 -8
  444. package/clis/linkedin/salesnav-inbox.js +5 -5
  445. package/clis/linkedin/salesnav-message.js +3 -3
  446. package/clis/linkedin/salesnav-search.js +4 -4
  447. package/clis/linkedin/salesnav-thread.js +1 -1
  448. package/clis/linkedin/search-api.js +3 -3
  449. package/clis/linkedin/search.js +8 -8
  450. package/clis/linkedin/social-api.js +31 -31
  451. package/clis/linkedin/timeline.js +3 -3
  452. package/clis/linkedin-learning/search.js +2 -2
  453. package/clis/linkedin-learning/trending.js +2 -2
  454. package/clis/linux-do/feed.js +4 -4
  455. package/clis/linux-do/topic-content.js +8 -8
  456. package/clis/lobsters/domain.js +1 -1
  457. package/clis/lobsters/read.js +7 -7
  458. package/clis/maimai/auth.js +2 -2
  459. package/clis/maimai/search-talents.js +4 -4
  460. package/clis/manus/_utils.js +1 -1
  461. package/clis/mastodon/login.js +1 -1
  462. package/clis/mastodon/post.js +1 -1
  463. package/clis/mastodon/shared.js +12 -12
  464. package/clis/mastodon/whoami.js +1 -1
  465. package/clis/maven/artifact.js +1 -1
  466. package/clis/maven/search.js +1 -1
  467. package/clis/maven/utils.js +1 -1
  468. package/clis/mdn/search.js +1 -1
  469. package/clis/medium/article.js +5 -5
  470. package/clis/medium/login.js +1 -1
  471. package/clis/medium/stats.js +3 -3
  472. package/clis/medium/tag.js +1 -1
  473. package/clis/medium/whoami.js +1 -1
  474. package/clis/mubu/notes.js +1 -1
  475. package/clis/mubu/utils.js +15 -15
  476. package/clis/note/auth.js +2 -2
  477. package/clis/note/note-utils.js +2 -2
  478. package/clis/note/publish.js +8 -8
  479. package/clis/notebooklm/add-source.js +8 -8
  480. package/clis/notebooklm/create.js +1 -1
  481. package/clis/notebooklm/generate-slides.js +1 -1
  482. package/clis/notebooklm/notes-get.js +1 -1
  483. package/clis/notebooklm/rpc.js +8 -8
  484. package/clis/notebooklm/source-fulltext.js +1 -1
  485. package/clis/notebooklm/utils.js +10 -10
  486. package/clis/nowcoder/auth.js +2 -2
  487. package/clis/nowcoder/comment.js +1 -1
  488. package/clis/nowcoder/comments.js +1 -1
  489. package/clis/nowcoder/dm-list.js +1 -1
  490. package/clis/nowcoder/dm-read.js +1 -1
  491. package/clis/nowcoder/dm-send.js +1 -1
  492. package/clis/nowcoder/drafts.js +1 -1
  493. package/clis/nowcoder/inbox.js +1 -1
  494. package/clis/nowcoder/like.js +1 -1
  495. package/clis/nowcoder/my.js +1 -1
  496. package/clis/nowcoder/post.js +1 -1
  497. package/clis/nowcoder/utils.js +13 -13
  498. package/clis/npm/downloads.js +1 -1
  499. package/clis/npm/package.js +1 -1
  500. package/clis/npm/search.js +1 -1
  501. package/clis/npm/utils.js +1 -1
  502. package/clis/nuget/package.js +1 -1
  503. package/clis/nuget/search.js +1 -1
  504. package/clis/nuget/utils.js +1 -1
  505. package/clis/nvd/cve.js +1 -1
  506. package/clis/oeis/search.js +1 -1
  507. package/clis/oeis/sequence.js +1 -1
  508. package/clis/oeis/utils.js +1 -1
  509. package/clis/ones/common.js +6 -6
  510. package/clis/ones/enrich-tasks.js +1 -1
  511. package/clis/ones/my-tasks.js +1 -1
  512. package/clis/ones/resolve-labels.js +1 -1
  513. package/clis/ones/task-helpers.js +1 -1
  514. package/clis/ones/task.js +1 -1
  515. package/clis/ones/worklog.js +7 -7
  516. package/clis/openalex/search.js +1 -1
  517. package/clis/openalex/utils.js +1 -1
  518. package/clis/openalex/work.js +1 -1
  519. package/clis/openfda/drug-label.js +1 -1
  520. package/clis/openfda/food-recall.js +1 -1
  521. package/clis/openfda/utils.js +1 -1
  522. package/clis/openreview/author.js +1 -1
  523. package/clis/openreview/paper.js +1 -1
  524. package/clis/openreview/reviews.js +3 -3
  525. package/clis/openreview/search.js +1 -1
  526. package/clis/openreview/utils.js +1 -1
  527. package/clis/openreview/venue.js +1 -1
  528. package/clis/oschina/article.js +1 -1
  529. package/clis/oschina/catalogs.js +1 -1
  530. package/clis/oschina/login.js +1 -1
  531. package/clis/oschina/stats.js +6 -6
  532. package/clis/oschina/whoami.js +1 -1
  533. package/clis/osv/query.js +1 -1
  534. package/clis/osv/utils.js +1 -1
  535. package/clis/osv/vulnerability.js +1 -1
  536. package/clis/packagist/package.js +1 -1
  537. package/clis/packagist/search.js +1 -1
  538. package/clis/packagist/utils.js +1 -1
  539. package/clis/pinterest/api.js +1 -1
  540. package/clis/pinterest/auth.js +1 -1
  541. package/clis/pinterest/boards.js +1 -1
  542. package/clis/pinterest/client.js +6 -6
  543. package/clis/pinterest/publish.js +5 -5
  544. package/clis/pixiv/auth.js +2 -2
  545. package/clis/pixiv/download.js +1 -1
  546. package/clis/pixiv/illusts.js +1 -1
  547. package/clis/pixiv/search.js +1 -1
  548. package/clis/pixiv/utils.js +3 -3
  549. package/clis/powerchina/auth.js +2 -2
  550. package/clis/powerchina/search.js +1 -1
  551. package/clis/producthunt/browse.js +2 -2
  552. package/clis/producthunt/hot.js +2 -2
  553. package/clis/producthunt/posts.js +1 -1
  554. package/clis/producthunt/today.js +1 -1
  555. package/clis/producthunt/utils.js +1 -1
  556. package/clis/pypi/downloads.js +1 -1
  557. package/clis/pypi/package.js +1 -1
  558. package/clis/pypi/utils.js +1 -1
  559. package/clis/qiita/auth.js +1 -1
  560. package/clis/qiita/gql.js +6 -6
  561. package/clis/qiita/publish.js +4 -4
  562. package/clis/qiita/stats.js +4 -4
  563. package/clis/qoder/_utils.js +16 -16
  564. package/clis/qoder/composer.js +1 -1
  565. package/clis/qoder/quest.js +1 -1
  566. package/clis/qoder/ui.js +14 -14
  567. package/clis/quark/auth.js +2 -2
  568. package/clis/quark/utils.js +2 -2
  569. package/clis/quora/answer-comments.js +3 -3
  570. package/clis/quora/create-answer.js +4 -4
  571. package/clis/quora/create-question.js +3 -3
  572. package/clis/quora/shared.js +17 -17
  573. package/clis/quora/whoami.js +1 -1
  574. package/clis/qwen/ask.js +1 -1
  575. package/clis/qwen/auth.js +3 -3
  576. package/clis/qwen/detail.js +1 -1
  577. package/clis/qwen/image.js +5 -5
  578. package/clis/qwen/status.js +1 -1
  579. package/clis/qwen/utils.js +16 -16
  580. package/clis/reddit/home.js +3 -3
  581. package/clis/reddit/read.js +10 -10
  582. package/clis/reddit/reply.js +4 -4
  583. package/clis/reddit/submit.js +11 -11
  584. package/clis/reddit/subreddit-info.js +3 -3
  585. package/clis/reddit/subscribed.js +4 -4
  586. package/clis/reddit/whoami.js +2 -2
  587. package/clis/rednote/comments.js +1 -1
  588. package/clis/rednote/download.js +1 -1
  589. package/clis/rednote/feed.js +1 -1
  590. package/clis/rednote/note.js +1 -1
  591. package/clis/rednote/notifications.js +2 -2
  592. package/clis/rednote/search.js +2 -2
  593. package/clis/rest-countries/country.js +1 -1
  594. package/clis/rest-countries/region.js +1 -1
  595. package/clis/rest-countries/utils.js +1 -1
  596. package/clis/reuters/article-detail.js +1 -1
  597. package/clis/reuters/auth.js +3 -3
  598. package/clis/reuters/search.js +1 -1
  599. package/clis/reuters/utils.js +4 -4
  600. package/clis/rfc/rfc.js +1 -1
  601. package/clis/rfc/utils.js +1 -1
  602. package/clis/rubygems/gem.js +1 -1
  603. package/clis/rubygems/search.js +1 -1
  604. package/clis/rubygems/utils.js +1 -1
  605. package/clis/segmentfault/article.js +3 -3
  606. package/clis/segmentfault/channels.js +1 -1
  607. package/clis/segmentfault/login.js +1 -1
  608. package/clis/segmentfault/stats.js +4 -4
  609. package/clis/segmentfault/tags.js +1 -1
  610. package/clis/segmentfault/whoami.js +1 -1
  611. package/clis/semanticscholar/citations.js +1 -1
  612. package/clis/semanticscholar/paper.js +1 -1
  613. package/clis/semanticscholar/recommendations.js +1 -1
  614. package/clis/semanticscholar/search.js +1 -1
  615. package/clis/semanticscholar/utils.js +1 -1
  616. package/clis/sinafinance/news.js +1 -1
  617. package/clis/sinafinance/stock-rank.js +1 -1
  618. package/clis/sinafinance/stock.js +1 -1
  619. package/clis/slock/attachment-download.js +1 -1
  620. package/clis/slock/attachment-upload.js +7 -7
  621. package/clis/slock/attachment-url.js +1 -1
  622. package/clis/slock/auth-verify.js +1 -1
  623. package/clis/slock/bookmark-add.js +1 -1
  624. package/clis/slock/bookmark-remove.js +1 -1
  625. package/clis/slock/channel-action.js +1 -1
  626. package/clis/slock/channel-create.js +1 -1
  627. package/clis/slock/channel-files.js +1 -1
  628. package/clis/slock/channel-list.js +1 -1
  629. package/clis/slock/channel-mark.js +1 -1
  630. package/clis/slock/channel-members.js +1 -1
  631. package/clis/slock/channel-unarchive.js +1 -1
  632. package/clis/slock/dm-list.js +1 -1
  633. package/clis/slock/errors.js +1 -1
  634. package/clis/slock/in-page.js +28 -28
  635. package/clis/slock/inbox-done.js +5 -5
  636. package/clis/slock/inbox.js +1 -1
  637. package/clis/slock/message-read.js +22 -22
  638. package/clis/slock/message-search.js +10 -10
  639. package/clis/slock/message-send.js +25 -25
  640. package/clis/slock/reaction-add.js +1 -1
  641. package/clis/slock/reaction-remove.js +1 -1
  642. package/clis/slock/resolve.js +1 -1
  643. package/clis/slock/server-list.js +2 -2
  644. package/clis/slock/task-claim.js +4 -4
  645. package/clis/slock/task-convert.js +13 -13
  646. package/clis/slock/task-create.js +1 -1
  647. package/clis/slock/task-delete.js +5 -5
  648. package/clis/slock/task-get.js +5 -5
  649. package/clis/slock/task-list-server.js +4 -4
  650. package/clis/slock/task-list.js +5 -5
  651. package/clis/slock/task-status.js +3 -3
  652. package/clis/slock/task-unclaim.js +3 -3
  653. package/clis/slock/thread-follow.js +1 -1
  654. package/clis/slock/thread-state.js +1 -1
  655. package/clis/slock/unread-summary.js +5 -5
  656. package/clis/slock/whoami.js +1 -1
  657. package/clis/smzdm/search.js +3 -3
  658. package/clis/sohu/article.js +1 -1
  659. package/clis/sohu/attributes.js +1 -1
  660. package/clis/sohu/categories.js +1 -1
  661. package/clis/sohu/channels.js +1 -1
  662. package/clis/sohu/columns.js +1 -1
  663. package/clis/sohu/login.js +1 -1
  664. package/clis/sohu/stats.js +3 -3
  665. package/clis/sohu/topics.js +1 -1
  666. package/clis/sohu/whoami.js +1 -1
  667. package/clis/spotify/spotify.js +1 -1
  668. package/clis/stackoverflow/read.js +6 -6
  669. package/clis/stackoverflow/related.js +1 -1
  670. package/clis/stackoverflow/tag.js +1 -1
  671. package/clis/stackoverflow/user.js +1 -1
  672. package/clis/stackoverflow/utils.js +1 -1
  673. package/clis/steam/app.js +1 -1
  674. package/clis/steam/search.js +1 -1
  675. package/clis/steam/utils.js +1 -1
  676. package/clis/substack/auth.js +2 -2
  677. package/clis/substack/post-utils.js +2 -2
  678. package/clis/substack/publish.js +5 -5
  679. package/clis/suno/auth.js +2 -2
  680. package/clis/suno/download.js +5 -5
  681. package/clis/suno/generate.js +3 -3
  682. package/clis/suno/list.js +1 -1
  683. package/clis/suno/status.js +1 -1
  684. package/clis/suno/utils.js +29 -29
  685. package/clis/telegram/send.js +7 -7
  686. package/clis/telegram/shared.js +2 -2
  687. package/clis/telegram/whoami.js +1 -1
  688. package/clis/test-utils.js +1 -1
  689. package/clis/threads/post.js +23 -23
  690. package/clis/threads/shared.js +3 -3
  691. package/clis/threads/whoami.js +1 -1
  692. package/clis/tieba/hot.js +3 -3
  693. package/clis/tieba/posts.js +1 -1
  694. package/clis/tieba/read.js +2 -2
  695. package/clis/tieba/search.js +3 -3
  696. package/clis/tieba/utils.js +1 -1
  697. package/clis/tiktok/comment.js +2 -2
  698. package/clis/tiktok/creator-videos.js +3 -3
  699. package/clis/tiktok/explore.js +3 -3
  700. package/clis/tiktok/follow.js +8 -8
  701. package/clis/tiktok/following.js +4 -4
  702. package/clis/tiktok/friends.js +7 -7
  703. package/clis/tiktok/live.js +3 -3
  704. package/clis/tiktok/notifications.js +6 -6
  705. package/clis/tiktok/publish.js +16 -16
  706. package/clis/tiktok/unfollow.js +4 -4
  707. package/clis/tiktok/user.js +2 -2
  708. package/clis/tiktok/utils.js +1 -1
  709. package/clis/toutiao/article.js +1 -1
  710. package/clis/toutiao/articles.js +2 -2
  711. package/clis/toutiao/auth.js +2 -2
  712. package/clis/toutiao/hot.js +1 -1
  713. package/clis/toutiao/recommend.js +1 -1
  714. package/clis/toutiao/utils.js +2 -2
  715. package/clis/trae-solo/_actions.js +4 -4
  716. package/clis/trae-solo/_fs.js +5 -5
  717. package/clis/trae-solo/_state.js +2 -2
  718. package/clis/trae-solo/automation.js +4 -4
  719. package/clis/trae-solo/mode.js +4 -4
  720. package/clis/trae-solo/model.js +4 -4
  721. package/clis/trae-solo/renderer-storage.js +4 -4
  722. package/clis/trae-solo/settings.js +1 -1
  723. package/clis/trae-solo/skill-fs.js +1 -1
  724. package/clis/trae-solo/skill.js +12 -12
  725. package/clis/trae-solo/state-fs.js +2 -2
  726. package/clis/trae-solo/task-fs.js +5 -5
  727. package/clis/trae-solo/workspaces-fs.js +1 -1
  728. package/clis/tumblr/auth.js +2 -2
  729. package/clis/tumblr/publish.js +3 -3
  730. package/clis/tvmaze/search.js +1 -1
  731. package/clis/tvmaze/show.js +1 -1
  732. package/clis/tvmaze/utils.js +1 -1
  733. package/clis/twitter/accept.js +7 -7
  734. package/clis/twitter/article.js +7 -7
  735. package/clis/twitter/bookmark-folder.js +3 -3
  736. package/clis/twitter/bookmark-folders.js +3 -3
  737. package/clis/twitter/bookmarks.js +4 -4
  738. package/clis/twitter/delete.js +5 -5
  739. package/clis/twitter/device-follow.js +3 -3
  740. package/clis/twitter/dm-list.js +1 -1
  741. package/clis/twitter/dm-read.js +1 -1
  742. package/clis/twitter/dm-send.js +5 -5
  743. package/clis/twitter/dm-shared.js +3 -3
  744. package/clis/twitter/download.js +6 -6
  745. package/clis/twitter/followers.js +5 -5
  746. package/clis/twitter/following.js +2 -2
  747. package/clis/twitter/like.js +3 -3
  748. package/clis/twitter/likes.js +8 -8
  749. package/clis/twitter/list-add-core.js +9 -9
  750. package/clis/twitter/list-create.js +5 -5
  751. package/clis/twitter/list-remove-core.js +9 -9
  752. package/clis/twitter/list-tweets.js +7 -7
  753. package/clis/twitter/lists.js +6 -6
  754. package/clis/twitter/notifications.js +2 -2
  755. package/clis/twitter/post.js +24 -24
  756. package/clis/twitter/profile.js +7 -7
  757. package/clis/twitter/quote.js +7 -7
  758. package/clis/twitter/reply-dm.js +7 -7
  759. package/clis/twitter/reply.js +12 -12
  760. package/clis/twitter/retweet.js +3 -3
  761. package/clis/twitter/scheduled-delete.js +3 -3
  762. package/clis/twitter/scheduled-list.js +2 -2
  763. package/clis/twitter/scheduled-utils.js +3 -3
  764. package/clis/twitter/search.js +5 -5
  765. package/clis/twitter/shared.js +6 -6
  766. package/clis/twitter/thread.js +4 -4
  767. package/clis/twitter/timeline.js +3 -3
  768. package/clis/twitter/trending.js +2 -2
  769. package/clis/twitter/tweets.js +11 -11
  770. package/clis/twitter/unlike.js +3 -3
  771. package/clis/twitter/unretweet.js +3 -3
  772. package/clis/twitter/utils.js +6 -6
  773. package/clis/upwork/detail.js +2 -2
  774. package/clis/upwork/feed.js +2 -2
  775. package/clis/upwork/search.js +2 -2
  776. package/clis/upwork/utils.js +1 -1
  777. package/clis/v2ex/auth.js +2 -2
  778. package/clis/v2ex/daily.js +3 -3
  779. package/clis/v2ex/me.js +2 -2
  780. package/clis/v2ex/notifications.js +2 -2
  781. package/clis/vk/post.js +1 -1
  782. package/clis/vk/shared.js +2 -2
  783. package/clis/vk/whoami.js +1 -1
  784. package/clis/web/read.js +8 -8
  785. package/clis/wechat-channels/auth.js +2 -2
  786. package/clis/wechat-channels/publish.js +30 -30
  787. package/clis/weibo/article.js +1 -1
  788. package/clis/weibo/auth.js +3 -3
  789. package/clis/weibo/comments.js +1 -1
  790. package/clis/weibo/delete.js +2 -2
  791. package/clis/weibo/feed.js +3 -3
  792. package/clis/weibo/hot.js +1 -1
  793. package/clis/weibo/publish.js +10 -10
  794. package/clis/weibo/search.js +2 -2
  795. package/clis/weibo/user-posts.js +3 -3
  796. package/clis/weibo/user.js +2 -2
  797. package/clis/weibo/utils.js +3 -3
  798. package/clis/weixin/article.js +1 -1
  799. package/clis/weixin/create-draft.js +26 -26
  800. package/clis/weixin/download.js +2 -2
  801. package/clis/weixin/login.js +1 -1
  802. package/clis/weixin/search.js +2 -2
  803. package/clis/weixin/stats.js +3 -3
  804. package/clis/weixin/whoami.js +1 -1
  805. package/clis/weread/ai-outline.js +2 -2
  806. package/clis/weread/book-search.js +2 -2
  807. package/clis/weread/book.js +2 -2
  808. package/clis/weread/notebooks.js +1 -1
  809. package/clis/weread/search.js +1 -1
  810. package/clis/weread/shelf.js +1 -1
  811. package/clis/weread/utils.js +6 -6
  812. package/clis/weread-official/book.js +1 -1
  813. package/clis/weread-official/discover.js +1 -1
  814. package/clis/weread-official/list-apis.js +1 -1
  815. package/clis/weread-official/notes.js +1 -1
  816. package/clis/weread-official/readdata.js +1 -1
  817. package/clis/weread-official/review.js +1 -1
  818. package/clis/weread-official/search.js +1 -1
  819. package/clis/weread-official/shelf.js +1 -1
  820. package/clis/weread-official/utils.js +1 -1
  821. package/clis/wikidata/entity.js +1 -1
  822. package/clis/wikidata/search.js +1 -1
  823. package/clis/wikidata/utils.js +1 -1
  824. package/clis/wikipedia/page.js +1 -1
  825. package/clis/wikipedia/trending.js +1 -1
  826. package/clis/wikipedia/utils.js +1 -1
  827. package/clis/wordpress/login.js +1 -1
  828. package/clis/wordpress/publish.js +1 -1
  829. package/clis/wordpress/shared.js +3 -3
  830. package/clis/wordpress/whoami.js +1 -1
  831. package/clis/woshipm/article.js +1 -1
  832. package/clis/woshipm/login.js +1 -1
  833. package/clis/woshipm/stats.js +4 -4
  834. package/clis/woshipm/whoami.js +1 -1
  835. package/clis/wttr/current.js +1 -1
  836. package/clis/wttr/forecast.js +1 -1
  837. package/clis/wttr/utils.js +1 -1
  838. package/clis/xianyu/collect.js +1 -1
  839. package/clis/xianyu/inbox.js +1 -1
  840. package/clis/xianyu/item-stats.js +2 -2
  841. package/clis/xianyu/location.js +1 -1
  842. package/clis/xianyu/manage.js +1 -1
  843. package/clis/xianyu/messages.js +1 -1
  844. package/clis/xianyu/mtop.js +5 -5
  845. package/clis/xianyu/order.js +1 -1
  846. package/clis/xianyu/promote-stats.js +2 -2
  847. package/clis/xianyu/publish.js +17 -17
  848. package/clis/xianyu/rate.js +1 -1
  849. package/clis/xianyu/reply.js +1 -1
  850. package/clis/xianyu/search.js +8 -8
  851. package/clis/xianyu/seller-data.js +1 -1
  852. package/clis/xianyu/seller-list.js +1 -1
  853. package/clis/xianyu/user.js +1 -1
  854. package/clis/xiaoe/catalog.js +2 -2
  855. package/clis/xiaoe/content.js +2 -2
  856. package/clis/xiaoe/courses.js +2 -2
  857. package/clis/xiaohongshu/ask.js +6 -6
  858. package/clis/xiaohongshu/comments.js +6 -6
  859. package/clis/xiaohongshu/creator-note-detail.js +7 -7
  860. package/clis/xiaohongshu/creator-notes-summary.js +1 -1
  861. package/clis/xiaohongshu/creator-notes.js +13 -13
  862. package/clis/xiaohongshu/creator-profile.js +2 -2
  863. package/clis/xiaohongshu/creator-stats.js +2 -2
  864. package/clis/xiaohongshu/delete-note.js +7 -7
  865. package/clis/xiaohongshu/download.js +4 -4
  866. package/clis/xiaohongshu/feed.js +2 -2
  867. package/clis/xiaohongshu/follow.js +3 -3
  868. package/clis/xiaohongshu/human.js +3 -3
  869. package/clis/xiaohongshu/note-helpers.js +1 -1
  870. package/clis/xiaohongshu/note.js +2 -2
  871. package/clis/xiaohongshu/notifications.js +1 -1
  872. package/clis/xiaohongshu/publish-video.js +8 -8
  873. package/clis/xiaohongshu/publish.js +59 -59
  874. package/clis/xiaohongshu/search.js +8 -8
  875. package/clis/xiaohongshu/unfollow.js +4 -4
  876. package/clis/xiaohongshu/user-helpers.js +1 -1
  877. package/clis/xiaohongshu/user.js +2 -2
  878. package/clis/xiaoyuzhou/auth.js +3 -3
  879. package/clis/xiaoyuzhou/download.js +1 -1
  880. package/clis/xiaoyuzhou/utils.js +1 -1
  881. package/clis/xueqiu/article.js +4 -4
  882. package/clis/xueqiu/comments.js +4 -4
  883. package/clis/xueqiu/danjuan-utils.js +4 -4
  884. package/clis/xueqiu/earnings-date.js +1 -1
  885. package/clis/xueqiu/events.js +3 -3
  886. package/clis/xueqiu/hashtags.js +3 -3
  887. package/clis/xueqiu/stocks.js +3 -3
  888. package/clis/xueqiu/users.js +3 -3
  889. package/clis/xueqiu/utils.js +3 -3
  890. package/clis/yahoo-finance/quote.js +1 -1
  891. package/clis/yollomi/background.js +1 -1
  892. package/clis/yollomi/edit.js +1 -1
  893. package/clis/yollomi/face-swap.js +1 -1
  894. package/clis/yollomi/generate.js +1 -1
  895. package/clis/yollomi/object-remover.js +1 -1
  896. package/clis/yollomi/remove-bg.js +1 -1
  897. package/clis/yollomi/restore.js +1 -1
  898. package/clis/yollomi/try-on.js +1 -1
  899. package/clis/yollomi/upload.js +4 -4
  900. package/clis/yollomi/upscale.js +1 -1
  901. package/clis/yollomi/utils.js +4 -4
  902. package/clis/yollomi/video.js +1 -1
  903. package/clis/youtube/channel.js +4 -4
  904. package/clis/youtube/feed.js +2 -2
  905. package/clis/youtube/like.js +5 -5
  906. package/clis/youtube/playlist.js +7 -7
  907. package/clis/youtube/publish.js +11 -11
  908. package/clis/youtube/search.js +3 -3
  909. package/clis/youtube/subscribe.js +7 -7
  910. package/clis/youtube/subscriptions.js +1 -1
  911. package/clis/youtube/transcript-group.js +2 -2
  912. package/clis/youtube/transcript.js +13 -13
  913. package/clis/youtube/unlike.js +5 -5
  914. package/clis/youtube/unsubscribe.js +7 -7
  915. package/clis/youtube/utils.js +3 -3
  916. package/clis/youtube/video.js +4 -4
  917. package/clis/youtube/watch-later.js +2 -2
  918. package/clis/yuanbao/ask.js +18 -18
  919. package/clis/yuanbao/detail.js +1 -1
  920. package/clis/yuanbao/read.js +1 -1
  921. package/clis/yuanbao/shared.js +9 -9
  922. package/clis/yuanbao/status.js +1 -1
  923. package/clis/yuque/article.js +1 -1
  924. package/clis/yuque/whoami.js +1 -1
  925. package/clis/zhihu/answer-comments.js +2 -2
  926. package/clis/zhihu/answer-detail.js +3 -3
  927. package/clis/zhihu/answer.js +1 -1
  928. package/clis/zhihu/article-transform.js +1 -1
  929. package/clis/zhihu/article.js +1 -1
  930. package/clis/zhihu/auth.js +2 -2
  931. package/clis/zhihu/collection.js +3 -3
  932. package/clis/zhihu/collections.js +3 -3
  933. package/clis/zhihu/download.js +2 -2
  934. package/clis/zhihu/image-profile.js +6 -6
  935. package/clis/zhihu/paginate.js +3 -3
  936. package/clis/zhihu/pin.js +4 -4
  937. package/clis/zhihu/question.js +3 -3
  938. package/clis/zhihu/recommend.js +3 -3
  939. package/clis/zhihu/search.js +3 -3
  940. package/clis/zhihu/stats.js +3 -3
  941. package/clis/zhihu/user-arg.js +1 -1
  942. package/clis/zhihu/write-shared.js +7 -7
  943. package/clis/zlibrary/utils.js +6 -6
  944. package/clis/zsxq/auth.js +3 -3
  945. package/clis/zsxq/search.js +1 -1
  946. package/clis/zsxq/topic.js +1 -1
  947. package/clis/zsxq/utils.js +5 -5
  948. package/dist/src/adapter-source.js +1 -1
  949. package/dist/src/browser/analyze.js +1 -1
  950. package/dist/src/browser/article-extract.js +2 -2
  951. package/dist/src/browser/ax-snapshot.js +2 -2
  952. package/dist/src/browser/base-page.js +25 -25
  953. package/dist/src/browser/bridge.js +1 -1
  954. package/dist/src/browser/cdp.js +1 -1
  955. package/dist/src/browser/daemon-client.js +1 -1
  956. package/dist/src/browser/daemon-lifecycle.js +7 -7
  957. package/dist/src/browser/dom-helpers.js +35 -35
  958. package/dist/src/browser/dom-snapshot.js +19 -19
  959. package/dist/src/browser/errors.js +3 -3
  960. package/dist/src/browser/extract.js +5 -5
  961. package/dist/src/browser/find.js +13 -13
  962. package/dist/src/browser/fingerprint.js +2 -2
  963. package/dist/src/browser/html-tree.js +6 -6
  964. package/dist/src/browser/managed-chrome.js +1 -1
  965. package/dist/src/browser/network-cache.js +1 -1
  966. package/dist/src/browser/network-key.js +1 -1
  967. package/dist/src/browser/page.js +7 -7
  968. package/dist/src/browser/profile.js +2 -2
  969. package/dist/src/browser/proxy-test.js +8 -8
  970. package/dist/src/browser/shape-filter.js +1 -1
  971. package/dist/src/browser/shape.js +1 -1
  972. package/dist/src/browser/stealth.js +3 -3
  973. package/dist/src/browser/tabs.js +2 -2
  974. package/dist/src/browser/target-errors.js +1 -1
  975. package/dist/src/browser/target-resolver.js +23 -23
  976. package/dist/src/browser/trace.js +2 -2
  977. package/dist/src/browser/utils.js +1 -1
  978. package/dist/src/browser/verify-fixture.js +2 -2
  979. package/dist/src/browser-session-lock.js +1 -1
  980. package/dist/src/build-manifest.js +11 -11
  981. package/dist/src/capabilityRouting.js +1 -1
  982. package/dist/src/cli-argv-preprocess.js +1 -1
  983. package/dist/src/cli.js +32 -32
  984. package/dist/src/commanderAdapter.js +3 -3
  985. package/dist/src/commands/auth.js +3 -3
  986. package/dist/src/commands/daemon.js +1 -1
  987. package/dist/src/completion-fast.js +1 -1
  988. package/dist/src/completion.js +1 -1
  989. package/dist/src/constants.js +1 -1
  990. package/dist/src/convention-audit.js +2 -2
  991. package/dist/src/daemon-utils.js +1 -1
  992. package/dist/src/daemon.js +1 -1
  993. package/dist/src/discovery.js +2 -2
  994. package/dist/src/doctor.js +9 -9
  995. package/dist/src/download/article-download.js +15 -15
  996. package/dist/src/download/index.js +4 -4
  997. package/dist/src/download/media-download.js +1 -1
  998. package/dist/src/download/progress.js +3 -3
  999. package/dist/src/electron-apps.js +1 -1
  1000. package/dist/src/errors.js +2 -2
  1001. package/dist/src/execution.js +2 -2
  1002. package/dist/src/external.js +1 -1
  1003. package/dist/src/help.js +8 -8
  1004. package/dist/src/hooks.js +1 -1
  1005. package/dist/src/interceptor.js +21 -21
  1006. package/dist/src/launcher.js +7 -7
  1007. package/dist/src/logger.js +8 -8
  1008. package/dist/src/main.js +7 -7
  1009. package/dist/src/observation/artifact.js +5 -5
  1010. package/dist/src/observation/retention.js +1 -1
  1011. package/dist/src/output.js +2 -2
  1012. package/dist/src/package-paths.js +1 -1
  1013. package/dist/src/pipeline/executor.js +1 -1
  1014. package/dist/src/pipeline/registry.js +1 -1
  1015. package/dist/src/pipeline/steps/browser.js +1 -1
  1016. package/dist/src/pipeline/steps/download.js +1 -1
  1017. package/dist/src/pipeline/steps/fetch.js +6 -6
  1018. package/dist/src/pipeline/steps/intercept.js +1 -1
  1019. package/dist/src/pipeline/steps/tap.js +17 -17
  1020. package/dist/src/pipeline/steps/transform.js +1 -1
  1021. package/dist/src/pipeline/template.js +1 -1
  1022. package/dist/src/plugin-manifest.js +1 -1
  1023. package/dist/src/plugin-scaffold.js +19 -19
  1024. package/dist/src/plugin.js +12 -12
  1025. package/dist/src/rate-limit.js +1 -1
  1026. package/dist/src/registry.js +1 -1
  1027. package/dist/src/runtime-detect.js +1 -1
  1028. package/dist/src/runtime.js +1 -1
  1029. package/dist/src/scripts/framework.js +1 -1
  1030. package/dist/src/scripts/interact.js +1 -1
  1031. package/dist/src/scripts/store.js +1 -1
  1032. package/dist/src/serialization.js +2 -2
  1033. package/dist/src/session-lease.js +1 -1
  1034. package/dist/src/snapshotFormatter.js +2 -2
  1035. package/dist/src/tui.js +12 -12
  1036. package/dist/src/user-runtime.js +1 -1
  1037. package/dist/src/utils.d.ts +12 -0
  1038. package/dist/src/utils.js +4 -4
  1039. package/dist/src/validate.js +2 -2
  1040. package/dist/src/verify.js +2 -2
  1041. package/dist/src/version.js +1 -1
  1042. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
- import{cli as O,Strategy as B}from"@jackwener/opencli/registry";import{ArgumentError as m,CommandExecutionError as u,EmptyResultError as y}from"@jackwener/opencli/errors";import{WEREAD_UA as x,WEREAD_WEB_ORIGIN as w}from"./utils.js";const C=100,j=500,$=50;function S(e){return String(e||"").replace(/<[^>]+>/g,"").replace(/&#x([0-9a-fA-F]+);/gi,(r,t)=>String.fromCharCode(parseInt(t,16))).replace(/&#(\d+);/g,(r,t)=>String.fromCharCode(Number(t))).replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&quot;/g,'"').trim()}function c(e){return String(e||"").replace(/\s+/g," ").trim()}function k(e,r,t,n){const o=Number(e??r);if(!Number.isInteger(o)||o<=0)throw new m(`${t} must be a positive integer`);if(n!=null&&o>n)throw new m(`${t} must be <= ${n}`);return o}function f(e){if(e==null||e==="")return null;const r=Number(e);return Number.isFinite(r)?r:null}function z(e){if(e===!0||e===1||e==="1")return!0;if(e===!1||e===0||e==="0")return!1;return null}function R(e,r){const t=c(e);if(!t)throw new m(`${r} is required`);return t}function U(e){let r;try{r=new URL(String(e||""),w)}catch{return""}const t=r.pathname.split("/").filter(Boolean);if(r.protocol!=="https:"||r.hostname!=="weread.qq.com"||t[0]!=="web"||t[1]!=="reader"||!t[2])return"";if(t.length!==3)return"";return r.toString()}async function A(e,r){let t;try{t=await fetch(e.toString(),{headers:{"User-Agent":x}})}catch(n){throw new u(`${r} request failed: ${n instanceof Error?n.message:String(n)}`)}if(!t.ok)throw new u(`${r} request failed: HTTP ${t.status}`);try{return await t.json()}catch{throw new u(`${r} returned invalid JSON`)}}async function E(e,r){let t;try{t=await fetch(e.toString(),{headers:{"User-Agent":x}})}catch(n){throw new u(`${r} request failed: ${n instanceof Error?n.message:String(n)}`)}if(!t.ok)throw new u(`${r} request failed: HTTP ${t.status}`);return t.text()}function F(e){const r=c(e);return r?`${w}/web/reader/${r}`:""}function W(e){const r="window.__INITIAL_STATE__=",t=e.indexOf(r);if(t<0)return null;const n=t+r.length,a=e.indexOf(";(function(){var s;",n),o=e.indexOf("</script>",n),s=a>=0?a:o;if(s<0)return null;try{return JSON.parse(e.slice(n,s))}catch{return null}}function H(e){const r=e.match(/<script[^>]*type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/i);if(!r)return{};try{const t=JSON.parse(r[1]),n={};n.bookId=c(t?.["@Id"]);n.title=c(t?.name);n.author=c(t?.author?.name);n.readerUrl=c(t?.url);return n}catch{return{}}}function q(e,r){const n=W(e)?.reader??{},a=n.bookInfo??{},o=H(e),s=Array.isArray(n.chapterInfos)?n.chapterInfos:[],h=c(n.infoId)||c(a.encodeId),i={};i.bookId=c(a.bookId)||c(n.bookId)||o.bookId;i.title=c(a.title)||o.title;i.author=c(a.author)||o.author;i.readerUrl=c(r)||F(h)||o.readerUrl;i.chapters=s;return i}async function L(e){if(!e)return null;const r=await E(e,"WeRead reader page"),t=q(r,e);return t.bookId?t:null}function M(e){return Array.from(e.matchAll(/<li[^>]*class="wr_bookList_item"[^>]*>([\s\S]*?)<\/li>/g)).map((t)=>{const n=t[1],a=n.match(/<a[^>]*href="([^"]+)"[^>]*class="wr_bookList_item_link"[^>]*>|<a[^>]*class="wr_bookList_item_link"[^>]*href="([^"]+)"[^>]*>/),o=n.match(/<p[^>]*class="wr_bookList_item_title"[^>]*>([\s\S]*?)<\/p>/),s=n.match(/<p[^>]*class="wr_bookList_item_author"[^>]*>([\s\S]*?)<\/p>/),h=a?.[1]||a?.[2]||"",i={};i.title=S(o?.[1]||"");i.author=S(s?.[1]||"");i.readerUrl=h?U(h):"";return i}).filter((t)=>t.title&&t.readerUrl)}async function J(e){const r=new URL("/web/search/books",w);r.searchParams.set("keyword",e);return M(await E(r,"WeRead search page"))}function T(e,r){const t=c(e.title),n=c(e.author);if(!t)return"";if(n){const o=r.filter((s)=>c(s.title)===t&&c(s.author)===n);if(o.length===1)return o[0].readerUrl}const a=r.filter((o)=>c(o.title)===t);return a.length===1?a[0].readerUrl:""}async function G(e,r){const t=new URL("/web/search/global",`${w}/web`);t.searchParams.set("keyword",e);const n=await A(t,"WeRead book search");if(!Array.isArray(n?.books))throw new u("WeRead book search returned malformed books");const a=n.books;if(a.length===0)throw new y("weread book-search",`No WeRead books found for "${e}"`);if(r>a.length)throw new m(`book-rank must be <= ${a.length}`,`Only ${a.length} book search result(s) were returned for "${e}"`);const o=a[r-1]?.bookInfo??{},s={bookId:c(o.bookId),title:c(o.title),author:c(o.author),readerUrl:"",chapters:[]};if(!s.bookId)throw new u(`WeRead book search result ${r} is missing bookId`);const h=await J(e);s.readerUrl=T(s,h);const i=await L(s.readerUrl);return{...s,...Object.fromEntries(Object.entries(i??{}).filter(([,d])=>d!=null&&d!==""&&!(Array.isArray(d)&&d.length===0)))}}async function D(e,r){if(/^https?:\/\//i.test(e)){const t=U(e);if(!t)throw new m("book URL must be a https://weread.qq.com/web/reader/<id> URL");const n=await L(t);if(!n?.bookId)throw new u("Could not parse a bookId from the reader URL");return n}if(/^\d+$/.test(e)){const t={};t.bookId=e;t.title="";t.author="";t.readerUrl="";t.chapters=[];return t}return G(e,r)}async function X(e,r,t,n){const a=[];let o=0;while(a.length<t){const s=t-a.length,h=s<$?s:$,i=new URL("/web/book/search",w);i.searchParams.set("bookId",e);i.searchParams.set("keyword",r);i.searchParams.set("maxIdx",String(o));i.searchParams.set("count",String(h));i.searchParams.set("fragmentSize",String(n));i.searchParams.set("onlyCount","0");const d=await A(i,"WeRead in-book search");if(!Array.isArray(d?.result))throw new u("WeRead in-book search returned malformed result");const p=d.result.map((l)=>{if(!l||typeof l!=="object")throw new u("WeRead in-book search returned malformed match");const _=c(l.abstract),b=f(l.searchIdx);if(!_||b==null||b<=0)throw new u("WeRead in-book search returned malformed match");return{...l,abstract:_,chapterIdx:f(l.chapterIdx),chapterUid:f(l.chapterUid),searchIdx:b}});if(p.length===0)break;a.push(...p);const g=p[p.length-1].searchIdx;if(g<=o)throw new u("WeRead in-book search returned non-advancing searchIdx");o=g;if(a.length>=t)break;const I=z(d?.hasMore);if(I==null){if(p.length<h)break;throw new u("WeRead in-book search returned malformed pagination state")}if(!I)break}if(a.length===0)throw new y("weread book-search",`No matches for "${r}" in book ${e}`);return a.slice(0,t)}function Z(e){const r=new Map;for(const t of e){const n=f(t?.chapterUid);if(n==null)continue;r.set(n,{chapterIdx:f(t?.chapterIdx),chapterTitle:c(t?.title)})}return r}function N(e,r){const t=Z(e.chapters??[]);return r.map((n,a)=>{const o=f(n?.chapterUid),s=t.get(o)??{},h=s.chapterIdx??f(n?.chapterIdx);return{rank:a+1,book_title:e.title||null,author:e.author||null,chapter_idx:h,chapter_title:s.chapterTitle||null,snippet:c(n?.abstract),search_idx:n.searchIdx,chapter_uid:o,book_id:e.bookId,url:e.readerUrl||null}})}function P(e,r,t){const a=[`# ${e.title||`WeRead book ${e.bookId}`}`];if(e.author)a.push(`- author: ${e.author}`);a.push(`- book_id: \`${e.bookId}\``);a.push(`- query: \`${r}\``);a.push(`- matches: ${t.length}`);if(e.readerUrl)a.push(`- url: ${e.readerUrl}`);a.push("");for(const o of t){const s=o.chapter_title||`chapter ${o.chapter_uid??""}`.trim();a.push(`## ${o.rank}. ${s}`);const h=[];if(o.chapter_idx!==null)h.push(`chapter_idx: ${o.chapter_idx}`);if(o.chapter_uid!==null)h.push(`chapter_uid: ${o.chapter_uid}`);h.push(`search_idx: ${o.search_idx}`);a.push("");a.push(`> ${o.snippet}`);a.push("");for(const i of h)a.push(`- ${i}`);if(o.rank<t.length)a.push("")}return a.join(`
2
- `)}O({site:"weread",name:"book-search",access:"read",description:"Search within a WeRead book after resolving it by title",domain:"weread.qq.com",strategy:B.PUBLIC,browser:!1,defaultFormat:"md",args:[{name:"book",positional:!0,required:!0,help:"Book title keyword, numeric bookId, or reader URL"},{name:"query",positional:!0,required:!0,help:"Keyword to search inside the selected book"},{name:"book-rank",type:"int",default:1,help:"Which book search result to use when book is a title keyword"},{name:"limit",type:"int",default:20,help:"Max in-book matches to return (1-100)"},{name:"fragment-size",type:"int",default:150,help:"Snippet length around each match (1-500)"},{name:"raw",type:"boolean",default:!1,help:"Output structured rows instead of markdown text"}],func:async(e)=>{const r=R(e.book,"book"),t=R(e.query,"query"),n=k(e["book-rank"],1,"book-rank"),a=k(e.limit,20,"limit",C),o=k(e["fragment-size"],150,"fragment-size",j),s=await D(r,n),h=await X(s.bookId,t,a,o),i=N(s,h);if(Boolean(e.raw))return i;return[{markdown:P(s,t,i)}]}});export const __test__={buildRows:N,extractReaderInitialState:W,formatMarkdownResults:P,parseReaderMetadata:q,parseSearchHtmlEntries:M,resolveReaderUrlForBook:T};
1
+ import{cli as B,Strategy as C}from"@jackwener/opencli/registry";import{ArgumentError as m,CommandExecutionError as u,EmptyResultError as y}from"@jackwener/opencli/errors";import{WEREAD_UA as x,WEREAD_WEB_ORIGIN as w}from"./utils.js";const j=100,z=500,S=50;function R(e){return String(e||"").replace(/<[^>]+>/g,"").replace(/&#x([0-9a-fA-F]+);/gi,(r,t)=>String.fromCharCode(parseInt(t,16))).replace(/&#(\d+);/g,(r,t)=>String.fromCharCode(Number(t))).replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&quot;/g,'"').trim()}function c(e){return String(e||"").replace(/\s+/g," ").trim()}function k(e,r,t,n){const o=Number(e??r);if(!Number.isInteger(o)||o<=0)throw new m(`${t} must be a positive integer`);if(n!=null&&o>n)throw new m(`${t} must be <= ${n}`);return o}function f(e){if(e==null||e==="")return null;const r=Number(e);return Number.isFinite(r)?r:null}function F(e){if(e===!0||e===1||e==="1")return!0;if(e===!1||e===0||e==="0")return!1;return null}function U(e,r){const t=c(e);if(!t)throw new m(`${r} is required`);return t}function A(e){let r;try{r=new URL(String(e||""),w)}catch{return""}const t=r.pathname.split("/").filter(Boolean);if(r.protocol!=="https:"||r.hostname!=="weread.qq.com"||t[0]!=="web"||t[1]!=="reader"||!t[2])return"";if(t.length!==3)return"";return r.toString()}async function E(e,r){let t;try{t=await fetch(e.toString(),{headers:{"User-Agent":x}})}catch(n){throw new u(`${r} request failed: ${n instanceof Error?n.message:String(n)}`)}if(!t.ok)throw new u(`${r} request failed: HTTP ${t.status}`);try{return await t.json()}catch{throw new u(`${r} returned invalid JSON`)}}async function W(e,r){let t;try{t=await fetch(e.toString(),{headers:{"User-Agent":x}})}catch(n){throw new u(`${r} request failed: ${n instanceof Error?n.message:String(n)}`)}if(!t.ok)throw new u(`${r} request failed: HTTP ${t.status}`);return t.text()}function H(e){const r=c(e);return r?`${w}/web/reader/${r}`:""}function q(e){const r="window.__INITIAL_STATE__=",t=e.indexOf(r);if(t<0)return null;const n=t+r.length,a=e.indexOf(";(function(){var s;",n),o=e.indexOf("</script>",n),s=a>=0?a:o;if(s<0)return null;try{return JSON.parse(e.slice(n,s))}catch{return null}}function J(e){const r=e.match(/<script[^>]*type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/i);if(!r)return{};try{const t=JSON.parse(r[1]),n={};n.bookId=c(t?.["@Id"]);n.title=c(t?.name);n.author=c(t?.author?.name);n.readerUrl=c(t?.url);return n}catch{return{}}}function L(e,r){const n=q(e)?.reader??{},a=n.bookInfo??{},o=J(e),s=Array.isArray(n.chapterInfos)?n.chapterInfos:[],h=c(n.infoId)||c(a.encodeId),i={};i.bookId=c(a.bookId)||c(n.bookId)||o.bookId;i.title=c(a.title)||o.title;i.author=c(a.author)||o.author;i.readerUrl=c(r)||H(h)||o.readerUrl;i.chapters=s;return i}async function M(e){if(!e)return null;const r=await W(e,"WeRead reader page"),t=L(r,e);return t.bookId?t:null}function T(e){return Array.from(e.matchAll(/<li[^>]*class="wr_bookList_item"[^>]*>([\s\S]*?)<\/li>/g)).map((t)=>{const n=t[1],a=n.match(/<a[^>]*href="([^"]+)"[^>]*class="wr_bookList_item_link"[^>]*>|<a[^>]*class="wr_bookList_item_link"[^>]*href="([^"]+)"[^>]*>/),o=n.match(/<p[^>]*class="wr_bookList_item_title"[^>]*>([\s\S]*?)<\/p>/),s=n.match(/<p[^>]*class="wr_bookList_item_author"[^>]*>([\s\S]*?)<\/p>/),h=a?.[1]||a?.[2]||"",i={};i.title=R(o?.[1]||"");i.author=R(s?.[1]||"");i.readerUrl=h?A(h):"";return i}).filter((t)=>t.title&&t.readerUrl)}async function G(e){const r=new URL("/web/search/books",w);r.searchParams.set("keyword",e);return T(await W(r,"WeRead search page"))}function N(e,r){const t=c(e.title),n=c(e.author);if(!t)return"";if(n){const o=r.filter((s)=>c(s.title)===t&&c(s.author)===n);if(o.length===1)return o[0].readerUrl}const a=r.filter((o)=>c(o.title)===t);return a.length===1?a[0].readerUrl:""}async function D(e,r){const t=new URL("/web/search/global",`${w}/web`);t.searchParams.set("keyword",e);const n=await E(t,"WeRead book search");if(!Array.isArray(n?.books))throw new u("WeRead book search returned malformed books");const a=n.books;if(a.length===0)throw new y("weread book-search",`No WeRead books found for "${e}"`);if(r>a.length)throw new m(`book-rank must be <= ${a.length}`,`Only ${a.length} book search result(s) were returned for "${e}"`);const o=a[r-1]?.bookInfo??{},s={bookId:c(o.bookId),title:c(o.title),author:c(o.author),readerUrl:"",chapters:[]};if(!s.bookId)throw new u(`WeRead book search result ${r} is missing bookId`);const h=await G(e);s.readerUrl=N(s,h);const i=await M(s.readerUrl);return{...s,...Object.fromEntries(Object.entries(i??{}).filter(([,d])=>d!=null&&d!==""&&!(Array.isArray(d)&&d.length===0)))}}async function X(e,r){if(/^https?:\/\//i.test(e)){const t=A(e);if(!t)throw new m("book URL must be a https://weread.qq.com/web/reader/<id> URL");const n=await M(t);if(!n?.bookId)throw new u("Could not parse a bookId from the reader URL");return n}if(/^\d+$/.test(e)){const t={};t.bookId=e;t.title="";t.author="";t.readerUrl="";t.chapters=[];return t}return D(e,r)}async function Z(e,r,t,n){const a=[];let o=0;while(a.length<t){const s=t-a.length,h=s<S?s:S,i=new URL("/web/book/search",w);i.searchParams.set("bookId",e);i.searchParams.set("keyword",r);i.searchParams.set("maxIdx",String(o));i.searchParams.set("count",String(h));i.searchParams.set("fragmentSize",String(n));i.searchParams.set("onlyCount","0");const d=await E(i,"WeRead in-book search");if(!Array.isArray(d?.result))throw new u("WeRead in-book search returned malformed result");const p=d.result.map((l)=>{if(!l||typeof l!=="object")throw new u("WeRead in-book search returned malformed match");const _=c(l.abstract),b=f(l.searchIdx);if(!_||b==null||b<=0)throw new u("WeRead in-book search returned malformed match");return{...l,abstract:_,chapterIdx:f(l.chapterIdx),chapterUid:f(l.chapterUid),searchIdx:b}});if(p.length===0)break;a.push(...p);const g=p[p.length-1].searchIdx;if(g<=o)throw new u("WeRead in-book search returned non-advancing searchIdx");o=g;if(a.length>=t)break;const I=F(d?.hasMore);if(I==null){if(p.length<h)break;throw new u("WeRead in-book search returned malformed pagination state")}if(!I)break}if(a.length===0)throw new y("weread book-search",`No matches for "${r}" in book ${e}`);return a.slice(0,t)}function K(e){const r=new Map;for(const t of e){const n=f(t?.chapterUid);if(n==null)continue;r.set(n,{chapterIdx:f(t?.chapterIdx),chapterTitle:c(t?.title)})}return r}function P(e,r){const t=K(e.chapters??[]);return r.map((n,a)=>{const o=f(n?.chapterUid),s=t.get(o)??{},h=s.chapterIdx??f(n?.chapterIdx);return{rank:a+1,book_title:e.title||null,author:e.author||null,chapter_idx:h,chapter_title:s.chapterTitle||null,snippet:c(n?.abstract),search_idx:n.searchIdx,chapter_uid:o,book_id:e.bookId,url:e.readerUrl||null}})}function O(e,r,t){const a=[`# ${e.title||`WeRead book ${e.bookId}`}`];if(e.author)a.push(`- author: ${e.author}`);a.push(`- book_id: \`${e.bookId}\``);a.push(`- query: \`${r}\``);a.push(`- matches: ${t.length}`);if(e.readerUrl)a.push(`- url: ${e.readerUrl}`);a.push("");for(const o of t){const s=o.chapter_title||`chapter ${o.chapter_uid??""}`.trim();a.push(`## ${o.rank}. ${s}`);const h=[];if(o.chapter_idx!==null)h.push(`chapter_idx: ${o.chapter_idx}`);if(o.chapter_uid!==null)h.push(`chapter_uid: ${o.chapter_uid}`);h.push(`search_idx: ${o.search_idx}`);a.push("");a.push(`> ${o.snippet}`);a.push("");for(const i of h)a.push(`- ${i}`);if(o.rank<t.length)a.push("")}return a.join(`
2
+ `)}B({site:"weread",name:"book-search",access:"read",description:"Search within a WeRead book after resolving it by title",domain:"weread.qq.com",strategy:C.PUBLIC,browser:!1,defaultFormat:"md",args:[{name:"book",positional:!0,required:!0,help:"Book title keyword, numeric bookId, or reader URL"},{name:"query",positional:!0,required:!0,help:"Keyword to search inside the selected book"},{name:"book-rank",type:"int",default:1,help:"Which book search result to use when book is a title keyword"},{name:"limit",type:"int",default:20,help:"Max in-book matches to return (1-100)"},{name:"fragment-size",type:"int",default:150,help:"Snippet length around each match (1-500)"},{name:"raw",type:"boolean",default:!1,help:"Output structured rows instead of markdown text"}],func:async(e)=>{const r=U(e.book,"book"),t=U(e.query,"query"),n=k(e["book-rank"],1,"book-rank"),a=k(e.limit,20,"limit",j),o=k(e["fragment-size"],150,"fragment-size",z),s=await X(r,n),h=await Z(s.bookId,t,a,o),i=P(s,h);if(Boolean(e.raw))return i;return[{markdown:O(s,t,i)}]}});export const __test__={buildRows:P,extractReaderInitialState:q,formatMarkdownResults:O,parseReaderMetadata:L,parseSearchHtmlEntries:T,resolveReaderUrlForBook:N};
@@ -1,3 +1,3 @@
1
- import{cli as I,Strategy as f}from"@jackwener/opencli/registry";import{CliError as b}from"@jackwener/opencli/errors";import{fetchPrivateApi as S,fetchWebApi as E,resolveShelfReader as k,WEREAD_UA as g,WEREAD_WEB_ORIGIN as _}from"./utils.js";function W(J){return J.replace(/<[^>]+>/g,"").replace(/&#x([0-9a-fA-F]+);/gi,(L,j)=>String.fromCharCode(parseInt(j,16))).replace(/&#(\d+);/g,(L,j)=>String.fromCharCode(Number(j))).replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&quot;/g,'"').trim()}function Y(J){return J.replace(/\s+/g," ").trim()}function B(J,L){return`${Y(J)}\x00${Y(L)}`}function A(J){const L=new Map;for(const j of J){const q=Y(j.title);if(!q)continue;L.set(q,(L.get(q)||0)+1)}return L}function R(J){const L=new Map;for(const j of J){const q=B(j.title,j.author);if(!Y(j.title)||!Y(j.author))continue;L.set(q,(L.get(q)||0)+1)}return L}export function strictTitleFromWereadDocumentTitle(J){const L=" - 微信读书",j=String(J||"").trim();if(!j.endsWith(L))return"";const q=j.slice(0,-L.length).trim();return q.includes(" - ")?"":q}export function extractReaderFallbackMetadata(J){const L=(V)=>V?.textContent?.trim()||"",j=(...V)=>{for(const G of V){const Q=L(J.querySelector(G));if(Q)return Q}return""},q=J.body?.innerText?.replace(/\s+/g," ").trim()||"",P=()=>{const V=q.match(/微信读书推荐值\s*([0-9.]+%)/);return V?V[1]:""},Z=()=>{const V=L(J.querySelector(".introDialog_content_pub_line"));return V.startsWith("出版社")?V.replace(/^出版社\s*/,"").trim():""},$=()=>{const V=[".horizontalReaderCoverPage_content_bookInfo_intro",".wr_flyleaf_page_bookIntro_content",".introDialog_content_intro_para"];for(const G of V){const Q=L(J.querySelector(G));if(Q)return Q}return""},F=(Array.from(J.scripts||[]).map((V)=>V.textContent||"").find((V)=>V.includes('"category"'))||"").match(/"category"\s*:\s*"([^"]+)"/),w=j(".horizontalReaderCoverPage_content_bookTitle",".wr_flyleaf_page_bookInfo_bookTitle",".outline_book_detail_header_title",".readerTopBar_title_link")||strictTitleFromWereadDocumentTitle(J.title||""),O=j(".horizontalReaderCoverPage_content_author",".wr_flyleaf_page_bookInfo_author",".outline_book_detail_header_author");return{title:w,author:O,publisher:Z(),intro:$(),category:F?F[1].trim():"",rating:P(),metadataReady:Boolean(w||O)}}async function p(J,L){const j=Y(J),q=Y(L);if(!j)return"";try{const[P,Z]=await Promise.all([E("/search/global",{keyword:j}),(async()=>{const Q=new URL("/web/search/books",_);Q.searchParams.set("keyword",j);const N=await fetch(Q.toString(),{headers:{"User-Agent":g}});if(!N.ok)return[];const U=await N.text();return Array.from(U.matchAll(/<li[^>]*class="wr_bookList_item"[^>]*>([\s\S]*?)<\/li>/g)).map((H)=>{const K=H[1],C=K.match(/<a[^>]*href="([^"]+)"[^>]*class="wr_bookList_item_link"[^>]*>|<a[^>]*class="wr_bookList_item_link"[^>]*href="([^"]+)"[^>]*>/),v=K.match(/<p[^>]*class="wr_bookList_item_title"[^>]*>([\s\S]*?)<\/p>/),M=K.match(/<p[^>]*class="wr_bookList_item_author"[^>]*>([\s\S]*?)<\/p>/),D=C?.[1]||C?.[2]||"";return{title:W(v?.[1]||""),author:W(M?.[1]||""),url:D?new URL(D,_).toString():""}}).filter((H)=>H.title&&H.url)})()]),$=Array.isArray(P?.books)?P.books:[],X=R($.map((Q)=>({title:Q.bookInfo?.title??"",author:Q.bookInfo?.author??""}))),F=R(Z.filter((Q)=>Q.author)),w=B(j,q);if(q&&(X.get(w)||0)===1&&(F.get(w)||0)===1){const Q=Z.find((N)=>B(N.title,N.author)===w);if(Q?.url)return Q.url}const O=Z.filter((Q)=>Y(Q.title)===j);if(q&&O.some((Q)=>Y(Q.author)))return"";const V=A($.map((Q)=>({title:Q.bookInfo?.title??""}))),G=A(Z);if((V.get(j)||0)!==1||(G.get(j)||0)!==1)return"";return Z.find((Q)=>Y(Q.title)===j)?.url||""}catch{return""}}async function z(J,L){await J.goto(L);await J.wait({selector:".horizontalReaderCoverPage_content_bookTitle, .wr_flyleaf_page_bookInfo_bookTitle, .readerTopBar_title_link",timeout:10});const j=await J.evaluate(`
1
+ import{cli as A,Strategy as v}from"@jackwener/opencli/registry";import{CliError as E}from"@jackwener/opencli/errors";import{fetchPrivateApi as U,fetchWebApi as z,resolveShelfReader as M,WEREAD_UA as P,WEREAD_WEB_ORIGIN as w}from"./utils.js";function S(r){return r.replace(/<[^>]+>/g,"").replace(/&#x([0-9a-fA-F]+);/gi,(o,t)=>String.fromCharCode(parseInt(t,16))).replace(/&#(\d+);/g,(o,t)=>String.fromCharCode(Number(t))).replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&quot;/g,'"').trim()}function c(r){return r.replace(/\s+/g," ").trim()}function p(r,o){return`${c(r)}\x00${c(o)}`}function R(r){const o=new Map;for(const t of r){const e=c(t.title);if(!e)continue;o.set(e,(o.get(e)||0)+1)}return o}function I(r){const o=new Map;for(const t of r){const e=p(t.title,t.author);if(!c(t.title)||!c(t.author))continue;o.set(e,(o.get(e)||0)+1)}return o}export function strictTitleFromWereadDocumentTitle(r){const o=" - 微信读书",t=String(r||"").trim();if(!t.endsWith(o))return"";const e=t.slice(0,-o.length).trim();return e.includes(" - ")?"":e}export function extractReaderFallbackMetadata(r){const o=(a)=>a?.textContent?.trim()||"",t=(...a)=>{for(const m of a){const n=o(r.querySelector(m));if(n)return n}return""},e=r.body?.innerText?.replace(/\s+/g," ").trim()||"",u=()=>{const a=e.match(/微信读书推荐值\s*([0-9.]+%)/);return a?a[1]:""},s=()=>{const a=o(r.querySelector(".introDialog_content_pub_line"));return a.startsWith("出版社")?a.replace(/^出版社\s*/,"").trim():""},l=()=>{const a=[".horizontalReaderCoverPage_content_bookInfo_intro",".wr_flyleaf_page_bookIntro_content",".introDialog_content_intro_para"];for(const m of a){const n=o(r.querySelector(m));if(n)return n}return""},f=(Array.from(r.scripts||[]).map((a)=>a.textContent||"").find((a)=>a.includes('"category"'))||"").match(/"category"\s*:\s*"([^"]+)"/),h=t(".horizontalReaderCoverPage_content_bookTitle",".wr_flyleaf_page_bookInfo_bookTitle",".outline_book_detail_header_title",".readerTopBar_title_link")||strictTitleFromWereadDocumentTitle(r.title||""),g=t(".horizontalReaderCoverPage_content_author",".wr_flyleaf_page_bookInfo_author",".outline_book_detail_header_author");return{title:h,author:g,publisher:s(),intro:l(),category:f?f[1].trim():"",rating:u(),metadataReady:Boolean(h||g)}}async function W(r,o){const t=c(r),e=c(o);if(!t)return"";try{const[u,s]=await Promise.all([z("/search/global",{keyword:t}),(async()=>{const n=new URL("/web/search/books",w);n.searchParams.set("keyword",t);const d=await fetch(n.toString(),{headers:{"User-Agent":P}});if(!d.ok)return[];const x=await d.text();return Array.from(x.matchAll(/<li[^>]*class="wr_bookList_item"[^>]*>([\s\S]*?)<\/li>/g)).map((_)=>{const b=_[1],y=b.match(/<a[^>]*href="([^"]+)"[^>]*class="wr_bookList_item_link"[^>]*>|<a[^>]*class="wr_bookList_item_link"[^>]*href="([^"]+)"[^>]*>/),T=b.match(/<p[^>]*class="wr_bookList_item_title"[^>]*>([\s\S]*?)<\/p>/),C=b.match(/<p[^>]*class="wr_bookList_item_author"[^>]*>([\s\S]*?)<\/p>/),k=y?.[1]||y?.[2]||"";return{title:S(T?.[1]||""),author:S(C?.[1]||""),url:k?new URL(k,w).toString():""}}).filter((_)=>_.title&&_.url)})()]),l=Array.isArray(u?.books)?u.books:[],i=I(l.map((n)=>({title:n.bookInfo?.title??"",author:n.bookInfo?.author??""}))),f=I(s.filter((n)=>n.author)),h=p(t,e);if(e&&(i.get(h)||0)===1&&(f.get(h)||0)===1){const n=s.find((d)=>p(d.title,d.author)===h);if(n?.url)return n.url}const g=s.filter((n)=>c(n.title)===t);if(e&&g.some((n)=>c(n.author)))return"";const a=R(l.map((n)=>({title:n.bookInfo?.title??""}))),m=R(s);if((a.get(t)||0)!==1||(m.get(t)||0)!==1)return"";return s.find((n)=>c(n.title)===t)?.url||""}catch{return""}}async function q(r,o){await r.goto(o);await r.wait({selector:".horizontalReaderCoverPage_content_bookTitle, .wr_flyleaf_page_bookInfo_bookTitle, .readerTopBar_title_link",timeout:10});const t=await r.evaluate(`
2
2
  (${extractReaderFallbackMetadata.toString()})(document)
3
- `);return{title:String(j?.title||"").trim(),author:String(j?.author||"").trim(),publisher:String(j?.publisher||"").trim(),intro:String(j?.intro||"").trim(),category:String(j?.category||"").trim(),rating:String(j?.rating||"").trim(),metadataReady:j?.metadataReady===!0}}I({site:"weread",name:"book",access:"read",description:"View book details on WeRead",domain:"weread.qq.com",strategy:f.COOKIE,args:[{name:"book-id",positional:!0,required:!0,help:"Book ID from search or shelf results"}],columns:["title","author","publisher","intro","category","rating"],func:async(J,L)=>{const j=String(L["book-id"]||"").trim();try{const q=await S(J,"/book/info",{bookId:j}),P=q.newRating?`${(q.newRating/10).toFixed(1)}%`:"-";return[{title:q.title??"",author:q.author??"",publisher:q.publisher??"",intro:q.intro??"",category:q.category??"",rating:P}]}catch(q){if(!(q instanceof b)||q.code!=="AUTH_REQUIRED")throw q;const{readerUrl:P,snapshot:Z}=await k(J,j);let $=P;if(!$){const F=Z.rawBooks.find((w)=>String(w?.bookId||"").trim()===j);$=await p(String(F?.title||""),String(F?.author||""))}if(!$)throw q;const X=await z(J,$);if(!X.metadataReady||!X.title)throw q;return[{title:X.title,author:X.author,publisher:X.publisher,intro:X.intro,category:X.category,rating:X.rating}]}}});
3
+ `);return{title:String(t?.title||"").trim(),author:String(t?.author||"").trim(),publisher:String(t?.publisher||"").trim(),intro:String(t?.intro||"").trim(),category:String(t?.category||"").trim(),rating:String(t?.rating||"").trim(),metadataReady:t?.metadataReady===!0}}A({site:"weread",name:"book",access:"read",description:"View book details on WeRead",domain:"weread.qq.com",strategy:v.COOKIE,args:[{name:"book-id",positional:!0,required:!0,help:"Book ID from search or shelf results"}],columns:["title","author","publisher","intro","category","rating"],func:async(r,o)=>{const t=String(o["book-id"]||"").trim();try{const e=await U(r,"/book/info",{bookId:t}),u=e.newRating?`${(e.newRating/10).toFixed(1)}%`:"-";return[{title:e.title??"",author:e.author??"",publisher:e.publisher??"",intro:e.intro??"",category:e.category??"",rating:u}]}catch(e){if(!(e instanceof E)||e.code!=="AUTH_REQUIRED")throw e;const{readerUrl:u,snapshot:s}=await M(r,t);let l=u;if(!l){const f=s.rawBooks.find((h)=>String(h?.bookId||"").trim()===t);l=await W(String(f?.title||""),String(f?.author||""))}if(!l)throw e;const i=await q(r,l);if(!i.metadataReady||!i.title)throw e;return[{title:i.title,author:i.author,publisher:i.publisher,intro:i.intro,category:i.category,rating:i.rating}]}}});
@@ -1 +1 @@
1
- import{cli as z,Strategy as B}from"@jackwener/opencli/registry";import{fetchPrivateApi as E}from"./utils.js";z({site:"weread",name:"notebooks",access:"read",description:"List books that have highlights or notes",domain:"weread.qq.com",strategy:B.COOKIE,columns:["title","author","noteCount","bookId"],func:async(x,F)=>{return((await E(x,"/user/notebooks"))?.books??[]).map((q)=>({title:q.book?.title??"",author:q.book?.author??"",noteCount:(q.bookmarkCount??0)+(q.reviewCount??0),bookId:q.bookId??""}))}});
1
+ import{cli as a,Strategy as e}from"@jackwener/opencli/registry";import{fetchPrivateApi as r}from"./utils.js";a({site:"weread",name:"notebooks",access:"read",description:"List books that have highlights or notes",domain:"weread.qq.com",strategy:e.COOKIE,columns:["title","author","noteCount","bookId"],func:async(t,s)=>{return((await r(t,"/user/notebooks"))?.books??[]).map((o)=>({title:o.book?.title??"",author:o.book?.author??"",noteCount:(o.bookmarkCount??0)+(o.reviewCount??0),bookId:o.bookId??""}))}});
@@ -1 +1 @@
1
- import{cli as O,Strategy as R}from"@jackwener/opencli/registry";import{CommandExecutionError as _,EmptyResultError as Q}from"@jackwener/opencli/errors";import{fetchWebApi as K,WEREAD_UA as U,WEREAD_WEB_ORIGIN as A}from"./utils.js";function M(Y,V){const F=parseInt(Y,V);if(!Number.isInteger(F)||F<0||F>1114111)return null;try{return String.fromCodePoint(F)}catch{return null}}function W(Y){return Y.replace(/<[^>]+>/g,"").replace(/&#x([0-9a-fA-F]+);/gi,(V,F)=>M(F,16)??V).replace(/&#(\d+);/g,(V,F)=>M(F,10)??V).replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").trim()}function j(Y){return Y.replace(/\s+/g," ").trim()}function f(Y,V){return`${j(Y)}\x00${j(V)}`}function w(Y){const V=new Map;for(const F of Y){const X=j(F.title);if(!X)continue;V.set(X,(V.get(X)||0)+1)}return V}function z(Y){const V=new Map;for(const F of Y){const X=f(F.title,F.author);if(!j(F.title)||!j(F.author))continue;V.set(X,(V.get(X)||0)+1)}return V}function N(Y,V){return(Y.get(V)||0)<=1}function q(Y){const V=new Map,F=new Map;for(const X of Y){const B=j(X.title);if(!B||!X.url)continue;const $=X.author?V:F,J=X.author?f(X.title,X.author):B,L=$.get(J);if(L){L.push(X.url);continue}$.set(J,[X.url])}return{exactQueues:V,titleOnlyQueues:F}}function g(Y){const{exactQueues:V,titleOnlyQueues:F,apiIdentityCounts:X,htmlIdentityCounts:B,apiTitleCounts:$,htmlTitleCounts:J,title:L,author:H}=Y,G=f(L,H);if(N(X,G)&&N(B,G)){const D=V.get(G)?.shift();if(D)return D}const Z=j(L);if(!N($,Z)||!N(J,Z))return"";return F.get(Z)?.shift()??""}async function x(Y){const V=new URL("/web/search/books",A);V.searchParams.set("keyword",Y);let F;try{F=await fetch(V.toString(),{headers:{"User-Agent":U}})}catch($){throw new _(`Failed to fetch WeRead search page: ${$ instanceof Error?$.message:String($)}`)}if(!F.ok)throw new _(`WeRead search page request failed: HTTP ${F.status}`);const X=await F.text();return Array.from(X.matchAll(/<li[^>]*class="wr_bookList_item"[^>]*>([\s\S]*?)<\/li>/g)).map(($)=>{const J=$[1],L=J.match(/<a[^>]*href="([^"]+)"[^>]*class="wr_bookList_item_link"[^>]*>|<a[^>]*class="wr_bookList_item_link"[^>]*href="([^"]+)"[^>]*>/),H=J.match(/<p[^>]*class="wr_bookList_item_title"[^>]*>([\s\S]*?)<\/p>/),G=J.match(/<p[^>]*class="wr_bookList_item_author"[^>]*>([\s\S]*?)<\/p>/),Z=L?.[1]||L?.[2]||"",D=W(H?.[1]||"");return{author:W(G?.[1]||""),url:Z?new URL(Z,A).toString():"",title:D}}).filter(($)=>$.url&&$.title)}O({site:"weread",name:"search",access:"read",description:"Search books on WeRead",domain:"weread.qq.com",strategy:R.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:"Search keyword"},{name:"limit",type:"int",default:10,help:"Max results"}],columns:["rank","title","author","bookId","url"],func:async(Y)=>{const[V,F]=await Promise.all([K("/search/global",{keyword:Y.query}),x(String(Y.query??""))]),X=V?.books??[];if(!Array.isArray(X))throw new _("WeRead search API returned an unreadable books payload");if(X.length===0)throw new Q("weread search",`No books were returned for query ${Y.query}.`);const{exactQueues:B,titleOnlyQueues:$}=q(F),J=z(X.map((Z)=>({title:Z.bookInfo?.title??"",author:Z.bookInfo?.author??""}))),L=z(F.filter((Z)=>Z.author)),H=w(X.map((Z)=>({title:Z.bookInfo?.title??""}))),G=w(F);return X.slice(0,Number(Y.limit)).map((Z,D)=>{const P=Z.bookInfo?.title??"",v=Z.bookInfo?.author??"";return{rank:D+1,title:P,author:v,bookId:Z.bookInfo?.bookId??"",url:g({exactQueues:B,titleOnlyQueues:$,apiIdentityCounts:J,htmlIdentityCounts:L,apiTitleCounts:H,htmlTitleCounts:G,title:P,author:v})}})}});
1
+ import{cli as _,Strategy as q}from"@jackwener/opencli/registry";import{CommandExecutionError as d,EmptyResultError as E}from"@jackwener/opencli/errors";import{fetchWebApi as C,WEREAD_UA as A,WEREAD_WEB_ORIGIN as w}from"./utils.js";function b(o,e){const t=parseInt(o,e);if(!Number.isInteger(t)||t<0||t>1114111)return null;try{return String.fromCodePoint(t)}catch{return null}}function g(o){return o.replace(/<[^>]+>/g,"").replace(/&#x([0-9a-fA-F]+);/gi,(e,t)=>b(t,16)??e).replace(/&#(\d+);/g,(e,t)=>b(t,10)??e).replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").trim()}function l(o){return o.replace(/\s+/g," ").trim()}function y(o,e){return`${l(o)}\x00${l(e)}`}function I(o){const e=new Map;for(const t of o){const r=l(t.title);if(!r)continue;e.set(r,(e.get(r)||0)+1)}return e}function S(o){const e=new Map;for(const t of o){const r=y(t.title,t.author);if(!l(t.title)||!l(t.author))continue;e.set(r,(e.get(r)||0)+1)}return e}function m(o,e){return(o.get(e)||0)<=1}function R(o){const e=new Map,t=new Map;for(const r of o){const c=l(r.title);if(!c||!r.url)continue;const a=r.author?e:t,s=r.author?y(r.title,r.author):c,i=a.get(s);if(i){i.push(r.url);continue}a.set(s,[r.url])}return{exactQueues:e,titleOnlyQueues:t}}function x(o){const{exactQueues:e,titleOnlyQueues:t,apiIdentityCounts:r,htmlIdentityCounts:c,apiTitleCounts:a,htmlTitleCounts:s,title:i,author:f}=o,u=y(i,f);if(m(r,u)&&m(c,u)){const h=e.get(u)?.shift();if(h)return h}const n=l(i);if(!m(a,n)||!m(s,n))return"";return t.get(n)?.shift()??""}async function M(o){const e=new URL("/web/search/books",w);e.searchParams.set("keyword",o);let t;try{t=await fetch(e.toString(),{headers:{"User-Agent":A}})}catch(a){throw new d(`Failed to fetch WeRead search page: ${a instanceof Error?a.message:String(a)}`)}if(!t.ok)throw new d(`WeRead search page request failed: HTTP ${t.status}`);const r=await t.text();return Array.from(r.matchAll(/<li[^>]*class="wr_bookList_item"[^>]*>([\s\S]*?)<\/li>/g)).map((a)=>{const s=a[1],i=s.match(/<a[^>]*href="([^"]+)"[^>]*class="wr_bookList_item_link"[^>]*>|<a[^>]*class="wr_bookList_item_link"[^>]*href="([^"]+)"[^>]*>/),f=s.match(/<p[^>]*class="wr_bookList_item_title"[^>]*>([\s\S]*?)<\/p>/),u=s.match(/<p[^>]*class="wr_bookList_item_author"[^>]*>([\s\S]*?)<\/p>/),n=i?.[1]||i?.[2]||"",h=g(f?.[1]||"");return{author:g(u?.[1]||""),url:n?new URL(n,w).toString():"",title:h}}).filter((a)=>a.url&&a.title)}_({site:"weread",name:"search",access:"read",description:"Search books on WeRead",domain:"weread.qq.com",strategy:q.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:"Search keyword"},{name:"limit",type:"int",default:10,help:"Max results"}],columns:["rank","title","author","bookId","url"],func:async(o)=>{const[e,t]=await Promise.all([C("/search/global",{keyword:o.query}),M(String(o.query??""))]),r=e?.books??[];if(!Array.isArray(r))throw new d("WeRead search API returned an unreadable books payload");if(r.length===0)throw new E("weread search",`No books were returned for query ${o.query}.`);const{exactQueues:c,titleOnlyQueues:a}=R(t),s=S(r.map((n)=>({title:n.bookInfo?.title??"",author:n.bookInfo?.author??""}))),i=S(t.filter((n)=>n.author)),f=I(r.map((n)=>({title:n.bookInfo?.title??""}))),u=I(t);return r.slice(0,Number(o.limit)).map((n,h)=>{const p=n.bookInfo?.title??"",k=n.bookInfo?.author??"";return{rank:h+1,title:p,author:k,bookId:n.bookInfo?.bookId??"",url:x({exactQueues:c,titleOnlyQueues:a,apiIdentityCounts:s,htmlIdentityCounts:i,apiTitleCounts:f,htmlTitleCounts:u,title:p,author:k})}})}});
@@ -1 +1 @@
1
- import{cli as G,Strategy as H}from"@jackwener/opencli/registry";import{CliError as J}from"@jackwener/opencli/errors";import{log as K}from"@jackwener/opencli/logger";import{buildWebShelfEntries as M,fetchPrivateApi as N,loadWebShelfSnapshot as O}from"./utils.js";function Q(B){if(!Number.isFinite(B))return 0;return Math.max(0,Math.trunc(B))}function T(B,D){return(B?.books??[]).slice(0,D).map((q)=>({title:q.bookInfo?.title??q.title??"",author:q.bookInfo?.author??q.author??"",progress:q.readingProgress!=null?`${q.readingProgress}%`:"-",bookId:q.bookId??q.bookInfo?.bookId??""}))}function U(B,D){if(D<=0)return[];return M(B).map((x)=>({title:x.title,author:x.author,progress:"-",bookId:x.bookId})).filter((x)=>Boolean(x.title||x.bookId)).slice(0,D)}G({site:"weread",name:"shelf",access:"read",description:"List books on your WeRead bookshelf",domain:"weread.qq.com",strategy:H.COOKIE,args:[{name:"limit",type:"int",default:20,help:"Max results"}],columns:["title","author","progress","bookId"],func:async(B,D)=>{const x=Q(Number(D.limit));if(x<=0)return[];try{const q=await N(B,"/shelf/sync",{synckey:"0",lectureSynckey:"0"});return T(q,x)}catch(q){if(!(q instanceof J)||q.code!=="AUTH_REQUIRED")throw q;const F=await O(B);if(!F.cacheFound)throw q;K.warn("WeRead private API auth expired; showing cached shelf data from localStorage. Results may be stale, and detail commands may still require re-login.");return U(F,x)}}});
1
+ import{cli as n,Strategy as s}from"@jackwener/opencli/registry";import{CliError as i}from"@jackwener/opencli/errors";import{log as l}from"@jackwener/opencli/logger";import{buildWebShelfEntries as c,fetchPrivateApi as u,loadWebShelfSnapshot as f}from"./utils.js";function d(e){if(!Number.isFinite(e))return 0;return Math.max(0,Math.trunc(e))}function h(e,t){return(e?.books??[]).slice(0,t).map((o)=>({title:o.bookInfo?.title??o.title??"",author:o.bookInfo?.author??o.author??"",progress:o.readingProgress!=null?`${o.readingProgress}%`:"-",bookId:o.bookId??o.bookInfo?.bookId??""}))}function b(e,t){if(t<=0)return[];return c(e).map((r)=>({title:r.title,author:r.author,progress:"-",bookId:r.bookId})).filter((r)=>Boolean(r.title||r.bookId)).slice(0,t)}n({site:"weread",name:"shelf",access:"read",description:"List books on your WeRead bookshelf",domain:"weread.qq.com",strategy:s.COOKIE,args:[{name:"limit",type:"int",default:20,help:"Max results"}],columns:["title","author","progress","bookId"],func:async(e,t)=>{const r=d(Number(t.limit));if(r<=0)return[];try{const o=await u(e,"/shelf/sync",{synckey:"0",lectureSynckey:"0"});return h(o,r)}catch(o){if(!(o instanceof i)||o.code!=="AUTH_REQUIRED")throw o;const a=await f(e);if(!a.cacheFound)throw o;l.warn("WeRead private API auth expired; showing cached shelf data from localStorage. Results may be stale, and detail commands may still require re-login.");return b(a,r)}}});
@@ -1,9 +1,9 @@
1
- import{CliError as P}from"@jackwener/opencli/errors";export const WEREAD_DOMAIN="weread.qq.com",WEREAD_WEB_ORIGIN=`https://${WEREAD_DOMAIN}`,WEREAD_SHELF_URL=`${WEREAD_WEB_ORIGIN}/web/shelf`;const v=`${WEREAD_WEB_ORIGIN}/web`,C=`https://i.${WEREAD_DOMAIN}`;export const WEREAD_UA="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";const D=new Set([-2010,-2012]);function V(J){return J.map((Q)=>`${Q.name}=${Q.value}`).join("; ")}function _(J,Q){return J.status===401||D.has(Number(Q?.errcode))}function w(J){return String(J.find((Q)=>Q.name==="wr_vid")?.value||"").trim()}function N(J){return{rawBooksKey:`shelf:rawBooks:${J}`,shelfIndexesKey:`shelf:shelfIndexes:${J}`}}function O(J){return{cacheFound:J?.cacheFound===!0,rawBooks:Array.isArray(J?.rawBooks)?J.rawBooks:[],shelfIndexes:Array.isArray(J?.shelfIndexes)?J.shelfIndexes:[]}}function T(J,Q){return`
1
+ import{CliError as f}from"@jackwener/opencli/errors";export const WEREAD_DOMAIN="weread.qq.com",WEREAD_WEB_ORIGIN=`https://${WEREAD_DOMAIN}`,WEREAD_SHELF_URL=`${WEREAD_WEB_ORIGIN}/web/shelf`;const g=`${WEREAD_WEB_ORIGIN}/web`,A=`https://i.${WEREAD_DOMAIN}`;export const WEREAD_UA="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";const R=new Set([-2010,-2012]);function x(e){return e.map((r)=>`${r.name}=${r.value}`).join("; ")}function B(e,r){return e.status===401||R.has(Number(r?.errcode))}function b(e){return String(e.find((r)=>r.name==="wr_vid")?.value||"").trim()}function m(e){return{rawBooksKey:`shelf:rawBooks:${e}`,shelfIndexesKey:`shelf:shelfIndexes:${e}`}}function k(e){return{cacheFound:e?.cacheFound===!0,rawBooks:Array.isArray(e?.rawBooks)?e.rawBooks:[],shelfIndexes:Array.isArray(e?.shelfIndexes)?e.shelfIndexes:[]}}function y(e,r){return`
2
2
  (() => new Promise((resolve) => {
3
3
  const deadline = Date.now() + 5000;
4
- const rawBooksKey = ${JSON.stringify(J.rawBooksKey)};
5
- const shelfIndexesKey = ${JSON.stringify(J.shelfIndexesKey)};
6
- const requireTrustedIndexes = ${JSON.stringify(Q)};
4
+ const rawBooksKey = ${JSON.stringify(e.rawBooksKey)};
5
+ const shelfIndexesKey = ${JSON.stringify(e.shelfIndexesKey)};
6
+ const requireTrustedIndexes = ${JSON.stringify(r)};
7
7
 
8
8
  const readJson = (raw) => {
9
9
  if (typeof raw !== 'string') return null;
@@ -57,11 +57,11 @@ import{CliError as P}from"@jackwener/opencli/errors";export const WEREAD_DOMAIN=
57
57
 
58
58
  poll();
59
59
  }))
60
- `}export async function fetchWebApi(J,Q){const Y=new URL(`${v}${J}`);if(Q)for(const[X,z]of Object.entries(Q))Y.searchParams.set(X,z);const Z=await fetch(Y.toString(),{headers:{"User-Agent":WEREAD_UA}});if(!Z.ok)throw new P("FETCH_ERROR",`HTTP ${Z.status} for ${J}`,"WeRead API may be temporarily unavailable");try{return await Z.json()}catch{throw new P("PARSE_ERROR",`Invalid JSON response for ${J}`,"WeRead may have returned an HTML error page")}}export async function fetchPrivateApi(J,Q,Y){const Z=new URL(`${C}${Q}`);if(Y)for(const[$,q]of Object.entries(Y))Z.searchParams.set($,q);const X=Z.toString(),[z,G]=await Promise.all([J.getCookies({url:X}),J.getCookies({domain:WEREAD_DOMAIN})]),L=new Map;for(const $ of G)L.set($.name,$);for(const $ of z)L.set($.name,$);const j=V(Array.from(L.values()));let M;try{M=await fetch(X,{headers:{"User-Agent":WEREAD_UA,Origin:"https://weread.qq.com",Referer:"https://weread.qq.com/",...j?{Cookie:j}:{}}})}catch($){throw new P("FETCH_ERROR",`Failed to fetch ${Q}: ${$ instanceof Error?$.message:String($)}`,"WeRead API may be temporarily unavailable")}let F;try{F=await M.json()}catch{throw new P("PARSE_ERROR",`Invalid JSON response for ${Q}`,"WeRead may have returned an HTML error page")}if(_(M,F))throw new P("AUTH_REQUIRED","Not logged in to WeRead","Please log in to weread.qq.com in Chrome first");if(!M.ok)throw new P("FETCH_ERROR",`HTTP ${M.status} for ${Q}`,"WeRead API may be temporarily unavailable");if(F?.errcode!=null&&F.errcode!==0)throw new P("API_ERROR",F.errmsg??`WeRead API error ${F.errcode}`);return F}function H(J){return Array.from(new Set(J.rawBooks.map((Q)=>String(Q?.bookId||"").trim()).filter(Boolean)))}function K(J){const Q=H(J);if(Q.length===0)return[];const Y=new Set(Q),Z=Array.from(new Set(J.shelfIndexes.filter((X)=>Number.isFinite(X?.idx)).sort((X,z)=>Number(X?.idx??Number.MAX_SAFE_INTEGER)-Number(z?.idx??Number.MAX_SAFE_INTEGER)).map((X)=>String(X?.bookId||"").trim()).filter((X)=>Y.has(X))));return Z.length===Q.length?Z:[]}export function buildWebShelfEntries(J,Q=[]){const Y=H(J),Z=K(J),X=Z.length>0?Z:Y,z=new Map;for(const G of J.rawBooks){const L=String(G?.bookId||"").trim();if(!L||z.has(L))continue;z.set(L,G)}return X.map((G,L)=>{const j=z.get(G);return{bookId:G,title:String(j?.title||"").trim(),author:String(j?.author||"").trim(),readerUrl:String(Q[L]||"").trim()}})}async function U(J){await J.goto(WEREAD_SHELF_URL);const Q=await J.getCookies({domain:WEREAD_DOMAIN}),Y=w(Q);if(!Y)return{snapshot:{cacheFound:!1,rawBooks:[],shelfIndexes:[]},currentVid:""};const Z=await J.evaluate(T(N(Y),!1));return{snapshot:O(Z),currentVid:Y}}export async function loadWebShelfSnapshot(J){const{snapshot:Q}=await U(J);return Q}async function x(J,Q,Y){if(!Q.cacheFound)return Q;if(K(Q).length>0)return Q;if(!Y)return Q;const Z=await J.evaluate(T(N(Y),!0));return O(Z)}export async function resolveShelfReaderUrl(J,Q){return(await resolveShelfReader(J,Q)).readerUrl}export async function resolveShelfReader(J,Q){const{snapshot:Y,currentVid:Z}=await U(J),X=await x(J,Y,Z);if(!X.cacheFound)return{snapshot:X,readerUrl:null};const z=H(X),G=K(X),L=G.length===0&&z.length>0&&X.shelfIndexes.length===0;if(G.length===0&&!L)return{snapshot:X,readerUrl:null};const j=await J.evaluate(`
60
+ `}export async function fetchWebApi(e,r){const o=new URL(`${g}${e}`);if(r)for(const[t,a]of Object.entries(r))o.searchParams.set(t,a);const n=await fetch(o.toString(),{headers:{"User-Agent":WEREAD_UA}});if(!n.ok)throw new f("FETCH_ERROR",`HTTP ${n.status} for ${e}`,"WeRead API may be temporarily unavailable");try{return await n.json()}catch{throw new f("PARSE_ERROR",`Invalid JSON response for ${e}`,"WeRead may have returned an HTML error page")}}export async function fetchPrivateApi(e,r,o){const n=new URL(`${A}${r}`);if(o)for(const[s,h]of Object.entries(o))n.searchParams.set(s,h);const t=n.toString(),[a,i]=await Promise.all([e.getCookies({url:t}),e.getCookies({domain:WEREAD_DOMAIN})]),d=new Map;for(const s of i)d.set(s.name,s);for(const s of a)d.set(s.name,s);const l=x(Array.from(d.values()));let u;try{u=await fetch(t,{headers:{"User-Agent":WEREAD_UA,Origin:"https://weread.qq.com",Referer:"https://weread.qq.com/",...l?{Cookie:l}:{}}})}catch(s){throw new f("FETCH_ERROR",`Failed to fetch ${r}: ${s instanceof Error?s.message:String(s)}`,"WeRead API may be temporarily unavailable")}let c;try{c=await u.json()}catch{throw new f("PARSE_ERROR",`Invalid JSON response for ${r}`,"WeRead may have returned an HTML error page")}if(B(u,c))throw new f("AUTH_REQUIRED","Not logged in to WeRead","Please log in to weread.qq.com in Chrome first");if(!u.ok)throw new f("FETCH_ERROR",`HTTP ${u.status} for ${r}`,"WeRead API may be temporarily unavailable");if(c?.errcode!=null&&c.errcode!==0)throw new f("API_ERROR",c.errmsg??`WeRead API error ${c.errcode}`);return c}function w(e){return Array.from(new Set(e.rawBooks.map((r)=>String(r?.bookId||"").trim()).filter(Boolean)))}function I(e){const r=w(e);if(r.length===0)return[];const o=new Set(r),n=Array.from(new Set(e.shelfIndexes.filter((t)=>Number.isFinite(t?.idx)).sort((t,a)=>Number(t?.idx??Number.MAX_SAFE_INTEGER)-Number(a?.idx??Number.MAX_SAFE_INTEGER)).map((t)=>String(t?.bookId||"").trim()).filter((t)=>o.has(t))));return n.length===r.length?n:[]}export function buildWebShelfEntries(e,r=[]){const o=w(e),n=I(e),t=n.length>0?n:o,a=new Map;for(const i of e.rawBooks){const d=String(i?.bookId||"").trim();if(!d||a.has(d))continue;a.set(d,i)}return t.map((i,d)=>{const l=a.get(i);return{bookId:i,title:String(l?.title||"").trim(),author:String(l?.author||"").trim(),readerUrl:String(r[d]||"").trim()}})}async function S(e){await e.goto(WEREAD_SHELF_URL);const r=await e.getCookies({domain:WEREAD_DOMAIN}),o=b(r);if(!o)return{snapshot:{cacheFound:!1,rawBooks:[],shelfIndexes:[]},currentVid:""};const n=await e.evaluate(y(m(o),!1));return{snapshot:k(n),currentVid:o}}export async function loadWebShelfSnapshot(e){const{snapshot:r}=await S(e);return r}async function E(e,r,o){if(!r.cacheFound)return r;if(I(r).length>0)return r;if(!o)return r;const n=await e.evaluate(y(m(o),!0));return k(n)}export async function resolveShelfReaderUrl(e,r){return(await resolveShelfReader(e,r)).readerUrl}export async function resolveShelfReader(e,r){const{snapshot:o,currentVid:n}=await S(e),t=await E(e,o,n);if(!t.cacheFound)return{snapshot:t,readerUrl:null};const a=w(t),i=I(t),d=i.length===0&&a.length>0&&t.shelfIndexes.length===0;if(i.length===0&&!d)return{snapshot:t,readerUrl:null};const l=await e.evaluate(`
61
61
  (() => Array.from(document.querySelectorAll('a.shelfBook[href]'))
62
62
  .map((anchor) => {
63
63
  const href = anchor.getAttribute('href') || '';
64
64
  return href ? new URL(href, location.origin).toString() : '';
65
65
  })
66
66
  .filter(Boolean))
67
- `),M=G.length>0?G.length:z.length;if(j.length!==M)return{snapshot:X,readerUrl:null};const $=buildWebShelfEntries(X,j).find((q)=>q.bookId===Q);return{snapshot:X,readerUrl:$?.readerUrl||null}}export function formatDate(J){if(!Number.isFinite(J)||J<=0)return"-";return new Date(J*1000+28800000).toISOString().slice(0,10)}
67
+ `),u=i.length>0?i.length:a.length;if(l.length!==u)return{snapshot:t,readerUrl:null};const s=buildWebShelfEntries(t,l).find((h)=>h.bookId===r);return{snapshot:t,readerUrl:s?.readerUrl||null}}export function formatDate(e){if(!Number.isFinite(e)||e<=0)return"-";return new Date(e*1000+28800000).toISOString().slice(0,10)}
@@ -1 +1 @@
1
- import{cli as S,Strategy as T}from"@jackwener/opencli/registry";import{callGateway as q,emptyResult as G,formatDate as L,formatDuration as U,formatRating as v,makeDeepLink as R,requireBookId as D,truncate as P}from"./utils.js";S({site:"weread-official",name:"book",access:"read",description:"Show WeRead book metadata, chapters, and reading progress",domain:"weread.qq.com",strategy:T.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,required:!0,help:"WeRead bookId (from `weread-official search`)"},{name:"no-chapters",type:"boolean",default:!1,help:"Skip /book/chapterinfo call"},{name:"no-progress",type:"boolean",default:!1,help:"Skip /book/getprogress call"}],columns:["section","idx","key","value","link"],func:async(Q)=>{const E=D(Q.bookId),V=[q("/book/info",{bookId:E})],M={chapters:!Q["no-chapters"],progress:!Q["no-progress"]};if(M.chapters)V.push(q("/book/chapterinfo",{bookId:E}));if(M.progress)V.push(q("/book/getprogress",{bookId:E}));const W=await Promise.all(V);let X=0;const x=W[X++],Y=M.chapters?W[X++]:null,B=M.progress?W[X++]:null,F=[],Z=[["bookId",String(x?.bookId??E)],["title",String(x?.title??"")],["author",String(x?.author??"")],["translator",String(x?.translator??"")],["category",String(x?.category??"")],["publisher",String(x?.publisher??"")],["publishTime",String(x?.publishTime??"")],["isbn",String(x?.isbn??"")],["wordCount",String(x?.wordCount??"")],["rating",v(x?.newRating)],["ratingCount",String(x?.newRatingCount??"")],["intro",P(x?.intro,400)],["cover",String(x?.cover??"")]];for(let z=0;z<Z.length;z+=1){const[A,J]=Z[z];F.push({section:"info",idx:z+1,key:A,value:J,link:""})}F.push({section:"info",idx:Z.length+1,key:"link",value:"",link:R({bookId:E})});if(Y)(Array.isArray(Y?.chapters)?Y.chapters:[]).forEach((A,J)=>{const K=String(A?.chapterUid??"").trim(),_=Number(A?.level??1),N=`${" ".repeat(Math.max(0,_-1))}${String(A?.title??"")}`,H=Number(A?.wordCount??0),$=Number(A?.paid??0)===1,O=Number(A?.price??0),j=[`${H}字`];if(O>0)j.push($?"已购买":`${O}元`);F.push({section:"chapter",idx:Number(A?.chapterIdx??J+1),key:K,value:`${N} (${j.join(" · ")})`,link:K?R({bookId:E,chapterUid:K}):""})});if(B){const z=B?.book??{},A=Number(z?.progress??0),J=L(z?.updateTime),K=A===100?L(z?.finishTime):"",_=U(z?.recordReadingTime),C=Number(z?.isStartReading??0)===1,N=[["progress",`${A}%`],["cumulative",_],["lastReadAt",J],["finishedAt",K],["isStartReading",C?"true":"false"],["currentChapterUid",String(z?.chapterUid??"")]];for(let H=0;H<N.length;H+=1){const[$,O]=N[H];F.push({section:"progress",idx:H+1,key:$,value:O,link:""})}}if(F.length===0)G("book",`No data returned for bookId=${E}`);return F}});
1
+ import{cli as C,Strategy as N}from"@jackwener/opencli/registry";import{callGateway as S,emptyResult as x,formatDate as I,formatDuration as T,formatRating as U,makeDeepLink as R,requireBookId as q,truncate as A}from"./utils.js";C({site:"weread-official",name:"book",access:"read",description:"Show WeRead book metadata, chapters, and reading progress",domain:"weread.qq.com",strategy:N.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,required:!0,help:"WeRead bookId (from `weread-official search`)"},{name:"no-chapters",type:"boolean",default:!1,help:"Skip /book/chapterinfo call"},{name:"no-progress",type:"boolean",default:!1,help:"Skip /book/getprogress call"}],columns:["section","idx","key","value","link"],func:async(u)=>{const r=q(u.bookId),d=[S("/book/info",{bookId:r})],c={chapters:!u["no-chapters"],progress:!u["no-progress"]};if(c.chapters)d.push(S("/book/chapterinfo",{bookId:r}));if(c.progress)d.push(S("/book/getprogress",{bookId:r}));const g=await Promise.all(d);let h=0;const e=g[h++],m=c.chapters?g[h++]:null,y=c.progress?g[h++]:null,i=[],f=[["bookId",String(e?.bookId??r)],["title",String(e?.title??"")],["author",String(e?.author??"")],["translator",String(e?.translator??"")],["category",String(e?.category??"")],["publisher",String(e?.publisher??"")],["publishTime",String(e?.publishTime??"")],["isbn",String(e?.isbn??"")],["wordCount",String(e?.wordCount??"")],["rating",U(e?.newRating)],["ratingCount",String(e?.newRatingCount??"")],["intro",A(e?.intro,400)],["cover",String(e?.cover??"")]];for(let t=0;t<f.length;t+=1){const[o,s]=f[t];i.push({section:"info",idx:t+1,key:o,value:s,link:""})}i.push({section:"info",idx:f.length+1,key:"link",value:"",link:R({bookId:r})});if(m)(Array.isArray(m?.chapters)?m.chapters:[]).forEach((o,s)=>{const a=String(o?.chapterUid??"").trim(),k=Number(o?.level??1),l=`${" ".repeat(Math.max(0,k-1))}${String(o?.title??"")}`,n=Number(o?.wordCount??0),b=Number(o?.paid??0)===1,p=Number(o?.price??0),v=[`${n}字`];if(p>0)v.push(b?"已购买":`${p}元`);i.push({section:"chapter",idx:Number(o?.chapterIdx??s+1),key:a,value:`${l} (${v.join(" · ")})`,link:a?R({bookId:r,chapterUid:a}):""})});if(y){const t=y?.book??{},o=Number(t?.progress??0),s=I(t?.updateTime),a=o===100?I(t?.finishTime):"",k=T(t?.recordReadingTime),w=Number(t?.isStartReading??0)===1,l=[["progress",`${o}%`],["cumulative",k],["lastReadAt",s],["finishedAt",a],["isStartReading",w?"true":"false"],["currentChapterUid",String(t?.chapterUid??"")]];for(let n=0;n<l.length;n+=1){const[b,p]=l[n];i.push({section:"progress",idx:n+1,key:b,value:p,link:""})}}if(i.length===0)x("book",`No data returned for bookId=${r}`);return i}});
@@ -1 +1 @@
1
- import{cli as Y,Strategy as Z}from"@jackwener/opencli/registry";import{callGateway as Q,emptyResult as T,formatRating as U,makeDeepLink as V,requireBookId as _,requirePositiveInt as $,truncate as W}from"./utils.js";Y({site:"weread-official",name:"discover",access:"read",description:"Personalized or similar-book recommendations from WeRead",domain:"weread.qq.com",strategy:Z.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,help:"Anchor bookId for similar-book mode; omit for personalized recommendations"},{name:"count",type:"int",default:12,help:"Page size (default 12)"},{name:"max-idx",type:"int",default:0,help:"Pagination cursor (recommend: previous searchIdx; similar: previous idx)"},{name:"session-id",help:"Carry-forward sessionId for /book/similar paging"}],columns:["rank","mode","bookId","title","author","rating","readingCount","category","idx","reason","cover","intro","link"],func:async(z)=>{const F=$(z.count,"count",{defaultValue:12,max:50}),C=Number(z["max-idx"]??0),E=z.bookId!==void 0&&z.bookId!==null&&String(z.bookId).trim()!==""?_(z.bookId):null;if(!E)return v({count:F,maxIdx:C});return P({bookId:E,count:F,maxIdx:C,sessionId:z["session-id"]})}});async function v({count:z,maxIdx:F}){const C=await Q("/book/recommend",{count:z,maxIdx:F}),E=Array.isArray(C?.books)?C.books:[];if(E.length===0)T("discover","No personalized recommendations available.");return E.map((h,J)=>{const H=String(h?.bookId??"").trim();return{rank:J+1,mode:"recommend",bookId:H,title:String(h?.title??""),author:String(h?.author??""),rating:U(h?.newRating),readingCount:Number(h?.readingCount??0),category:String(h?.category??""),idx:Number(h?.searchIdx??0),reason:String(h?.reason??""),cover:String(h?.cover??""),intro:W(h?.intro,200),link:H?V({bookId:H}):""}})}async function P({bookId:z,count:F,maxIdx:C,sessionId:E}){const h={bookId:z,count:F,maxIdx:C},J=String(E??"").trim();if(J)h.sessionId=J;const H=await Q("/book/similar",h),N=H?.booksimilar??H,O=Array.isArray(N?.books)?N.books:[];if(O.length===0)T("discover",`No similar books for bookId=${z}.`);return O.map((K,X)=>{const A=K?.book?.bookInfo??K?.bookInfo??{},M=String(A?.bookId??"").trim();return{rank:X+1,mode:"similar",bookId:M,title:String(A?.title??""),author:String(A?.author??""),rating:U(A?.newRating),readingCount:Number(A?.readingCount??0),category:String(A?.category??""),idx:Number(K?.idx??0),reason:"",cover:String(A?.cover??""),intro:W(A?.intro,200),link:M?V({bookId:M}):""}})}
1
+ import{cli as p,Strategy as S}from"@jackwener/opencli/registry";import{callGateway as u,emptyResult as k,formatRating as b,makeDeepLink as g,requireBookId as h,requirePositiveInt as x,truncate as f}from"./utils.js";p({site:"weread-official",name:"discover",access:"read",description:"Personalized or similar-book recommendations from WeRead",domain:"weread.qq.com",strategy:S.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,help:"Anchor bookId for similar-book mode; omit for personalized recommendations"},{name:"count",type:"int",default:12,help:"Page size (default 12)"},{name:"max-idx",type:"int",default:0,help:"Pagination cursor (recommend: previous searchIdx; similar: previous idx)"},{name:"session-id",help:"Carry-forward sessionId for /book/similar paging"}],columns:["rank","mode","bookId","title","author","rating","readingCount","category","idx","reason","cover","intro","link"],func:async(i)=>{const t=x(i.count,"count",{defaultValue:12,max:50}),n=Number(i["max-idx"]??0),e=i.bookId!==void 0&&i.bookId!==null&&String(i.bookId).trim()!==""?h(i.bookId):null;if(!e)return v({count:t,maxIdx:n});return y({bookId:e,count:t,maxIdx:n,sessionId:i["session-id"]})}});async function v({count:i,maxIdx:t}){const n=await u("/book/recommend",{count:i,maxIdx:t}),e=Array.isArray(n?.books)?n.books:[];if(e.length===0)k("discover","No personalized recommendations available.");return e.map((o,s)=>{const a=String(o?.bookId??"").trim();return{rank:s+1,mode:"recommend",bookId:a,title:String(o?.title??""),author:String(o?.author??""),rating:b(o?.newRating),readingCount:Number(o?.readingCount??0),category:String(o?.category??""),idx:Number(o?.searchIdx??0),reason:String(o?.reason??""),cover:String(o?.cover??""),intro:f(o?.intro,200),link:a?g({bookId:a}):""}})}async function y({bookId:i,count:t,maxIdx:n,sessionId:e}){const o={bookId:i,count:t,maxIdx:n},s=String(e??"").trim();if(s)o.sessionId=s;const a=await u("/book/similar",o),c=a?.booksimilar??a,l=Array.isArray(c?.books)?c.books:[];if(l.length===0)k("discover",`No similar books for bookId=${i}.`);return l.map((d,I)=>{const r=d?.book?.bookInfo??d?.bookInfo??{},m=String(r?.bookId??"").trim();return{rank:I+1,mode:"similar",bookId:m,title:String(r?.title??""),author:String(r?.author??""),rating:b(r?.newRating),readingCount:Number(r?.readingCount??0),category:String(r?.category??""),idx:Number(d?.idx??0),reason:"",cover:String(r?.cover??""),intro:f(r?.intro,200),link:m?g({bookId:m}):""}})}
@@ -1 +1 @@
1
- import{cli as Y,Strategy as Z}from"@jackwener/opencli/registry";import{callGateway as $,emptyResult as A,SKILL_VERSION as G}from"./utils.js";Y({site:"weread-official",name:"list-apis",access:"read",description:"List every api_name supported by the WeRead agent gateway",domain:"weread.qq.com",strategy:Z.PUBLIC,browser:!1,args:[],columns:["rank","apiName","description","required","optional","extras"],func:async()=>{const B=await $("/_list",{}),D=J(B);if(D.length===0)A("list-apis","Gateway returned no api inventory.");const F=D.map((C,H)=>{const M=Q(C?.required??C?.requiredParams??C?.params?.required),U=Q(C?.optional??C?.optionalParams??C?.params?.optional),W=String(C?.description??C?.help??C?.summary??""),X=T(C,["api_name","apiName","name","description","help","summary","required","optional","requiredParams","optionalParams","params"]);return{rank:H+1,apiName:String(C?.api_name??C?.apiName??C?.name??""),description:W,required:M,optional:U,extras:X}});F.push({rank:F.length+1,apiName:"(client)",description:"Local skill version reported with every gateway request",required:"",optional:"",extras:`SKILL_VERSION=${G}`});return F}});function J(B){if(!B||typeof B!=="object")return[];const D=[B?.apis,B?.list,B?.data,B?.items,B?.endpoints];for(const F of D)if(Array.isArray(F)&&F.length>0)return F;if(Array.isArray(B))return B;return[]}function Q(B){if(!B)return"";if(Array.isArray(B))return B.map((D)=>typeof D==="string"?D:D?.name??D?.param??"").filter(Boolean).join(", ");if(typeof B==="object")return Object.keys(B).filter(Boolean).join(", ");return String(B)}function T(B,D){if(!B||typeof B!=="object")return"";const F=new Set(D),C={};for(const[H,M]of Object.entries(B)){if(F.has(H))continue;C[H]=M}if(Object.keys(C).length===0)return"";try{return JSON.stringify(C)}catch{return""}}
1
+ import{cli as m,Strategy as u}from"@jackwener/opencli/registry";import{callGateway as f,emptyResult as l,SKILL_VERSION as d}from"./utils.js";m({site:"weread-official",name:"list-apis",access:"read",description:"List every api_name supported by the WeRead agent gateway",domain:"weread.qq.com",strategy:u.PUBLIC,browser:!1,args:[],columns:["rank","apiName","description","required","optional","extras"],func:async()=>{const r=await f("/_list",{}),i=g(r);if(i.length===0)l("list-apis","Gateway returned no api inventory.");const t=i.map((e,a)=>{const n=s(e?.required??e?.requiredParams??e?.params?.required),o=s(e?.optional??e?.optionalParams??e?.params?.optional),c=String(e?.description??e?.help??e?.summary??""),p=w(e,["api_name","apiName","name","description","help","summary","required","optional","requiredParams","optionalParams","params"]);return{rank:a+1,apiName:String(e?.api_name??e?.apiName??e?.name??""),description:c,required:n,optional:o,extras:p}});t.push({rank:t.length+1,apiName:"(client)",description:"Local skill version reported with every gateway request",required:"",optional:"",extras:`SKILL_VERSION=${d}`});return t}});function g(r){if(!r||typeof r!=="object")return[];const i=[r?.apis,r?.list,r?.data,r?.items,r?.endpoints];for(const t of i)if(Array.isArray(t)&&t.length>0)return t;if(Array.isArray(r))return r;return[]}function s(r){if(!r)return"";if(Array.isArray(r))return r.map((i)=>typeof i==="string"?i:i?.name??i?.param??"").filter(Boolean).join(", ");if(typeof r==="object")return Object.keys(r).filter(Boolean).join(", ");return String(r)}function w(r,i){if(!r||typeof r!=="object")return"";const t=new Set(i),e={};for(const[a,n]of Object.entries(r)){if(t.has(a))continue;e[a]=n}if(Object.keys(e).length===0)return"";try{return JSON.stringify(e)}catch{return""}}
@@ -1 +1 @@
1
- import{cli as q,Strategy as x}from"@jackwener/opencli/registry";import{callGateway as O,emptyResult as W,formatDate as j,makeDeepLink as V,parseRange as G,requireBookId as N,requirePositiveInt as E,truncate as K}from"./utils.js";q({site:"weread-official",name:"notes",access:"read",description:"List notebooks overview or merged highlights+thoughts for a book",domain:"weread.qq.com",strategy:x.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,help:"Limit to one book; omit for full notebook overview"},{name:"count",type:"int",default:20,help:"Page size for the notebooks overview (1-100)"},{name:"last-sort",type:"int",help:"Cursor: pass previous page sort value to fetch the next page (/user/notebooks)"}],columns:["kind","bookId","title","author","chapter","reviewCount","noteCount","bookmarkCount","totalNotes","progress","finished","sort","range","text","thought","star","createTime","link"],func:async(z)=>{const M=z.bookId!==void 0&&z.bookId!==null&&String(z.bookId).trim()!==""?N(z.bookId):null;if(!M)return P(z);return T(M)}});async function P(z){const X={count:E(z.count,"count",{defaultValue:20,max:100})};if(z["last-sort"]!==void 0&&z["last-sort"]!==null&&z["last-sort"]!=="")X.lastSort=E(z["last-sort"],"last-sort");const Q=await O("/user/notebooks",X),$=Array.isArray(Q?.books)?Q.books:[];if($.length===0)W("notes","No notebooks found.");return $.map((F)=>{const Y=F?.book??{},Z=String(F?.bookId??Y?.bookId??"").trim(),H=Number(F?.reviewCount??0),A=Number(F?.noteCount??0),J=Number(F?.bookmarkCount??0);return{kind:"notebook",bookId:Z,title:String(Y?.title??""),author:String(Y?.author??""),chapter:"",reviewCount:H,noteCount:A,bookmarkCount:J,totalNotes:H+A+J,progress:String(F?.readingProgress??""),finished:Number(F?.markedStatus??0)===1,sort:Number(F?.sort??0),range:"",text:"",thought:"",star:"",createTime:"",link:Z?V({bookId:Z}):""}})}async function T(z){const[M,X]=await Promise.all([O("/book/bookmarklist",{bookId:z}),O("/review/list/mine",{bookid:z})]),Q=new Map,$=Array.isArray(M?.chapters)?M.chapters:[];for(const H of $){const A=String(H?.chapterUid??"").trim();if(!A)continue;Q.set(A,String(H?.title??""))}const F=[],Y=Array.isArray(M?.updated)?M.updated:[];for(const H of Y){const A=String(H?.chapterUid??"").trim(),{rangeStart:J,rangeEnd:_}=G(H?.range);F.push({kind:"highlight",bookId:z,title:"",author:"",chapter:Q.get(A)??"",reviewCount:0,noteCount:0,bookmarkCount:0,totalNotes:0,progress:"",finished:!1,sort:0,range:String(H?.range??""),text:K(H?.markText,400),thought:"",star:"",createTime:j(H?.createTime),link:J&&_&&A?V({bookId:z,chapterUid:A,rangeStart:J,rangeEnd:_}):A?V({bookId:z,chapterUid:A}):V({bookId:z})})}const Z=Array.isArray(X?.reviews)?X.reviews:[];for(const H of Z){const A=H?.review??{},J=String(A?.chapterUid??"").trim(),_=Number(A?.star??-1);F.push({kind:"thought",bookId:z,title:"",author:"",chapter:String(A?.chapterName??"")||(Q.get(J)??""),reviewCount:0,noteCount:0,bookmarkCount:0,totalNotes:0,progress:"",finished:Number(A?.isFinish??0)===1,sort:0,range:String(A?.range??""),text:"",thought:K(A?.content,400),star:_>=0?String(_):"",createTime:j(A?.createTime),link:J?V({bookId:z,chapterUid:J}):V({bookId:z})})}if(F.length===0)W("notes",`No highlights or thoughts saved for bookId=${z}.`);return F}
1
+ import{cli as b,Strategy as w}from"@jackwener/opencli/registry";import{callGateway as k,emptyResult as p,formatDate as g,makeDeepLink as a,parseRange as v,requireBookId as C,requirePositiveInt as d,truncate as f}from"./utils.js";b({site:"weread-official",name:"notes",access:"read",description:"List notebooks overview or merged highlights+thoughts for a book",domain:"weread.qq.com",strategy:w.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,help:"Limit to one book; omit for full notebook overview"},{name:"count",type:"int",default:20,help:"Page size for the notebooks overview (1-100)"},{name:"last-sort",type:"int",help:"Cursor: pass previous page sort value to fetch the next page (/user/notebooks)"}],columns:["kind","bookId","title","author","chapter","reviewCount","noteCount","bookmarkCount","totalNotes","progress","finished","sort","range","text","thought","star","createTime","link"],func:async(t)=>{const s=t.bookId!==void 0&&t.bookId!==null&&String(t.bookId).trim()!==""?C(t.bookId):null;if(!s)return S(t);return N(s)}});async function S(t){const u={count:d(t.count,"count",{defaultValue:20,max:100})};if(t["last-sort"]!==void 0&&t["last-sort"]!==null&&t["last-sort"]!=="")u.lastSort=d(t["last-sort"],"last-sort");const i=await k("/user/notebooks",u),m=Array.isArray(i?.books)?i.books:[];if(m.length===0)p("notes","No notebooks found.");return m.map((e)=>{const c=e?.book??{},h=String(e?.bookId??c?.bookId??"").trim(),r=Number(e?.reviewCount??0),o=Number(e?.noteCount??0),n=Number(e?.bookmarkCount??0);return{kind:"notebook",bookId:h,title:String(c?.title??""),author:String(c?.author??""),chapter:"",reviewCount:r,noteCount:o,bookmarkCount:n,totalNotes:r+o+n,progress:String(e?.readingProgress??""),finished:Number(e?.markedStatus??0)===1,sort:Number(e?.sort??0),range:"",text:"",thought:"",star:"",createTime:"",link:h?a({bookId:h}):""}})}async function N(t){const[s,u]=await Promise.all([k("/book/bookmarklist",{bookId:t}),k("/review/list/mine",{bookid:t})]),i=new Map,m=Array.isArray(s?.chapters)?s.chapters:[];for(const r of m){const o=String(r?.chapterUid??"").trim();if(!o)continue;i.set(o,String(r?.title??""))}const e=[],c=Array.isArray(s?.updated)?s.updated:[];for(const r of c){const o=String(r?.chapterUid??"").trim(),{rangeStart:n,rangeEnd:l}=v(r?.range);e.push({kind:"highlight",bookId:t,title:"",author:"",chapter:i.get(o)??"",reviewCount:0,noteCount:0,bookmarkCount:0,totalNotes:0,progress:"",finished:!1,sort:0,range:String(r?.range??""),text:f(r?.markText,400),thought:"",star:"",createTime:g(r?.createTime),link:n&&l&&o?a({bookId:t,chapterUid:o,rangeStart:n,rangeEnd:l}):o?a({bookId:t,chapterUid:o}):a({bookId:t})})}const h=Array.isArray(u?.reviews)?u.reviews:[];for(const r of h){const o=r?.review??{},n=String(o?.chapterUid??"").trim(),l=Number(o?.star??-1);e.push({kind:"thought",bookId:t,title:"",author:"",chapter:String(o?.chapterName??"")||(i.get(n)??""),reviewCount:0,noteCount:0,bookmarkCount:0,totalNotes:0,progress:"",finished:Number(o?.isFinish??0)===1,sort:0,range:String(o?.range??""),text:"",thought:f(o?.content,400),star:l>=0?String(l):"",createTime:g(o?.createTime),link:n?a({bookId:t,chapterUid:n}):a({bookId:t})})}if(e.length===0)p("notes",`No highlights or thoughts saved for bookId=${t}.`);return e}
@@ -1 +1 @@
1
- import{cli as H,Strategy as M}from"@jackwener/opencli/registry";import{callGateway as _,emptyResult as S,formatDate as h,formatDuration as N,requireChoice as k,requirePositiveInt as v}from"./utils.js";const MODE_CHOICES=["weekly","monthly","annually","overall"];H({site:"weread-official",name:"readdata",access:"read",description:"Reading statistics: time, streak, preferences, top books",domain:"weread.qq.com",strategy:M.PUBLIC,browser:!1,args:[{name:"mode",default:"monthly",choices:MODE_CHOICES,help:"Stat window: weekly / monthly / annually / overall"},{name:"base-time",type:"int",help:"Optional Unix timestamp inside the target period; default is current period"}],columns:["section","idx","key","value","detail"],func:async(L)=>{const Q=k(L.mode,MODE_CHOICES,"mode","monthly"),U={mode:Q};if(L["base-time"]!==void 0&&L["base-time"]!==null&&L["base-time"]!=="")U.baseTime=v(L["base-time"],"base-time");const z=await _("/readdata/detail",U),F=[],V=Number(z?.totalReadTime??0),W=Number(z?.dayAverageReadTime??0),P=Number(z?.readDays??0),X=z?.compare,Y=Number.isFinite(Number(X))?Number(X):null,Z=[["mode",Q,""],["baseTime",h(z?.baseTime),String(z?.baseTime??"")],["readDays",String(P),""],["totalReadTime",N(V),`${V}s`],["dayAverageReadTime",N(W),`${W}s`],["compareToPrev",Y===null?"":`${(Y*100).toFixed(1)}%`,""],["readRate",z?.readRate!==void 0?`${Number(z.readRate).toFixed(1)}%`:"",""],["preferTimeWord",String(z?.preferTimeWord??""),""],["preferCategoryWord",String(z?.preferCategoryWord??""),""]];for(let x=0;x<Z.length;x+=1){const[B,J,K]=Z[x];F.push({section:"summary",idx:x+1,key:B,value:J,detail:K})}(Array.isArray(z?.readLongest)?z.readLongest:[]).forEach((x,B)=>{const J=x?.book??{},K=x?.albumInfo??null,j=K?String(K?.name??""):String(J?.title??""),q=K?String(K?.authorName??""):String(J?.author??""),G=Array.isArray(x?.tags)?x.tags.join(","):"",A=Number(x?.readTime??0);F.push({section:"longest",idx:B+1,key:j,value:N(A),detail:`${q}${G?` [${G}]`:""}`})});(Array.isArray(z?.readStat)?z.readStat:[]).forEach((x,B)=>{F.push({section:"readStat",idx:B+1,key:String(x?.stat??""),value:String(x?.counts??""),detail:""})});(Array.isArray(z?.preferCategory)?z.preferCategory:[]).forEach((x,B)=>{const J=Number(x?.readingTime??0);F.push({section:"preferCategory",idx:B+1,key:String(x?.categoryTitle??""),value:N(J),detail:`${Number(x?.readingCount??0)}本`})});(Array.isArray(z?.preferAuthor)?z.preferAuthor:[]).forEach((x,B)=>{F.push({section:"preferAuthor",idx:B+1,key:String(x?.name??""),value:String(x?.readTime??""),detail:`${Number(x?.count??0)}本`})});(Array.isArray(z?.preferPublisher)?z.preferPublisher:[]).forEach((x,B)=>{F.push({section:"preferPublisher",idx:B+1,key:String(x?.name??""),value:`${Number(x?.count??0)}本`,detail:""})});const $=Array.isArray(z?.preferTime)?z.preferTime:[];if($.length===24)for(let x=0;x<24;x+=1){const B=(6+x)%24,J=Number($[x]??0);F.push({section:"preferTime",idx:x+1,key:`${String(B).padStart(2,"0")}:00`,value:N(J),detail:`${J}s`})}if(F.length===0)S("readdata",`No reading data for mode=${Q}.`);return F}});export{MODE_CHOICES};
1
+ import{cli as T,Strategy as v}from"@jackwener/opencli/registry";import{callGateway as N,emptyResult as k,formatDate as x,formatDuration as n,requireChoice as C,requirePositiveInt as w}from"./utils.js";const MODE_CHOICES=["weekly","monthly","annually","overall"];T({site:"weread-official",name:"readdata",access:"read",description:"Reading statistics: time, streak, preferences, top books",domain:"weread.qq.com",strategy:v.PUBLIC,browser:!1,args:[{name:"mode",default:"monthly",choices:MODE_CHOICES,help:"Stat window: weekly / monthly / annually / overall"},{name:"base-time",type:"int",help:"Optional Unix timestamp inside the target period; default is current period"}],columns:["section","idx","key","value","detail"],func:async(s)=>{const d=C(s.mode,MODE_CHOICES,"mode","monthly"),m={mode:d};if(s["base-time"]!==void 0&&s["base-time"]!==null&&s["base-time"]!=="")m.baseTime=w(s["base-time"],"base-time");const r=await N("/readdata/detail",m),t=[],l=Number(r?.totalReadTime??0),u=Number(r?.dayAverageReadTime??0),h=Number(r?.readDays??0),c=r?.compare,p=Number.isFinite(Number(c))?Number(c):null,f=[["mode",d,""],["baseTime",x(r?.baseTime),String(r?.baseTime??"")],["readDays",String(h),""],["totalReadTime",n(l),`${l}s`],["dayAverageReadTime",n(u),`${u}s`],["compareToPrev",p===null?"":`${(p*100).toFixed(1)}%`,""],["readRate",r?.readRate!==void 0?`${Number(r.readRate).toFixed(1)}%`:"",""],["preferTimeWord",String(r?.preferTimeWord??""),""],["preferCategoryWord",String(r?.preferCategoryWord??""),""]];for(let e=0;e<f.length;e+=1){const[a,o,i]=f[e];t.push({section:"summary",idx:e+1,key:a,value:o,detail:i})}(Array.isArray(r?.readLongest)?r.readLongest:[]).forEach((e,a)=>{const o=e?.book??{},i=e?.albumInfo??null,b=i?String(i?.name??""):String(o?.title??""),S=i?String(i?.authorName??""):String(o?.author??""),g=Array.isArray(e?.tags)?e.tags.join(","):"",A=Number(e?.readTime??0);t.push({section:"longest",idx:a+1,key:b,value:n(A),detail:`${S}${g?` [${g}]`:""}`})});(Array.isArray(r?.readStat)?r.readStat:[]).forEach((e,a)=>{t.push({section:"readStat",idx:a+1,key:String(e?.stat??""),value:String(e?.counts??""),detail:""})});(Array.isArray(r?.preferCategory)?r.preferCategory:[]).forEach((e,a)=>{const o=Number(e?.readingTime??0);t.push({section:"preferCategory",idx:a+1,key:String(e?.categoryTitle??""),value:n(o),detail:`${Number(e?.readingCount??0)}本`})});(Array.isArray(r?.preferAuthor)?r.preferAuthor:[]).forEach((e,a)=>{t.push({section:"preferAuthor",idx:a+1,key:String(e?.name??""),value:String(e?.readTime??""),detail:`${Number(e?.count??0)}本`})});(Array.isArray(r?.preferPublisher)?r.preferPublisher:[]).forEach((e,a)=>{t.push({section:"preferPublisher",idx:a+1,key:String(e?.name??""),value:`${Number(e?.count??0)}本`,detail:""})});const y=Array.isArray(r?.preferTime)?r.preferTime:[];if(y.length===24)for(let e=0;e<24;e+=1){const a=(6+e)%24,o=Number(y[e]??0);t.push({section:"preferTime",idx:e+1,key:`${String(a).padStart(2,"0")}:00`,value:n(o),detail:`${o}s`})}if(t.length===0)k("readdata",`No reading data for mode=${d}.`);return t}});export{MODE_CHOICES};
@@ -1 +1 @@
1
- import{cli as G,Strategy as R}from"@jackwener/opencli/registry";import{ArgumentError as f}from"@jackwener/opencli/errors";import{callGateway as D,emptyResult as b,formatDate as h,formatStar as j,makeDeepLink as q,requireBookId as K,requirePositiveInt as U,truncate as O}from"./utils.js";const TYPE_ALIASES=Object.freeze({all:0,recommend:1,"thumbs-down":2,newest:3,neutral:4});G({site:"weread-official",name:"review",access:"read",description:"Browse public reviews of a WeRead book",domain:"weread.qq.com",strategy:R.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,required:!0,help:"WeRead bookId (from `weread-official search`)"},{name:"type",default:"all",choices:Object.keys(TYPE_ALIASES),help:"Review filter (all/recommend/thumbs-down/newest/neutral)"},{name:"count",type:"int",default:20,help:"Page size (1-100, default 20)"},{name:"max-idx",type:"int",default:0,help:"Pagination cursor — pass idx from last row of previous page"},{name:"synckey",type:"int",help:"Sync cursor returned by previous response"}],columns:["rank","idx","reviewId","star","starLabel","author","isFinish","chapter","content","createTime","link"],func:async(x)=>{const C=K(x.bookId),F=String(x.type??"all").trim();if(!Object.prototype.hasOwnProperty.call(TYPE_ALIASES,F))throw new f(`weread-official: type must be one of: ${Object.keys(TYPE_ALIASES).join(", ")}`);const V=TYPE_ALIASES[F],W=U(x.count,"count",{defaultValue:20,max:100}),H={bookId:C,reviewListType:V,count:W,maxIdx:Number(x["max-idx"]??0)};if(x.synckey!==void 0&&x.synckey!==null&&x.synckey!=="")H.synckey=U(x.synckey,"synckey");const J=await D("/review/list",H),M=Array.isArray(J?.reviews)?J.reviews:[];if(M.length===0)b("review",`No public reviews for bookId=${C} (type=${F}).`);return M.map((N,X)=>{const Q=N?.review??{},z=Q?.review??{},Z=z?.author??{},$=String(z?.chapterName??"").trim(),B=String(Q?.reviewId??z?.reviewId??"").trim();return{rank:X+1,idx:Number(N?.idx??0),reviewId:B,star:Number(z?.star??0),starLabel:j(z?.star),author:String(Z?.name??""),isFinish:Number(z?.isFinish??0)===1,chapter:$,content:O(z?.content,300),createTime:h(z?.createTime),link:q({bookId:C})}})}});export{TYPE_ALIASES};
1
+ import{cli as f,Strategy as b}from"@jackwener/opencli/registry";import{ArgumentError as h}from"@jackwener/opencli/errors";import{callGateway as k,emptyResult as v,formatDate as I,formatStar as x,makeDeepLink as S,requireBookId as L,requirePositiveInt as m,truncate as N}from"./utils.js";const TYPE_ALIASES=Object.freeze({all:0,recommend:1,"thumbs-down":2,newest:3,neutral:4});f({site:"weread-official",name:"review",access:"read",description:"Browse public reviews of a WeRead book",domain:"weread.qq.com",strategy:b.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,required:!0,help:"WeRead bookId (from `weread-official search`)"},{name:"type",default:"all",choices:Object.keys(TYPE_ALIASES),help:"Review filter (all/recommend/thumbs-down/newest/neutral)"},{name:"count",type:"int",default:20,help:"Page size (1-100, default 20)"},{name:"max-idx",type:"int",default:0,help:"Pagination cursor — pass idx from last row of previous page"},{name:"synckey",type:"int",help:"Sync cursor returned by previous response"}],columns:["rank","idx","reviewId","star","starLabel","author","isFinish","chapter","content","createTime","link"],func:async(e)=>{const r=L(e.bookId),i=String(e.type??"all").trim();if(!Object.prototype.hasOwnProperty.call(TYPE_ALIASES,i))throw new h(`weread-official: type must be one of: ${Object.keys(TYPE_ALIASES).join(", ")}`);const l=TYPE_ALIASES[i],u=m(e.count,"count",{defaultValue:20,max:100}),o={bookId:r,reviewListType:l,count:u,maxIdx:Number(e["max-idx"]??0)};if(e.synckey!==void 0&&e.synckey!==null&&e.synckey!=="")o.synckey=m(e.synckey,"synckey");const n=await k("/review/list",o),a=Array.isArray(n?.reviews)?n.reviews:[];if(a.length===0)v("review",`No public reviews for bookId=${r} (type=${i}).`);return a.map((s,d)=>{const c=s?.review??{},t=c?.review??{},y=t?.author??{},p=String(t?.chapterName??"").trim(),w=String(c?.reviewId??t?.reviewId??"").trim();return{rank:d+1,idx:Number(s?.idx??0),reviewId:w,star:Number(t?.star??0),starLabel:x(t?.star),author:String(y?.name??""),isFinish:Number(t?.isFinish??0)===1,chapter:p,content:N(t?.content,300),createTime:I(t?.createTime),link:S({bookId:r})}})}});export{TYPE_ALIASES};
@@ -1 +1 @@
1
- import{cli as T,Strategy as q}from"@jackwener/opencli/registry";import{ArgumentError as v}from"@jackwener/opencli/errors";import{callGateway as x,emptyResult as $,formatRating as j,makeDeepLink as h,requirePositiveInt as H,requireText as b,truncate as I}from"./utils.js";export const SEARCH_SCOPES=Object.freeze({all:0,ebook:10,webnovel:16,audio:14,author:6,fulltext:12,booklist:13,mp:2,article:4});const L=Object.freeze({0:"全部",10:"电子书",16:"网文小说",14:"微信听书",6:"作者",12:"全文",13:"书单",2:"公众号",4:"文章"});T({site:"weread-official",name:"search",access:"read",description:"Search WeRead store via the official agent gateway",domain:"weread.qq.com",strategy:q.PUBLIC,browser:!1,args:[{name:"keyword",positional:!0,required:!0,help:"Search keyword"},{name:"scope",default:"ebook",choices:Object.keys(SEARCH_SCOPES),help:"Search type (all/ebook/webnovel/audio/author/fulltext/booklist/mp/article)"},{name:"count",type:"int",help:"Page size (gateway default 15 when omitted)"},{name:"max-idx",type:"int",default:0,help:"Pagination offset, use searchIdx of last item from previous page"}],columns:["rank","scope","bookId","title","author","rating","readingCount","category","searchIdx","cover","intro","link"],func:async(z)=>{const N=b(z.keyword,"keyword"),J=String(z.scope??"ebook").trim();if(!Object.prototype.hasOwnProperty.call(SEARCH_SCOPES,J))throw new v(`weread-official: scope must be one of: ${Object.keys(SEARCH_SCOPES).join(", ")}`);const B=SEARCH_SCOPES[J],W={keyword:N,scope:B,maxIdx:z["max-idx"]??0};if(z.count!==void 0&&z.count!==null&&z.count!=="")W.count=H(z.count,"count",{max:100});const X=await x("/store/search",W),Y=Array.isArray(X?.results)?X.results:[];if(Y.length===0)$("search",`No results for "${N}" (scope=${J}).`);const Q=[];let Z=0;for(const U of Y){const D=L[Number(U?.scope)]??"",G=Array.isArray(U?.books)?U.books:[];for(const M of G){Z+=1;const F=M?.bookInfo??{},V=String(F.bookId??"").trim();Q.push({rank:Z,scope:D,bookId:V,title:String(F.title??""),author:String(F.author??""),rating:j(M?.newRating),readingCount:Number(M?.readingCount??0),category:String(F.category??""),searchIdx:Number(M?.searchIdx??0),cover:String(F.cover??""),intro:I(F.intro,120),link:V?h({bookId:V}):""})}}if(Q.length===0)$("search",`No books found in results for "${N}" (scope=${J}).`);return Q}});
1
+ import{cli as h,Strategy as k}from"@jackwener/opencli/registry";import{ArgumentError as b}from"@jackwener/opencli/errors";import{callGateway as g,emptyResult as f,formatRating as w,makeDeepLink as x,requirePositiveInt as S,requireText as I,truncate as v}from"./utils.js";export const SEARCH_SCOPES=Object.freeze({all:0,ebook:10,webnovel:16,audio:14,author:6,fulltext:12,booklist:13,mp:2,article:4});const O=Object.freeze({0:"全部",10:"电子书",16:"网文小说",14:"微信听书",6:"作者",12:"全文",13:"书单",2:"公众号",4:"文章"});h({site:"weread-official",name:"search",access:"read",description:"Search WeRead store via the official agent gateway",domain:"weread.qq.com",strategy:k.PUBLIC,browser:!1,args:[{name:"keyword",positional:!0,required:!0,help:"Search keyword"},{name:"scope",default:"ebook",choices:Object.keys(SEARCH_SCOPES),help:"Search type (all/ebook/webnovel/audio/author/fulltext/booklist/mp/article)"},{name:"count",type:"int",help:"Page size (gateway default 15 when omitted)"},{name:"max-idx",type:"int",default:0,help:"Pagination offset, use searchIdx of last item from previous page"}],columns:["rank","scope","bookId","title","author","rating","readingCount","category","searchIdx","cover","intro","link"],func:async(e)=>{const a=I(e.keyword,"keyword"),t=String(e.scope??"ebook").trim();if(!Object.prototype.hasOwnProperty.call(SEARCH_SCOPES,t))throw new b(`weread-official: scope must be one of: ${Object.keys(SEARCH_SCOPES).join(", ")}`);const d=SEARCH_SCOPES[t],s={keyword:a,scope:d,maxIdx:e["max-idx"]??0};if(e.count!==void 0&&e.count!==null&&e.count!=="")s.count=S(e.count,"count",{max:100});const u=await g("/store/search",s),l=Array.isArray(u?.results)?u.results:[];if(l.length===0)f("search",`No results for "${a}" (scope=${t}).`);const n=[];let p=0;for(const i of l){const m=O[Number(i?.scope)]??"",y=Array.isArray(i?.books)?i.books:[];for(const r of y){p+=1;const o=r?.bookInfo??{},c=String(o.bookId??"").trim();n.push({rank:p,scope:m,bookId:c,title:String(o.title??""),author:String(o.author??""),rating:w(r?.newRating),readingCount:Number(r?.readingCount??0),category:String(o.category??""),searchIdx:Number(r?.searchIdx??0),cover:String(o.cover??""),intro:v(o.intro,120),link:c?x({bookId:c}):""})}}if(n.length===0)f("search",`No books found in results for "${a}" (scope=${t}).`);return n}});
@@ -1 +1 @@
1
- import{cli as Q,Strategy as T}from"@jackwener/opencli/registry";import{callGateway as U,emptyResult as V,formatDate as F,makeDeepLink as W}from"./utils.js";Q({site:"weread-official",name:"shelf",access:"read",description:"Sync your WeRead shelf (books + albums + article bookmark entry) via the official gateway",domain:"weread.qq.com",strategy:T.PUBLIC,browser:!1,args:[],columns:["kind","id","title","author","category","secret","isTop","finished","updateTime","cover","link"],func:async()=>{const A=await U("/shelf/sync",{}),H=Array.isArray(A?.books)?A.books:[],J=Array.isArray(A?.albums)?A.albums:[],B=A?.mp,N=Boolean(B&&typeof B==="object"&&(Array.isArray(B)?B.length>0:Object.keys(B).length>0)),C=[];for(const q of H){const z=String(q?.bookId??"").trim();C.push({kind:"book",id:z,title:String(q?.title??""),author:String(q?.author??""),category:String(q?.category??""),secret:Number(q?.secret??0)===1,isTop:Number(q?.isTop??0)===1,finished:Number(q?.finishReading??0)===1,updateTime:F(q?.readUpdateTime??q?.updateTime),cover:String(q?.cover??""),link:z?W({bookId:z}):""})}for(const q of J){const z=q?.albumInfo??{},E=q?.albumInfoExtra??{},O=String(z?.albumId??"").trim();C.push({kind:"album",id:O,title:String(z?.name??""),author:String(z?.authorName??""),category:"",secret:Number(E?.secret??0)===1,isTop:Number(E?.isTop??0)===1,finished:Number(z?.finish??0)===1,updateTime:F(E?.lectureReadUpdateTime??z?.updateTime),cover:String(z?.cover??""),link:""})}if(N)C.push({kind:"mp",id:"",title:"文章收藏",author:"",category:"",secret:!0,isTop:!1,finished:!1,updateTime:"",cover:"",link:""});if(C.length===0)V("shelf","Your WeRead shelf is empty.");return C}});
1
+ import{cli as u,Strategy as d}from"@jackwener/opencli/registry";import{callGateway as f,emptyResult as p,formatDate as s,makeDeepLink as b}from"./utils.js";u({site:"weread-official",name:"shelf",access:"read",description:"Sync your WeRead shelf (books + albums + article bookmark entry) via the official gateway",domain:"weread.qq.com",strategy:d.PUBLIC,browser:!1,args:[],columns:["kind","id","title","author","category","secret","isTop","finished","updateTime","cover","link"],func:async()=>{const r=await f("/shelf/sync",{}),n=Array.isArray(r?.books)?r.books:[],c=Array.isArray(r?.albums)?r.albums:[],o=r?.mp,m=Boolean(o&&typeof o==="object"&&(Array.isArray(o)?o.length>0:Object.keys(o).length>0)),i=[];for(const e of n){const t=String(e?.bookId??"").trim();i.push({kind:"book",id:t,title:String(e?.title??""),author:String(e?.author??""),category:String(e?.category??""),secret:Number(e?.secret??0)===1,isTop:Number(e?.isTop??0)===1,finished:Number(e?.finishReading??0)===1,updateTime:s(e?.readUpdateTime??e?.updateTime),cover:String(e?.cover??""),link:t?b({bookId:t}):""})}for(const e of c){const t=e?.albumInfo??{},a=e?.albumInfoExtra??{},l=String(t?.albumId??"").trim();i.push({kind:"album",id:l,title:String(t?.name??""),author:String(t?.authorName??""),category:"",secret:Number(a?.secret??0)===1,isTop:Number(a?.isTop??0)===1,finished:Number(t?.finish??0)===1,updateTime:s(a?.lectureReadUpdateTime??t?.updateTime),cover:String(t?.cover??""),link:""})}if(m)i.push({kind:"mp",id:"",title:"文章收藏",author:"",category:"",secret:!0,isTop:!1,finished:!1,updateTime:"",cover:"",link:""});if(i.length===0)p("shelf","Your WeRead shelf is empty.");return i}});
@@ -1 +1 @@
1
- import{ArgumentError as B,AuthRequiredError as q,CommandExecutionError as K,EmptyResultError as W,TimeoutError as C}from"@jackwener/opencli/errors";export const WEREAD_GATEWAY_URL="https://i.weread.qq.com/api/agent/gateway",WEREAD_DOMAIN="weread.qq.com",SKILL_VERSION="1.0.3";const O=30000,U=new Set([-2010,-2012]);export function getApiKey(){const J=String(process.env.WEREAD_API_KEY??"").trim();if(!J)throw new q(WEREAD_DOMAIN,"WEREAD_API_KEY is not set. Export it with `export WEREAD_API_KEY=<wrk-...>`.");return J}export function buildGatewayBody(J,P={}){if(!J||typeof J!=="string")throw new B("weread-official: api_name is required");const z={api_name:J,skill_version:SKILL_VERSION};for(const[Z,Q]of Object.entries(P??{})){if(Q===void 0||Q===null||Q==="")continue;z[Z]=Q}return z}export async function callGateway(J,P={},{timeoutMs:z=O}={}){const Z=getApiKey(),Q=buildGatewayBody(J,P),$=new AbortController,Y=setTimeout(()=>$.abort(),z);let F;try{F=await fetch(WEREAD_GATEWAY_URL,{method:"POST",headers:{Authorization:`Bearer ${Z}`,"Content-Type":"application/json"},body:JSON.stringify(Q),signal:$.signal})}catch(X){if(X?.name==="AbortError")throw new C(`weread-official ${J}`,Math.round(z/1000));const G=X instanceof Error?X.message:String(X);throw new K(`weread-official ${J} request failed`,G)}finally{clearTimeout(Y)}if(!F.ok)throw new K(`weread-official ${J} HTTP ${F.status}`,"Check WeRead gateway availability and that WEREAD_API_KEY is still valid.");let j;try{j=await F.json()}catch(X){const G=X instanceof Error?X.message:String(X);throw new K(`weread-official ${J} returned invalid JSON`,G)}if(j&&typeof j==="object"&&j.upgrade_info){const X=j.upgrade_info,G=X?.required_version??X?.version??"unknown",w=X?.message??"WeRead skill version is outdated";throw new K(`WeRead skill 需升级: ${w}. Required skill_version=${G}, current=${SKILL_VERSION}`,"Pull the latest weread-skills.zip and bump SKILL_VERSION in clis/weread-official/utils.js.")}const H=Number(j?.errcode??0);if(H!==0){const X=String(j?.errmsg??"unknown error");if(U.has(H))throw new q(WEREAD_DOMAIN,`WEREAD_API_KEY rejected (errcode=${H}, ${X}). Regenerate the key and re-export it.`);throw new K(`weread-official ${J} returned errcode=${H}`,X)}return j}export function formatDate(J){const P=Number(J);if(!Number.isFinite(P)||P<=0)return"";const z=new Date(P*1000);if(Number.isNaN(z.getTime()))return"";const Z=z.getUTCFullYear(),Q=String(z.getUTCMonth()+1).padStart(2,"0"),$=String(z.getUTCDate()).padStart(2,"0");return`${Z}-${Q}-${$}`}export function formatDuration(J){if(J===null||J===void 0||J==="")return"";const P=Number(J);if(!Number.isFinite(P)||P<0)return"";const z=Math.floor(P),Z=Math.floor(z/3600),Q=Math.floor(z%3600/60);if(Z>0)return`${Z}小时${Q}分钟`;return`${Q}分钟`}export function formatStar(J){const P=Number(J);if(!Number.isFinite(P)||P<=0)return"无评分";const z=Math.min(5,Math.floor(P/20));if(z<=0)return"无评分";return"⭐".repeat(z)}export function formatRating(J){const P=Number(J);if(!Number.isFinite(P)||P<=0)return"暂无";const z=P/10;if(z>=90)return`神作 ${Math.round(z)}%`;if(z>=80)return`力荐 ${Math.round(z)}%`;if(z>=70)return`好评 ${Math.round(z)}%`;return`${z.toFixed(1)}分`}export function truncate(J,P=200){const z=String(J??"");if(!z)return"";if(z.length<=P)return z;return`${z.slice(0,P)}…`}export function makeDeepLink({bookId:J,chapterUid:P="",rangeStart:z="",rangeEnd:Z="",userVid:Q=""}={}){const $=String(J??"").trim();if(!$)return"";const Y=String(P??"").trim(),F=String(z??"").trim(),j=String(Z??"").trim();if(Y&&F&&j){const H=new URLSearchParams({bookId:$,chapterUid:Y,rangeStart:F,rangeEnd:j}),X=String(Q??"").trim();if(X)H.set("userVid",X);return`weread://bestbookmark?${H.toString()}`}if(Y)return`weread://reading?bId=${$}&chapterUid=${Y}`;return`weread://reading?bId=${$}`}export function parseRange(J){const z=String(J??"").trim().match(/^(\d+)-(\d+)$/);if(!z)return{rangeStart:"",rangeEnd:""};return{rangeStart:z[1],rangeEnd:z[2]}}export function requireText(J,P){const z=String(J??"").trim();if(!z)throw new B(`weread-official: ${P} cannot be empty`);return z}export function requireBookId(J,P="bookId"){const z=requireText(J,P);if(!/^[A-Za-z0-9_-]+$/.test(z))throw new B(`weread-official: ${P} contains invalid characters`,"Pass a bookId from `weread-official search`.");return z}export function requirePositiveInt(J,P,{defaultValue:z,max:Z}={}){if(J===void 0||J===null||J===""){if(z===void 0)throw new B(`weread-official: ${P} is required`);return z}const Q=String(J).trim();if(!/^\d+$/.test(Q))throw new B(`weread-official: ${P} must be a positive integer`);const $=Number(Q);if(!Number.isSafeInteger($)||$<1)throw new B(`weread-official: ${P} must be a positive integer`);if(Z!==void 0&&$>Z)throw new B(`weread-official: ${P} must be <= ${Z}`);return $}export function requireChoice(J,P,z,Z){const Q=String(J??Z??"").trim();if(!P.includes(Q))throw new B(`weread-official: ${z} must be one of: ${P.join(", ")}`);return Q}export function emptyResult(J,P){throw new W(`weread-official ${J}`,P)}
1
+ import{ArgumentError as c,AuthRequiredError as m,CommandExecutionError as l,EmptyResultError as h,TimeoutError as p}from"@jackwener/opencli/errors";export const WEREAD_GATEWAY_URL="https://i.weread.qq.com/api/agent/gateway",WEREAD_DOMAIN="weread.qq.com",SKILL_VERSION="1.0.3";const E=30000,S=new Set([-2010,-2012]);export function getApiKey(){const t=String(process.env.WEREAD_API_KEY??"").trim();if(!t)throw new m(WEREAD_DOMAIN,"WEREAD_API_KEY is not set. Export it with `export WEREAD_API_KEY=<wrk-...>`.");return t}export function buildGatewayBody(t,r={}){if(!t||typeof t!=="string")throw new c("weread-official: api_name is required");const e={api_name:t,skill_version:SKILL_VERSION};for(const[i,n]of Object.entries(r??{})){if(n===void 0||n===null||n==="")continue;e[i]=n}return e}export async function callGateway(t,r={},{timeoutMs:e=E}={}){const i=getApiKey(),n=buildGatewayBody(t,r),a=new AbortController,d=setTimeout(()=>a.abort(),e);let u;try{u=await fetch(WEREAD_GATEWAY_URL,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},body:JSON.stringify(n),signal:a.signal})}catch(o){if(o?.name==="AbortError")throw new p(`weread-official ${t}`,Math.round(e/1000));const w=o instanceof Error?o.message:String(o);throw new l(`weread-official ${t} request failed`,w)}finally{clearTimeout(d)}if(!u.ok)throw new l(`weread-official ${t} HTTP ${u.status}`,"Check WeRead gateway availability and that WEREAD_API_KEY is still valid.");let s;try{s=await u.json()}catch(o){const w=o instanceof Error?o.message:String(o);throw new l(`weread-official ${t} returned invalid JSON`,w)}if(s&&typeof s==="object"&&s.upgrade_info){const o=s.upgrade_info,w=o?.required_version??o?.version??"unknown",g=o?.message??"WeRead skill version is outdated";throw new l(`WeRead skill 需升级: ${g}. Required skill_version=${w}, current=${SKILL_VERSION}`,"Pull the latest weread-skills.zip and bump SKILL_VERSION in clis/weread-official/utils.js.")}const f=Number(s?.errcode??0);if(f!==0){const o=String(s?.errmsg??"unknown error");if(S.has(f))throw new m(WEREAD_DOMAIN,`WEREAD_API_KEY rejected (errcode=${f}, ${o}). Regenerate the key and re-export it.`);throw new l(`weread-official ${t} returned errcode=${f}`,o)}return s}export function formatDate(t){const r=Number(t);if(!Number.isFinite(r)||r<=0)return"";const e=new Date(r*1000);if(Number.isNaN(e.getTime()))return"";const i=e.getUTCFullYear(),n=String(e.getUTCMonth()+1).padStart(2,"0"),a=String(e.getUTCDate()).padStart(2,"0");return`${i}-${n}-${a}`}export function formatDuration(t){if(t===null||t===void 0||t==="")return"";const r=Number(t);if(!Number.isFinite(r)||r<0)return"";const e=Math.floor(r),i=Math.floor(e/3600),n=Math.floor(e%3600/60);if(i>0)return`${i}小时${n}分钟`;return`${n}分钟`}export function formatStar(t){const r=Number(t);if(!Number.isFinite(r)||r<=0)return"无评分";const e=Math.min(5,Math.floor(r/20));if(e<=0)return"无评分";return"⭐".repeat(e)}export function formatRating(t){const r=Number(t);if(!Number.isFinite(r)||r<=0)return"暂无";const e=r/10;if(e>=90)return`神作 ${Math.round(e)}%`;if(e>=80)return`力荐 ${Math.round(e)}%`;if(e>=70)return`好评 ${Math.round(e)}%`;return`${e.toFixed(1)}分`}export function truncate(t,r=200){const e=String(t??"");if(!e)return"";if(e.length<=r)return e;return`${e.slice(0,r)}…`}export function makeDeepLink({bookId:t,chapterUid:r="",rangeStart:e="",rangeEnd:i="",userVid:n=""}={}){const a=String(t??"").trim();if(!a)return"";const d=String(r??"").trim(),u=String(e??"").trim(),s=String(i??"").trim();if(d&&u&&s){const f=new URLSearchParams({bookId:a,chapterUid:d,rangeStart:u,rangeEnd:s}),o=String(n??"").trim();if(o)f.set("userVid",o);return`weread://bestbookmark?${f.toString()}`}if(d)return`weread://reading?bId=${a}&chapterUid=${d}`;return`weread://reading?bId=${a}`}export function parseRange(t){const e=String(t??"").trim().match(/^(\d+)-(\d+)$/);if(!e)return{rangeStart:"",rangeEnd:""};return{rangeStart:e[1],rangeEnd:e[2]}}export function requireText(t,r){const e=String(t??"").trim();if(!e)throw new c(`weread-official: ${r} cannot be empty`);return e}export function requireBookId(t,r="bookId"){const e=requireText(t,r);if(!/^[A-Za-z0-9_-]+$/.test(e))throw new c(`weread-official: ${r} contains invalid characters`,"Pass a bookId from `weread-official search`.");return e}export function requirePositiveInt(t,r,{defaultValue:e,max:i}={}){if(t===void 0||t===null||t===""){if(e===void 0)throw new c(`weread-official: ${r} is required`);return e}const n=String(t).trim();if(!/^\d+$/.test(n))throw new c(`weread-official: ${r} must be a positive integer`);const a=Number(n);if(!Number.isSafeInteger(a)||a<1)throw new c(`weread-official: ${r} must be a positive integer`);if(i!==void 0&&a>i)throw new c(`weread-official: ${r} must be <= ${i}`);return a}export function requireChoice(t,r,e,i){const n=String(t??i??"").trim();if(!r.includes(n))throw new c(`weread-official: ${e} must be one of: ${r.join(", ")}`);return n}export function emptyResult(t,r){throw new h(`weread-official ${t}`,r)}
@@ -1 +1 @@
1
- import{cli as d,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as y}from"@jackwener/opencli/errors";import{WIKIDATA_BASE as l,joinAliases as u,pickLocalised as o,requireEntityId as m,requireLanguage as g,wikidataFetch as k}from"./utils.js";d({site:"wikidata",name:"entity",access:"read",description:"Fetch a Wikidata entity by Q/P/L id (label, description, aliases, claim summary)",domain:"www.wikidata.org",strategy:p.PUBLIC,browser:!1,args:[{name:"id",positional:!0,required:!0,help:"Entity id (e.g. Q937 = Albert Einstein, P31 = instance of)"},{name:"language",default:"en",help:"Display language (ISO 639, falls back to English when missing)"}],columns:["qid","type","label","description","aliases","claimPropertyCount","sitelinkCount","enwikiTitle","modified","url"],func:async(a)=>{const e=m(a.id),t=g(a.language),r=`${l}/wiki/Special:EntityData/${encodeURIComponent(e)}.json`,i=(await k(r,"wikidata entity"))?.entities?.[e];if(!i)throw new y("wikidata entity",`Wikidata entity ${e} returned no payload.`);const c=i.claims&&typeof i.claims==="object"?i.claims:{},s=i.sitelinks&&typeof i.sitelinks==="object"?i.sitelinks:{},n=s?.enwiki?.title;return[{qid:e,type:typeof i.type==="string"?i.type:null,label:o(i.labels,t),description:o(i.descriptions,t),aliases:u(i.aliases,t),claimPropertyCount:Object.keys(c).length,sitelinkCount:Object.keys(s).length,enwikiTitle:typeof n==="string"&&n.trim()?n:null,modified:typeof i.modified==="string"?i.modified:null,url:`${l}/wiki/${e}`}]}});
1
+ import{cli as d,Strategy as y}from"@jackwener/opencli/registry";import{EmptyResultError as m}from"@jackwener/opencli/errors";import{WIKIDATA_BASE as l,joinAliases as p,pickLocalised as o,requireEntityId as u,requireLanguage as k,wikidataFetch as g}from"./utils.js";d({site:"wikidata",name:"entity",access:"read",description:"Fetch a Wikidata entity by Q/P/L id (label, description, aliases, claim summary)",domain:"www.wikidata.org",strategy:y.PUBLIC,browser:!1,args:[{name:"id",positional:!0,required:!0,help:"Entity id (e.g. Q937 = Albert Einstein, P31 = instance of)"},{name:"language",default:"en",help:"Display language (ISO 639, falls back to English when missing)"}],columns:["qid","type","label","description","aliases","claimPropertyCount","sitelinkCount","enwikiTitle","modified","url"],func:async(a)=>{const e=u(a.id),t=k(a.language),r=`${l}/wiki/Special:EntityData/${encodeURIComponent(e)}.json`,i=(await g(r,"wikidata entity"))?.entities?.[e];if(!i)throw new m("wikidata entity",`Wikidata entity ${e} returned no payload.`);const c=i.claims&&typeof i.claims==="object"?i.claims:{},s=i.sitelinks&&typeof i.sitelinks==="object"?i.sitelinks:{},n=s?.enwiki?.title;return[{qid:e,type:typeof i.type==="string"?i.type:null,label:o(i.labels,t),description:o(i.descriptions,t),aliases:p(i.aliases,t),claimPropertyCount:Object.keys(c).length,sitelinkCount:Object.keys(s).length,enwikiTitle:typeof n==="string"&&n.trim()?n:null,modified:typeof i.modified==="string"?i.modified:null,url:`${l}/wiki/${e}`}]}});
@@ -1 +1 @@
1
- import{cli as u,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as h}from"@jackwener/opencli/errors";import{WIKIDATA_BASE as l,requireBoundedInt as m,requireLanguage as y,requireString as g,wikidataFetch as w}from"./utils.js";u({site:"wikidata",name:"search",access:"read",description:"Search Wikidata items by keyword (returns Q-IDs)",domain:"www.wikidata.org",strategy:p.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:"Search keyword (label / alias)"},{name:"language",default:"en",help:"Search & display language (ISO 639, e.g. en, fr, zh)"},{name:"limit",type:"int",default:20,help:"Max items (1-50)"}],columns:["rank","qid","label","description","matchType","matchText","url"],func:async(t)=>{const r=g(t.query,"query"),a=y(t.language),n=m(t.limit,20,50),c=`${l}/w/api.php?action=wbsearchentities&search=${encodeURIComponent(r)}&language=${encodeURIComponent(a)}&uselang=${encodeURIComponent(a)}&type=item&format=json&limit=${n}&origin=*`,o=await w(c,"wikidata search"),s=Array.isArray(o?.search)?o.search:[];if(!s.length)throw new h("wikidata search",`No Wikidata items matched "${r}" in language "${a}".`);return s.slice(0,n).map((e,d)=>{const i=String(e?.id??"").trim();return{rank:d+1,qid:i,label:typeof e?.label==="string"?e.label:null,description:typeof e?.description==="string"?e.description:null,matchType:typeof e?.match?.type==="string"?e.match.type:null,matchText:typeof e?.match?.text==="string"?e.match.text:null,url:i?`${l}/wiki/${i}`:""}})}});
1
+ import{cli as p,Strategy as d}from"@jackwener/opencli/registry";import{EmptyResultError as m}from"@jackwener/opencli/errors";import{WIKIDATA_BASE as s,requireBoundedInt as h,requireLanguage as g,requireString as y,wikidataFetch as w}from"./utils.js";p({site:"wikidata",name:"search",access:"read",description:"Search Wikidata items by keyword (returns Q-IDs)",domain:"www.wikidata.org",strategy:d.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:"Search keyword (label / alias)"},{name:"language",default:"en",help:"Search & display language (ISO 639, e.g. en, fr, zh)"},{name:"limit",type:"int",default:20,help:"Max items (1-50)"}],columns:["rank","qid","label","description","matchType","matchText","url"],func:async(t)=>{const i=y(t.query,"query"),a=g(t.language),n=h(t.limit,20,50),c=`${s}/w/api.php?action=wbsearchentities&search=${encodeURIComponent(i)}&language=${encodeURIComponent(a)}&uselang=${encodeURIComponent(a)}&type=item&format=json&limit=${n}&origin=*`,o=await w(c,"wikidata search"),l=Array.isArray(o?.search)?o.search:[];if(!l.length)throw new m("wikidata search",`No Wikidata items matched "${i}" in language "${a}".`);return l.slice(0,n).map((e,u)=>{const r=String(e?.id??"").trim();return{rank:u+1,qid:r,label:typeof e?.label==="string"?e.label:null,description:typeof e?.description==="string"?e.description:null,matchType:typeof e?.match?.type==="string"?e.match.type:null,matchText:typeof e?.match?.text==="string"?e.match.text:null,url:r?`${s}/wiki/${r}`:""}})}});
@@ -1 +1 @@
1
- import{ArgumentError as K,CommandExecutionError as L,EmptyResultError as O}from"@jackwener/opencli/errors";export const WIKIDATA_BASE="https://www.wikidata.org";const Q="opencli-wikidata-adapter/1.0 (+https://github.com/jackwener/OpenCLI; mailto:ppcli@example.com)",S=/^[QPL]\d+$/;export function requireString(z,F){const B=String(z??"").trim();if(!B)throw new K(`wikidata ${F} cannot be empty`);return B}export function requireBoundedInt(z,F,B,H="limit"){const G=z??F,J=typeof G==="number"?G:Number(G);if(!Number.isInteger(J)||J<=0)throw new K(`wikidata ${H} must be a positive integer`);if(J>B)throw new K(`wikidata ${H} must be <= ${B}`);return J}export function requireEntityId(z){const F=String(z??"").trim().toUpperCase();if(!F)throw new K('wikidata entity id is required (e.g. "Q937")');const B=F.replace(/^HTTPS?:\/\/[^/]+\/WIKI\//i,"");if(!S.test(B))throw new K(`wikidata entity id "${z}" is not a valid Q/P/L identifier`,'Expected format: "Q<digits>" (item), "P<digits>" (property), or "L<digits>" (lexeme).');return B}export function requireLanguage(z,F="en"){const B=String(z??F).trim().toLowerCase();if(!/^[a-z]{2,3}(-[a-z]{2,8})?$/.test(B))throw new K(`wikidata language "${z}" is not a valid language code`,'Expected an ISO 639 language code such as "en", "fr", "zh", "zh-hans".');return B}export async function wikidataFetch(z,F){let B;try{B=await fetch(z,{headers:{"user-agent":Q,accept:"application/json"}})}catch(G){throw new L(`${F} request failed: ${G?.message??G}`,"Check that www.wikidata.org is reachable from this network.")}if(B.status===404)throw new O(F,`Wikidata returned 404 for ${z}.`);if(B.status===429)throw new L(`${F} returned HTTP 429 (rate limited)`,"Wikidata throttles anonymous traffic; back off and retry.");if(!B.ok)throw new L(`${F} returned HTTP ${B.status}`);let H;try{H=await B.json()}catch(G){throw new L(`${F} returned malformed JSON: ${G?.message??G}`)}return H}export function pickLocalised(z,F){if(!z||typeof z!=="object")return null;const B=z[F];if(B&&typeof B.value==="string"&&B.value.trim())return B.value;if(F!=="en"&&z.en&&typeof z.en.value==="string"&&z.en.value.trim())return z.en.value;return null}export function joinAliases(z,F,B=5){if(!z||typeof z!=="object")return"";let H=Array.isArray(z[F])?z[F]:[];if(H.length===0&&F!=="en"&&Array.isArray(z.en))H=z.en;const G=H.map((J)=>J&&typeof J.value==="string"?J.value:"").filter(Boolean);if(G.length===0)return"";if(G.length>B)return[...G.slice(0,B),`(+${G.length-B})`].join(", ");return G.join(", ")}
1
+ import{ArgumentError as a,CommandExecutionError as s,EmptyResultError as u}from"@jackwener/opencli/errors";export const WIKIDATA_BASE="https://www.wikidata.org";const c="opencli-wikidata-adapter/1.0 (+https://github.com/jackwener/OpenCLI; mailto:ppcli@example.com)",w=/^[QPL]\d+$/;export function requireString(t,r){const e=String(t??"").trim();if(!e)throw new a(`wikidata ${r} cannot be empty`);return e}export function requireBoundedInt(t,r,e,n="limit"){const i=t??r,o=typeof i==="number"?i:Number(i);if(!Number.isInteger(o)||o<=0)throw new a(`wikidata ${n} must be a positive integer`);if(o>e)throw new a(`wikidata ${n} must be <= ${e}`);return o}export function requireEntityId(t){const r=String(t??"").trim().toUpperCase();if(!r)throw new a('wikidata entity id is required (e.g. "Q937")');const e=r.replace(/^HTTPS?:\/\/[^/]+\/WIKI\//i,"");if(!w.test(e))throw new a(`wikidata entity id "${t}" is not a valid Q/P/L identifier`,'Expected format: "Q<digits>" (item), "P<digits>" (property), or "L<digits>" (lexeme).');return e}export function requireLanguage(t,r="en"){const e=String(t??r).trim().toLowerCase();if(!/^[a-z]{2,3}(-[a-z]{2,8})?$/.test(e))throw new a(`wikidata language "${t}" is not a valid language code`,'Expected an ISO 639 language code such as "en", "fr", "zh", "zh-hans".');return e}export async function wikidataFetch(t,r){let e;try{e=await fetch(t,{headers:{"user-agent":c,accept:"application/json"}})}catch(i){throw new s(`${r} request failed: ${i?.message??i}`,"Check that www.wikidata.org is reachable from this network.")}if(e.status===404)throw new u(r,`Wikidata returned 404 for ${t}.`);if(e.status===429)throw new s(`${r} returned HTTP 429 (rate limited)`,"Wikidata throttles anonymous traffic; back off and retry.");if(!e.ok)throw new s(`${r} returned HTTP ${e.status}`);let n;try{n=await e.json()}catch(i){throw new s(`${r} returned malformed JSON: ${i?.message??i}`)}return n}export function pickLocalised(t,r){if(!t||typeof t!=="object")return null;const e=t[r];if(e&&typeof e.value==="string"&&e.value.trim())return e.value;if(r!=="en"&&t.en&&typeof t.en.value==="string"&&t.en.value.trim())return t.en.value;return null}export function joinAliases(t,r,e=5){if(!t||typeof t!=="object")return"";let n=Array.isArray(t[r])?t[r]:[];if(n.length===0&&r!=="en"&&Array.isArray(t.en))n=t.en;const i=n.map((o)=>o&&typeof o.value==="string"?o.value:"").filter(Boolean);if(i.length===0)return"";if(i.length>e)return[...i.slice(0,e),`(+${i.length-e})`].join(", ");return i.join(", ")}
@@ -1,3 +1,3 @@
1
- import{cli as u,Strategy as w}from"@jackwener/opencli/registry";import{ArgumentError as c,CommandExecutionError as o,EmptyResultError as m}from"@jackwener/opencli/errors";u({site:"wikipedia",name:"page",access:"read",description:"Full plain-text extract of a Wikipedia article (optional paragraph cap).",domain:"wikipedia.org",strategy:w.PUBLIC,browser:!1,args:[{name:"title",positional:!0,required:!0,type:"string",help:'Article title (e.g. "Transformer (machine learning model)")'},{name:"lang",type:"string",default:"en",help:"Language code (en, zh, ja, de, ...)."},{name:"paragraphs",type:"int",default:0,help:"Cap to first N paragraphs (0 = full article)."}],columns:["title","description","pageId","paragraphs","extract","url"],func:async(i)=>{const l=String(i.title??"").trim();if(!l)throw new c("wikipedia page title cannot be empty");const s=String(i.lang??"en").trim().toLowerCase();if(!/^[a-z]{2,3}(?:-[a-z0-9]+)?$/.test(s))throw new c(`wikipedia lang must be a language code like en, zh, ja (got "${i.lang}")`);const n=Number(i.paragraphs??0);if(!Number.isInteger(n)||n<0)throw new c("paragraphs must be a non-negative integer (0 = full article)");const e=new URL(`https://${s}.wikipedia.org/w/api.php`);e.searchParams.set("action","query");e.searchParams.set("format","json");e.searchParams.set("formatversion","2");e.searchParams.set("prop","extracts|info|description");e.searchParams.set("inprop","url");e.searchParams.set("explaintext","1");e.searchParams.set("redirects","1");e.searchParams.set("titles",l);let p;try{p=await fetch(e,{headers:{"User-Agent":"ppcli/1.0 (+https://github.com/jackwener/OpenCLI)",Accept:"application/json"}})}catch(t){throw new o(`wikipedia page request failed: ${t?.message||t}`)}if(!p.ok)throw new o(`wikipedia page failed: HTTP ${p.status}`);let r;try{r=await p.json()}catch(t){throw new o(`wikipedia returned malformed JSON: ${t?.message||t}`)}if(r?.error)throw new o(`wikipedia API error: ${r.error.info||r.error.code}`);const a=(Array.isArray(r?.query?.pages)?r.query.pages:[])[0];if(!a||a.missing)throw new m("wikipedia page",`No article "${l}" on ${s}.wikipedia.org. Try \`ppcli wikipedia search\` first.`);const g=String(a.extract??"");if(!g.trim())throw new m("wikipedia page",`Article "${a.title}" exists but has no plain-text extract (likely a disambiguation/redirect page).`);const h=g.split(/\n{2,}/).map((t)=>t.trim()).filter(Boolean),d=n>0?h.slice(0,n):h;return[{title:a.title,description:a.description||"",pageId:a.pageid??null,paragraphs:d.length,extract:d.join(`
1
+ import{cli as w,Strategy as u}from"@jackwener/opencli/registry";import{ArgumentError as c,CommandExecutionError as o,EmptyResultError as h}from"@jackwener/opencli/errors";w({site:"wikipedia",name:"page",access:"read",description:"Full plain-text extract of a Wikipedia article (optional paragraph cap).",domain:"wikipedia.org",strategy:u.PUBLIC,browser:!1,args:[{name:"title",positional:!0,required:!0,type:"string",help:'Article title (e.g. "Transformer (machine learning model)")'},{name:"lang",type:"string",default:"en",help:"Language code (en, zh, ja, de, ...)."},{name:"paragraphs",type:"int",default:0,help:"Cap to first N paragraphs (0 = full article)."}],columns:["title","description","pageId","paragraphs","extract","url"],func:async(i)=>{const l=String(i.title??"").trim();if(!l)throw new c("wikipedia page title cannot be empty");const s=String(i.lang??"en").trim().toLowerCase();if(!/^[a-z]{2,3}(?:-[a-z0-9]+)?$/.test(s))throw new c(`wikipedia lang must be a language code like en, zh, ja (got "${i.lang}")`);const n=Number(i.paragraphs??0);if(!Number.isInteger(n)||n<0)throw new c("paragraphs must be a non-negative integer (0 = full article)");const e=new URL(`https://${s}.wikipedia.org/w/api.php`);e.searchParams.set("action","query");e.searchParams.set("format","json");e.searchParams.set("formatversion","2");e.searchParams.set("prop","extracts|info|description");e.searchParams.set("inprop","url");e.searchParams.set("explaintext","1");e.searchParams.set("redirects","1");e.searchParams.set("titles",l);let p;try{p=await fetch(e,{headers:{"User-Agent":"ppcli/1.0 (+https://github.com/jackwener/OpenCLI)",Accept:"application/json"}})}catch(r){throw new o(`wikipedia page request failed: ${r?.message||r}`)}if(!p.ok)throw new o(`wikipedia page failed: HTTP ${p.status}`);let t;try{t=await p.json()}catch(r){throw new o(`wikipedia returned malformed JSON: ${r?.message||r}`)}if(t?.error)throw new o(`wikipedia API error: ${t.error.info||t.error.code}`);const a=(Array.isArray(t?.query?.pages)?t.query.pages:[])[0];if(!a||a.missing)throw new h("wikipedia page",`No article "${l}" on ${s}.wikipedia.org. Try \`ppcli wikipedia search\` first.`);const g=String(a.extract??"");if(!g.trim())throw new h("wikipedia page",`Article "${a.title}" exists but has no plain-text extract (likely a disambiguation/redirect page).`);const m=g.split(/\n{2,}/).map((r)=>r.trim()).filter(Boolean),d=n>0?m.slice(0,n):m;return[{title:a.title,description:a.description||"",pageId:a.pageid??null,paragraphs:d.length,extract:d.join(`
2
2
 
3
3
  `),url:a.fullurl||`https://${s}.wikipedia.org/wiki/${encodeURIComponent(a.title.replace(/ /g,"_"))}`}]}});
@@ -1 +1 @@
1
- import{CliError as G}from"@jackwener/opencli/errors";import{cli as Q,Strategy as R}from"@jackwener/opencli/registry";import{DESC_MAX_LEN as T,wikiFetch as U}from"./utils.js";Q({site:"wikipedia",name:"trending",access:"read",description:"Most-read Wikipedia articles (yesterday)",strategy:R.PUBLIC,browser:!1,args:[{name:"limit",type:"int",default:10,help:"Max results"},{name:"lang",default:"en",help:"Language code (e.g. en, zh, ja)"}],columns:["rank","title","description","views"],func:async(x)=>{const H=x.lang||"en",I=Math.max(1,Math.min(Number(x.limit),50)),q=new Date(Date.now()-86400000),J=q.getUTCFullYear(),K=String(q.getUTCMonth()+1).padStart(2,"0"),O=String(q.getUTCDate()).padStart(2,"0"),z=(await U(H,`/api/rest_v1/feed/featured/${J}/${K}/${O}`))?.mostread?.articles;if(!z?.length)throw new G("NOT_FOUND","No trending articles available","Try a different language with --lang");const B=z.slice(0,I);if(B.some((f)=>!String(f?.title||"").trim()))throw new G("PARSE_ERROR","Wikipedia trending returned an article without title","Trending rows require a title so they can be opened with wikipedia page.");return B.map((f,P)=>({rank:P+1,title:f.title,description:(f.description??"").slice(0,T),views:f.views??0}))}});
1
+ import{CliError as r}from"@jackwener/opencli/errors";import{cli as m,Strategy as p}from"@jackwener/opencli/registry";import{DESC_MAX_LEN as w,wikiFetch as h}from"./utils.js";m({site:"wikipedia",name:"trending",access:"read",description:"Most-read Wikipedia articles (yesterday)",strategy:p.PUBLIC,browser:!1,args:[{name:"limit",type:"int",default:10,help:"Max results"},{name:"lang",default:"en",help:"Language code (e.g. en, zh, ja)"}],columns:["rank","title","description","views"],func:async(i)=>{const s=i.lang||"en",l=Math.max(1,Math.min(Number(i.limit),50)),t=new Date(Date.now()-86400000),o=t.getUTCFullYear(),d=String(t.getUTCMonth()+1).padStart(2,"0"),c=String(t.getUTCDate()).padStart(2,"0"),a=(await h(s,`/api/rest_v1/feed/featured/${o}/${d}/${c}`))?.mostread?.articles;if(!a?.length)throw new r("NOT_FOUND","No trending articles available","Try a different language with --lang");const n=a.slice(0,l);if(n.some((e)=>!String(e?.title||"").trim()))throw new r("PARSE_ERROR","Wikipedia trending returned an article without title","Trending rows require a title so they can be opened with wikipedia page.");return n.map((e,g)=>({rank:g+1,title:e.title,description:(e.description??"").slice(0,w),views:e.views??0}))}});
@@ -1 +1 @@
1
- import{CliError as x}from"@jackwener/opencli/errors";export const EXTRACT_MAX_LEN=300,DESC_MAX_LEN=80;export async function wikiFetch(b,f){const v=`https://${b}.wikipedia.org${f}`,q=await fetch(v,{headers:{"User-Agent":"ppcli/1.0 (https://github.com/jackwener/OpenCLI)"}});if(!q.ok)throw new x("FETCH_ERROR",`Wikipedia API HTTP ${q.status}`,"Check your title or search term");return q.json()}export function formatSummaryRow(b,f){return{title:b.title,description:b.description??"-",extract:(b.extract??"").slice(0,EXTRACT_MAX_LEN),url:b.content_urls?.desktop?.page??`https://${f}.wikipedia.org`}}
1
+ import{CliError as o}from"@jackwener/opencli/errors";export const EXTRACT_MAX_LEN=300,DESC_MAX_LEN=80;export async function wikiFetch(t,e){const i=`https://${t}.wikipedia.org${e}`,r=await fetch(i,{headers:{"User-Agent":"ppcli/1.0 (https://github.com/jackwener/OpenCLI)"}});if(!r.ok)throw new o("FETCH_ERROR",`Wikipedia API HTTP ${r.status}`,"Check your title or search term");return r.json()}export function formatSummaryRow(t,e){return{title:t.title,description:t.description??"-",extract:(t.extract??"").slice(0,EXTRACT_MAX_LEN),url:t.content_urls?.desktop?.page??`https://${e}.wikipedia.org`}}
@@ -1 +1 @@
1
- import{cli as Y,Strategy as Z}from"@jackwener/opencli/registry";import{TimeoutError as $}from"@jackwener/opencli/errors";import{resolveBaseUrl as h,readCookieLogin as x,gotoWpAdmin as v,WP_ADMIN as B,WP_LOGIN as G}from"./shared.js";const Q=300,R=3000;async function z(f){if(typeof f?.closeWindow==="function")try{await f.closeWindow()}catch{}}Y({site:"wordpress",name:"login",access:"write",description:"打开自建 WordPress 站点的登录页并等待浏览器会话完成登录(加站模式:站点网址取自连接里的 WORDPRESS_BASE_URL,或用 --base-url)。",domain:"wordpress.org",strategy:Z.COOKIE,browser:!0,navigateBefore:!1,defaultWindowMode:"foreground",siteSession:"persistent",args:[{name:"site",help:"连接名称或站点网址;省略时使用默认站点"},{name:"base-url",help:"站点根网址(默认读连接里的 WORDPRESS_BASE_URL)"},{name:"timeout",type:"int",default:Q,help:"等待用户完成登录的最长秒数"}],columns:["status","logged_in","site"],func:async(f,H)=>{const q=h(H);if(await x(f,q)){await z(f);return[{status:"already_logged_in",logged_in:!0,site:q}]}if(!(await v(f,q,B)).onLogin&&await x(f,q)){await z(f);return[{status:"already_logged_in",logged_in:!0,site:q}]}await f.goto(q+G);const J=Number(H.timeout??Q),K=Date.now()+J*1000;while(Date.now()<K){const X=K-Date.now();await f.wait({time:Math.min(R/1000,Math.max(0.2,X/1000))});if(await x(f,q)){await z(f);return[{status:"login_complete",logged_in:!0,site:q}]}}throw new $("wordpress login",J,`请在打开的窗口里完成 ${q} 的登录后重试。`)}});
1
+ import{cli as d,Strategy as w}from"@jackwener/opencli/registry";import{TimeoutError as u}from"@jackwener/opencli/errors";import{resolveBaseUrl as c,readCookieLogin as o,gotoWpAdmin as m,WP_ADMIN as _,WP_LOGIN as f}from"./shared.js";const a=300,g=3000;async function i(t){if(typeof t?.closeWindow==="function")try{await t.closeWindow()}catch{}}d({site:"wordpress",name:"login",access:"write",description:"打开自建 WordPress 站点的登录页并等待浏览器会话完成登录(加站模式:站点网址取自连接里的 WORDPRESS_BASE_URL,或用 --base-url)。",domain:"wordpress.org",strategy:w.COOKIE,browser:!0,navigateBefore:!1,defaultWindowMode:"foreground",siteSession:"persistent",args:[{name:"site",help:"连接名称或站点网址;省略时使用默认站点"},{name:"base-url",help:"站点根网址(默认读连接里的 WORDPRESS_BASE_URL)"},{name:"timeout",type:"int",default:a,help:"等待用户完成登录的最长秒数"}],columns:["status","logged_in","site"],func:async(t,n)=>{const e=c(n);if(await o(t,e)){await i(t);return[{status:"already_logged_in",logged_in:!0,site:e}]}if(!(await m(t,e,_)).onLogin&&await o(t,e)){await i(t);return[{status:"already_logged_in",logged_in:!0,site:e}]}await t.goto(e+f);const s=Number(n.timeout??a),r=Date.now()+s*1000;while(Date.now()<r){const l=r-Date.now();await t.wait({time:Math.min(g/1000,Math.max(0.2,l/1000))});if(await o(t,e)){await i(t);return[{status:"login_complete",logged_in:!0,site:e}]}}throw new u("wordpress login",s,`请在打开的窗口里完成 ${e} 的登录后重试。`)}});