@agentrhq/webcmd 0.1.2 → 0.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/README.md +183 -218
- package/cli-manifest.json +16247 -34913
- package/clis/_atlassian/shared.js +1 -1
- package/clis/booking/search.js +4 -4
- package/clis/chatgpt/ask.js +2 -2
- package/clis/chatgpt/utils.js +41 -42
- package/clis/chatgpt/utils.test.js +23 -23
- package/clis/chatgpt-app/ax.js +5 -5
- package/clis/chatgpt-app/ax.test.js +8 -8
- package/clis/chatgpt-app/new.js +2 -2
- package/clis/codex/sidebar.js +1 -1
- package/clis/codex/sidebar.test.js +12 -12
- package/clis/coingecko/top.js +3 -3
- package/clis/dblp/dblp.test.js +1 -1
- package/clis/discord-app/search.js +1 -1
- package/clis/discord-app/utils.js +6 -6
- package/clis/facebook/__fixtures__/notifications-page.html +6 -6
- package/clis/facebook/add-friend.js +2 -2
- package/clis/facebook/feed.js +18 -18
- package/clis/facebook/friends.js +4 -4
- package/clis/facebook/groups.js +3 -3
- package/clis/facebook/join-group.js +2 -2
- package/clis/facebook/marketplace-inbox.js +3 -3
- package/clis/facebook/marketplace-listings.js +1 -1
- package/clis/facebook/notifications.js +14 -15
- package/clis/facebook/notifications.test.js +28 -29
- package/clis/gemini/ask.test.js +12 -12
- package/clis/gemini/deep-research-result.js +2 -2
- package/clis/gemini/deep-research-result.test.js +2 -2
- package/clis/gemini/deep-research.js +2 -2
- package/clis/gemini/deep-research.test.js +1 -1
- package/clis/gemini/models.js +11 -11
- package/clis/gemini/models.test.js +1 -1
- package/clis/gemini/reply-state.test.js +89 -89
- package/clis/gemini/utils.js +41 -41
- package/clis/gemini/utils.test.js +30 -30
- package/clis/geogebra/utils.js +1 -1
- package/clis/google-scholar/search.js +3 -3
- package/clis/grok/delete.js +1 -1
- package/clis/grok/export-all.js +2 -2
- package/clis/grok/export.js +2 -2
- package/clis/grok/pin.js +3 -3
- package/clis/grok/utils.js +12 -12
- package/clis/grok/utils.test.js +2 -2
- package/clis/indeed/indeed.test.js +3 -3
- package/clis/indeed/utils.js +1 -1
- package/clis/instagram/post.js +19 -19
- package/clis/instagram/post.test.js +2 -2
- package/clis/instagram/reel.js +6 -6
- package/clis/linkedin/connect.js +3 -3
- package/clis/linkedin/people-search.js +4 -4
- package/clis/linkedin/profile-experience.js +6 -6
- package/clis/linkedin/profile-experience.test.js +10 -10
- package/clis/linkedin/profile-read.js +1 -1
- package/clis/linkedin/safe-send.js +1 -1
- package/clis/linkedin/search.js +1 -1
- package/clis/linkedin/shared.js +2 -2
- package/clis/linkedin/timeline.js +5 -5
- package/clis/manus/manus.test.js +2 -2
- package/clis/medium/feed.js +3 -3
- package/clis/medium/search.js +3 -3
- package/clis/medium/user.js +3 -3
- package/clis/notebooklm/auth.js +2 -2
- package/clis/notebooklm/note-list.test.js +4 -4
- package/clis/notebooklm/notes-get.test.js +8 -8
- package/clis/notebooklm/source-fulltext.test.js +11 -11
- package/clis/notebooklm/utils.js +28 -28
- package/clis/notebooklm/utils.test.js +10 -10
- package/clis/pixiv/search.test.js +3 -3
- package/clis/qoder/quest.js +2 -2
- package/clis/reddit/home.js +2 -2
- package/clis/reddit/hot.js +1 -1
- package/clis/reddit/read.js +2 -2
- package/clis/reddit/read.test.js +1 -1
- package/clis/reddit/reply.js +2 -2
- package/clis/reddit/whoami.js +2 -2
- package/clis/reuters/article-detail.js +1 -1
- package/clis/reuters/search.js +1 -1
- package/clis/slock/attachment-upload.test.js +1 -1
- package/clis/slock/task-convert.js +1 -1
- package/clis/substack/feed.js +3 -3
- package/clis/substack/publication.js +3 -3
- package/clis/substack/search.js +4 -4
- package/clis/tiktok/comment.js +2 -2
- package/clis/tiktok/follow.js +4 -4
- package/clis/tiktok/like.js +1 -1
- package/clis/tiktok/save.js +1 -1
- package/clis/tiktok/unfollow.js +4 -4
- package/clis/tiktok/unlike.js +1 -1
- package/clis/tiktok/unsave.js +2 -2
- package/clis/tiktok/write-refactor.test.js +5 -5
- package/clis/twitter/accept.js +3 -3
- package/clis/twitter/followers.js +1 -1
- package/clis/twitter/list-remove-core.js +2 -2
- package/clis/twitter/list-tweets.test.js +3 -3
- package/clis/twitter/lists.js +6 -6
- package/clis/twitter/lists.test.js +2 -2
- package/clis/twitter/reply-dm.js +1 -1
- package/clis/twitter/shared.test.js +4 -5
- package/clis/twitter/trending.js +1 -1
- package/clis/twitter/utils.js +1 -1
- package/clis/web/read.js +1 -1
- package/clis/web/read.test.js +2 -2
- package/clis/yahoo-finance/quote.js +1 -1
- package/clis/youtube/history.js +4 -4
- package/clis/youtube/transcript-group.js +1 -1
- package/clis/youtube/transcript-group.test.js +5 -5
- package/clis/youtube/transcript.js +5 -5
- package/clis/youtube/video.js +4 -4
- package/clis/youtube/video.test.js +6 -6
- package/dist/src/browser/analyze.test.js +13 -13
- package/dist/src/browser/bridge-readiness.d.ts +1 -1
- package/dist/src/browser/daemon-client.d.ts +1 -0
- package/dist/src/browser/daemon-client.js +102 -50
- package/dist/src/browser/daemon-client.test.js +104 -19
- package/dist/src/browser/errors.js +11 -0
- package/dist/src/browser/protocol.d.ts +2 -0
- package/dist/src/browser.test.js +2 -2
- package/dist/src/cli-argv-preprocess.d.ts +2 -2
- package/dist/src/cli-argv-preprocess.js +2 -2
- package/dist/src/cli-argv-preprocess.test.js +35 -35
- package/dist/src/cli.js +2 -2
- package/dist/src/cli.test.js +57 -57
- package/dist/src/commanderAdapter.test.js +19 -19
- package/dist/src/convention-audit.js +1 -1
- package/dist/src/daemon/server.js +28 -23
- package/dist/src/daemon/server.test.js +52 -0
- package/dist/src/daemon-utils.d.ts +1 -0
- package/dist/src/daemon-utils.js +9 -0
- package/dist/src/daemon.test.js +10 -1
- package/dist/src/doctor.js +7 -1
- package/dist/src/doctor.test.js +8 -1
- package/dist/src/download/article-download.d.ts +3 -3
- package/dist/src/download/article-download.js +7 -7
- package/dist/src/download/article-download.test.js +6 -6
- package/dist/src/download/index.js +1 -1
- package/dist/src/download/index.test.js +1 -2
- package/dist/src/download/media-download.d.ts +1 -1
- package/dist/src/download/media-download.js +1 -1
- package/dist/src/electron-apps.js +0 -8
- package/dist/src/electron-apps.test.js +2 -11
- package/dist/src/errors.test.js +9 -9
- package/dist/src/execution.js +2 -0
- package/dist/src/execution.test.js +12 -0
- package/dist/src/external-clis.yaml +0 -37
- package/dist/src/external.d.ts +1 -1
- package/dist/src/external.test.js +2 -17
- package/dist/src/generate-release-notes-cli.test.js +140 -0
- package/dist/src/help.d.ts +3 -3
- package/dist/src/help.test.js +8 -8
- package/dist/src/main.js +1 -1
- package/dist/src/manifest-types.d.ts +1 -1
- package/dist/src/node-network.test.js +2 -2
- package/dist/src/output.js +1 -1
- package/dist/src/pipeline/steps/download.test.js +3 -3
- package/dist/src/registry.test.js +2 -2
- package/dist/src/release-notes.d.ts +38 -0
- package/dist/src/release-notes.js +99 -0
- package/dist/src/release-notes.test.js +61 -0
- package/dist/src/serialization.test.js +7 -7
- package/dist/src/snapshotFormatter.js +3 -5
- package/dist/src/snapshotFormatter.test.d.ts +1 -1
- package/dist/src/snapshotFormatter.test.js +50 -50
- package/dist/src/tui.js +1 -1
- package/package.json +4 -1
- package/scripts/generate-release-notes.ts +234 -0
- package/scripts/postinstall.js +1 -1
- package/scripts/silent-column-drop-baseline.json +0 -498
- package/scripts/typed-error-lint-baseline.json +0 -464
- package/skills/webcmd-adapter-author/SKILL.md +216 -213
- package/skills/webcmd-adapter-author/references/adapter-template.md +206 -399
- package/skills/webcmd-adapter-author/references/api-discovery.md +111 -220
- package/skills/webcmd-adapter-author/references/coverage-matrix.md +34 -68
- package/skills/webcmd-adapter-author/references/field-conventions.md +84 -167
- package/skills/webcmd-adapter-author/references/field-decode-playbook.md +60 -146
- package/skills/webcmd-adapter-author/references/jsdom-fixture-pattern.md +111 -178
- package/skills/webcmd-adapter-author/references/output-design.md +47 -125
- package/skills/webcmd-adapter-author/references/site-memory.md +116 -166
- package/skills/webcmd-adapter-author/references/site-recon.md +74 -78
- package/skills/webcmd-adapter-author/references/strategy-selection.md +80 -124
- package/skills/webcmd-adapter-author/references/success-rate-pitfalls.md +80 -105
- package/skills/webcmd-adapter-author/references/typed-errors.md +87 -178
- package/skills/webcmd-autofix/SKILL.md +136 -143
- package/skills/webcmd-sitemap-author/SKILL.md +58 -67
- package/skills/webcmd-sitemap-author/references/sitemap-schema.md +354 -494
- package/skills/webcmd-usage/SKILL.md +106 -97
- package/clis/12306/auth.js +0 -59
- package/clis/12306/me.js +0 -73
- package/clis/12306/orders.js +0 -96
- package/clis/12306/passengers.js +0 -90
- package/clis/12306/price.js +0 -166
- package/clis/12306/stations.js +0 -66
- package/clis/12306/train.js +0 -91
- package/clis/12306/trains.js +0 -166
- package/clis/12306/utils.js +0 -272
- package/clis/12306/utils.test.js +0 -424
- package/clis/1688/assets.js +0 -205
- package/clis/1688/assets.test.js +0 -39
- package/clis/1688/auth.js +0 -46
- package/clis/1688/download.js +0 -77
- package/clis/1688/download.test.js +0 -31
- package/clis/1688/item.js +0 -188
- package/clis/1688/item.test.js +0 -67
- package/clis/1688/search.js +0 -310
- package/clis/1688/search.test.js +0 -75
- package/clis/1688/shared.js +0 -557
- package/clis/1688/shared.test.js +0 -57
- package/clis/1688/store.js +0 -227
- package/clis/1688/store.test.js +0 -62
- package/clis/1point3acres/auth.js +0 -52
- package/clis/1point3acres/digest.js +0 -35
- package/clis/1point3acres/forum.js +0 -51
- package/clis/1point3acres/forums.js +0 -44
- package/clis/1point3acres/hot.js +0 -35
- package/clis/1point3acres/latest.js +0 -35
- package/clis/1point3acres/notifications.js +0 -64
- package/clis/1point3acres/search.js +0 -71
- package/clis/1point3acres/thread.js +0 -117
- package/clis/1point3acres/user.js +0 -77
- package/clis/1point3acres/utils.js +0 -247
- package/clis/36kr/article.js +0 -66
- package/clis/36kr/article.test.js +0 -46
- package/clis/36kr/hot.js +0 -87
- package/clis/36kr/hot.test.js +0 -15
- package/clis/36kr/news.js +0 -52
- package/clis/36kr/news.test.js +0 -85
- package/clis/36kr/search.js +0 -79
- package/clis/51job/company.js +0 -126
- package/clis/51job/detail.js +0 -109
- package/clis/51job/hot.js +0 -56
- package/clis/51job/search.js +0 -80
- package/clis/51job/utils.js +0 -302
- package/clis/51job/utils.test.js +0 -69
- package/clis/aibase/news.js +0 -110
- package/clis/aibase/news.test.js +0 -59
- package/clis/autohome/__fixtures__/catalog.html +0 -11
- package/clis/autohome/__fixtures__/koubei.json +0 -116
- package/clis/autohome/autohome.test.js +0 -115
- package/clis/autohome/brand.js +0 -108
- package/clis/autohome/score.js +0 -103
- package/clis/autohome/utils.js +0 -157
- package/clis/baidu-scholar/search.js +0 -87
- package/clis/baidu-scholar/search.test.js +0 -23
- package/clis/bilibili/auth.js +0 -36
- package/clis/bilibili/comment.js +0 -107
- package/clis/bilibili/comment.test.js +0 -153
- package/clis/bilibili/comments.js +0 -136
- package/clis/bilibili/comments.test.js +0 -142
- package/clis/bilibili/download.js +0 -178
- package/clis/bilibili/download.test.js +0 -173
- package/clis/bilibili/dynamic.js +0 -34
- package/clis/bilibili/dynamic.test.js +0 -68
- package/clis/bilibili/favorite.js +0 -47
- package/clis/bilibili/feed.js +0 -220
- package/clis/bilibili/follow.js +0 -140
- package/clis/bilibili/follow.test.js +0 -203
- package/clis/bilibili/following.js +0 -44
- package/clis/bilibili/history.js +0 -45
- package/clis/bilibili/hot.js +0 -40
- package/clis/bilibili/hot.test.js +0 -17
- package/clis/bilibili/me.js +0 -13
- package/clis/bilibili/ranking.js +0 -25
- package/clis/bilibili/search.js +0 -24
- package/clis/bilibili/subtitle.js +0 -141
- package/clis/bilibili/subtitle.test.js +0 -240
- package/clis/bilibili/summary.js +0 -167
- package/clis/bilibili/summary.test.js +0 -210
- package/clis/bilibili/unfollow.js +0 -121
- package/clis/bilibili/user-videos.js +0 -39
- package/clis/bilibili/utils.js +0 -273
- package/clis/bilibili/utils.test.js +0 -97
- package/clis/bilibili/video.js +0 -155
- package/clis/bilibili/video.test.js +0 -308
- package/clis/boss/auth.js +0 -47
- package/clis/boss/batchgreet.js +0 -61
- package/clis/boss/chatlist.js +0 -116
- package/clis/boss/chatlist.test.js +0 -211
- package/clis/boss/chatmsg.js +0 -117
- package/clis/boss/chatmsg.test.js +0 -230
- package/clis/boss/detail.js +0 -63
- package/clis/boss/exchange.js +0 -46
- package/clis/boss/greet.js +0 -49
- package/clis/boss/invite.js +0 -64
- package/clis/boss/joblist.js +0 -31
- package/clis/boss/mark.js +0 -70
- package/clis/boss/recommend.js +0 -45
- package/clis/boss/resume.js +0 -150
- package/clis/boss/search.js +0 -197
- package/clis/boss/search.test.js +0 -78
- package/clis/boss/send.js +0 -44
- package/clis/boss/stats.js +0 -66
- package/clis/boss/utils.js +0 -468
- package/clis/boss/utils.test.js +0 -34
- package/clis/chaoxing/assignments.js +0 -76
- package/clis/chaoxing/auth.js +0 -54
- package/clis/chaoxing/exams.js +0 -75
- package/clis/chaoxing/utils.js +0 -223
- package/clis/chaoxing/utils.test.js +0 -45
- package/clis/cnki/search.js +0 -61
- package/clis/cnki/search.test.js +0 -18
- package/clis/ctrip/auth.js +0 -50
- package/clis/ctrip/ctrip.test.js +0 -719
- package/clis/ctrip/flight.js +0 -136
- package/clis/ctrip/hotel-search.js +0 -132
- package/clis/ctrip/hotel-suggest.js +0 -45
- package/clis/ctrip/search.js +0 -41
- package/clis/ctrip/utils.js +0 -473
- package/clis/deepseek/ask.js +0 -158
- package/clis/deepseek/ask.test.js +0 -399
- package/clis/deepseek/auth.js +0 -54
- package/clis/deepseek/detail.js +0 -46
- package/clis/deepseek/detail.test.js +0 -81
- package/clis/deepseek/history.js +0 -27
- package/clis/deepseek/new.js +0 -33
- package/clis/deepseek/read.js +0 -25
- package/clis/deepseek/send.js +0 -140
- package/clis/deepseek/send.test.js +0 -107
- package/clis/deepseek/status.js +0 -26
- package/clis/deepseek/utils.js +0 -487
- package/clis/deepseek/utils.test.js +0 -370
- package/clis/dianping/__fixtures__/search.html +0 -168
- package/clis/dianping/__fixtures__/shop.html +0 -6
- package/clis/dianping/auth.js +0 -49
- package/clis/dianping/cityResolver.js +0 -185
- package/clis/dianping/dianping.test.js +0 -578
- package/clis/dianping/search.js +0 -157
- package/clis/dianping/shop.js +0 -173
- package/clis/dianping/utils.js +0 -157
- package/clis/dongchedi/__fixtures__/search.json +0 -60
- package/clis/dongchedi/__fixtures__/series-detail.json +0 -911
- package/clis/dongchedi/__fixtures__/series-score.json +0 -1396
- package/clis/dongchedi/dongchedi.test.js +0 -191
- package/clis/dongchedi/koubei.js +0 -85
- package/clis/dongchedi/models.js +0 -91
- package/clis/dongchedi/score.js +0 -83
- package/clis/dongchedi/search.js +0 -83
- package/clis/dongchedi/series.js +0 -87
- package/clis/dongchedi/specs.js +0 -115
- package/clis/dongchedi/utils.js +0 -180
- package/clis/douban/auth.js +0 -50
- package/clis/douban/book-hot.js +0 -15
- package/clis/douban/download.js +0 -68
- package/clis/douban/download.test.js +0 -170
- package/clis/douban/marks.js +0 -116
- package/clis/douban/movie-hot.js +0 -15
- package/clis/douban/movie-hot.test.js +0 -14
- package/clis/douban/photos.js +0 -35
- package/clis/douban/reviews.js +0 -107
- package/clis/douban/search.js +0 -18
- package/clis/douban/search.test.js +0 -11
- package/clis/douban/subject.js +0 -46
- package/clis/douban/subject.test.js +0 -11
- package/clis/douban/top250.js +0 -68
- package/clis/douban/utils.js +0 -657
- package/clis/douban/utils.test.js +0 -488
- package/clis/doubao/ask.js +0 -40
- package/clis/doubao/auth.js +0 -66
- package/clis/doubao/detail.js +0 -35
- package/clis/doubao/detail.test.js +0 -42
- package/clis/doubao/history.js +0 -30
- package/clis/doubao/history.test.js +0 -37
- package/clis/doubao/meeting-summary.js +0 -41
- package/clis/doubao/meeting-transcript.js +0 -38
- package/clis/doubao/new.js +0 -22
- package/clis/doubao/read.js +0 -21
- package/clis/doubao/send.js +0 -24
- package/clis/doubao/status.js +0 -26
- package/clis/doubao/utils.js +0 -1156
- package/clis/doubao/utils.test.js +0 -396
- package/clis/doubao-app/ask.js +0 -54
- package/clis/doubao-app/dump.js +0 -25
- package/clis/doubao-app/new.js +0 -21
- package/clis/doubao-app/read.js +0 -19
- package/clis/doubao-app/screenshot.js +0 -19
- package/clis/doubao-app/send.js +0 -28
- package/clis/doubao-app/status.js +0 -17
- package/clis/doubao-app/utils.js +0 -110
- package/clis/douyin/_shared/browser-fetch.js +0 -66
- package/clis/douyin/_shared/browser-fetch.test.js +0 -64
- package/clis/douyin/_shared/creation-id.js +0 -5
- package/clis/douyin/_shared/creation-id.test.js +0 -22
- package/clis/douyin/_shared/evaluate-result.js +0 -16
- package/clis/douyin/_shared/imagex-upload.js +0 -53
- package/clis/douyin/_shared/imagex-upload.test.js +0 -87
- package/clis/douyin/_shared/public-api.js +0 -29
- package/clis/douyin/_shared/sts2.js +0 -21
- package/clis/douyin/_shared/sts2.test.js +0 -27
- package/clis/douyin/_shared/text-extra.js +0 -15
- package/clis/douyin/_shared/text-extra.test.js +0 -37
- package/clis/douyin/_shared/timing.js +0 -22
- package/clis/douyin/_shared/timing.test.js +0 -28
- package/clis/douyin/_shared/tos-upload-short-read.test.js +0 -83
- package/clis/douyin/_shared/tos-upload.js +0 -331
- package/clis/douyin/_shared/tos-upload.test.js +0 -229
- package/clis/douyin/_shared/transcode.js +0 -45
- package/clis/douyin/_shared/transcode.test.js +0 -91
- package/clis/douyin/_shared/vod-upload.js +0 -212
- package/clis/douyin/_shared/vod-upload.test.js +0 -38
- package/clis/douyin/activities.js +0 -23
- package/clis/douyin/activities.test.js +0 -55
- package/clis/douyin/auth.js +0 -39
- package/clis/douyin/collections.js +0 -23
- package/clis/douyin/collections.test.js +0 -45
- package/clis/douyin/delete.js +0 -152
- package/clis/douyin/delete.test.js +0 -100
- package/clis/douyin/draft.js +0 -355
- package/clis/douyin/draft.test.js +0 -335
- package/clis/douyin/drafts.js +0 -24
- package/clis/douyin/drafts.test.js +0 -11
- package/clis/douyin/hashtag.js +0 -114
- package/clis/douyin/hashtag.test.js +0 -171
- package/clis/douyin/location.js +0 -25
- package/clis/douyin/location.test.js +0 -23
- package/clis/douyin/profile.js +0 -29
- package/clis/douyin/profile.test.js +0 -46
- package/clis/douyin/publish-upload-id.test.js +0 -206
- package/clis/douyin/publish.js +0 -341
- package/clis/douyin/publish.test.js +0 -38
- package/clis/douyin/search.js +0 -308
- package/clis/douyin/search.test.js +0 -307
- package/clis/douyin/stats.js +0 -28
- package/clis/douyin/stats.test.js +0 -22
- package/clis/douyin/update.js +0 -32
- package/clis/douyin/update.test.js +0 -11
- package/clis/douyin/user-videos.js +0 -82
- package/clis/douyin/user-videos.test.js +0 -151
- package/clis/douyin/videos.js +0 -52
- package/clis/douyin/videos.test.js +0 -54
- package/clis/eastmoney/_secid.js +0 -78
- package/clis/eastmoney/announcement.js +0 -53
- package/clis/eastmoney/convertible.js +0 -74
- package/clis/eastmoney/etf.js +0 -66
- package/clis/eastmoney/holders.js +0 -79
- package/clis/eastmoney/hot-rank.js +0 -51
- package/clis/eastmoney/hot-rank.test.js +0 -59
- package/clis/eastmoney/index-board.js +0 -97
- package/clis/eastmoney/kline.js +0 -88
- package/clis/eastmoney/kuaixun.js +0 -55
- package/clis/eastmoney/longhu.js +0 -68
- package/clis/eastmoney/money-flow.js +0 -79
- package/clis/eastmoney/northbound.js +0 -58
- package/clis/eastmoney/quote.js +0 -108
- package/clis/eastmoney/rank.js +0 -95
- package/clis/eastmoney/sectors.js +0 -77
- package/clis/flomo/auth.js +0 -55
- package/clis/flomo/memos.js +0 -228
- package/clis/flomo/memos.test.js +0 -144
- package/clis/gitee/auth.js +0 -41
- package/clis/gitee/index.js +0 -3
- package/clis/gitee/search.js +0 -137
- package/clis/gitee/search.test.js +0 -65
- package/clis/gitee/trending.js +0 -568
- package/clis/gitee/user.js +0 -200
- package/clis/gitee/user.test.js +0 -63
- package/clis/gov-law/commands.test.js +0 -39
- package/clis/gov-law/recent.js +0 -22
- package/clis/gov-law/search.js +0 -41
- package/clis/gov-law/shared.js +0 -51
- package/clis/gov-policy/__fixtures__/recent.html +0 -16
- package/clis/gov-policy/__fixtures__/search.html +0 -41
- package/clis/gov-policy/gov-policy.test.js +0 -224
- package/clis/gov-policy/recent.js +0 -90
- package/clis/gov-policy/search.js +0 -91
- package/clis/gov-policy/utils.js +0 -54
- package/clis/guazi/__fixtures__/detail.html +0 -7
- package/clis/guazi/__fixtures__/list.html +0 -5
- package/clis/guazi/browse.js +0 -95
- package/clis/guazi/car.js +0 -110
- package/clis/guazi/guazi.test.js +0 -126
- package/clis/guazi/utils.js +0 -133
- package/clis/huodongxing/events.js +0 -322
- package/clis/huodongxing/events.test.js +0 -296
- package/clis/hupu/__fixtures__/hot-home.html +0 -64
- package/clis/hupu/auth.js +0 -47
- package/clis/hupu/detail.js +0 -72
- package/clis/hupu/hot.js +0 -163
- package/clis/hupu/hot.test.js +0 -224
- package/clis/hupu/like.js +0 -76
- package/clis/hupu/mentions.js +0 -160
- package/clis/hupu/reply.js +0 -72
- package/clis/hupu/search.js +0 -60
- package/clis/hupu/unlike.js +0 -76
- package/clis/hupu/utils.js +0 -319
- package/clis/jd/add-cart.js +0 -72
- package/clis/jd/auth.js +0 -46
- package/clis/jd/cart.js +0 -80
- package/clis/jd/commands.test.js +0 -41
- package/clis/jd/detail.js +0 -63
- package/clis/jd/item.js +0 -730
- package/clis/jd/item.test.js +0 -354
- package/clis/jd/item.test.ts +0 -517
- package/clis/jd/reviews.js +0 -55
- package/clis/jd/search.js +0 -66
- package/clis/jianyu/auth.js +0 -62
- package/clis/jianyu/detail.js +0 -21
- package/clis/jianyu/search.js +0 -634
- package/clis/jianyu/search.test.js +0 -153
- package/clis/jianyu/shared/china-bid-search.js +0 -165
- package/clis/jianyu/shared/procurement-contract.js +0 -324
- package/clis/jianyu/shared/procurement-contract.test.js +0 -72
- package/clis/jianyu/shared/procurement-detail.js +0 -107
- package/clis/jianyu/shared/procurement-detail.test.js +0 -84
- package/clis/jike/auth.js +0 -48
- package/clis/jike/comment.js +0 -107
- package/clis/jike/create.js +0 -106
- package/clis/jike/feed.js +0 -68
- package/clis/jike/like.js +0 -61
- package/clis/jike/notifications.js +0 -169
- package/clis/jike/post.js +0 -72
- package/clis/jike/read.test.js +0 -86
- package/clis/jike/repost.js +0 -103
- package/clis/jike/search.js +0 -68
- package/clis/jike/topic.js +0 -65
- package/clis/jike/user.js +0 -65
- package/clis/jike/utils.js +0 -25
- package/clis/jimeng/auth.js +0 -46
- package/clis/jimeng/generate.js +0 -84
- package/clis/jimeng/history.js +0 -48
- package/clis/jimeng/new.js +0 -44
- package/clis/jimeng/workspaces.js +0 -42
- package/clis/juejin/hot.js +0 -37
- package/clis/juejin/juejin.test.js +0 -241
- package/clis/juejin/recommend.js +0 -61
- package/clis/juejin/utils.js +0 -199
- package/clis/ke/auth.js +0 -46
- package/clis/ke/chengjiao.js +0 -78
- package/clis/ke/ershoufang.js +0 -101
- package/clis/ke/utils.js +0 -104
- package/clis/ke/xiaoqu.js +0 -78
- package/clis/ke/zufang.js +0 -95
- package/clis/kimi/_utils.js +0 -110
- package/clis/kimi/audit-extras.js +0 -268
- package/clis/kimi/auth.js +0 -57
- package/clis/kimi/chat.js +0 -470
- package/clis/kimi/kimi.test.js +0 -187
- package/clis/kimi/storage.js +0 -169
- package/clis/kimi/ui.js +0 -314
- package/clis/kimi/usage.js +0 -144
- package/clis/linux-do/auth.js +0 -55
- package/clis/linux-do/categories.js +0 -50
- package/clis/linux-do/feed.js +0 -395
- package/clis/linux-do/feed.test.js +0 -153
- package/clis/linux-do/search.js +0 -29
- package/clis/linux-do/tags.js +0 -28
- package/clis/linux-do/topic-content.js +0 -155
- package/clis/linux-do/topic-content.test.js +0 -59
- package/clis/linux-do/topic.js +0 -53
- package/clis/linux-do/user-posts.js +0 -57
- package/clis/linux-do/user-topics.js +0 -37
- package/clis/maimai/auth.js +0 -47
- package/clis/maimai/search-talents.js +0 -192
- package/clis/maimai/search-talents.test.js +0 -29
- package/clis/mubu/doc.js +0 -41
- package/clis/mubu/docs.js +0 -44
- package/clis/mubu/notes.js +0 -245
- package/clis/mubu/recent.js +0 -28
- package/clis/mubu/search.js +0 -63
- package/clis/mubu/utils.js +0 -304
- package/clis/nowcoder/auth.js +0 -65
- package/clis/nowcoder/companies.js +0 -24
- package/clis/nowcoder/creators.js +0 -28
- package/clis/nowcoder/detail.js +0 -62
- package/clis/nowcoder/experience.js +0 -37
- package/clis/nowcoder/hot.js +0 -25
- package/clis/nowcoder/jobs.js +0 -22
- package/clis/nowcoder/notifications.js +0 -30
- package/clis/nowcoder/papers.js +0 -41
- package/clis/nowcoder/practice.js +0 -38
- package/clis/nowcoder/recommend.js +0 -31
- package/clis/nowcoder/referral.js +0 -40
- package/clis/nowcoder/salary.js +0 -41
- package/clis/nowcoder/search.js +0 -50
- package/clis/nowcoder/suggest.js +0 -34
- package/clis/nowcoder/topics.js +0 -28
- package/clis/nowcoder/trending.js +0 -26
- package/clis/ones/common.js +0 -144
- package/clis/ones/enrich-tasks.js +0 -37
- package/clis/ones/login.js +0 -81
- package/clis/ones/logout.js +0 -18
- package/clis/ones/me.js +0 -31
- package/clis/ones/my-tasks.js +0 -121
- package/clis/ones/resolve-labels.js +0 -64
- package/clis/ones/task-helpers.js +0 -212
- package/clis/ones/task-helpers.test.js +0 -12
- package/clis/ones/task.js +0 -67
- package/clis/ones/tasks.js +0 -80
- package/clis/ones/token-info.js +0 -43
- package/clis/ones/worklog.js +0 -268
- package/clis/ones/worklog.test.js +0 -20
- package/clis/powerchina/auth.js +0 -52
- package/clis/powerchina/search.js +0 -251
- package/clis/powerchina/search.test.js +0 -93
- package/clis/quark/auth.js +0 -47
- package/clis/quark/ls.js +0 -64
- package/clis/quark/mkdir.js +0 -37
- package/clis/quark/mv.js +0 -54
- package/clis/quark/rename.js +0 -27
- package/clis/quark/rm.js +0 -25
- package/clis/quark/save.js +0 -81
- package/clis/quark/share-tree.js +0 -46
- package/clis/quark/utils.js +0 -146
- package/clis/quark/utils.test.js +0 -58
- package/clis/qwen/ask.js +0 -104
- package/clis/qwen/ask.test.js +0 -36
- package/clis/qwen/auth.js +0 -56
- package/clis/qwen/detail.js +0 -62
- package/clis/qwen/history.js +0 -61
- package/clis/qwen/image.js +0 -179
- package/clis/qwen/new.js +0 -23
- package/clis/qwen/read.js +0 -41
- package/clis/qwen/send.js +0 -55
- package/clis/qwen/status.js +0 -37
- package/clis/qwen/utils.js +0 -461
- package/clis/qwen/utils.test.js +0 -128
- package/clis/rednote/auth.js +0 -52
- package/clis/rednote/comments.js +0 -85
- package/clis/rednote/download.js +0 -59
- package/clis/rednote/feed.js +0 -27
- package/clis/rednote/navigation.test.js +0 -26
- package/clis/rednote/note.js +0 -68
- package/clis/rednote/notifications.js +0 -139
- package/clis/rednote/rednote.test.js +0 -240
- package/clis/rednote/search.js +0 -107
- package/clis/rednote/user.js +0 -55
- package/clis/sinablog/article.js +0 -15
- package/clis/sinablog/hot.js +0 -15
- package/clis/sinablog/search.js +0 -52
- package/clis/sinablog/user.js +0 -16
- package/clis/sinablog/utils.js +0 -186
- package/clis/sinafinance/news.js +0 -62
- package/clis/sinafinance/rolling-news.js +0 -41
- package/clis/sinafinance/stock-rank.js +0 -66
- package/clis/sinafinance/stock.js +0 -121
- package/clis/sinafinance/stock.test.js +0 -59
- package/clis/smzdm/search.js +0 -149
- package/clis/smzdm/search.test.js +0 -114
- package/clis/taobao/add-cart.js +0 -150
- package/clis/taobao/auth.js +0 -58
- package/clis/taobao/cart.js +0 -96
- package/clis/taobao/commands.test.js +0 -41
- package/clis/taobao/detail.js +0 -71
- package/clis/taobao/reviews.js +0 -77
- package/clis/taobao/search.js +0 -97
- package/clis/tdx/hot-rank.js +0 -48
- package/clis/tdx/hot-rank.test.js +0 -59
- package/clis/ths/hot-rank.js +0 -50
- package/clis/ths/hot-rank.test.js +0 -64
- package/clis/tieba/commands.test.js +0 -79
- package/clis/tieba/hot.js +0 -48
- package/clis/tieba/posts.js +0 -86
- package/clis/tieba/read.js +0 -141
- package/clis/tieba/search.js +0 -109
- package/clis/tieba/utils.js +0 -240
- package/clis/tieba/utils.test.js +0 -290
- package/clis/toutiao/articles.js +0 -55
- package/clis/toutiao/auth.js +0 -70
- package/clis/toutiao/hot.js +0 -63
- package/clis/toutiao/toutiao.test.js +0 -378
- package/clis/toutiao/utils.js +0 -161
- package/clis/trae-cn/activity.js +0 -22
- package/clis/trae-cn/approve.js +0 -52
- package/clis/trae-cn/ask.js +0 -99
- package/clis/trae-cn/dump.js +0 -5
- package/clis/trae-cn/export.js +0 -40
- package/clis/trae-cn/model.js +0 -22
- package/clis/trae-cn/new.js +0 -63
- package/clis/trae-cn/read.js +0 -23
- package/clis/trae-cn/screenshot.js +0 -5
- package/clis/trae-cn/select-model.js +0 -25
- package/clis/trae-cn/send.js +0 -23
- package/clis/trae-cn/setup.js +0 -75
- package/clis/trae-cn/status.js +0 -27
- package/clis/trae-cn/targets.js +0 -96
- package/clis/trae-cn/trae-cn.test.js +0 -412
- package/clis/trae-cn/utils.js +0 -750
- package/clis/trae-cn/watch.js +0 -119
- package/clis/uisdc/news.js +0 -105
- package/clis/uisdc/news.test.js +0 -66
- package/clis/v2ex/auth.js +0 -44
- package/clis/v2ex/daily.js +0 -99
- package/clis/v2ex/hot.js +0 -26
- package/clis/v2ex/latest.js +0 -26
- package/clis/v2ex/me.js +0 -100
- package/clis/v2ex/member.js +0 -28
- package/clis/v2ex/node.js +0 -39
- package/clis/v2ex/nodes.js +0 -26
- package/clis/v2ex/notifications.js +0 -72
- package/clis/v2ex/replies.js +0 -27
- package/clis/v2ex/topic.js +0 -31
- package/clis/v2ex/user.js +0 -34
- package/clis/wanfang/search.js +0 -66
- package/clis/wanfang/search.test.js +0 -23
- package/clis/wechat-channels/auth.js +0 -62
- package/clis/wechat-channels/publish.js +0 -732
- package/clis/wechat-channels/publish.test.js +0 -144
- package/clis/weibo/auth.js +0 -53
- package/clis/weibo/comments.js +0 -53
- package/clis/weibo/delete.js +0 -172
- package/clis/weibo/delete.test.js +0 -94
- package/clis/weibo/envelope.test.js +0 -85
- package/clis/weibo/favorites.js +0 -170
- package/clis/weibo/favorites.test.js +0 -114
- package/clis/weibo/feed.js +0 -69
- package/clis/weibo/hot.js +0 -39
- package/clis/weibo/me.js +0 -75
- package/clis/weibo/post.js +0 -75
- package/clis/weibo/publish.js +0 -306
- package/clis/weibo/publish.test.js +0 -192
- package/clis/weibo/search.js +0 -80
- package/clis/weibo/user-posts.js +0 -234
- package/clis/weibo/user-posts.test.js +0 -92
- package/clis/weibo/user.js +0 -63
- package/clis/weibo/utils.js +0 -59
- package/clis/weibo/utils.test.js +0 -36
- package/clis/weixin/create-draft.js +0 -226
- package/clis/weixin/download.js +0 -371
- package/clis/weixin/download.test.js +0 -106
- package/clis/weixin/drafts.js +0 -66
- package/clis/weixin/drafts.test.js +0 -69
- package/clis/weixin/search.js +0 -157
- package/clis/weixin/search.test.js +0 -227
- package/clis/weread/ai-outline.js +0 -171
- package/clis/weread/ai-outline.test.js +0 -83
- package/clis/weread/auth.js +0 -59
- package/clis/weread/book-search.js +0 -438
- package/clis/weread/book-search.test.js +0 -242
- package/clis/weread/book.js +0 -233
- package/clis/weread/commands.test.js +0 -398
- package/clis/weread/highlights.js +0 -24
- package/clis/weread/notebooks.js +0 -22
- package/clis/weread/notes.js +0 -30
- package/clis/weread/private-api-regression.test.js +0 -369
- package/clis/weread/ranking.js +0 -29
- package/clis/weread/search-regression.test.js +0 -494
- package/clis/weread/search.js +0 -186
- package/clis/weread/shelf.js +0 -66
- package/clis/weread/utils.js +0 -321
- package/clis/weread/utils.test.js +0 -128
- package/clis/weread-official/book.js +0 -135
- package/clis/weread-official/commands.test.js +0 -385
- package/clis/weread-official/discover.js +0 -107
- package/clis/weread-official/list-apis.js +0 -95
- package/clis/weread-official/notes.js +0 -171
- package/clis/weread-official/readdata.js +0 -158
- package/clis/weread-official/review.js +0 -93
- package/clis/weread-official/search.js +0 -106
- package/clis/weread-official/shelf.js +0 -97
- package/clis/weread-official/utils.js +0 -293
- package/clis/weread-official/utils.test.js +0 -242
- package/clis/xianyu/auth.js +0 -68
- package/clis/xianyu/chat.js +0 -74
- package/clis/xianyu/chat.test.js +0 -84
- package/clis/xianyu/im.js +0 -322
- package/clis/xianyu/im.test.js +0 -253
- package/clis/xianyu/inbox.js +0 -96
- package/clis/xianyu/item.js +0 -153
- package/clis/xianyu/item.test.js +0 -56
- package/clis/xianyu/messages.js +0 -91
- package/clis/xianyu/publish.js +0 -485
- package/clis/xianyu/publish.test.js +0 -220
- package/clis/xianyu/reply.js +0 -82
- package/clis/xianyu/search.js +0 -262
- package/clis/xianyu/search.test.js +0 -104
- package/clis/xianyu/utils.js +0 -8
- package/clis/xiaoe/auth.js +0 -55
- package/clis/xiaoe/catalog.js +0 -227
- package/clis/xiaoe/content.js +0 -175
- package/clis/xiaoe/courses.js +0 -127
- package/clis/xiaoe/detail.js +0 -36
- package/clis/xiaoe/play-url.js +0 -121
- package/clis/xiaoe/xiaoe.test.js +0 -486
- package/clis/xiaohongshu/ask.js +0 -426
- package/clis/xiaohongshu/ask.test.js +0 -271
- package/clis/xiaohongshu/auth.js +0 -53
- package/clis/xiaohongshu/collection-helpers.js +0 -283
- package/clis/xiaohongshu/collection-helpers.test.js +0 -125
- package/clis/xiaohongshu/comments.js +0 -228
- package/clis/xiaohongshu/comments.test.js +0 -320
- package/clis/xiaohongshu/creator-note-detail.js +0 -482
- package/clis/xiaohongshu/creator-note-detail.test.js +0 -451
- package/clis/xiaohongshu/creator-notes-summary.js +0 -98
- package/clis/xiaohongshu/creator-notes-summary.test.js +0 -94
- package/clis/xiaohongshu/creator-notes.js +0 -479
- package/clis/xiaohongshu/creator-notes.test.js +0 -281
- package/clis/xiaohongshu/creator-profile.js +0 -55
- package/clis/xiaohongshu/creator-stats.js +0 -76
- package/clis/xiaohongshu/creator-stats.test.js +0 -24
- package/clis/xiaohongshu/delete-note.js +0 -260
- package/clis/xiaohongshu/delete-note.test.js +0 -172
- package/clis/xiaohongshu/download.js +0 -249
- package/clis/xiaohongshu/download.test.js +0 -339
- package/clis/xiaohongshu/draft-clear.js +0 -91
- package/clis/xiaohongshu/draft-delete.js +0 -103
- package/clis/xiaohongshu/draft-open.js +0 -43
- package/clis/xiaohongshu/draft-utils.js +0 -142
- package/clis/xiaohongshu/drafts.js +0 -28
- package/clis/xiaohongshu/drafts.test.js +0 -172
- package/clis/xiaohongshu/feed.js +0 -163
- package/clis/xiaohongshu/feed.test.js +0 -126
- package/clis/xiaohongshu/follow.js +0 -226
- package/clis/xiaohongshu/follow.test.js +0 -211
- package/clis/xiaohongshu/liked.js +0 -29
- package/clis/xiaohongshu/liked.test.js +0 -82
- package/clis/xiaohongshu/navigation.test.js +0 -38
- package/clis/xiaohongshu/note-helpers.js +0 -69
- package/clis/xiaohongshu/note.js +0 -104
- package/clis/xiaohongshu/note.test.js +0 -249
- package/clis/xiaohongshu/notifications.js +0 -46
- package/clis/xiaohongshu/publish.js +0 -1423
- package/clis/xiaohongshu/publish.test.js +0 -1141
- package/clis/xiaohongshu/saved.js +0 -29
- package/clis/xiaohongshu/saved.test.js +0 -143
- package/clis/xiaohongshu/search.js +0 -330
- package/clis/xiaohongshu/search.test.js +0 -325
- package/clis/xiaohongshu/unfollow.js +0 -285
- package/clis/xiaohongshu/user-helpers.js +0 -78
- package/clis/xiaohongshu/user-helpers.test.js +0 -160
- package/clis/xiaohongshu/user.js +0 -140
- package/clis/xiaohongshu/user.test.js +0 -141
- package/clis/xiaoyuzhou/auth.js +0 -303
- package/clis/xiaoyuzhou/auth.test.js +0 -124
- package/clis/xiaoyuzhou/download.js +0 -54
- package/clis/xiaoyuzhou/download.test.js +0 -135
- package/clis/xiaoyuzhou/episode.js +0 -34
- package/clis/xiaoyuzhou/podcast-episodes.js +0 -41
- package/clis/xiaoyuzhou/podcast-episodes.test.js +0 -78
- package/clis/xiaoyuzhou/podcast.js +0 -33
- package/clis/xiaoyuzhou/transcript.js +0 -77
- package/clis/xiaoyuzhou/transcript.test.js +0 -195
- package/clis/xiaoyuzhou/utils.js +0 -15
- package/clis/xiaoyuzhou/utils.test.js +0 -39
- package/clis/xueqiu/auth.js +0 -63
- package/clis/xueqiu/comments.js +0 -355
- package/clis/xueqiu/comments.test.js +0 -696
- package/clis/xueqiu/danjuan-utils.js +0 -126
- package/clis/xueqiu/danjuan-utils.test.js +0 -41
- package/clis/xueqiu/earnings-date.js +0 -45
- package/clis/xueqiu/feed.js +0 -39
- package/clis/xueqiu/fund-holdings.js +0 -29
- package/clis/xueqiu/fund-snapshot.js +0 -26
- package/clis/xueqiu/groups.js +0 -23
- package/clis/xueqiu/hot-stock.js +0 -32
- package/clis/xueqiu/hot.js +0 -37
- package/clis/xueqiu/kline.js +0 -44
- package/clis/xueqiu/search.js +0 -37
- package/clis/xueqiu/stock.js +0 -65
- package/clis/xueqiu/utils.js +0 -48
- package/clis/xueqiu/utils.test.js +0 -26
- package/clis/xueqiu/watchlist.js +0 -37
- package/clis/youdao/note.js +0 -258
- package/clis/youdao/note.test.js +0 -99
- package/clis/yuanbao/ask.js +0 -362
- package/clis/yuanbao/ask.test.js +0 -124
- package/clis/yuanbao/auth.js +0 -59
- package/clis/yuanbao/detail.js +0 -65
- package/clis/yuanbao/history.js +0 -51
- package/clis/yuanbao/new.js +0 -72
- package/clis/yuanbao/new.test.js +0 -30
- package/clis/yuanbao/read.js +0 -38
- package/clis/yuanbao/send.js +0 -57
- package/clis/yuanbao/shared.js +0 -341
- package/clis/yuanbao/shared.test.js +0 -80
- package/clis/yuanbao/status.js +0 -44
- package/clis/zhihu/answer-comments.js +0 -280
- package/clis/zhihu/answer-comments.test.js +0 -287
- package/clis/zhihu/answer-detail.js +0 -216
- package/clis/zhihu/answer-detail.test.js +0 -338
- package/clis/zhihu/answer.js +0 -54
- package/clis/zhihu/answer.test.js +0 -54
- package/clis/zhihu/auth.js +0 -59
- package/clis/zhihu/collection.js +0 -199
- package/clis/zhihu/collection.test.js +0 -337
- package/clis/zhihu/collections.js +0 -128
- package/clis/zhihu/collections.test.js +0 -182
- package/clis/zhihu/comment.js +0 -55
- package/clis/zhihu/comment.test.js +0 -50
- package/clis/zhihu/download.js +0 -80
- package/clis/zhihu/download.test.js +0 -12
- package/clis/zhihu/favorite.js +0 -87
- package/clis/zhihu/favorite.test.js +0 -59
- package/clis/zhihu/follow.js +0 -50
- package/clis/zhihu/follow.test.js +0 -42
- package/clis/zhihu/followers.js +0 -40
- package/clis/zhihu/followers.test.js +0 -42
- package/clis/zhihu/following.js +0 -40
- package/clis/zhihu/following.test.js +0 -44
- package/clis/zhihu/hot.js +0 -44
- package/clis/zhihu/like.js +0 -47
- package/clis/zhihu/like.test.js +0 -41
- package/clis/zhihu/paginate.js +0 -128
- package/clis/zhihu/pins.js +0 -41
- package/clis/zhihu/pins.test.js +0 -44
- package/clis/zhihu/question.js +0 -113
- package/clis/zhihu/question.test.js +0 -251
- package/clis/zhihu/recommend.js +0 -103
- package/clis/zhihu/recommend.test.js +0 -143
- package/clis/zhihu/search.js +0 -206
- package/clis/zhihu/search.test.js +0 -198
- package/clis/zhihu/target.js +0 -91
- package/clis/zhihu/target.test.js +0 -77
- package/clis/zhihu/text.js +0 -29
- package/clis/zhihu/text.test.js +0 -24
- package/clis/zhihu/user-answers.js +0 -41
- package/clis/zhihu/user-answers.test.js +0 -69
- package/clis/zhihu/user-arg.js +0 -34
- package/clis/zhihu/user-articles.js +0 -40
- package/clis/zhihu/user-articles.test.js +0 -44
- package/clis/zhihu/user.js +0 -59
- package/clis/zhihu/user.test.js +0 -73
- package/clis/zhihu/write-shared.js +0 -228
- package/clis/zhihu/write-shared.test.js +0 -176
- package/clis/zsxq/auth.js +0 -68
- package/clis/zsxq/dynamics.js +0 -48
- package/clis/zsxq/groups.js +0 -33
- package/clis/zsxq/search.js +0 -44
- package/clis/zsxq/search.test.js +0 -24
- package/clis/zsxq/topic.js +0 -50
- package/clis/zsxq/topic.test.js +0 -30
- package/clis/zsxq/topics.js +0 -26
- package/clis/zsxq/topics.test.js +0 -24
- package/clis/zsxq/utils.js +0 -233
- package/clis/zsxq/utils.test.js +0 -31
- package/dist/src/weixin-download.test.js +0 -45
- package/skills/webcmd-adapter-author/references/site-memory/bilibili.md +0 -70
- package/skills/webcmd-adapter-author/references/site-memory/eastmoney.md +0 -70
- package/skills/webcmd-adapter-author/references/site-memory/tonghuashun.md +0 -51
- package/skills/webcmd-adapter-author/references/site-memory/xueqiu.md +0 -58
- /package/{clis/douyin/_shared/types.js → dist/src/generate-release-notes-cli.test.d.ts} +0 -0
- /package/dist/src/{weixin-download.test.d.ts → release-notes.test.d.ts} +0 -0
package/clis/weread/shelf.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@agentrhq/webcmd/registry';
|
|
2
|
-
import { CliError } from '@agentrhq/webcmd/errors';
|
|
3
|
-
import { log } from '@agentrhq/webcmd/logger';
|
|
4
|
-
import { buildWebShelfEntries, fetchPrivateApi, loadWebShelfSnapshot, } from './utils.js';
|
|
5
|
-
function normalizeShelfLimit(limit) {
|
|
6
|
-
if (!Number.isFinite(limit))
|
|
7
|
-
return 0;
|
|
8
|
-
return Math.max(0, Math.trunc(limit));
|
|
9
|
-
}
|
|
10
|
-
function normalizePrivateApiRows(data, limit) {
|
|
11
|
-
const books = data?.books ?? [];
|
|
12
|
-
return books.slice(0, limit).map((item) => ({
|
|
13
|
-
title: item.bookInfo?.title ?? item.title ?? '',
|
|
14
|
-
author: item.bookInfo?.author ?? item.author ?? '',
|
|
15
|
-
// TODO: readingProgress field name from community docs, verify with real API response
|
|
16
|
-
progress: item.readingProgress != null ? `${item.readingProgress}%` : '-',
|
|
17
|
-
bookId: item.bookId ?? item.bookInfo?.bookId ?? '',
|
|
18
|
-
}));
|
|
19
|
-
}
|
|
20
|
-
function normalizeWebShelfRows(snapshot, limit) {
|
|
21
|
-
if (limit <= 0)
|
|
22
|
-
return [];
|
|
23
|
-
return buildWebShelfEntries(snapshot)
|
|
24
|
-
.map((entry) => ({
|
|
25
|
-
title: entry.title,
|
|
26
|
-
author: entry.author,
|
|
27
|
-
progress: '-',
|
|
28
|
-
bookId: entry.bookId,
|
|
29
|
-
}))
|
|
30
|
-
.filter((item) => Boolean(item.title || item.bookId))
|
|
31
|
-
.slice(0, limit);
|
|
32
|
-
}
|
|
33
|
-
cli({
|
|
34
|
-
site: 'weread',
|
|
35
|
-
name: 'shelf',
|
|
36
|
-
access: 'read',
|
|
37
|
-
description: 'List books on your WeRead bookshelf',
|
|
38
|
-
domain: 'weread.qq.com',
|
|
39
|
-
strategy: Strategy.COOKIE,
|
|
40
|
-
args: [
|
|
41
|
-
{ name: 'limit', type: 'int', default: 20, help: 'Max results' },
|
|
42
|
-
],
|
|
43
|
-
columns: ['title', 'author', 'progress', 'bookId'],
|
|
44
|
-
func: async (page, args) => {
|
|
45
|
-
const limit = normalizeShelfLimit(Number(args.limit));
|
|
46
|
-
if (limit <= 0)
|
|
47
|
-
return [];
|
|
48
|
-
try {
|
|
49
|
-
const data = await fetchPrivateApi(page, '/shelf/sync', { synckey: '0', lectureSynckey: '0' });
|
|
50
|
-
return normalizePrivateApiRows(data, limit);
|
|
51
|
-
}
|
|
52
|
-
catch (error) {
|
|
53
|
-
if (!(error instanceof CliError) || error.code !== 'AUTH_REQUIRED') {
|
|
54
|
-
throw error;
|
|
55
|
-
}
|
|
56
|
-
const snapshot = await loadWebShelfSnapshot(page);
|
|
57
|
-
if (!snapshot.cacheFound) {
|
|
58
|
-
throw error;
|
|
59
|
-
}
|
|
60
|
-
// Make the fallback explicit so users do not mistake cached shelf data
|
|
61
|
-
// for a valid private API session.
|
|
62
|
-
log.warn('WeRead private API auth expired; showing cached shelf data from localStorage. Results may be stale, and detail commands may still require re-login.');
|
|
63
|
-
return normalizeWebShelfRows(snapshot, limit);
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
});
|
package/clis/weread/utils.js
DELETED
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WeRead shared helpers: fetch wrappers and formatting.
|
|
3
|
-
*
|
|
4
|
-
* Two API domains:
|
|
5
|
-
* - WEB_API (weread.qq.com/web/*): public, Node.js fetch
|
|
6
|
-
* - API (i.weread.qq.com/*): private, Node.js fetch with cookies from browser
|
|
7
|
-
*/
|
|
8
|
-
import { CliError } from '@agentrhq/webcmd/errors';
|
|
9
|
-
export const WEREAD_DOMAIN = 'weread.qq.com';
|
|
10
|
-
export const WEREAD_WEB_ORIGIN = `https://${WEREAD_DOMAIN}`;
|
|
11
|
-
export const WEREAD_SHELF_URL = `${WEREAD_WEB_ORIGIN}/web/shelf`;
|
|
12
|
-
const WEB_API = `${WEREAD_WEB_ORIGIN}/web`;
|
|
13
|
-
const API = `https://i.${WEREAD_DOMAIN}`;
|
|
14
|
-
export const WEREAD_UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
|
15
|
-
const WEREAD_AUTH_ERRCODES = new Set([-2010, -2012]);
|
|
16
|
-
function buildCookieHeader(cookies) {
|
|
17
|
-
return cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join('; ');
|
|
18
|
-
}
|
|
19
|
-
function isAuthErrorResponse(resp, data) {
|
|
20
|
-
return resp.status === 401 || WEREAD_AUTH_ERRCODES.has(Number(data?.errcode));
|
|
21
|
-
}
|
|
22
|
-
function getCurrentVid(cookies) {
|
|
23
|
-
return String(cookies.find((cookie) => cookie.name === 'wr_vid')?.value || '').trim();
|
|
24
|
-
}
|
|
25
|
-
function getWebShelfStorageKeys(currentVid) {
|
|
26
|
-
return {
|
|
27
|
-
rawBooksKey: `shelf:rawBooks:${currentVid}`,
|
|
28
|
-
shelfIndexesKey: `shelf:shelfIndexes:${currentVid}`,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function normalizeWebShelfSnapshot(value) {
|
|
32
|
-
return {
|
|
33
|
-
cacheFound: value?.cacheFound === true,
|
|
34
|
-
rawBooks: Array.isArray(value?.rawBooks) ? value.rawBooks : [],
|
|
35
|
-
shelfIndexes: Array.isArray(value?.shelfIndexes) ? value.shelfIndexes : [],
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function buildShelfSnapshotPollScript(storageKeys, requireTrustedIndexes) {
|
|
39
|
-
return `
|
|
40
|
-
(() => new Promise((resolve) => {
|
|
41
|
-
const deadline = Date.now() + 5000;
|
|
42
|
-
const rawBooksKey = ${JSON.stringify(storageKeys.rawBooksKey)};
|
|
43
|
-
const shelfIndexesKey = ${JSON.stringify(storageKeys.shelfIndexesKey)};
|
|
44
|
-
const requireTrustedIndexes = ${JSON.stringify(requireTrustedIndexes)};
|
|
45
|
-
|
|
46
|
-
const readJson = (raw) => {
|
|
47
|
-
if (typeof raw !== 'string') return null;
|
|
48
|
-
try {
|
|
49
|
-
return JSON.parse(raw);
|
|
50
|
-
} catch {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const collectBookIds = (items) => Array.isArray(items)
|
|
56
|
-
? Array.from(new Set(items.map((item) => String(item?.bookId || '').trim()).filter(Boolean)))
|
|
57
|
-
: [];
|
|
58
|
-
|
|
59
|
-
// Mirror of getTrustedIndexedBookIds in Node.js — keep in sync
|
|
60
|
-
const hasTrustedIndexes = (rawBooks, shelfIndexes) => {
|
|
61
|
-
const rawBookIds = collectBookIds(rawBooks);
|
|
62
|
-
if (rawBookIds.length === 0) return false;
|
|
63
|
-
|
|
64
|
-
const rawBookIdSet = new Set(rawBookIds);
|
|
65
|
-
const projectedIndexedBookIds = Array.isArray(shelfIndexes)
|
|
66
|
-
? Array.from(new Set(
|
|
67
|
-
shelfIndexes
|
|
68
|
-
.filter((entry) => Number.isFinite(entry?.idx))
|
|
69
|
-
.sort((left, right) => Number(left?.idx ?? Number.MAX_SAFE_INTEGER) - Number(right?.idx ?? Number.MAX_SAFE_INTEGER))
|
|
70
|
-
.map((entry) => String(entry?.bookId || '').trim())
|
|
71
|
-
.filter((bookId) => rawBookIdSet.has(bookId)),
|
|
72
|
-
))
|
|
73
|
-
: [];
|
|
74
|
-
|
|
75
|
-
return projectedIndexedBookIds.length === rawBookIds.length;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const poll = () => {
|
|
79
|
-
const rawBooks = readJson(localStorage.getItem(rawBooksKey));
|
|
80
|
-
const shelfIndexes = readJson(localStorage.getItem(shelfIndexesKey));
|
|
81
|
-
const cacheFound = Array.isArray(rawBooks);
|
|
82
|
-
const ready = cacheFound && (!requireTrustedIndexes || hasTrustedIndexes(rawBooks, shelfIndexes));
|
|
83
|
-
|
|
84
|
-
if (ready || Date.now() >= deadline) {
|
|
85
|
-
resolve({
|
|
86
|
-
cacheFound,
|
|
87
|
-
rawBooks: Array.isArray(rawBooks) ? rawBooks : [],
|
|
88
|
-
shelfIndexes: Array.isArray(shelfIndexes) ? shelfIndexes : [],
|
|
89
|
-
});
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
setTimeout(poll, 100);
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
poll();
|
|
97
|
-
}))
|
|
98
|
-
`;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Fetch a public WeRead web endpoint (Node.js direct fetch).
|
|
102
|
-
* Used by search and ranking commands (browser: false).
|
|
103
|
-
*/
|
|
104
|
-
export async function fetchWebApi(path, params) {
|
|
105
|
-
const url = new URL(`${WEB_API}${path}`);
|
|
106
|
-
if (params) {
|
|
107
|
-
for (const [k, v] of Object.entries(params))
|
|
108
|
-
url.searchParams.set(k, v);
|
|
109
|
-
}
|
|
110
|
-
const resp = await fetch(url.toString(), {
|
|
111
|
-
headers: { 'User-Agent': WEREAD_UA },
|
|
112
|
-
});
|
|
113
|
-
if (!resp.ok) {
|
|
114
|
-
throw new CliError('FETCH_ERROR', `HTTP ${resp.status} for ${path}`, 'WeRead API may be temporarily unavailable');
|
|
115
|
-
}
|
|
116
|
-
try {
|
|
117
|
-
return await resp.json();
|
|
118
|
-
}
|
|
119
|
-
catch {
|
|
120
|
-
throw new CliError('PARSE_ERROR', `Invalid JSON response for ${path}`, 'WeRead may have returned an HTML error page');
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Fetch a private WeRead API endpoint with cookies extracted from the browser.
|
|
125
|
-
* The HTTP request itself runs in Node.js to avoid page-context CORS failures.
|
|
126
|
-
*
|
|
127
|
-
* Cookies are collected from both the API subdomain (i.weread.qq.com) and the
|
|
128
|
-
* main domain (weread.qq.com). WeRead may set auth cookies as host-only on
|
|
129
|
-
* weread.qq.com, which won't match i.weread.qq.com in a URL-based lookup.
|
|
130
|
-
*/
|
|
131
|
-
export async function fetchPrivateApi(page, path, params) {
|
|
132
|
-
const url = new URL(`${API}${path}`);
|
|
133
|
-
if (params) {
|
|
134
|
-
for (const [k, v] of Object.entries(params))
|
|
135
|
-
url.searchParams.set(k, v);
|
|
136
|
-
}
|
|
137
|
-
const urlStr = url.toString();
|
|
138
|
-
// Merge cookies from both domains; API-domain cookies take precedence on name collision
|
|
139
|
-
const [apiCookies, domainCookies] = await Promise.all([
|
|
140
|
-
page.getCookies({ url: urlStr }),
|
|
141
|
-
page.getCookies({ domain: WEREAD_DOMAIN }),
|
|
142
|
-
]);
|
|
143
|
-
const merged = new Map();
|
|
144
|
-
for (const c of domainCookies)
|
|
145
|
-
merged.set(c.name, c);
|
|
146
|
-
for (const c of apiCookies)
|
|
147
|
-
merged.set(c.name, c);
|
|
148
|
-
const cookieHeader = buildCookieHeader(Array.from(merged.values()));
|
|
149
|
-
let resp;
|
|
150
|
-
try {
|
|
151
|
-
resp = await fetch(urlStr, {
|
|
152
|
-
headers: {
|
|
153
|
-
'User-Agent': WEREAD_UA,
|
|
154
|
-
'Origin': 'https://weread.qq.com',
|
|
155
|
-
'Referer': 'https://weread.qq.com/',
|
|
156
|
-
...(cookieHeader ? { 'Cookie': cookieHeader } : {}),
|
|
157
|
-
},
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
catch (error) {
|
|
161
|
-
throw new CliError('FETCH_ERROR', `Failed to fetch ${path}: ${error instanceof Error ? error.message : String(error)}`, 'WeRead API may be temporarily unavailable');
|
|
162
|
-
}
|
|
163
|
-
let data;
|
|
164
|
-
try {
|
|
165
|
-
data = await resp.json();
|
|
166
|
-
}
|
|
167
|
-
catch {
|
|
168
|
-
throw new CliError('PARSE_ERROR', `Invalid JSON response for ${path}`, 'WeRead may have returned an HTML error page');
|
|
169
|
-
}
|
|
170
|
-
if (isAuthErrorResponse(resp, data)) {
|
|
171
|
-
throw new CliError('AUTH_REQUIRED', 'Not logged in to WeRead', 'Please log in to weread.qq.com in Chrome first');
|
|
172
|
-
}
|
|
173
|
-
if (!resp.ok) {
|
|
174
|
-
throw new CliError('FETCH_ERROR', `HTTP ${resp.status} for ${path}`, 'WeRead API may be temporarily unavailable');
|
|
175
|
-
}
|
|
176
|
-
if (data?.errcode != null && data.errcode !== 0) {
|
|
177
|
-
throw new CliError('API_ERROR', data.errmsg ?? `WeRead API error ${data.errcode}`);
|
|
178
|
-
}
|
|
179
|
-
return data;
|
|
180
|
-
}
|
|
181
|
-
function getUniqueRawBookIds(snapshot) {
|
|
182
|
-
return Array.from(new Set(snapshot.rawBooks
|
|
183
|
-
.map((book) => String(book?.bookId || '').trim())
|
|
184
|
-
.filter(Boolean)));
|
|
185
|
-
}
|
|
186
|
-
/** Mirror of hasTrustedIndexes in buildShelfSnapshotPollScript — keep in sync */
|
|
187
|
-
function getTrustedIndexedBookIds(snapshot) {
|
|
188
|
-
const rawBookIds = getUniqueRawBookIds(snapshot);
|
|
189
|
-
if (rawBookIds.length === 0)
|
|
190
|
-
return [];
|
|
191
|
-
const rawBookIdSet = new Set(rawBookIds);
|
|
192
|
-
const projectedIndexedBookIds = Array.from(new Set(snapshot.shelfIndexes
|
|
193
|
-
.filter((entry) => Number.isFinite(entry?.idx))
|
|
194
|
-
.sort((left, right) => Number(left?.idx ?? Number.MAX_SAFE_INTEGER) - Number(right?.idx ?? Number.MAX_SAFE_INTEGER))
|
|
195
|
-
.map((entry) => String(entry?.bookId || '').trim())
|
|
196
|
-
.filter((bookId) => rawBookIdSet.has(bookId))));
|
|
197
|
-
return projectedIndexedBookIds.length === rawBookIds.length ? projectedIndexedBookIds : [];
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Build stable shelf records from the web cache plus optional rendered reader URLs.
|
|
201
|
-
* We only trust shelfIndexes when it fully covers the same bookId set as rawBooks;
|
|
202
|
-
* otherwise we keep rawBooks order to avoid partial hydration reordering entries.
|
|
203
|
-
*/
|
|
204
|
-
export function buildWebShelfEntries(snapshot, readerUrls = []) {
|
|
205
|
-
const rawBookIds = getUniqueRawBookIds(snapshot);
|
|
206
|
-
const trustedIndexedBookIds = getTrustedIndexedBookIds(snapshot);
|
|
207
|
-
const orderedBookIds = trustedIndexedBookIds.length > 0 ? trustedIndexedBookIds : rawBookIds;
|
|
208
|
-
const rawBookById = new Map();
|
|
209
|
-
for (const book of snapshot.rawBooks) {
|
|
210
|
-
const bookId = String(book?.bookId || '').trim();
|
|
211
|
-
if (!bookId || rawBookById.has(bookId))
|
|
212
|
-
continue;
|
|
213
|
-
rawBookById.set(bookId, book);
|
|
214
|
-
}
|
|
215
|
-
return orderedBookIds.map((bookId, index) => {
|
|
216
|
-
const book = rawBookById.get(bookId);
|
|
217
|
-
return {
|
|
218
|
-
bookId,
|
|
219
|
-
title: String(book?.title || '').trim(),
|
|
220
|
-
author: String(book?.author || '').trim(),
|
|
221
|
-
readerUrl: String(readerUrls[index] || '').trim(),
|
|
222
|
-
};
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Internal: load shelf snapshot and return the currentVid alongside it,
|
|
227
|
-
* so callers like resolveShelfReaderUrl can reuse it without a second getCookies.
|
|
228
|
-
*/
|
|
229
|
-
async function loadWebShelfSnapshotWithVid(page) {
|
|
230
|
-
await page.goto(WEREAD_SHELF_URL);
|
|
231
|
-
const cookies = await page.getCookies({ domain: WEREAD_DOMAIN });
|
|
232
|
-
const currentVid = getCurrentVid(cookies);
|
|
233
|
-
if (!currentVid) {
|
|
234
|
-
return { snapshot: { cacheFound: false, rawBooks: [], shelfIndexes: [] }, currentVid: '' };
|
|
235
|
-
}
|
|
236
|
-
const result = await page.evaluate(buildShelfSnapshotPollScript(getWebShelfStorageKeys(currentVid), false));
|
|
237
|
-
return {
|
|
238
|
-
snapshot: normalizeWebShelfSnapshot(result),
|
|
239
|
-
currentVid,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Read the structured shelf cache from the WeRead shelf page.
|
|
244
|
-
* The page hydrates localStorage asynchronously, so we poll briefly before
|
|
245
|
-
* giving up and treating the cache as unavailable for the current session.
|
|
246
|
-
*/
|
|
247
|
-
export async function loadWebShelfSnapshot(page) {
|
|
248
|
-
const { snapshot } = await loadWebShelfSnapshotWithVid(page);
|
|
249
|
-
return snapshot;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* `book` needs a trustworthy `bookId -> readerUrl` mapping, which may lag behind
|
|
253
|
-
* the first rawBooks cache hydration. Keep the fast shelf fallback path separate
|
|
254
|
-
* and only wait here, with a bounded poll, when resolving reader URLs.
|
|
255
|
-
*/
|
|
256
|
-
async function waitForTrustedWebShelfSnapshot(page, snapshot, currentVid) {
|
|
257
|
-
// Cache not available; nothing to wait for
|
|
258
|
-
if (!snapshot.cacheFound)
|
|
259
|
-
return snapshot;
|
|
260
|
-
// Indexes already fully cover rawBooks; no need to re-poll
|
|
261
|
-
if (getTrustedIndexedBookIds(snapshot).length > 0)
|
|
262
|
-
return snapshot;
|
|
263
|
-
if (!currentVid)
|
|
264
|
-
return snapshot;
|
|
265
|
-
const result = await page.evaluate(buildShelfSnapshotPollScript(getWebShelfStorageKeys(currentVid), true));
|
|
266
|
-
return normalizeWebShelfSnapshot(result);
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Resolve a shelf bookId to the current web reader URL by pairing structured
|
|
270
|
-
* shelf cache order with the visible shelf links rendered on the page.
|
|
271
|
-
*/
|
|
272
|
-
export async function resolveShelfReaderUrl(page, bookId) {
|
|
273
|
-
const resolution = await resolveShelfReader(page, bookId);
|
|
274
|
-
return resolution.readerUrl;
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Resolve the current reader URL for a shelf entry and return the parsed shelf
|
|
278
|
-
* snapshot used during resolution, so callers can reuse cached title/author
|
|
279
|
-
* metadata without loading the shelf page twice.
|
|
280
|
-
*/
|
|
281
|
-
export async function resolveShelfReader(page, bookId) {
|
|
282
|
-
const { snapshot: initialSnapshot, currentVid } = await loadWebShelfSnapshotWithVid(page);
|
|
283
|
-
const snapshot = await waitForTrustedWebShelfSnapshot(page, initialSnapshot, currentVid);
|
|
284
|
-
if (!snapshot.cacheFound) {
|
|
285
|
-
return { snapshot, readerUrl: null };
|
|
286
|
-
}
|
|
287
|
-
const rawBookIds = getUniqueRawBookIds(snapshot);
|
|
288
|
-
const trustedIndexedBookIds = getTrustedIndexedBookIds(snapshot);
|
|
289
|
-
const canUseRawOrderFallback = trustedIndexedBookIds.length === 0
|
|
290
|
-
&& rawBookIds.length > 0
|
|
291
|
-
&& snapshot.shelfIndexes.length === 0;
|
|
292
|
-
if (trustedIndexedBookIds.length === 0 && !canUseRawOrderFallback) {
|
|
293
|
-
return { snapshot, readerUrl: null };
|
|
294
|
-
}
|
|
295
|
-
const readerUrls = await page.evaluate(`
|
|
296
|
-
(() => Array.from(document.querySelectorAll('a.shelfBook[href]'))
|
|
297
|
-
.map((anchor) => {
|
|
298
|
-
const href = anchor.getAttribute('href') || '';
|
|
299
|
-
return href ? new URL(href, location.origin).toString() : '';
|
|
300
|
-
})
|
|
301
|
-
.filter(Boolean))
|
|
302
|
-
`);
|
|
303
|
-
const expectedEntryCount = trustedIndexedBookIds.length > 0 ? trustedIndexedBookIds.length : rawBookIds.length;
|
|
304
|
-
if (readerUrls.length !== expectedEntryCount) {
|
|
305
|
-
return { snapshot, readerUrl: null };
|
|
306
|
-
}
|
|
307
|
-
const entries = buildWebShelfEntries(snapshot, readerUrls);
|
|
308
|
-
const entry = entries.find((candidate) => candidate.bookId === bookId);
|
|
309
|
-
return {
|
|
310
|
-
snapshot,
|
|
311
|
-
readerUrl: entry?.readerUrl || null,
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
/** Format a Unix timestamp (seconds) to YYYY-MM-DD in UTC+8. Returns '-' for invalid input. */
|
|
315
|
-
export function formatDate(ts) {
|
|
316
|
-
if (!Number.isFinite(ts) || ts <= 0)
|
|
317
|
-
return '-';
|
|
318
|
-
// WeRead timestamps are China-centric; offset to UTC+8 to avoid off-by-one near midnight
|
|
319
|
-
const d = new Date(ts * 1000 + 8 * 3600_000);
|
|
320
|
-
return d.toISOString().slice(0, 10);
|
|
321
|
-
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { buildWebShelfEntries, formatDate, fetchWebApi } from './utils.js';
|
|
3
|
-
describe('formatDate', () => {
|
|
4
|
-
it('formats a typical Unix timestamp in UTC+8', () => {
|
|
5
|
-
// 1705276800 = 2024-01-15 00:00:00 UTC = 2024-01-15 08:00:00 Beijing
|
|
6
|
-
expect(formatDate(1705276800)).toBe('2024-01-15');
|
|
7
|
-
});
|
|
8
|
-
it('handles UTC midnight edge case with UTC+8 offset', () => {
|
|
9
|
-
// 1705190399 = 2024-01-13 23:59:59 UTC = 2024-01-14 07:59:59 Beijing
|
|
10
|
-
expect(formatDate(1705190399)).toBe('2024-01-14');
|
|
11
|
-
});
|
|
12
|
-
it('returns dash for zero', () => {
|
|
13
|
-
expect(formatDate(0)).toBe('-');
|
|
14
|
-
});
|
|
15
|
-
it('returns dash for negative', () => {
|
|
16
|
-
expect(formatDate(-1)).toBe('-');
|
|
17
|
-
});
|
|
18
|
-
it('returns dash for NaN', () => {
|
|
19
|
-
expect(formatDate(NaN)).toBe('-');
|
|
20
|
-
});
|
|
21
|
-
it('returns dash for Infinity', () => {
|
|
22
|
-
expect(formatDate(Infinity)).toBe('-');
|
|
23
|
-
});
|
|
24
|
-
it('returns dash for undefined', () => {
|
|
25
|
-
expect(formatDate(undefined)).toBe('-');
|
|
26
|
-
});
|
|
27
|
-
it('returns dash for null', () => {
|
|
28
|
-
expect(formatDate(null)).toBe('-');
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
describe('fetchWebApi', () => {
|
|
32
|
-
beforeEach(() => {
|
|
33
|
-
vi.restoreAllMocks();
|
|
34
|
-
});
|
|
35
|
-
it('returns parsed JSON for successful response', async () => {
|
|
36
|
-
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
|
|
37
|
-
ok: true,
|
|
38
|
-
json: () => Promise.resolve({ books: [{ title: 'Test' }] }),
|
|
39
|
-
}));
|
|
40
|
-
const result = await fetchWebApi('/search/global', { keyword: 'test' });
|
|
41
|
-
expect(result).toEqual({ books: [{ title: 'Test' }] });
|
|
42
|
-
});
|
|
43
|
-
it('throws CliError on HTTP error', async () => {
|
|
44
|
-
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
|
|
45
|
-
ok: false,
|
|
46
|
-
status: 403,
|
|
47
|
-
json: () => Promise.resolve({}),
|
|
48
|
-
}));
|
|
49
|
-
await expect(fetchWebApi('/search/global')).rejects.toThrow('HTTP 403');
|
|
50
|
-
});
|
|
51
|
-
it('throws PARSE_ERROR on non-JSON response', async () => {
|
|
52
|
-
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
|
|
53
|
-
ok: true,
|
|
54
|
-
json: () => Promise.reject(new SyntaxError('Unexpected token <')),
|
|
55
|
-
}));
|
|
56
|
-
await expect(fetchWebApi('/search/global')).rejects.toThrow('Invalid JSON');
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
describe('buildWebShelfEntries', () => {
|
|
60
|
-
it('keeps mixed shelf item reader urls aligned when shelf indexes include non-book roles', () => {
|
|
61
|
-
const result = buildWebShelfEntries({
|
|
62
|
-
cacheFound: true,
|
|
63
|
-
rawBooks: [
|
|
64
|
-
{ bookId: 'MP_WXS_1', title: '公众号文章一', author: '作者甲' },
|
|
65
|
-
{ bookId: 'BOOK_2', title: '普通书二', author: '作者乙' },
|
|
66
|
-
{ bookId: 'MP_WXS_3', title: '公众号文章三', author: '作者丙' },
|
|
67
|
-
],
|
|
68
|
-
shelfIndexes: [
|
|
69
|
-
{ bookId: 'MP_WXS_1', idx: 0, role: 'mp' },
|
|
70
|
-
{ bookId: 'BOOK_2', idx: 1, role: 'book' },
|
|
71
|
-
{ bookId: 'MP_WXS_3', idx: 2, role: 'mp' },
|
|
72
|
-
],
|
|
73
|
-
}, [
|
|
74
|
-
'https://weread.qq.com/web/reader/mp1',
|
|
75
|
-
'https://weread.qq.com/web/reader/book2',
|
|
76
|
-
'https://weread.qq.com/web/reader/mp3',
|
|
77
|
-
]);
|
|
78
|
-
expect(result).toEqual([
|
|
79
|
-
{
|
|
80
|
-
bookId: 'MP_WXS_1',
|
|
81
|
-
title: '公众号文章一',
|
|
82
|
-
author: '作者甲',
|
|
83
|
-
readerUrl: 'https://weread.qq.com/web/reader/mp1',
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
bookId: 'BOOK_2',
|
|
87
|
-
title: '普通书二',
|
|
88
|
-
author: '作者乙',
|
|
89
|
-
readerUrl: 'https://weread.qq.com/web/reader/book2',
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
bookId: 'MP_WXS_3',
|
|
93
|
-
title: '公众号文章三',
|
|
94
|
-
author: '作者丙',
|
|
95
|
-
readerUrl: 'https://weread.qq.com/web/reader/mp3',
|
|
96
|
-
},
|
|
97
|
-
]);
|
|
98
|
-
});
|
|
99
|
-
it('falls back to raw cache order when shelf indexes are incomplete', () => {
|
|
100
|
-
const result = buildWebShelfEntries({
|
|
101
|
-
cacheFound: true,
|
|
102
|
-
rawBooks: [
|
|
103
|
-
{ bookId: 'BOOK_1', title: '第一本', author: '作者甲' },
|
|
104
|
-
{ bookId: 'BOOK_2', title: '第二本', author: '作者乙' },
|
|
105
|
-
],
|
|
106
|
-
shelfIndexes: [
|
|
107
|
-
{ bookId: 'BOOK_2', idx: 0, role: 'book' },
|
|
108
|
-
],
|
|
109
|
-
}, [
|
|
110
|
-
'https://weread.qq.com/web/reader/book1',
|
|
111
|
-
'https://weread.qq.com/web/reader/book2',
|
|
112
|
-
]);
|
|
113
|
-
expect(result).toEqual([
|
|
114
|
-
{
|
|
115
|
-
bookId: 'BOOK_1',
|
|
116
|
-
title: '第一本',
|
|
117
|
-
author: '作者甲',
|
|
118
|
-
readerUrl: 'https://weread.qq.com/web/reader/book1',
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
bookId: 'BOOK_2',
|
|
122
|
-
title: '第二本',
|
|
123
|
-
author: '作者乙',
|
|
124
|
-
readerUrl: 'https://weread.qq.com/web/reader/book2',
|
|
125
|
-
},
|
|
126
|
-
]);
|
|
127
|
-
});
|
|
128
|
-
});
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { cli, Strategy } from '@agentrhq/webcmd/registry';
|
|
2
|
-
import {
|
|
3
|
-
callGateway,
|
|
4
|
-
emptyResult,
|
|
5
|
-
formatDate,
|
|
6
|
-
formatDuration,
|
|
7
|
-
formatRating,
|
|
8
|
-
makeDeepLink,
|
|
9
|
-
requireBookId,
|
|
10
|
-
truncate,
|
|
11
|
-
} from './utils.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* 3-in-1 book lookup: `/book/info` always runs; `/book/chapterinfo` and
|
|
15
|
-
* `/book/getprogress` are opt-out via `--no-chapters` / `--no-progress`
|
|
16
|
-
* so users can shave 1-2 gateway calls when only a single section is needed.
|
|
17
|
-
*
|
|
18
|
-
* Output is a flat row list with a `section` column so table/json/yaml
|
|
19
|
-
* consumers can filter without ad-hoc joins:
|
|
20
|
-
* - section=info — single row, basic metadata
|
|
21
|
-
* - section=chapter — one row per chapter (level/title/wordCount)
|
|
22
|
-
* - section=progress — single row, progress % + cumulative read time
|
|
23
|
-
*/
|
|
24
|
-
cli({
|
|
25
|
-
site: 'weread-official',
|
|
26
|
-
name: 'book',
|
|
27
|
-
access: 'read',
|
|
28
|
-
description: 'Show WeRead book metadata, chapters, and reading progress',
|
|
29
|
-
domain: 'weread.qq.com',
|
|
30
|
-
strategy: Strategy.PUBLIC,
|
|
31
|
-
browser: false,
|
|
32
|
-
args: [
|
|
33
|
-
{ name: 'bookId', positional: true, required: true, help: 'WeRead bookId (from `weread-official search`)' },
|
|
34
|
-
{ name: 'no-chapters', type: 'boolean', default: false, help: 'Skip /book/chapterinfo call' },
|
|
35
|
-
{ name: 'no-progress', type: 'boolean', default: false, help: 'Skip /book/getprogress call' },
|
|
36
|
-
],
|
|
37
|
-
columns: ['section', 'idx', 'key', 'value', 'link'],
|
|
38
|
-
func: async (args) => {
|
|
39
|
-
const bookId = requireBookId(args.bookId);
|
|
40
|
-
|
|
41
|
-
const tasks = [callGateway('/book/info', { bookId })];
|
|
42
|
-
const want = {
|
|
43
|
-
chapters: !args['no-chapters'],
|
|
44
|
-
progress: !args['no-progress'],
|
|
45
|
-
};
|
|
46
|
-
if (want.chapters) tasks.push(callGateway('/book/chapterinfo', { bookId }));
|
|
47
|
-
if (want.progress) tasks.push(callGateway('/book/getprogress', { bookId }));
|
|
48
|
-
|
|
49
|
-
const results = await Promise.all(tasks);
|
|
50
|
-
let cursor = 0;
|
|
51
|
-
const info = results[cursor++];
|
|
52
|
-
const chapters = want.chapters ? results[cursor++] : null;
|
|
53
|
-
const progress = want.progress ? results[cursor++] : null;
|
|
54
|
-
|
|
55
|
-
const rows = [];
|
|
56
|
-
|
|
57
|
-
// ── info section ────────────────────────────────────────────────────
|
|
58
|
-
const infoPairs = [
|
|
59
|
-
['bookId', String(info?.bookId ?? bookId)],
|
|
60
|
-
['title', String(info?.title ?? '')],
|
|
61
|
-
['author', String(info?.author ?? '')],
|
|
62
|
-
['translator', String(info?.translator ?? '')],
|
|
63
|
-
['category', String(info?.category ?? '')],
|
|
64
|
-
['publisher', String(info?.publisher ?? '')],
|
|
65
|
-
['publishTime', String(info?.publishTime ?? '')],
|
|
66
|
-
['isbn', String(info?.isbn ?? '')],
|
|
67
|
-
['wordCount', String(info?.wordCount ?? '')],
|
|
68
|
-
['rating', formatRating(info?.newRating)],
|
|
69
|
-
['ratingCount', String(info?.newRatingCount ?? '')],
|
|
70
|
-
['intro', truncate(info?.intro, 400)],
|
|
71
|
-
['cover', String(info?.cover ?? '')],
|
|
72
|
-
];
|
|
73
|
-
for (let i = 0; i < infoPairs.length; i += 1) {
|
|
74
|
-
const [key, value] = infoPairs[i];
|
|
75
|
-
rows.push({ section: 'info', idx: i + 1, key, value, link: '' });
|
|
76
|
-
}
|
|
77
|
-
rows.push({
|
|
78
|
-
section: 'info',
|
|
79
|
-
idx: infoPairs.length + 1,
|
|
80
|
-
key: 'link',
|
|
81
|
-
value: '',
|
|
82
|
-
link: makeDeepLink({ bookId }),
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// ── chapters section ────────────────────────────────────────────────
|
|
86
|
-
if (chapters) {
|
|
87
|
-
const list = Array.isArray(chapters?.chapters) ? chapters.chapters : [];
|
|
88
|
-
list.forEach((ch, i) => {
|
|
89
|
-
const chapterUid = String(ch?.chapterUid ?? '').trim();
|
|
90
|
-
const level = Number(ch?.level ?? 1);
|
|
91
|
-
const indent = ' '.repeat(Math.max(0, level - 1));
|
|
92
|
-
const title = `${indent}${String(ch?.title ?? '')}`;
|
|
93
|
-
const wordCount = Number(ch?.wordCount ?? 0);
|
|
94
|
-
const paid = Number(ch?.paid ?? 0) === 1;
|
|
95
|
-
const price = Number(ch?.price ?? 0);
|
|
96
|
-
const meta = [`${wordCount}字`];
|
|
97
|
-
if (price > 0) meta.push(paid ? '已购买' : `${price}元`);
|
|
98
|
-
rows.push({
|
|
99
|
-
section: 'chapter',
|
|
100
|
-
idx: Number(ch?.chapterIdx ?? i + 1),
|
|
101
|
-
key: chapterUid,
|
|
102
|
-
value: `${title} (${meta.join(' · ')})`,
|
|
103
|
-
link: chapterUid ? makeDeepLink({ bookId, chapterUid }) : '',
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// ── progress section ────────────────────────────────────────────────
|
|
109
|
-
if (progress) {
|
|
110
|
-
const p = progress?.book ?? {};
|
|
111
|
-
const pct = Number(p?.progress ?? 0);
|
|
112
|
-
const updateTime = formatDate(p?.updateTime);
|
|
113
|
-
const finishTime = pct === 100 ? formatDate(p?.finishTime) : '';
|
|
114
|
-
const cumulative = formatDuration(p?.recordReadingTime);
|
|
115
|
-
const isStart = Number(p?.isStartReading ?? 0) === 1;
|
|
116
|
-
const progressPairs = [
|
|
117
|
-
['progress', `${pct}%`],
|
|
118
|
-
['cumulative', cumulative],
|
|
119
|
-
['lastReadAt', updateTime],
|
|
120
|
-
['finishedAt', finishTime],
|
|
121
|
-
['isStartReading', isStart ? 'true' : 'false'],
|
|
122
|
-
['currentChapterUid', String(p?.chapterUid ?? '')],
|
|
123
|
-
];
|
|
124
|
-
for (let i = 0; i < progressPairs.length; i += 1) {
|
|
125
|
-
const [key, value] = progressPairs[i];
|
|
126
|
-
rows.push({ section: 'progress', idx: i + 1, key, value, link: '' });
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (rows.length === 0) {
|
|
131
|
-
emptyResult('book', `No data returned for bookId=${bookId}`);
|
|
132
|
-
}
|
|
133
|
-
return rows;
|
|
134
|
-
},
|
|
135
|
-
});
|