@jackwener/opencli 1.1.1 → 1.2.0
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.
- package/CONTRIBUTING.md +39 -1
- package/README.md +9 -10
- package/README.zh-CN.md +39 -17
- package/SKILL.md +10 -5
- package/dist/browser/cdp.d.ts +4 -4
- package/dist/browser/cdp.js +39 -16
- package/dist/browser/daemon-client.d.ts +2 -1
- package/dist/browser/dom-helpers.js +38 -7
- package/dist/browser/dom-snapshot.d.ts +86 -0
- package/dist/browser/dom-snapshot.js +729 -0
- package/dist/browser/dom-snapshot.test.d.ts +11 -0
- package/dist/browser/dom-snapshot.test.js +212 -0
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.js +1 -0
- package/dist/browser/page.d.ts +14 -24
- package/dist/browser/page.js +37 -4
- package/dist/build-manifest.d.ts +11 -4
- package/dist/build-manifest.js +59 -21
- package/dist/build-manifest.test.js +58 -2
- package/dist/cli-manifest.json +3856 -1509
- package/dist/cli.js +66 -0
- package/dist/clis/barchart/greeks.js +1 -1
- package/dist/clis/barchart/options.js +1 -1
- package/dist/clis/barchart/quote.js +1 -1
- package/dist/clis/bilibili/download.js +1 -1
- package/dist/clis/bilibili/following.js +1 -1
- package/dist/clis/bilibili/subtitle.js +1 -1
- package/dist/clis/bilibili/user-videos.js +1 -1
- package/dist/clis/boss/batchgreet.js +10 -97
- package/dist/clis/boss/chatlist.js +8 -25
- package/dist/clis/boss/chatmsg.js +11 -42
- package/dist/clis/boss/common.d.ts +92 -0
- package/dist/clis/boss/common.js +223 -0
- package/dist/clis/boss/detail.js +7 -49
- package/dist/clis/boss/exchange.js +13 -79
- package/dist/clis/boss/greet.js +18 -145
- package/dist/clis/boss/invite.js +26 -121
- package/dist/clis/boss/joblist.js +6 -31
- package/dist/clis/boss/mark.js +12 -85
- package/dist/clis/boss/recommend.js +10 -49
- package/dist/clis/boss/resume.js +18 -118
- package/dist/clis/boss/search.js +12 -60
- package/dist/clis/boss/send.js +17 -151
- package/dist/clis/boss/stats.js +18 -69
- package/dist/clis/coupang/add-to-cart.js +1 -1
- package/dist/clis/devto/tag.yaml +34 -0
- package/dist/clis/devto/top.yaml +29 -0
- package/dist/clis/devto/user.yaml +33 -0
- package/dist/clis/douban/book-hot.d.ts +1 -0
- package/dist/clis/douban/book-hot.js +14 -0
- package/dist/clis/douban/marks.d.ts +1 -0
- package/dist/clis/douban/marks.js +115 -0
- package/dist/clis/douban/movie-hot.d.ts +1 -0
- package/dist/clis/douban/movie-hot.js +14 -0
- package/dist/clis/douban/reviews.d.ts +1 -0
- package/dist/clis/douban/reviews.js +106 -0
- package/dist/clis/douban/search.d.ts +1 -0
- package/dist/clis/douban/search.js +16 -0
- package/dist/clis/douban/shared.d.ts +4 -0
- package/dist/clis/douban/shared.js +155 -0
- package/dist/clis/douban/subject.yaml +76 -0
- package/dist/clis/douban/top250.yaml +70 -0
- package/dist/clis/douban/utils.d.ts +35 -0
- package/dist/clis/douban/utils.js +48 -0
- package/dist/clis/facebook/add-friend.yaml +43 -0
- package/dist/clis/facebook/events.yaml +44 -0
- package/dist/clis/facebook/feed.yaml +63 -0
- package/dist/clis/facebook/friends.yaml +42 -0
- package/dist/clis/facebook/groups.yaml +50 -0
- package/dist/clis/facebook/join-group.yaml +44 -0
- package/dist/clis/facebook/memories.yaml +39 -0
- package/dist/clis/facebook/notifications.yaml +40 -0
- package/dist/clis/facebook/profile.yaml +37 -0
- package/dist/clis/facebook/search.yaml +46 -0
- package/dist/clis/google/news.d.ts +5 -0
- package/dist/clis/google/news.js +58 -0
- package/dist/clis/google/search.d.ts +10 -0
- package/dist/clis/google/search.js +127 -0
- package/dist/clis/google/suggest.d.ts +5 -0
- package/dist/clis/google/suggest.js +34 -0
- package/dist/clis/google/trends.d.ts +5 -0
- package/dist/clis/google/trends.js +38 -0
- package/dist/clis/google/utils.d.ts +9 -0
- package/dist/clis/google/utils.js +23 -0
- package/dist/clis/google/utils.test.d.ts +1 -0
- package/dist/clis/google/utils.test.js +75 -0
- package/dist/clis/grok/ask.d.ts +14 -0
- package/dist/clis/grok/ask.js +257 -65
- package/dist/clis/grok/ask.test.d.ts +1 -0
- package/dist/clis/grok/ask.test.js +36 -0
- package/dist/clis/instagram/comment.yaml +52 -0
- package/dist/clis/instagram/explore.yaml +43 -0
- package/dist/clis/instagram/follow.yaml +41 -0
- package/dist/clis/instagram/followers.yaml +51 -0
- package/dist/clis/instagram/following.yaml +51 -0
- package/dist/clis/instagram/like.yaml +46 -0
- package/dist/clis/instagram/profile.yaml +42 -0
- package/dist/clis/instagram/save.yaml +46 -0
- package/dist/clis/instagram/saved.yaml +40 -0
- package/dist/clis/instagram/search.yaml +43 -0
- package/dist/clis/instagram/unfollow.yaml +38 -0
- package/dist/clis/instagram/unlike.yaml +46 -0
- package/dist/clis/instagram/unsave.yaml +46 -0
- package/dist/clis/instagram/user.yaml +54 -0
- package/dist/clis/jike/repost.js +1 -1
- package/dist/clis/jimeng/generate.yaml +1 -0
- package/dist/clis/linux-do/category.yaml +1 -0
- package/dist/clis/lobsters/active.yaml +29 -0
- package/dist/clis/lobsters/hot.yaml +29 -0
- package/dist/clis/lobsters/newest.yaml +29 -0
- package/dist/clis/lobsters/tag.yaml +34 -0
- package/dist/clis/medium/feed.d.ts +1 -0
- package/dist/clis/medium/feed.js +15 -0
- package/dist/clis/medium/search.d.ts +1 -0
- package/dist/clis/medium/search.js +15 -0
- package/dist/clis/medium/shared.d.ts +5 -0
- package/dist/clis/medium/shared.js +78 -0
- package/dist/clis/medium/user.d.ts +1 -0
- package/dist/clis/medium/user.js +15 -0
- package/dist/clis/reddit/comment.js +1 -1
- package/dist/clis/reddit/read.js +1 -1
- package/dist/clis/reddit/save.js +1 -1
- package/dist/clis/reddit/subreddit.yaml +1 -0
- package/dist/clis/reddit/subscribe.js +1 -1
- package/dist/clis/reddit/upvote.js +1 -1
- package/dist/clis/sinablog/article.d.ts +1 -0
- package/dist/clis/sinablog/article.js +14 -0
- package/dist/clis/sinablog/hot.d.ts +1 -0
- package/dist/clis/sinablog/hot.js +14 -0
- package/dist/clis/sinablog/search.d.ts +1 -0
- package/dist/clis/sinablog/search.js +51 -0
- package/dist/clis/sinablog/shared.d.ts +7 -0
- package/dist/clis/sinablog/shared.js +187 -0
- package/dist/clis/sinablog/user.d.ts +1 -0
- package/dist/clis/sinablog/user.js +15 -0
- package/dist/clis/substack/feed.d.ts +1 -0
- package/dist/clis/substack/feed.js +15 -0
- package/dist/clis/substack/publication.d.ts +1 -0
- package/dist/clis/substack/publication.js +15 -0
- package/dist/clis/substack/search.d.ts +1 -0
- package/dist/clis/substack/search.js +77 -0
- package/dist/clis/substack/shared.d.ts +4 -0
- package/dist/clis/substack/shared.js +129 -0
- package/dist/clis/tiktok/comment.yaml +66 -0
- package/dist/clis/tiktok/explore.yaml +39 -0
- package/dist/clis/tiktok/follow.yaml +39 -0
- package/dist/clis/tiktok/following.yaml +46 -0
- package/dist/clis/tiktok/friends.yaml +47 -0
- package/dist/clis/tiktok/like.yaml +38 -0
- package/dist/clis/tiktok/live.yaml +51 -0
- package/dist/clis/tiktok/notifications.yaml +52 -0
- package/dist/clis/tiktok/profile.yaml +45 -0
- package/dist/clis/tiktok/save.yaml +34 -0
- package/dist/clis/tiktok/search.yaml +46 -0
- package/dist/clis/tiktok/unfollow.yaml +44 -0
- package/dist/clis/tiktok/unlike.yaml +38 -0
- package/dist/clis/tiktok/unsave.yaml +36 -0
- package/dist/clis/tiktok/user.yaml +44 -0
- package/dist/clis/twitter/download.d.ts +1 -1
- package/dist/clis/twitter/download.js +3 -3
- package/dist/clis/twitter/followers.js +1 -1
- package/dist/clis/twitter/following.js +1 -1
- package/dist/clis/twitter/thread.js +1 -1
- package/dist/clis/twitter/timeline.d.ts +23 -0
- package/dist/clis/twitter/timeline.js +42 -14
- package/dist/clis/twitter/timeline.test.d.ts +1 -0
- package/dist/clis/twitter/timeline.test.js +102 -0
- package/dist/clis/wikipedia/random.d.ts +1 -0
- package/dist/clis/wikipedia/random.js +19 -0
- package/dist/clis/wikipedia/search.js +3 -3
- package/dist/clis/wikipedia/summary.js +4 -9
- package/dist/clis/wikipedia/trending.d.ts +1 -0
- package/dist/clis/wikipedia/trending.js +35 -0
- package/dist/clis/wikipedia/utils.d.ts +28 -0
- package/dist/clis/wikipedia/utils.js +13 -0
- package/dist/clis/xiaohongshu/creator-note-detail.js +1 -1
- package/dist/clis/xiaohongshu/creator-note-detail.test.js +2 -0
- package/dist/clis/xiaohongshu/creator-notes.test.js +2 -0
- package/dist/clis/xiaohongshu/download.js +1 -1
- package/dist/clis/xueqiu/earnings-date.yaml +69 -0
- package/dist/clis/xueqiu/search.yaml +2 -1
- package/dist/clis/xueqiu/stock.yaml +2 -0
- package/dist/clis/yahoo-finance/quote.js +1 -1
- package/dist/commanderAdapter.js +13 -7
- package/dist/discovery.d.ts +8 -0
- package/dist/discovery.js +105 -19
- package/dist/doctor.js +3 -1
- package/dist/doctor.test.js +46 -2
- package/dist/engine.test.d.ts +0 -3
- package/dist/engine.test.js +74 -6
- package/dist/execution.d.ts +4 -2
- package/dist/execution.js +31 -7
- package/dist/explore.d.ts +76 -3
- package/dist/explore.js +11 -4
- package/dist/generate.d.ts +41 -2
- package/dist/generate.js +5 -4
- package/dist/main.js +2 -1
- package/dist/pipeline/executor.d.ts +2 -2
- package/dist/pipeline/executor.js +2 -2
- package/dist/pipeline/executor.test.js +33 -6
- package/dist/pipeline/registry.d.ts +1 -1
- package/dist/pipeline/steps/browser.d.ts +7 -7
- package/dist/pipeline/steps/browser.js +15 -7
- package/dist/pipeline/steps/fetch.d.ts +1 -1
- package/dist/pipeline/steps/fetch.js +11 -7
- package/dist/pipeline/steps/transform.d.ts +6 -5
- package/dist/pipeline/steps/transform.js +30 -9
- package/dist/pipeline/template.d.ts +6 -6
- package/dist/pipeline/template.js +43 -5
- package/dist/pipeline/template.test.js +18 -0
- package/dist/pipeline/transform.test.js +11 -0
- package/dist/plugin.d.ts +31 -0
- package/dist/plugin.js +216 -0
- package/dist/plugin.test.d.ts +4 -0
- package/dist/plugin.test.js +76 -0
- package/dist/registry-api.d.ts +11 -0
- package/dist/registry-api.js +9 -0
- package/dist/registry.d.ts +11 -0
- package/dist/registry.js +6 -1
- package/dist/synthesize.d.ts +94 -4
- package/dist/synthesize.js +5 -4
- package/dist/types.d.ts +39 -26
- package/dist/validate.js +8 -2
- package/docs/.vitepress/config.mts +6 -4
- package/docs/adapters/browser/barchart.md +6 -5
- package/docs/adapters/browser/bilibili.md +9 -0
- package/docs/adapters/browser/devto.md +35 -0
- package/docs/adapters/browser/douban.md +38 -0
- package/docs/adapters/browser/facebook.md +36 -0
- package/docs/adapters/browser/google.md +62 -0
- package/docs/adapters/browser/grok.md +26 -8
- package/docs/adapters/browser/instagram.md +46 -0
- package/docs/adapters/browser/lobsters.md +32 -0
- package/docs/adapters/browser/medium.md +32 -0
- package/docs/adapters/browser/reddit.md +9 -0
- package/docs/adapters/browser/sinablog.md +36 -0
- package/docs/adapters/browser/substack.md +38 -0
- package/docs/adapters/browser/tiktok.md +68 -0
- package/docs/adapters/browser/wikipedia.md +11 -2
- package/docs/adapters/browser/xueqiu.md +10 -0
- package/docs/adapters/browser/yahoo-finance.md +6 -5
- package/docs/adapters/desktop/antigravity.md +6 -0
- package/docs/adapters/desktop/chatgpt.md +2 -1
- package/docs/adapters/desktop/codex.md +5 -1
- package/docs/adapters/desktop/cursor.md +4 -0
- package/docs/adapters/desktop/discord.md +7 -7
- package/docs/adapters/index.md +1 -4
- package/docs/guide/getting-started.md +1 -0
- package/docs/guide/plugins.md +153 -0
- package/docs/zh/guide/plugins.md +107 -0
- package/extension/src/background.ts +18 -11
- package/package.json +10 -5
- package/scripts/clean-dist.cjs +13 -0
- package/src/browser/cdp.ts +71 -31
- package/src/browser/daemon-client.ts +2 -1
- package/src/browser/dom-helpers.ts +38 -7
- package/src/browser/dom-snapshot.test.ts +249 -0
- package/src/browser/dom-snapshot.ts +770 -0
- package/src/browser/index.ts +2 -0
- package/src/browser/page.ts +50 -19
- package/src/build-manifest.test.ts +70 -2
- package/src/build-manifest.ts +94 -26
- package/src/cli.ts +71 -2
- package/src/clis/barchart/greeks.ts +1 -1
- package/src/clis/barchart/options.ts +1 -1
- package/src/clis/barchart/quote.ts +1 -1
- package/src/clis/bilibili/download.ts +1 -1
- package/src/clis/bilibili/following.ts +1 -1
- package/src/clis/bilibili/subtitle.ts +1 -1
- package/src/clis/bilibili/user-videos.ts +1 -1
- package/src/clis/boss/batchgreet.ts +14 -106
- package/src/clis/boss/chatlist.ts +12 -26
- package/src/clis/boss/chatmsg.ts +16 -40
- package/src/clis/boss/common.ts +287 -0
- package/src/clis/boss/detail.ts +8 -54
- package/src/clis/boss/exchange.ts +15 -89
- package/src/clis/boss/greet.ts +23 -160
- package/src/clis/boss/invite.ts +36 -133
- package/src/clis/boss/joblist.ts +7 -36
- package/src/clis/boss/mark.ts +13 -94
- package/src/clis/boss/recommend.ts +12 -57
- package/src/clis/boss/resume.ts +19 -124
- package/src/clis/boss/search.ts +13 -66
- package/src/clis/boss/send.ts +21 -161
- package/src/clis/boss/stats.ts +19 -74
- package/src/clis/coupang/add-to-cart.ts +1 -1
- package/src/clis/devto/tag.yaml +34 -0
- package/src/clis/devto/top.yaml +29 -0
- package/src/clis/devto/user.yaml +33 -0
- package/src/clis/douban/book-hot.ts +15 -0
- package/src/clis/douban/marks.ts +135 -0
- package/src/clis/douban/movie-hot.ts +15 -0
- package/src/clis/douban/reviews.ts +127 -0
- package/src/clis/douban/search.ts +17 -0
- package/src/clis/douban/shared.ts +165 -0
- package/src/clis/douban/subject.yaml +76 -0
- package/src/clis/douban/top250.yaml +70 -0
- package/src/clis/douban/utils.ts +81 -0
- package/src/clis/facebook/add-friend.yaml +43 -0
- package/src/clis/facebook/events.yaml +44 -0
- package/src/clis/facebook/feed.yaml +63 -0
- package/src/clis/facebook/friends.yaml +42 -0
- package/src/clis/facebook/groups.yaml +50 -0
- package/src/clis/facebook/join-group.yaml +44 -0
- package/src/clis/facebook/memories.yaml +39 -0
- package/src/clis/facebook/notifications.yaml +40 -0
- package/src/clis/facebook/profile.yaml +37 -0
- package/src/clis/facebook/search.yaml +46 -0
- package/src/clis/google/news.ts +66 -0
- package/src/clis/google/search.ts +133 -0
- package/src/clis/google/suggest.ts +40 -0
- package/src/clis/google/trends.ts +44 -0
- package/src/clis/google/utils.test.ts +82 -0
- package/src/clis/google/utils.ts +24 -0
- package/src/clis/grok/ask.test.ts +53 -0
- package/src/clis/grok/ask.ts +300 -69
- package/src/clis/instagram/comment.yaml +52 -0
- package/src/clis/instagram/explore.yaml +43 -0
- package/src/clis/instagram/follow.yaml +41 -0
- package/src/clis/instagram/followers.yaml +51 -0
- package/src/clis/instagram/following.yaml +51 -0
- package/src/clis/instagram/like.yaml +46 -0
- package/src/clis/instagram/profile.yaml +42 -0
- package/src/clis/instagram/save.yaml +46 -0
- package/src/clis/instagram/saved.yaml +40 -0
- package/src/clis/instagram/search.yaml +43 -0
- package/src/clis/instagram/unfollow.yaml +38 -0
- package/src/clis/instagram/unlike.yaml +46 -0
- package/src/clis/instagram/unsave.yaml +46 -0
- package/src/clis/instagram/user.yaml +54 -0
- package/src/clis/jike/repost.ts +1 -1
- package/src/clis/jimeng/generate.yaml +1 -0
- package/src/clis/linux-do/category.yaml +1 -0
- package/src/clis/lobsters/active.yaml +29 -0
- package/src/clis/lobsters/hot.yaml +29 -0
- package/src/clis/lobsters/newest.yaml +29 -0
- package/src/clis/lobsters/tag.yaml +34 -0
- package/src/clis/medium/feed.ts +16 -0
- package/src/clis/medium/search.ts +16 -0
- package/src/clis/medium/shared.ts +83 -0
- package/src/clis/medium/user.ts +16 -0
- package/src/clis/reddit/comment.ts +1 -1
- package/src/clis/reddit/read.ts +1 -1
- package/src/clis/reddit/save.ts +1 -1
- package/src/clis/reddit/subreddit.yaml +1 -0
- package/src/clis/reddit/subscribe.ts +1 -1
- package/src/clis/reddit/upvote.ts +1 -1
- package/src/clis/sinablog/article.ts +15 -0
- package/src/clis/sinablog/hot.ts +15 -0
- package/src/clis/sinablog/search.ts +56 -0
- package/src/clis/sinablog/shared.ts +198 -0
- package/src/clis/sinablog/user.ts +16 -0
- package/src/clis/substack/feed.ts +16 -0
- package/src/clis/substack/publication.ts +16 -0
- package/src/clis/substack/search.ts +91 -0
- package/src/clis/substack/shared.ts +132 -0
- package/src/clis/tiktok/comment.yaml +66 -0
- package/src/clis/tiktok/explore.yaml +39 -0
- package/src/clis/tiktok/follow.yaml +39 -0
- package/src/clis/tiktok/following.yaml +46 -0
- package/src/clis/tiktok/friends.yaml +47 -0
- package/src/clis/tiktok/like.yaml +38 -0
- package/src/clis/tiktok/live.yaml +51 -0
- package/src/clis/tiktok/notifications.yaml +52 -0
- package/src/clis/tiktok/profile.yaml +45 -0
- package/src/clis/tiktok/save.yaml +34 -0
- package/src/clis/tiktok/search.yaml +46 -0
- package/src/clis/tiktok/unfollow.yaml +44 -0
- package/src/clis/tiktok/unlike.yaml +38 -0
- package/src/clis/tiktok/unsave.yaml +36 -0
- package/src/clis/tiktok/user.yaml +44 -0
- package/src/clis/twitter/download.ts +3 -3
- package/src/clis/twitter/followers.ts +1 -1
- package/src/clis/twitter/following.ts +1 -1
- package/src/clis/twitter/thread.ts +1 -1
- package/src/clis/twitter/timeline.test.ts +109 -0
- package/src/clis/twitter/timeline.ts +59 -19
- package/src/clis/wikipedia/random.ts +19 -0
- package/src/clis/wikipedia/search.ts +10 -4
- package/src/clis/wikipedia/summary.ts +4 -9
- package/src/clis/wikipedia/trending.ts +41 -0
- package/src/clis/wikipedia/utils.ts +31 -0
- package/src/clis/xiaohongshu/creator-note-detail.test.ts +2 -0
- package/src/clis/xiaohongshu/creator-note-detail.ts +1 -1
- package/src/clis/xiaohongshu/creator-notes.test.ts +2 -0
- package/src/clis/xiaohongshu/download.ts +1 -1
- package/src/clis/xueqiu/earnings-date.yaml +69 -0
- package/src/clis/xueqiu/search.yaml +2 -1
- package/src/clis/xueqiu/stock.yaml +2 -0
- package/src/clis/yahoo-finance/quote.ts +1 -1
- package/src/commanderAdapter.ts +17 -10
- package/src/discovery.ts +134 -24
- package/src/doctor.test.ts +59 -2
- package/src/doctor.ts +4 -2
- package/src/engine.test.ts +79 -6
- package/src/execution.ts +42 -16
- package/src/explore.ts +77 -9
- package/src/generate.ts +58 -9
- package/src/main.ts +2 -1
- package/src/pipeline/executor.test.ts +35 -6
- package/src/pipeline/executor.ts +11 -7
- package/src/pipeline/registry.ts +3 -3
- package/src/pipeline/steps/browser.ts +24 -15
- package/src/pipeline/steps/fetch.ts +18 -13
- package/src/pipeline/steps/transform.ts +40 -15
- package/src/pipeline/template.test.ts +18 -0
- package/src/pipeline/template.ts +86 -13
- package/src/pipeline/transform.test.ts +15 -2
- package/src/plugin.test.ts +86 -0
- package/src/plugin.ts +254 -0
- package/src/registry-api.ts +12 -0
- package/src/registry.ts +19 -1
- package/src/synthesize.ts +102 -21
- package/src/types.ts +44 -12
- package/src/validate.ts +19 -4
- package/tests/e2e/browser-public.test.ts +11 -0
- package/tests/e2e/public-commands.test.ts +64 -0
- package/dist/clis/feishu/new.d.ts +0 -1
- package/dist/clis/feishu/new.js +0 -27
- package/dist/clis/feishu/read.d.ts +0 -1
- package/dist/clis/feishu/read.js +0 -40
- package/dist/clis/feishu/search.d.ts +0 -1
- package/dist/clis/feishu/search.js +0 -30
- package/dist/clis/feishu/send.d.ts +0 -1
- package/dist/clis/feishu/send.js +0 -39
- package/dist/clis/feishu/status.d.ts +0 -1
- package/dist/clis/feishu/status.js +0 -28
- package/dist/clis/neteasemusic/like.d.ts +0 -1
- package/dist/clis/neteasemusic/like.js +0 -25
- package/dist/clis/neteasemusic/lyrics.d.ts +0 -1
- package/dist/clis/neteasemusic/lyrics.js +0 -47
- package/dist/clis/neteasemusic/next.d.ts +0 -1
- package/dist/clis/neteasemusic/next.js +0 -26
- package/dist/clis/neteasemusic/play.d.ts +0 -1
- package/dist/clis/neteasemusic/play.js +0 -26
- package/dist/clis/neteasemusic/playing.d.ts +0 -1
- package/dist/clis/neteasemusic/playing.js +0 -59
- package/dist/clis/neteasemusic/playlist.d.ts +0 -1
- package/dist/clis/neteasemusic/playlist.js +0 -46
- package/dist/clis/neteasemusic/prev.d.ts +0 -1
- package/dist/clis/neteasemusic/prev.js +0 -25
- package/dist/clis/neteasemusic/search.d.ts +0 -1
- package/dist/clis/neteasemusic/search.js +0 -52
- package/dist/clis/neteasemusic/status.d.ts +0 -1
- package/dist/clis/neteasemusic/status.js +0 -16
- package/dist/clis/neteasemusic/volume.d.ts +0 -1
- package/dist/clis/neteasemusic/volume.js +0 -54
- package/dist/clis/wechat/chats.d.ts +0 -1
- package/dist/clis/wechat/chats.js +0 -28
- package/dist/clis/wechat/contacts.d.ts +0 -1
- package/dist/clis/wechat/contacts.js +0 -28
- package/dist/clis/wechat/read.d.ts +0 -1
- package/dist/clis/wechat/read.js +0 -58
- package/dist/clis/wechat/search.d.ts +0 -1
- package/dist/clis/wechat/search.js +0 -31
- package/dist/clis/wechat/send.d.ts +0 -1
- package/dist/clis/wechat/send.js +0 -42
- package/dist/clis/wechat/status.d.ts +0 -1
- package/dist/clis/wechat/status.js +0 -29
- package/dist/pipeline.d.ts +0 -7
- package/dist/pipeline.js +0 -7
- package/docs/adapters/browser/github.md +0 -26
- package/docs/adapters/desktop/feishu.md +0 -20
- package/docs/adapters/desktop/neteasemusic.md +0 -31
- package/docs/adapters/desktop/wechat.md +0 -28
- package/src/clis/antigravity/README.md +0 -5
- package/src/clis/antigravity/README.zh-CN.md +0 -51
- package/src/clis/chaoxing/README.md +0 -14
- package/src/clis/chaoxing/README.zh-CN.md +0 -35
- package/src/clis/chatgpt/README.md +0 -5
- package/src/clis/chatgpt/README.zh-CN.md +0 -44
- package/src/clis/chatwise/README.md +0 -5
- package/src/clis/chatwise/README.zh-CN.md +0 -38
- package/src/clis/codex/README.md +0 -5
- package/src/clis/codex/README.zh-CN.md +0 -33
- package/src/clis/cursor/README.md +0 -5
- package/src/clis/cursor/README.zh-CN.md +0 -33
- package/src/clis/discord-app/README.md +0 -5
- package/src/clis/discord-app/README.zh-CN.md +0 -28
- package/src/clis/feishu/README.md +0 -5
- package/src/clis/feishu/README.zh-CN.md +0 -20
- package/src/clis/feishu/new.ts +0 -32
- package/src/clis/feishu/read.ts +0 -48
- package/src/clis/feishu/search.ts +0 -35
- package/src/clis/feishu/send.ts +0 -46
- package/src/clis/feishu/status.ts +0 -34
- package/src/clis/neteasemusic/README.md +0 -5
- package/src/clis/neteasemusic/README.zh-CN.md +0 -31
- package/src/clis/neteasemusic/like.ts +0 -28
- package/src/clis/neteasemusic/lyrics.ts +0 -53
- package/src/clis/neteasemusic/next.ts +0 -30
- package/src/clis/neteasemusic/play.ts +0 -30
- package/src/clis/neteasemusic/playing.ts +0 -62
- package/src/clis/neteasemusic/playlist.ts +0 -51
- package/src/clis/neteasemusic/prev.ts +0 -29
- package/src/clis/neteasemusic/search.ts +0 -58
- package/src/clis/neteasemusic/status.ts +0 -18
- package/src/clis/neteasemusic/volume.ts +0 -61
- package/src/clis/notion/README.md +0 -5
- package/src/clis/notion/README.zh-CN.md +0 -29
- package/src/clis/wechat/README.md +0 -5
- package/src/clis/wechat/README.zh-CN.md +0 -28
- package/src/clis/wechat/chats.ts +0 -33
- package/src/clis/wechat/contacts.ts +0 -33
- package/src/clis/wechat/read.ts +0 -72
- package/src/clis/wechat/search.ts +0 -36
- package/src/clis/wechat/send.ts +0 -49
- package/src/clis/wechat/status.ts +0 -35
- package/src/pipeline.ts +0 -8
package/dist/cli.js
CHANGED
|
@@ -210,6 +210,72 @@ export function runCli(BUILTIN_CLIS, USER_CLIS) {
|
|
|
210
210
|
.action((shell) => {
|
|
211
211
|
printCompletionScript(shell);
|
|
212
212
|
});
|
|
213
|
+
// ── Plugin management ──────────────────────────────────────────────────────
|
|
214
|
+
const pluginCmd = program.command('plugin').description('Manage opencli plugins');
|
|
215
|
+
pluginCmd
|
|
216
|
+
.command('install')
|
|
217
|
+
.description('Install a plugin from GitHub')
|
|
218
|
+
.argument('<source>', 'Plugin source (e.g. github:user/repo)')
|
|
219
|
+
.action(async (source) => {
|
|
220
|
+
const { installPlugin } = await import('./plugin.js');
|
|
221
|
+
try {
|
|
222
|
+
const name = installPlugin(source);
|
|
223
|
+
console.log(chalk.green(`✅ Plugin "${name}" installed successfully.`));
|
|
224
|
+
console.log(chalk.dim(` Restart opencli to use the new commands.`));
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
228
|
+
process.exitCode = 1;
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
pluginCmd
|
|
232
|
+
.command('uninstall')
|
|
233
|
+
.description('Uninstall a plugin')
|
|
234
|
+
.argument('<name>', 'Plugin name')
|
|
235
|
+
.action(async (name) => {
|
|
236
|
+
const { uninstallPlugin } = await import('./plugin.js');
|
|
237
|
+
try {
|
|
238
|
+
uninstallPlugin(name);
|
|
239
|
+
console.log(chalk.green(`✅ Plugin "${name}" uninstalled.`));
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
243
|
+
process.exitCode = 1;
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
pluginCmd
|
|
247
|
+
.command('list')
|
|
248
|
+
.description('List installed plugins')
|
|
249
|
+
.option('-f, --format <fmt>', 'Output format: table, json', 'table')
|
|
250
|
+
.action(async (opts) => {
|
|
251
|
+
const { listPlugins } = await import('./plugin.js');
|
|
252
|
+
const plugins = listPlugins();
|
|
253
|
+
if (plugins.length === 0) {
|
|
254
|
+
console.log(chalk.dim(' No plugins installed.'));
|
|
255
|
+
console.log(chalk.dim(` Install one with: opencli plugin install github:user/repo`));
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (opts.format === 'json') {
|
|
259
|
+
renderOutput(plugins, {
|
|
260
|
+
fmt: 'json',
|
|
261
|
+
columns: ['name', 'commands', 'source'],
|
|
262
|
+
title: 'opencli/plugins',
|
|
263
|
+
source: 'opencli plugin list',
|
|
264
|
+
});
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
console.log();
|
|
268
|
+
console.log(chalk.bold(' Installed plugins'));
|
|
269
|
+
console.log();
|
|
270
|
+
for (const p of plugins) {
|
|
271
|
+
const cmds = p.commands.length > 0 ? chalk.dim(` (${p.commands.join(', ')})`) : '';
|
|
272
|
+
const src = p.source ? chalk.dim(` ← ${p.source}`) : '';
|
|
273
|
+
console.log(` ${chalk.cyan(p.name)}${cmds}${src}`);
|
|
274
|
+
}
|
|
275
|
+
console.log();
|
|
276
|
+
console.log(chalk.dim(` ${plugins.length} plugin(s) installed`));
|
|
277
|
+
console.log();
|
|
278
|
+
});
|
|
213
279
|
// ── External CLIs ─────────────────────────────────────────────────────────
|
|
214
280
|
const externalClis = loadExternalClis();
|
|
215
281
|
program
|
|
@@ -11,7 +11,7 @@ cli({
|
|
|
11
11
|
domain: 'www.barchart.com',
|
|
12
12
|
strategy: Strategy.COOKIE,
|
|
13
13
|
args: [
|
|
14
|
-
{ name: 'symbol', required: true, help: 'Stock ticker (e.g. AAPL)' },
|
|
14
|
+
{ name: 'symbol', required: true, positional: true, help: 'Stock ticker (e.g. AAPL)' },
|
|
15
15
|
{ name: 'expiration', type: 'str', help: 'Expiration date (YYYY-MM-DD). Defaults to the nearest available expiration.' },
|
|
16
16
|
{ name: 'limit', type: 'int', default: 10, help: 'Number of near-the-money strikes per type' },
|
|
17
17
|
],
|
|
@@ -10,7 +10,7 @@ cli({
|
|
|
10
10
|
domain: 'www.barchart.com',
|
|
11
11
|
strategy: Strategy.COOKIE,
|
|
12
12
|
args: [
|
|
13
|
-
{ name: 'symbol', required: true, help: 'Stock ticker (e.g. AAPL)' },
|
|
13
|
+
{ name: 'symbol', required: true, positional: true, help: 'Stock ticker (e.g. AAPL)' },
|
|
14
14
|
{ name: 'type', type: 'str', default: 'Call', help: 'Option type: Call or Put', choices: ['Call', 'Put'] },
|
|
15
15
|
{ name: 'limit', type: 'int', default: 20, help: 'Max number of strikes to return' },
|
|
16
16
|
],
|
|
@@ -10,7 +10,7 @@ cli({
|
|
|
10
10
|
domain: 'www.barchart.com',
|
|
11
11
|
strategy: Strategy.COOKIE,
|
|
12
12
|
args: [
|
|
13
|
-
{ name: 'symbol', required: true, help: 'Stock ticker (e.g. AAPL, MSFT, TSLA)' },
|
|
13
|
+
{ name: 'symbol', required: true, positional: true, help: 'Stock ticker (e.g. AAPL, MSFT, TSLA)' },
|
|
14
14
|
],
|
|
15
15
|
columns: [
|
|
16
16
|
'symbol', 'name', 'price', 'change', 'changePct',
|
|
@@ -19,7 +19,7 @@ cli({
|
|
|
19
19
|
domain: 'www.bilibili.com',
|
|
20
20
|
strategy: Strategy.COOKIE,
|
|
21
21
|
args: [
|
|
22
|
-
{ name: 'bvid', required: true, help: 'Video BV ID (e.g., BV1xxx)' },
|
|
22
|
+
{ name: 'bvid', required: true, positional: true, help: 'Video BV ID (e.g., BV1xxx)' },
|
|
23
23
|
{ name: 'output', default: './bilibili-downloads', help: 'Output directory' },
|
|
24
24
|
{ name: 'quality', default: 'best', help: 'Video quality (best, 1080p, 720p, 480p)' },
|
|
25
25
|
],
|
|
@@ -6,7 +6,7 @@ cli({
|
|
|
6
6
|
description: '获取 Bilibili 用户的关注列表',
|
|
7
7
|
strategy: Strategy.COOKIE,
|
|
8
8
|
args: [
|
|
9
|
-
{ name: 'uid', required: false, help: '目标用户 ID(默认为当前登录用户)' },
|
|
9
|
+
{ name: 'uid', positional: true, required: false, help: '目标用户 ID(默认为当前登录用户)' },
|
|
10
10
|
{ name: 'page', type: 'int', required: false, default: 1, help: '页码' },
|
|
11
11
|
{ name: 'limit', type: 'int', required: false, default: 50, help: '每页数量 (最大 50)' },
|
|
12
12
|
],
|
|
@@ -6,7 +6,7 @@ cli({
|
|
|
6
6
|
description: '获取 Bilibili 视频的字幕',
|
|
7
7
|
strategy: Strategy.COOKIE,
|
|
8
8
|
args: [
|
|
9
|
-
{ name: 'bvid', required: true },
|
|
9
|
+
{ name: 'bvid', required: true, positional: true },
|
|
10
10
|
{ name: 'lang', required: false, help: '字幕语言代码 (如 zh-CN, en-US, ai-zh),默认取第一个' },
|
|
11
11
|
],
|
|
12
12
|
columns: ['index', 'from', 'to', 'content'],
|
|
@@ -7,7 +7,7 @@ cli({
|
|
|
7
7
|
domain: 'www.bilibili.com',
|
|
8
8
|
strategy: Strategy.COOKIE,
|
|
9
9
|
args: [
|
|
10
|
-
{ name: 'uid', required: true, help: 'User UID or username' },
|
|
10
|
+
{ name: 'uid', required: true, positional: true, help: 'User UID or username' },
|
|
11
11
|
{ name: 'limit', type: 'int', default: 20, help: 'Number of results' },
|
|
12
12
|
{ name: 'order', default: 'pubdate', help: 'Sort: pubdate, click, stow' },
|
|
13
13
|
{ name: 'page', type: 'int', default: 1, help: 'Page number' },
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* BOSS直聘 batchgreet — batch greet recommended candidates.
|
|
3
|
-
*
|
|
4
|
-
* Combines recommend (greetRecSortList) + greet (UI automation).
|
|
5
|
-
* Sends greeting messages to multiple candidates sequentially.
|
|
6
3
|
*/
|
|
7
4
|
import { cli, Strategy } from '../../registry.js';
|
|
5
|
+
import { requirePage, navigateToChat, fetchRecommendList, clickCandidateInList, typeAndSendMessage, verbose, } from './common.js';
|
|
8
6
|
cli({
|
|
9
7
|
site: 'boss',
|
|
10
8
|
name: 'batchgreet',
|
|
11
9
|
description: 'BOSS直聘批量向推荐候选人发送招呼',
|
|
12
10
|
domain: 'www.zhipin.com',
|
|
13
11
|
strategy: Strategy.COOKIE,
|
|
12
|
+
navigateBefore: false,
|
|
14
13
|
browser: true,
|
|
15
14
|
args: [
|
|
16
15
|
{ name: 'job-id', default: '', help: 'Filter by encrypted job ID (greet all jobs if empty)' },
|
|
@@ -19,38 +18,13 @@ cli({
|
|
|
19
18
|
],
|
|
20
19
|
columns: ['name', 'status', 'detail'],
|
|
21
20
|
func: async (page, kwargs) => {
|
|
22
|
-
|
|
23
|
-
throw new Error('Browser page required');
|
|
21
|
+
requirePage(page);
|
|
24
22
|
const filterJobId = kwargs['job-id'] || '';
|
|
25
23
|
const limit = kwargs.limit || 5;
|
|
26
24
|
const text = kwargs.text || '你好,请问您对这个职位感兴趣吗?';
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
await page.goto('https://www.zhipin.com/web/chat/index');
|
|
31
|
-
await page.wait({ time: 3 });
|
|
32
|
-
// Get recommended candidates
|
|
33
|
-
const listData = await page.evaluate(`
|
|
34
|
-
async () => {
|
|
35
|
-
return new Promise((resolve, reject) => {
|
|
36
|
-
const xhr = new XMLHttpRequest();
|
|
37
|
-
xhr.open('GET', 'https://www.zhipin.com/wapi/zprelation/friend/greetRecSortList', true);
|
|
38
|
-
xhr.withCredentials = true;
|
|
39
|
-
xhr.timeout = 15000;
|
|
40
|
-
xhr.setRequestHeader('Accept', 'application/json');
|
|
41
|
-
xhr.onload = () => { try { resolve(JSON.parse(xhr.responseText)); } catch(e) { reject(e); } };
|
|
42
|
-
xhr.onerror = () => reject(new Error('Network Error'));
|
|
43
|
-
xhr.send();
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
`);
|
|
47
|
-
if (listData.code !== 0) {
|
|
48
|
-
if (listData.code === 7 || listData.code === 37) {
|
|
49
|
-
throw new Error('Cookie 已过期!请在当前 Chrome 浏览器中重新登录 BOSS 直聘。');
|
|
50
|
-
}
|
|
51
|
-
throw new Error(`获取推荐列表失败: ${listData.message}`);
|
|
52
|
-
}
|
|
53
|
-
let candidates = listData.zpData?.friendList || [];
|
|
25
|
+
verbose(`Batch greeting up to ${limit} candidates...`);
|
|
26
|
+
await navigateToChat(page, 3);
|
|
27
|
+
let candidates = await fetchRecommendList(page);
|
|
54
28
|
if (filterJobId) {
|
|
55
29
|
candidates = candidates.filter((f) => f.encryptJobId === filterJobId);
|
|
56
30
|
}
|
|
@@ -63,78 +37,17 @@ cli({
|
|
|
63
37
|
const numericUid = candidate.uid;
|
|
64
38
|
const friendName = candidate.name || '候选人';
|
|
65
39
|
try {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
async () => {
|
|
69
|
-
const item = document.querySelector('#_${numericUid}-0') || document.querySelector('[id^="_${numericUid}"]');
|
|
70
|
-
if (item) {
|
|
71
|
-
item.click();
|
|
72
|
-
return { clicked: true };
|
|
73
|
-
}
|
|
74
|
-
const items = document.querySelectorAll('.geek-item');
|
|
75
|
-
for (const el of items) {
|
|
76
|
-
if (el.id && el.id.startsWith('_${numericUid}')) {
|
|
77
|
-
el.click();
|
|
78
|
-
return { clicked: true };
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return { clicked: false };
|
|
82
|
-
}
|
|
83
|
-
`);
|
|
84
|
-
if (!clicked.clicked) {
|
|
40
|
+
const clicked = await clickCandidateInList(page, numericUid);
|
|
41
|
+
if (!clicked) {
|
|
85
42
|
results.push({ name: friendName, status: '❌ 跳过', detail: '在聊天列表中未找到' });
|
|
86
43
|
continue;
|
|
87
44
|
}
|
|
88
45
|
await page.wait({ time: 2 });
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
async () => {
|
|
92
|
-
const selectors = [
|
|
93
|
-
'.chat-editor [contenteditable="true"]',
|
|
94
|
-
'.chat-input [contenteditable="true"]',
|
|
95
|
-
'[contenteditable="true"]',
|
|
96
|
-
'textarea',
|
|
97
|
-
];
|
|
98
|
-
for (const sel of selectors) {
|
|
99
|
-
const el = document.querySelector(sel);
|
|
100
|
-
if (el && el.offsetParent !== null) {
|
|
101
|
-
el.focus();
|
|
102
|
-
if (el.tagName === 'TEXTAREA' || el.tagName === 'INPUT') {
|
|
103
|
-
el.value = ${JSON.stringify(text)};
|
|
104
|
-
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
105
|
-
} else {
|
|
106
|
-
el.textContent = '';
|
|
107
|
-
el.focus();
|
|
108
|
-
document.execCommand('insertText', false, ${JSON.stringify(text)});
|
|
109
|
-
el.dispatchEvent(new Event('input', { bubbles: true }));
|
|
110
|
-
}
|
|
111
|
-
return { found: true };
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return { found: false };
|
|
115
|
-
}
|
|
116
|
-
`);
|
|
117
|
-
if (!typed.found) {
|
|
46
|
+
const sent = await typeAndSendMessage(page, text);
|
|
47
|
+
if (!sent) {
|
|
118
48
|
results.push({ name: friendName, status: '❌ 失败', detail: '找不到消息输入框' });
|
|
119
49
|
continue;
|
|
120
50
|
}
|
|
121
|
-
await page.wait({ time: 0.5 });
|
|
122
|
-
// Click send
|
|
123
|
-
const sent = await page.evaluate(`
|
|
124
|
-
async () => {
|
|
125
|
-
const btn = document.querySelector('.conversation-editor .submit')
|
|
126
|
-
|| document.querySelector('.submit-content .submit')
|
|
127
|
-
|| document.querySelector('.conversation-operate .submit');
|
|
128
|
-
if (btn) {
|
|
129
|
-
btn.click();
|
|
130
|
-
return { clicked: true };
|
|
131
|
-
}
|
|
132
|
-
return { clicked: false };
|
|
133
|
-
}
|
|
134
|
-
`);
|
|
135
|
-
if (!sent.clicked) {
|
|
136
|
-
await page.pressKey('Enter');
|
|
137
|
-
}
|
|
138
51
|
await page.wait({ time: 1.5 });
|
|
139
52
|
results.push({ name: friendName, status: '✅ 已发送', detail: text });
|
|
140
53
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { requirePage, navigateToChat, fetchFriendList } from './common.js';
|
|
2
3
|
cli({
|
|
3
4
|
site: 'boss',
|
|
4
5
|
name: 'chatlist',
|
|
5
6
|
description: 'BOSS直聘查看聊天列表(招聘端)',
|
|
6
7
|
domain: 'www.zhipin.com',
|
|
7
8
|
strategy: Strategy.COOKIE,
|
|
9
|
+
navigateBefore: false,
|
|
8
10
|
browser: true,
|
|
9
11
|
args: [
|
|
10
12
|
{ name: 'page', type: 'int', default: 1, help: 'Page number' },
|
|
@@ -13,32 +15,13 @@ cli({
|
|
|
13
15
|
],
|
|
14
16
|
columns: ['name', 'job', 'last_msg', 'last_time', 'uid', 'security_id'],
|
|
15
17
|
func: async (page, kwargs) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
await page
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const pageNum = kwargs.page || 1;
|
|
22
|
-
const limit = kwargs.limit || 20;
|
|
23
|
-
const targetUrl = `https://www.zhipin.com/wapi/zprelation/friend/getBossFriendListV2.json?page=${pageNum}&status=0&jobId=${jobId}`;
|
|
24
|
-
const data = await page.evaluate(`
|
|
25
|
-
async () => {
|
|
26
|
-
return new Promise((resolve, reject) => {
|
|
27
|
-
const xhr = new XMLHttpRequest();
|
|
28
|
-
xhr.open('GET', '${targetUrl}', true);
|
|
29
|
-
xhr.withCredentials = true;
|
|
30
|
-
xhr.timeout = 15000;
|
|
31
|
-
xhr.setRequestHeader('Accept', 'application/json');
|
|
32
|
-
xhr.onload = () => { try { resolve(JSON.parse(xhr.responseText)); } catch(e) { reject(new Error('JSON parse failed')); } };
|
|
33
|
-
xhr.onerror = () => reject(new Error('Network Error'));
|
|
34
|
-
xhr.send();
|
|
18
|
+
requirePage(page);
|
|
19
|
+
await navigateToChat(page);
|
|
20
|
+
const friends = await fetchFriendList(page, {
|
|
21
|
+
pageNum: kwargs.page || 1,
|
|
22
|
+
jobId: kwargs['job-id'] || '0',
|
|
35
23
|
});
|
|
36
|
-
|
|
37
|
-
`);
|
|
38
|
-
if (data.code !== 0)
|
|
39
|
-
throw new Error(`API error: ${data.message} (code=${data.code})`);
|
|
40
|
-
const friends = (data.zpData?.friendList || []).slice(0, limit);
|
|
41
|
-
return friends.map((f) => ({
|
|
24
|
+
return friends.slice(0, kwargs.limit || 20).map((f) => ({
|
|
42
25
|
name: f.name || '',
|
|
43
26
|
job: f.jobName || '',
|
|
44
27
|
last_msg: f.lastMessageInfo?.text || '',
|
|
@@ -1,63 +1,32 @@
|
|
|
1
1
|
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
import { requirePage, navigateToChat, bossFetch, findFriendByUid } from './common.js';
|
|
2
3
|
cli({
|
|
3
4
|
site: 'boss',
|
|
4
5
|
name: 'chatmsg',
|
|
5
6
|
description: 'BOSS直聘查看与候选人的聊天消息',
|
|
6
7
|
domain: 'www.zhipin.com',
|
|
7
8
|
strategy: Strategy.COOKIE,
|
|
9
|
+
navigateBefore: false,
|
|
8
10
|
browser: true,
|
|
9
11
|
args: [
|
|
10
|
-
{ name: 'uid', required: true, help: 'Encrypted UID (from chatlist)' },
|
|
12
|
+
{ name: 'uid', required: true, positional: true, help: 'Encrypted UID (from chatlist)' },
|
|
11
13
|
{ name: 'page', type: 'int', default: 1, help: 'Page number' },
|
|
12
14
|
],
|
|
13
15
|
columns: ['from', 'type', 'text', 'time'],
|
|
14
16
|
func: async (page, kwargs) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
await page.
|
|
18
|
-
await page.wait({ time: 2 });
|
|
19
|
-
const uid = kwargs.uid;
|
|
20
|
-
const friendData = await page.evaluate(`
|
|
21
|
-
async () => {
|
|
22
|
-
return new Promise((resolve, reject) => {
|
|
23
|
-
const xhr = new XMLHttpRequest();
|
|
24
|
-
xhr.open('GET', 'https://www.zhipin.com/wapi/zprelation/friend/getBossFriendListV2.json?page=1&status=0&jobId=0', true);
|
|
25
|
-
xhr.withCredentials = true;
|
|
26
|
-
xhr.timeout = 15000;
|
|
27
|
-
xhr.setRequestHeader('Accept', 'application/json');
|
|
28
|
-
xhr.onload = () => { try { resolve(JSON.parse(xhr.responseText)); } catch(e) { reject(e); } };
|
|
29
|
-
xhr.onerror = () => reject(new Error('Network Error'));
|
|
30
|
-
xhr.send();
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
`);
|
|
34
|
-
if (friendData.code !== 0)
|
|
35
|
-
throw new Error('获取好友列表失败');
|
|
36
|
-
const friend = (friendData.zpData?.friendList || []).find((f) => f.encryptUid === uid);
|
|
17
|
+
requirePage(page);
|
|
18
|
+
await navigateToChat(page);
|
|
19
|
+
const friend = await findFriendByUid(page, kwargs.uid);
|
|
37
20
|
if (!friend)
|
|
38
21
|
throw new Error('未找到该候选人');
|
|
39
22
|
const gid = friend.uid;
|
|
40
23
|
const securityId = encodeURIComponent(friend.securityId);
|
|
41
24
|
const msgUrl = `https://www.zhipin.com/wapi/zpchat/boss/historyMsg?gid=${gid}&securityId=${securityId}&page=${kwargs.page}&c=20&src=0`;
|
|
42
|
-
const msgData = await page
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
xhr.withCredentials = true;
|
|
48
|
-
xhr.timeout = 15000;
|
|
49
|
-
xhr.setRequestHeader('Accept', 'application/json');
|
|
50
|
-
xhr.onload = () => { try { resolve(JSON.parse(xhr.responseText)); } catch(e) { resolve({raw: xhr.responseText.substring(0,500)}); } };
|
|
51
|
-
xhr.onerror = () => reject(new Error('Network Error'));
|
|
52
|
-
xhr.send();
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
`);
|
|
56
|
-
if (msgData.raw)
|
|
57
|
-
throw new Error('Non-JSON: ' + msgData.raw);
|
|
58
|
-
if (msgData.code !== 0)
|
|
59
|
-
throw new Error('API error: ' + (msgData.message || msgData.code));
|
|
60
|
-
const TYPE_MAP = { 1: '文本', 2: '图片', 3: '招呼', 4: '简历', 5: '系统', 6: '名片', 7: '语音', 8: '视频', 9: '表情' };
|
|
25
|
+
const msgData = await bossFetch(page, msgUrl);
|
|
26
|
+
const TYPE_MAP = {
|
|
27
|
+
1: '文本', 2: '图片', 3: '招呼', 4: '简历', 5: '系统',
|
|
28
|
+
6: '名片', 7: '语音', 8: '视频', 9: '表情',
|
|
29
|
+
};
|
|
61
30
|
const messages = msgData.zpData?.messages || msgData.zpData?.historyMsgList || [];
|
|
62
31
|
return messages.map((m) => {
|
|
63
32
|
const fromObj = m.from || {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BOSS直聘 common utilities — shared logic for all boss adapters.
|
|
3
|
+
*
|
|
4
|
+
* Consolidates:
|
|
5
|
+
* - Page navigation with cookie context
|
|
6
|
+
* - XHR-based API calls (GET/POST) with automatic login state detection
|
|
7
|
+
* - Cookie expiry error codes (code 7, 37)
|
|
8
|
+
* - Verbose logging
|
|
9
|
+
*/
|
|
10
|
+
import type { IPage } from '../../types.js';
|
|
11
|
+
export interface BossApiResponse {
|
|
12
|
+
code: number;
|
|
13
|
+
message?: string;
|
|
14
|
+
zpData?: any;
|
|
15
|
+
[key: string]: any;
|
|
16
|
+
}
|
|
17
|
+
export interface FetchOptions {
|
|
18
|
+
/** HTTP method, defaults to 'GET' */
|
|
19
|
+
method?: 'GET' | 'POST';
|
|
20
|
+
/** POST body (will be sent as application/x-www-form-urlencoded) */
|
|
21
|
+
body?: string;
|
|
22
|
+
/** XHR timeout in ms, defaults to 15000 */
|
|
23
|
+
timeout?: number;
|
|
24
|
+
/** If true, don't throw on non-zero code — return the raw response */
|
|
25
|
+
allowNonZero?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Assert that page is available (non-null).
|
|
29
|
+
*/
|
|
30
|
+
export declare function requirePage(page: IPage | null): asserts page is IPage;
|
|
31
|
+
/**
|
|
32
|
+
* Navigate to BOSS chat page and wait for it to settle.
|
|
33
|
+
* This establishes the cookie context needed for subsequent API calls.
|
|
34
|
+
*/
|
|
35
|
+
export declare function navigateToChat(page: IPage, waitSeconds?: number): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Navigate to a custom BOSS page (for search/detail that use different pages).
|
|
38
|
+
*/
|
|
39
|
+
export declare function navigateTo(page: IPage, url: string, waitSeconds?: number): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Check if an API response indicates cookie expiry and throw a clear error.
|
|
42
|
+
* Call this after every BOSS API response with a non-zero code.
|
|
43
|
+
*/
|
|
44
|
+
export declare function checkAuth(data: BossApiResponse): void;
|
|
45
|
+
/**
|
|
46
|
+
* Throw if the API response is not code 0.
|
|
47
|
+
* Checks for cookie expiry first, then throws with the provided message.
|
|
48
|
+
*/
|
|
49
|
+
export declare function assertOk(data: BossApiResponse, errorPrefix?: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Make a credentialed XHR request via page.evaluate().
|
|
52
|
+
*
|
|
53
|
+
* This is the single XHR template — no more copy-pasting the same 15-line
|
|
54
|
+
* XMLHttpRequest boilerplate across every adapter.
|
|
55
|
+
*
|
|
56
|
+
* @returns Parsed JSON response
|
|
57
|
+
* @throws On network error, timeout, JSON parse failure, or cookie expiry
|
|
58
|
+
*/
|
|
59
|
+
export declare function bossFetch(page: IPage, url: string, opts?: FetchOptions): Promise<BossApiResponse>;
|
|
60
|
+
/**
|
|
61
|
+
* Fetch the boss friend (chat) list.
|
|
62
|
+
*/
|
|
63
|
+
export declare function fetchFriendList(page: IPage, opts?: {
|
|
64
|
+
pageNum?: number;
|
|
65
|
+
jobId?: string;
|
|
66
|
+
}): Promise<any[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Fetch the recommended candidates (greetRecSortList).
|
|
69
|
+
*/
|
|
70
|
+
export declare function fetchRecommendList(page: IPage): Promise<any[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Find a friend by encryptUid, searching through friend list and optionally greet list.
|
|
73
|
+
* Returns null if not found.
|
|
74
|
+
*/
|
|
75
|
+
export declare function findFriendByUid(page: IPage, encryptUid: string, opts?: {
|
|
76
|
+
maxPages?: number;
|
|
77
|
+
checkGreetList?: boolean;
|
|
78
|
+
}): Promise<any | null>;
|
|
79
|
+
/**
|
|
80
|
+
* Click on a candidate in the chat list by their numeric UID.
|
|
81
|
+
* @returns true if clicked, false if not found
|
|
82
|
+
*/
|
|
83
|
+
export declare function clickCandidateInList(page: IPage, numericUid: string | number): Promise<boolean>;
|
|
84
|
+
/**
|
|
85
|
+
* Type a message into the chat editor and send it.
|
|
86
|
+
* @returns true if sent successfully
|
|
87
|
+
*/
|
|
88
|
+
export declare function typeAndSendMessage(page: IPage, text: string): Promise<boolean>;
|
|
89
|
+
/**
|
|
90
|
+
* Verbose log helper — prints when OPENCLI_VERBOSE or DEBUG=opencli is set.
|
|
91
|
+
*/
|
|
92
|
+
export declare function verbose(msg: string): void;
|