@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
|
@@ -16,6 +16,12 @@ function isExpectedApplePodcastsRestriction(code: number, stderr: string): boole
|
|
|
16
16
|
return /Error \[FETCH_ERROR\]: (Charts API HTTP \d+|Unable to reach Apple Podcasts charts)/.test(stderr);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
function isExpectedGoogleRestriction(code: number, stderr: string): boolean {
|
|
20
|
+
if (code === 0) return false;
|
|
21
|
+
// Network unreachable (DNS/proxy) or HTTP error from Google
|
|
22
|
+
return /fetch failed/.test(stderr) || /Error \[FETCH_ERROR\]: HTTP (403|429|451|503)\b/.test(stderr);
|
|
23
|
+
}
|
|
24
|
+
|
|
19
25
|
// Keep old name as alias for existing tests
|
|
20
26
|
const isExpectedXiaoyuzhouRestriction = isExpectedChineseSiteRestriction;
|
|
21
27
|
|
|
@@ -207,6 +213,64 @@ describe('public commands E2E', () => {
|
|
|
207
213
|
expect(stderr).toMatch(/limit must be a positive integer|Argument "limit" must be a valid number/);
|
|
208
214
|
}, 30_000);
|
|
209
215
|
|
|
216
|
+
// ── google suggest (public JSON API) ──
|
|
217
|
+
it('google suggest returns suggestions', async () => {
|
|
218
|
+
const { stdout, stderr, code } = await runCli(['google', 'suggest', 'python', '-f', 'json']);
|
|
219
|
+
if (isExpectedGoogleRestriction(code, stderr)) {
|
|
220
|
+
console.warn(`google suggest skipped: ${stderr.trim()}`);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
expect(code).toBe(0);
|
|
224
|
+
const data = parseJsonOutput(stdout);
|
|
225
|
+
expect(Array.isArray(data)).toBe(true);
|
|
226
|
+
expect(data.length).toBeGreaterThanOrEqual(1);
|
|
227
|
+
expect(data[0]).toHaveProperty('suggestion');
|
|
228
|
+
}, 30_000);
|
|
229
|
+
|
|
230
|
+
// ── google news (public RSS) ──
|
|
231
|
+
it('google news returns headlines', async () => {
|
|
232
|
+
const { stdout, stderr, code } = await runCli(['google', 'news', '--limit', '3', '-f', 'json']);
|
|
233
|
+
if (isExpectedGoogleRestriction(code, stderr)) {
|
|
234
|
+
console.warn(`google news skipped: ${stderr.trim()}`);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
expect(code).toBe(0);
|
|
238
|
+
const data = parseJsonOutput(stdout);
|
|
239
|
+
expect(Array.isArray(data)).toBe(true);
|
|
240
|
+
expect(data.length).toBeGreaterThanOrEqual(1);
|
|
241
|
+
expect(data[0]).toHaveProperty('title');
|
|
242
|
+
expect(data[0]).toHaveProperty('source');
|
|
243
|
+
expect(data[0]).toHaveProperty('url');
|
|
244
|
+
}, 30_000);
|
|
245
|
+
|
|
246
|
+
it('google news search returns results', async () => {
|
|
247
|
+
const { stdout, stderr, code } = await runCli(['google', 'news', 'AI', '--limit', '3', '-f', 'json']);
|
|
248
|
+
if (isExpectedGoogleRestriction(code, stderr)) {
|
|
249
|
+
console.warn(`google news search skipped: ${stderr.trim()}`);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
expect(code).toBe(0);
|
|
253
|
+
const data = parseJsonOutput(stdout);
|
|
254
|
+
expect(Array.isArray(data)).toBe(true);
|
|
255
|
+
expect(data.length).toBeGreaterThanOrEqual(1);
|
|
256
|
+
expect(data[0]).toHaveProperty('title');
|
|
257
|
+
}, 30_000);
|
|
258
|
+
|
|
259
|
+
// ── google trends (public RSS) ──
|
|
260
|
+
it('google trends returns trending searches', async () => {
|
|
261
|
+
const { stdout, stderr, code } = await runCli(['google', 'trends', '--region', 'US', '--limit', '3', '-f', 'json']);
|
|
262
|
+
if (isExpectedGoogleRestriction(code, stderr)) {
|
|
263
|
+
console.warn(`google trends skipped: ${stderr.trim()}`);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
expect(code).toBe(0);
|
|
267
|
+
const data = parseJsonOutput(stdout);
|
|
268
|
+
expect(Array.isArray(data)).toBe(true);
|
|
269
|
+
expect(data.length).toBeGreaterThanOrEqual(1);
|
|
270
|
+
expect(data[0]).toHaveProperty('title');
|
|
271
|
+
expect(data[0]).toHaveProperty('traffic');
|
|
272
|
+
}, 30_000);
|
|
273
|
+
|
|
210
274
|
// ── weread (Chinese site — may return empty on overseas CI runners) ──
|
|
211
275
|
it('weread search returns books', async () => {
|
|
212
276
|
const { stdout, stderr, code } = await runCli(['weread', 'search', 'python', '--limit', '3', '-f', 'json']);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const newCommand: import("../../registry.js").CliCommand;
|
package/dist/clis/feishu/new.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
|
-
import { cli, Strategy } from '../../registry.js';
|
|
3
|
-
export const newCommand = cli({
|
|
4
|
-
site: 'feishu',
|
|
5
|
-
name: 'new',
|
|
6
|
-
description: 'Create a new message or document in Feishu',
|
|
7
|
-
domain: 'localhost',
|
|
8
|
-
strategy: Strategy.PUBLIC,
|
|
9
|
-
browser: false,
|
|
10
|
-
args: [],
|
|
11
|
-
columns: ['Status'],
|
|
12
|
-
func: async (page) => {
|
|
13
|
-
try {
|
|
14
|
-
execSync("osascript -e 'tell application \"Lark\" to activate'");
|
|
15
|
-
execSync("osascript -e 'delay 0.3'");
|
|
16
|
-
// Cmd+N for new conversation/document
|
|
17
|
-
execSync("osascript " +
|
|
18
|
-
"-e 'tell application \"System Events\"' " +
|
|
19
|
-
"-e 'keystroke \"n\" using command down' " +
|
|
20
|
-
"-e 'end tell'");
|
|
21
|
-
return [{ Status: 'New item dialog opened (Cmd+N)' }];
|
|
22
|
-
}
|
|
23
|
-
catch (err) {
|
|
24
|
-
return [{ Status: 'Error: ' + err.message }];
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const readCommand: import("../../registry.js").CliCommand;
|
package/dist/clis/feishu/read.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { execSync, spawnSync } from 'node:child_process';
|
|
2
|
-
import { cli, Strategy } from '../../registry.js';
|
|
3
|
-
export const readCommand = cli({
|
|
4
|
-
site: 'feishu',
|
|
5
|
-
name: 'read',
|
|
6
|
-
description: 'Read the current chat content by selecting all and copying',
|
|
7
|
-
domain: 'localhost',
|
|
8
|
-
strategy: Strategy.PUBLIC,
|
|
9
|
-
browser: false,
|
|
10
|
-
args: [],
|
|
11
|
-
columns: ['Content'],
|
|
12
|
-
func: async (page) => {
|
|
13
|
-
try {
|
|
14
|
-
let clipBackup = '';
|
|
15
|
-
try {
|
|
16
|
-
clipBackup = execSync('pbpaste', { encoding: 'utf-8' });
|
|
17
|
-
}
|
|
18
|
-
catch { /* empty */ }
|
|
19
|
-
execSync("osascript -e 'tell application \"Lark\" to activate'");
|
|
20
|
-
execSync("osascript -e 'delay 0.3'");
|
|
21
|
-
execSync("osascript " +
|
|
22
|
-
"-e 'tell application \"System Events\"' " +
|
|
23
|
-
"-e 'keystroke \"a\" using command down' " +
|
|
24
|
-
"-e 'delay 0.2' " +
|
|
25
|
-
"-e 'keystroke \"c\" using command down' " +
|
|
26
|
-
"-e 'delay 0.2' " +
|
|
27
|
-
"-e 'end tell'");
|
|
28
|
-
const content = execSync('pbpaste', { encoding: 'utf-8' }).trim();
|
|
29
|
-
if (clipBackup) {
|
|
30
|
-
spawnSync('pbcopy', { input: clipBackup });
|
|
31
|
-
}
|
|
32
|
-
// Deselect
|
|
33
|
-
execSync("osascript -e 'tell application \"System Events\" to key code 53'");
|
|
34
|
-
return [{ Content: content || '(no content captured)' }];
|
|
35
|
-
}
|
|
36
|
-
catch (err) {
|
|
37
|
-
return [{ Content: 'Error: ' + err.message }];
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const searchCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
|
-
import { cli, Strategy } from '../../registry.js';
|
|
3
|
-
export const searchCommand = cli({
|
|
4
|
-
site: 'feishu',
|
|
5
|
-
name: 'search',
|
|
6
|
-
description: 'Open Feishu global search and type a query (Cmd+K)',
|
|
7
|
-
domain: 'localhost',
|
|
8
|
-
strategy: Strategy.PUBLIC,
|
|
9
|
-
browser: false,
|
|
10
|
-
args: [{ name: 'query', required: true, positional: true, help: 'Search query' }],
|
|
11
|
-
columns: ['Status'],
|
|
12
|
-
func: async (page, kwargs) => {
|
|
13
|
-
const query = kwargs.query;
|
|
14
|
-
try {
|
|
15
|
-
execSync("osascript -e 'tell application \"Lark\" to activate'");
|
|
16
|
-
execSync("osascript -e 'delay 0.3'");
|
|
17
|
-
// Feishu uses Cmd+K for global search (similar to Slack/Notion)
|
|
18
|
-
execSync("osascript " +
|
|
19
|
-
"-e 'tell application \"System Events\"' " +
|
|
20
|
-
"-e 'keystroke \"k\" using command down' " +
|
|
21
|
-
"-e 'delay 0.5' " +
|
|
22
|
-
`-e 'keystroke ${JSON.stringify(query)}' ` +
|
|
23
|
-
"-e 'end tell'");
|
|
24
|
-
return [{ Status: `Searching for: ${query}` }];
|
|
25
|
-
}
|
|
26
|
-
catch (err) {
|
|
27
|
-
return [{ Status: 'Error: ' + err.message }];
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const sendCommand: import("../../registry.js").CliCommand;
|
package/dist/clis/feishu/send.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { execSync, spawnSync } from 'node:child_process';
|
|
2
|
-
import { cli, Strategy } from '../../registry.js';
|
|
3
|
-
export const sendCommand = cli({
|
|
4
|
-
site: 'feishu',
|
|
5
|
-
name: 'send',
|
|
6
|
-
description: 'Send a message in the active Feishu (Lark) conversation',
|
|
7
|
-
domain: 'localhost',
|
|
8
|
-
strategy: Strategy.PUBLIC,
|
|
9
|
-
browser: false,
|
|
10
|
-
args: [{ name: 'text', required: true, positional: true, help: 'Message to send' }],
|
|
11
|
-
columns: ['Status'],
|
|
12
|
-
func: async (page, kwargs) => {
|
|
13
|
-
const text = kwargs.text;
|
|
14
|
-
try {
|
|
15
|
-
// Backup clipboard
|
|
16
|
-
let clipBackup = '';
|
|
17
|
-
try {
|
|
18
|
-
clipBackup = execSync('pbpaste', { encoding: 'utf-8' });
|
|
19
|
-
}
|
|
20
|
-
catch { /* empty */ }
|
|
21
|
-
spawnSync('pbcopy', { input: text });
|
|
22
|
-
execSync("osascript -e 'tell application \"Lark\" to activate'");
|
|
23
|
-
execSync("osascript -e 'delay 0.5'");
|
|
24
|
-
execSync("osascript " +
|
|
25
|
-
"-e 'tell application \"System Events\"' " +
|
|
26
|
-
"-e 'keystroke \"v\" using command down' " +
|
|
27
|
-
"-e 'delay 0.2' " +
|
|
28
|
-
"-e 'keystroke return' " +
|
|
29
|
-
"-e 'end tell'");
|
|
30
|
-
if (clipBackup) {
|
|
31
|
-
spawnSync('pbcopy', { input: clipBackup });
|
|
32
|
-
}
|
|
33
|
-
return [{ Status: 'Success' }];
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
return [{ Status: 'Error: ' + err.message }];
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const statusCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
|
-
import { cli, Strategy } from '../../registry.js';
|
|
3
|
-
export const statusCommand = cli({
|
|
4
|
-
site: 'feishu',
|
|
5
|
-
name: 'status',
|
|
6
|
-
description: 'Check if Feishu (Lark) Desktop is running on macOS',
|
|
7
|
-
domain: 'localhost',
|
|
8
|
-
strategy: Strategy.PUBLIC,
|
|
9
|
-
browser: false,
|
|
10
|
-
args: [],
|
|
11
|
-
columns: ['Status', 'Detail'],
|
|
12
|
-
func: async (page) => {
|
|
13
|
-
try {
|
|
14
|
-
const running = execSync("osascript -e 'application \"Lark\" is running'", { encoding: 'utf-8' }).trim();
|
|
15
|
-
if (running !== 'true') {
|
|
16
|
-
return [{ Status: 'Stopped', Detail: 'Feishu/Lark is not running' }];
|
|
17
|
-
}
|
|
18
|
-
const windowCount = execSync("osascript -e 'tell application \"System Events\" to count windows of application process \"Lark\"'", { encoding: 'utf-8' }).trim();
|
|
19
|
-
return [{
|
|
20
|
-
Status: 'Running',
|
|
21
|
-
Detail: `${windowCount} window(s) open`,
|
|
22
|
-
}];
|
|
23
|
-
}
|
|
24
|
-
catch (err) {
|
|
25
|
-
return [{ Status: 'Error', Detail: err.message }];
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const likeCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '../../registry.js';
|
|
2
|
-
export const likeCommand = cli({
|
|
3
|
-
site: 'neteasemusic',
|
|
4
|
-
name: 'like',
|
|
5
|
-
description: 'Like/unlike the currently playing song',
|
|
6
|
-
domain: 'localhost',
|
|
7
|
-
strategy: Strategy.UI,
|
|
8
|
-
browser: true,
|
|
9
|
-
args: [],
|
|
10
|
-
columns: ['Status'],
|
|
11
|
-
func: async (page) => {
|
|
12
|
-
const result = await page.evaluate(`
|
|
13
|
-
(function() {
|
|
14
|
-
// The like/heart button in the player bar
|
|
15
|
-
const btn = document.querySelector('.m-playbar .icn-love, .m-playbar [class*="like"], .m-player [class*="love"], [data-action="like"]');
|
|
16
|
-
if (!btn) return 'Like button not found';
|
|
17
|
-
|
|
18
|
-
const wasLiked = btn.classList.contains('loved') || btn.classList.contains('active') || btn.getAttribute('data-liked') === 'true';
|
|
19
|
-
btn.click();
|
|
20
|
-
return wasLiked ? 'Unliked' : 'Liked';
|
|
21
|
-
})()
|
|
22
|
-
`);
|
|
23
|
-
return [{ Status: result }];
|
|
24
|
-
},
|
|
25
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const lyricsCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '../../registry.js';
|
|
2
|
-
export const lyricsCommand = cli({
|
|
3
|
-
site: 'neteasemusic',
|
|
4
|
-
name: 'lyrics',
|
|
5
|
-
description: 'Get the lyrics of the currently playing song',
|
|
6
|
-
domain: 'localhost',
|
|
7
|
-
strategy: Strategy.UI,
|
|
8
|
-
browser: true,
|
|
9
|
-
args: [],
|
|
10
|
-
columns: ['Line'],
|
|
11
|
-
func: async (page) => {
|
|
12
|
-
// Try to open lyrics panel if not visible
|
|
13
|
-
await page.evaluate(`
|
|
14
|
-
(function() {
|
|
15
|
-
const btn = document.querySelector('.m-playbar .icn-lyric, [class*="lyric-btn"], [data-action="lyric"]');
|
|
16
|
-
if (btn) btn.click();
|
|
17
|
-
})()
|
|
18
|
-
`);
|
|
19
|
-
await page.wait(1);
|
|
20
|
-
const lyrics = await page.evaluate(`
|
|
21
|
-
(function() {
|
|
22
|
-
// Look for lyrics container
|
|
23
|
-
const selectors = [
|
|
24
|
-
'.m-lyric p, .m-lyric [class*="line"]',
|
|
25
|
-
'[class*="lyric-content"] p',
|
|
26
|
-
'.listlyric li',
|
|
27
|
-
'[class*="lyric"] [class*="line"]',
|
|
28
|
-
'.j-lyric p',
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
for (const sel of selectors) {
|
|
32
|
-
const nodes = document.querySelectorAll(sel);
|
|
33
|
-
if (nodes.length > 0) {
|
|
34
|
-
return Array.from(nodes).map(n => (n.textContent || '').trim()).filter(l => l.length > 0);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Fallback: try the body text for any lyrics-like content
|
|
39
|
-
return [];
|
|
40
|
-
})()
|
|
41
|
-
`);
|
|
42
|
-
if (lyrics.length === 0) {
|
|
43
|
-
return [{ Line: 'No lyrics found. Try opening the lyrics panel first.' }];
|
|
44
|
-
}
|
|
45
|
-
return lyrics.map((line) => ({ Line: line }));
|
|
46
|
-
},
|
|
47
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const nextCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '../../registry.js';
|
|
2
|
-
export const nextCommand = cli({
|
|
3
|
-
site: 'neteasemusic',
|
|
4
|
-
name: 'next',
|
|
5
|
-
description: 'Skip to the next song',
|
|
6
|
-
domain: 'localhost',
|
|
7
|
-
strategy: Strategy.UI,
|
|
8
|
-
browser: true,
|
|
9
|
-
args: [],
|
|
10
|
-
columns: ['Status'],
|
|
11
|
-
func: async (page) => {
|
|
12
|
-
const clicked = await page.evaluate(`
|
|
13
|
-
(function() {
|
|
14
|
-
const btn = document.querySelector('.m-playbar .btnfwd, .m-playbar [class*="next"], .m-player .btn-next, [data-action="next"]');
|
|
15
|
-
if (btn) { btn.click(); return true; }
|
|
16
|
-
return false;
|
|
17
|
-
})()
|
|
18
|
-
`);
|
|
19
|
-
if (!clicked) {
|
|
20
|
-
// Fallback: Ctrl+Right is common next-track shortcut
|
|
21
|
-
await page.pressKey('Control+ArrowRight');
|
|
22
|
-
}
|
|
23
|
-
await page.wait(1);
|
|
24
|
-
return [{ Status: 'Skipped to next song' }];
|
|
25
|
-
},
|
|
26
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const playCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '../../registry.js';
|
|
2
|
-
export const playCommand = cli({
|
|
3
|
-
site: 'neteasemusic',
|
|
4
|
-
name: 'play',
|
|
5
|
-
description: 'Toggle play/pause for the current song',
|
|
6
|
-
domain: 'localhost',
|
|
7
|
-
strategy: Strategy.UI,
|
|
8
|
-
browser: true,
|
|
9
|
-
args: [],
|
|
10
|
-
columns: ['Status'],
|
|
11
|
-
func: async (page) => {
|
|
12
|
-
// Click the play/pause button or use Space key
|
|
13
|
-
const clicked = await page.evaluate(`
|
|
14
|
-
(function() {
|
|
15
|
-
const btn = document.querySelector('.m-playbar .btnp, .m-playbar [class*="play"], .m-player .btn-play, [data-action="play"]');
|
|
16
|
-
if (btn) { btn.click(); return true; }
|
|
17
|
-
return false;
|
|
18
|
-
})()
|
|
19
|
-
`);
|
|
20
|
-
if (!clicked) {
|
|
21
|
-
// Fallback: use Space key which is the universal play/pause shortcut
|
|
22
|
-
await page.pressKey('Space');
|
|
23
|
-
}
|
|
24
|
-
return [{ Status: 'Play/Pause toggled' }];
|
|
25
|
-
},
|
|
26
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const playingCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '../../registry.js';
|
|
2
|
-
export const playingCommand = cli({
|
|
3
|
-
site: 'neteasemusic',
|
|
4
|
-
name: 'playing',
|
|
5
|
-
description: 'Get the currently playing song info',
|
|
6
|
-
domain: 'localhost',
|
|
7
|
-
strategy: Strategy.UI,
|
|
8
|
-
browser: true,
|
|
9
|
-
args: [],
|
|
10
|
-
columns: ['Title', 'Artist', 'Album', 'Duration', 'Progress'],
|
|
11
|
-
func: async (page) => {
|
|
12
|
-
const info = await page.evaluate(`
|
|
13
|
-
(function() {
|
|
14
|
-
// NeteaseMusic player bar is at the bottom
|
|
15
|
-
const selectors = {
|
|
16
|
-
title: '.m-playbar .j-song .name, .m-playbar .song .name, [class*="playing"] .name, .m-player .name',
|
|
17
|
-
artist: '.m-playbar .j-song .by, .m-playbar .song .by, [class*="playing"] .artist, .m-player .by',
|
|
18
|
-
album: '.m-playbar .j-song .album, [class*="playing"] .album',
|
|
19
|
-
time: '.m-playbar .j-dur, .m-playbar .time, .m-player .time',
|
|
20
|
-
progress: '.m-playbar .barbg .rng, .m-playbar [role="progressbar"], .m-player [class*="progress"]',
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
function getText(sel) {
|
|
24
|
-
for (const s of sel.split(',')) {
|
|
25
|
-
const el = document.querySelector(s.trim());
|
|
26
|
-
if (el) return (el.textContent || el.innerText || '').trim();
|
|
27
|
-
}
|
|
28
|
-
return '';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const title = getText(selectors.title);
|
|
32
|
-
const artist = getText(selectors.artist);
|
|
33
|
-
const album = getText(selectors.album);
|
|
34
|
-
const time = getText(selectors.time);
|
|
35
|
-
|
|
36
|
-
// Try to get playback progress from the progress bar width
|
|
37
|
-
let progress = '';
|
|
38
|
-
const bar = document.querySelector('.m-playbar .barbg .rng, [class*="progress"] [class*="played"]');
|
|
39
|
-
if (bar) {
|
|
40
|
-
const style = bar.getAttribute('style') || '';
|
|
41
|
-
const match = style.match(/width:\\s*(\\d+\\.?\\d*)%/);
|
|
42
|
-
if (match) progress = match[1] + '%';
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (!title) {
|
|
46
|
-
// Fallback: try document title which often contains "songName - NeteaseMusic"
|
|
47
|
-
const docTitle = document.title;
|
|
48
|
-
if (docTitle && !docTitle.includes('NeteaseMusic')) {
|
|
49
|
-
return { Title: docTitle, Artist: '', Album: '', Duration: '', Progress: '' };
|
|
50
|
-
}
|
|
51
|
-
return { Title: 'No song playing', Artist: '—', Album: '—', Duration: '—', Progress: '—' };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return { Title: title, Artist: artist, Album: album, Duration: time, Progress: progress };
|
|
55
|
-
})()
|
|
56
|
-
`);
|
|
57
|
-
return [info];
|
|
58
|
-
},
|
|
59
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const playlistCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '../../registry.js';
|
|
2
|
-
export const playlistCommand = cli({
|
|
3
|
-
site: 'neteasemusic',
|
|
4
|
-
name: 'playlist',
|
|
5
|
-
description: 'Show the current playback queue / playlist',
|
|
6
|
-
domain: 'localhost',
|
|
7
|
-
strategy: Strategy.UI,
|
|
8
|
-
browser: true,
|
|
9
|
-
args: [],
|
|
10
|
-
columns: ['Index', 'Title', 'Artist'],
|
|
11
|
-
func: async (page) => {
|
|
12
|
-
// Open the playlist panel (usually a button at the bottom bar)
|
|
13
|
-
await page.evaluate(`
|
|
14
|
-
(function() {
|
|
15
|
-
const btn = document.querySelector('.m-playbar .icn-list, .m-playbar [class*="playlist"], [data-action="playlist"], .m-playbar .btnlist');
|
|
16
|
-
if (btn) btn.click();
|
|
17
|
-
})()
|
|
18
|
-
`);
|
|
19
|
-
await page.wait(1);
|
|
20
|
-
const items = await page.evaluate(`
|
|
21
|
-
(function() {
|
|
22
|
-
const results = [];
|
|
23
|
-
// Playlist panel items
|
|
24
|
-
const rows = document.querySelectorAll('.m-playlist li, [class*="playlist-panel"] li, .listlyric li, .j-playlist li');
|
|
25
|
-
|
|
26
|
-
rows.forEach((row, i) => {
|
|
27
|
-
const nameEl = row.querySelector('.name, [class*="name"], a, span:first-child');
|
|
28
|
-
const artistEl = row.querySelector('.by, [class*="artist"], .ar');
|
|
29
|
-
|
|
30
|
-
const title = nameEl ? (nameEl.getAttribute('title') || nameEl.textContent || '').trim() : (row.textContent || '').trim();
|
|
31
|
-
const artist = artistEl ? (artistEl.textContent || '').trim() : '';
|
|
32
|
-
|
|
33
|
-
if (title && title.length > 0) {
|
|
34
|
-
results.push({ Index: i + 1, Title: title.substring(0, 80), Artist: artist });
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
return results;
|
|
39
|
-
})()
|
|
40
|
-
`);
|
|
41
|
-
if (items.length === 0) {
|
|
42
|
-
return [{ Index: 0, Title: 'Playlist is empty or panel not open', Artist: '—' }];
|
|
43
|
-
}
|
|
44
|
-
return items;
|
|
45
|
-
},
|
|
46
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const prevCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '../../registry.js';
|
|
2
|
-
export const prevCommand = cli({
|
|
3
|
-
site: 'neteasemusic',
|
|
4
|
-
name: 'prev',
|
|
5
|
-
description: 'Go back to the previous song',
|
|
6
|
-
domain: 'localhost',
|
|
7
|
-
strategy: Strategy.UI,
|
|
8
|
-
browser: true,
|
|
9
|
-
args: [],
|
|
10
|
-
columns: ['Status'],
|
|
11
|
-
func: async (page) => {
|
|
12
|
-
const clicked = await page.evaluate(`
|
|
13
|
-
(function() {
|
|
14
|
-
const btn = document.querySelector('.m-playbar .btnbak, .m-playbar [class*="prev"], .m-player .btn-prev, [data-action="prev"]');
|
|
15
|
-
if (btn) { btn.click(); return true; }
|
|
16
|
-
return false;
|
|
17
|
-
})()
|
|
18
|
-
`);
|
|
19
|
-
if (!clicked) {
|
|
20
|
-
await page.pressKey('Control+ArrowLeft');
|
|
21
|
-
}
|
|
22
|
-
await page.wait(1);
|
|
23
|
-
return [{ Status: 'Went to previous song' }];
|
|
24
|
-
},
|
|
25
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const searchCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '../../registry.js';
|
|
2
|
-
export const searchCommand = cli({
|
|
3
|
-
site: 'neteasemusic',
|
|
4
|
-
name: 'search',
|
|
5
|
-
description: 'Search for songs, artists, albums, or playlists',
|
|
6
|
-
domain: 'localhost',
|
|
7
|
-
strategy: Strategy.UI,
|
|
8
|
-
browser: true,
|
|
9
|
-
args: [{ name: 'query', required: true, positional: true, help: 'Search query' }],
|
|
10
|
-
columns: ['Index', 'Title', 'Artist'],
|
|
11
|
-
func: async (page, kwargs) => {
|
|
12
|
-
const query = kwargs.query;
|
|
13
|
-
// Focus and fill the search box
|
|
14
|
-
await page.evaluate(`
|
|
15
|
-
(function(q) {
|
|
16
|
-
const input = document.querySelector('.m-search input, #srch, [class*="search"] input, input[type="search"]');
|
|
17
|
-
if (!input) throw new Error('Search input not found');
|
|
18
|
-
input.focus();
|
|
19
|
-
const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
|
|
20
|
-
setter.call(input, q);
|
|
21
|
-
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
22
|
-
})(${JSON.stringify(query)})
|
|
23
|
-
`);
|
|
24
|
-
await page.pressKey('Enter');
|
|
25
|
-
await page.wait(2);
|
|
26
|
-
// Scrape results
|
|
27
|
-
const results = await page.evaluate(`
|
|
28
|
-
(function() {
|
|
29
|
-
const items = [];
|
|
30
|
-
// Song list items in search results
|
|
31
|
-
const rows = document.querySelectorAll('.srchsongst li, .m-table tbody tr, [class*="songlist"] [class*="item"], table tbody tr');
|
|
32
|
-
|
|
33
|
-
rows.forEach((row, i) => {
|
|
34
|
-
if (i >= 20) return;
|
|
35
|
-
const nameEl = row.querySelector('.sn, .name a, [class*="songName"], td:nth-child(2) a, b[title]');
|
|
36
|
-
const artistEl = row.querySelector('.ar, .artist, [class*="artist"], td:nth-child(4) a, td:nth-child(3) a');
|
|
37
|
-
|
|
38
|
-
const title = nameEl ? (nameEl.getAttribute('title') || nameEl.textContent || '').trim() : '';
|
|
39
|
-
const artist = artistEl ? (artistEl.getAttribute('title') || artistEl.textContent || '').trim() : '';
|
|
40
|
-
|
|
41
|
-
if (title) items.push({ Index: i + 1, Title: title, Artist: artist });
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
return items;
|
|
45
|
-
})()
|
|
46
|
-
`);
|
|
47
|
-
if (results.length === 0) {
|
|
48
|
-
return [{ Index: 0, Title: `No results for "${query}"`, Artist: '—' }];
|
|
49
|
-
}
|
|
50
|
-
return results;
|
|
51
|
-
},
|
|
52
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const statusCommand: import("../../registry.js").CliCommand;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '../../registry.js';
|
|
2
|
-
export const statusCommand = cli({
|
|
3
|
-
site: 'neteasemusic',
|
|
4
|
-
name: 'status',
|
|
5
|
-
description: 'Check CDP connection to NeteaseMusic Desktop',
|
|
6
|
-
domain: 'localhost',
|
|
7
|
-
strategy: Strategy.UI,
|
|
8
|
-
browser: true,
|
|
9
|
-
args: [],
|
|
10
|
-
columns: ['Status', 'Url', 'Title'],
|
|
11
|
-
func: async (page) => {
|
|
12
|
-
const url = await page.evaluate('window.location.href');
|
|
13
|
-
const title = await page.evaluate('document.title');
|
|
14
|
-
return [{ Status: 'Connected', Url: url, Title: title }];
|
|
15
|
-
},
|
|
16
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const volumeCommand: import("../../registry.js").CliCommand;
|