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 +1 @@
1
- import{cli as j,Strategy as U}from"@jackwener/opencli/registry";import{CommandExecutionError as z,EmptyResultError as A}from"@jackwener/opencli/errors";import{requirePage as G,navigateToChat as Y,navigateToGeekChat as D,bossFetch as S,findFriendByUid as N,findGeekFriendByUid as _,fetchGeekHistoryMsg as v,readEncryptSystemId as B,assertOk as T,IDENTITY_MISMATCH_CODE as I,readPositiveInteger as R,readRequiredString as F}from"./utils.js";const x={1:"文本",2:"图片",3:"招呼",4:"简历",5:"系统",6:"名片",7:"语音",8:"视频",9:"表情"};function M(J,L){const Q=J.from||{};return{from:(typeof Q==="object"?Q.uid!==L.uid:!1)?"我":typeof Q==="object"?Q.name:L.name,type:x[J.type]||`其他(${J.type})`,text:J.text||J.body?.text||"",time:J.time?new Date(J.time).toLocaleString("zh-CN"):""}}function O(J,L){const Q=J.from&&J.from.uid;return{from:Q!=null&&String(Q)===String(L.uid)?"对方":"我",type:x[J.type]||`其他(${J.type})`,text:J.text||J.body?.text||J.body?.content||J.body?.showText||JSON.stringify(J.body||{}).slice(0,120),time:J.time?new Date(J.time).toLocaleString("zh-CN"):""}}async function P(J,L,Q){const V=Q??await N(J,L.uid);if(!V)throw new A("boss chatmsg","未找到该候选人");if(!V.securityId)throw new z("该聊天缺少 securityId,无法获取历史消息");const Z=V.uid,$=encodeURIComponent(V.securityId),W=`https://www.zhipin.com/wapi/zpchat/boss/historyMsg?gid=${Z}&securityId=${$}&page=${L.page}&c=20&src=0`,q=await S(J,W),X=q.zpData?.messages??q.zpData?.historyMsgList;if(!Array.isArray(X))throw new z("Boss recruiter history response did not include a message list");if(X.length===0)throw new A("boss chatmsg","Boss returned no messages for this chat.");return X.map((K)=>M(K,V))}async function h(J,L,Q){const V=await _(J,L.uid,{encryptSystemId:Q});if(!V)throw new A("boss chatmsg","未找到该聊天(geek 侧)");if(!V.securityId)throw new z("该聊天缺少 securityId,无法获取历史消息");return(await v(J,V,{page:L.page})).map(($)=>O($,V))}j({site:"boss",name:"chatmsg",access:"read",description:"BOSS直聘查看聊天消息历史(招聘端/求职端)",domain:"www.zhipin.com",strategy:U.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",required:!0,positional:!0,help:"Encrypted UID (from chatlist)"},{name:"page",type:"int",default:1,help:"Page number"},{name:"side",default:"auto",choices:["auto","boss","geek"],help:"Identity side: auto (default), boss (recruiter), or geek (job-seeker)"}],columns:["from","type","text","time"],func:async(J,L)=>{G(J);const Q=F(L.uid,"chatmsg uid"),V=R(L.page,"chatmsg --page",1),Z={...L,uid:Q,page:V},$=L.side||"auto";if($==="boss"){await Y(J);return await P(J,Z)}if($==="geek"){await D(J);const H=await B(J);return await h(J,Z,H)}await Y(J);const W=await N(J,Q,{allowNonZero:!0});if(W?.friend)return await P(J,Z,W.friend);if(W?.code&&W.code!==0&&W.code!==I)T(W);await D(J);const q=await B(J),X=await _(J,Q,{encryptSystemId:q});if(!X)throw new A("boss chatmsg","uid 在招聘端与求职端聊天列表中均未找到");if(!X.securityId)throw new z("该聊天缺少 securityId,无法获取历史消息");return(await v(J,X,{page:V})).map((H)=>O(H,X))}});
1
+ import{cli as C,Strategy as E}from"@jackwener/opencli/registry";import{CommandExecutionError as d,EmptyResultError as u}from"@jackwener/opencli/errors";import{requirePage as M,navigateToChat as y,navigateToGeekChat as g,bossFetch as x,findFriendByUid as w,findGeekFriendByUid as h,fetchGeekHistoryMsg as p,readEncryptSystemId as l,assertOk as B,IDENTITY_MISMATCH_CODE as z,readPositiveInteger as D,readRequiredString as k}from"./utils.js";const b={1:"文本",2:"图片",3:"招呼",4:"简历",5:"系统",6:"名片",7:"语音",8:"视频",9:"表情"};function O(t,e){const s=t.from||{};return{from:(typeof s==="object"?s.uid!==e.uid:!1)?"我":typeof s==="object"?s.name:e.name,type:b[t.type]||`其他(${t.type})`,text:t.text||t.body?.text||"",time:t.time?new Date(t.time).toLocaleString("zh-CN"):""}}function I(t,e){const s=t.from&&t.from.uid;return{from:s!=null&&String(s)===String(e.uid)?"对方":"我",type:b[t.type]||`其他(${t.type})`,text:t.text||t.body?.text||t.body?.content||t.body?.showText||JSON.stringify(t.body||{}).slice(0,120),time:t.time?new Date(t.time).toLocaleString("zh-CN"):""}}async function S(t,e,s){const i=s??await w(t,e.uid);if(!i)throw new u("boss chatmsg","未找到该候选人");if(!i.securityId)throw new d("该聊天缺少 securityId,无法获取历史消息");const a=i.uid,n=encodeURIComponent(i.securityId),o=`https://www.zhipin.com/wapi/zpchat/boss/historyMsg?gid=${a}&securityId=${n}&page=${e.page}&c=20&src=0`,c=await x(t,o),r=c.zpData?.messages??c.zpData?.historyMsgList;if(!Array.isArray(r))throw new d("Boss recruiter history response did not include a message list");if(r.length===0)throw new u("boss chatmsg","Boss returned no messages for this chat.");return r.map((f)=>O(f,i))}async function T(t,e,s){const i=await h(t,e.uid,{encryptSystemId:s});if(!i)throw new u("boss chatmsg","未找到该聊天(geek 侧)");if(!i.securityId)throw new d("该聊天缺少 securityId,无法获取历史消息");return(await p(t,i,{page:e.page})).map((n)=>I(n,i))}C({site:"boss",name:"chatmsg",access:"read",description:"BOSS直聘查看聊天消息历史(招聘端/求职端)",domain:"www.zhipin.com",strategy:E.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",required:!0,positional:!0,help:"Encrypted UID (from chatlist)"},{name:"page",type:"int",default:1,help:"Page number"},{name:"side",default:"auto",choices:["auto","boss","geek"],help:"Identity side: auto (default), boss (recruiter), or geek (job-seeker)"}],columns:["from","type","text","time"],func:async(t,e)=>{M(t);const s=k(e.uid,"chatmsg uid"),i=D(e.page,"chatmsg --page",1),a={...e,uid:s,page:i},n=e.side||"auto";if(n==="boss"){await y(t);return await S(t,a)}if(n==="geek"){await g(t);const m=await l(t);return await T(t,a,m)}await y(t);const o=await w(t,s,{allowNonZero:!0});if(o?.friend)return await S(t,a,o.friend);if(o?.code&&o.code!==0&&o.code!==z)B(o);await g(t);const c=await l(t),r=await h(t,s,{encryptSystemId:c});if(!r)throw new u("boss chatmsg","uid 在招聘端与求职端聊天列表中均未找到");if(!r.securityId)throw new d("该聊天缺少 securityId,无法获取历史消息");return(await p(t,r,{page:i})).map((m)=>I(m,r))}});
@@ -1 +1 @@
1
- import{cli as c,Strategy as i}from"@jackwener/opencli/registry";import{CITY_CODES as t}from"./utils.js";c({site:"boss",name:"cities",access:"read",description:"BOSS直聘列出支持的城市与城市代码",domain:"www.zhipin.com",strategy:i.COOKIE,navigateBefore:!1,browser:!1,args:[],columns:["city","code"],func:async()=>Object.entries(t).map(([e,s])=>({city:e,code:s}))});
1
+ import{cli as i,Strategy as a}from"@jackwener/opencli/registry";import{CITY_CODES as r}from"./utils.js";i({site:"boss",name:"cities",access:"read",description:"BOSS直聘列出支持的城市与城市代码",domain:"www.zhipin.com",strategy:a.COOKIE,navigateBefore:!1,browser:!1,args:[],columns:["city","code"],func:async()=>Object.entries(r).map(([e,s])=>({city:e,code:s}))});
@@ -1 +1 @@
1
- import{cli as M,Strategy as O}from"@jackwener/opencli/registry";import{requirePage as Q,navigateTo as R,bossFetch as V,verbose as W}from"./utils.js";M({site:"boss",name:"detail",access:"read",description:"BOSS直聘查看职位详情",domain:"www.zhipin.com",strategy:O.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"security-id",positional:!0,required:!0,help:"Security ID from search results (securityId field)"}],columns:["name","salary","experience","degree","city","district","description","skills","welfare","boss_name","boss_title","active_time","company","industry","scale","stage","address","url"],func:async(G,J)=>{Q(G);const K=J["security-id"];W("Fetching job detail...");await R(G,"https://www.zhipin.com/web/geek/job");const L=`https://www.zhipin.com/wapi/zpgeek/job/detail.json?securityId=${encodeURIComponent(K)}`,H=(await V(G,L)).zpData||{},A=H.jobInfo||{},E=H.bossInfo||{},B=H.brandComInfo||{};if(!A.jobName)throw Error("该职位信息不存在或已下架");return[{name:A.jobName||"",salary:A.salaryDesc||"",experience:A.experienceName||"",degree:A.degreeName||"",city:A.locationName||"",district:[A.areaDistrict,A.businessDistrict].filter(Boolean).join("·"),description:A.postDescription||"",skills:(A.showSkills||[]).join(", "),welfare:(B.labels||[]).join(", "),boss_name:E.name||"",boss_title:E.title||"",active_time:E.activeTimeDesc||"",company:B.brandName||E.brandName||"",industry:B.industryName||"",scale:B.scaleName||"",stage:B.stageName||"",address:A.address||"",url:A.encryptId?"https://www.zhipin.com/job_detail/"+A.encryptId+".html":""}]}});
1
+ import{cli as c,Strategy as d}from"@jackwener/opencli/registry";import{requirePage as l,navigateTo as m,bossFetch as p,verbose as b}from"./utils.js";c({site:"boss",name:"detail",access:"read",description:"BOSS直聘查看职位详情",domain:"www.zhipin.com",strategy:d.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"security-id",positional:!0,required:!0,help:"Security ID from search results (securityId field)"}],columns:["name","salary","experience","degree","city","district","description","skills","welfare","boss_name","boss_title","active_time","company","industry","scale","stage","address","url"],func:async(a,r)=>{l(a);const o=r["security-id"];b("Fetching job detail...");await m(a,"https://www.zhipin.com/web/geek/job");const n=`https://www.zhipin.com/wapi/zpgeek/job/detail.json?securityId=${encodeURIComponent(o)}`,i=(await p(a,n)).zpData||{},e=i.jobInfo||{},s=i.bossInfo||{},t=i.brandComInfo||{};if(!e.jobName)throw Error("该职位信息不存在或已下架");return[{name:e.jobName||"",salary:e.salaryDesc||"",experience:e.experienceName||"",degree:e.degreeName||"",city:e.locationName||"",district:[e.areaDistrict,e.businessDistrict].filter(Boolean).join("·"),description:e.postDescription||"",skills:(e.showSkills||[]).join(", "),welfare:(t.labels||[]).join(", "),boss_name:s.name||"",boss_title:s.title||"",active_time:s.activeTimeDesc||"",company:t.brandName||s.brandName||"",industry:t.industryName||"",scale:t.scaleName||"",stage:t.stageName||"",address:e.address||"",url:e.encryptId?"https://www.zhipin.com/job_detail/"+e.encryptId+".html":""}]}});
@@ -1 +1 @@
1
- import{cli as Y,Strategy as Z}from"@jackwener/opencli/registry";import{CommandExecutionError as _}from"@jackwener/opencli/errors";import{requirePage as $,navigateToChat as q,navigateToGeekChat as U,bossFetch as E,findFriendByUid as F,geekPost as L,fetchGeekBossData as N,resolveGeekBossId as P,isRecruiterSide as S,verbose as Q}from"./utils.js";function V(z){return z==="wechat"?"微信":"手机号"}async function W(z,H){const J=H.type||"phone";await U(z);const K=await P(z,H.uid),M=await N(z,K),O=M.securityId||"";if(!O)throw new _(`无法获取 securityId (uid=${K}),该会话可能已失效`);Q(`Requesting ${J} exchange from boss ${K}...`);await L(z,"/wapi/zpchat/exchange/request",{type:J==="wechat"?2:1,bossId:K,securityId:O});return[{status:"✅ 交换请求已发送",detail:`已向 ${M.name||M.bossName||K} 请求交换${V(J)}`}]}async function X(z,H){const J=H.type||"phone";Q(`Requesting ${J} exchange for ${H.uid}...`);await q(z);const K=await F(z,H.uid,{checkGreetList:!0});if(!K)throw Error("未找到该候选人");const M=K.name||"候选人",O=new URLSearchParams({type:String(J==="wechat"?2:1),securityId:K.securityId||"",uniqueId:String(K.uid),name:M});await E(z,"https://www.zhipin.com/wapi/zpchat/exchange/request",{method:"POST",body:O.toString()});return[{status:"✅ 交换请求已发送",detail:`已向 ${M} 发送${V(J)}交换请求`}]}Y({site:"boss",name:"exchange",access:"write",description:"BOSS直聘请求交换联系方式(手机/微信,求职端与招聘端都支持)",domain:"www.zhipin.com",strategy:Z.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",required:!0,positional:!0,help:"对方 uid:求职端=Boss 的 friendId/encryptFriendId;招聘端=候选人的 encryptUid"},{name:"type",default:"phone",choices:["phone","wechat"],help:"Exchange type: phone or wechat"},{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"}],columns:["status","detail"],func:async(z,H)=>{$(z);const J=H.side||"auto";if(J==="geek")return W(z,H);if(J==="boss")return X(z,H);return await S(z)?X(z,H):W(z,H)}});
1
+ import{cli as d,Strategy as h}from"@jackwener/opencli/registry";import{CommandExecutionError as m}from"@jackwener/opencli/errors";import{requirePage as y,navigateToChat as f,navigateToGeekChat as w,bossFetch as p,findFriendByUid as l,geekPost as b,fetchGeekBossData as I,resolveGeekBossId as x,isRecruiterSide as S,verbose as r}from"./utils.js";function a(e){return e==="wechat"?"微信":"手机号"}async function c(e,t){const i=t.type||"phone";await w(e);const n=await x(e,t.uid),s=await I(e,n),o=s.securityId||"";if(!o)throw new m(`无法获取 securityId (uid=${n}),该会话可能已失效`);r(`Requesting ${i} exchange from boss ${n}...`);await b(e,"/wapi/zpchat/exchange/request",{type:i==="wechat"?2:1,bossId:n,securityId:o});return[{status:"✅ 交换请求已发送",detail:`已向 ${s.name||s.bossName||n} 请求交换${a(i)}`}]}async function u(e,t){const i=t.type||"phone";r(`Requesting ${i} exchange for ${t.uid}...`);await f(e);const n=await l(e,t.uid,{checkGreetList:!0});if(!n)throw Error("未找到该候选人");const s=n.name||"候选人",o=new URLSearchParams({type:String(i==="wechat"?2:1),securityId:n.securityId||"",uniqueId:String(n.uid),name:s});await p(e,"https://www.zhipin.com/wapi/zpchat/exchange/request",{method:"POST",body:o.toString()});return[{status:"✅ 交换请求已发送",detail:`已向 ${s} 发送${a(i)}交换请求`}]}d({site:"boss",name:"exchange",access:"write",description:"BOSS直聘请求交换联系方式(手机/微信,求职端与招聘端都支持)",domain:"www.zhipin.com",strategy:h.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",required:!0,positional:!0,help:"对方 uid:求职端=Boss 的 friendId/encryptFriendId;招聘端=候选人的 encryptUid"},{name:"type",default:"phone",choices:["phone","wechat"],help:"Exchange type: phone or wechat"},{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"}],columns:["status","detail"],func:async(e,t)=>{y(e);const i=t.side||"auto";if(i==="geek")return c(e,t);if(i==="boss")return u(e,t);return await S(e)?u(e,t):c(e,t)}});
@@ -1 +1 @@
1
- import{cli as _,Strategy as $}from"@jackwener/opencli/registry";import{ArgumentError as V}from"@jackwener/opencli/errors";import{requirePage as h,navigateToChat as q,navigateToGeekJob as B,findFriendByUid as J,clickCandidateInList as L,typeAndSendMessage as M,geekAddFriend as N,verbose as W}from"./utils.js";async function X(D,H){const K=H["security-id"];if(!K)throw new V("求职端打招呼需要 --security-id(从 boss search / boss recommend 的 security_id 列拿)");W(`Greeting boss for job ${K}...`);await B(D);const O=await N(D,K,H.lid||"");return[{status:"✅ 打招呼成功",detail:O?.bossName?`已向 ${O.bossName} 打招呼,用 boss chatlist --side geek 看会话`:"已发送打招呼 / 投递,用 boss chatlist --side geek 看会话"}]}async function Y(D,H){if(!H.uid)throw new V("招聘端打招呼需要 uid 参数(候选人 encryptUid,从 boss recommend 拿)");W(`Greeting candidate ${H.uid}...`);await q(D,3);const K=await J(D,H.uid,{maxPages:1,checkGreetList:!0});if(!K)throw Error("未找到该候选人,请确认 uid 是否正确(可从 recommend 命令获取)");const O=K.uid,Z=K.name||"候选人";if(!await L(D,O))throw Error("无法在聊天列表中找到该用户,候选人可能不在当前列表中");await D.wait({time:2});const Q=H.text||"你好,请问您对这个职位感兴趣吗?";if(!await M(D,Q))throw Error("找不到消息输入框");await D.wait({time:1});return[{status:"✅ 招呼已发送",detail:`已向 ${Z} 发送: ${Q}`}]}_({site:"boss",name:"greet",access:"write",description:"BOSS直聘打招呼(求职端向 Boss 投递简历 / 招聘端向候选人发招呼)",domain:"www.zhipin.com",strategy:$.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",positional:!0,default:"",help:"[boss] Encrypted UID of the candidate (from recommend)"},{name:"security-id",required:!0,help:"Security ID:求职端=职位的 securityId(boss search 结果);招聘端=候选人的 securityId"},{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"},{name:"lid",default:"",help:"[geek] Lid parameter from search results (optional)"},{name:"job-id",default:"",help:"[boss] Encrypted job ID"},{name:"text",fromFile:!0,default:"",help:"[boss] Custom greeting message (uses default template if empty)"}],columns:["status","detail"],func:async(D,H)=>{h(D);const K=H.side||"auto";if(K==="geek")return X(D,H);if(K==="boss")return Y(D,H);return H.uid?Y(D,H):X(D,H)}});
1
+ import{cli as u,Strategy as m}from"@jackwener/opencli/registry";import{ArgumentError as o}from"@jackwener/opencli/errors";import{requirePage as f,navigateToChat as l,navigateToGeekJob as b,findFriendByUid as h,clickCandidateInList as y,typeAndSendMessage as w,geekAddFriend as p,verbose as n}from"./utils.js";async function d(e,t){const i=t["security-id"];if(!i)throw new o("求职端打招呼需要 --security-id(从 boss search / boss recommend 的 security_id 列拿)");n(`Greeting boss for job ${i}...`);await b(e);const s=await p(e,i,t.lid||"");return[{status:"✅ 打招呼成功",detail:s?.bossName?`已向 ${s.bossName} 打招呼,用 boss chatlist --side geek 看会话`:"已发送打招呼 / 投递,用 boss chatlist --side geek 看会话"}]}async function a(e,t){if(!t.uid)throw new o("招聘端打招呼需要 uid 参数(候选人 encryptUid,从 boss recommend 拿)");n(`Greeting candidate ${t.uid}...`);await l(e,3);const i=await h(e,t.uid,{maxPages:1,checkGreetList:!0});if(!i)throw Error("未找到该候选人,请确认 uid 是否正确(可从 recommend 命令获取)");const s=i.uid,c=i.name||"候选人";if(!await y(e,s))throw Error("无法在聊天列表中找到该用户,候选人可能不在当前列表中");await e.wait({time:2});const r=t.text||"你好,请问您对这个职位感兴趣吗?";if(!await w(e,r))throw Error("找不到消息输入框");await e.wait({time:1});return[{status:"✅ 招呼已发送",detail:`已向 ${c} 发送: ${r}`}]}u({site:"boss",name:"greet",access:"write",description:"BOSS直聘打招呼(求职端向 Boss 投递简历 / 招聘端向候选人发招呼)",domain:"www.zhipin.com",strategy:m.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",positional:!0,default:"",help:"[boss] Encrypted UID of the candidate (from recommend)"},{name:"security-id",required:!0,help:"Security ID:求职端=职位的 securityId(boss search 结果);招聘端=候选人的 securityId"},{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"},{name:"lid",default:"",help:"[geek] Lid parameter from search results (optional)"},{name:"job-id",default:"",help:"[boss] Encrypted job ID"},{name:"text",fromFile:!0,default:"",help:"[boss] Custom greeting message (uses default template if empty)"}],columns:["status","detail"],func:async(e,t)=>{f(e);const i=t.side||"auto";if(i==="geek")return d(e,t);if(i==="boss")return a(e,t);return t.uid?a(e,t):d(e,t)}});
@@ -1 +1 @@
1
- import{cli as M,Strategy as N}from"@jackwener/opencli/registry";import{EmptyResultError as D}from"@jackwener/opencli/errors";import{requirePage as O,navigateToChat as Q,navigateToGeekJob as U,geekGet as V,bossFetch as W,isRecruiterSide as X,verbose as H}from"./utils.js";function Y(f){return{job_name:f.jobName||"",company:f.brandName||"",time:f.interviewTime||f.startTimeDesc||"",address:f.address||f.addressText||"",contact:[f.contactName,f.contactPhone].filter(Boolean).join(" "),status:f.statusDesc||""}}function Z(f){return{job_name:f.jobName||"",company:f.geekName||"",time:f.interviewTime||f.startTimeDesc||"",address:f.address||f.addressText||"",contact:[f.contactName,f.contactPhone].filter(Boolean).join(" "),status:f.statusDesc||""}}async function K(f){H("Fetching interview invitations (geek side)...");await U(f);const A=await V(f,"/wapi/zpinterview/geek/interview/data.json"),x=A.interviewList??A.list??[];if(x.length===0)throw new D("boss interviews","暂无面试邀请。");return x.map(Y)}async function L(f){H("Fetching interview list (recruiter side)...");await Q(f);const A=await W(f,"https://www.zhipin.com/wapi/zpinterview/boss/interview/valid/list"),x=A.zpData?.list??A.zpData?.interviewList??[];if(x.length===0)throw new D("boss interviews","暂无面试安排。");return x.map(Z)}M({site:"boss",name:"interviews",access:"read",description:"BOSS直聘查看面试(求职端=收到的邀请 / 招聘端=我发出的面试)",domain:"www.zhipin.com",strategy:N.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"}],columns:["job_name","company","time","address","contact","status"],func:async(f,A)=>{O(f);const x=A.side||"auto";if(x==="geek")return K(f);if(x==="boss")return L(f);return await X(f)?L(f):K(f)}});
1
+ import{cli as o,Strategy as c}from"@jackwener/opencli/registry";import{EmptyResultError as i}from"@jackwener/opencli/errors";import{requirePage as m,navigateToChat as w,navigateToGeekJob as d,geekGet as u,bossFetch as v,isRecruiterSide as l,verbose as a}from"./utils.js";function b(e){return{job_name:e.jobName||"",company:e.brandName||"",time:e.interviewTime||e.startTimeDesc||"",address:e.address||e.addressText||"",contact:[e.contactName,e.contactPhone].filter(Boolean).join(" "),status:e.statusDesc||""}}function f(e){return{job_name:e.jobName||"",company:e.geekName||"",time:e.interviewTime||e.startTimeDesc||"",address:e.address||e.addressText||"",contact:[e.contactName,e.contactPhone].filter(Boolean).join(" "),status:e.statusDesc||""}}async function n(e){a("Fetching interview invitations (geek side)...");await d(e);const s=await u(e,"/wapi/zpinterview/geek/interview/data.json"),t=s.interviewList??s.list??[];if(t.length===0)throw new i("boss interviews","暂无面试邀请。");return t.map(b)}async function r(e){a("Fetching interview list (recruiter side)...");await w(e);const s=await v(e,"https://www.zhipin.com/wapi/zpinterview/boss/interview/valid/list"),t=s.zpData?.list??s.zpData?.interviewList??[];if(t.length===0)throw new i("boss interviews","暂无面试安排。");return t.map(f)}o({site:"boss",name:"interviews",access:"read",description:"BOSS直聘查看面试(求职端=收到的邀请 / 招聘端=我发出的面试)",domain:"www.zhipin.com",strategy:c.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"}],columns:["job_name","company","time","address","contact","status"],func:async(e,s)=>{m(e);const t=s.side||"auto";if(t==="geek")return n(e);if(t==="boss")return r(e);return await l(e)?r(e):n(e)}});
@@ -1,4 +1,4 @@
1
- import{cli as u,Strategy as v}from"@jackwener/opencli/registry";import{requirePage as h,navigateToChat as l,bossFetch as a,findFriendByUid as f,verbose as y}from"./utils.js";u({site:"boss",name:"invite",access:"write",description:"BOSS直聘发送面试邀请",domain:"www.zhipin.com",strategy:v.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",positional:!0,required:!0,help:"Encrypted UID of the candidate"},{name:"time",required:!0,help:"Interview time (e.g. 2025-04-01 14:00)"},{name:"address",default:"",help:"Interview address (uses saved address if empty)"},{name:"contact",default:"",help:"Contact person name (uses saved contact if empty)"}],columns:["status","detail"],func:async(e,t)=>{h(e);y(`Sending interview invitation to ${t.uid}...`);await l(e);const i=await f(e,t.uid,{checkGreetList:!0});if(!i)throw Error("未找到该候选人");const c=i.name||"候选人",n=await a(e,"https://www.zhipin.com/wapi/zpinterview/boss/interview/contactInit",{allowNonZero:!0,timeout:1e4}),s=t.contact||n.zpData?.contactName||"",w=n.zpData?.contactPhone||"",m=n.zpData?.contactId||"",r=(await a(e,"https://www.zhipin.com/wapi/zpinterview/boss/interview/listAddress",{allowNonZero:!0,timeout:1e4})).zpData?.list?.[0]||{},o=t.address||r.cityAddressText||r.addressText||"",d=new Date(t.time).getTime();if(isNaN(d))throw Error(`时间格式错误: ${t.time},请使用格式如 2025-04-01 14:00`);const p=new URLSearchParams({uid:String(i.uid),securityId:i.securityId||"",encryptJobId:i.encryptJobId||"",interviewTime:String(d),contactId:m,contactName:s,contactPhone:w,address:o,interviewType:"1"});await a(e,"https://www.zhipin.com/wapi/zpinterview/boss/interview/invite.json",{method:"POST",body:p.toString()});return[{status:"✅ 面试邀请已发送",detail:`已向 ${c} 发送面试邀请
1
+ import{cli as u,Strategy as h}from"@jackwener/opencli/registry";import{requirePage as v,navigateToChat as l,bossFetch as a,findFriendByUid as f,verbose as y}from"./utils.js";u({site:"boss",name:"invite",access:"write",description:"BOSS直聘发送面试邀请",domain:"www.zhipin.com",strategy:h.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",positional:!0,required:!0,help:"Encrypted UID of the candidate"},{name:"time",required:!0,help:"Interview time (e.g. 2025-04-01 14:00)"},{name:"address",default:"",help:"Interview address (uses saved address if empty)"},{name:"contact",default:"",help:"Contact person name (uses saved contact if empty)"}],columns:["status","detail"],func:async(e,t)=>{v(e);y(`Sending interview invitation to ${t.uid}...`);await l(e);const i=await f(e,t.uid,{checkGreetList:!0});if(!i)throw Error("未找到该候选人");const c=i.name||"候选人",n=await a(e,"https://www.zhipin.com/wapi/zpinterview/boss/interview/contactInit",{allowNonZero:!0,timeout:1e4}),s=t.contact||n.zpData?.contactName||"",w=n.zpData?.contactPhone||"",m=n.zpData?.contactId||"",r=(await a(e,"https://www.zhipin.com/wapi/zpinterview/boss/interview/listAddress",{allowNonZero:!0,timeout:1e4})).zpData?.list?.[0]||{},o=t.address||r.cityAddressText||r.addressText||"",d=new Date(t.time).getTime();if(isNaN(d))throw Error(`时间格式错误: ${t.time},请使用格式如 2025-04-01 14:00`);const p=new URLSearchParams({uid:String(i.uid),securityId:i.securityId||"",encryptJobId:i.encryptJobId||"",interviewTime:String(d),contactId:m,contactName:s,contactPhone:w,address:o,interviewType:"1"});await a(e,"https://www.zhipin.com/wapi/zpinterview/boss/interview/invite.json",{method:"POST",body:p.toString()});return[{status:"✅ 面试邀请已发送",detail:`已向 ${c} 发送面试邀请
2
2
  时间: ${t.time}
3
3
  地点: ${o}
4
4
  联系人: ${s}`}]}});
@@ -1 +1 @@
1
- import{cli as s,Strategy as o}from"@jackwener/opencli/registry";import{requirePage as e,navigateToChat as i,bossFetch as r,verbose as b}from"./utils.js";s({site:"boss",name:"joblist",access:"read",description:"BOSS直聘查看我发布的职位列表",domain:"www.zhipin.com",strategy:o.COOKIE,navigateBefore:!1,browser:!0,args:[],columns:["job_name","salary","city","status","encrypt_job_id"],func:async(a,n)=>{e(a);b("Fetching job list...");await i(a);return((await r(a,"https://www.zhipin.com/wapi/zpjob/job/chatted/jobList")).zpData||[]).map((t)=>({job_name:t.jobName||"",salary:t.salaryDesc||"",city:t.address||"",status:t.jobOnlineStatus===1?"在线":"已关闭",encrypt_job_id:t.encryptJobId||""}))}});
1
+ import{cli as s,Strategy as o}from"@jackwener/opencli/registry";import{requirePage as e,navigateToChat as i,bossFetch as r,verbose as n}from"./utils.js";s({site:"boss",name:"joblist",access:"read",description:"BOSS直聘查看我发布的职位列表",domain:"www.zhipin.com",strategy:o.COOKIE,navigateBefore:!1,browser:!0,args:[],columns:["job_name","salary","city","status","encrypt_job_id"],func:async(t,c)=>{e(t);n("Fetching job list...");await i(t);return((await r(t,"https://www.zhipin.com/wapi/zpjob/job/chatted/jobList")).zpData||[]).map((a)=>({job_name:a.jobName||"",salary:a.salaryDesc||"",city:a.address||"",status:a.jobOnlineStatus===1?"在线":"已关闭",encrypt_job_id:a.encryptJobId||""}))}});
package/clis/boss/mark.js CHANGED
@@ -1 +1 @@
1
- import{cli as q,Strategy as U}from"@jackwener/opencli/registry";import{ArgumentError as C,EmptyResultError as F}from"@jackwener/opencli/errors";import{requirePage as T,navigateToChat as h,navigateToGeekChat as j,bossFetch as N,findFriendByUid as G,resolveGeekBoss as R,isRecruiterSide as S,verbose as Y}from"./utils.js";const O={"新招呼":1,"沟通中":2,"已约面":3,"已获取简历":4,"已交换电话":5,"已交换微信":6,"不合适":7,"牛人发起":8,"收藏":11};function M(x){if(O[x])return O[x];if(x!==""&&!isNaN(Number(x)))return Number(x);const D=Object.entries(O).find(([z])=>z.includes(x));if(D)return D[1];throw new C(`未知标签: ${x}。可用标签: ${Object.keys(O).join(", ")}`)}async function Z(x,{friendId:D,friendSource:z,labelId:H,remove:Q}){const V=Q?"deleteMark":"addMark",W=new URLSearchParams({friendId:String(D),friendSource:String(z??0),labelId:String(H)});await N(x,`https://www.zhipin.com/wapi/zprelation/friend/label/${V}?${W.toString()}`)}q({site:"boss",name:"mark",access:"write",description:"BOSS直聘给会话打标签(求职端标记 Boss / 招聘端标记候选人)",domain:"www.zhipin.com",strategy:U.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",positional:!0,required:!0,help:"对方 uid(从 boss chatlist 拿)"},{name:"label",required:!0,help:"Label name (新招呼/沟通中/已约面/已获取简历/已交换电话/已交换微信/不合适/收藏) or label ID"},{name:"remove",type:"boolean",default:!1,help:"Remove the label instead of adding"},{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"}],columns:["status","detail"],func:async(x,D)=>{T(x);const z=D.remove||!1,H=M(D.label),Q=Object.entries(O).find(([,J])=>J===H)?.[0]||String(H),V=D.side||"auto",W=async()=>{await j(x);const{id:J,friend:K}=await R(x,D.uid);Y(`${z?"Removing":"Adding"} label ${H} for boss ${J}...`);await Z(x,{friendId:J,friendSource:K?.friendSource??0,labelId:H,remove:z});return[{status:z?"✅ 标签已移除":"✅ 标签已添加",detail:`Boss ${J}: ${z?"移除":"添加"}标签「${Q}」`}]},X=async(J)=>{const K=J??await G(x,D.uid,{checkGreetList:!0});if(!K)throw new F("boss candidate search");const $=K.name||"候选人";Y(`${z?"Removing":"Adding"} label ${H} for ${D.uid}...`);await Z(x,{friendId:K.uid,friendSource:K.friendSource??0,labelId:H,remove:z});return[{status:z?"✅ 标签已移除":"✅ 标签已添加",detail:`${$}: ${z?"移除":"添加"}标签「${Q}」`}]};if(V==="geek")return W();if(V==="boss"){await h(x);return X(null)}return await S(x)?X(null):W()}});
1
+ import{cli as b,Strategy as h}from"@jackwener/opencli/registry";import{ArgumentError as w,EmptyResultError as S}from"@jackwener/opencli/errors";import{requirePage as y,navigateToChat as v,navigateToGeekChat as g,bossFetch as k,findFriendByUid as B,resolveGeekBoss as L,isRecruiterSide as R,verbose as l}from"./utils.js";const o={"新招呼":1,"沟通中":2,"已约面":3,"已获取简历":4,"已交换电话":5,"已交换微信":6,"不合适":7,"牛人发起":8,"收藏":11};function p(e){if(o[e])return o[e];if(e!==""&&!isNaN(Number(e)))return Number(e);const t=Object.entries(o).find(([r])=>r.includes(e));if(t)return t[1];throw new w(`未知标签: ${e}。可用标签: ${Object.keys(o).join(", ")}`)}async function f(e,{friendId:t,friendSource:r,labelId:i,remove:s}){const d=s?"deleteMark":"addMark",c=new URLSearchParams({friendId:String(t),friendSource:String(r??0),labelId:String(i)});await k(e,`https://www.zhipin.com/wapi/zprelation/friend/label/${d}?${c.toString()}`)}b({site:"boss",name:"mark",access:"write",description:"BOSS直聘给会话打标签(求职端标记 Boss / 招聘端标记候选人)",domain:"www.zhipin.com",strategy:h.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",positional:!0,required:!0,help:"对方 uid(从 boss chatlist 拿)"},{name:"label",required:!0,help:"Label name (新招呼/沟通中/已约面/已获取简历/已交换电话/已交换微信/不合适/收藏) or label ID"},{name:"remove",type:"boolean",default:!1,help:"Remove the label instead of adding"},{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"}],columns:["status","detail"],func:async(e,t)=>{y(e);const r=t.remove||!1,i=p(t.label),s=Object.entries(o).find(([,n])=>n===i)?.[0]||String(i),d=t.side||"auto",c=async()=>{await g(e);const{id:n,friend:a}=await L(e,t.uid);l(`${r?"Removing":"Adding"} label ${i} for boss ${n}...`);await f(e,{friendId:n,friendSource:a?.friendSource??0,labelId:i,remove:r});return[{status:r?"✅ 标签已移除":"✅ 标签已添加",detail:`Boss ${n}: ${r?"移除":"添加"}标签「${s}」`}]},u=async(n)=>{const a=n??await B(e,t.uid,{checkGreetList:!0});if(!a)throw new S("boss candidate search");const m=a.name||"候选人";l(`${r?"Removing":"Adding"} label ${i} for ${t.uid}...`);await f(e,{friendId:a.uid,friendSource:a.friendSource??0,labelId:i,remove:r});return[{status:r?"✅ 标签已移除":"✅ 标签已添加",detail:`${m}: ${r?"移除":"添加"}标签「${s}」`}]};if(d==="geek")return c();if(d==="boss"){await v(e);return u(null)}return await R(e)?u(null):c()}});
package/clis/boss/me.js CHANGED
@@ -1,4 +1,4 @@
1
- import{cli as $,Strategy as q}from"@jackwener/opencli/registry";import{requirePage as A,navigateTo as D,geekGet as L,verbose as O}from"./utils.js";const M="https://www.zhipin.com/web/geek/resume";async function N(B){return await B.evaluate(`
1
+ import{cli as w,Strategy as l}from"@jackwener/opencli/registry";import{requirePage as f,navigateTo as x,geekGet as a,verbose as d}from"./utils.js";const g="https://www.zhipin.com/web/geek/resume";async function _(n){return await n.evaluate(`
2
2
  (() => {
3
3
  // 1. 页面自己发过的请求里带 id=<expectId>
4
4
  try {
@@ -23,4 +23,4 @@ import{cli as $,Strategy as q}from"@jackwener/opencli/registry";import{requirePa
23
23
  } catch (_) {}
24
24
  return '';
25
25
  })()
26
- `)||""}$({site:"boss",name:"me",access:"read",description:"BOSS直聘查看我的资料与求职期望(求职端)",domain:"www.zhipin.com",strategy:q.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"expect-id",default:"",help:"encryptExpectId(不传则从简历页自动抠)"}],columns:["name","gender","age","degree","work_years","start_work","hometown","expect_position","expect_city","expect_salary","expect_industry","done_positions","interest_positions","interest_cities"],func:async(B,J)=>{A(B);O("Fetching profile...");await D(B,M,2);const f=await L(B,"/wapi/zpgeek/resume/baseinfo/query.json");let h={};const K=J["expect-id"]||await N(B);if(K){const C=await L(B,"/wapi/zpgeek/resume/expect/query.json",{id:K},{allowNonZero:!0});h=C&&C.code===void 0?C.expect??C:{}}else O("expectId not found — skipping job expectation section");const H=(C)=>(C||[]).map((F)=>typeof F==="string"?F:F?.name||F?.positionName||F?.locationName||F?.cityName).filter(Boolean).join(" / "),Q=f.gender===1?"男":f.gender===2?"女":"",V=f.workYearDesc||(typeof f.workYears==="number"&&f.workYears>0?`${f.workYears}年`:""),W=[h.locationName,h.subLocationName].filter(Boolean).join(" "),X=h.industryDesc&&h.industryDesc!=="行业不限"?h.industryDesc:"";return[{name:f.name||f.nickName||f.geekName||"",gender:Q,age:f.ageDesc||(f.age?`${f.age}岁`:""),degree:f.degreeCategory||"",work_years:V,start_work:f.startWorkDateDesc||"",hometown:f.hometownName||"",expect_position:h.positionName||"",expect_city:W,expect_salary:h.salaryDescNew||h.salaryDesc||"",expect_industry:X,done_positions:H(h.doneWorkPositionList),interest_positions:H(h.interestPositionList),interest_cities:H(h.interestLocationList)}]}});
26
+ `)||""}w({site:"boss",name:"me",access:"read",description:"BOSS直聘查看我的资料与求职期望(求职端)",domain:"www.zhipin.com",strategy:l.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"expect-id",default:"",help:"encryptExpectId(不传则从简历页自动抠)"}],columns:["name","gender","age","degree","work_years","start_work","hometown","expect_position","expect_city","expect_salary","expect_industry","done_positions","interest_positions","interest_cities"],func:async(n,i)=>{f(n);d("Fetching profile...");await x(n,g,2);const e=await a(n,"/wapi/zpgeek/resume/baseinfo/query.json");let t={};const c=i["expect-id"]||await _(n);if(c){const o=await a(n,"/wapi/zpgeek/resume/expect/query.json",{id:c},{allowNonZero:!0});t=o&&o.code===void 0?o.expect??o:{}}else d("expectId not found — skipping job expectation section");const s=(o)=>(o||[]).map((r)=>typeof r==="string"?r:r?.name||r?.positionName||r?.locationName||r?.cityName).filter(Boolean).join(" / "),p=e.gender===1?"男":e.gender===2?"女":"",m=e.workYearDesc||(typeof e.workYears==="number"&&e.workYears>0?`${e.workYears}年`:""),u=[t.locationName,t.subLocationName].filter(Boolean).join(" "),y=t.industryDesc&&t.industryDesc!=="行业不限"?t.industryDesc:"";return[{name:e.name||e.nickName||e.geekName||"",gender:p,age:e.ageDesc||(e.age?`${e.age}岁`:""),degree:e.degreeCategory||"",work_years:m,start_work:e.startWorkDateDesc||"",hometown:e.hometownName||"",expect_position:t.positionName||"",expect_city:u,expect_salary:t.salaryDescNew||t.salaryDesc||"",expect_industry:y,done_positions:s(t.doneWorkPositionList),interest_positions:s(t.interestPositionList),interest_cities:s(t.interestLocationList)}]}});
@@ -1 +1 @@
1
- import{cli as K,Strategy as P}from"@jackwener/opencli/registry";import{EmptyResultError as z}from"@jackwener/opencli/errors";import{requirePage as I,navigateToChat as N,navigateToGeekJob as T,bossFetch as U,fetchRecommendList as _,geekGet as h,isRecruiterSide as D,verbose as q}from"./utils.js";const G=["name","salary","company","area","experience","degree","boss","security_id","url"],L=["name","job_name","last_time","labels","encrypt_uid","security_id","encrypt_job_id"];async function B(A,H){q("Fetching recommended jobs (geek side)...");await T(A);const V=await h(A,"/wapi/zprelation/interaction/geekGetJob",{page:H.page||1,tag:5,isActive:"true"}),W=V.jobList??V.cardList??[];if(!Array.isArray(W)||W.length===0)throw new z("boss recommend","推荐职位为空。请先在 BOSS 直聘 App 或网页完善求职期望(岗位 + 城市),推荐流才会有数据。");const Y=H.limit||20;return W.slice(0,Y).map((Q)=>{const x=Q.jobInfo??Q,X=Q.brandInfo??Q,Z=Q.bossInfo??Q,$=x.encryptJobId||Q.encryptJobId||"";return{name:x.jobName||"",salary:x.salaryDesc||"",company:X.brandName||"",area:[x.cityName,x.areaDistrict,x.businessDistrict].filter(Boolean).join("·"),experience:x.jobExperience||x.experienceName||"",degree:x.jobDegree||x.degreeName||"",boss:[Z.bossName,Z.bossTitle].filter(Boolean).join(" · "),security_id:x.securityId||Q.securityId||"",url:$?`https://www.zhipin.com/job_detail/${$}.html`:""}})}async function F(A,H){q("Fetching recommended candidates (recruiter side)...");await N(A);const V=await U(A,"https://www.zhipin.com/wapi/zprelation/friend/label/get",{allowNonZero:!0}),W={};if(V.code===0&&V.zpData?.labels)for(const x of V.zpData.labels)W[x.labelId]=x.label;const Y=await _(A),Q=H.limit||20;return Y.slice(0,Q).map((x)=>({name:x.name||"",job_name:x.jobName||"",last_time:x.lastTime||"",labels:(x.relationLabelList||[]).map((X)=>W[X]||String(X)).join(", "),encrypt_uid:x.encryptUid||"",security_id:x.securityId||"",encrypt_job_id:x.encryptJobId||""}))}K({site:"boss",name:"recommend",access:"read",description:"BOSS直聘查看推荐(求职端=推荐职位 / 招聘端=推荐候选人)",domain:"www.zhipin.com",strategy:P.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"},{name:"limit",type:"int",default:20,help:"Number of results to return"},{name:"page",type:"int",default:1,help:"[geek] Page number"}],columns:[...new Set([...G,...L])],func:async(A,H)=>{I(A);const V=H.side||"auto";if(V==="geek")return B(A,H);if(V==="boss")return F(A,H);return await D(A)?F(A,H):B(A,H)}});
1
+ import{cli as u,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as y}from"@jackwener/opencli/errors";import{requirePage as f,navigateToChat as h,navigateToGeekJob as w,bossFetch as _,fetchRecommendList as g,geekGet as I,isRecruiterSide as S,verbose as m}from"./utils.js";const N=["name","salary","company","area","experience","degree","boss","security_id","url"],j=["name","job_name","last_time","labels","encrypt_uid","security_id","encrypt_job_id"];async function d(t,i){m("Fetching recommended jobs (geek side)...");await w(t);const o=await I(t,"/wapi/zprelation/interaction/geekGetJob",{page:i.page||1,tag:5,isActive:"true"}),n=o.jobList??o.cardList??[];if(!Array.isArray(n)||n.length===0)throw new y("boss recommend","推荐职位为空。请先在 BOSS 直聘 App 或网页完善求职期望(岗位 + 城市),推荐流才会有数据。");const s=i.limit||20;return n.slice(0,s).map((a)=>{const e=a.jobInfo??a,r=a.brandInfo??a,c=a.bossInfo??a,l=e.encryptJobId||a.encryptJobId||"";return{name:e.jobName||"",salary:e.salaryDesc||"",company:r.brandName||"",area:[e.cityName,e.areaDistrict,e.businessDistrict].filter(Boolean).join("·"),experience:e.jobExperience||e.experienceName||"",degree:e.jobDegree||e.degreeName||"",boss:[c.bossName,c.bossTitle].filter(Boolean).join(" · "),security_id:e.securityId||a.securityId||"",url:l?`https://www.zhipin.com/job_detail/${l}.html`:""}})}async function b(t,i){m("Fetching recommended candidates (recruiter side)...");await h(t);const o=await _(t,"https://www.zhipin.com/wapi/zprelation/friend/label/get",{allowNonZero:!0}),n={};if(o.code===0&&o.zpData?.labels)for(const e of o.zpData.labels)n[e.labelId]=e.label;const s=await g(t),a=i.limit||20;return s.slice(0,a).map((e)=>({name:e.name||"",job_name:e.jobName||"",last_time:e.lastTime||"",labels:(e.relationLabelList||[]).map((r)=>n[r]||String(r)).join(", "),encrypt_uid:e.encryptUid||"",security_id:e.securityId||"",encrypt_job_id:e.encryptJobId||""}))}u({site:"boss",name:"recommend",access:"read",description:"BOSS直聘查看推荐(求职端=推荐职位 / 招聘端=推荐候选人)",domain:"www.zhipin.com",strategy:p.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"},{name:"limit",type:"int",default:20,help:"Number of results to return"},{name:"page",type:"int",default:1,help:"[geek] Page number"}],columns:[...new Set([...N,...j])],func:async(t,i)=>{f(t);const o=i.side||"auto";if(o==="geek")return d(t,i);if(o==="boss")return b(t,i);return await S(t)?b(t,i):d(t,i)}});
@@ -1 +1 @@
1
- import{cli as o,Strategy as n}from"@jackwener/opencli/registry";import{ArgumentError as u}from"@jackwener/opencli/errors";import{requirePage as c,navigateTo as d,geekPost as w,fetchGeekAttachmentResumes as h,verbose as l}from"./utils.js";o({site:"boss",name:"resumedelete",access:"write",description:"BOSS直聘删除账号里的一份附件简历(求职端)",domain:"www.zhipin.com",strategy:n.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"resume-id",positional:!0,required:!0,help:"encryptResumeId(从 boss resumelist 拿)"}],columns:["status","detail"],func:async(t,a)=>{c(t);const e=String(a["resume-id"]);await d(t,"https://www.zhipin.com/web/geek/resume",2);const r=await h(t),m=r.find((s)=>String(s.resumeId)===e);if(!m){const s=r.map((i)=>`${i.resumeId}(${i.showName||"未命名"})`).join(", ")||"(空)";throw new u(`resume-id=${e} 不在账号简历列表 [${s}] 中,没有执行删除`)}l(`Deleting attachment resume ${e}...`);await w(t,"/wapi/zpgeek/resume/attachment/delete.json",{resumeId:e});return[{status:"✅ 简历已删除",detail:`已删除附件简历「${m.showName||e}」`}]}});
1
+ import{cli as o,Strategy as n}from"@jackwener/opencli/registry";import{ArgumentError as u}from"@jackwener/opencli/errors";import{requirePage as c,navigateTo as w,geekPost as d,fetchGeekAttachmentResumes as h,verbose as l}from"./utils.js";o({site:"boss",name:"resumedelete",access:"write",description:"BOSS直聘删除账号里的一份附件简历(求职端)",domain:"www.zhipin.com",strategy:n.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"resume-id",positional:!0,required:!0,help:"encryptResumeId(从 boss resumelist 拿)"}],columns:["status","detail"],func:async(t,a)=>{c(t);const e=String(a["resume-id"]);await w(t,"https://www.zhipin.com/web/geek/resume",2);const r=await h(t),i=r.find((s)=>String(s.resumeId)===e);if(!i){const s=r.map((m)=>`${m.resumeId}(${m.showName||"未命名"})`).join(", ")||"(空)";throw new u(`resume-id=${e} 不在账号简历列表 [${s}] 中,没有执行删除`)}l(`Deleting attachment resume ${e}...`);await d(t,"/wapi/zpgeek/resume/attachment/delete.json",{resumeId:e});return[{status:"✅ 简历已删除",detail:`已删除附件简历「${i.showName||e}」`}]}});
@@ -1 +1 @@
1
- import{cli as i,Strategy as m}from"@jackwener/opencli/registry";import{EmptyResultError as r}from"@jackwener/opencli/errors";import{requirePage as a,navigateTo as o,fetchGeekAttachmentResumes as u,verbose as n}from"./utils.js";i({site:"boss",name:"resumelist",access:"read",description:"BOSS直聘列出账号绑定的附件简历(求职端)",domain:"www.zhipin.com",strategy:m.COOKIE,navigateBefore:!1,browser:!0,args:[],columns:["resume_id","name","suffix","size","upload_time"],func:async(s)=>{a(s);n("Fetching attachment resumes...");await o(s,"https://www.zhipin.com/web/geek/resume",2);const t=await u(s);if(t.length===0)throw new r("boss resumelist","账号还没有绑定附件简历,请先在 BOSS 直聘 App 或网页简历页上传。");return t.map((e)=>({resume_id:e.resumeId||"",name:e.showName||"",suffix:e.suffixName||"",size:e.resumeSizeDesc||"",upload_time:e.uploadTime?new Date(e.uploadTime).toLocaleString("zh-CN"):""}))}});
1
+ import{cli as i,Strategy as m}from"@jackwener/opencli/registry";import{EmptyResultError as a}from"@jackwener/opencli/errors";import{requirePage as r,navigateTo as o,fetchGeekAttachmentResumes as u,verbose as n}from"./utils.js";i({site:"boss",name:"resumelist",access:"read",description:"BOSS直聘列出账号绑定的附件简历(求职端)",domain:"www.zhipin.com",strategy:m.COOKIE,navigateBefore:!1,browser:!0,args:[],columns:["resume_id","name","suffix","size","upload_time"],func:async(s)=>{r(s);n("Fetching attachment resumes...");await o(s,"https://www.zhipin.com/web/geek/resume",2);const t=await u(s);if(t.length===0)throw new a("boss resumelist","账号还没有绑定附件简历,请先在 BOSS 直聘 App 或网页简历页上传。");return t.map((e)=>({resume_id:e.resumeId||"",name:e.showName||"",suffix:e.suffixName||"",size:e.resumeSizeDesc||"",upload_time:e.uploadTime?new Date(e.uploadTime).toLocaleString("zh-CN"):""}))}});
@@ -1,29 +1,29 @@
1
- import*as C from"node:fs";import*as $ from"node:path";import{cli as D,Strategy as X}from"@jackwener/opencli/registry";import{ArgumentError as O,CommandExecutionError as Q}from"@jackwener/opencli/errors";import{setInputFiles as Y}from"../_shared/file-inject.js";import{requirePage as h,navigateTo as N,geekPost as S,verbose as y}from"./utils.js";const A="https://www.zhipin.com/web/geek/resume",V="pp-boss-resume-upload",j=10485760,q={pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg"};function F(J){const H=$.resolve(String(J).replace(/^~(?=$|\/)/,process.env.HOME||"~"));let z;try{z=C.statSync(H)}catch{throw new O(`文件不存在: ${H}`)}if(!z.isFile())throw new O(`不是一个文件: ${H}`);const K=$.extname(H).toLowerCase().replace(/^\./,"");if(!q[K])throw new O(`不支持的文件类型: .${K}(支持 ${Object.keys(q).sort().join("/")})`);if(z.size<=0)throw new O(`文件为空: ${H}`);if(z.size>j)throw new O(`文件过大: ${(z.size/1024/1024).toFixed(1)}MB(上限 ${j/1024/1024}MB)`);return{abs:H,name:$.basename(H),suffix:K,mime:q[K],size:z.size}}D({site:"boss",name:"resumeupload",access:"write",description:"BOSS直聘上传附件简历到账号库(求职端)",domain:"www.zhipin.com",strategy:X.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"file",positional:!0,required:!0,help:"本地简历文件路径(pdf/doc/docx/ppt/pptx/png/jpg,≤10MB)"},{name:"file-type",type:"int",default:1,help:"1=普通简历(默认),2=作品集"},{name:"annex-type",type:"int",default:1,help:"save 时的 annexType,1=普通简历(默认)"}],columns:["status","resume_id","name","detail"],func:async(J,H)=>{h(J);const z=F(H.file);y(`Uploading resume ${z.name} (${(z.size/1024).toFixed(0)}KB)...`);await N(J,A,2);await J.evaluate(`
1
+ import*as g from"node:fs";import*as c from"node:path";import{cli as h,Strategy as S}from"@jackwener/opencli/registry";import{ArgumentError as s,CommandExecutionError as o}from"@jackwener/opencli/errors";import{setInputFiles as b}from"../_shared/file-inject.js";import{requirePage as x,navigateTo as v,geekPost as O,verbose as f}from"./utils.js";const E="https://www.zhipin.com/web/geek/resume",a="pp-boss-resume-upload",w=10485760,l={pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",ppt:"application/vnd.ms-powerpoint",pptx:"application/vnd.openxmlformats-officedocument.presentationml.presentation",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg"};function N(n){const t=c.resolve(String(n).replace(/^~(?=$|\/)/,process.env.HOME||"~"));let e;try{e=g.statSync(t)}catch{throw new s(`文件不存在: ${t}`)}if(!e.isFile())throw new s(`不是一个文件: ${t}`);const i=c.extname(t).toLowerCase().replace(/^\./,"");if(!l[i])throw new s(`不支持的文件类型: .${i}(支持 ${Object.keys(l).sort().join("/")})`);if(e.size<=0)throw new s(`文件为空: ${t}`);if(e.size>w)throw new s(`文件过大: ${(e.size/1024/1024).toFixed(1)}MB(上限 ${w/1024/1024}MB)`);return{abs:t,name:c.basename(t),suffix:i,mime:l[i],size:e.size}}h({site:"boss",name:"resumeupload",access:"write",description:"BOSS直聘上传附件简历到账号库(求职端)",domain:"www.zhipin.com",strategy:S.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"file",positional:!0,required:!0,help:"本地简历文件路径(pdf/doc/docx/ppt/pptx/png/jpg,≤10MB)"},{name:"file-type",type:"int",default:1,help:"1=普通简历(默认),2=作品集"},{name:"annex-type",type:"int",default:1,help:"save 时的 annexType,1=普通简历(默认)"}],columns:["status","resume_id","name","detail"],func:async(n,t)=>{x(n);const e=N(t.file);f(`Uploading resume ${e.name} (${(e.size/1024).toFixed(0)}KB)...`);await v(n,E,2);await n.evaluate(`
2
2
  (() => {
3
- let el = document.getElementById(${JSON.stringify(V)});
3
+ let el = document.getElementById(${JSON.stringify(a)});
4
4
  if (!el) {
5
5
  el = document.createElement('input');
6
6
  el.type = 'file';
7
- el.id = ${JSON.stringify(V)};
7
+ el.id = ${JSON.stringify(a)};
8
8
  el.style.position = 'fixed';
9
9
  el.style.left = '-9999px';
10
10
  document.body.appendChild(el);
11
11
  }
12
12
  return true;
13
13
  })()
14
- `);try{await Y(J,`#${V}`,[z.abs])}catch(Z){throw new Q(`简历文件注入页面失败: ${Z instanceof Error?Z.message:String(Z)}`)}const K=await J.evaluate(`
14
+ `);try{await b(n,`#${a}`,[e.abs])}catch(m){throw new o(`简历文件注入页面失败: ${m instanceof Error?m.message:String(m)}`)}const i=await n.evaluate(`
15
15
  (async () => {
16
- const input = document.getElementById(${JSON.stringify(V)});
16
+ const input = document.getElementById(${JSON.stringify(a)});
17
17
  if (!input || !input.files || input.files.length === 0) {
18
18
  return { ok: false, error: '文件未进入页面 input' };
19
19
  }
20
20
  const src = input.files[0];
21
21
  const buf = await src.arrayBuffer();
22
22
  // 按真实后缀重建 File,保证 MIME 正确(注入通道构造的 File 可能是 octet-stream)
23
- const file = new File([buf], ${JSON.stringify(z.name)}, { type: ${JSON.stringify(z.mime)} });
23
+ const file = new File([buf], ${JSON.stringify(e.name)}, { type: ${JSON.stringify(e.mime)} });
24
24
  const fd = new FormData();
25
- fd.append('file', file, ${JSON.stringify(z.name)});
26
- fd.append('fileType', ${JSON.stringify(String(H["file-type"]??1))});
25
+ fd.append('file', file, ${JSON.stringify(e.name)});
26
+ fd.append('fileType', ${JSON.stringify(String(t["file-type"]??1))});
27
27
  const headers = { 'X-Requested-With': 'XMLHttpRequest' };
28
28
  const bst = (document.cookie.match(/(?:^|;\\s*)bst=([^;]+)/) || [])[1];
29
29
  if (bst) headers['zp_token'] = decodeURIComponent(bst);
@@ -44,10 +44,10 @@ import*as C from"node:fs";import*as $ from"node:path";import{cli as D,Strategy a
44
44
  return { ok: false, error: String(e && e.message || e) };
45
45
  }
46
46
  })()
47
- `);await J.evaluate(`
47
+ `);await n.evaluate(`
48
48
  (() => {
49
- const el = document.getElementById(${JSON.stringify(V)});
49
+ const el = document.getElementById(${JSON.stringify(a)});
50
50
  if (el && el.parentNode) el.parentNode.removeChild(el);
51
51
  return true;
52
52
  })()
53
- `);if(!K?.ok)throw new Q(`上传简历失败: ${K?.error||"未知错误"}`);const L=K.body||{};if(L.code!==0)throw new Q(`上传简历失败: ${L.message||"未知错误"} (code=${L.code})`);const G=L.zpData?.previewUrl,B=L.zpData?.attachmentName||z.name;if(!G)throw new Q(`上传响应缺少 previewUrl: ${JSON.stringify(L.zpData||{}).slice(0,200)}`);y("Saving attachment resume...");const R=await S(J,"/wapi/zpgeek/resume/attachment/save.json",{previewUrl:G,annexType:H["annex-type"]??1}),W=R?.resumeId;if(!W)throw new Q(`保存简历失败,响应缺少 resumeId: ${JSON.stringify(R||{}).slice(0,200)}`);return[{status:"✅ 简历已上传",resume_id:String(W),name:B,detail:`可用 boss sendresume <uid> --resume-id ${W} 发给 Boss`}]}});
53
+ `);if(!i?.ok)throw new o(`上传简历失败: ${i?.error||"未知错误"}`);const r=i.body||{};if(r.code!==0)throw new o(`上传简历失败: ${r.message||"未知错误"} (code=${r.code})`);const d=r.zpData?.previewUrl,y=r.zpData?.attachmentName||e.name;if(!d)throw new o(`上传响应缺少 previewUrl: ${JSON.stringify(r.zpData||{}).slice(0,200)}`);f("Saving attachment resume...");const u=await O(n,"/wapi/zpgeek/resume/attachment/save.json",{previewUrl:d,annexType:t["annex-type"]??1}),p=u?.resumeId;if(!p)throw new o(`保存简历失败,响应缺少 resumeId: ${JSON.stringify(u||{}).slice(0,200)}`);return[{status:"✅ 简历已上传",resume_id:String(p),name:y,detail:`可用 boss sendresume <uid> --resume-id ${p} 发给 Boss`}]}});
@@ -1 +1 @@
1
- import{cli as O,Strategy as T}from"@jackwener/opencli/registry";import{ArgumentError as E}from"@jackwener/opencli/errors";import{requirePage as D,navigateTo as x,bossFetch as A,verbose as l,CITY_CODES as d}from"./utils.js";const K={"不限":"0","在校/应届":"108","在校生":"108","在校":"108","应届生":"102","应届":"102","经验不限":"101","1年以内":"103","1-3年":"104","3-5年":"105","5-10年":"106","10年以上":"107"},v={"不限":"0","初中及以下":"209","中专/中技":"208","高中":"206","大专":"202","本科":"203","硕士":"204","博士":"205"},J={"不限":"0","3K以下":"401","3-5K":"402","5-10K":"403","10-15K":"404","15-20K":"405","20-30K":"406","30-50K":"407","50K以上":"408"},z={"不限":"0","互联网":"100020","电子商务":"100021","游戏":"100024","人工智能":"100901","大数据":"100902","金融":"100101","教育培训":"100200","医疗健康":"100300"},f={"不限":"0","全职":"1901","实习":"1902","兼职":"1903"},B=new Set(Object.values(f));function C(e){if(!e)return"101010100";if(/^\d+$/.test(e))return e;if(d[e])return d[e];for(const[r,s]of Object.entries(d))if(r.includes(e))return s;return"101010100"}function a(e,r){if(!e)return"";if(r[e]!==void 0)return r[e];for(const[s,i]of Object.entries(r))if(s.includes(e))return i;return e}function P(e){if(!e)return"";if(f[e]!==void 0)return f[e];if(B.has(e))return e;throw new E(`Invalid jobType: ${e}`,"Use one of: 全职, 兼职, 实习, 不限")}function _(e){if(e===!0)return"Y";if(e===!1)return"N";return""}O({site:"boss",name:"search",access:"read",description:"BOSS直聘搜索职位(不带关键词时返回为你推荐职位)",domain:"www.zhipin.com",strategy:T.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"query",positional:!0,help:"Search keyword (optional, empty = recommended jobs)"},{name:"city",default:"北京",help:"City name or code (e.g. 杭州, 上海, 101010100)"},{name:"experience",default:"",help:"Experience: 在校生(实习)/应届生(校招)/经验不限/1年以内/1-3年/3-5年/5-10年/10年以上"},{name:"degree",default:"",help:"Degree: 大专/本科/硕士/博士"},{name:"salary",default:"",help:"Salary: 3K以下/3-5K/5-10K/10-15K/15-20K/20-30K/30-50K/50K以上"},{name:"industry",default:"",help:"Industry code or name (e.g. 100020, 互联网)"},{name:"jobType",default:"",help:"Job type: 全职/兼职/实习(不传=不限,混合校招与实习)"},{name:"page",type:"int",default:1,help:"Page number"},{name:"limit",type:"int",default:15,help:"Number of results"}],columns:["name","salary","company","area","experience","degree","skills","boss","bossOnline","security_id","url"],func:async(e,r)=>{D(e);const s=String(r.query??"").trim(),i=C(r.city);l("Navigating to set referrer context...");await x(e,`https://www.zhipin.com/web/geek/job?query=${encodeURIComponent(s)}&city=${i}`);await new Promise((n)=>setTimeout(n,1000));const m=a(r.experience,K),u=a(r.degree,v),y=a(r.salary,J),b=a(r.industry,z),p=P(r.jobType),h=r.limit||15;let c=r.page||1,o=[];const g=new Set;while(o.length<h){if(o.length>0)await new Promise((t)=>setTimeout(t,1000+Math.random()*2000));const n=new URLSearchParams({scene:"1",query:s,city:i,page:String(c),pageSize:"15"});if(m)n.set("experience",m);if(u)n.set("degree",u);if(y)n.set("salary",y);if(b)n.set("industry",b);if(p)n.set("jobType",p);const I=`https://www.zhipin.com/wapi/zpgeek/search/joblist.json?${n.toString()}`;l(`Fetching page ${c}... (current jobs: ${o.length})`);const j=(await A(e,I)).zpData||{},w=j.jobList||[];if(w.length===0)break;let S=0;for(const t of w){if(!t.encryptJobId||g.has(t.encryptJobId))continue;g.add(t.encryptJobId);o.push({name:t.jobName,salary:t.salaryDesc,company:t.brandName,area:[t.cityName,t.areaDistrict,t.businessDistrict].filter(Boolean).join("·"),experience:t.jobExperience,degree:t.jobDegree,skills:(t.skills||[]).join(","),boss:t.bossName+" · "+t.bossTitle,bossOnline:_(t.bossOnline),security_id:t.securityId||"",url:"https://www.zhipin.com/job_detail/"+t.encryptJobId+".html"});S++;if(o.length>=h)break}if(S===0){l(`API returned duplicate page, stopping pagination at ${o.length} items`);break}if(!j.hasMore)break;c++}return o}});export const __test__={EXP_MAP:K,resolveMap:a,resolveJobType:P,formatBossOnline:_};
1
+ import{cli as O,Strategy as T}from"@jackwener/opencli/registry";import{ArgumentError as E}from"@jackwener/opencli/errors";import{requirePage as D,navigateTo as x,bossFetch as v,verbose as l,CITY_CODES as d}from"./utils.js";const S={"不限":"0","在校/应届":"108","在校生":"108","在校":"108","应届生":"102","应届":"102","经验不限":"101","1年以内":"103","1-3年":"104","3-5年":"105","5-10年":"106","10年以上":"107"},A={"不限":"0","初中及以下":"209","中专/中技":"208","高中":"206","大专":"202","本科":"203","硕士":"204","博士":"205"},J={"不限":"0","3K以下":"401","3-5K":"402","5-10K":"403","10-15K":"404","15-20K":"405","20-30K":"406","30-50K":"407","50K以上":"408"},z={"不限":"0","互联网":"100020","电子商务":"100021","游戏":"100024","人工智能":"100901","大数据":"100902","金融":"100101","教育培训":"100200","医疗健康":"100300"},f={"不限":"0","全职":"1901","实习":"1902","兼职":"1903"},C=new Set(Object.values(f));function M(e){if(!e)return"101010100";if(/^\d+$/.test(e))return e;if(d[e])return d[e];for(const[r,s]of Object.entries(d))if(r.includes(e))return s;return"101010100"}function a(e,r){if(!e)return"";if(r[e]!==void 0)return r[e];for(const[s,i]of Object.entries(r))if(s.includes(e))return i;return e}function _(e){if(!e)return"";if(f[e]!==void 0)return f[e];if(C.has(e))return e;throw new E(`Invalid jobType: ${e}`,"Use one of: 全职, 兼职, 实习, 不限")}function P(e){if(e===!0)return"Y";if(e===!1)return"N";return""}O({site:"boss",name:"search",access:"read",description:"BOSS直聘搜索职位(不带关键词时返回为你推荐职位)",domain:"www.zhipin.com",strategy:T.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"query",positional:!0,help:"Search keyword (optional, empty = recommended jobs)"},{name:"city",default:"北京",help:"City name or code (e.g. 杭州, 上海, 101010100)"},{name:"experience",default:"",help:"Experience: 在校生(实习)/应届生(校招)/经验不限/1年以内/1-3年/3-5年/5-10年/10年以上"},{name:"degree",default:"",help:"Degree: 大专/本科/硕士/博士"},{name:"salary",default:"",help:"Salary: 3K以下/3-5K/5-10K/10-15K/15-20K/20-30K/30-50K/50K以上"},{name:"industry",default:"",help:"Industry code or name (e.g. 100020, 互联网)"},{name:"jobType",default:"",help:"Job type: 全职/兼职/实习(不传=不限,混合校招与实习)"},{name:"page",type:"int",default:1,help:"Page number"},{name:"limit",type:"int",default:15,help:"Number of results"}],columns:["name","salary","company","area","experience","degree","skills","boss","bossOnline","security_id","url"],func:async(e,r)=>{D(e);const s=String(r.query??"").trim(),i=M(r.city);l("Navigating to set referrer context...");await x(e,`https://www.zhipin.com/web/geek/job?query=${encodeURIComponent(s)}&city=${i}`);await new Promise((n)=>setTimeout(n,1000));const m=a(r.experience,S),u=a(r.degree,A),y=a(r.salary,J),p=a(r.industry,z),b=_(r.jobType),h=r.limit||15;let c=r.page||1,o=[];const g=new Set;while(o.length<h){if(o.length>0)await new Promise((t)=>setTimeout(t,1000+Math.random()*2000));const n=new URLSearchParams({scene:"1",query:s,city:i,page:String(c),pageSize:"15"});if(m)n.set("experience",m);if(u)n.set("degree",u);if(y)n.set("salary",y);if(p)n.set("industry",p);if(b)n.set("jobType",b);const I=`https://www.zhipin.com/wapi/zpgeek/search/joblist.json?${n.toString()}`;l(`Fetching page ${c}... (current jobs: ${o.length})`);const j=(await v(e,I)).zpData||{},w=j.jobList||[];if(w.length===0)break;let K=0;for(const t of w){if(!t.encryptJobId||g.has(t.encryptJobId))continue;g.add(t.encryptJobId);o.push({name:t.jobName,salary:t.salaryDesc,company:t.brandName,area:[t.cityName,t.areaDistrict,t.businessDistrict].filter(Boolean).join("·"),experience:t.jobExperience,degree:t.jobDegree,skills:(t.skills||[]).join(","),boss:t.bossName+" · "+t.bossTitle,bossOnline:P(t.bossOnline),security_id:t.securityId||"",url:"https://www.zhipin.com/job_detail/"+t.encryptJobId+".html"});K++;if(o.length>=h)break}if(K===0){l(`API returned duplicate page, stopping pagination at ${o.length} items`);break}if(!j.hasMore)break;c++}return o}});export const __test__={EXP_MAP:S,resolveMap:a,resolveJobType:_,formatBossOnline:P};
package/clis/boss/send.js CHANGED
@@ -1 +1 @@
1
- import{cli as X,Strategy as Y}from"@jackwener/opencli/registry";import{EmptyResultError as Z,selectorError as H}from"@jackwener/opencli/errors";import{requirePage as _,navigateToChat as $,findFriendByUid as q,clickCandidateInList as F,typeAndSendMessage as K,geekOpenChat as L,resolveGeekBossId as N,navigateToGeekChat as O,isRecruiterSide as P,verbose as B}from"./utils.js";async function Q(x,z){await O(x);const D=await N(x,z.uid);B(`Opening geek chat with boss ${D}...`);await L(x,D);if(!await K(x,z.text))throw H("消息输入框","聊天页面 UI 可能已改变,或该会话不存在");await x.wait({time:1});return[{status:"✅ 发送成功",detail:`已向 Boss ${D} 发送: ${z.text}`}]}async function V(x,z){await $(x,3);const D=await q(x,z.uid,{maxPages:5});if(!D)throw new Z("boss candidate search","请确认 uid 是否正确");const J=D.uid,W=D.name||"候选人";if(!await F(x,J))throw H("聊天列表中的用户","请确认聊天列表中有此人");await x.wait({time:2});if(!await K(x,z.text))throw H("消息输入框","聊天页面 UI 可能已改变");await x.wait({time:1});return[{status:"✅ 发送成功",detail:`已向 ${W} 发送: ${z.text}`}]}X({site:"boss",name:"send",access:"write",description:"BOSS直聘发送聊天消息(求职端回复 Boss / 招聘端回复候选人)",domain:"www.zhipin.com",strategy:Y.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",positional:!0,required:!0,help:"对方 uid(从 boss chatlist 拿)"},{name:"text",fromFile:!0,required:!0,positional:!0,help:"Message text to send"},{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"}],columns:["status","detail"],func:async(x,z)=>{_(x);const D=z.side||"auto";if(D==="geek")return Q(x,z);if(D==="boss")return V(x,z);return await P(x)?V(x,z):Q(x,z)}});
1
+ import{cli as u,Strategy as c}from"@jackwener/opencli/registry";import{EmptyResultError as m,selectorError as s}from"@jackwener/opencli/errors";import{requirePage as l,navigateToChat as f,findFriendByUid as w,clickCandidateInList as h,typeAndSendMessage as o,geekOpenChat as b,resolveGeekBossId as y,navigateToGeekChat as x,isRecruiterSide as I,verbose as B}from"./utils.js";async function a(t,e){await x(t);const i=await y(t,e.uid);B(`Opening geek chat with boss ${i}...`);await b(t,i);if(!await o(t,e.text))throw s("消息输入框","聊天页面 UI 可能已改变,或该会话不存在");await t.wait({time:1});return[{status:"✅ 发送成功",detail:`已向 Boss ${i} 发送: ${e.text}`}]}async function r(t,e){await f(t,3);const i=await w(t,e.uid,{maxPages:5});if(!i)throw new m("boss candidate search","请确认 uid 是否正确");const n=i.uid,d=i.name||"候选人";if(!await h(t,n))throw s("聊天列表中的用户","请确认聊天列表中有此人");await t.wait({time:2});if(!await o(t,e.text))throw s("消息输入框","聊天页面 UI 可能已改变");await t.wait({time:1});return[{status:"✅ 发送成功",detail:`已向 ${d} 发送: ${e.text}`}]}u({site:"boss",name:"send",access:"write",description:"BOSS直聘发送聊天消息(求职端回复 Boss / 招聘端回复候选人)",domain:"www.zhipin.com",strategy:c.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",positional:!0,required:!0,help:"对方 uid(从 boss chatlist 拿)"},{name:"text",fromFile:!0,required:!0,positional:!0,help:"Message text to send"},{name:"side",default:"auto",choices:["auto","geek","boss"],help:"Identity side: auto (default), geek (job-seeker), boss (recruiter)"}],columns:["status","detail"],func:async(t,e)=>{l(t);const i=e.side||"auto";if(i==="geek")return a(t,e);if(i==="boss")return r(t,e);return await I(t)?r(t,e):a(t,e)}});
@@ -1 +1 @@
1
- import{cli as a,Strategy as d}from"@jackwener/opencli/registry";import{CommandExecutionError as u}from"@jackwener/opencli/errors";import{requirePage as n,navigateToGeekChat as m,geekPost as c,fetchGeekBossData as y,resolveGeekBossId as p,resolveGeekResumeId as I,verbose as l}from"./utils.js";a({site:"boss",name:"sendresume",access:"write",description:"BOSS直聘向 Boss 发送附件简历(求职端)",domain:"www.zhipin.com",strategy:d.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",positional:!0,required:!0,help:"Boss 的 uid(数字 friendId 或 encryptFriendId,从 boss chatlist --side geek 拿)"},{name:"resume-id",default:"",help:"encryptResumeId(从 boss resumelist 拿)。账号只有一份时可不传"}],columns:["status","detail"],func:async(e,i)=>{n(e);await m(e);const s=await p(e,i.uid),t=await y(e,s),o=t.securityId||"";if(!o)throw new u(`无法获取 securityId (uid=${s}),该会话可能已失效`);const r=await I(e,i["resume-id"]);l(`Sending resume ${r} to boss ${s}...`);await c(e,"/wapi/zpchat/exchange/request",{type:3,bossId:s,securityId:o,mid:"",encryptResumeId:r});return[{status:"✅ 简历已发送",detail:`已向 ${t.name||t.bossName||s} 发送附件简历 ${r}`}]}});
1
+ import{cli as a,Strategy as d}from"@jackwener/opencli/registry";import{CommandExecutionError as n}from"@jackwener/opencli/errors";import{requirePage as u,navigateToGeekChat as m,geekPost as c,fetchGeekBossData as l,resolveGeekBossId as w,resolveGeekResumeId as I,verbose as f}from"./utils.js";a({site:"boss",name:"sendresume",access:"write",description:"BOSS直聘向 Boss 发送附件简历(求职端)",domain:"www.zhipin.com",strategy:d.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"uid",positional:!0,required:!0,help:"Boss 的 uid(数字 friendId 或 encryptFriendId,从 boss chatlist --side geek 拿)"},{name:"resume-id",default:"",help:"encryptResumeId(从 boss resumelist 拿)。账号只有一份时可不传"}],columns:["status","detail"],func:async(e,i)=>{u(e);await m(e);const s=await w(e,i.uid),t=await l(e,s),o=t.securityId||"";if(!o)throw new n(`无法获取 securityId (uid=${s}),该会话可能已失效`);const r=await I(e,i["resume-id"]);f(`Sending resume ${r} to boss ${s}...`);await c(e,"/wapi/zpchat/exchange/request",{type:3,bossId:s,securityId:o,mid:"",encryptResumeId:r});return[{status:"✅ 简历已发送",detail:`已向 ${t.name||t.bossName||s} 发送附件简历 ${r}`}]}});
@@ -1 +1 @@
1
- import{cli as V,Strategy as W}from"@jackwener/opencli/registry";import{requirePage as X,navigateToChat as Y,bossFetch as O,fetchFriendList as Z,verbose as _}from"./utils.js";V({site:"boss",name:"stats",access:"read",description:"BOSS直聘职位数据统计",domain:"www.zhipin.com",strategy:W.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"job-id",default:"",help:"Encrypted job ID (show all if empty)"}],columns:["job_name","salary","city","status","total_chats","encrypt_job_id"],func:async(z,Q)=>{X(z);_("Fetching job statistics...");const B=Q["job-id"]||"";await Y(z);const R=await O(z,"https://www.zhipin.com/wapi/zpjob/job/chatted/jobList"),U=(await O(z,"https://www.zhipin.com/wapi/zpchat/chatHelper/statistics",{allowNonZero:!0})).zpData?.totalFriendCount||0;let K=[];try{K=await Z(z)}catch{}const E={};for(const x of K){const M=x.jobName||"unknown";E[M]=(E[M]||0)+1}let A=R.zpData||[];if(B)A=A.filter((x)=>x.encryptJobId===B);const H=A.map((x)=>({job_name:x.jobName||"",salary:x.salaryDesc||"",city:x.address||"",status:x.jobOnlineStatus===1?"在线":"已关闭",total_chats:String(E[x.jobName]||0),encrypt_job_id:x.encryptJobId||""}));if(!B&&H.length>0)H.push({job_name:"--- 总计 ---",salary:"",city:"",status:`${A.length} 个职位`,total_chats:String(U),encrypt_job_id:""});return H}});
1
+ import{cli as p,Strategy as d}from"@jackwener/opencli/registry";import{requirePage as m,navigateToChat as w,bossFetch as r,fetchFriendList as y,verbose as f}from"./utils.js";p({site:"boss",name:"stats",access:"read",description:"BOSS直聘职位数据统计",domain:"www.zhipin.com",strategy:d.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"job-id",default:"",help:"Encrypted job ID (show all if empty)"}],columns:["job_name","salary","city","status","total_chats","encrypt_job_id"],func:async(a,b)=>{m(a);f("Fetching job statistics...");const s=b["job-id"]||"";await w(a);const l=await r(a,"https://www.zhipin.com/wapi/zpjob/job/chatted/jobList"),h=(await r(a,"https://www.zhipin.com/wapi/zpchat/chatHelper/statistics",{allowNonZero:!0})).zpData?.totalFriendCount||0;let n=[];try{n=await y(a)}catch{}const e={};for(const t of n){const c=t.jobName||"unknown";e[c]=(e[c]||0)+1}let o=l.zpData||[];if(s)o=o.filter((t)=>t.encryptJobId===s);const i=o.map((t)=>({job_name:t.jobName||"",salary:t.salaryDesc||"",city:t.address||"",status:t.jobOnlineStatus===1?"在线":"已关闭",total_chats:String(e[t.jobName]||0),encrypt_job_id:t.encryptJobId||""}));if(!s&&i.length>0)i.push({job_name:"--- 总计 ---",salary:"",city:"",status:`${o.length} 个职位`,total_chats:String(h),encrypt_job_id:""});return i}});
@@ -1 +1 @@
1
- import{cli as $,Strategy as q}from"@jackwener/opencli/registry";import{EmptyResultError as W}from"@jackwener/opencli/errors";import{requirePage as F,navigateToGeekChat as A,readEncryptSystemId as B,fetchGeekFriendLabelList as H,fetchGeekLastMsgs as R,fetchGeekUserInfo as j,readPositiveInteger as v,verbose as C}from"./utils.js";const X=20;$({site:"boss",name:"unread",access:"read",description:"BOSS直聘查看未回复的消息(求职端,Boss 发来但我还没回)",domain:"www.zhipin.com",strategy:q.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"limit",type:"int",default:50,help:"How many recent conversations to scan"}],columns:["name","company","job","last_msg","last_time","uid"],func:async(J,Y)=>{F(J);const Z=v(Y.limit,"unread --limit",50,200);C("Scanning for unreplied conversations...");await A(J);const _=await B(J),K=(await H(J,{encryptSystemId:_})).slice(0,Z);if(K.length===0)throw new W("boss unread","暂无沟通记录。");const O=(await j(J)).userId,Q=[];for(let x=0;x<K.length;x+=X){const z=K.slice(x,x+X).map((D)=>D.friendId).filter(Boolean);Q.push(...await R(J,z))}const V=new Map;for(const x of Q){const z=x.lastMsgInfo||{},D=z.fromId===O?z.toId:z.fromId;if(D)V.set(String(D),x)}const N=[];for(const x of K){const z=V.get(String(x.friendId)),D=z?.lastMsgInfo||{};if(!D.fromId||String(D.fromId)===String(O))continue;N.push({name:x.name||"",company:x.brandName||"",job:x.jobName||"",last_msg:D.showText||"",last_time:z.lastTime||"",uid:String(x.friendId)})}if(N.length===0)throw new W("boss unread","没有未回复的消息。");return N}});
1
+ import{cli as u,Strategy as w}from"@jackwener/opencli/registry";import{EmptyResultError as c}from"@jackwener/opencli/errors";import{requirePage as I,navigateToGeekChat as h,readEncryptSystemId as y,fetchGeekFriendLabelList as p,fetchGeekLastMsgs as b,fetchGeekUserInfo as S,readPositiveInteger as v,verbose as B}from"./utils.js";const f=20;u({site:"boss",name:"unread",access:"read",description:"BOSS直聘查看未回复的消息(求职端,Boss 发来但我还没回)",domain:"www.zhipin.com",strategy:w.COOKIE,navigateBefore:!1,browser:!0,args:[{name:"limit",type:"int",default:50,help:"How many recent conversations to scan"}],columns:["name","company","job","last_msg","last_time","uid"],func:async(s,d)=>{I(s);const l=v(d.limit,"unread --limit",50,200);B("Scanning for unreplied conversations...");await h(s);const g=await y(s),o=(await p(s,{encryptSystemId:g})).slice(0,l);if(o.length===0)throw new c("boss unread","暂无沟通记录。");const i=(await S(s)).userId,a=[];for(let e=0;e<o.length;e+=f){const t=o.slice(e,e+f).map((n)=>n.friendId).filter(Boolean);a.push(...await b(s,t))}const m=new Map;for(const e of a){const t=e.lastMsgInfo||{},n=t.fromId===i?t.toId:t.fromId;if(n)m.set(String(n),e)}const r=[];for(const e of o){const t=m.get(String(e.friendId)),n=t?.lastMsgInfo||{};if(!n.fromId||String(n.fromId)===String(i))continue;r.push({name:e.name||"",company:e.brandName||"",job:e.jobName||"",last_msg:n.showText||"",last_time:t.lastTime||"",uid:String(e.friendId)})}if(r.length===0)throw new c("boss unread","没有未回复的消息。");return r}});
@@ -1,24 +1,24 @@
1
- import{ArgumentError as P,AuthRequiredError as L,CommandExecutionError as z,EmptyResultError as F}from"@jackwener/opencli/errors";const K="www.zhipin.com",v=`https://${K}/web/chat/index`,G=new Set([7,37]),T="Cookie 已过期!请在当前 Chrome 浏览器中重新登录 BOSS 直聘。",B="该命令仅支持招聘端(BOSS 端)账号,请使用招聘者账号登录后重试。",N=15000;export function requirePage(Q){if(!Q)throw new z("Browser page required")}export function readPositiveInteger(Q,V,W,J){const $=Q===void 0||Q===null||Q===""?W:Number(Q);if(!Number.isInteger($)||$<1)throw new P(`boss ${V} must be a positive integer`);if(J!==void 0&&$>J)throw new P(`boss ${V} must be <= ${J}`);return $}export function readRequiredString(Q,V){const W=String(Q??"").trim();if(!W)throw new P(`boss ${V} cannot be empty`);return W}export async function navigateToChat(Q,V=2){await Q.goto(v);await Q.wait({time:V})}export async function navigateTo(Q,V,W=1){await Q.goto(V);await Q.wait({time:W})}export function checkAuth(Q){if(G.has(Q.code))throw new L(K,T)}function k(Q){if(Q.code===IDENTITY_MISMATCH_CODE)throw new L(K,B)}export function assertOk(Q,V){if(!Q||typeof Q!=="object")throw new z(`${V?`${V}: `:""}Boss API returned malformed response`);if(Q.code===0)return;checkAuth(Q);k(Q);const W=V?`${V}: `:"";throw new z(`${W}${Q.message||"Unknown error"} (code=${Q.code})`)}export async function bossFetch(Q,V,W={}){const J=W.method??"GET",$=W.timeout??N,j=W.body??null,X=`
1
+ import{ArgumentError as f,AuthRequiredError as p,CommandExecutionError as u,EmptyResultError as m}from"@jackwener/opencli/errors";const d="www.zhipin.com",w=`https://${d}/web/chat/index`,h=new Set([7,37]),g="Cookie 已过期!请在当前 Chrome 浏览器中重新登录 BOSS 直聘。",S="该命令仅支持招聘端(BOSS 端)账号,请使用招聘者账号登录后重试。",b=15000;export function requirePage(e){if(!e)throw new u("Browser page required")}export function readPositiveInteger(e,t,n,o){const r=e===void 0||e===null||e===""?n:Number(e);if(!Number.isInteger(r)||r<1)throw new f(`boss ${t} must be a positive integer`);if(o!==void 0&&r>o)throw new f(`boss ${t} must be <= ${o}`);return r}export function readRequiredString(e,t){const n=String(e??"").trim();if(!n)throw new f(`boss ${t} cannot be empty`);return n}export async function navigateToChat(e,t=2){await e.goto(w);await e.wait({time:t})}export async function navigateTo(e,t,n=1){await e.goto(t);await e.wait({time:n})}export function checkAuth(e){if(h.has(e.code))throw new p(d,g)}function I(e){if(e.code===IDENTITY_MISMATCH_CODE)throw new p(d,S)}export function assertOk(e,t){if(!e||typeof e!=="object")throw new u(`${t?`${t}: `:""}Boss API returned malformed response`);if(e.code===0)return;checkAuth(e);I(e);const n=t?`${t}: `:"";throw new u(`${n}${e.message||"Unknown error"} (code=${e.code})`)}export async function bossFetch(e,t,n={}){const o=n.method??"GET",r=n.timeout??b,s=n.body??null,i=`
2
2
  async () => {
3
3
  return new Promise((resolve, reject) => {
4
4
  const xhr = new XMLHttpRequest();
5
- xhr.open(${JSON.stringify(J)}, ${JSON.stringify(V)}, true);
5
+ xhr.open(${JSON.stringify(o)}, ${JSON.stringify(t)}, true);
6
6
  xhr.withCredentials = true;
7
- xhr.timeout = ${$};
7
+ xhr.timeout = ${r};
8
8
  xhr.setRequestHeader('Accept', 'application/json');
9
- ${J==="POST"?"xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');":""}
9
+ ${o==="POST"?"xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');":""}
10
10
  xhr.onload = () => {
11
11
  try { resolve(JSON.parse(xhr.responseText)); }
12
12
  catch(e) { reject(new Error('JSON parse failed: ' + xhr.responseText.substring(0, 200))); }
13
13
  };
14
14
  xhr.onerror = () => reject(new Error('Network Error'));
15
15
  xhr.ontimeout = () => reject(new Error('Timeout'));
16
- xhr.send(${j?JSON.stringify(j):"null"});
16
+ xhr.send(${s?JSON.stringify(s):"null"});
17
17
  });
18
18
  }
19
- `;let Z;try{Z=await Q.evaluate(X)}catch(Y){if(Y instanceof L||Y instanceof z)throw Y;const H=Y instanceof Error?Y.message:String(Y);throw new z(`Boss API request failed: ${H}`)}if(!Z||typeof Z!=="object")throw new z("Boss API returned malformed response");if(!W.allowNonZero&&Z.code!==0)assertOk(Z);return Z}export async function fetchFriendList(Q,V={}){const W=V.pageNum??1,J=V.jobId??"0",$=`https://${K}/wapi/zprelation/friend/getBossFriendListV2.json?page=${W}&status=0&jobId=${J}`,j=await bossFetch(Q,$,{allowNonZero:V.allowNonZero});if(V.allowNonZero&&j.code!==0)return j;const X=j.zpData?.friendList;if(!Array.isArray(X))throw new z("Boss friend list response did not include zpData.friendList");return X}export async function fetchRecommendList(Q){const V=`https://${K}/wapi/zprelation/friend/greetRecSortList`,J=(await bossFetch(Q,V)).zpData?.friendList;if(!Array.isArray(J))throw new z("Boss recommend response did not include zpData.friendList");return J}export async function findFriendByUid(Q,V,W={}){const J=W.maxPages??1,$=W.checkGreetList??!1;for(let j=1;j<=J;j++){const X=await fetchFriendList(Q,{pageNum:j,allowNonZero:W.allowNonZero});if(W.allowNonZero&&!Array.isArray(X))return{friend:null,code:X.code};const Z=Array.isArray(X)?X:[],Y=Z.find((H)=>H.encryptUid===V);if(Y)return W.allowNonZero?{friend:Y,code:0}:Y;if(Z.length===0)break}if($){const X=(await fetchRecommendList(Q)).find((Z)=>Z.encryptUid===V);if(X)return W.allowNonZero?{friend:X,code:0}:X}return W.allowNonZero?{friend:null,code:0}:null}export async function clickCandidateInList(Q,V){const W=String(V).replace(/[^0-9]/g,"");return(await Q.evaluate(`
19
+ `;let c;try{c=await e.evaluate(i)}catch(a){if(a instanceof p||a instanceof u)throw a;const l=a instanceof Error?a.message:String(a);throw new u(`Boss API request failed: ${l}`)}if(!c||typeof c!=="object")throw new u("Boss API returned malformed response");if(!n.allowNonZero&&c.code!==0)assertOk(c);return c}export async function fetchFriendList(e,t={}){const n=t.pageNum??1,o=t.jobId??"0",r=`https://${d}/wapi/zprelation/friend/getBossFriendListV2.json?page=${n}&status=0&jobId=${o}`,s=await bossFetch(e,r,{allowNonZero:t.allowNonZero});if(t.allowNonZero&&s.code!==0)return s;const i=s.zpData?.friendList;if(!Array.isArray(i))throw new u("Boss friend list response did not include zpData.friendList");return i}export async function fetchRecommendList(e){const t=`https://${d}/wapi/zprelation/friend/greetRecSortList`,o=(await bossFetch(e,t)).zpData?.friendList;if(!Array.isArray(o))throw new u("Boss recommend response did not include zpData.friendList");return o}export async function findFriendByUid(e,t,n={}){const o=n.maxPages??1,r=n.checkGreetList??!1;for(let s=1;s<=o;s++){const i=await fetchFriendList(e,{pageNum:s,allowNonZero:n.allowNonZero});if(n.allowNonZero&&!Array.isArray(i))return{friend:null,code:i.code};const c=Array.isArray(i)?i:[],a=c.find((l)=>l.encryptUid===t);if(a)return n.allowNonZero?{friend:a,code:0}:a;if(c.length===0)break}if(r){const i=(await fetchRecommendList(e)).find((c)=>c.encryptUid===t);if(i)return n.allowNonZero?{friend:i,code:0}:i}return n.allowNonZero?{friend:null,code:0}:null}export async function clickCandidateInList(e,t){const n=String(t).replace(/[^0-9]/g,"");return(await e.evaluate(`
20
20
  async () => {
21
- const uid = ${JSON.stringify(W)};
21
+ const uid = ${JSON.stringify(n)};
22
22
  const item = document.querySelector('#_' + uid + '-0') || document.querySelector('[id^="_' + uid + '"]');
23
23
  if (item) {
24
24
  item.click();
@@ -33,7 +33,7 @@ import{ArgumentError as P,AuthRequiredError as L,CommandExecutionError as z,Empt
33
33
  }
34
34
  return { clicked: false };
35
35
  }
36
- `)).clicked}export async function typeAndSendMessage(Q,V){if(!(await Q.evaluate(`
36
+ `)).clicked}export async function typeAndSendMessage(e,t){if(!(await e.evaluate(`
37
37
  async () => {
38
38
  const selectors = [
39
39
  '.chat-editor [contenteditable="true"]',
@@ -48,12 +48,12 @@ import{ArgumentError as P,AuthRequiredError as L,CommandExecutionError as z,Empt
48
48
  if (el && el.offsetParent !== null) {
49
49
  el.focus();
50
50
  if (el.tagName === 'TEXTAREA' || el.tagName === 'INPUT') {
51
- el.value = ${JSON.stringify(V)};
51
+ el.value = ${JSON.stringify(t)};
52
52
  el.dispatchEvent(new Event('input', { bubbles: true }));
53
53
  } else {
54
54
  el.textContent = '';
55
55
  el.focus();
56
- document.execCommand('insertText', false, ${JSON.stringify(V)});
56
+ document.execCommand('insertText', false, ${JSON.stringify(t)});
57
57
  el.dispatchEvent(new Event('input', { bubbles: true }));
58
58
  }
59
59
  return { found: true };
@@ -61,7 +61,7 @@ import{ArgumentError as P,AuthRequiredError as L,CommandExecutionError as z,Empt
61
61
  }
62
62
  return { found: false };
63
63
  }
64
- `)).found)return!1;await Q.wait({time:0.5});if(!(await Q.evaluate(`
64
+ `)).found)return!1;await e.wait({time:0.5});if(!(await e.evaluate(`
65
65
  async () => {
66
66
  const btn = document.querySelector('.conversation-editor .submit')
67
67
  || document.querySelector('.submit-content .submit')
@@ -72,7 +72,7 @@ import{ArgumentError as P,AuthRequiredError as L,CommandExecutionError as z,Empt
72
72
  }
73
73
  return { clicked: false };
74
74
  }
75
- `)).clicked)await Q.pressKey("Enter");return!0}export function verbose(Q){if(process.env.OPENCLI_VERBOSE)console.error(`[ppcli:boss] ${Q}`)}export const IDENTITY_MISMATCH_CODE=24;const q=`https://${K}/web/geek/chat`;export async function navigateToGeekChat(Q,V=2){await Q.goto(q);await Q.wait({time:V})}export async function readEncryptSystemId(Q){return await Q.evaluate(`
75
+ `)).clicked)await e.pressKey("Enter");return!0}export function verbose(e){if(process.env.OPENCLI_VERBOSE)console.error(`[ppcli:boss] ${e}`)}export const IDENTITY_MISMATCH_CODE=24;const y=`https://${d}/web/geek/chat`;export async function navigateToGeekChat(e,t=2){await e.goto(y);await e.wait({time:t})}export async function readEncryptSystemId(e){return await e.evaluate(`
76
76
  (() => {
77
77
  // 1. Vue app state / Pinia / $route.query
78
78
  // The chat component reads encryptSystemId from the app runtime to build
@@ -158,4 +158,4 @@ import{ArgumentError as P,AuthRequiredError as L,CommandExecutionError as z,Empt
158
158
  } catch (_) {}
159
159
  return '';
160
160
  })()
161
- `)||""}export async function fetchGeekFriendLabelList(Q,V={}){const W=V.labelId??0,J=V.encryptSystemId??"",$=`https://${K}/wapi/zprelation/friend/geekFilterByLabel?labelId=${W}&encryptSystemId=${encodeURIComponent(J)}`,j=await bossFetch(Q,$,{allowNonZero:V.allowNonZero});if(V.allowNonZero&&j.code!==0)return j;const X=j.zpData?.friendList;if(!Array.isArray(X))throw new z("Boss geek chat list response did not include zpData.friendList");return X}export async function fetchGeekFriendInfoList(Q,V=[]){if(!V.length)return[];const W=50,J=[];for(let $=0;$<V.length;$+=W){const X=`friendIds=${V.slice($,$+W).map(String).join(",")}`,Y=(await bossFetch(Q,`https://${K}/wapi/zprelation/friend/getGeekFriendList.json`,{method:"POST",body:X})).zpData?.result;if(!Array.isArray(Y))throw new z("Boss geek friend enrichment response did not include zpData.result");J.push(...Y)}return J}export async function findGeekFriendByUid(Q,V,W={}){const $=(await fetchGeekFriendLabelList(Q,{encryptSystemId:W.encryptSystemId})).find((X)=>X.encryptFriendId===V||String(X.uid)===String(V)||String(X.friendId)===String(V));if(!$)return null;const j=await fetchGeekFriendInfoList(Q,[$.friendId]);return{...$,...j[0]||{}}}export async function fetchGeekHistoryMsg(Q,V,W={}){const J=W.page??1,$=V.uid,j=encodeURIComponent(V.securityId||""),X=`https://${K}/wapi/zpchat/geek/historyMsg?bossId=${$}&securityId=${j}&page=${J}&c=20&src=0`,Z=await bossFetch(Q,X),Y=Z.zpData?.messages??Z.zpData?.historyMsgList;if(!Array.isArray(Y))throw new z("Boss geek history response did not include a message list");if(Y.length===0)throw new F("boss chatmsg","Boss returned no messages for this chat.");return Y}const M=`https://${K}/web/geek/job`;export async function navigateToGeekJob(Q,V=2){await Q.goto(M);await Q.wait({time:V})}export async function geekGet(Q,V,W={},J={}){const $=new URLSearchParams;for(const[Y,H]of Object.entries(W)){if(H===void 0||H===null||H==="")continue;$.set(Y,String(H))}const j=$.toString(),X=`https://${K}${V}${j?`?${j}`:""}`,Z=await bossFetch(Q,X,J);if(J.allowNonZero&&Z.code!==0)return Z;return Z.zpData??{}}export async function geekPost(Q,V,W={},J={}){const $=new URLSearchParams;for(const[X,Z]of Object.entries(W)){if(Z===void 0||Z===null)continue;$.set(X,String(Z))}const j=await bossFetch(Q,`https://${K}${V}`,{...J,method:"POST",body:$.toString()});if(J.allowNonZero&&j.code!==0)return j;return j.zpData??{}}export async function fetchGeekUserInfo(Q){return geekGet(Q,"/wapi/zpuser/wap/getUserInfo.json")}export async function fetchGeekBossData(Q,V){const W=await geekGet(Q,"/wapi/zpchat/geek/getBossData",{bossId:V});return W?.data??W??{}}export async function fetchGeekLastMsgs(Q,V=[]){if(!V.length)return[];const W=await geekGet(Q,"/wapi/zpchat/geek/userLastMsg",{friendIds:V.map(String).join(",")});return Array.isArray(W)?W:W?.result??[]}export async function fetchGeekAttachmentResumes(Q){return(await geekGet(Q,"/wapi/zpgeek/resume/attachment/checkbox.json"))?.resumeList??[]}export async function resolveGeekResumeId(Q,V){const W=await fetchGeekAttachmentResumes(Q);if(V){if(!W.find((j)=>String(j.resumeId)===String(V))){const j=W.map((X)=>X.resumeId||"?").join(", ")||"(空)";throw new P(`指定的 --resume-id=${V} 不在账号简历列表 [${j}] 中`)}return String(V)}if(W.length===0)throw new F("boss resumelist","账号还没有绑定附件简历,请先用 boss resumeupload 上传,或在 BOSS 直聘 App 里上传。");if(W.length===1){const $=W[0].resumeId;if(!$)throw new z("唯一附件简历缺失 resumeId 字段");return String($)}const J=W.map(($)=>`${$.resumeId}(${$.showName||"未命名"})`).join(", ");throw new P(`账号绑定了 ${W.length} 份附件简历,请用 --resume-id 指定其中一份:${J}`)}export async function resolveGeekBoss(Q,V){const W=String(V??"").trim();if(!W)throw new P("boss id cannot be empty");if(/^\d+$/.test(W))return{id:W,friend:null};const J=await findGeekFriendByUid(Q,W);if(!J)throw new F("boss chatlist",`未在沟通列表中找到 ${W},请先用 boss chatlist --side geek 查 uid。`);const $=J.uid??J.friendId;if(!$)throw new z("沟通列表条目缺失 uid / friendId");return{id:String($),friend:J}}export async function resolveGeekBossId(Q,V){return(await resolveGeekBoss(Q,V)).id}export async function geekAddFriend(Q,V,W=""){return geekGet(Q,"/wapi/zpgeek/friend/add.json",{securityId:V,lid:W})}export async function geekOpenChat(Q,V,W=3){await Q.goto(`${q}?id=${encodeURIComponent(String(V))}`);await Q.wait({time:W})}export const CITY_CODES={"全国":"100010000","北京":"101010100","上海":"101020100","广州":"101280100","深圳":"101280600","杭州":"101210100","成都":"101270100","南京":"101190100","武汉":"101200100","西安":"101110100","苏州":"101190400","长沙":"101250100","天津":"101030100","重庆":"101040100","郑州":"101180100","东莞":"101281600","青岛":"101120200","合肥":"101220100","佛山":"101280800","宁波":"101210400","厦门":"101230200","大连":"101070200","珠海":"101280700","无锡":"101190200","济南":"101120100","福州":"101230100","昆明":"101290100","哈尔滨":"101050100","沈阳":"101070100","石家庄":"101090100","贵阳":"101260100","南宁":"101300100","太原":"101100100","海口":"101310100","兰州":"101160100","乌鲁木齐":"101130100","长春":"101060100","南昌":"101240100","常州":"101191100","温州":"101210700","嘉兴":"101210300","徐州":"101190800","香港":"101320100"};export async function isRecruiterSide(Q){await navigateToChat(Q);const V=await bossFetch(Q,`https://${K}/wapi/zprelation/friend/getBossFriendListV2.json?page=1&status=0&jobId=0`,{allowNonZero:!0});if(V.code===0)return!0;if(V.code===IDENTITY_MISMATCH_CODE)return!1;assertOk(V,"boss 身份探测");return!1}
161
+ `)||""}export async function fetchGeekFriendLabelList(e,t={}){const n=t.labelId??0,o=t.encryptSystemId??"",r=`https://${d}/wapi/zprelation/friend/geekFilterByLabel?labelId=${n}&encryptSystemId=${encodeURIComponent(o)}`,s=await bossFetch(e,r,{allowNonZero:t.allowNonZero});if(t.allowNonZero&&s.code!==0)return s;const i=s.zpData?.friendList;if(!Array.isArray(i))throw new u("Boss geek chat list response did not include zpData.friendList");return i}export async function fetchGeekFriendInfoList(e,t=[]){if(!t.length)return[];const n=50,o=[];for(let r=0;r<t.length;r+=n){const i=`friendIds=${t.slice(r,r+n).map(String).join(",")}`,a=(await bossFetch(e,`https://${d}/wapi/zprelation/friend/getGeekFriendList.json`,{method:"POST",body:i})).zpData?.result;if(!Array.isArray(a))throw new u("Boss geek friend enrichment response did not include zpData.result");o.push(...a)}return o}export async function findGeekFriendByUid(e,t,n={}){const r=(await fetchGeekFriendLabelList(e,{encryptSystemId:n.encryptSystemId})).find((i)=>i.encryptFriendId===t||String(i.uid)===String(t)||String(i.friendId)===String(t));if(!r)return null;const s=await fetchGeekFriendInfoList(e,[r.friendId]);return{...r,...s[0]||{}}}export async function fetchGeekHistoryMsg(e,t,n={}){const o=n.page??1,r=t.uid,s=encodeURIComponent(t.securityId||""),i=`https://${d}/wapi/zpchat/geek/historyMsg?bossId=${r}&securityId=${s}&page=${o}&c=20&src=0`,c=await bossFetch(e,i),a=c.zpData?.messages??c.zpData?.historyMsgList;if(!Array.isArray(a))throw new u("Boss geek history response did not include a message list");if(a.length===0)throw new m("boss chatmsg","Boss returned no messages for this chat.");return a}const k=`https://${d}/web/geek/job`;export async function navigateToGeekJob(e,t=2){await e.goto(k);await e.wait({time:t})}export async function geekGet(e,t,n={},o={}){const r=new URLSearchParams;for(const[a,l]of Object.entries(n)){if(l===void 0||l===null||l==="")continue;r.set(a,String(l))}const s=r.toString(),i=`https://${d}${t}${s?`?${s}`:""}`,c=await bossFetch(e,i,o);if(o.allowNonZero&&c.code!==0)return c;return c.zpData??{}}export async function geekPost(e,t,n={},o={}){const r=new URLSearchParams;for(const[i,c]of Object.entries(n)){if(c===void 0||c===null)continue;r.set(i,String(c))}const s=await bossFetch(e,`https://${d}${t}`,{...o,method:"POST",body:r.toString()});if(o.allowNonZero&&s.code!==0)return s;return s.zpData??{}}export async function fetchGeekUserInfo(e){return geekGet(e,"/wapi/zpuser/wap/getUserInfo.json")}export async function fetchGeekBossData(e,t){const n=await geekGet(e,"/wapi/zpchat/geek/getBossData",{bossId:t});return n?.data??n??{}}export async function fetchGeekLastMsgs(e,t=[]){if(!t.length)return[];const n=await geekGet(e,"/wapi/zpchat/geek/userLastMsg",{friendIds:t.map(String).join(",")});return Array.isArray(n)?n:n?.result??[]}export async function fetchGeekAttachmentResumes(e){return(await geekGet(e,"/wapi/zpgeek/resume/attachment/checkbox.json"))?.resumeList??[]}export async function resolveGeekResumeId(e,t){const n=await fetchGeekAttachmentResumes(e);if(t){if(!n.find((s)=>String(s.resumeId)===String(t))){const s=n.map((i)=>i.resumeId||"?").join(", ")||"(空)";throw new f(`指定的 --resume-id=${t} 不在账号简历列表 [${s}] 中`)}return String(t)}if(n.length===0)throw new m("boss resumelist","账号还没有绑定附件简历,请先用 boss resumeupload 上传,或在 BOSS 直聘 App 里上传。");if(n.length===1){const r=n[0].resumeId;if(!r)throw new u("唯一附件简历缺失 resumeId 字段");return String(r)}const o=n.map((r)=>`${r.resumeId}(${r.showName||"未命名"})`).join(", ");throw new f(`账号绑定了 ${n.length} 份附件简历,请用 --resume-id 指定其中一份:${o}`)}export async function resolveGeekBoss(e,t){const n=String(t??"").trim();if(!n)throw new f("boss id cannot be empty");if(/^\d+$/.test(n))return{id:n,friend:null};const o=await findGeekFriendByUid(e,n);if(!o)throw new m("boss chatlist",`未在沟通列表中找到 ${n},请先用 boss chatlist --side geek 查 uid。`);const r=o.uid??o.friendId;if(!r)throw new u("沟通列表条目缺失 uid / friendId");return{id:String(r),friend:o}}export async function resolveGeekBossId(e,t){return(await resolveGeekBoss(e,t)).id}export async function geekAddFriend(e,t,n=""){return geekGet(e,"/wapi/zpgeek/friend/add.json",{securityId:t,lid:n})}export async function geekOpenChat(e,t,n=3){await e.goto(`${y}?id=${encodeURIComponent(String(t))}`);await e.wait({time:n})}export const CITY_CODES={"全国":"100010000","北京":"101010100","上海":"101020100","广州":"101280100","深圳":"101280600","杭州":"101210100","成都":"101270100","南京":"101190100","武汉":"101200100","西安":"101110100","苏州":"101190400","长沙":"101250100","天津":"101030100","重庆":"101040100","郑州":"101180100","东莞":"101281600","青岛":"101120200","合肥":"101220100","佛山":"101280800","宁波":"101210400","厦门":"101230200","大连":"101070200","珠海":"101280700","无锡":"101190200","济南":"101120100","福州":"101230100","昆明":"101290100","哈尔滨":"101050100","沈阳":"101070100","石家庄":"101090100","贵阳":"101260100","南宁":"101300100","太原":"101100100","海口":"101310100","兰州":"101160100","乌鲁木齐":"101130100","长春":"101060100","南昌":"101240100","常州":"101191100","温州":"101210700","嘉兴":"101210300","徐州":"101190800","香港":"101320100"};export async function isRecruiterSide(e){await navigateToChat(e);const t=await bossFetch(e,`https://${d}/wapi/zprelation/friend/getBossFriendListV2.json?page=1&status=0&jobId=0`,{allowNonZero:!0});if(t.code===0)return!0;if(t.code===IDENTITY_MISMATCH_CODE)return!1;assertOk(t,"boss 身份探测");return!1}
@@ -1 +1 @@
1
- import{cli as V,Strategy as W}from"@jackwener/opencli/registry";import{AuthRequiredError as X}from"@jackwener/opencli/errors";import{getCourses as Y,initSession as Z,enterCourse as _,getTabIframeUrl as $,parseAssignmentsFromDom as q,sleep as D}from"./utils.js";V({site:"chaoxing",name:"assignments",access:"read",description:"学习通作业列表",domain:"mooc2-ans.chaoxing.com",strategy:W.COOKIE,args:[{name:"course",type:"string",help:"按课程名过滤(模糊匹配)"},{name:"status",type:"string",default:"all",choices:["all","pending","submitted","graded"],help:"按状态过滤"},{name:"limit",type:"int",default:20,help:"最大返回数量"},{name:"timeout",type:"int",required:!1,default:90,help:"Max seconds for the overall command (default: 90)"}],columns:["rank","course","title","deadline","status","score"],func:async(x,O)=>{const{course:B,status:N="all",limit:P=20}=O;await Z(x);const K=await Y(x);if(!K.length)throw new X("mooc2-ans.chaoxing.com","未获取到课程列表");const L=B?K.filter((v)=>v.title.includes(B)):K;if(B&&!L.length)throw Error(`未找到匹配「${B}」的课程`);const G=[];for(const v of L){try{await _(x,v);const z=await $(x,"作业");if(!z)continue;await x.goto(z);await x.wait(2);const H=await q(x,v.title);G.push(...H)}catch{}if(L.length>1)await D(600)}G.sort((v,z)=>{const H=(J)=>J==="未交"?0:J==="待批阅"?1:J==="已完成"?2:J==="已批阅"?3:4;return H(v.status)-H(z.status)});const Q={pending:["未交"],submitted:["待批阅","已完成"],graded:["已批阅"]};return(N==="all"?G:G.filter((v)=>Q[N]?.includes(v.status))).slice(0,Number(P)).map((v,z)=>({rank:z+1,...v}))}});
1
+ import{cli as f,Strategy as h}from"@jackwener/opencli/registry";import{AuthRequiredError as w}from"@jackwener/opencli/errors";import{getCourses as g,initSession as p,enterCourse as y,getTabIframeUrl as b,parseAssignmentsFromDom as x,sleep as R}from"./utils.js";f({site:"chaoxing",name:"assignments",access:"read",description:"学习通作业列表",domain:"mooc2-ans.chaoxing.com",strategy:h.COOKIE,args:[{name:"course",type:"string",help:"按课程名过滤(模糊匹配)"},{name:"status",type:"string",default:"all",choices:["all","pending","submitted","graded"],help:"按状态过滤"},{name:"limit",type:"int",default:20,help:"最大返回数量"},{name:"timeout",type:"int",required:!1,default:90,help:"Max seconds for the overall command (default: 90)"}],columns:["rank","course","title","deadline","status","score"],func:async(e,u)=>{const{course:a,status:c="all",limit:m=20}=u;await p(e);const n=await g(e);if(!n.length)throw new w("mooc2-ans.chaoxing.com","未获取到课程列表");const l=a?n.filter((t)=>t.title.includes(a)):n;if(a&&!l.length)throw Error(`未找到匹配「${a}」的课程`);const i=[];for(const t of l){try{await y(e,t);const s=await b(e,"作业");if(!s)continue;await e.goto(s);await e.wait(2);const r=await x(e,t.title);i.push(...r)}catch{}if(l.length>1)await R(600)}i.sort((t,s)=>{const r=(o)=>o==="未交"?0:o==="待批阅"?1:o==="已完成"?2:o==="已批阅"?3:4;return r(t.status)-r(s.status)});const d={pending:["未交"],submitted:["待批阅","已完成"],graded:["已批阅"]};return(c==="all"?i:i.filter((t)=>d[c]?.includes(t.status))).slice(0,Number(m)).map((t,s)=>({rank:s+1,...t}))}});
@@ -1 +1 @@
1
- import{cli as P,Strategy as Q}from"@jackwener/opencli/registry";import{getCourses as V,initSession as W,enterCourse as X,getTabIframeUrl as Y,parseExamsFromDom as Z,sleep as _}from"./utils.js";P({site:"chaoxing",name:"exams",access:"read",description:"学习通考试列表",domain:"mooc2-ans.chaoxing.com",strategy:Q.COOKIE,args:[{name:"course",type:"string",help:"按课程名过滤(模糊匹配)"},{name:"status",type:"string",default:"all",choices:["all","upcoming","ongoing","finished"],help:"按状态过滤"},{name:"limit",type:"int",default:20,help:"最大返回数量"},{name:"timeout",type:"int",required:!1,default:90,help:"Max seconds for the overall command (default: 90)"}],columns:["rank","course","title","start","end","status","score"],func:async(q,L)=>{const{course:z,status:K="all",limit:N=20}=L;await W(q);const H=await V(q);if(!H.length)throw Error("未获取到课程列表,请确认已登录学习通");const J=z?H.filter((h)=>h.title.includes(z)):H;if(z&&!J.length)throw Error(`未找到匹配「${z}」的课程`);const A=[];for(const h of J){try{await X(q,h);const v=await Y(q,"考试");if(!v)continue;await q.goto(v);await q.wait(2);const B=await Z(q,h.title);A.push(...B)}catch{}if(J.length>1)await _(600)}A.sort((h,v)=>{const B=(G)=>G==="未开始"?0:G==="进行中"?1:G==="已结束"?2:G==="已完成"?3:4;return B(h.status)-B(v.status)});const O={upcoming:["未开始"],ongoing:["进行中"],finished:["已结束","已完成"]};return(K==="all"?A:A.filter((h)=>O[K]?.includes(h.status))).slice(0,Number(N)).map((h,v)=>({rank:v+1,...h}))}});
1
+ import{cli as d,Strategy as h}from"@jackwener/opencli/registry";import{getCourses as w,initSession as g,enterCourse as p,getTabIframeUrl as y,parseExamsFromDom as x,sleep as E}from"./utils.js";d({site:"chaoxing",name:"exams",access:"read",description:"学习通考试列表",domain:"mooc2-ans.chaoxing.com",strategy:h.COOKIE,args:[{name:"course",type:"string",help:"按课程名过滤(模糊匹配)"},{name:"status",type:"string",default:"all",choices:["all","upcoming","ongoing","finished"],help:"按状态过滤"},{name:"limit",type:"int",default:20,help:"最大返回数量"},{name:"timeout",type:"int",required:!1,default:90,help:"Max seconds for the overall command (default: 90)"}],columns:["rank","course","title","start","end","status","score"],func:async(e,u)=>{const{course:a,status:c="all",limit:m=20}=u;await g(e);const n=await w(e);if(!n.length)throw Error("未获取到课程列表,请确认已登录学习通");const l=a?n.filter((t)=>t.title.includes(a)):n;if(a&&!l.length)throw Error(`未找到匹配「${a}」的课程`);const o=[];for(const t of l){try{await p(e,t);const s=await y(e,"考试");if(!s)continue;await e.goto(s);await e.wait(2);const i=await x(e,t.title);o.push(...i)}catch{}if(l.length>1)await E(600)}o.sort((t,s)=>{const i=(r)=>r==="未开始"?0:r==="进行中"?1:r==="已结束"?2:r==="已完成"?3:4;return i(t.status)-i(s.status)});const f={upcoming:["未开始"],ongoing:["进行中"],finished:["已结束","已完成"]};return(c==="all"?o:o.filter((t)=>f[c]?.includes(t.status))).slice(0,Number(m)).map((t,s)=>({rank:s+1,...t}))}});