@jackwener/opencli 1.3.3 → 1.4.1
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/.github/actions/setup-chrome/action.yml +5 -4
- package/.github/pull_request_template.md +3 -1
- package/.github/workflows/build-extension.yml +7 -1
- package/.github/workflows/ci.yml +46 -6
- package/.github/workflows/docs.yml +1 -1
- package/.github/workflows/e2e-headed.yml +36 -3
- package/.github/workflows/release.yml +1 -1
- package/.github/workflows/security.yml +0 -3
- package/CHANGELOG.md +78 -0
- package/CONTRIBUTING.md +6 -3
- package/PRIVACY.md +57 -0
- package/README.md +31 -4
- package/README.zh-CN.md +31 -4
- package/SKILL.md +107 -2
- package/TESTING.md +1 -0
- package/chatwise-opencli.ps1 +82 -0
- package/dist/analysis.d.ts +38 -0
- package/dist/analysis.js +166 -0
- package/dist/browser/cdp.d.ts +0 -4
- package/dist/browser/cdp.js +53 -41
- package/dist/browser/cdp.test.d.ts +1 -0
- package/dist/browser/cdp.test.js +52 -0
- package/dist/browser/dom-snapshot.d.ts +2 -2
- package/dist/browser/dom-snapshot.js +54 -1
- package/dist/browser/dom-snapshot.test.js +36 -0
- package/dist/browser/index.d.ts +2 -2
- package/dist/browser/index.js +1 -1
- package/dist/browser/mcp.d.ts +0 -2
- package/dist/browser/mcp.js +2 -3
- package/dist/browser/page.d.ts +4 -3
- package/dist/browser/page.js +34 -37
- package/dist/browser/stealth.d.ts +0 -2
- package/dist/browser/stealth.js +24 -9
- package/dist/browser.test.js +2 -2
- package/dist/build-manifest.js +15 -9
- package/dist/build-manifest.test.js +12 -0
- package/dist/cascade.js +4 -2
- package/dist/cli-manifest.json +1325 -256
- package/dist/cli.js +57 -29
- package/dist/clis/_shared/desktop-commands.d.ts +22 -0
- package/dist/clis/_shared/desktop-commands.js +108 -0
- package/dist/clis/antigravity/serve.js +5 -2
- package/dist/clis/apple-podcasts/search.js +2 -1
- package/dist/clis/arxiv/search.js +3 -3
- package/dist/clis/bbc/news.js +0 -1
- package/dist/clis/bilibili/dynamic.test.d.ts +1 -0
- package/dist/clis/bilibili/dynamic.test.js +68 -0
- package/dist/clis/bilibili/favorite.js +4 -2
- package/dist/clis/bilibili/following.js +3 -2
- package/dist/clis/bilibili/subtitle.js +8 -7
- package/dist/clis/bilibili/utils.js +2 -2
- package/dist/clis/boss/batchgreet.js +1 -1
- package/dist/clis/boss/chatlist.js +1 -1
- package/dist/clis/boss/chatmsg.js +1 -1
- package/dist/clis/boss/detail.js +1 -1
- package/dist/clis/boss/exchange.js +1 -1
- package/dist/clis/boss/greet.js +1 -1
- package/dist/clis/boss/invite.js +1 -1
- package/dist/clis/boss/joblist.js +1 -1
- package/dist/clis/boss/mark.js +4 -3
- package/dist/clis/boss/recommend.js +1 -1
- package/dist/clis/boss/resume.js +1 -1
- package/dist/clis/boss/search.js +1 -1
- package/dist/clis/boss/send.js +5 -4
- package/dist/clis/boss/stats.js +1 -1
- package/dist/clis/chatgpt/ask.js +4 -0
- package/dist/clis/chatgpt/new.js +5 -1
- package/dist/clis/chatgpt/read.js +5 -1
- package/dist/clis/chatgpt/send.js +2 -1
- package/dist/clis/chatgpt/status.js +5 -1
- package/dist/clis/chatwise/ask.js +8 -2
- package/dist/clis/chatwise/export.js +2 -0
- package/dist/clis/chatwise/history.js +2 -0
- package/dist/clis/chatwise/model.js +8 -3
- package/dist/clis/chatwise/new.js +3 -18
- package/dist/clis/chatwise/read.js +2 -0
- package/dist/clis/chatwise/screenshot.js +3 -27
- package/dist/clis/chatwise/send.js +8 -2
- package/dist/clis/chatwise/shared.d.ts +2 -0
- package/dist/clis/chatwise/shared.js +6 -0
- package/dist/clis/chatwise/status.js +3 -22
- package/dist/clis/codex/ask.js +6 -2
- package/dist/clis/codex/dump.js +2 -25
- package/dist/clis/codex/new.js +2 -25
- package/dist/clis/codex/screenshot.js +2 -27
- package/dist/clis/codex/send.js +6 -4
- package/dist/clis/codex/status.js +2 -22
- package/dist/clis/ctrip/search.js +0 -1
- package/dist/clis/cursor/ask.js +2 -1
- package/dist/clis/cursor/composer.js +2 -1
- package/dist/clis/cursor/dump.js +2 -25
- package/dist/clis/cursor/new.js +2 -18
- package/dist/clis/cursor/read.js +2 -1
- package/dist/clis/cursor/screenshot.js +1 -30
- package/dist/clis/cursor/send.js +2 -1
- package/dist/clis/cursor/status.js +2 -21
- package/dist/clis/dictionary/examples.yaml +25 -0
- package/dist/clis/dictionary/search.yaml +27 -0
- package/dist/clis/dictionary/synonyms.yaml +25 -0
- package/dist/clis/douban/book-hot.js +1 -1
- package/dist/clis/douban/movie-hot.js +1 -1
- package/dist/clis/douban/search.js +1 -1
- package/dist/clis/douban/utils.d.ts +4 -1
- package/dist/clis/douban/utils.js +156 -1
- package/dist/clis/doubao/ask.js +1 -1
- package/dist/clis/doubao/new.js +1 -1
- package/dist/clis/doubao/read.js +1 -1
- package/dist/clis/doubao/send.js +1 -1
- package/dist/clis/doubao/status.js +1 -1
- package/dist/clis/doubao-app/ask.js +1 -1
- package/dist/clis/doubao-app/new.js +1 -1
- package/dist/clis/doubao-app/read.js +1 -1
- package/dist/clis/doubao-app/send.js +1 -1
- package/dist/clis/douyin/_shared/browser-fetch.d.ts +10 -0
- package/dist/clis/douyin/_shared/browser-fetch.js +30 -0
- package/dist/clis/douyin/_shared/browser-fetch.test.d.ts +1 -0
- package/dist/clis/douyin/_shared/browser-fetch.test.js +31 -0
- package/dist/clis/douyin/_shared/creation-id.d.ts +1 -0
- package/dist/clis/douyin/_shared/creation-id.js +5 -0
- package/dist/clis/douyin/_shared/creation-id.test.d.ts +1 -0
- package/dist/clis/douyin/_shared/creation-id.test.js +22 -0
- package/dist/clis/douyin/_shared/imagex-upload.d.ts +20 -0
- package/dist/clis/douyin/_shared/imagex-upload.js +53 -0
- package/dist/clis/douyin/_shared/imagex-upload.test.d.ts +1 -0
- package/dist/clis/douyin/_shared/imagex-upload.test.js +87 -0
- package/dist/clis/douyin/_shared/sts2.d.ts +8 -0
- package/dist/clis/douyin/_shared/sts2.js +15 -0
- package/dist/clis/douyin/_shared/text-extra.d.ts +18 -0
- package/dist/clis/douyin/_shared/text-extra.js +15 -0
- package/dist/clis/douyin/_shared/text-extra.test.d.ts +1 -0
- package/dist/clis/douyin/_shared/text-extra.test.js +37 -0
- package/dist/clis/douyin/_shared/timing.d.ts +2 -0
- package/dist/clis/douyin/_shared/timing.js +22 -0
- package/dist/clis/douyin/_shared/timing.test.d.ts +1 -0
- package/dist/clis/douyin/_shared/timing.test.js +28 -0
- package/dist/clis/douyin/_shared/tos-upload-short-read.test.d.ts +11 -0
- package/dist/clis/douyin/_shared/tos-upload-short-read.test.js +83 -0
- package/dist/clis/douyin/_shared/tos-upload.d.ts +53 -0
- package/dist/clis/douyin/_shared/tos-upload.js +295 -0
- package/dist/clis/douyin/_shared/tos-upload.test.d.ts +1 -0
- package/dist/clis/douyin/_shared/tos-upload.test.js +229 -0
- package/dist/clis/douyin/_shared/transcode.d.ts +27 -0
- package/dist/clis/douyin/_shared/transcode.js +45 -0
- package/dist/clis/douyin/_shared/transcode.test.d.ts +1 -0
- package/dist/clis/douyin/_shared/transcode.test.js +93 -0
- package/dist/clis/douyin/_shared/types.d.ts +26 -0
- package/dist/clis/douyin/_shared/types.js +1 -0
- package/dist/clis/douyin/activities.d.ts +1 -0
- package/dist/clis/douyin/activities.js +20 -0
- package/dist/clis/douyin/activities.test.d.ts +1 -0
- package/dist/clis/douyin/activities.test.js +22 -0
- package/dist/clis/douyin/collections.d.ts +1 -0
- package/dist/clis/douyin/collections.js +22 -0
- package/dist/clis/douyin/collections.test.d.ts +1 -0
- package/dist/clis/douyin/collections.test.js +23 -0
- package/dist/clis/douyin/delete.d.ts +1 -0
- package/dist/clis/douyin/delete.js +18 -0
- package/dist/clis/douyin/delete.test.d.ts +1 -0
- package/dist/clis/douyin/delete.test.js +11 -0
- package/dist/clis/douyin/draft.d.ts +14 -0
- package/dist/clis/douyin/draft.js +237 -0
- package/dist/clis/douyin/draft.test.d.ts +1 -0
- package/dist/clis/douyin/draft.test.js +11 -0
- package/dist/clis/douyin/drafts.d.ts +1 -0
- package/dist/clis/douyin/drafts.js +23 -0
- package/dist/clis/douyin/drafts.test.d.ts +1 -0
- package/dist/clis/douyin/drafts.test.js +11 -0
- package/dist/clis/douyin/hashtag.d.ts +1 -0
- package/dist/clis/douyin/hashtag.js +45 -0
- package/dist/clis/douyin/hashtag.test.d.ts +1 -0
- package/dist/clis/douyin/hashtag.test.js +25 -0
- package/dist/clis/douyin/location.d.ts +1 -0
- package/dist/clis/douyin/location.js +24 -0
- package/dist/clis/douyin/location.test.d.ts +1 -0
- package/dist/clis/douyin/location.test.js +23 -0
- package/dist/clis/douyin/profile.d.ts +1 -0
- package/dist/clis/douyin/profile.js +28 -0
- package/dist/clis/douyin/profile.test.d.ts +1 -0
- package/dist/clis/douyin/profile.test.js +11 -0
- package/dist/clis/douyin/publish.d.ts +14 -0
- package/dist/clis/douyin/publish.js +288 -0
- package/dist/clis/douyin/publish.test.d.ts +1 -0
- package/dist/clis/douyin/publish.test.js +38 -0
- package/dist/clis/douyin/stats.d.ts +1 -0
- package/dist/clis/douyin/stats.js +27 -0
- package/dist/clis/douyin/stats.test.d.ts +1 -0
- package/dist/clis/douyin/stats.test.js +22 -0
- package/dist/clis/douyin/update.d.ts +1 -0
- package/dist/clis/douyin/update.js +31 -0
- package/dist/clis/douyin/update.test.d.ts +1 -0
- package/dist/clis/douyin/update.test.js +11 -0
- package/dist/clis/douyin/videos.d.ts +1 -0
- package/dist/clis/douyin/videos.js +34 -0
- package/dist/clis/douyin/videos.test.d.ts +1 -0
- package/dist/clis/douyin/videos.test.js +11 -0
- package/dist/clis/grok/ask.d.ts +4 -0
- package/dist/clis/grok/ask.js +28 -10
- package/dist/clis/grok/ask.test.js +18 -0
- package/dist/clis/hackernews/search.yaml +1 -1
- package/dist/clis/instagram/search.yaml +2 -1
- package/dist/clis/jd/item.d.ts +1 -0
- package/dist/clis/jd/item.js +96 -0
- package/dist/clis/jd/item.test.d.ts +1 -0
- package/dist/clis/jd/item.test.js +28 -0
- package/dist/clis/jike/feed.js +1 -1
- package/dist/clis/jike/search.js +1 -1
- package/dist/clis/linkedin/search.js +5 -4
- package/dist/clis/linkedin/timeline.d.ts +21 -0
- package/dist/clis/linkedin/timeline.js +503 -0
- package/dist/clis/linkedin/timeline.test.d.ts +1 -0
- package/dist/clis/linkedin/timeline.test.js +81 -0
- package/dist/clis/linux-do/search.yaml +3 -1
- package/dist/clis/medium/feed.js +1 -1
- package/dist/clis/medium/search.js +2 -2
- package/dist/clis/medium/user.js +1 -1
- package/dist/clis/medium/{shared.js → utils.js} +2 -1
- package/dist/clis/pixiv/detail.yaml +49 -0
- package/dist/clis/pixiv/download.d.ts +7 -0
- package/dist/clis/pixiv/download.js +78 -0
- package/dist/clis/pixiv/download.test.d.ts +1 -0
- package/dist/clis/pixiv/download.test.js +87 -0
- package/dist/clis/pixiv/illusts.d.ts +8 -0
- package/dist/clis/pixiv/illusts.js +65 -0
- package/dist/clis/pixiv/illusts.test.d.ts +1 -0
- package/dist/clis/pixiv/illusts.test.js +99 -0
- package/dist/clis/pixiv/ranking.yaml +53 -0
- package/dist/clis/pixiv/search.d.ts +6 -0
- package/dist/clis/pixiv/search.js +43 -0
- package/dist/clis/pixiv/search.test.d.ts +1 -0
- package/dist/clis/pixiv/search.test.js +83 -0
- package/dist/clis/pixiv/test-utils.d.ts +12 -0
- package/dist/clis/pixiv/test-utils.js +23 -0
- package/dist/clis/pixiv/user.yaml +46 -0
- package/dist/clis/pixiv/utils.d.ts +27 -0
- package/dist/clis/pixiv/utils.js +49 -0
- package/dist/clis/reddit/comment.js +2 -1
- package/dist/clis/reddit/read.js +4 -3
- package/dist/clis/reddit/read.test.d.ts +1 -0
- package/dist/clis/reddit/read.test.js +28 -0
- package/dist/clis/reddit/save.js +2 -1
- package/dist/clis/reddit/saved.js +7 -3
- package/dist/clis/reddit/subscribe.js +2 -1
- package/dist/clis/reddit/upvote.js +2 -1
- package/dist/clis/reddit/upvoted.js +7 -3
- package/dist/clis/reuters/search.js +0 -1
- package/dist/clis/sinablog/article.js +1 -1
- package/dist/clis/sinablog/hot.js +1 -1
- package/dist/clis/sinablog/user.js +1 -1
- package/dist/clis/substack/feed.js +1 -1
- package/dist/clis/substack/publication.js +1 -1
- package/dist/clis/substack/search.js +3 -2
- package/dist/clis/substack/{shared.js → utils.js} +3 -2
- package/dist/clis/tiktok/search.yaml +2 -1
- package/dist/clis/twitter/accept.js +2 -1
- package/dist/clis/twitter/article.js +4 -1
- package/dist/clis/twitter/block.js +2 -1
- package/dist/clis/twitter/bookmark.js +2 -1
- package/dist/clis/twitter/bookmarks.js +3 -2
- package/dist/clis/twitter/delete.js +2 -1
- package/dist/clis/twitter/follow.js +2 -1
- package/dist/clis/twitter/followers.js +3 -2
- package/dist/clis/twitter/following.js +3 -2
- package/dist/clis/twitter/hide-reply.js +2 -1
- package/dist/clis/twitter/like.js +2 -1
- package/dist/clis/twitter/notifications.js +2 -1
- package/dist/clis/twitter/post.js +2 -1
- package/dist/clis/twitter/profile.js +5 -2
- package/dist/clis/twitter/reply-dm.js +2 -1
- package/dist/clis/twitter/reply.js +2 -1
- package/dist/clis/twitter/search.js +32 -13
- package/dist/clis/twitter/search.test.d.ts +1 -0
- package/dist/clis/twitter/search.test.js +156 -0
- package/dist/clis/twitter/thread.js +2 -2
- package/dist/clis/twitter/timeline.js +3 -2
- package/dist/clis/twitter/trending.js +3 -2
- package/dist/clis/twitter/unblock.js +2 -1
- package/dist/clis/twitter/unbookmark.js +2 -1
- package/dist/clis/twitter/unfollow.js +2 -1
- package/dist/clis/v2ex/daily.js +3 -2
- package/dist/clis/v2ex/me.js +3 -2
- package/dist/clis/v2ex/notifications.js +4 -4
- package/dist/clis/web/read.d.ts +16 -0
- package/dist/clis/web/read.js +202 -0
- package/dist/clis/weibo/comments.d.ts +1 -0
- package/dist/clis/weibo/comments.js +53 -0
- package/dist/clis/weibo/feed.d.ts +1 -0
- package/dist/clis/weibo/feed.js +56 -0
- package/dist/clis/weibo/hot.js +0 -1
- package/dist/clis/weibo/me.d.ts +1 -0
- package/dist/clis/weibo/me.js +76 -0
- package/dist/clis/weibo/post.d.ts +1 -0
- package/dist/clis/weibo/post.js +75 -0
- package/dist/clis/weibo/user.d.ts +1 -0
- package/dist/clis/weibo/user.js +63 -0
- package/dist/clis/weibo/utils.d.ts +6 -0
- package/dist/clis/weibo/utils.js +30 -0
- package/dist/clis/weread/search.js +3 -2
- package/dist/clis/xueqiu/danjuan-utils.d.ts +55 -0
- package/dist/clis/xueqiu/danjuan-utils.js +126 -0
- package/dist/clis/xueqiu/danjuan-utils.test.d.ts +1 -0
- package/dist/clis/xueqiu/danjuan-utils.test.js +41 -0
- package/dist/clis/xueqiu/fund-holdings.d.ts +1 -0
- package/dist/clis/xueqiu/fund-holdings.js +28 -0
- package/dist/clis/xueqiu/fund-snapshot.d.ts +1 -0
- package/dist/clis/xueqiu/fund-snapshot.js +25 -0
- package/dist/clis/xueqiu/search.yaml +2 -1
- package/dist/clis/yahoo-finance/quote.js +0 -1
- package/dist/clis/youtube/channel.d.ts +1 -0
- package/dist/clis/youtube/channel.js +150 -0
- package/dist/clis/youtube/comments.d.ts +1 -0
- package/dist/clis/youtube/comments.js +95 -0
- package/dist/clis/youtube/search.js +0 -1
- package/dist/clis/youtube/transcript.js +5 -4
- package/dist/clis/youtube/video.js +3 -2
- package/dist/clis/zhihu/search.yaml +2 -1
- package/dist/daemon.js +7 -3
- package/dist/discovery.js +11 -10
- package/dist/doctor.js +2 -1
- package/dist/download/index.d.ts +4 -12
- package/dist/download/index.js +33 -12
- package/dist/download/index.test.js +79 -2
- package/dist/download/media-download.js +4 -2
- package/dist/engine.test.js +76 -4
- package/dist/execution.d.ts +1 -9
- package/dist/execution.js +56 -46
- package/dist/explore.js +12 -111
- package/dist/external-clis.yaml +0 -25
- package/dist/external.js +7 -5
- package/dist/external.test.js +4 -0
- package/dist/generate.d.ts +0 -9
- package/dist/generate.js +4 -20
- package/dist/hooks.d.ts +46 -0
- package/dist/hooks.js +56 -0
- package/dist/hooks.test.d.ts +4 -0
- package/dist/hooks.test.js +92 -0
- package/dist/interceptor.js +70 -23
- package/dist/main.js +2 -0
- package/dist/output.js +12 -6
- package/dist/pipeline/executor.js +1 -1
- package/dist/pipeline/steps/browser.js +1 -3
- package/dist/pipeline/steps/download.js +42 -26
- package/dist/pipeline/steps/download.test.d.ts +1 -0
- package/dist/pipeline/steps/download.test.js +101 -0
- package/dist/pipeline/steps/fetch.js +40 -22
- package/dist/pipeline/steps/fetch.test.d.ts +1 -0
- package/dist/pipeline/steps/fetch.test.js +123 -0
- package/dist/pipeline/steps/transform.js +2 -6
- package/dist/pipeline/template.js +66 -52
- package/dist/pipeline/template.test.js +28 -0
- package/dist/pipeline/transform.test.js +18 -0
- package/dist/plugin.d.ts +40 -1
- package/dist/plugin.js +214 -17
- package/dist/plugin.test.d.ts +1 -1
- package/dist/plugin.test.js +219 -3
- package/dist/record.js +6 -98
- package/dist/registry-api.d.ts +2 -0
- package/dist/registry-api.js +1 -0
- package/dist/registry.d.ts +5 -2
- package/dist/registry.js +1 -2
- package/dist/runtime.d.ts +0 -1
- package/dist/runtime.js +14 -4
- package/dist/snapshotFormatter.d.ts +7 -14
- package/dist/snapshotFormatter.js +38 -78
- package/dist/utils.d.ts +9 -0
- package/dist/utils.js +29 -0
- package/dist/validate.js +3 -5
- package/dist/weread-search-regression.test.d.ts +1 -0
- package/dist/weread-search-regression.test.js +39 -0
- package/dist/yaml-schema.d.ts +26 -0
- package/dist/yaml-schema.js +5 -0
- package/docs/.vitepress/config.mts +16 -0
- package/docs/adapters/browser/dictionary.md +27 -0
- package/docs/adapters/browser/douyin.md +75 -0
- package/docs/adapters/browser/jd.md +27 -0
- package/docs/adapters/browser/linkedin.md +6 -0
- package/docs/adapters/browser/pixiv.md +92 -0
- package/docs/adapters/browser/twitter.md +6 -0
- package/docs/adapters/browser/web.md +30 -0
- package/docs/adapters/browser/xueqiu.md +27 -9
- package/docs/adapters/index.md +9 -2
- package/docs/comparison.md +125 -0
- package/docs/developer/contributing.md +21 -2
- package/docs/developer/testing.md +14 -8
- package/docs/developer/ts-adapter.md +18 -0
- package/docs/developer/yaml-adapter.md +16 -0
- package/docs/guide/plugins.md +10 -0
- package/docs/zh/guide/plugins.md +10 -0
- package/extension/dist/background.js +100 -35
- package/extension/manifest.json +6 -2
- package/extension/package.json +1 -1
- package/extension/popup.html +84 -0
- package/extension/popup.js +25 -0
- package/extension/src/background.test.ts +46 -1
- package/extension/src/background.ts +128 -34
- package/extension/src/cdp.ts +9 -9
- package/package.json +3 -2
- package/scripts/check-doc-coverage.sh +2 -0
- package/src/analysis.ts +170 -0
- package/src/browser/cdp.test.ts +66 -0
- package/src/browser/cdp.ts +59 -44
- package/src/browser/dom-snapshot.test.ts +42 -0
- package/src/browser/dom-snapshot.ts +56 -3
- package/src/browser/index.ts +2 -2
- package/src/browser/mcp.ts +2 -4
- package/src/browser/page.ts +34 -37
- package/src/browser/stealth.ts +24 -10
- package/src/browser.test.ts +2 -2
- package/src/build-manifest.test.ts +14 -0
- package/src/build-manifest.ts +13 -31
- package/src/cascade.ts +5 -3
- package/src/cli.ts +66 -34
- package/src/clis/_shared/desktop-commands.ts +121 -0
- package/src/clis/antigravity/serve.ts +6 -3
- package/src/clis/apple-podcasts/search.ts +2 -1
- package/src/clis/arxiv/search.ts +3 -3
- package/src/clis/bbc/news.ts +0 -1
- package/src/clis/bilibili/dynamic.test.ts +79 -0
- package/src/clis/bilibili/favorite.ts +5 -2
- package/src/clis/bilibili/following.ts +3 -2
- package/src/clis/bilibili/subtitle.ts +8 -7
- package/src/clis/bilibili/utils.ts +2 -2
- package/src/clis/boss/batchgreet.ts +1 -1
- package/src/clis/boss/chatlist.ts +1 -1
- package/src/clis/boss/chatmsg.ts +1 -1
- package/src/clis/boss/detail.ts +1 -1
- package/src/clis/boss/exchange.ts +1 -1
- package/src/clis/boss/greet.ts +1 -1
- package/src/clis/boss/invite.ts +1 -1
- package/src/clis/boss/joblist.ts +1 -1
- package/src/clis/boss/mark.ts +4 -3
- package/src/clis/boss/recommend.ts +1 -1
- package/src/clis/boss/resume.ts +1 -1
- package/src/clis/boss/search.ts +1 -1
- package/src/clis/boss/send.ts +5 -4
- package/src/clis/boss/stats.ts +1 -1
- package/src/clis/chatgpt/ask.ts +5 -0
- package/src/clis/chatgpt/new.ts +7 -2
- package/src/clis/chatgpt/read.ts +7 -2
- package/src/clis/chatgpt/send.ts +3 -2
- package/src/clis/chatgpt/status.ts +6 -1
- package/src/clis/chatwise/ask.ts +7 -2
- package/src/clis/chatwise/export.ts +2 -0
- package/src/clis/chatwise/history.ts +2 -0
- package/src/clis/chatwise/model.ts +7 -3
- package/src/clis/chatwise/new.ts +3 -20
- package/src/clis/chatwise/read.ts +2 -0
- package/src/clis/chatwise/screenshot.ts +3 -32
- package/src/clis/chatwise/send.ts +7 -2
- package/src/clis/chatwise/shared.ts +8 -0
- package/src/clis/chatwise/status.ts +3 -24
- package/src/clis/codex/ask.ts +5 -2
- package/src/clis/codex/dump.ts +2 -27
- package/src/clis/codex/new.ts +2 -28
- package/src/clis/codex/screenshot.ts +2 -32
- package/src/clis/codex/send.ts +5 -4
- package/src/clis/codex/status.ts +2 -24
- package/src/clis/ctrip/search.ts +0 -1
- package/src/clis/cursor/ask.ts +2 -1
- package/src/clis/cursor/composer.ts +2 -1
- package/src/clis/cursor/dump.ts +2 -27
- package/src/clis/cursor/new.ts +2 -20
- package/src/clis/cursor/read.ts +2 -1
- package/src/clis/cursor/screenshot.ts +1 -36
- package/src/clis/cursor/send.ts +2 -1
- package/src/clis/cursor/status.ts +2 -22
- package/src/clis/dictionary/examples.yaml +25 -0
- package/src/clis/dictionary/search.yaml +27 -0
- package/src/clis/dictionary/synonyms.yaml +25 -0
- package/src/clis/douban/book-hot.ts +1 -1
- package/src/clis/douban/movie-hot.ts +1 -1
- package/src/clis/douban/search.ts +1 -1
- package/src/clis/douban/utils.ts +165 -1
- package/src/clis/doubao/ask.ts +1 -1
- package/src/clis/doubao/new.ts +1 -1
- package/src/clis/doubao/read.ts +1 -1
- package/src/clis/doubao/send.ts +1 -1
- package/src/clis/doubao/status.ts +1 -1
- package/src/clis/doubao-app/ask.ts +1 -1
- package/src/clis/doubao-app/new.ts +1 -1
- package/src/clis/doubao-app/read.ts +1 -1
- package/src/clis/doubao-app/send.ts +1 -1
- package/src/clis/douyin/_shared/browser-fetch.test.ts +38 -0
- package/src/clis/douyin/_shared/browser-fetch.ts +45 -0
- package/src/clis/douyin/_shared/creation-id.test.ts +26 -0
- package/src/clis/douyin/_shared/creation-id.ts +8 -0
- package/src/clis/douyin/_shared/imagex-upload.test.ts +113 -0
- package/src/clis/douyin/_shared/imagex-upload.ts +76 -0
- package/src/clis/douyin/_shared/sts2.ts +20 -0
- package/src/clis/douyin/_shared/text-extra.test.ts +42 -0
- package/src/clis/douyin/_shared/text-extra.ts +33 -0
- package/src/clis/douyin/_shared/timing.test.ts +38 -0
- package/src/clis/douyin/_shared/timing.ts +22 -0
- package/src/clis/douyin/_shared/tos-upload-short-read.test.ts +102 -0
- package/src/clis/douyin/_shared/tos-upload.test.ts +281 -0
- package/src/clis/douyin/_shared/tos-upload.ts +444 -0
- package/src/clis/douyin/_shared/transcode.test.ts +117 -0
- package/src/clis/douyin/_shared/transcode.ts +78 -0
- package/src/clis/douyin/_shared/types.ts +29 -0
- package/src/clis/douyin/activities.test.ts +25 -0
- package/src/clis/douyin/activities.ts +23 -0
- package/src/clis/douyin/collections.test.ts +26 -0
- package/src/clis/douyin/collections.ts +25 -0
- package/src/clis/douyin/delete.test.ts +12 -0
- package/src/clis/douyin/delete.ts +20 -0
- package/src/clis/douyin/draft.test.ts +12 -0
- package/src/clis/douyin/draft.ts +282 -0
- package/src/clis/douyin/drafts.test.ts +12 -0
- package/src/clis/douyin/drafts.ts +27 -0
- package/src/clis/douyin/hashtag.test.ts +28 -0
- package/src/clis/douyin/hashtag.ts +56 -0
- package/src/clis/douyin/location.test.ts +26 -0
- package/src/clis/douyin/location.ts +27 -0
- package/src/clis/douyin/profile.test.ts +12 -0
- package/src/clis/douyin/profile.ts +37 -0
- package/src/clis/douyin/publish.test.ts +45 -0
- package/src/clis/douyin/publish.ts +340 -0
- package/src/clis/douyin/stats.test.ts +25 -0
- package/src/clis/douyin/stats.ts +30 -0
- package/src/clis/douyin/update.test.ts +12 -0
- package/src/clis/douyin/update.ts +43 -0
- package/src/clis/douyin/videos.test.ts +12 -0
- package/src/clis/douyin/videos.ts +49 -0
- package/src/clis/grok/ask.test.ts +25 -0
- package/src/clis/grok/ask.ts +25 -12
- package/src/clis/hackernews/search.yaml +1 -1
- package/src/clis/instagram/search.yaml +2 -1
- package/src/clis/jd/item.test.ts +35 -0
- package/src/clis/jd/item.ts +101 -0
- package/src/clis/jike/feed.ts +1 -1
- package/src/clis/jike/search.ts +1 -1
- package/src/clis/linkedin/search.ts +5 -4
- package/src/clis/linkedin/timeline.test.ts +99 -0
- package/src/clis/linkedin/timeline.ts +532 -0
- package/src/clis/linux-do/search.yaml +3 -1
- package/src/clis/medium/feed.ts +1 -1
- package/src/clis/medium/search.ts +2 -2
- package/src/clis/medium/user.ts +1 -1
- package/src/clis/medium/{shared.ts → utils.ts} +2 -1
- package/src/clis/pixiv/detail.yaml +49 -0
- package/src/clis/pixiv/download.test.ts +114 -0
- package/src/clis/pixiv/download.ts +91 -0
- package/src/clis/pixiv/illusts.test.ts +115 -0
- package/src/clis/pixiv/illusts.ts +78 -0
- package/src/clis/pixiv/ranking.yaml +53 -0
- package/src/clis/pixiv/search.test.ts +97 -0
- package/src/clis/pixiv/search.ts +53 -0
- package/src/clis/pixiv/test-utils.ts +29 -0
- package/src/clis/pixiv/user.yaml +46 -0
- package/src/clis/pixiv/utils.ts +62 -0
- package/src/clis/reddit/comment.ts +2 -1
- package/src/clis/reddit/read.test.ts +34 -0
- package/src/clis/reddit/read.ts +4 -3
- package/src/clis/reddit/save.ts +2 -1
- package/src/clis/reddit/saved.ts +6 -2
- package/src/clis/reddit/subscribe.ts +2 -1
- package/src/clis/reddit/upvote.ts +2 -1
- package/src/clis/reddit/upvoted.ts +6 -2
- package/src/clis/reuters/search.ts +0 -1
- package/src/clis/sinablog/article.ts +1 -1
- package/src/clis/sinablog/hot.ts +1 -1
- package/src/clis/sinablog/user.ts +1 -1
- package/src/clis/substack/feed.ts +1 -1
- package/src/clis/substack/publication.ts +1 -1
- package/src/clis/substack/search.ts +3 -2
- package/src/clis/substack/{shared.ts → utils.ts} +3 -2
- package/src/clis/tiktok/search.yaml +2 -1
- package/src/clis/twitter/accept.ts +2 -1
- package/src/clis/twitter/article.ts +3 -1
- package/src/clis/twitter/block.ts +2 -1
- package/src/clis/twitter/bookmark.ts +2 -1
- package/src/clis/twitter/bookmarks.ts +3 -2
- package/src/clis/twitter/delete.ts +2 -1
- package/src/clis/twitter/follow.ts +2 -1
- package/src/clis/twitter/followers.ts +3 -2
- package/src/clis/twitter/following.ts +3 -2
- package/src/clis/twitter/hide-reply.ts +2 -1
- package/src/clis/twitter/like.ts +2 -1
- package/src/clis/twitter/notifications.ts +2 -1
- package/src/clis/twitter/post.ts +2 -1
- package/src/clis/twitter/profile.ts +4 -2
- package/src/clis/twitter/reply-dm.ts +2 -1
- package/src/clis/twitter/reply.ts +2 -1
- package/src/clis/twitter/search.test.ts +180 -0
- package/src/clis/twitter/search.ts +40 -14
- package/src/clis/twitter/thread.ts +2 -2
- package/src/clis/twitter/timeline.ts +3 -2
- package/src/clis/twitter/trending.ts +3 -2
- package/src/clis/twitter/unblock.ts +2 -1
- package/src/clis/twitter/unbookmark.ts +2 -1
- package/src/clis/twitter/unfollow.ts +2 -1
- package/src/clis/v2ex/daily.ts +3 -2
- package/src/clis/v2ex/me.ts +3 -2
- package/src/clis/v2ex/notifications.ts +3 -4
- package/src/clis/web/read.ts +210 -0
- package/src/clis/weibo/comments.ts +54 -0
- package/src/clis/weibo/feed.ts +57 -0
- package/src/clis/weibo/hot.ts +0 -1
- package/src/clis/weibo/me.ts +77 -0
- package/src/clis/weibo/post.ts +77 -0
- package/src/clis/weibo/user.ts +64 -0
- package/src/clis/weibo/utils.ts +32 -0
- package/src/clis/weread/search.ts +3 -2
- package/src/clis/xueqiu/danjuan-utils.test.ts +49 -0
- package/src/clis/xueqiu/danjuan-utils.ts +176 -0
- package/src/clis/xueqiu/fund-holdings.ts +32 -0
- package/src/clis/xueqiu/fund-snapshot.ts +27 -0
- package/src/clis/xueqiu/search.yaml +2 -1
- package/src/clis/yahoo-finance/quote.ts +0 -1
- package/src/clis/youtube/channel.ts +155 -0
- package/src/clis/youtube/comments.ts +97 -0
- package/src/clis/youtube/search.ts +0 -1
- package/src/clis/youtube/transcript.ts +5 -4
- package/src/clis/youtube/video.ts +3 -2
- package/src/clis/zhihu/search.yaml +2 -1
- package/src/daemon.ts +5 -4
- package/src/discovery.ts +12 -34
- package/src/doctor.ts +3 -2
- package/src/download/index.test.ts +93 -2
- package/src/download/index.ts +44 -23
- package/src/download/media-download.ts +5 -3
- package/src/engine.test.ts +84 -3
- package/src/execution.ts +62 -46
- package/src/explore.ts +21 -90
- package/src/external-clis.yaml +0 -25
- package/src/external.test.ts +9 -0
- package/src/external.ts +12 -10
- package/src/generate.ts +4 -41
- package/src/hooks.test.ts +126 -0
- package/src/hooks.ts +90 -0
- package/src/interceptor.ts +73 -23
- package/src/main.ts +2 -0
- package/src/output.ts +14 -6
- package/src/pipeline/executor.ts +1 -1
- package/src/pipeline/steps/browser.ts +1 -3
- package/src/pipeline/steps/download.test.ts +136 -0
- package/src/pipeline/steps/download.ts +47 -34
- package/src/pipeline/steps/fetch.test.ts +179 -0
- package/src/pipeline/steps/fetch.ts +39 -23
- package/src/pipeline/steps/transform.ts +2 -6
- package/src/pipeline/template.test.ts +28 -0
- package/src/pipeline/template.ts +67 -79
- package/src/pipeline/transform.test.ts +20 -0
- package/src/plugin.test.ts +251 -3
- package/src/plugin.ts +265 -21
- package/src/record.ts +12 -84
- package/src/registry-api.ts +2 -0
- package/src/registry.ts +7 -4
- package/src/runtime.ts +14 -4
- package/src/snapshotFormatter.ts +43 -121
- package/src/utils.ts +39 -0
- package/src/validate.ts +3 -5
- package/src/weread-search-regression.test.ts +44 -0
- package/src/yaml-schema.ts +28 -0
- package/tests/e2e/browser-auth.test.ts +25 -0
- package/tests/e2e/browser-public-extended.test.ts +162 -0
- package/tests/e2e/browser-public.test.ts +7 -146
- package/tests/e2e/plugin-management.test.ts +137 -0
- package/tests/e2e/public-commands.test.ts +34 -1
- package/vitest.config.ts +33 -8
- package/.github/workflows/pkg-pr-new.yml +0 -30
- package/dist/clis/douban/shared.d.ts +0 -4
- package/dist/clis/douban/shared.js +0 -155
- package/src/clis/douban/shared.ts +0 -165
- /package/dist/clis/boss/{common.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/boss/{common.js → utils.js} +0 -0
- /package/dist/clis/doubao/{common.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/doubao/{common.js → utils.js} +0 -0
- /package/dist/clis/doubao-app/{common.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/doubao-app/{common.js → utils.js} +0 -0
- /package/dist/clis/jike/{shared.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/jike/{shared.js → utils.js} +0 -0
- /package/dist/clis/medium/{shared.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/sinablog/{shared.d.ts → utils.d.ts} +0 -0
- /package/dist/clis/sinablog/{shared.js → utils.js} +0 -0
- /package/dist/clis/substack/{shared.d.ts → utils.d.ts} +0 -0
- /package/src/clis/boss/{common.ts → utils.ts} +0 -0
- /package/src/clis/doubao/{common.ts → utils.ts} +0 -0
- /package/src/clis/doubao-app/{common.ts → utils.ts} +0 -0
- /package/src/clis/jike/{shared.ts → utils.ts} +0 -0
- /package/src/clis/sinablog/{shared.ts → utils.ts} +0 -0
package/src/browser/stealth.ts
CHANGED
|
@@ -9,9 +9,6 @@
|
|
|
9
9
|
* Inspired by puppeteer-extra-plugin-stealth.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
/** Guard flag set on `window` to prevent double-injection. */
|
|
13
|
-
export const STEALTH_GUARD = '__opencli_stealth_applied';
|
|
14
|
-
|
|
15
12
|
/**
|
|
16
13
|
* Return a self-contained JS string that, when evaluated in a page context,
|
|
17
14
|
* applies all stealth patches. Safe to call multiple times — the guard flag
|
|
@@ -20,16 +17,25 @@ export const STEALTH_GUARD = '__opencli_stealth_applied';
|
|
|
20
17
|
export function generateStealthJs(): string {
|
|
21
18
|
return `
|
|
22
19
|
(() => {
|
|
23
|
-
// Guard:
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
20
|
+
// Guard: prevent double-injection across separate CDP evaluations.
|
|
21
|
+
// We cannot use a closure variable (each eval is a fresh scope), and
|
|
22
|
+
// window properties / Symbols are discoverable by anti-bot scripts.
|
|
23
|
+
// Instead, stash the flag in a non-enumerable getter on a built-in
|
|
24
|
+
// prototype that fingerprinters are unlikely to scan.
|
|
25
|
+
const _gProto = EventTarget.prototype;
|
|
26
|
+
const _gKey = '__lsn'; // looks like an internal listener cache
|
|
27
|
+
if (_gProto[_gKey]) return 'skipped';
|
|
28
|
+
try {
|
|
29
|
+
Object.defineProperty(_gProto, _gKey, { value: true, enumerable: false, configurable: true });
|
|
30
|
+
} catch {}
|
|
27
31
|
|
|
28
|
-
// 1. navigator.webdriver →
|
|
32
|
+
// 1. navigator.webdriver → false
|
|
29
33
|
// Most common check; Playwright/Puppeteer/CDP set this to true.
|
|
34
|
+
// Real Chrome returns false (not undefined) — returning undefined is
|
|
35
|
+
// itself a detection signal for advanced fingerprinters.
|
|
30
36
|
try {
|
|
31
37
|
Object.defineProperty(navigator, 'webdriver', {
|
|
32
|
-
get: () =>
|
|
38
|
+
get: () => false,
|
|
33
39
|
configurable: true,
|
|
34
40
|
});
|
|
35
41
|
} catch {}
|
|
@@ -119,9 +125,17 @@ export function generateStealthJs(): string {
|
|
|
119
125
|
// We override the stack property getter on Error.prototype to filter them.
|
|
120
126
|
// Note: Error.prepareStackTrace is V8/Node-only and not available in
|
|
121
127
|
// browser page context, so we use a property descriptor approach instead.
|
|
128
|
+
// We use generic protocol patterns instead of product-specific names to
|
|
129
|
+
// also catch our own injected code frames without leaking identifiers.
|
|
122
130
|
try {
|
|
123
131
|
const _origDescriptor = Object.getOwnPropertyDescriptor(Error.prototype, 'stack');
|
|
124
|
-
const _cdpPatterns = [
|
|
132
|
+
const _cdpPatterns = [
|
|
133
|
+
'puppeteer_evaluation_script',
|
|
134
|
+
'pptr:',
|
|
135
|
+
'debugger://',
|
|
136
|
+
'__playwright',
|
|
137
|
+
'__puppeteer',
|
|
138
|
+
];
|
|
125
139
|
if (_origDescriptor && _origDescriptor.get) {
|
|
126
140
|
Object.defineProperty(Error.prototype, 'stack', {
|
|
127
141
|
get: function () {
|
package/src/browser.test.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { afterEach, describe, it, expect, vi } from 'vitest';
|
|
2
2
|
import { BrowserBridge, __test__, generateStealthJs } from './browser/index.js';
|
|
3
|
-
import { STEALTH_GUARD } from './browser/stealth.js';
|
|
4
3
|
import * as daemonClient from './browser/daemon-client.js';
|
|
5
4
|
|
|
6
5
|
describe('browser helpers', () => {
|
|
@@ -170,7 +169,8 @@ describe('stealth anti-detection', () => {
|
|
|
170
169
|
|
|
171
170
|
it('includes guard flag to prevent double-injection', () => {
|
|
172
171
|
const js = generateStealthJs();
|
|
173
|
-
|
|
172
|
+
// Guard uses a non-enumerable property on a built-in prototype
|
|
173
|
+
expect(js).toContain("EventTarget.prototype");
|
|
174
174
|
// Guard should check early and return 'skipped'
|
|
175
175
|
expect(js).toContain("return 'skipped'");
|
|
176
176
|
// Normal path returns 'applied'
|
|
@@ -129,4 +129,18 @@ describe('manifest helper rules', () => {
|
|
|
129
129
|
|
|
130
130
|
expect(scanTs(file, 'demo')).toBeNull();
|
|
131
131
|
});
|
|
132
|
+
|
|
133
|
+
it('keeps literal domain and navigateBefore for TS adapters', () => {
|
|
134
|
+
const file = path.join(process.cwd(), 'src', 'clis', 'xueqiu', 'fund-holdings.ts');
|
|
135
|
+
const entry = scanTs(file, 'xueqiu');
|
|
136
|
+
|
|
137
|
+
expect(entry).toMatchObject({
|
|
138
|
+
site: 'xueqiu',
|
|
139
|
+
name: 'fund-holdings',
|
|
140
|
+
domain: 'danjuanfunds.com',
|
|
141
|
+
navigateBefore: 'https://danjuanfunds.com/my-money',
|
|
142
|
+
type: 'ts',
|
|
143
|
+
modulePath: 'xueqiu/fund-holdings.js',
|
|
144
|
+
});
|
|
145
|
+
});
|
|
132
146
|
});
|
package/src/build-manifest.ts
CHANGED
|
@@ -46,33 +46,9 @@ export interface ManifestEntry {
|
|
|
46
46
|
navigateBefore?: boolean | string;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
type?: string;
|
|
51
|
-
default?: unknown;
|
|
52
|
-
required?: boolean;
|
|
53
|
-
positional?: boolean;
|
|
54
|
-
description?: string;
|
|
55
|
-
help?: string;
|
|
56
|
-
choices?: string[];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
interface YamlCliDefinition {
|
|
60
|
-
site?: string;
|
|
61
|
-
name?: string;
|
|
62
|
-
description?: string;
|
|
63
|
-
domain?: string;
|
|
64
|
-
strategy?: string;
|
|
65
|
-
browser?: boolean;
|
|
66
|
-
args?: Record<string, YamlArgDefinition>;
|
|
67
|
-
columns?: string[];
|
|
68
|
-
pipeline?: Record<string, unknown>[];
|
|
69
|
-
timeout?: number;
|
|
70
|
-
navigateBefore?: boolean | string;
|
|
71
|
-
}
|
|
49
|
+
import type { YamlCliDefinition } from './yaml-schema.js';
|
|
72
50
|
|
|
73
|
-
|
|
74
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
75
|
-
}
|
|
51
|
+
import { isRecord } from './utils.js';
|
|
76
52
|
|
|
77
53
|
|
|
78
54
|
function extractBalancedBlock(
|
|
@@ -179,7 +155,8 @@ export function parseTsArgsBlock(argsBlock: string): ManifestEntry['args'] {
|
|
|
179
155
|
choices: parseInlineChoices(body),
|
|
180
156
|
});
|
|
181
157
|
|
|
182
|
-
cursor = objectStart + body.length
|
|
158
|
+
cursor = objectStart + body.length;
|
|
159
|
+
if (cursor <= objectStart) break; // safety: prevent infinite loop
|
|
183
160
|
}
|
|
184
161
|
|
|
185
162
|
return args;
|
|
@@ -283,9 +260,14 @@ export function scanTs(filePath: string, site: string): ManifestEntry | null {
|
|
|
283
260
|
entry.args = parseTsArgsBlock(argsBlock);
|
|
284
261
|
}
|
|
285
262
|
|
|
286
|
-
// Extract navigateBefore: false
|
|
287
|
-
const
|
|
288
|
-
if (
|
|
263
|
+
// Extract navigateBefore: false / true / 'https://...'
|
|
264
|
+
const navBoolMatch = src.match(/navigateBefore\s*:\s*(true|false)/);
|
|
265
|
+
if (navBoolMatch) {
|
|
266
|
+
entry.navigateBefore = navBoolMatch[1] === 'true';
|
|
267
|
+
} else {
|
|
268
|
+
const navStringMatch = src.match(/navigateBefore\s*:\s*['"`]([^'"`]+)['"`]/);
|
|
269
|
+
if (navStringMatch) entry.navigateBefore = navStringMatch[1];
|
|
270
|
+
}
|
|
289
271
|
|
|
290
272
|
return entry;
|
|
291
273
|
} catch (err) {
|
|
@@ -300,7 +282,7 @@ export function scanTs(filePath: string, site: string): ManifestEntry | null {
|
|
|
300
282
|
* prefer the TS version (it self-registers and typically has richer logic).
|
|
301
283
|
*/
|
|
302
284
|
export function shouldReplaceManifestEntry(current: ManifestEntry, next: ManifestEntry): boolean {
|
|
303
|
-
if (current.type === next.type) return
|
|
285
|
+
if (current.type === next.type) return false;
|
|
304
286
|
return current.type === 'yaml' && next.type === 'ts';
|
|
305
287
|
}
|
|
306
288
|
|
package/src/cascade.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import { Strategy } from './registry.js';
|
|
14
14
|
import type { IPage } from './types.js';
|
|
15
|
+
import { getErrorMessage } from './errors.js';
|
|
15
16
|
|
|
16
17
|
/** Strategy cascade order (simplest → most complex) */
|
|
17
18
|
const CASCADE_ORDER: Strategy[] = [
|
|
@@ -128,9 +129,9 @@ export async function probeEndpoint(
|
|
|
128
129
|
result.error = `Strategy ${strategy} requires site-specific implementation`;
|
|
129
130
|
break;
|
|
130
131
|
}
|
|
131
|
-
} catch (err
|
|
132
|
+
} catch (err) {
|
|
132
133
|
result.success = false;
|
|
133
|
-
result.error =
|
|
134
|
+
result.error = getErrorMessage(err);
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
return result;
|
|
@@ -145,9 +146,10 @@ export async function cascadeProbe(
|
|
|
145
146
|
url: string,
|
|
146
147
|
opts: { maxStrategy?: Strategy; timeout?: number } = {},
|
|
147
148
|
): Promise<CascadeResult> {
|
|
148
|
-
const
|
|
149
|
+
const rawIdx = opts.maxStrategy
|
|
149
150
|
? CASCADE_ORDER.indexOf(opts.maxStrategy)
|
|
150
151
|
: CASCADE_ORDER.indexOf(Strategy.HEADER); // Don't auto-try INTERCEPT/UI
|
|
152
|
+
const maxIdx = rawIdx === -1 ? CASCADE_ORDER.indexOf(Strategy.HEADER) : rawIdx;
|
|
151
153
|
|
|
152
154
|
const probes: ProbeResult[] = [];
|
|
153
155
|
|
package/src/cli.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { PKG_VERSION } from './version.js';
|
|
|
15
15
|
import { printCompletionScript } from './completion.js';
|
|
16
16
|
import { loadExternalClis, executeExternalCli, installExternalCli, registerExternalCli, isBinaryInstalled } from './external.js';
|
|
17
17
|
import { registerAllCommands } from './commanderAdapter.js';
|
|
18
|
+
import { getErrorMessage } from './errors.js';
|
|
18
19
|
|
|
19
20
|
export function runCli(BUILTIN_CLIS: string, USER_CLIS: string): void {
|
|
20
21
|
const program = new Command();
|
|
@@ -173,8 +174,6 @@ export function runCli(BUILTIN_CLIS: string, USER_CLIS: string): void {
|
|
|
173
174
|
const r = await generateCliFromUrl({
|
|
174
175
|
url,
|
|
175
176
|
BrowserFactory: getBrowserFactory(),
|
|
176
|
-
builtinClis: BUILTIN_CLIS,
|
|
177
|
-
userClis: USER_CLIS,
|
|
178
177
|
goal: opts.goal,
|
|
179
178
|
site: opts.site,
|
|
180
179
|
workspace,
|
|
@@ -262,8 +261,8 @@ export function runCli(BUILTIN_CLIS: string, USER_CLIS: string): void {
|
|
|
262
261
|
const name = installPlugin(source);
|
|
263
262
|
await discoverPlugins();
|
|
264
263
|
console.log(chalk.green(`✅ Plugin "${name}" installed successfully. Commands are ready to use.`));
|
|
265
|
-
} catch (err
|
|
266
|
-
console.error(chalk.red(`Error: ${err
|
|
264
|
+
} catch (err) {
|
|
265
|
+
console.error(chalk.red(`Error: ${getErrorMessage(err)}`));
|
|
267
266
|
process.exitCode = 1;
|
|
268
267
|
}
|
|
269
268
|
});
|
|
@@ -277,25 +276,69 @@ export function runCli(BUILTIN_CLIS: string, USER_CLIS: string): void {
|
|
|
277
276
|
try {
|
|
278
277
|
uninstallPlugin(name);
|
|
279
278
|
console.log(chalk.green(`✅ Plugin "${name}" uninstalled.`));
|
|
280
|
-
} catch (err
|
|
281
|
-
console.error(chalk.red(`Error: ${err
|
|
279
|
+
} catch (err) {
|
|
280
|
+
console.error(chalk.red(`Error: ${getErrorMessage(err)}`));
|
|
282
281
|
process.exitCode = 1;
|
|
283
282
|
}
|
|
284
283
|
});
|
|
285
284
|
|
|
286
285
|
pluginCmd
|
|
287
286
|
.command('update')
|
|
288
|
-
.description('Update a plugin to the latest version')
|
|
289
|
-
.argument('
|
|
290
|
-
.
|
|
291
|
-
|
|
287
|
+
.description('Update a plugin (or all plugins) to the latest version')
|
|
288
|
+
.argument('[name]', 'Plugin name (required unless --all is passed)')
|
|
289
|
+
.option('--all', 'Update all installed plugins')
|
|
290
|
+
.action(async (name: string | undefined, opts: { all?: boolean }) => {
|
|
291
|
+
if (!name && !opts.all) {
|
|
292
|
+
console.error(chalk.red('Error: Please specify a plugin name or use the --all flag.'));
|
|
293
|
+
process.exitCode = 1;
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (name && opts.all) {
|
|
297
|
+
console.error(chalk.red('Error: Cannot specify both a plugin name and --all.'));
|
|
298
|
+
process.exitCode = 1;
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const { updatePlugin, updateAllPlugins } = await import('./plugin.js');
|
|
292
303
|
const { discoverPlugins } = await import('./discovery.js');
|
|
304
|
+
if (opts.all) {
|
|
305
|
+
const results = updateAllPlugins();
|
|
306
|
+
if (results.length > 0) {
|
|
307
|
+
await discoverPlugins();
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
let hasErrors = false;
|
|
311
|
+
console.log(chalk.bold(' Update Results:'));
|
|
312
|
+
for (const result of results) {
|
|
313
|
+
if (result.success) {
|
|
314
|
+
console.log(` ${chalk.green('✓')} ${result.name}`);
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
hasErrors = true;
|
|
318
|
+
console.log(` ${chalk.red('✗')} ${result.name} — ${chalk.dim(result.error)}`);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (results.length === 0) {
|
|
322
|
+
console.log(chalk.dim(' No plugins installed.'));
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
console.log();
|
|
327
|
+
if (hasErrors) {
|
|
328
|
+
console.error(chalk.red('Completed with some errors.'));
|
|
329
|
+
process.exitCode = 1;
|
|
330
|
+
} else {
|
|
331
|
+
console.log(chalk.green('✅ All plugins updated successfully.'));
|
|
332
|
+
}
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
|
|
293
336
|
try {
|
|
294
|
-
updatePlugin(name);
|
|
337
|
+
updatePlugin(name!);
|
|
295
338
|
await discoverPlugins();
|
|
296
339
|
console.log(chalk.green(`✅ Plugin "${name}" updated successfully.`));
|
|
297
|
-
} catch (err
|
|
298
|
-
console.error(chalk.red(`Error: ${err
|
|
340
|
+
} catch (err) {
|
|
341
|
+
console.error(chalk.red(`Error: ${getErrorMessage(err)}`));
|
|
299
342
|
process.exitCode = 1;
|
|
300
343
|
}
|
|
301
344
|
});
|
|
@@ -326,9 +369,10 @@ export function runCli(BUILTIN_CLIS: string, USER_CLIS: string): void {
|
|
|
326
369
|
console.log(chalk.bold(' Installed plugins'));
|
|
327
370
|
console.log();
|
|
328
371
|
for (const p of plugins) {
|
|
372
|
+
const version = p.version ? chalk.green(` @${p.version}`) : '';
|
|
329
373
|
const cmds = p.commands.length > 0 ? chalk.dim(` (${p.commands.join(', ')})`) : '';
|
|
330
374
|
const src = p.source ? chalk.dim(` ← ${p.source}`) : '';
|
|
331
|
-
console.log(` ${chalk.cyan(p.name)}${cmds}${src}`);
|
|
375
|
+
console.log(` ${chalk.cyan(p.name)}${version}${cmds}${src}`);
|
|
332
376
|
}
|
|
333
377
|
console.log();
|
|
334
378
|
console.log(chalk.dim(` ${plugins.length} plugin(s) installed`));
|
|
@@ -371,8 +415,8 @@ export function runCli(BUILTIN_CLIS: string, USER_CLIS: string): void {
|
|
|
371
415
|
})();
|
|
372
416
|
try {
|
|
373
417
|
executeExternalCli(name, args, externalClis);
|
|
374
|
-
} catch (err
|
|
375
|
-
console.error(chalk.red(`Error: ${err
|
|
418
|
+
} catch (err) {
|
|
419
|
+
console.error(chalk.red(`Error: ${getErrorMessage(err)}`));
|
|
376
420
|
process.exitCode = 1;
|
|
377
421
|
}
|
|
378
422
|
}
|
|
@@ -408,29 +452,17 @@ export function runCli(BUILTIN_CLIS: string, USER_CLIS: string): void {
|
|
|
408
452
|
registerAllCommands(program, siteGroups);
|
|
409
453
|
|
|
410
454
|
// ── Unknown command fallback ──────────────────────────────────────────────
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
'rm', 'sudo', 'dd', 'mkfs', 'fdisk', 'shutdown', 'reboot',
|
|
414
|
-
'kill', 'killall', 'chmod', 'chown', 'passwd', 'su', 'mount',
|
|
415
|
-
'umount', 'format', 'diskutil',
|
|
416
|
-
]);
|
|
455
|
+
// Security: do NOT auto-discover and register arbitrary system binaries.
|
|
456
|
+
// Only explicitly registered external CLIs (via `opencli register`) are allowed.
|
|
417
457
|
|
|
418
458
|
program.on('command:*', (operands: string[]) => {
|
|
419
459
|
const binary = operands[0];
|
|
420
|
-
|
|
421
|
-
console.error(chalk.red(`Refusing to register system command '${binary}'.`));
|
|
422
|
-
process.exitCode = 1;
|
|
423
|
-
return;
|
|
424
|
-
}
|
|
460
|
+
console.error(chalk.red(`error: unknown command '${binary}'`));
|
|
425
461
|
if (isBinaryInstalled(binary)) {
|
|
426
|
-
console.
|
|
427
|
-
registerExternalCli(binary);
|
|
428
|
-
passthroughExternal(binary);
|
|
429
|
-
} else {
|
|
430
|
-
console.error(chalk.red(`error: unknown command '${binary}'`));
|
|
431
|
-
program.outputHelp();
|
|
432
|
-
process.exitCode = 1;
|
|
462
|
+
console.error(chalk.dim(` Tip: '${binary}' exists on your PATH. Use 'opencli register ${binary}' to add it as an external CLI.`));
|
|
433
463
|
}
|
|
464
|
+
program.outputHelp();
|
|
465
|
+
process.exitCode = 1;
|
|
434
466
|
});
|
|
435
467
|
|
|
436
468
|
program.parse();
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared command factories for Electron/desktop app adapters.
|
|
3
|
+
* Eliminates duplicate screenshot/status/new/dump implementations
|
|
4
|
+
* across cursor, codex, chatwise, etc.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import { cli, Strategy } from '../../registry.js';
|
|
9
|
+
import type { IPage } from '../../types.js';
|
|
10
|
+
import type { CliOptions } from '../../registry.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Factory: capture DOM HTML + accessibility snapshot.
|
|
14
|
+
*/
|
|
15
|
+
export function makeScreenshotCommand(site: string, displayName?: string, extra: Partial<CliOptions> = {}) {
|
|
16
|
+
const label = displayName ?? site;
|
|
17
|
+
return cli({
|
|
18
|
+
...extra,
|
|
19
|
+
site,
|
|
20
|
+
name: 'screenshot',
|
|
21
|
+
description: `Capture a snapshot of the current ${label} window (DOM + Accessibility tree)`,
|
|
22
|
+
domain: 'localhost',
|
|
23
|
+
strategy: Strategy.UI,
|
|
24
|
+
browser: true,
|
|
25
|
+
args: [
|
|
26
|
+
{ name: 'output', required: false, help: `Output file path (default: /tmp/${site}-snapshot.txt)` },
|
|
27
|
+
],
|
|
28
|
+
columns: ['Status', 'File'],
|
|
29
|
+
func: async (page: IPage, kwargs: any) => {
|
|
30
|
+
const outputPath = (kwargs.output as string) || `/tmp/${site}-snapshot.txt`;
|
|
31
|
+
|
|
32
|
+
const snap = await page.snapshot({ compact: true });
|
|
33
|
+
const html = await page.evaluate('document.documentElement.outerHTML');
|
|
34
|
+
|
|
35
|
+
const htmlPath = outputPath.replace(/\.\w+$/, '') + '-dom.html';
|
|
36
|
+
const snapPath = outputPath.replace(/\.\w+$/, '') + '-a11y.txt';
|
|
37
|
+
|
|
38
|
+
fs.writeFileSync(htmlPath, html);
|
|
39
|
+
fs.writeFileSync(snapPath, typeof snap === 'string' ? snap : JSON.stringify(snap, null, 2));
|
|
40
|
+
|
|
41
|
+
return [
|
|
42
|
+
{ Status: 'Success', File: htmlPath },
|
|
43
|
+
{ Status: 'Success', File: snapPath },
|
|
44
|
+
];
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Factory: check CDP connection status.
|
|
51
|
+
*/
|
|
52
|
+
export function makeStatusCommand(site: string, displayName?: string, extra: Partial<CliOptions> = {}) {
|
|
53
|
+
const label = displayName ?? site;
|
|
54
|
+
return cli({
|
|
55
|
+
...extra,
|
|
56
|
+
site,
|
|
57
|
+
name: 'status',
|
|
58
|
+
description: `Check active CDP connection to ${label}`,
|
|
59
|
+
domain: 'localhost',
|
|
60
|
+
strategy: Strategy.UI,
|
|
61
|
+
browser: true,
|
|
62
|
+
columns: ['Status', 'Url', 'Title'],
|
|
63
|
+
func: async (page: IPage) => {
|
|
64
|
+
const url = await page.evaluate('window.location.href');
|
|
65
|
+
const title = await page.evaluate('document.title');
|
|
66
|
+
return [{ Status: 'Connected', Url: url, Title: title }];
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Factory: start a new session via Cmd/Ctrl+N.
|
|
73
|
+
*/
|
|
74
|
+
export function makeNewCommand(site: string, displayName?: string, extra: Partial<CliOptions> = {}) {
|
|
75
|
+
const label = displayName ?? site;
|
|
76
|
+
return cli({
|
|
77
|
+
...extra,
|
|
78
|
+
site,
|
|
79
|
+
name: 'new',
|
|
80
|
+
description: `Start a new ${label} session`,
|
|
81
|
+
domain: 'localhost',
|
|
82
|
+
strategy: Strategy.UI,
|
|
83
|
+
browser: true,
|
|
84
|
+
columns: ['Status'],
|
|
85
|
+
func: async (page: IPage) => {
|
|
86
|
+
const isMac = process.platform === 'darwin';
|
|
87
|
+
await page.pressKey(isMac ? 'Meta+N' : 'Control+N');
|
|
88
|
+
await page.wait(1);
|
|
89
|
+
return [{ Status: 'Success' }];
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Factory: dump DOM + snapshot for reverse-engineering.
|
|
96
|
+
*/
|
|
97
|
+
export function makeDumpCommand(site: string) {
|
|
98
|
+
return cli({
|
|
99
|
+
site,
|
|
100
|
+
name: 'dump',
|
|
101
|
+
description: `Dump the DOM and Accessibility tree of ${site} for reverse-engineering`,
|
|
102
|
+
domain: 'localhost',
|
|
103
|
+
strategy: Strategy.UI,
|
|
104
|
+
browser: true,
|
|
105
|
+
columns: ['action', 'files'],
|
|
106
|
+
func: async (page: IPage) => {
|
|
107
|
+
const dom = await page.evaluate('document.body.innerHTML');
|
|
108
|
+
fs.writeFileSync(`/tmp/${site}-dom.html`, dom);
|
|
109
|
+
|
|
110
|
+
const snap = await page.snapshot({ interactive: false });
|
|
111
|
+
fs.writeFileSync(`/tmp/${site}-snapshot.json`, JSON.stringify(snap, null, 2));
|
|
112
|
+
|
|
113
|
+
return [
|
|
114
|
+
{
|
|
115
|
+
action: 'Dom extraction finished',
|
|
116
|
+
files: `/tmp/${site}-dom.html, /tmp/${site}-snapshot.json`,
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';
|
|
14
14
|
import { CDPBridge } from '../../browser/cdp.js';
|
|
15
15
|
import type { IPage } from '../../types.js';
|
|
16
|
+
import { getErrorMessage } from '../../errors.js';
|
|
16
17
|
|
|
17
18
|
// ─── Types ───────────────────────────────────────────────────────────
|
|
18
19
|
|
|
@@ -461,15 +462,17 @@ export async function startServe(opts: { port?: number } = {}): Promise<void> {
|
|
|
461
462
|
cdp = new CDPBridge();
|
|
462
463
|
try {
|
|
463
464
|
page = await cdp.connect({ timeout: 15_000 });
|
|
464
|
-
} catch (err:
|
|
465
|
+
} catch (err: unknown) {
|
|
465
466
|
cdp = null;
|
|
466
|
-
const
|
|
467
|
+
const errMsg = getErrorMessage(err);
|
|
468
|
+
const cause = err instanceof Error ? (err.cause as Record<string, unknown> | undefined) : undefined;
|
|
469
|
+
const isRefused = cause?.code === 'ECONNREFUSED' || errMsg.includes('ECONNREFUSED');
|
|
467
470
|
throw new Error(
|
|
468
471
|
isRefused
|
|
469
472
|
? `Cannot connect to Antigravity at ${endpoint}.\n` +
|
|
470
473
|
' 1. Make sure Antigravity is running\n' +
|
|
471
474
|
' 2. Launch with: --remote-debugging-port=9224'
|
|
472
|
-
: `CDP connection failed: ${
|
|
475
|
+
: `CDP connection failed: ${errMsg}`
|
|
473
476
|
);
|
|
474
477
|
}
|
|
475
478
|
|
|
@@ -12,7 +12,7 @@ cli({
|
|
|
12
12
|
{ name: 'query', positional: true, required: true, help: 'Search keyword' },
|
|
13
13
|
{ name: 'limit', type: 'int', default: 10, help: 'Max results' },
|
|
14
14
|
],
|
|
15
|
-
columns: ['id', 'title', 'author', 'episodes', 'genre'],
|
|
15
|
+
columns: ['id', 'title', 'author', 'episodes', 'genre', 'url'],
|
|
16
16
|
func: async (_page, args) => {
|
|
17
17
|
const term = encodeURIComponent(args.query);
|
|
18
18
|
const limit = Math.max(1, Math.min(Number(args.limit), 25));
|
|
@@ -24,6 +24,7 @@ cli({
|
|
|
24
24
|
author: p.artistName,
|
|
25
25
|
episodes: p.trackCount ?? '-',
|
|
26
26
|
genre: p.primaryGenreName ?? '-',
|
|
27
|
+
url: p.collectionViewUrl || '',
|
|
27
28
|
}));
|
|
28
29
|
},
|
|
29
30
|
});
|
package/src/clis/arxiv/search.ts
CHANGED
|
@@ -12,13 +12,13 @@ cli({
|
|
|
12
12
|
{ name: 'query', positional: true, required: true, help: 'Search keyword (e.g. "attention is all you need")' },
|
|
13
13
|
{ name: 'limit', type: 'int', default: 10, help: 'Max results (max 25)' },
|
|
14
14
|
],
|
|
15
|
-
columns: ['id', 'title', 'authors', 'published'],
|
|
15
|
+
columns: ['id', 'title', 'authors', 'published', 'url'],
|
|
16
16
|
func: async (_page, args) => {
|
|
17
17
|
const limit = Math.max(1, Math.min(Number(args.limit), 25));
|
|
18
|
-
const query = encodeURIComponent(`all:${args.
|
|
18
|
+
const query = encodeURIComponent(`all:${args.query}`);
|
|
19
19
|
const xml = await arxivFetch(`search_query=${query}&max_results=${limit}&sortBy=relevance`);
|
|
20
20
|
const entries = parseEntries(xml);
|
|
21
21
|
if (!entries.length) throw new CliError('NOT_FOUND', 'No papers found', 'Try a different keyword');
|
|
22
|
-
return entries.map(e => ({ id: e.id, title: e.title, authors: e.authors, published: e.published }));
|
|
22
|
+
return entries.map(e => ({ id: e.id, title: e.title, authors: e.authors, published: e.published, url: e.url }));
|
|
23
23
|
},
|
|
24
24
|
});
|
package/src/clis/bbc/news.ts
CHANGED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
const { mockApiGet } = vi.hoisted(() => ({
|
|
4
|
+
mockApiGet: vi.fn(),
|
|
5
|
+
}));
|
|
6
|
+
|
|
7
|
+
vi.mock('./utils.js', () => ({
|
|
8
|
+
apiGet: mockApiGet,
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
import { getRegistry } from '../../registry.js';
|
|
12
|
+
import './dynamic.js';
|
|
13
|
+
|
|
14
|
+
describe('bilibili dynamic adapter', () => {
|
|
15
|
+
const command = getRegistry().get('bilibili/dynamic');
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
mockApiGet.mockReset();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('maps desc text rows from the dynamic feed payload', async () => {
|
|
22
|
+
mockApiGet.mockResolvedValue({
|
|
23
|
+
data: {
|
|
24
|
+
items: [
|
|
25
|
+
{
|
|
26
|
+
id_str: '123',
|
|
27
|
+
modules: {
|
|
28
|
+
module_author: { name: 'Alice' },
|
|
29
|
+
module_dynamic: { desc: { text: 'hello world' } },
|
|
30
|
+
module_stat: { like: { count: 9 } },
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const result = await command!.func!({} as any, { limit: 5 });
|
|
38
|
+
|
|
39
|
+
expect(mockApiGet).toHaveBeenCalledWith({}, '/x/polymer/web-dynamic/v1/feed/all', { params: {}, signed: false });
|
|
40
|
+
expect(result).toEqual([
|
|
41
|
+
{
|
|
42
|
+
id: '123',
|
|
43
|
+
author: 'Alice',
|
|
44
|
+
text: 'hello world',
|
|
45
|
+
likes: 9,
|
|
46
|
+
url: 'https://t.bilibili.com/123',
|
|
47
|
+
},
|
|
48
|
+
]);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('falls back to archive title when desc text is absent', async () => {
|
|
52
|
+
mockApiGet.mockResolvedValue({
|
|
53
|
+
data: {
|
|
54
|
+
items: [
|
|
55
|
+
{
|
|
56
|
+
id_str: '456',
|
|
57
|
+
modules: {
|
|
58
|
+
module_author: { name: 'Bob' },
|
|
59
|
+
module_dynamic: { major: { archive: { title: 'Video title' } } },
|
|
60
|
+
module_stat: { like: { count: 3 } },
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const result = await command!.func!({} as any, { limit: 5 });
|
|
68
|
+
|
|
69
|
+
expect(result).toEqual([
|
|
70
|
+
{
|
|
71
|
+
id: '456',
|
|
72
|
+
author: 'Bob',
|
|
73
|
+
text: 'Video title',
|
|
74
|
+
likes: 3,
|
|
75
|
+
url: 'https://t.bilibili.com/456',
|
|
76
|
+
},
|
|
77
|
+
]);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cli, Strategy } from '../../registry.js';
|
|
2
|
-
import { apiGet, payloadData } from './utils.js';
|
|
2
|
+
import { apiGet, payloadData, getSelfUid } from './utils.js';
|
|
3
3
|
|
|
4
4
|
cli({
|
|
5
5
|
site: 'bilibili',
|
|
@@ -15,9 +15,12 @@ cli({
|
|
|
15
15
|
func: async (page, kwargs) => {
|
|
16
16
|
const { limit = 20, page: pageNum = 1 } = kwargs;
|
|
17
17
|
|
|
18
|
+
// Get current user's UID
|
|
19
|
+
const uid = await getSelfUid(page);
|
|
20
|
+
|
|
18
21
|
// Get default favorite folder ID
|
|
19
22
|
const foldersPayload = await apiGet(page, '/x/v3/fav/folder/created/list-all', {
|
|
20
|
-
params: { up_mid:
|
|
23
|
+
params: { up_mid: uid },
|
|
21
24
|
signed: true,
|
|
22
25
|
});
|
|
23
26
|
const folders = payloadData(foldersPayload)?.list ?? [];
|