publishport-opencli 1.0.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/LICENSE +214 -0
- package/README.md +299 -0
- package/README.zh-CN.md +341 -0
- package/cli-manifest.json +51513 -0
- package/clis/12306/auth.js +25 -0
- package/clis/12306/me.js +9 -0
- package/clis/12306/orders.js +13 -0
- package/clis/12306/passengers.js +14 -0
- package/clis/12306/price.js +1 -0
- package/clis/12306/stations.js +1 -0
- package/clis/12306/train.js +1 -0
- package/clis/12306/trains.js +1 -0
- package/clis/12306/utils.js +1 -0
- package/clis/1688/assets.js +127 -0
- package/clis/1688/auth.js +1 -0
- package/clis/1688/download.js +1 -0
- package/clis/1688/item.js +21 -0
- package/clis/1688/search.js +129 -0
- package/clis/1688/shared.js +11 -0
- package/clis/1688/store.js +26 -0
- package/clis/1point3acres/auth.js +18 -0
- package/clis/1point3acres/digest.js +1 -0
- package/clis/1point3acres/forum.js +1 -0
- package/clis/1point3acres/forums.js +1 -0
- package/clis/1point3acres/hot.js +1 -0
- package/clis/1point3acres/latest.js +1 -0
- package/clis/1point3acres/notifications.js +1 -0
- package/clis/1point3acres/search.js +1 -0
- package/clis/1point3acres/thread.js +2 -0
- package/clis/1point3acres/user.js +1 -0
- package/clis/1point3acres/utils.js +6 -0
- package/clis/36kr/article.js +20 -0
- package/clis/36kr/hot.js +16 -0
- package/clis/36kr/news.js +1 -0
- package/clis/36kr/search.js +36 -0
- package/clis/51job/company.js +36 -0
- package/clis/51job/detail.js +35 -0
- package/clis/51job/hot.js +1 -0
- package/clis/51job/search.js +1 -0
- package/clis/51job/utils.js +21 -0
- package/clis/_atlassian/shared.js +21 -0
- package/clis/_shared/article/auth.js +16 -0
- package/clis/_shared/article/douban-md2draft.js +4 -0
- package/clis/_shared/article/format.js +1 -0
- package/clis/_shared/article/images.js +95 -0
- package/clis/_shared/article/login.js +1 -0
- package/clis/_shared/article/page-runtime.js +745 -0
- package/clis/_shared/article/publish.js +34 -0
- package/clis/_shared/common.js +1 -0
- package/clis/_shared/content-guard.js +1 -0
- package/clis/_shared/desktop-commands.js +1 -0
- package/clis/_shared/search-adapter.js +1 -0
- package/clis/_shared/site-auth.js +1 -0
- package/clis/_shared/token-auth.js +2 -0
- package/clis/_shared/video-publish.js +62 -0
- package/clis/aibase/news.js +31 -0
- package/clis/amazon/auth.js +19 -0
- package/clis/amazon/bestsellers.js +1 -0
- package/clis/amazon/discussion.js +20 -0
- package/clis/amazon/movers-shakers.js +1 -0
- package/clis/amazon/new-releases.js +1 -0
- package/clis/amazon/offer.js +29 -0
- package/clis/amazon/product.js +25 -0
- package/clis/amazon/rankings.js +68 -0
- package/clis/amazon/search.js +16 -0
- package/clis/amazon/shared.js +11 -0
- package/clis/antigravity/SKILL.md +38 -0
- package/clis/antigravity/_actions.js +201 -0
- package/clis/antigravity/audit-extras.js +78 -0
- package/clis/antigravity/delete.js +1 -0
- package/clis/antigravity/dump.js +1 -0
- package/clis/antigravity/extract-code.js +18 -0
- package/clis/antigravity/history.js +1 -0
- package/clis/antigravity/mark-read.js +1 -0
- package/clis/antigravity/model.js +90 -0
- package/clis/antigravity/new.js +9 -0
- package/clis/antigravity/read.js +10 -0
- package/clis/antigravity/rename.js +1 -0
- package/clis/antigravity/send.js +11 -0
- package/clis/antigravity/serve.js +97 -0
- package/clis/antigravity/status.js +1 -0
- package/clis/antigravity/storage.js +12 -0
- package/clis/antigravity/watch.js +6 -0
- package/clis/apple-podcasts/episodes.js +1 -0
- package/clis/apple-podcasts/search.js +1 -0
- package/clis/apple-podcasts/top.js +1 -0
- package/clis/apple-podcasts/utils.js +1 -0
- package/clis/archive/item.js +1 -0
- package/clis/archive/search.js +1 -0
- package/clis/archive/snapshots.js +1 -0
- package/clis/archive/wayback.js +1 -0
- package/clis/arxiv/author.js +1 -0
- package/clis/arxiv/paper.js +1 -0
- package/clis/arxiv/recent.js +1 -0
- package/clis/arxiv/search.js +1 -0
- package/clis/arxiv/utils.js +1 -0
- package/clis/autohome/__fixtures__/catalog.html +11 -0
- package/clis/autohome/__fixtures__/koubei.json +116 -0
- package/clis/autohome/brand.js +1 -0
- package/clis/autohome/score.js +1 -0
- package/clis/autohome/utils.js +1 -0
- package/clis/baidu-scholar/search.js +63 -0
- package/clis/baijiahao/article.js +1 -0
- package/clis/baijiahao/lists.js +1 -0
- package/clis/baijiahao/login.js +1 -0
- package/clis/baijiahao/publish.js +57 -0
- package/clis/baijiahao/stats.js +1 -0
- package/clis/baijiahao/whoami.js +1 -0
- package/clis/band/auth.js +29 -0
- package/clis/band/bands.js +37 -0
- package/clis/band/mentions.js +6 -0
- package/clis/band/post.js +76 -0
- package/clis/band/posts.js +50 -0
- package/clis/barchart/flow.js +70 -0
- package/clis/barchart/greeks.js +88 -0
- package/clis/barchart/options.js +61 -0
- package/clis/barchart/quote.js +87 -0
- package/clis/bbc/news.js +1 -0
- package/clis/bbc/topic.js +1 -0
- package/clis/bbc/utils.js +1 -0
- package/clis/bilibili/article.js +1 -0
- package/clis/bilibili/auth.js +1 -0
- package/clis/bilibili/categories.js +1 -0
- package/clis/bilibili/coin.js +1 -0
- package/clis/bilibili/comment-del.js +1 -0
- package/clis/bilibili/comment-like.js +1 -0
- package/clis/bilibili/comment.js +1 -0
- package/clis/bilibili/comments.js +1 -0
- package/clis/bilibili/dm-list.js +1 -0
- package/clis/bilibili/dm-read.js +1 -0
- package/clis/bilibili/dm-send.js +1 -0
- package/clis/bilibili/download.js +7 -0
- package/clis/bilibili/drafts.js +1 -0
- package/clis/bilibili/dynamic-post.js +24 -0
- package/clis/bilibili/dynamic.js +1 -0
- package/clis/bilibili/favorite-add.js +1 -0
- package/clis/bilibili/favorite.js +1 -0
- package/clis/bilibili/feed.js +2 -0
- package/clis/bilibili/follow.js +1 -0
- package/clis/bilibili/following.js +1 -0
- package/clis/bilibili/history.js +1 -0
- package/clis/bilibili/hot.js +15 -0
- package/clis/bilibili/like.js +1 -0
- package/clis/bilibili/me.js +1 -0
- package/clis/bilibili/partitions.js +1 -0
- package/clis/bilibili/ranking.js +1 -0
- package/clis/bilibili/search.js +1 -0
- package/clis/bilibili/stats.js +1 -0
- package/clis/bilibili/subtitle.js +21 -0
- package/clis/bilibili/summary.js +1 -0
- package/clis/bilibili/topics.js +1 -0
- package/clis/bilibili/unfollow.js +1 -0
- package/clis/bilibili/upload.js +1 -0
- package/clis/bilibili/user-videos.js +1 -0
- package/clis/bilibili/utils.js +50 -0
- package/clis/bilibili/video-drafts.js +1 -0
- package/clis/bilibili/video.js +1 -0
- package/clis/binance/asks.js +1 -0
- package/clis/binance/depth.js +1 -0
- package/clis/binance/gainers.js +1 -0
- package/clis/binance/klines.js +1 -0
- package/clis/binance/losers.js +1 -0
- package/clis/binance/pairs.js +1 -0
- package/clis/binance/price.js +1 -0
- package/clis/binance/prices.js +1 -0
- package/clis/binance/ticker.js +1 -0
- package/clis/binance/top.js +1 -0
- package/clis/binance/trades.js +1 -0
- package/clis/bloomberg/businessweek.js +12 -0
- package/clis/bloomberg/crypto.js +1 -0
- package/clis/bloomberg/economics.js +1 -0
- package/clis/bloomberg/feeds.js +1 -0
- package/clis/bloomberg/green.js +1 -0
- package/clis/bloomberg/industries.js +1 -0
- package/clis/bloomberg/main.js +1 -0
- package/clis/bloomberg/markets.js +1 -0
- package/clis/bloomberg/news.js +57 -0
- package/clis/bloomberg/opinions.js +1 -0
- package/clis/bloomberg/politics.js +1 -0
- package/clis/bloomberg/pursuits.js +1 -0
- package/clis/bloomberg/tech.js +1 -0
- package/clis/bloomberg/utils.js +17 -0
- package/clis/bluesky/post.js +1 -0
- package/clis/bluesky/shared.js +56 -0
- package/clis/bluesky/whoami.js +1 -0
- package/clis/booking/search.js +93 -0
- package/clis/boss/auth.js +13 -0
- package/clis/boss/batchgreet.js +1 -0
- package/clis/boss/chatlist.js +1 -0
- package/clis/boss/chatmsg.js +1 -0
- package/clis/boss/detail.js +1 -0
- package/clis/boss/exchange.js +1 -0
- package/clis/boss/greet.js +1 -0
- package/clis/boss/invite.js +4 -0
- package/clis/boss/joblist.js +1 -0
- package/clis/boss/mark.js +1 -0
- package/clis/boss/recommend.js +1 -0
- package/clis/boss/resume.js +90 -0
- package/clis/boss/search.js +1 -0
- package/clis/boss/send.js +1 -0
- package/clis/boss/stats.js +1 -0
- package/clis/boss/utils.js +161 -0
- package/clis/brave/search.js +23 -0
- package/clis/chaoxing/assignments.js +1 -0
- package/clis/chaoxing/auth.js +21 -0
- package/clis/chaoxing/exams.js +1 -0
- package/clis/chaoxing/utils.js +58 -0
- package/clis/chatgpt/ask.js +1 -0
- package/clis/chatgpt/auth.js +17 -0
- package/clis/chatgpt/detail.js +1 -0
- package/clis/chatgpt/history.js +1 -0
- package/clis/chatgpt/image.js +1 -0
- package/clis/chatgpt/model.js +1 -0
- package/clis/chatgpt/new.js +1 -0
- package/clis/chatgpt/project-file-add.js +1 -0
- package/clis/chatgpt/project-list.js +1 -0
- package/clis/chatgpt/read.js +1 -0
- package/clis/chatgpt/send.js +1 -0
- package/clis/chatgpt/status.js +1 -0
- package/clis/chatgpt/utils.js +1092 -0
- package/clis/chatgpt-app/ask.js +1 -0
- package/clis/chatgpt-app/ax.js +512 -0
- package/clis/chatgpt-app/model.js +1 -0
- package/clis/chatgpt-app/new.js +1 -0
- package/clis/chatgpt-app/read.js +1 -0
- package/clis/chatgpt-app/send.js +1 -0
- package/clis/chatgpt-app/status.js +1 -0
- package/clis/chatwise/ask.js +1 -0
- package/clis/chatwise/export.js +21 -0
- package/clis/chatwise/history.js +26 -0
- package/clis/chatwise/model.js +48 -0
- package/clis/chatwise/new.js +1 -0
- package/clis/chatwise/read.js +25 -0
- package/clis/chatwise/screenshot.js +1 -0
- package/clis/chatwise/send.js +1 -0
- package/clis/chatwise/status.js +1 -0
- package/clis/chatwise/utils.js +75 -0
- package/clis/chess/analyze.js +1 -0
- package/clis/chess/game.js +1 -0
- package/clis/chess/games.js +1 -0
- package/clis/chess/stats.js +1 -0
- package/clis/chess/utils.js +1 -0
- package/clis/claude/ask.js +4 -0
- package/clis/claude/auth.js +19 -0
- package/clis/claude/detail.js +1 -0
- package/clis/claude/history.js +1 -0
- package/clis/claude/new.js +1 -0
- package/clis/claude/read.js +1 -0
- package/clis/claude/send.js +1 -0
- package/clis/claude/status.js +1 -0
- package/clis/claude/utils.js +179 -0
- package/clis/cnblogs/article.js +1 -0
- package/clis/cnblogs/login.js +1 -0
- package/clis/cnblogs/stats.js +37 -0
- package/clis/cnblogs/whoami.js +1 -0
- package/clis/cnki/search.js +38 -0
- package/clis/codex/_actions.js +72 -0
- package/clis/codex/archive.js +1 -0
- package/clis/codex/ask.js +23 -0
- package/clis/codex/dump.js +1 -0
- package/clis/codex/export.js +12 -0
- package/clis/codex/extract-diff.js +28 -0
- package/clis/codex/history.js +1 -0
- package/clis/codex/model.js +118 -0
- package/clis/codex/new.js +1 -0
- package/clis/codex/pin.js +1 -0
- package/clis/codex/projects.js +1 -0
- package/clis/codex/read.js +16 -0
- package/clis/codex/rename.js +34 -0
- package/clis/codex/screenshot.js +1 -0
- package/clis/codex/send.js +16 -0
- package/clis/codex/sidebar.js +1 -0
- package/clis/codex/status.js +1 -0
- package/clis/coingecko/categories.js +1 -0
- package/clis/coingecko/coin.js +1 -0
- package/clis/coingecko/derivatives.js +1 -0
- package/clis/coingecko/exchanges.js +1 -0
- package/clis/coingecko/global.js +1 -0
- package/clis/coingecko/top.js +1 -0
- package/clis/coingecko/trending.js +1 -0
- package/clis/confluence/create.js +1 -0
- package/clis/confluence/page.js +1 -0
- package/clis/confluence/search.js +1 -0
- package/clis/confluence/shared.js +1 -0
- package/clis/confluence/update.js +1 -0
- package/clis/coupang/add-to-cart.js +86 -0
- package/clis/coupang/auth.js +16 -0
- package/clis/coupang/product.js +161 -0
- package/clis/coupang/search.js +385 -0
- package/clis/coupang/utils.js +1 -0
- package/clis/crates/crate.js +1 -0
- package/clis/crates/search.js +1 -0
- package/clis/crates/utils.js +1 -0
- package/clis/csdn/article.js +29 -0
- package/clis/csdn/columns.js +1 -0
- package/clis/csdn/login.js +1 -0
- package/clis/csdn/stats.js +71 -0
- package/clis/csdn/whoami.js +1 -0
- package/clis/cto51/article.js +1 -0
- package/clis/cto51/whoami.js +1 -0
- package/clis/ctrip/auth.js +1 -0
- package/clis/ctrip/flight.js +17 -0
- package/clis/ctrip/hotel-search.js +24 -0
- package/clis/ctrip/hotel-suggest.js +1 -0
- package/clis/ctrip/search.js +1 -0
- package/clis/ctrip/utils.js +119 -0
- package/clis/cursor/ask.js +22 -0
- package/clis/cursor/composer.js +12 -0
- package/clis/cursor/dump.js +1 -0
- package/clis/cursor/export.js +23 -0
- package/clis/cursor/extract-code.js +18 -0
- package/clis/cursor/history.js +26 -0
- package/clis/cursor/model.js +18 -0
- package/clis/cursor/new.js +1 -0
- package/clis/cursor/read.js +27 -0
- package/clis/cursor/screenshot.js +1 -0
- package/clis/cursor/send.js +12 -0
- package/clis/cursor/status.js +1 -0
- package/clis/dblp/author.js +1 -0
- package/clis/dblp/paper.js +1 -0
- package/clis/dblp/search.js +1 -0
- package/clis/dblp/utils.js +1 -0
- package/clis/dblp/venue.js +1 -0
- package/clis/deepseek/ask.js +1 -0
- package/clis/deepseek/auth.js +22 -0
- package/clis/deepseek/detail.js +1 -0
- package/clis/deepseek/history.js +1 -0
- package/clis/deepseek/new.js +1 -0
- package/clis/deepseek/read.js +1 -0
- package/clis/deepseek/send.js +50 -0
- package/clis/deepseek/status.js +1 -0
- package/clis/deepseek/utils.js +202 -0
- package/clis/defillama/protocol.js +1 -0
- package/clis/defillama/protocols.js +1 -0
- package/clis/defillama/utils.js +1 -0
- package/clis/devto/auth.js +9 -0
- package/clis/devto/latest.js +1 -0
- package/clis/devto/publish.js +17 -0
- package/clis/devto/read.js +3 -0
- package/clis/devto/stats.js +27 -0
- package/clis/devto/tag.js +1 -0
- package/clis/devto/top.js +1 -0
- package/clis/devto/user.js +1 -0
- package/clis/dianping/__fixtures__/search.html +168 -0
- package/clis/dianping/__fixtures__/shop.html +6 -0
- package/clis/dianping/auth.js +10 -0
- package/clis/dianping/cityResolver.js +4 -0
- package/clis/dianping/search.js +1 -0
- package/clis/dianping/shop.js +1 -0
- package/clis/dianping/utils.js +1 -0
- package/clis/dictionary/examples.js +1 -0
- package/clis/dictionary/search.js +1 -0
- package/clis/dictionary/synonyms.js +1 -0
- package/clis/discord-app/channels.js +1 -0
- package/clis/discord-app/delete.js +66 -0
- package/clis/discord-app/goto.js +1 -0
- package/clis/discord-app/members.js +21 -0
- package/clis/discord-app/read.js +1 -0
- package/clis/discord-app/search.js +29 -0
- package/clis/discord-app/send.js +10 -0
- package/clis/discord-app/servers.js +1 -0
- package/clis/discord-app/status.js +1 -0
- package/clis/discord-app/thread-read.js +1 -0
- package/clis/discord-app/threads.js +1 -0
- package/clis/discord-app/utils.js +226 -0
- package/clis/discord-web/auth.js +10 -0
- package/clis/discord-web/send.js +13 -0
- package/clis/dockerhub/image.js +1 -0
- package/clis/dockerhub/search.js +1 -0
- package/clis/dockerhub/utils.js +1 -0
- package/clis/dongchedi/__fixtures__/search.json +60 -0
- package/clis/dongchedi/__fixtures__/series-detail.json +911 -0
- package/clis/dongchedi/__fixtures__/series-score.json +1396 -0
- package/clis/dongchedi/koubei.js +1 -0
- package/clis/dongchedi/models.js +1 -0
- package/clis/dongchedi/score.js +1 -0
- package/clis/dongchedi/search.js +1 -0
- package/clis/dongchedi/series.js +1 -0
- package/clis/dongchedi/specs.js +1 -0
- package/clis/dongchedi/utils.js +1 -0
- package/clis/douban/article.js +53 -0
- package/clis/douban/auth.js +21 -0
- package/clis/douban/book-hot.js +1 -0
- package/clis/douban/download.js +1 -0
- package/clis/douban/marks.js +59 -0
- package/clis/douban/movie-hot.js +1 -0
- package/clis/douban/photos.js +1 -0
- package/clis/douban/reviews.js +53 -0
- package/clis/douban/search.js +1 -0
- package/clis/douban/subject.js +1 -0
- package/clis/douban/top250.js +50 -0
- package/clis/douban/utils.js +344 -0
- package/clis/doubao/ask.js +1 -0
- package/clis/doubao/auth.js +28 -0
- package/clis/doubao/detail.js +1 -0
- package/clis/doubao/history.js +1 -0
- package/clis/doubao/meeting-summary.js +1 -0
- package/clis/doubao/meeting-transcript.js +1 -0
- package/clis/doubao/new.js +1 -0
- package/clis/doubao/read.js +1 -0
- package/clis/doubao/send.js +1 -0
- package/clis/doubao/status.js +1 -0
- package/clis/doubao/utils.js +704 -0
- package/clis/doubao-app/ask.js +1 -0
- package/clis/doubao-app/dump.js +1 -0
- package/clis/doubao-app/new.js +1 -0
- package/clis/doubao-app/read.js +1 -0
- package/clis/doubao-app/screenshot.js +1 -0
- package/clis/doubao-app/send.js +1 -0
- package/clis/doubao-app/status.js +1 -0
- package/clis/doubao-app/utils.js +64 -0
- package/clis/douyin/_shared/browser-fetch.js +28 -0
- package/clis/douyin/_shared/creation-id.js +1 -0
- package/clis/douyin/_shared/evaluate-result.js +1 -0
- package/clis/douyin/_shared/imagex-upload.js +1 -0
- package/clis/douyin/_shared/public-api.js +1 -0
- package/clis/douyin/_shared/sts2.js +1 -0
- package/clis/douyin/_shared/text-extra.js +1 -0
- package/clis/douyin/_shared/timing.js +1 -0
- package/clis/douyin/_shared/tos-upload.js +5 -0
- package/clis/douyin/_shared/transcode.js +1 -0
- package/clis/douyin/_shared/types.js +1 -0
- package/clis/douyin/_shared/vod-upload.js +5 -0
- package/clis/douyin/activities.js +1 -0
- package/clis/douyin/auth.js +1 -0
- package/clis/douyin/collections.js +1 -0
- package/clis/douyin/delete.js +76 -0
- package/clis/douyin/draft.js +166 -0
- package/clis/douyin/drafts.js +1 -0
- package/clis/douyin/hashtag.js +1 -0
- package/clis/douyin/location.js +1 -0
- package/clis/douyin/profile.js +1 -0
- package/clis/douyin/publish-image.js +64 -0
- package/clis/douyin/publish.js +14 -0
- package/clis/douyin/search.js +51 -0
- package/clis/douyin/stats.js +1 -0
- package/clis/douyin/update.js +1 -0
- package/clis/douyin/user-videos.js +1 -0
- package/clis/douyin/videos.js +1 -0
- package/clis/duckduckgo/search.js +1 -0
- package/clis/duckduckgo/suggest.js +1 -0
- package/clis/eastmoney/_secid.js +1 -0
- package/clis/eastmoney/announcement.js +1 -0
- package/clis/eastmoney/article.js +1 -0
- package/clis/eastmoney/convertible.js +1 -0
- package/clis/eastmoney/etf.js +1 -0
- package/clis/eastmoney/holders.js +1 -0
- package/clis/eastmoney/hot-rank.js +30 -0
- package/clis/eastmoney/index-board.js +1 -0
- package/clis/eastmoney/kline.js +1 -0
- package/clis/eastmoney/kuaixun.js +1 -0
- package/clis/eastmoney/longhu.js +1 -0
- package/clis/eastmoney/money-flow.js +1 -0
- package/clis/eastmoney/northbound.js +1 -0
- package/clis/eastmoney/quote.js +1 -0
- package/clis/eastmoney/rank.js +1 -0
- package/clis/eastmoney/sectors.js +1 -0
- package/clis/eastmoney/whoami.js +1 -0
- package/clis/endoflife/product.js +1 -0
- package/clis/endoflife/utils.js +1 -0
- package/clis/facebook/__fixtures__/notifications-page.html +13 -0
- package/clis/facebook/add-friend.js +24 -0
- package/clis/facebook/auth.js +1 -0
- package/clis/facebook/comment.js +18 -0
- package/clis/facebook/events.js +26 -0
- package/clis/facebook/feed.js +209 -0
- package/clis/facebook/friends.js +24 -0
- package/clis/facebook/groups.js +32 -0
- package/clis/facebook/join-group.js +25 -0
- package/clis/facebook/like.js +29 -0
- package/clis/facebook/marketplace-inbox.js +34 -0
- package/clis/facebook/marketplace-listings.js +33 -0
- package/clis/facebook/memories.js +21 -0
- package/clis/facebook/notifications.js +31 -0
- package/clis/facebook/post.js +88 -0
- package/clis/facebook/profile.js +18 -0
- package/clis/facebook/search.js +22 -0
- package/clis/flathub/app.js +1 -0
- package/clis/flathub/search.js +1 -0
- package/clis/flathub/utils.js +1 -0
- package/clis/flomo/auth.js +22 -0
- package/clis/flomo/memos.js +13 -0
- package/clis/gemini/ask.js +1 -0
- package/clis/gemini/auth.js +14 -0
- package/clis/gemini/deep-research-result.js +4 -0
- package/clis/gemini/deep-research.js +1 -0
- package/clis/gemini/detail.js +1 -0
- package/clis/gemini/history.js +1 -0
- package/clis/gemini/image.js +3 -0
- package/clis/gemini/new.js +1 -0
- package/clis/gemini/read.js +1 -0
- package/clis/gemini/status.js +1 -0
- package/clis/gemini/utils.js +1234 -0
- package/clis/geogebra/add-circle.js +1 -0
- package/clis/geogebra/add-line.js +1 -0
- package/clis/geogebra/add-point.js +1 -0
- package/clis/geogebra/add-polygon.js +1 -0
- package/clis/geogebra/eval.js +1 -0
- package/clis/geogebra/hexagon.js +1 -0
- package/clis/geogebra/info.js +13 -0
- package/clis/geogebra/list.js +1 -0
- package/clis/geogebra/triangle.js +1 -0
- package/clis/geogebra/utils.js +99 -0
- package/clis/ghost/publish.js +1 -0
- package/clis/ghost/shared.js +1 -0
- package/clis/ghost/whoami.js +1 -0
- package/clis/gitee/auth.js +12 -0
- package/clis/gitee/index.js +1 -0
- package/clis/gitee/search.js +1 -0
- package/clis/gitee/trending.js +240 -0
- package/clis/gitee/user.js +71 -0
- package/clis/github/auth.js +7 -0
- package/clis/github-trending/repos.js +1 -0
- package/clis/google/news.js +1 -0
- package/clis/google/search.js +90 -0
- package/clis/google/suggest.js +1 -0
- package/clis/google/trends.js +1 -0
- package/clis/google/utils.js +1 -0
- package/clis/google-scholar/cite.js +20 -0
- package/clis/google-scholar/profile.js +36 -0
- package/clis/google-scholar/search.js +35 -0
- package/clis/goproxy/module.js +1 -0
- package/clis/goproxy/utils.js +1 -0
- package/clis/goproxy/versions.js +1 -0
- package/clis/gov-law/recent.js +1 -0
- package/clis/gov-law/search.js +14 -0
- package/clis/gov-law/shared.js +29 -0
- package/clis/gov-policy/__fixtures__/recent.html +16 -0
- package/clis/gov-policy/__fixtures__/search.html +41 -0
- package/clis/gov-policy/recent.js +8 -0
- package/clis/gov-policy/search.js +8 -0
- package/clis/gov-policy/utils.js +1 -0
- package/clis/grok/ask.js +1 -0
- package/clis/grok/auth.js +17 -0
- package/clis/grok/delete.js +1 -0
- package/clis/grok/detail.js +1 -0
- package/clis/grok/export-all.js +170 -0
- package/clis/grok/export-utils.js +1 -0
- package/clis/grok/export.js +106 -0
- package/clis/grok/history.js +1 -0
- package/clis/grok/image.js +119 -0
- package/clis/grok/image.test.ts +127 -0
- package/clis/grok/new.js +1 -0
- package/clis/grok/pin.js +1 -0
- package/clis/grok/read.js +1 -0
- package/clis/grok/send.js +1 -0
- package/clis/grok/status.js +1 -0
- package/clis/grok/utils.js +337 -0
- package/clis/guazi/__fixtures__/detail.html +7 -0
- package/clis/guazi/__fixtures__/list.html +5 -0
- package/clis/guazi/browse.js +1 -0
- package/clis/guazi/car.js +1 -0
- package/clis/guazi/utils.js +1 -0
- package/clis/hackernews/ask.js +1 -0
- package/clis/hackernews/auth.js +9 -0
- package/clis/hackernews/best.js +1 -0
- package/clis/hackernews/comment.js +61 -0
- package/clis/hackernews/jobs.js +1 -0
- package/clis/hackernews/new.js +1 -0
- package/clis/hackernews/read.js +11 -0
- package/clis/hackernews/search.js +1 -0
- package/clis/hackernews/show.js +1 -0
- package/clis/hackernews/submit.js +65 -0
- package/clis/hackernews/top.js +1 -0
- package/clis/hackernews/user.js +1 -0
- package/clis/hashnode/auth.js +11 -0
- package/clis/hashnode/publish.js +92 -0
- package/clis/hf/auth.js +12 -0
- package/clis/hf/datasets.js +1 -0
- package/clis/hf/models.js +1 -0
- package/clis/hf/paper.js +1 -0
- package/clis/hf/spaces.js +1 -0
- package/clis/hf/top.js +1 -0
- package/clis/homebrew/cask.js +1 -0
- package/clis/homebrew/formula.js +1 -0
- package/clis/homebrew/popular.js +1 -0
- package/clis/homebrew/utils.js +1 -0
- package/clis/huodongxing/events.js +1 -0
- package/clis/hupu/__fixtures__/hot-home.html +64 -0
- package/clis/hupu/auth.js +14 -0
- package/clis/hupu/detail.js +7 -0
- package/clis/hupu/hot.js +14 -0
- package/clis/hupu/like.js +1 -0
- package/clis/hupu/mentions.js +91 -0
- package/clis/hupu/reply.js +1 -0
- package/clis/hupu/search.js +1 -0
- package/clis/hupu/unlike.js +1 -0
- package/clis/hupu/utils.js +243 -0
- package/clis/imdb/person.js +140 -0
- package/clis/imdb/reviews.js +40 -0
- package/clis/imdb/search.js +113 -0
- package/clis/imdb/title.js +1 -0
- package/clis/imdb/top.js +1 -0
- package/clis/imdb/trending.js +1 -0
- package/clis/imdb/utils.js +162 -0
- package/clis/imooc/article.js +59 -0
- package/clis/imooc/login.js +1 -0
- package/clis/imooc/whoami.js +1 -0
- package/clis/indeed/job.js +20 -0
- package/clis/indeed/search.js +37 -0
- package/clis/indeed/utils.js +1 -0
- package/clis/infoq/article.js +19 -0
- package/clis/infoq/login.js +1 -0
- package/clis/infoq/whoami.js +1 -0
- package/clis/instagram/_shared/private-publish.js +75 -0
- package/clis/instagram/_shared/protocol-capture.js +180 -0
- package/clis/instagram/_shared/runtime-info.js +33 -0
- package/clis/instagram/auth.js +22 -0
- package/clis/instagram/collection-create.js +38 -0
- package/clis/instagram/collection-delete.js +72 -0
- package/clis/instagram/comment.js +26 -0
- package/clis/instagram/detail.js +2 -0
- package/clis/instagram/download.js +83 -0
- package/clis/instagram/explore.js +27 -0
- package/clis/instagram/follow.js +24 -0
- package/clis/instagram/followers.js +30 -0
- package/clis/instagram/following.js +74 -0
- package/clis/instagram/like.js +25 -0
- package/clis/instagram/note.js +162 -0
- package/clis/instagram/post.js +718 -0
- package/clis/instagram/profile.js +25 -0
- package/clis/instagram/reel.js +452 -0
- package/clis/instagram/save.js +25 -0
- package/clis/instagram/saved.js +37 -0
- package/clis/instagram/search.js +23 -0
- package/clis/instagram/story.js +21 -0
- package/clis/instagram/unfollow.js +21 -0
- package/clis/instagram/unlike.js +25 -0
- package/clis/instagram/unsave.js +25 -0
- package/clis/instagram/user.js +1 -0
- package/clis/jd/add-cart.js +22 -0
- package/clis/jd/auth.js +12 -0
- package/clis/jd/cart.js +59 -0
- package/clis/jd/detail.js +42 -0
- package/clis/jd/item.js +98 -0
- package/clis/jd/item.test.ts +517 -0
- package/clis/jd/reviews.js +31 -0
- package/clis/jd/search.js +42 -0
- package/clis/jianshu/article.js +1 -0
- package/clis/jianshu/login.js +1 -0
- package/clis/jianshu/notebooks.js +1 -0
- package/clis/jianshu/whoami.js +1 -0
- package/clis/jianyu/auth.js +28 -0
- package/clis/jianyu/detail.js +1 -0
- package/clis/jianyu/search.js +73 -0
- package/clis/jianyu/shared/china-bid-search.js +86 -0
- package/clis/jianyu/shared/procurement-contract.js +1 -0
- package/clis/jianyu/shared/procurement-detail.js +18 -0
- package/clis/jike/auth.js +19 -0
- package/clis/jike/comment.js +82 -0
- package/clis/jike/create.js +83 -0
- package/clis/jike/feed.js +32 -0
- package/clis/jike/like.js +38 -0
- package/clis/jike/notifications.js +115 -0
- package/clis/jike/post.js +33 -0
- package/clis/jike/repost.js +67 -0
- package/clis/jike/search.js +29 -0
- package/clis/jike/topic.js +20 -0
- package/clis/jike/user.js +19 -0
- package/clis/jike/utils.js +15 -0
- package/clis/jimeng/auth.js +13 -0
- package/clis/jimeng/generate.js +60 -0
- package/clis/jimeng/history.js +32 -0
- package/clis/jimeng/new.js +26 -0
- package/clis/jimeng/workspaces.js +22 -0
- package/clis/jira/attachments.js +1 -0
- package/clis/jira/comments.js +1 -0
- package/clis/jira/issue.js +1 -0
- package/clis/jira/links.js +1 -0
- package/clis/jira/search.js +1 -0
- package/clis/jira/shared.js +1 -0
- package/clis/juejin/article.js +5 -0
- package/clis/juejin/categories.js +1 -0
- package/clis/juejin/hot.js +1 -0
- package/clis/juejin/login.js +1 -0
- package/clis/juejin/recommend.js +1 -0
- package/clis/juejin/stats.js +53 -0
- package/clis/juejin/tags.js +1 -0
- package/clis/juejin/utils.js +1 -0
- package/clis/juejin/whoami.js +1 -0
- package/clis/ke/auth.js +14 -0
- package/clis/ke/chengjiao.js +45 -0
- package/clis/ke/ershoufang.js +50 -0
- package/clis/ke/utils.js +21 -0
- package/clis/ke/xiaoqu.js +45 -0
- package/clis/ke/zufang.js +50 -0
- package/clis/kimi/_utils.js +38 -0
- package/clis/kimi/audit-extras.js +64 -0
- package/clis/kimi/auth.js +17 -0
- package/clis/kimi/chat.js +77 -0
- package/clis/kimi/storage.js +14 -0
- package/clis/kimi/ui.js +89 -0
- package/clis/kimi/usage.js +51 -0
- package/clis/kuaishou/auth.js +1 -0
- package/clis/kuaishou/publish.js +53 -0
- package/clis/lesswrong/_helpers.js +9 -0
- package/clis/lesswrong/comments.js +9 -0
- package/clis/lesswrong/curated.js +5 -0
- package/clis/lesswrong/frontpage.js +5 -0
- package/clis/lesswrong/new.js +5 -0
- package/clis/lesswrong/read.js +5 -0
- package/clis/lesswrong/sequences.js +5 -0
- package/clis/lesswrong/shortform.js +5 -0
- package/clis/lesswrong/tag.js +5 -0
- package/clis/lesswrong/tags.js +5 -0
- package/clis/lesswrong/top-month.js +5 -0
- package/clis/lesswrong/top-week.js +5 -0
- package/clis/lesswrong/top-year.js +5 -0
- package/clis/lesswrong/top.js +5 -0
- package/clis/lesswrong/user-posts.js +5 -0
- package/clis/lesswrong/user.js +5 -0
- package/clis/lichess/top.js +1 -0
- package/clis/lichess/user.js +1 -0
- package/clis/lichess/utils.js +1 -0
- package/clis/linkedin/auth.js +27 -0
- package/clis/linkedin/comment.js +1 -0
- package/clis/linkedin/connect.js +244 -0
- package/clis/linkedin/create.js +113 -0
- package/clis/linkedin/follow.js +1 -0
- package/clis/linkedin/inbox.js +1 -0
- package/clis/linkedin/job-detail.js +40 -0
- package/clis/linkedin/jobs-preferences.js +34 -0
- package/clis/linkedin/like.js +1 -0
- package/clis/linkedin/notifications.js +1 -0
- package/clis/linkedin/people-search.js +1 -0
- package/clis/linkedin/post-analytics.js +1 -0
- package/clis/linkedin/post-comments.js +1 -0
- package/clis/linkedin/post-detail.js +1 -0
- package/clis/linkedin/posts-core.js +138 -0
- package/clis/linkedin/posts.js +1 -0
- package/clis/linkedin/profile-analytics.js +1 -0
- package/clis/linkedin/profile-api.js +218 -0
- package/clis/linkedin/profile-experience.js +1 -0
- package/clis/linkedin/profile-projects.js +1 -0
- package/clis/linkedin/profile-read.js +3 -0
- package/clis/linkedin/reply.js +1 -0
- package/clis/linkedin/repost.js +1 -0
- package/clis/linkedin/safe-send.js +155 -0
- package/clis/linkedin/salesnav-inbox.js +21 -0
- package/clis/linkedin/salesnav-message.js +33 -0
- package/clis/linkedin/salesnav-search.js +15 -0
- package/clis/linkedin/salesnav-thread.js +1 -0
- package/clis/linkedin/search-api.js +42 -0
- package/clis/linkedin/search.js +50 -0
- package/clis/linkedin/sent-invitations.js +46 -0
- package/clis/linkedin/services-read.js +57 -0
- package/clis/linkedin/shared.js +10 -0
- package/clis/linkedin/social-api.js +260 -0
- package/clis/linkedin/thread-snapshot.js +81 -0
- package/clis/linkedin/timeline.js +37 -0
- package/clis/linkedin-learning/auth.js +27 -0
- package/clis/linkedin-learning/course.js +17 -0
- package/clis/linkedin-learning/search.js +17 -0
- package/clis/linkedin-learning/trending.js +17 -0
- package/clis/linux-do/auth.js +20 -0
- package/clis/linux-do/categories.js +1 -0
- package/clis/linux-do/feed.js +19 -0
- package/clis/linux-do/search.js +1 -0
- package/clis/linux-do/tags.js +1 -0
- package/clis/linux-do/topic-content.js +28 -0
- package/clis/linux-do/topic.js +1 -0
- package/clis/linux-do/user-posts.js +1 -0
- package/clis/linux-do/user-topics.js +1 -0
- package/clis/lobsters/active.js +1 -0
- package/clis/lobsters/domain.js +1 -0
- package/clis/lobsters/hot.js +1 -0
- package/clis/lobsters/newest.js +1 -0
- package/clis/lobsters/read.js +11 -0
- package/clis/lobsters/tag.js +1 -0
- package/clis/maimai/auth.js +19 -0
- package/clis/maimai/search-talents.js +37 -0
- package/clis/manus/_utils.js +28 -0
- package/clis/manus/auth.js +20 -0
- package/clis/manus/connectors.js +4 -0
- package/clis/manus/credits.js +4 -0
- package/clis/manus/list.js +7 -0
- package/clis/manus/read.js +7 -0
- package/clis/manus/skills.js +4 -0
- package/clis/manus/status.js +8 -0
- package/clis/mastodon/post.js +1 -0
- package/clis/mastodon/shared.js +48 -0
- package/clis/mastodon/whoami.js +1 -0
- package/clis/maven/artifact.js +1 -0
- package/clis/maven/search.js +1 -0
- package/clis/maven/utils.js +1 -0
- package/clis/mdn/search.js +1 -0
- package/clis/medium/article.js +12 -0
- package/clis/medium/feed.js +1 -0
- package/clis/medium/login.js +1 -0
- package/clis/medium/search.js +1 -0
- package/clis/medium/stats.js +56 -0
- package/clis/medium/tag.js +1 -0
- package/clis/medium/user.js +1 -0
- package/clis/medium/utils.js +62 -0
- package/clis/medium/whoami.js +1 -0
- package/clis/mubu/doc.js +1 -0
- package/clis/mubu/docs.js +1 -0
- package/clis/mubu/notes.js +1 -0
- package/clis/mubu/recent.js +1 -0
- package/clis/mubu/search.js +1 -0
- package/clis/mubu/utils.js +31 -0
- package/clis/note/auth.js +12 -0
- package/clis/note/note-utils.js +2 -0
- package/clis/note/publish.js +17 -0
- package/clis/notebooklm/add-source.js +46 -0
- package/clis/notebooklm/auth.js +21 -0
- package/clis/notebooklm/create.js +1 -0
- package/clis/notebooklm/current.js +1 -0
- package/clis/notebooklm/generate-audio.js +1 -0
- package/clis/notebooklm/generate-slides.js +1 -0
- package/clis/notebooklm/get.js +1 -0
- package/clis/notebooklm/history.js +1 -0
- package/clis/notebooklm/list.js +1 -0
- package/clis/notebooklm/note-list.js +1 -0
- package/clis/notebooklm/notes-get.js +1 -0
- package/clis/notebooklm/open.js +1 -0
- package/clis/notebooklm/rpc.js +36 -0
- package/clis/notebooklm/shared.js +1 -0
- package/clis/notebooklm/source-fulltext.js +1 -0
- package/clis/notebooklm/source-get.js +1 -0
- package/clis/notebooklm/source-guide.js +1 -0
- package/clis/notebooklm/source-list.js +1 -0
- package/clis/notebooklm/status.js +1 -0
- package/clis/notebooklm/summary.js +1 -0
- package/clis/notebooklm/utils.js +172 -0
- package/clis/notebooklm/write-note.js +1 -0
- package/clis/nowcoder/auth.js +24 -0
- package/clis/nowcoder/comment.js +1 -0
- package/clis/nowcoder/comments.js +1 -0
- package/clis/nowcoder/companies.js +1 -0
- package/clis/nowcoder/creators.js +1 -0
- package/clis/nowcoder/delete.js +1 -0
- package/clis/nowcoder/detail.js +46 -0
- package/clis/nowcoder/dm-list.js +1 -0
- package/clis/nowcoder/dm-read.js +1 -0
- package/clis/nowcoder/dm-send.js +1 -0
- package/clis/nowcoder/drafts.js +1 -0
- package/clis/nowcoder/experience.js +20 -0
- package/clis/nowcoder/hot.js +1 -0
- package/clis/nowcoder/inbox.js +1 -0
- package/clis/nowcoder/jobs.js +1 -0
- package/clis/nowcoder/like.js +1 -0
- package/clis/nowcoder/my.js +1 -0
- package/clis/nowcoder/notifications.js +16 -0
- package/clis/nowcoder/papers.js +22 -0
- package/clis/nowcoder/post.js +1 -0
- package/clis/nowcoder/practice.js +21 -0
- package/clis/nowcoder/recommend.js +1 -0
- package/clis/nowcoder/referral.js +21 -0
- package/clis/nowcoder/salary.js +22 -0
- package/clis/nowcoder/search.js +31 -0
- package/clis/nowcoder/suggest.js +17 -0
- package/clis/nowcoder/topics.js +1 -0
- package/clis/nowcoder/trending.js +1 -0
- package/clis/nowcoder/utils.js +68 -0
- package/clis/npm/downloads.js +1 -0
- package/clis/npm/package.js +1 -0
- package/clis/npm/search.js +1 -0
- package/clis/npm/utils.js +1 -0
- package/clis/nuget/package.js +1 -0
- package/clis/nuget/search.js +1 -0
- package/clis/nuget/utils.js +1 -0
- package/clis/nvd/cve.js +1 -0
- package/clis/oeis/search.js +1 -0
- package/clis/oeis/sequence.js +1 -0
- package/clis/oeis/utils.js +1 -0
- package/clis/ones/common.js +23 -0
- package/clis/ones/enrich-tasks.js +1 -0
- package/clis/ones/login.js +2 -0
- package/clis/ones/logout.js +1 -0
- package/clis/ones/me.js +1 -0
- package/clis/ones/my-tasks.js +1 -0
- package/clis/ones/resolve-labels.js +1 -0
- package/clis/ones/task-helpers.js +1 -0
- package/clis/ones/task.js +1 -0
- package/clis/ones/tasks.js +1 -0
- package/clis/ones/token-info.js +1 -0
- package/clis/ones/worklog.js +14 -0
- package/clis/openalex/search.js +1 -0
- package/clis/openalex/utils.js +1 -0
- package/clis/openalex/work.js +1 -0
- package/clis/openfda/drug-label.js +1 -0
- package/clis/openfda/food-recall.js +1 -0
- package/clis/openfda/utils.js +1 -0
- package/clis/openreview/author.js +1 -0
- package/clis/openreview/paper.js +1 -0
- package/clis/openreview/reviews.js +4 -0
- package/clis/openreview/search.js +1 -0
- package/clis/openreview/utils.js +1 -0
- package/clis/openreview/venue.js +1 -0
- package/clis/oschina/article.js +1 -0
- package/clis/oschina/catalogs.js +1 -0
- package/clis/oschina/login.js +1 -0
- package/clis/oschina/stats.js +54 -0
- package/clis/oschina/whoami.js +1 -0
- package/clis/osv/query.js +1 -0
- package/clis/osv/utils.js +1 -0
- package/clis/osv/vulnerability.js +1 -0
- package/clis/packagist/package.js +1 -0
- package/clis/packagist/search.js +1 -0
- package/clis/packagist/utils.js +1 -0
- package/clis/paperreview/feedback.js +1 -0
- package/clis/paperreview/review.js +1 -0
- package/clis/paperreview/submit.js +1 -0
- package/clis/paperreview/utils.js +1 -0
- package/clis/pinterest/api.js +1 -0
- package/clis/pinterest/auth.js +1 -0
- package/clis/pinterest/boards.js +1 -0
- package/clis/pinterest/client.js +20 -0
- package/clis/pinterest/publish.js +13 -0
- package/clis/pixiv/auth.js +17 -0
- package/clis/pixiv/detail.js +1 -0
- package/clis/pixiv/download.js +1 -0
- package/clis/pixiv/illusts.js +1 -0
- package/clis/pixiv/ranking.js +26 -0
- package/clis/pixiv/search.js +1 -0
- package/clis/pixiv/user.js +1 -0
- package/clis/pixiv/utils.js +18 -0
- package/clis/powerchina/auth.js +17 -0
- package/clis/powerchina/search.js +1 -0
- package/clis/producthunt/browse.js +54 -0
- package/clis/producthunt/hot.js +64 -0
- package/clis/producthunt/posts.js +1 -0
- package/clis/producthunt/today.js +1 -0
- package/clis/producthunt/utils.js +1 -0
- package/clis/pubmed/article.js +1 -0
- package/clis/pubmed/author.js +1 -0
- package/clis/pubmed/citations.js +1 -0
- package/clis/pubmed/clinical-trial.js +1 -0
- package/clis/pubmed/journal.js +1 -0
- package/clis/pubmed/mesh.js +1 -0
- package/clis/pubmed/related.js +1 -0
- package/clis/pubmed/review.js +1 -0
- package/clis/pubmed/search.js +1 -0
- package/clis/pubmed/utils.js +1 -0
- package/clis/pypi/downloads.js +1 -0
- package/clis/pypi/package.js +1 -0
- package/clis/pypi/utils.js +1 -0
- package/clis/qiita/auth.js +1 -0
- package/clis/qiita/gql.js +32 -0
- package/clis/qiita/publish.js +7 -0
- package/clis/qiita/stats.js +37 -0
- package/clis/qoder/_utils.js +113 -0
- package/clis/qoder/composer.js +1 -0
- package/clis/qoder/history.js +25 -0
- package/clis/qoder/quest.js +1 -0
- package/clis/qoder/read.js +1 -0
- package/clis/qoder/status.js +1 -0
- package/clis/qoder/ui.js +59 -0
- package/clis/quark/auth.js +16 -0
- package/clis/quark/ls.js +1 -0
- package/clis/quark/mkdir.js +1 -0
- package/clis/quark/mv.js +1 -0
- package/clis/quark/rename.js +1 -0
- package/clis/quark/rm.js +1 -0
- package/clis/quark/save.js +1 -0
- package/clis/quark/share-tree.js +1 -0
- package/clis/quark/utils.js +13 -0
- package/clis/quora/create-answer.js +22 -0
- package/clis/quora/create-question.js +24 -0
- package/clis/quora/shared.js +43 -0
- package/clis/quora/whoami.js +1 -0
- package/clis/qwen/ask.js +1 -0
- package/clis/qwen/auth.js +17 -0
- package/clis/qwen/detail.js +1 -0
- package/clis/qwen/history.js +1 -0
- package/clis/qwen/image.js +31 -0
- package/clis/qwen/new.js +1 -0
- package/clis/qwen/read.js +1 -0
- package/clis/qwen/send.js +1 -0
- package/clis/qwen/status.js +1 -0
- package/clis/qwen/utils.js +185 -0
- package/clis/reddit/auth.js +17 -0
- package/clis/reddit/comment.js +36 -0
- package/clis/reddit/frontpage.js +40 -0
- package/clis/reddit/home.js +32 -0
- package/clis/reddit/hot.js +46 -0
- package/clis/reddit/popular.js +46 -0
- package/clis/reddit/read.js +398 -0
- package/clis/reddit/reply.js +56 -0
- package/clis/reddit/save.js +30 -0
- package/clis/reddit/saved.js +24 -0
- package/clis/reddit/search.js +51 -0
- package/clis/reddit/submit.js +42 -0
- package/clis/reddit/subreddit-info.js +29 -0
- package/clis/reddit/subreddit.js +52 -0
- package/clis/reddit/subscribe.js +29 -0
- package/clis/reddit/subscribed.js +68 -0
- package/clis/reddit/upvote.js +43 -0
- package/clis/reddit/upvoted.js +24 -0
- package/clis/reddit/user-comments.js +20 -0
- package/clis/reddit/user-posts.js +17 -0
- package/clis/reddit/user.js +20 -0
- package/clis/reddit/whoami.js +19 -0
- package/clis/rednote/auth.js +19 -0
- package/clis/rednote/comments.js +1 -0
- package/clis/rednote/download.js +1 -0
- package/clis/rednote/feed.js +1 -0
- package/clis/rednote/note.js +1 -0
- package/clis/rednote/notifications.js +67 -0
- package/clis/rednote/search.js +32 -0
- package/clis/rednote/user.js +1 -0
- package/clis/rest-countries/country.js +1 -0
- package/clis/rest-countries/region.js +1 -0
- package/clis/rest-countries/utils.js +1 -0
- package/clis/reuters/article-detail.js +1 -0
- package/clis/reuters/auth.js +39 -0
- package/clis/reuters/search.js +1 -0
- package/clis/reuters/utils.js +50 -0
- package/clis/rfc/rfc.js +1 -0
- package/clis/rfc/utils.js +1 -0
- package/clis/rubygems/gem.js +1 -0
- package/clis/rubygems/search.js +1 -0
- package/clis/rubygems/utils.js +1 -0
- package/clis/segmentfault/_signed-request.js +43 -0
- package/clis/segmentfault/article.js +3 -0
- package/clis/segmentfault/channels.js +1 -0
- package/clis/segmentfault/login.js +1 -0
- package/clis/segmentfault/stats.js +82 -0
- package/clis/segmentfault/tags.js +1 -0
- package/clis/segmentfault/whoami.js +1 -0
- package/clis/semanticscholar/citations.js +1 -0
- package/clis/semanticscholar/paper.js +1 -0
- package/clis/semanticscholar/recommendations.js +1 -0
- package/clis/semanticscholar/search.js +1 -0
- package/clis/semanticscholar/utils.js +1 -0
- package/clis/sinablog/article.js +1 -0
- package/clis/sinablog/hot.js +1 -0
- package/clis/sinablog/search.js +1 -0
- package/clis/sinablog/user.js +1 -0
- package/clis/sinablog/utils.js +153 -0
- package/clis/sinafinance/news.js +1 -0
- package/clis/sinafinance/rolling-news.js +20 -0
- package/clis/sinafinance/stock-rank.js +41 -0
- package/clis/sinafinance/stock.js +1 -0
- package/clis/slock/attachment-download.js +1 -0
- package/clis/slock/attachment-upload.js +34 -0
- package/clis/slock/attachment-url.js +1 -0
- package/clis/slock/auth-verify.js +1 -0
- package/clis/slock/bookmark-add.js +11 -0
- package/clis/slock/bookmark-list.js +10 -0
- package/clis/slock/bookmark-remove.js +7 -0
- package/clis/slock/channel-action.js +1 -0
- package/clis/slock/channel-archive.js +1 -0
- package/clis/slock/channel-create.js +1 -0
- package/clis/slock/channel-files.js +1 -0
- package/clis/slock/channel-info.js +1 -0
- package/clis/slock/channel-join.js +1 -0
- package/clis/slock/channel-leave.js +1 -0
- package/clis/slock/channel-list.js +1 -0
- package/clis/slock/channel-mark.js +1 -0
- package/clis/slock/channel-members.js +1 -0
- package/clis/slock/channel-unarchive.js +1 -0
- package/clis/slock/dm-list.js +1 -0
- package/clis/slock/errors.js +1 -0
- package/clis/slock/in-page.js +113 -0
- package/clis/slock/inbox-done.js +9 -0
- package/clis/slock/inbox-read-all.js +1 -0
- package/clis/slock/inbox.js +1 -0
- package/clis/slock/login.js +1 -0
- package/clis/slock/message-read.js +61 -0
- package/clis/slock/message-search.js +24 -0
- package/clis/slock/message-send.js +55 -0
- package/clis/slock/reaction-add.js +1 -0
- package/clis/slock/reaction-remove.js +1 -0
- package/clis/slock/resolve.js +1 -0
- package/clis/slock/server-list.js +9 -0
- package/clis/slock/server-use.js +18 -0
- package/clis/slock/shared.js +1 -0
- package/clis/slock/task-claim.js +14 -0
- package/clis/slock/task-convert.js +35 -0
- package/clis/slock/task-create.js +24 -0
- package/clis/slock/task-delete.js +9 -0
- package/clis/slock/task-get.js +11 -0
- package/clis/slock/task-list-server.js +12 -0
- package/clis/slock/task-list.js +14 -0
- package/clis/slock/task-status.js +19 -0
- package/clis/slock/task-unclaim.js +13 -0
- package/clis/slock/thread-done.js +1 -0
- package/clis/slock/thread-follow.js +1 -0
- package/clis/slock/thread-list.js +1 -0
- package/clis/slock/thread-state.js +1 -0
- package/clis/slock/thread-undone.js +1 -0
- package/clis/slock/thread-unfollow.js +1 -0
- package/clis/slock/unread-summary.js +18 -0
- package/clis/slock/whoami.js +1 -0
- package/clis/smzdm/search.js +71 -0
- package/clis/sohu/article.js +1 -0
- package/clis/sohu/attributes.js +1 -0
- package/clis/sohu/categories.js +1 -0
- package/clis/sohu/channels.js +1 -0
- package/clis/sohu/columns.js +1 -0
- package/clis/sohu/login.js +1 -0
- package/clis/sohu/mpbp.js +1 -0
- package/clis/sohu/stats.js +95 -0
- package/clis/sohu/topics.js +1 -0
- package/clis/sohu/whoami.js +1 -0
- package/clis/spotify/spotify.js +1 -0
- package/clis/spotify/utils.js +8 -0
- package/clis/stackoverflow/bounties.js +1 -0
- package/clis/stackoverflow/hot.js +1 -0
- package/clis/stackoverflow/read.js +13 -0
- package/clis/stackoverflow/related.js +1 -0
- package/clis/stackoverflow/search.js +1 -0
- package/clis/stackoverflow/tag.js +1 -0
- package/clis/stackoverflow/unanswered.js +1 -0
- package/clis/stackoverflow/user.js +1 -0
- package/clis/stackoverflow/utils.js +1 -0
- package/clis/steam/app.js +1 -0
- package/clis/steam/search.js +1 -0
- package/clis/steam/top-sellers.js +1 -0
- package/clis/steam/utils.js +1 -0
- package/clis/substack/auth.js +11 -0
- package/clis/substack/feed.js +1 -0
- package/clis/substack/post-utils.js +2 -0
- package/clis/substack/publication.js +1 -0
- package/clis/substack/publish.js +10 -0
- package/clis/substack/search.js +1 -0
- package/clis/substack/utils.js +108 -0
- package/clis/suno/auth.js +21 -0
- package/clis/suno/download.js +17 -0
- package/clis/suno/generate.js +4 -0
- package/clis/suno/list.js +14 -0
- package/clis/suno/status.js +1 -0
- package/clis/suno/utils.js +102 -0
- package/clis/taobao/add-cart.js +93 -0
- package/clis/taobao/auth.js +8 -0
- package/clis/taobao/cart.js +68 -0
- package/clis/taobao/detail.js +48 -0
- package/clis/taobao/reviews.js +52 -0
- package/clis/taobao/search.js +64 -0
- package/clis/tdx/hot-rank.js +25 -0
- package/clis/telegram/send.js +18 -0
- package/clis/telegram/shared.js +21 -0
- package/clis/telegram/whoami.js +1 -0
- package/clis/test-utils.js +1 -0
- package/clis/threads/post.js +152 -0
- package/clis/threads/shared.js +27 -0
- package/clis/threads/whoami.js +1 -0
- package/clis/ths/hot-rank.js +27 -0
- package/clis/tieba/hot.js +16 -0
- package/clis/tieba/posts.js +1 -0
- package/clis/tieba/read.js +84 -0
- package/clis/tieba/search.js +54 -0
- package/clis/tieba/utils.js +1 -0
- package/clis/tiktok/auth.js +30 -0
- package/clis/tiktok/comment.js +69 -0
- package/clis/tiktok/creator-videos.js +45 -0
- package/clis/tiktok/explore.js +76 -0
- package/clis/tiktok/follow.js +49 -0
- package/clis/tiktok/following.js +103 -0
- package/clis/tiktok/friends.js +79 -0
- package/clis/tiktok/like.js +19 -0
- package/clis/tiktok/live.js +79 -0
- package/clis/tiktok/notifications.js +77 -0
- package/clis/tiktok/profile.js +26 -0
- package/clis/tiktok/publish.js +82 -0
- package/clis/tiktok/save.js +15 -0
- package/clis/tiktok/search.js +24 -0
- package/clis/tiktok/unfollow.js +59 -0
- package/clis/tiktok/unlike.js +19 -0
- package/clis/tiktok/unsave.js +17 -0
- package/clis/tiktok/user.js +143 -0
- package/clis/tiktok/utils.js +272 -0
- package/clis/toutiao/article.js +1 -0
- package/clis/toutiao/articles.js +6 -0
- package/clis/toutiao/auth.js +50 -0
- package/clis/toutiao/hot.js +1 -0
- package/clis/toutiao/utils.js +2 -0
- package/clis/trae-cn/activity.js +1 -0
- package/clis/trae-cn/approve.js +1 -0
- package/clis/trae-cn/ask.js +1 -0
- package/clis/trae-cn/dump.js +1 -0
- package/clis/trae-cn/export.js +3 -0
- package/clis/trae-cn/model.js +1 -0
- package/clis/trae-cn/new.js +1 -0
- package/clis/trae-cn/read.js +1 -0
- package/clis/trae-cn/screenshot.js +1 -0
- package/clis/trae-cn/select-model.js +1 -0
- package/clis/trae-cn/send.js +1 -0
- package/clis/trae-cn/setup.js +1 -0
- package/clis/trae-cn/status.js +1 -0
- package/clis/trae-cn/targets.js +1 -0
- package/clis/trae-cn/utils.js +456 -0
- package/clis/trae-cn/watch.js +3 -0
- package/clis/trae-solo/_actions.js +41 -0
- package/clis/trae-solo/_fs.js +6 -0
- package/clis/trae-solo/_state.js +2 -0
- package/clis/trae-solo/automation.js +43 -0
- package/clis/trae-solo/history.js +15 -0
- package/clis/trae-solo/mode.js +31 -0
- package/clis/trae-solo/model.js +50 -0
- package/clis/trae-solo/renderer-storage.js +11 -0
- package/clis/trae-solo/settings.js +1 -0
- package/clis/trae-solo/skill-fs.js +1 -0
- package/clis/trae-solo/skill.js +81 -0
- package/clis/trae-solo/state-fs.js +2 -0
- package/clis/trae-solo/status.js +1 -0
- package/clis/trae-solo/task-fs.js +5 -0
- package/clis/trae-solo/user-rules.js +1 -0
- package/clis/trae-solo/workspaces-fs.js +1 -0
- package/clis/tumblr/auth.js +24 -0
- package/clis/tumblr/publish.js +14 -0
- package/clis/tvmaze/search.js +1 -0
- package/clis/tvmaze/show.js +1 -0
- package/clis/tvmaze/utils.js +1 -0
- package/clis/twitter/accept.js +116 -0
- package/clis/twitter/article.js +116 -0
- package/clis/twitter/auth.js +4 -0
- package/clis/twitter/block.js +62 -0
- package/clis/twitter/bookmark-folder.js +4 -0
- package/clis/twitter/bookmark-folders.js +4 -0
- package/clis/twitter/bookmark.js +44 -0
- package/clis/twitter/bookmarks.js +27 -0
- package/clis/twitter/delete.js +36 -0
- package/clis/twitter/device-follow.js +13 -0
- package/clis/twitter/dm-list.js +1 -0
- package/clis/twitter/dm-read.js +1 -0
- package/clis/twitter/dm-send.js +13 -0
- package/clis/twitter/dm-shared.js +6 -0
- package/clis/twitter/download.js +38 -0
- package/clis/twitter/follow-batch.js +43 -0
- package/clis/twitter/follow.js +39 -0
- package/clis/twitter/followers.js +59 -0
- package/clis/twitter/following.js +4 -0
- package/clis/twitter/hide-reply.js +57 -0
- package/clis/twitter/like.js +48 -0
- package/clis/twitter/likes.js +14 -0
- package/clis/twitter/list-add-batch.js +1 -0
- package/clis/twitter/list-add-core.js +35 -0
- package/clis/twitter/list-add.js +1 -0
- package/clis/twitter/list-batch-utils.js +1 -0
- package/clis/twitter/list-create.js +12 -0
- package/clis/twitter/list-delete.js +36 -0
- package/clis/twitter/list-remove-batch.js +1 -0
- package/clis/twitter/list-remove-core.js +127 -0
- package/clis/twitter/list-remove.js +1 -0
- package/clis/twitter/list-tweets.js +27 -0
- package/clis/twitter/lists.js +27 -0
- package/clis/twitter/notifications.js +4 -0
- package/clis/twitter/post.js +158 -0
- package/clis/twitter/profile.js +66 -0
- package/clis/twitter/quote.js +123 -0
- package/clis/twitter/reply-dm.js +112 -0
- package/clis/twitter/reply.js +97 -0
- package/clis/twitter/retweet.js +62 -0
- package/clis/twitter/schedule.js +96 -0
- package/clis/twitter/scheduled-delete.js +60 -0
- package/clis/twitter/scheduled-list.js +15 -0
- package/clis/twitter/scheduled-utils.js +18 -0
- package/clis/twitter/search.js +12 -0
- package/clis/twitter/shared.js +76 -0
- package/clis/twitter/thread.js +4 -0
- package/clis/twitter/timeline.js +4 -0
- package/clis/twitter/trending.js +18 -0
- package/clis/twitter/tweets.js +12 -0
- package/clis/twitter/unblock.js +45 -0
- package/clis/twitter/unbookmark.js +41 -0
- package/clis/twitter/unfollow.js +45 -0
- package/clis/twitter/unlike.js +48 -0
- package/clis/twitter/unretweet.js +62 -0
- package/clis/twitter/utils.js +55 -0
- package/clis/uisdc/news.js +25 -0
- package/clis/uiverse/_shared.js +257 -0
- package/clis/uiverse/code.js +1 -0
- package/clis/uiverse/preview.js +1 -0
- package/clis/upwork/auth.js +19 -0
- package/clis/upwork/detail.js +22 -0
- package/clis/upwork/feed.js +21 -0
- package/clis/upwork/search.js +21 -0
- package/clis/upwork/utils.js +1 -0
- package/clis/v2ex/auth.js +10 -0
- package/clis/v2ex/daily.js +41 -0
- package/clis/v2ex/hot.js +1 -0
- package/clis/v2ex/latest.js +1 -0
- package/clis/v2ex/me.js +58 -0
- package/clis/v2ex/member.js +1 -0
- package/clis/v2ex/node.js +1 -0
- package/clis/v2ex/nodes.js +1 -0
- package/clis/v2ex/notifications.js +40 -0
- package/clis/v2ex/replies.js +1 -0
- package/clis/v2ex/topic.js +1 -0
- package/clis/v2ex/user.js +1 -0
- package/clis/vk/post.js +1 -0
- package/clis/vk/shared.js +8 -0
- package/clis/vk/whoami.js +1 -0
- package/clis/wanfang/search.js +42 -0
- package/clis/web/read.js +260 -0
- package/clis/wechat-channels/auth.js +31 -0
- package/clis/wechat-channels/publish.js +298 -0
- package/clis/weibo/article.js +1 -0
- package/clis/weibo/auth.js +17 -0
- package/clis/weibo/comments.js +28 -0
- package/clis/weibo/delete.js +84 -0
- package/clis/weibo/favorites.js +27 -0
- package/clis/weibo/feed.js +33 -0
- package/clis/weibo/hot.js +17 -0
- package/clis/weibo/me.js +51 -0
- package/clis/weibo/post.js +46 -0
- package/clis/weibo/publish.js +98 -0
- package/clis/weibo/search.js +47 -0
- package/clis/weibo/user-posts.js +92 -0
- package/clis/weibo/user.js +37 -0
- package/clis/weibo/utils.js +16 -0
- package/clis/weixin/article.js +1 -0
- package/clis/weixin/create-draft.js +152 -0
- package/clis/weixin/download.js +100 -0
- package/clis/weixin/drafts.js +27 -0
- package/clis/weixin/login.js +1 -0
- package/clis/weixin/search.js +44 -0
- package/clis/weixin/stats.js +43 -0
- package/clis/weixin/whoami.js +1 -0
- package/clis/weread/ai-outline.js +2 -0
- package/clis/weread/auth.js +24 -0
- package/clis/weread/book-search.js +2 -0
- package/clis/weread/book.js +3 -0
- package/clis/weread/highlights.js +1 -0
- package/clis/weread/notebooks.js +1 -0
- package/clis/weread/notes.js +1 -0
- package/clis/weread/ranking.js +1 -0
- package/clis/weread/search.js +1 -0
- package/clis/weread/shelf.js +1 -0
- package/clis/weread/utils.js +67 -0
- package/clis/weread-official/book.js +1 -0
- package/clis/weread-official/discover.js +1 -0
- package/clis/weread-official/list-apis.js +1 -0
- package/clis/weread-official/notes.js +1 -0
- package/clis/weread-official/readdata.js +1 -0
- package/clis/weread-official/review.js +1 -0
- package/clis/weread-official/search.js +1 -0
- package/clis/weread-official/shelf.js +1 -0
- package/clis/weread-official/utils.js +1 -0
- package/clis/wikidata/entity.js +1 -0
- package/clis/wikidata/search.js +1 -0
- package/clis/wikidata/utils.js +1 -0
- package/clis/wikipedia/page.js +3 -0
- package/clis/wikipedia/random.js +1 -0
- package/clis/wikipedia/search.js +1 -0
- package/clis/wikipedia/summary.js +1 -0
- package/clis/wikipedia/trending.js +1 -0
- package/clis/wikipedia/utils.js +1 -0
- package/clis/wordpress/login.js +1 -0
- package/clis/wordpress/publish.js +1 -0
- package/clis/wordpress/shared.js +54 -0
- package/clis/wordpress/whoami.js +1 -0
- package/clis/woshipm/article.js +1 -0
- package/clis/woshipm/login.js +1 -0
- package/clis/woshipm/stats.js +52 -0
- package/clis/woshipm/whoami.js +1 -0
- package/clis/wttr/current.js +1 -0
- package/clis/wttr/forecast.js +1 -0
- package/clis/wttr/utils.js +1 -0
- package/clis/xianyu/auth.js +11 -0
- package/clis/xianyu/chat.js +1 -0
- package/clis/xianyu/im.js +240 -0
- package/clis/xianyu/inbox.js +1 -0
- package/clis/xianyu/item.js +97 -0
- package/clis/xianyu/messages.js +1 -0
- package/clis/xianyu/publish.js +245 -0
- package/clis/xianyu/reply.js +1 -0
- package/clis/xianyu/search.js +141 -0
- package/clis/xianyu/utils.js +1 -0
- package/clis/xiaoe/auth.js +10 -0
- package/clis/xiaoe/catalog.js +134 -0
- package/clis/xiaoe/content.js +16 -0
- package/clis/xiaoe/courses.js +43 -0
- package/clis/xiaoe/detail.js +19 -0
- package/clis/xiaoe/play-url.js +97 -0
- package/clis/xiaohongshu/ask.js +130 -0
- package/clis/xiaohongshu/auth.js +13 -0
- package/clis/xiaohongshu/collection-helpers.js +64 -0
- package/clis/xiaohongshu/comments.js +89 -0
- package/clis/xiaohongshu/creator-note-detail.js +80 -0
- package/clis/xiaohongshu/creator-notes-summary.js +1 -0
- package/clis/xiaohongshu/creator-notes.js +107 -0
- package/clis/xiaohongshu/creator-profile.js +13 -0
- package/clis/xiaohongshu/creator-stats.js +13 -0
- package/clis/xiaohongshu/delete-note.js +69 -0
- package/clis/xiaohongshu/download.js +200 -0
- package/clis/xiaohongshu/draft-clear.js +44 -0
- package/clis/xiaohongshu/draft-delete.js +37 -0
- package/clis/xiaohongshu/draft-open.js +1 -0
- package/clis/xiaohongshu/draft-utils.js +36 -0
- package/clis/xiaohongshu/drafts.js +1 -0
- package/clis/xiaohongshu/feed.js +38 -0
- package/clis/xiaohongshu/follow.js +75 -0
- package/clis/xiaohongshu/liked.js +1 -0
- package/clis/xiaohongshu/note-helpers.js +1 -0
- package/clis/xiaohongshu/note.js +32 -0
- package/clis/xiaohongshu/notifications.js +1 -0
- package/clis/xiaohongshu/publish-video.js +87 -0
- package/clis/xiaohongshu/publish.js +637 -0
- package/clis/xiaohongshu/saved.js +1 -0
- package/clis/xiaohongshu/search.js +194 -0
- package/clis/xiaohongshu/unfollow.js +98 -0
- package/clis/xiaohongshu/user-helpers.js +1 -0
- package/clis/xiaohongshu/user.js +30 -0
- package/clis/xiaoyuzhou/auth.js +3 -0
- package/clis/xiaoyuzhou/download.js +1 -0
- package/clis/xiaoyuzhou/episode.js +1 -0
- package/clis/xiaoyuzhou/podcast-episodes.js +1 -0
- package/clis/xiaoyuzhou/podcast.js +1 -0
- package/clis/xiaoyuzhou/transcript.js +1 -0
- package/clis/xiaoyuzhou/utils.js +1 -0
- package/clis/xueqiu/article.js +4 -0
- package/clis/xueqiu/auth.js +27 -0
- package/clis/xueqiu/comments.js +38 -0
- package/clis/xueqiu/danjuan-utils.js +84 -0
- package/clis/xueqiu/earnings-date.js +1 -0
- package/clis/xueqiu/events.js +17 -0
- package/clis/xueqiu/feed.js +1 -0
- package/clis/xueqiu/fund-holdings.js +1 -0
- package/clis/xueqiu/fund-snapshot.js +1 -0
- package/clis/xueqiu/groups.js +1 -0
- package/clis/xueqiu/hashtags.js +26 -0
- package/clis/xueqiu/hot-stock.js +1 -0
- package/clis/xueqiu/hot.js +1 -0
- package/clis/xueqiu/kline.js +1 -0
- package/clis/xueqiu/search.js +1 -0
- package/clis/xueqiu/stock.js +1 -0
- package/clis/xueqiu/stocks.js +13 -0
- package/clis/xueqiu/users.js +12 -0
- package/clis/xueqiu/utils.js +9 -0
- package/clis/xueqiu/watchlist.js +1 -0
- package/clis/yahoo/search.js +21 -0
- package/clis/yahoo-finance/quote.js +50 -0
- package/clis/yollomi/background.js +1 -0
- package/clis/yollomi/edit.js +1 -0
- package/clis/yollomi/face-swap.js +1 -0
- package/clis/yollomi/generate.js +1 -0
- package/clis/yollomi/models.js +1 -0
- package/clis/yollomi/object-remover.js +1 -0
- package/clis/yollomi/remove-bg.js +1 -0
- package/clis/yollomi/restore.js +1 -0
- package/clis/yollomi/try-on.js +1 -0
- package/clis/yollomi/upload.js +17 -0
- package/clis/yollomi/upscale.js +1 -0
- package/clis/yollomi/utils.js +16 -0
- package/clis/yollomi/video.js +1 -0
- package/clis/youdao/note.js +113 -0
- package/clis/youtube/auth.js +20 -0
- package/clis/youtube/channel.js +118 -0
- package/clis/youtube/comments.js +64 -0
- package/clis/youtube/feed.js +89 -0
- package/clis/youtube/history.js +87 -0
- package/clis/youtube/like.js +33 -0
- package/clis/youtube/playlist.js +47 -0
- package/clis/youtube/publish.js +56 -0
- package/clis/youtube/search.js +39 -0
- package/clis/youtube/subscribe.js +42 -0
- package/clis/youtube/subscriptions.js +26 -0
- package/clis/youtube/transcript-group.js +2 -0
- package/clis/youtube/transcript.js +417 -0
- package/clis/youtube/unlike.js +33 -0
- package/clis/youtube/unsubscribe.js +42 -0
- package/clis/youtube/utils.js +34 -0
- package/clis/youtube/video.js +96 -0
- package/clis/youtube/watch-later.js +41 -0
- package/clis/yuanbao/ask.js +145 -0
- package/clis/yuanbao/auth.js +23 -0
- package/clis/yuanbao/detail.js +1 -0
- package/clis/yuanbao/history.js +1 -0
- package/clis/yuanbao/new.js +16 -0
- package/clis/yuanbao/read.js +1 -0
- package/clis/yuanbao/send.js +1 -0
- package/clis/yuanbao/shared.js +127 -0
- package/clis/yuanbao/status.js +1 -0
- package/clis/yuque/article.js +1 -0
- package/clis/yuque/whoami.js +1 -0
- package/clis/zhihu/answer-comments.js +11 -0
- package/clis/zhihu/answer-detail.js +11 -0
- package/clis/zhihu/answer.js +15 -0
- package/clis/zhihu/article-transform.js +1 -0
- package/clis/zhihu/article.js +7 -0
- package/clis/zhihu/auth.js +11 -0
- package/clis/zhihu/collection.js +7 -0
- package/clis/zhihu/collections.js +7 -0
- package/clis/zhihu/comment.js +17 -0
- package/clis/zhihu/download.js +39 -0
- package/clis/zhihu/favorite.js +39 -0
- package/clis/zhihu/follow.js +19 -0
- package/clis/zhihu/followers.js +1 -0
- package/clis/zhihu/following.js +1 -0
- package/clis/zhihu/hot.js +21 -0
- package/clis/zhihu/like.js +16 -0
- package/clis/zhihu/paginate.js +11 -0
- package/clis/zhihu/pin.js +24 -0
- package/clis/zhihu/pins.js +1 -0
- package/clis/zhihu/question.js +7 -0
- package/clis/zhihu/recommend.js +7 -0
- package/clis/zhihu/search.js +11 -0
- package/clis/zhihu/stats.js +41 -0
- package/clis/zhihu/target.js +1 -0
- package/clis/zhihu/text.js +6 -0
- package/clis/zhihu/user-answers.js +1 -0
- package/clis/zhihu/user-arg.js +1 -0
- package/clis/zhihu/user-articles.js +1 -0
- package/clis/zhihu/user.js +11 -0
- package/clis/zhihu/write-shared.js +71 -0
- package/clis/zlibrary/info.js +1 -0
- package/clis/zlibrary/search.js +1 -0
- package/clis/zlibrary/utils.js +48 -0
- package/clis/zsxq/auth.js +33 -0
- package/clis/zsxq/dynamics.js +1 -0
- package/clis/zsxq/groups.js +1 -0
- package/clis/zsxq/search.js +1 -0
- package/clis/zsxq/topic.js +1 -0
- package/clis/zsxq/topics.js +1 -0
- package/clis/zsxq/utils.js +72 -0
- package/dist/src/adapter-shadow.d.ts +11 -0
- package/dist/src/adapter-shadow.js +2 -0
- package/dist/src/adapter-shadow.test.d.ts +1 -0
- package/dist/src/adapter-source.d.ts +11 -0
- package/dist/src/adapter-source.js +1 -0
- package/dist/src/adapter-source.test.d.ts +1 -0
- package/dist/src/browser/analyze.d.ts +118 -0
- package/dist/src/browser/analyze.js +1 -0
- package/dist/src/browser/analyze.test.d.ts +1 -0
- package/dist/src/browser/article-extract.d.ts +57 -0
- package/dist/src/browser/article-extract.e2e.test.d.ts +1 -0
- package/dist/src/browser/article-extract.js +2 -0
- package/dist/src/browser/article-extract.test.d.ts +1 -0
- package/dist/src/browser/ax-snapshot.d.ts +37 -0
- package/dist/src/browser/ax-snapshot.js +2 -0
- package/dist/src/browser/ax-snapshot.test.d.ts +1 -0
- package/dist/src/browser/base-page.d.ts +151 -0
- package/dist/src/browser/base-page.js +225 -0
- package/dist/src/browser/base-page.test.d.ts +1 -0
- package/dist/src/browser/bridge-readiness.d.ts +14 -0
- package/dist/src/browser/bridge-readiness.js +1 -0
- package/dist/src/browser/bridge-readiness.test.d.ts +1 -0
- package/dist/src/browser/bridge.d.ts +26 -0
- package/dist/src/browser/bridge.js +1 -0
- package/dist/src/browser/cdp-click-fixture.test.d.ts +1 -0
- package/dist/src/browser/cdp.d.ts +51 -0
- package/dist/src/browser/cdp.js +1 -0
- package/dist/src/browser/cdp.test.d.ts +1 -0
- package/dist/src/browser/compound.d.ts +59 -0
- package/dist/src/browser/compound.js +82 -0
- package/dist/src/browser/compound.test.d.ts +1 -0
- package/dist/src/browser/config.d.ts +2 -0
- package/dist/src/browser/config.js +1 -0
- package/dist/src/browser/daemon-client.d.ts +79 -0
- package/dist/src/browser/daemon-client.js +1 -0
- package/dist/src/browser/daemon-client.test.d.ts +1 -0
- package/dist/src/browser/daemon-lifecycle.d.ts +37 -0
- package/dist/src/browser/daemon-lifecycle.js +12 -0
- package/dist/src/browser/daemon-transport.d.ts +55 -0
- package/dist/src/browser/daemon-transport.js +1 -0
- package/dist/src/browser/daemon-version.d.ts +4 -0
- package/dist/src/browser/daemon-version.js +2 -0
- package/dist/src/browser/dom-helpers.d.ts +41 -0
- package/dist/src/browser/dom-helpers.js +166 -0
- package/dist/src/browser/dom-helpers.test.d.ts +1 -0
- package/dist/src/browser/dom-snapshot.d.ts +93 -0
- package/dist/src/browser/dom-snapshot.js +809 -0
- package/dist/src/browser/dom-snapshot.test.d.ts +11 -0
- package/dist/src/browser/errors.d.ts +38 -0
- package/dist/src/browser/errors.js +5 -0
- package/dist/src/browser/errors.test.d.ts +1 -0
- package/dist/src/browser/extract.d.ts +69 -0
- package/dist/src/browser/extract.js +42 -0
- package/dist/src/browser/extract.test.d.ts +1 -0
- package/dist/src/browser/find.d.ts +84 -0
- package/dist/src/browser/find.js +328 -0
- package/dist/src/browser/find.test.d.ts +1 -0
- package/dist/src/browser/fingerprint.d.ts +44 -0
- package/dist/src/browser/fingerprint.js +82 -0
- package/dist/src/browser/html-tree.d.ts +75 -0
- package/dist/src/browser/html-tree.js +61 -0
- package/dist/src/browser/html-tree.test.d.ts +1 -0
- package/dist/src/browser/index.d.ts +14 -0
- package/dist/src/browser/index.js +1 -0
- package/dist/src/browser/managed-chrome.d.ts +89 -0
- package/dist/src/browser/managed-chrome.js +1 -0
- package/dist/src/browser/network-cache.d.ts +49 -0
- package/dist/src/browser/network-cache.js +1 -0
- package/dist/src/browser/network-cache.test.d.ts +1 -0
- package/dist/src/browser/network-key.d.ts +22 -0
- package/dist/src/browser/network-key.js +1 -0
- package/dist/src/browser/network-key.test.d.ts +1 -0
- package/dist/src/browser/page.d.ts +83 -0
- package/dist/src/browser/page.js +15 -0
- package/dist/src/browser/page.test.d.ts +1 -0
- package/dist/src/browser/profile.d.ts +96 -0
- package/dist/src/browser/profile.js +2 -0
- package/dist/src/browser/proxy-test.d.ts +28 -0
- package/dist/src/browser/proxy-test.js +12 -0
- package/dist/src/browser/shape-filter.d.ts +52 -0
- package/dist/src/browser/shape-filter.js +1 -0
- package/dist/src/browser/shape-filter.test.d.ts +1 -0
- package/dist/src/browser/shape.d.ts +23 -0
- package/dist/src/browser/shape.js +1 -0
- package/dist/src/browser/shape.test.d.ts +1 -0
- package/dist/src/browser/stealth.d.ts +18 -0
- package/dist/src/browser/stealth.js +391 -0
- package/dist/src/browser/stealth.test.d.ts +1 -0
- package/dist/src/browser/tabs.d.ts +13 -0
- package/dist/src/browser/tabs.js +2 -0
- package/dist/src/browser/target-errors.d.ts +39 -0
- package/dist/src/browser/target-errors.js +1 -0
- package/dist/src/browser/target-errors.test.d.ts +1 -0
- package/dist/src/browser/target-resolver.d.ts +158 -0
- package/dist/src/browser/target-resolver.js +423 -0
- package/dist/src/browser/target-resolver.test.d.ts +1 -0
- package/dist/src/browser/trace.d.ts +21 -0
- package/dist/src/browser/trace.js +2 -0
- package/dist/src/browser/utils.d.ts +20 -0
- package/dist/src/browser/utils.js +1 -0
- package/dist/src/browser/utils.test.d.ts +1 -0
- package/dist/src/browser/verify-fixture.d.ts +65 -0
- package/dist/src/browser/verify-fixture.js +2 -0
- package/dist/src/browser/verify-fixture.test.d.ts +1 -0
- package/dist/src/browser/visual-refs.d.ts +11 -0
- package/dist/src/browser/visual-refs.js +94 -0
- package/dist/src/browser-session-lock.d.ts +13 -0
- package/dist/src/browser-session-lock.js +1 -0
- package/dist/src/browser-session-lock.test.d.ts +1 -0
- package/dist/src/browser.test.d.ts +1 -0
- package/dist/src/build-manifest.d.ts +103 -0
- package/dist/src/build-manifest.js +16 -0
- package/dist/src/build-manifest.test.d.ts +1 -0
- package/dist/src/capabilityRouting.d.ts +19 -0
- package/dist/src/capabilityRouting.js +1 -0
- package/dist/src/capabilityRouting.test.d.ts +1 -0
- package/dist/src/cli-argv-preprocess.d.ts +63 -0
- package/dist/src/cli-argv-preprocess.js +1 -0
- package/dist/src/cli-argv-preprocess.test.d.ts +1 -0
- package/dist/src/cli.d.ts +79 -0
- package/dist/src/cli.js +132 -0
- package/dist/src/cli.test.d.ts +1 -0
- package/dist/src/commanderAdapter.d.ts +21 -0
- package/dist/src/commanderAdapter.js +3 -0
- package/dist/src/commanderAdapter.test.d.ts +1 -0
- package/dist/src/commands/auth.d.ts +40 -0
- package/dist/src/commands/auth.js +2 -0
- package/dist/src/commands/auth.test.d.ts +1 -0
- package/dist/src/commands/daemon.d.ts +25 -0
- package/dist/src/commands/daemon.js +1 -0
- package/dist/src/commands/daemon.test.d.ts +1 -0
- package/dist/src/completion-fast.d.ts +22 -0
- package/dist/src/completion-fast.js +1 -0
- package/dist/src/completion-shared.d.ts +13 -0
- package/dist/src/completion-shared.js +30 -0
- package/dist/src/completion.d.ts +21 -0
- package/dist/src/completion.js +1 -0
- package/dist/src/completion.test.d.ts +1 -0
- package/dist/src/constants.d.ts +22 -0
- package/dist/src/constants.js +1 -0
- package/dist/src/convention-audit.d.ts +50 -0
- package/dist/src/convention-audit.js +2 -0
- package/dist/src/convention-audit.test.d.ts +1 -0
- package/dist/src/daemon-utils.d.ts +18 -0
- package/dist/src/daemon-utils.js +1 -0
- package/dist/src/daemon.d.ts +22 -0
- package/dist/src/daemon.js +1 -0
- package/dist/src/daemon.test.d.ts +1 -0
- package/dist/src/discovery.d.ts +43 -0
- package/dist/src/discovery.js +2 -0
- package/dist/src/doctor.d.ts +38 -0
- package/dist/src/doctor.js +13 -0
- package/dist/src/doctor.test.d.ts +1 -0
- package/dist/src/download/article-download.d.ts +72 -0
- package/dist/src/download/article-download.js +21 -0
- package/dist/src/download/article-download.test.d.ts +1 -0
- package/dist/src/download/index.d.ts +71 -0
- package/dist/src/download/index.js +7 -0
- package/dist/src/download/index.test.d.ts +1 -0
- package/dist/src/download/media-download.d.ts +49 -0
- package/dist/src/download/media-download.js +1 -0
- package/dist/src/download/media-download.test.d.ts +1 -0
- package/dist/src/download/progress.d.ts +36 -0
- package/dist/src/download/progress.js +5 -0
- package/dist/src/download/progress.test.d.ts +1 -0
- package/dist/src/electron-apps.d.ts +31 -0
- package/dist/src/electron-apps.js +1 -0
- package/dist/src/electron-apps.test.d.ts +1 -0
- package/dist/src/engine.test.d.ts +1 -0
- package/dist/src/errors.d.ts +117 -0
- package/dist/src/errors.js +2 -0
- package/dist/src/errors.test.d.ts +1 -0
- package/dist/src/execution.d.ts +24 -0
- package/dist/src/execution.js +2 -0
- package/dist/src/execution.test.d.ts +1 -0
- package/dist/src/extension-manifest-regression.test.d.ts +1 -0
- package/dist/src/external-clis.yaml +109 -0
- package/dist/src/external.d.ts +49 -0
- package/dist/src/external.js +1 -0
- package/dist/src/external.test.d.ts +1 -0
- package/dist/src/help.d.ts +88 -0
- package/dist/src/help.js +8 -0
- package/dist/src/help.test.d.ts +1 -0
- package/dist/src/hooks.d.ts +46 -0
- package/dist/src/hooks.js +1 -0
- package/dist/src/hooks.test.d.ts +4 -0
- package/dist/src/interceptor.d.ts +44 -0
- package/dist/src/interceptor.js +123 -0
- package/dist/src/interceptor.test.d.ts +4 -0
- package/dist/src/launcher.d.ts +41 -0
- package/dist/src/launcher.js +7 -0
- package/dist/src/launcher.test.d.ts +1 -0
- package/dist/src/logger.d.ts +26 -0
- package/dist/src/logger.js +9 -0
- package/dist/src/main.d.ts +5 -0
- package/dist/src/main.js +10 -0
- package/dist/src/manifest-types.d.ts +43 -0
- package/dist/src/manifest-types.js +1 -0
- package/dist/src/node-network.d.ts +10 -0
- package/dist/src/node-network.js +1 -0
- package/dist/src/node-network.test.d.ts +1 -0
- package/dist/src/observation/artifact.d.ts +16 -0
- package/dist/src/observation/artifact.js +8 -0
- package/dist/src/observation/artifact.test.d.ts +1 -0
- package/dist/src/observation/events.d.ts +89 -0
- package/dist/src/observation/events.js +1 -0
- package/dist/src/observation/index.d.ts +7 -0
- package/dist/src/observation/index.js +1 -0
- package/dist/src/observation/manager.d.ts +9 -0
- package/dist/src/observation/manager.js +1 -0
- package/dist/src/observation/manager.test.d.ts +1 -0
- package/dist/src/observation/redaction.d.ts +11 -0
- package/dist/src/observation/redaction.js +2 -0
- package/dist/src/observation/redaction.test.d.ts +1 -0
- package/dist/src/observation/retention.d.ts +32 -0
- package/dist/src/observation/retention.js +1 -0
- package/dist/src/observation/retention.test.d.ts +1 -0
- package/dist/src/observation/ring-buffer.d.ts +22 -0
- package/dist/src/observation/ring-buffer.js +1 -0
- package/dist/src/observation/ring-buffer.test.d.ts +1 -0
- package/dist/src/observation/session.d.ts +25 -0
- package/dist/src/observation/session.js +1 -0
- package/dist/src/output.d.ts +14 -0
- package/dist/src/output.js +2 -0
- package/dist/src/output.test.d.ts +1 -0
- package/dist/src/package-exports.test.d.ts +1 -0
- package/dist/src/package-paths.d.ts +8 -0
- package/dist/src/package-paths.js +1 -0
- package/dist/src/pipeline/executor.d.ts +11 -0
- package/dist/src/pipeline/executor.js +1 -0
- package/dist/src/pipeline/executor.test.d.ts +4 -0
- package/dist/src/pipeline/index.d.ts +5 -0
- package/dist/src/pipeline/index.js +1 -0
- package/dist/src/pipeline/registry.d.ts +28 -0
- package/dist/src/pipeline/registry.js +1 -0
- package/dist/src/pipeline/steps/browser.d.ts +13 -0
- package/dist/src/pipeline/steps/browser.js +1 -0
- package/dist/src/pipeline/steps/download.d.ts +18 -0
- package/dist/src/pipeline/steps/download.js +1 -0
- package/dist/src/pipeline/steps/download.test.d.ts +1 -0
- package/dist/src/pipeline/steps/fetch.d.ts +5 -0
- package/dist/src/pipeline/steps/fetch.js +31 -0
- package/dist/src/pipeline/steps/fetch.test.d.ts +1 -0
- package/dist/src/pipeline/steps/intercept.d.ts +5 -0
- package/dist/src/pipeline/steps/intercept.js +1 -0
- package/dist/src/pipeline/steps/tap.d.ts +12 -0
- package/dist/src/pipeline/steps/tap.js +53 -0
- package/dist/src/pipeline/steps/transform.d.ts +9 -0
- package/dist/src/pipeline/steps/transform.js +1 -0
- package/dist/src/pipeline/template.d.ts +17 -0
- package/dist/src/pipeline/template.js +1 -0
- package/dist/src/pipeline/template.test.d.ts +4 -0
- package/dist/src/pipeline/transform.test.d.ts +4 -0
- package/dist/src/plugin-manifest.d.ts +70 -0
- package/dist/src/plugin-manifest.js +1 -0
- package/dist/src/plugin-manifest.test.d.ts +4 -0
- package/dist/src/plugin-scaffold.d.ts +28 -0
- package/dist/src/plugin-scaffold.js +75 -0
- package/dist/src/plugin-scaffold.test.d.ts +4 -0
- package/dist/src/plugin.d.ts +145 -0
- package/dist/src/plugin.js +20 -0
- package/dist/src/plugin.test.d.ts +4 -0
- package/dist/src/rate-limit.d.ts +15 -0
- package/dist/src/rate-limit.js +2 -0
- package/dist/src/rate-limit.test.d.ts +1 -0
- package/dist/src/registry-api.d.ts +13 -0
- package/dist/src/registry-api.js +1 -0
- package/dist/src/registry.d.ts +130 -0
- package/dist/src/registry.js +1 -0
- package/dist/src/registry.test.d.ts +4 -0
- package/dist/src/runtime-detect.d.ts +31 -0
- package/dist/src/runtime-detect.js +1 -0
- package/dist/src/runtime-detect.test.d.ts +1 -0
- package/dist/src/runtime.d.ts +57 -0
- package/dist/src/runtime.js +1 -0
- package/dist/src/scripts/framework.d.ts +7 -0
- package/dist/src/scripts/framework.js +1 -0
- package/dist/src/scripts/interact.d.ts +4 -0
- package/dist/src/scripts/interact.js +1 -0
- package/dist/src/scripts/store.d.ts +13 -0
- package/dist/src/scripts/store.js +1 -0
- package/dist/src/serialization.d.ts +42 -0
- package/dist/src/serialization.js +4 -0
- package/dist/src/serialization.test.d.ts +1 -0
- package/dist/src/skills.d.ts +14 -0
- package/dist/src/skills.js +6 -0
- package/dist/src/skills.test.d.ts +1 -0
- package/dist/src/snapshotFormatter.d.ts +11 -0
- package/dist/src/snapshotFormatter.js +3 -0
- package/dist/src/snapshotFormatter.test.d.ts +7 -0
- package/dist/src/tui.d.ts +28 -0
- package/dist/src/tui.js +16 -0
- package/dist/src/tui.test.d.ts +1 -0
- package/dist/src/types.d.ts +236 -0
- package/dist/src/types.js +1 -0
- package/dist/src/utils.d.ts +57 -0
- package/dist/src/utils.js +38 -0
- package/dist/src/utils.test.d.ts +1 -0
- package/dist/src/validate.d.ts +21 -0
- package/dist/src/validate.js +3 -0
- package/dist/src/validate.test.d.ts +9 -0
- package/dist/src/verify.d.ts +27 -0
- package/dist/src/verify.js +2 -0
- package/dist/src/verify.test.d.ts +8 -0
- package/dist/src/version.d.ts +4 -0
- package/dist/src/version.js +1 -0
- package/dist/src/weixin-download.test.d.ts +1 -0
- package/docs/guide/browser-bridge.md +94 -0
- package/docs/guide/electron-app-cli.md +199 -0
- package/docs/guide/exit-codes.md +24 -0
- package/docs/guide/extending-opencli.md +134 -0
- package/docs/guide/getting-started.md +81 -0
- package/docs/guide/installation.md +52 -0
- package/docs/guide/plugins.md +226 -0
- package/docs/guide/remote-orchestration.md +116 -0
- package/docs/guide/troubleshooting.md +69 -0
- package/package.json +116 -0
- package/scripts/check-doc-coverage.sh +81 -0
- package/scripts/check-listing-id-pairing.mjs +193 -0
- package/scripts/check-silent-column-drop.mjs +105 -0
- package/scripts/check-typed-error-lint.mjs +118 -0
- package/scripts/clean-dist.cjs +13 -0
- package/scripts/copy-yaml.cjs +12 -0
- package/scripts/fetch-adapters.js +293 -0
- package/scripts/minify-release.mjs +115 -0
- package/scripts/postinstall.js +174 -0
- package/scripts/silent-column-drop-baseline.json +910 -0
- package/scripts/typed-error-lint-baseline.json +1098 -0
- package/skills/opencli-adapter-author/SKILL.md +256 -0
- package/skills/opencli-adapter-author/references/adapter-template.md +471 -0
- package/skills/opencli-adapter-author/references/api-discovery.md +295 -0
- package/skills/opencli-adapter-author/references/coverage-matrix.md +81 -0
- package/skills/opencli-adapter-author/references/field-conventions.md +172 -0
- package/skills/opencli-adapter-author/references/field-decode-playbook.md +181 -0
- package/skills/opencli-adapter-author/references/jsdom-fixture-pattern.md +196 -0
- package/skills/opencli-adapter-author/references/output-design.md +149 -0
- package/skills/opencli-adapter-author/references/site-memory/bilibili.md +70 -0
- package/skills/opencli-adapter-author/references/site-memory/eastmoney.md +70 -0
- package/skills/opencli-adapter-author/references/site-memory/tonghuashun.md +51 -0
- package/skills/opencli-adapter-author/references/site-memory/xueqiu.md +58 -0
- package/skills/opencli-adapter-author/references/site-memory.md +231 -0
- package/skills/opencli-adapter-author/references/site-recon.md +134 -0
- package/skills/opencli-adapter-author/references/strategy-selection.md +169 -0
- package/skills/opencli-adapter-author/references/success-rate-pitfalls.md +162 -0
- package/skills/opencli-adapter-author/references/typed-errors.md +234 -0
- package/skills/opencli-autofix/SKILL.md +297 -0
- package/skills/opencli-browser/SKILL.md +468 -0
- package/skills/opencli-browser-sitemap/SKILL.md +96 -0
- package/skills/opencli-sitemap-author/SKILL.md +161 -0
- package/skills/opencli-sitemap-author/references/sitemap-schema.md +660 -0
- package/skills/opencli-usage/SKILL.md +168 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import{cli as Q,Strategy as j}from"@jackwener/opencli/registry";import{downloadArticle as E}from"@jackwener/opencli/download/article-download";const L=[['"','"'],["'","'"],["“","”"],["‘","’"],["「","」"],["『","』"],["„","‟"],["‹","›"],["«","»"]],G=new Set(L.map(([K])=>K).concat("<")),N=new Set(L.map(([,K])=>K).concat(">"));function U(K){let q=K;for(let F=0;F<4;F+=1){const Y=q;for(const[X,Z]of L)if(q.length>=2&&q.startsWith(X)&&q.endsWith(Z)){q=q.slice(X.length,q.length-Z.length).trim();break}while(q&&G.has(q[0]))q=q.slice(1).trimStart();while(q&&N.has(q[q.length-1]))q=q.slice(0,-1).trimEnd();if(q===Y)break}return q}export function normalizeWechatUrl(K){let q=(K||"").trim();if(!q)return q;q=U(q);q=q.replace(/\\+([:/&?=#%])/g,"$1");q=q.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"');if(q.startsWith("mp.weixin.qq.com/")||q.startsWith("//mp.weixin.qq.com/"))q="https://"+q.replace(/^\/+/,"");try{const F=new URL(q);if(["http:","https:"].includes(F.protocol)&&F.hostname.toLowerCase()==="mp.weixin.qq.com"){F.protocol="https:";q=F.toString()}}catch{}return q}export function formatWechatTimestamp(K){const q=Number.parseInt(K,10);if(!Number.isFinite(q)||q<=0)return"";const F=K.length===13?q:q*1000,Y=new Date(F),X=($)=>String($).padStart(2,"0"),Z=new Date(Y.getTime()+28800000);return`${Z.getUTCFullYear()}-${X(Z.getUTCMonth()+1)}-${X(Z.getUTCDate())} ${X(Z.getUTCHours())}:${X(Z.getUTCMinutes())}:${X(Z.getUTCSeconds())}`}export function extractWechatCreateTimeValue(K){const q=K.match(/create_time\s*:\s*JsDecode\('([^']+)'\)(?=[\s,;}]|$)/);if(q)return q[1];const F=K.match(/create_time\s*[:=]\s*(?:"([^"]+)"|'([^']+)'|([0-9A-Za-z]+))(?=[\s,;}]|$)/);if(!F)return"";return F[1]||F[2]||F[3]||""}export function extractWechatPublishTime(K,q){const F=(K||"").trim();if(F)return F;const Y=extractWechatCreateTimeValue(q);if(!/^\d{10}$|^\d{13}$/.test(Y))return"";return formatWechatTimestamp(Y)}export function detectWechatAccessIssue(K,q){const F=(K||"").replace(/\s+/g," ").trim();if(/环境异常/.test(F)&&/(完成验证后即可继续访问|去验证)/.test(F))return"environment verification required";if(/secitptpage\/verify\.html/.test(q)||/id=["']js_verify["']/.test(q))return"environment verification required";return""}export function pickFirstWechatMetaText(...K){for(const q of K){const F=(q||"").replace(/\s+/g," ").trim();if(F&&F!=="Name cleared")return F}return""}export function buildExtractWechatPublishTimeJs(){return`(${function K(q,F){function Y(H){const B=Number.parseInt(H,10);if(!Number.isFinite(B)||B<=0)return"";const v=H.length===13?B:B*1000,f=new Date(v),J=(O)=>String(O).padStart(2,"0"),y=new Date(f.getTime()+28800000);return`${y.getUTCFullYear()}-${J(y.getUTCMonth()+1)}-${J(y.getUTCDate())} ${J(y.getUTCHours())}:${J(y.getUTCMinutes())}:${J(y.getUTCSeconds())}`}function X(H){const B=H.match(/create_time\s*:\s*JsDecode\('([^']+)'\)(?=[\s,;}]|$)/);if(B)return B[1];const v=H.match(/create_time\s*[:=]\s*(?:"([^"]+)"|'([^']+)'|([0-9A-Za-z]+))(?=[\s,;}]|$)/);if(!v)return"";return v[1]||v[2]||v[3]||""}const Z=(q||"").trim();if(Z)return Z;const $=X(F);if(!/^\d{10}$|^\d{13}$/.test($))return"";return Y($)}.toString()})`}export function buildDetectWechatAccessIssueJs(){return`(${function K(q,F){const Y=(q||"").replace(/\s+/g," ").trim();if(/环境异常/.test(Y)&&/(完成验证后即可继续访问|去验证)/.test(Y))return"environment verification required";if(/secitptpage\/verify\.html/.test(F)||/id=["']js_verify["']/.test(F))return"environment verification required";return""}.toString()})`}Q({site:"weixin",name:"download",access:"read",description:"下载微信公众号文章为 Markdown 格式",domain:"mp.weixin.qq.com",strategy:j.COOKIE,args:[{name:"url",required:!0,help:"WeChat article URL (mp.weixin.qq.com/s/xxx)"},{name:"output",default:"./weixin-articles",help:"Output directory"},{name:"download-images",type:"boolean",default:!0,help:"Download images locally"}],columns:["title","author","publish_time","status","size","saved"],func:async(K,q)=>{const F=q.url,Y=normalizeWechatUrl(F);if(!Y.startsWith("https://mp.weixin.qq.com/"))return[{title:"Error",author:"-",publish_time:"-",status:"invalid URL",size:"-",saved:"-"}];await K.goto(Y);await K.wait(5);const X=await K.evaluate(`
|
|
2
|
+
(() => {
|
|
3
|
+
const result = {
|
|
4
|
+
title: '',
|
|
5
|
+
author: '',
|
|
6
|
+
publishTime: '',
|
|
7
|
+
errorHint: '',
|
|
8
|
+
contentHtml: '',
|
|
9
|
+
codeBlocks: [],
|
|
10
|
+
imageUrls: []
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const pickFirstText = (...selectors) => {
|
|
14
|
+
for (const selector of selectors) {
|
|
15
|
+
const text = document.querySelector(selector)?.textContent?.replace(/\\s+/g, ' ').trim() || '';
|
|
16
|
+
if (text && text !== 'Name cleared') return text;
|
|
17
|
+
}
|
|
18
|
+
return '';
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// WeChat has multiple article templates. Newer pages use #js_text_title.
|
|
22
|
+
result.title = pickFirstText(
|
|
23
|
+
'#activity-name',
|
|
24
|
+
'#js_text_title',
|
|
25
|
+
'.rich_media_title',
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
result.author = pickFirstText(
|
|
29
|
+
'#js_name',
|
|
30
|
+
'.wx_follow_nickname',
|
|
31
|
+
'#profileBt .profile_nickname',
|
|
32
|
+
'.rich_media_meta.rich_media_meta_nickname',
|
|
33
|
+
'.rich_media_meta_nickname',
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// Publish time: prefer the rendered DOM text, then fall back to numeric create_time values.
|
|
37
|
+
const publishTimeEl = document.querySelector('#publish_time');
|
|
38
|
+
const extractWechatPublishTime = ${buildExtractWechatPublishTimeJs()};
|
|
39
|
+
result.publishTime = extractWechatPublishTime(
|
|
40
|
+
publishTimeEl ? publishTimeEl.textContent : '',
|
|
41
|
+
document.documentElement.innerHTML,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const detectWechatAccessIssue = ${buildDetectWechatAccessIssueJs()};
|
|
45
|
+
result.errorHint = detectWechatAccessIssue(
|
|
46
|
+
document.body ? document.body.innerText : '',
|
|
47
|
+
document.documentElement.innerHTML,
|
|
48
|
+
);
|
|
49
|
+
if (result.errorHint) return result;
|
|
50
|
+
|
|
51
|
+
// Content processing
|
|
52
|
+
const contentEl = document.querySelector('#js_content');
|
|
53
|
+
if (!contentEl) return result;
|
|
54
|
+
|
|
55
|
+
// Fix lazy-loaded images: data-src -> src
|
|
56
|
+
contentEl.querySelectorAll('img').forEach(img => {
|
|
57
|
+
const dataSrc = img.getAttribute('data-src');
|
|
58
|
+
if (dataSrc) img.setAttribute('src', dataSrc);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Extract code blocks with placeholder replacement
|
|
62
|
+
const codeBlocks = [];
|
|
63
|
+
contentEl.querySelectorAll('.code-snippet__fix').forEach(el => {
|
|
64
|
+
el.querySelectorAll('.code-snippet__line-index').forEach(li => li.remove());
|
|
65
|
+
const pre = el.querySelector('pre[data-lang]');
|
|
66
|
+
const lang = pre ? (pre.getAttribute('data-lang') || '') : '';
|
|
67
|
+
const lines = [];
|
|
68
|
+
el.querySelectorAll('code').forEach(codeTag => {
|
|
69
|
+
const text = codeTag.textContent;
|
|
70
|
+
if (/^[ce]?ounter\\(line/.test(text)) return;
|
|
71
|
+
lines.push(text);
|
|
72
|
+
});
|
|
73
|
+
if (lines.length === 0) lines.push(el.textContent);
|
|
74
|
+
const placeholder = 'CODEBLOCK-PLACEHOLDER-' + codeBlocks.length;
|
|
75
|
+
codeBlocks.push({ lang, code: lines.join('\\n') });
|
|
76
|
+
const p = document.createElement('p');
|
|
77
|
+
p.textContent = placeholder;
|
|
78
|
+
el.replaceWith(p);
|
|
79
|
+
});
|
|
80
|
+
result.codeBlocks = codeBlocks;
|
|
81
|
+
|
|
82
|
+
// Remove noise elements
|
|
83
|
+
['script', 'style', '.qr_code_pc', '.reward_area'].forEach(sel => {
|
|
84
|
+
contentEl.querySelectorAll(sel).forEach(tag => tag.remove());
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Collect image URLs (deduplicated)
|
|
88
|
+
const seen = new Set();
|
|
89
|
+
contentEl.querySelectorAll('img[src]').forEach(img => {
|
|
90
|
+
const src = img.getAttribute('src');
|
|
91
|
+
if (src && !seen.has(src)) {
|
|
92
|
+
seen.add(src);
|
|
93
|
+
result.imageUrls.push(src);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
result.contentHtml = contentEl.innerHTML;
|
|
98
|
+
return result;
|
|
99
|
+
})()
|
|
100
|
+
`);if(X?.errorHint==="environment verification required")return[{title:"Error",author:"-",publish_time:"-",status:"failed — verification required in WeChat browser page",size:"-",saved:"-"}];return E({title:X?.title||"",author:X?.author,publishTime:X?.publishTime,sourceUrl:Y,contentHtml:X?.contentHtml||"",codeBlocks:X?.codeBlocks,imageUrls:X?.imageUrls},{output:q.output,downloadImages:q["download-images"],imageHeaders:{Referer:"https://mp.weixin.qq.com/"},frontmatterLabels:{author:"公众号"},detectImageExt:(Z)=>{const $=Z.match(/wx_fmt=(\w+)/)||Z.match(/\.(\w{3,4})(?:\?|$)/);return $?$[1]:"png"}})}});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import{AuthRequiredError as a,EmptyResultError as s}from"@jackwener/opencli/errors";import{cli as n,Strategy as o}from"@jackwener/opencli/registry";const l="mp.weixin.qq.com";export const draftsCommand=n({site:"weixin",name:"drafts",access:"read",description:"列出微信公众号草稿箱",domain:l,strategy:o.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"limit",type:"int",default:10,help:"最多显示条数"},{name:"timeout",type:"int",required:!1,default:60,help:"Max seconds for the overall command (default: 60)"}],columns:["Index","Title","Time"],func:async(t,i)=>{await t.goto("https://mp.weixin.qq.com/");await t.wait(3);const r=await t.evaluate("(window.location.href.match(/token=(\\d+)/)||[])[1]");if(!r)throw new a(l,"微信公众号草稿箱需要已登录的 mp.weixin.qq.com 会话");await t.goto(`https://mp.weixin.qq.com/cgi-bin/appmsg?begin=0&count=${i.limit}&type=77&action=list_card&token=${r}&lang=zh_CN`);await t.wait(4);const e=await t.evaluate(`(() => {
|
|
2
|
+
var results = [];
|
|
3
|
+
var idx = 0;
|
|
4
|
+
|
|
5
|
+
var cards = document.querySelectorAll('.weui-desktop-card');
|
|
6
|
+
for (var i = 0; i < cards.length; i++) {
|
|
7
|
+
if (cards[i].className.includes('card_new')) continue;
|
|
8
|
+
var titleEl = cards[i].querySelector('[class*=title]');
|
|
9
|
+
var timeEl = cards[i].querySelector('[class*=tips]');
|
|
10
|
+
var title = titleEl ? titleEl.textContent.trim() : '';
|
|
11
|
+
var time = timeEl ? timeEl.textContent.trim().replace(/\\s+/g, ' ') : '';
|
|
12
|
+
if (title) results.push({ Index: ++idx, Title: title, Time: time });
|
|
13
|
+
}
|
|
14
|
+
if (results.length > 0) return results;
|
|
15
|
+
|
|
16
|
+
var rows = document.querySelectorAll('tr, [class*=appmsg_item], [class*=list_item]');
|
|
17
|
+
rows.forEach(function(row) {
|
|
18
|
+
var titleEl = row.querySelector('[class*=title] a, [class*=title], h4');
|
|
19
|
+
var timeEl = row.querySelector('[class*=time], td:nth-child(2)');
|
|
20
|
+
var title = titleEl ? titleEl.textContent.trim() : '';
|
|
21
|
+
var time = timeEl ? timeEl.textContent.trim() : '';
|
|
22
|
+
if (title && title !== '内容' && title.length < 80) {
|
|
23
|
+
results.push({ Index: ++idx, Title: title, Time: time });
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return results;
|
|
27
|
+
})()`);if(!e||e.length===0)throw new s("weixin drafts","No structured drafts found in the current Weixin Official Account backend");return e.slice(0,i.limit)}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{registerArticleLogin as k}from"../_shared/article/login.js";import{weixinAuthProfile as b}from"./article.js";k({site:"weixin",domain:"mp.weixin.qq.com",profile:{home:b.home,checkAuth:b.checkAuth},loginDescription:"打开微信公众平台首页并等待浏览器完成扫码登录(供桌面客户端引导登录)。"});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import{ArgumentError as $,CommandExecutionError as W,EmptyResultError as L}from"@jackwener/opencli/errors";import{cli as R,Strategy as T}from"@jackwener/opencli/registry";const b="weixin.sogou.com",q=1,z=10,G=10;function M(j,B,H,J){if(j===void 0||j===null)return H;const X=String(j).trim();if(!/^\d+$/.test(X))throw new $(`weixin search --${B} must be a positive integer`,`Pass --${B} as a whole number${J?` from 1 to ${J}`:" greater than 0"}.`);const Q=Number(X);if(!Number.isSafeInteger(Q)||Q<1||J&&Q>J)throw new $(`weixin search --${B} is out of range`,`Pass --${B} as a whole number${J?` from 1 to ${J}`:" greater than 0"}.`);return Q}function f(j){return M(j,"page",q)}function D(j){return M(j,"limit",z,G)}function F(j,B){const H=new URL("https://weixin.sogou.com/weixin");H.searchParams.set("query",j);H.searchParams.set("type","2");H.searchParams.set("page",String(B));H.searchParams.set("ie","utf8");return H.toString()}function _(){return String.raw`(() => {
|
|
2
|
+
const clean = (value) => {
|
|
3
|
+
return (value || '')
|
|
4
|
+
.replace(/\s+/g, ' ')
|
|
5
|
+
.replace(/<!--red_beg-->|<!--red_end-->/g, '')
|
|
6
|
+
.replace(/document\.write\(timeConvert\('\d+'\)\)/g, '')
|
|
7
|
+
.trim();
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const absolutize = (href) => {
|
|
11
|
+
if (!href) return '';
|
|
12
|
+
try {
|
|
13
|
+
return new URL(href, window.location.origin).toString();
|
|
14
|
+
} catch {
|
|
15
|
+
return href;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const bodyText = clean(document.body && document.body.innerText);
|
|
20
|
+
const blocked = /验证码|安全验证|异常访问|访问过于频繁|请输入验证码/.test(bodyText);
|
|
21
|
+
const empty = /没有找到相关的微信文章|未找到相关|暂无相关|没有找到/.test(bodyText)
|
|
22
|
+
|| Boolean(document.querySelector('.no-result, .no_result, .s-noresult'));
|
|
23
|
+
const cards = Array.from(document.querySelectorAll('.news-list li'));
|
|
24
|
+
const extracted = cards.map((item) => {
|
|
25
|
+
const linkEl = item.querySelector('h3 a[href]');
|
|
26
|
+
const summaryEl = item.querySelector('p.txt-info');
|
|
27
|
+
const timeEl = item.querySelector('.s-p .s2');
|
|
28
|
+
return {
|
|
29
|
+
title: clean(linkEl && linkEl.textContent),
|
|
30
|
+
url: absolutize(linkEl && linkEl.getAttribute('href')),
|
|
31
|
+
summary: clean(summaryEl && summaryEl.textContent),
|
|
32
|
+
publish_time: clean(timeEl && timeEl.textContent),
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
const rows = extracted.filter((row) => row.title && row.url);
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
blocked,
|
|
39
|
+
empty,
|
|
40
|
+
cardCount: cards.length,
|
|
41
|
+
invalidCount: extracted.length - rows.length,
|
|
42
|
+
rows,
|
|
43
|
+
};
|
|
44
|
+
})()`}R({site:"weixin",name:"search",access:"read",description:"使用搜狗微信搜索公众号文章;如需导出正文 Markdown,请使用 weixin download 处理公众号文章链接",domain:b,strategy:T.PUBLIC,browser:!0,args:[{name:"query",positional:!0,required:!0,help:"搜索关键词;如需正文 Markdown,请使用 weixin download 处理公众号文章链接"},{name:"page",type:"int",default:1,help:"结果页码,从 1 开始"},{name:"limit",type:"int",default:10,help:"返回条数,最大 10"}],columns:["rank","page","title","url","summary","publish_time"],func:async(j,B)=>{const H=String(B.query??"").trim();if(!H)throw new $("A search query is required.","Pass a non-empty keyword to search Weixin articles via Sogou.");const J=f(B.page),X=D(B.limit),Q=F(H,J);let K;try{await j.goto(Q);await j.wait(2);K=await j.evaluate(_())}catch(O){const Z=O instanceof Error?O.message:String(O);throw new W("weixin search failed while loading Sogou results",Z)}if(!K||typeof K!=="object"||!Array.isArray(K.rows))throw new W("weixin search returned an unreadable browser payload","Sogou Weixin may have changed its result page structure.");if(K.blocked)throw new W("Sogou Weixin blocked this search request","Open weixin.sogou.com in Chrome and complete any verification before retrying.");if(K.invalidCount>0)throw new W("Sogou Weixin returned article cards without required title or URL","The result page structure may have changed; refusing to return a partial result set.");const Y=K.rows;if(Y.length===0&&K.empty)throw new L("weixin search","Try a different keyword or a different page number.");if(Y.length===0)throw new W("weixin search did not expose article result cards","Sogou Weixin may have changed its selectors or returned a transient shell page.");return Y.slice(0,X).map((O,Z)=>({rank:(J-1)*10+Z+1,page:J,title:O.title,url:O.url,summary:O.summary,publish_time:O.publish_time}))}});export const __test__={MAX_LIMIT:G,normalizePage:f,normalizeLimit:D,buildSearchUrl:F,buildExtractSearchResultsEvaluate:_};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import{AuthRequiredError as G,EmptyResultError as O}from"@jackwener/opencli/errors";import{cli as W,Strategy as X}from"@jackwener/opencli/registry";const q="mp.weixin.qq.com",L=10;function Z(z){if(!z)return"";const C=new Date(z*1000),F=(H)=>String(H).padStart(2,"0");return`${C.getFullYear()}-${F(C.getMonth()+1)}-${F(C.getDate())} ${F(C.getHours())}:${F(C.getMinutes())}`}function f(z){if(z===1)return"发表";if(z===2)return"群发";return z===void 0||z===null?"":`类型${z}`}async function M(z){await z.goto("https://mp.weixin.qq.com/");await z.wait(3);const C=await z.evaluate("(window.location.href.match(/token=(\\d+)/)||[])[1]");if(!C)throw new G(q,"未检测到登录态:请先在 Chrome 登录 mp.weixin.qq.com(微信公众平台)再重试");return C}async function R(z,C,F){await z.goto(`https://mp.weixin.qq.com/cgi-bin/appmsgpublish?sub=list&begin=${F}&count=${L}&token=${C}&lang=zh_CN`);await z.wait(4);const H=await z.evaluate(`(() => {
|
|
2
|
+
const d = window.wx && window.wx.cgiData;
|
|
3
|
+
if (!d || !Array.isArray(d.publish_list)) return JSON.stringify({ error: 'no_cgi_data' });
|
|
4
|
+
const items = [];
|
|
5
|
+
for (const entry of d.publish_list) {
|
|
6
|
+
// 页面 JS 已把 publish_info 字符串解析并平铺到 entry 上
|
|
7
|
+
const msgs = Array.isArray(entry.appmsg_info) ? entry.appmsg_info : [];
|
|
8
|
+
for (const am of msgs) {
|
|
9
|
+
if (!am || am.is_deleted) continue;
|
|
10
|
+
items.push({
|
|
11
|
+
msgid: entry.msgid || am.appmsgid || 0,
|
|
12
|
+
itemidx: am.itemidx || 1,
|
|
13
|
+
publish_type: entry.publish_type,
|
|
14
|
+
title: am.title || '',
|
|
15
|
+
url: am.content_url || '',
|
|
16
|
+
digest: am.digest || '',
|
|
17
|
+
send_time: (am.line_info && am.line_info.send_time) || (entry.publish_info && entry.publish_info.create_time) || 0,
|
|
18
|
+
read_num: am.read_num ?? 0,
|
|
19
|
+
old_like_num: am.old_like_num ?? 0, // 点赞(赞)
|
|
20
|
+
like_num: am.like_num ?? 0, // 在看
|
|
21
|
+
share_num: am.share_num ?? 0, // 分享
|
|
22
|
+
comment_num: am.comment_num ?? 0, // 留言
|
|
23
|
+
reprint_num: am.reprint_num ?? 0, // 转载
|
|
24
|
+
moment_like_num: am.moment_like_num ?? 0, // 朋友圈点赞
|
|
25
|
+
copyright_type: am.copyright_type ?? 0, // 1=原创
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return JSON.stringify({ total: d.total_count ?? 0, items });
|
|
30
|
+
})()`),J=typeof H==="string"?JSON.parse(H):H;if(!J||J.error)throw Error("发表记录页未读到数据(window.wx.cgiData.publish_list 缺失):页面可能改版或登录态失效,请重新登录 mp.weixin.qq.com 后重试");return J}async function T(z,C){const F=new Map;try{await z.goto(`https://mp.weixin.qq.com/misc/appmsganalysis?action=report&type=daily_v2&token=${C}&lang=zh_CN`);await z.wait(5);const H=await z.evaluate(`(async () => {
|
|
31
|
+
// 重放页面自己发出的 get_article_list 请求(含 fingerprint),不自行构造参数
|
|
32
|
+
const listUrl = performance.getEntriesByType('resource').map(r => r.name)
|
|
33
|
+
.find(u => u.includes('action=get_article_list'));
|
|
34
|
+
if (!listUrl) return JSON.stringify({ list: [] });
|
|
35
|
+
const resp = await fetch(listUrl, { credentials: 'include' });
|
|
36
|
+
if (!resp.ok) return JSON.stringify({ list: [] });
|
|
37
|
+
const json = await resp.json();
|
|
38
|
+
const list = (json && json.article_list || []).map(a => ({
|
|
39
|
+
msg_id: a.msg_id, item_idx: a.item_idx,
|
|
40
|
+
total_read_uv: a.total_read_uv, read_uv_ratio: a.read_uv_ratio,
|
|
41
|
+
}));
|
|
42
|
+
return JSON.stringify({ list });
|
|
43
|
+
})()`),J=typeof H==="string"?JSON.parse(H):H;for(const K of J&&J.list||[])if(K&&K.msg_id)F.set(`${K.msg_id}_${K.item_idx||1}`,K)}catch{}return F}W({site:"weixin",name:"stats",access:"read",description:"微信公众号内容数据(每篇阅读/赞/在看/分享/留言/转载等全量运营指标)",domain:q,strategy:X.COOKIE,browser:!0,navigateBefore:!1,args:[{name:"limit",type:"int",default:20,help:"返回条数"}],columns:["id","type","title","url","published_at","views","likes","looking","comments","collects","shares","reprints","extra"],func:async(z,C)=>{const F=C.limit||20,H=await M(z),J=[];let K=1/0;for(let B=0;B<K&&J.length<F;B+=L){const Q=await R(z,H,B);K=Q.total;if(!Q.items.length)break;J.push(...Q.items)}if(J.length===0)throw new O("weixin stats","该公众号暂无已发表/已群发内容(发表记录为空)——先发布内容后再查数据");const U=J.slice(0,F),j=await T(z,H);return U.map((B)=>{const Q=`${B.msgid}_${B.itemidx}`,Y=j.get(Q),V={摘要:B.digest||void 0,原创:B.copyright_type===1?!0:void 0,朋友圈点赞:B.moment_like_num||void 0,近30天阅读人数:Y?Y.total_read_uv:void 0,近30天阅读人数占比:Y?Y.read_uv_ratio:void 0};for(const $ of Object.keys(V))if(V[$]===void 0)delete V[$];return{id:Q,type:f(B.publish_type),title:B.title,url:B.url,published_at:Z(B.send_time),views:B.read_num,likes:B.old_like_num,looking:B.like_num,comments:B.comment_num,collects:"",shares:B.share_num,reprints:B.reprint_num,extra:Object.keys(V).length?JSON.stringify(V):""}})}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as B,Strategy as D}from"@jackwener/opencli/registry";import{checkLogin as E,cookieQuickCheck as F}from"../_shared/article/auth.js";import{weixinAuthProfile as G}from"./article.js";B({site:"weixin",name:"whoami",access:"read",description:"查询当前登录的微信公众号账户信息。",domain:"mp.weixin.qq.com",strategy:D.COOKIE,browser:!0,columns:["logged_in","user_id","username"],authStatus:{quickCheck:F("https://mp.weixin.qq.com",["slave_sid","slave_user"])},func:async(z)=>{const b=await E(z,G);return[{logged_in:b.isAuthenticated,user_id:b.userId||"",username:b.username||""}]}});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{cli as O,Strategy as N}from"@jackwener/opencli/registry";import{CliError as n}from"@jackwener/opencli/errors";import{WEREAD_UA as E,WEREAD_WEB_ORIGIN as k,WEREAD_DOMAIN as C}from"./utils.js";const I=`${k}/web`;function T(o){return o.map((t)=>`${t.name}=${t.value}`).join("; ")}async function D(o,t,s){const a=`${I}${t}`,[A,l]=await Promise.all([o.getCookies({url:a}),o.getCookies({domain:C})]),d=new Map;for(const i of l)d.set(i.name,i);for(const i of A)d.set(i.name,i);const p=T(Array.from(d.values())),f=await fetch(a,{method:"POST",headers:{"User-Agent":E,"Content-Type":"application/json",Origin:k,Referer:`${k}/`,...p?{Cookie:p}:{}},body:JSON.stringify(s)});if(f.status===401)throw new n("AUTH_REQUIRED","Not logged in to WeRead","Please log in to weread.qq.com in Chrome first");let c;try{c=await f.json()}catch{throw new n("PARSE_ERROR",`Invalid JSON response for ${t}`,"WeRead may have returned an HTML error page")}if(c?.errcode===-2010||c?.errcode===-2012)throw new n("AUTH_REQUIRED","Not logged in to WeRead","Please log in to weread.qq.com in Chrome first");if(!f.ok)throw new n("FETCH_ERROR",`HTTP ${f.status} for ${t}`,"WeRead API may be temporarily unavailable");return c}async function v(o,t){const s=`${I}${o}`,a=await fetch(s,{method:"POST",headers:{"User-Agent":E,"Content-Type":"application/json"},body:JSON.stringify(t)});if(!a.ok)throw new n("FETCH_ERROR",`HTTP ${a.status} for ${o}`,"WeRead API may be temporarily unavailable");try{return await a.json()}catch{throw new n("PARSE_ERROR",`Invalid JSON response for ${o}`,"WeRead may have returned an HTML error page")}}O({site:"weread",name:"ai-outline",access:"read",description:"Get AI-generated outline for a book",domain:"weread.qq.com",strategy:N.COOKIE,defaultFormat:"plain",args:[{name:"book-id",positional:!0,required:!0,help:"Book ID (from shelf or search results)"},{name:"limit",type:"int",default:200,help:"Max outline items to return"},{name:"depth",type:"int",default:4,help:"Max outline depth (2=topics, 3=key points, 4=details)"},{name:"raw",type:"boolean",default:!1,help:"Output structured rows (chapter/idx/level/text) for programmatic use"}],columns:void 0,func:async(o,t)=>{const s=String(t["book-id"]||"").trim(),a=Boolean(t.raw),l=(await D(o,"/book/chapterInfos",{bookIds:[s],sinces:[0]}))?.data?.[0]?.updated??[];if(l.length===0)throw new n("NOT_FOUND","No chapters found for this book","Check that the book ID is correct");const d=l.map((e)=>e.chapterUid),p=new Map;for(const e of l)p.set(e.chapterUid,e.title??"");const c=(await v("/book/outline",{bookId:s,chapterUids:d}))?.itemsArray??[],i=Number(t.depth),R=[];for(const e of c){const u=e.items;if(!Array.isArray(u)||u.length===0)continue;const g=p.get(e.chapterUid)??`Chapter ${e.chapterUid}`;let r="",h=0;for(const m of u){const w=m.level??1;if(w<=1)continue;if(w>i)continue;let y=m.uiIdx??"";if(w===3&&y){r=y;h=0}if(w===4&&!y&&r){h++;y=`${r}.${h}`}R.push({chapter:g,idx:y,level:w,text:m.text??""})}}if(R.length===0)throw new n("NOT_FOUND","No AI outline available for this book","AI outlines may not be generated for all books");if(a)return R.slice(0,Number(t.limit));const b=new Map;for(const e of R){if(!b.has(e.chapter))b.set(e.chapter,[]);b.get(e.chapter).push(e)}const $=[];for(const[e,u]of b){const g=[`\uD83D\uDCD6 ${e}`];for(const r of u){const h=" ".repeat(r.level-2),m=r.level===2?`${r.idx}. `:`${r.idx} `;g.push(`${h}${m}${r.text}`)}$.push({outline:g.join(`
|
|
2
|
+
`)})}return $.slice(0,Number(t.limit))}});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import{AuthRequiredError as r,CommandExecutionError as i}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as d}from"../_shared/site-auth.js";async function a(t){return(await t.getCookies({url:"https://weread.qq.com"})).some((o)=>o.name==="wr_vid"&&o.value)}async function n(t){if(!await a(t))throw new r("weread.qq.com","WeRead wr_vid cookie missing");await t.goto("https://weread.qq.com/");await t.wait(2);const e=await t.evaluate(`(async () => {
|
|
2
|
+
try {
|
|
3
|
+
const wrVid = (document.cookie.split('; ').find(c => c.startsWith('wr_vid=')) || '').split('=')[1] || '';
|
|
4
|
+
if (!wrVid) {
|
|
5
|
+
return { kind: 'auth', detail: 'WeRead wr_vid cookie absent in document.cookie' };
|
|
6
|
+
}
|
|
7
|
+
const res = await fetch('/web/user', { credentials: 'include', headers: { 'Accept': 'application/json' } });
|
|
8
|
+
if (res.status === 401 || res.status === 403) {
|
|
9
|
+
return { kind: 'auth', detail: 'WeRead /web/user HTTP ' + res.status };
|
|
10
|
+
}
|
|
11
|
+
if (!res.ok) return { kind: 'http', httpStatus: res.status };
|
|
12
|
+
const d = await res.json();
|
|
13
|
+
if (d && d.errCode && d.errCode !== 0) {
|
|
14
|
+
return { kind: 'auth', detail: 'WeRead /web/user errCode=' + d.errCode };
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
ok: true,
|
|
18
|
+
user_id: String(d.userVid || wrVid),
|
|
19
|
+
name: String(d.name || d.nickName || ''),
|
|
20
|
+
};
|
|
21
|
+
} catch (e) {
|
|
22
|
+
return { kind: 'exception', detail: String(e && e.message || e) };
|
|
23
|
+
}
|
|
24
|
+
})()`);if(e?.kind==="auth")throw new r("weread.qq.com",e.detail);if(e?.kind==="http")throw new i(`HTTP ${e.httpStatus} from /web/user`);if(e?.kind==="exception")throw new i(`WeRead whoami failed: ${e.detail}`);if(!e?.ok)throw new i(`Unexpected WeRead probe: ${JSON.stringify(e)}`);return{user_id:e.user_id,name:e.name}}d({site:"weread",domain:"weread.qq.com",loginUrl:"https://weread.qq.com/",columns:["user_id","name"],quickCheck:a,verify:n,poll:async(t)=>{if(!await a(t))throw new r("weread.qq.com","Waiting for WeRead wr_vid cookie");return n(t)}});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{cli as O,Strategy as B}from"@jackwener/opencli/registry";import{ArgumentError as m,CommandExecutionError as u,EmptyResultError as y}from"@jackwener/opencli/errors";import{WEREAD_UA as x,WEREAD_WEB_ORIGIN as w}from"./utils.js";const C=100,j=500,$=50;function S(e){return String(e||"").replace(/<[^>]+>/g,"").replace(/&#x([0-9a-fA-F]+);/gi,(r,t)=>String.fromCharCode(parseInt(t,16))).replace(/&#(\d+);/g,(r,t)=>String.fromCharCode(Number(t))).replace(/ /g," ").replace(/&/g,"&").replace(/"/g,'"').trim()}function c(e){return String(e||"").replace(/\s+/g," ").trim()}function k(e,r,t,n){const o=Number(e??r);if(!Number.isInteger(o)||o<=0)throw new m(`${t} must be a positive integer`);if(n!=null&&o>n)throw new m(`${t} must be <= ${n}`);return o}function f(e){if(e==null||e==="")return null;const r=Number(e);return Number.isFinite(r)?r:null}function z(e){if(e===!0||e===1||e==="1")return!0;if(e===!1||e===0||e==="0")return!1;return null}function R(e,r){const t=c(e);if(!t)throw new m(`${r} is required`);return t}function U(e){let r;try{r=new URL(String(e||""),w)}catch{return""}const t=r.pathname.split("/").filter(Boolean);if(r.protocol!=="https:"||r.hostname!=="weread.qq.com"||t[0]!=="web"||t[1]!=="reader"||!t[2])return"";if(t.length!==3)return"";return r.toString()}async function A(e,r){let t;try{t=await fetch(e.toString(),{headers:{"User-Agent":x}})}catch(n){throw new u(`${r} request failed: ${n instanceof Error?n.message:String(n)}`)}if(!t.ok)throw new u(`${r} request failed: HTTP ${t.status}`);try{return await t.json()}catch{throw new u(`${r} returned invalid JSON`)}}async function E(e,r){let t;try{t=await fetch(e.toString(),{headers:{"User-Agent":x}})}catch(n){throw new u(`${r} request failed: ${n instanceof Error?n.message:String(n)}`)}if(!t.ok)throw new u(`${r} request failed: HTTP ${t.status}`);return t.text()}function F(e){const r=c(e);return r?`${w}/web/reader/${r}`:""}function W(e){const r="window.__INITIAL_STATE__=",t=e.indexOf(r);if(t<0)return null;const n=t+r.length,a=e.indexOf(";(function(){var s;",n),o=e.indexOf("</script>",n),s=a>=0?a:o;if(s<0)return null;try{return JSON.parse(e.slice(n,s))}catch{return null}}function H(e){const r=e.match(/<script[^>]*type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/i);if(!r)return{};try{const t=JSON.parse(r[1]),n={};n.bookId=c(t?.["@Id"]);n.title=c(t?.name);n.author=c(t?.author?.name);n.readerUrl=c(t?.url);return n}catch{return{}}}function q(e,r){const n=W(e)?.reader??{},a=n.bookInfo??{},o=H(e),s=Array.isArray(n.chapterInfos)?n.chapterInfos:[],h=c(n.infoId)||c(a.encodeId),i={};i.bookId=c(a.bookId)||c(n.bookId)||o.bookId;i.title=c(a.title)||o.title;i.author=c(a.author)||o.author;i.readerUrl=c(r)||F(h)||o.readerUrl;i.chapters=s;return i}async function L(e){if(!e)return null;const r=await E(e,"WeRead reader page"),t=q(r,e);return t.bookId?t:null}function M(e){return Array.from(e.matchAll(/<li[^>]*class="wr_bookList_item"[^>]*>([\s\S]*?)<\/li>/g)).map((t)=>{const n=t[1],a=n.match(/<a[^>]*href="([^"]+)"[^>]*class="wr_bookList_item_link"[^>]*>|<a[^>]*class="wr_bookList_item_link"[^>]*href="([^"]+)"[^>]*>/),o=n.match(/<p[^>]*class="wr_bookList_item_title"[^>]*>([\s\S]*?)<\/p>/),s=n.match(/<p[^>]*class="wr_bookList_item_author"[^>]*>([\s\S]*?)<\/p>/),h=a?.[1]||a?.[2]||"",i={};i.title=S(o?.[1]||"");i.author=S(s?.[1]||"");i.readerUrl=h?U(h):"";return i}).filter((t)=>t.title&&t.readerUrl)}async function J(e){const r=new URL("/web/search/books",w);r.searchParams.set("keyword",e);return M(await E(r,"WeRead search page"))}function T(e,r){const t=c(e.title),n=c(e.author);if(!t)return"";if(n){const o=r.filter((s)=>c(s.title)===t&&c(s.author)===n);if(o.length===1)return o[0].readerUrl}const a=r.filter((o)=>c(o.title)===t);return a.length===1?a[0].readerUrl:""}async function G(e,r){const t=new URL("/web/search/global",`${w}/web`);t.searchParams.set("keyword",e);const n=await A(t,"WeRead book search");if(!Array.isArray(n?.books))throw new u("WeRead book search returned malformed books");const a=n.books;if(a.length===0)throw new y("weread book-search",`No WeRead books found for "${e}"`);if(r>a.length)throw new m(`book-rank must be <= ${a.length}`,`Only ${a.length} book search result(s) were returned for "${e}"`);const o=a[r-1]?.bookInfo??{},s={bookId:c(o.bookId),title:c(o.title),author:c(o.author),readerUrl:"",chapters:[]};if(!s.bookId)throw new u(`WeRead book search result ${r} is missing bookId`);const h=await J(e);s.readerUrl=T(s,h);const i=await L(s.readerUrl);return{...s,...Object.fromEntries(Object.entries(i??{}).filter(([,d])=>d!=null&&d!==""&&!(Array.isArray(d)&&d.length===0)))}}async function D(e,r){if(/^https?:\/\//i.test(e)){const t=U(e);if(!t)throw new m("book URL must be a https://weread.qq.com/web/reader/<id> URL");const n=await L(t);if(!n?.bookId)throw new u("Could not parse a bookId from the reader URL");return n}if(/^\d+$/.test(e)){const t={};t.bookId=e;t.title="";t.author="";t.readerUrl="";t.chapters=[];return t}return G(e,r)}async function X(e,r,t,n){const a=[];let o=0;while(a.length<t){const s=t-a.length,h=s<$?s:$,i=new URL("/web/book/search",w);i.searchParams.set("bookId",e);i.searchParams.set("keyword",r);i.searchParams.set("maxIdx",String(o));i.searchParams.set("count",String(h));i.searchParams.set("fragmentSize",String(n));i.searchParams.set("onlyCount","0");const d=await A(i,"WeRead in-book search");if(!Array.isArray(d?.result))throw new u("WeRead in-book search returned malformed result");const p=d.result.map((l)=>{if(!l||typeof l!=="object")throw new u("WeRead in-book search returned malformed match");const _=c(l.abstract),b=f(l.searchIdx);if(!_||b==null||b<=0)throw new u("WeRead in-book search returned malformed match");return{...l,abstract:_,chapterIdx:f(l.chapterIdx),chapterUid:f(l.chapterUid),searchIdx:b}});if(p.length===0)break;a.push(...p);const g=p[p.length-1].searchIdx;if(g<=o)throw new u("WeRead in-book search returned non-advancing searchIdx");o=g;if(a.length>=t)break;const I=z(d?.hasMore);if(I==null){if(p.length<h)break;throw new u("WeRead in-book search returned malformed pagination state")}if(!I)break}if(a.length===0)throw new y("weread book-search",`No matches for "${r}" in book ${e}`);return a.slice(0,t)}function Z(e){const r=new Map;for(const t of e){const n=f(t?.chapterUid);if(n==null)continue;r.set(n,{chapterIdx:f(t?.chapterIdx),chapterTitle:c(t?.title)})}return r}function N(e,r){const t=Z(e.chapters??[]);return r.map((n,a)=>{const o=f(n?.chapterUid),s=t.get(o)??{},h=s.chapterIdx??f(n?.chapterIdx);return{rank:a+1,book_title:e.title||null,author:e.author||null,chapter_idx:h,chapter_title:s.chapterTitle||null,snippet:c(n?.abstract),search_idx:n.searchIdx,chapter_uid:o,book_id:e.bookId,url:e.readerUrl||null}})}function P(e,r,t){const a=[`# ${e.title||`WeRead book ${e.bookId}`}`];if(e.author)a.push(`- author: ${e.author}`);a.push(`- book_id: \`${e.bookId}\``);a.push(`- query: \`${r}\``);a.push(`- matches: ${t.length}`);if(e.readerUrl)a.push(`- url: ${e.readerUrl}`);a.push("");for(const o of t){const s=o.chapter_title||`chapter ${o.chapter_uid??""}`.trim();a.push(`## ${o.rank}. ${s}`);const h=[];if(o.chapter_idx!==null)h.push(`chapter_idx: ${o.chapter_idx}`);if(o.chapter_uid!==null)h.push(`chapter_uid: ${o.chapter_uid}`);h.push(`search_idx: ${o.search_idx}`);a.push("");a.push(`> ${o.snippet}`);a.push("");for(const i of h)a.push(`- ${i}`);if(o.rank<t.length)a.push("")}return a.join(`
|
|
2
|
+
`)}O({site:"weread",name:"book-search",access:"read",description:"Search within a WeRead book after resolving it by title",domain:"weread.qq.com",strategy:B.PUBLIC,browser:!1,defaultFormat:"md",args:[{name:"book",positional:!0,required:!0,help:"Book title keyword, numeric bookId, or reader URL"},{name:"query",positional:!0,required:!0,help:"Keyword to search inside the selected book"},{name:"book-rank",type:"int",default:1,help:"Which book search result to use when book is a title keyword"},{name:"limit",type:"int",default:20,help:"Max in-book matches to return (1-100)"},{name:"fragment-size",type:"int",default:150,help:"Snippet length around each match (1-500)"},{name:"raw",type:"boolean",default:!1,help:"Output structured rows instead of markdown text"}],func:async(e)=>{const r=R(e.book,"book"),t=R(e.query,"query"),n=k(e["book-rank"],1,"book-rank"),a=k(e.limit,20,"limit",C),o=k(e["fragment-size"],150,"fragment-size",j),s=await D(r,n),h=await X(s.bookId,t,a,o),i=N(s,h);if(Boolean(e.raw))return i;return[{markdown:P(s,t,i)}]}});export const __test__={buildRows:N,extractReaderInitialState:W,formatMarkdownResults:P,parseReaderMetadata:q,parseSearchHtmlEntries:M,resolveReaderUrlForBook:T};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{cli as I,Strategy as f}from"@jackwener/opencli/registry";import{CliError as b}from"@jackwener/opencli/errors";import{fetchPrivateApi as S,fetchWebApi as E,resolveShelfReader as k,WEREAD_UA as g,WEREAD_WEB_ORIGIN as _}from"./utils.js";function W(J){return J.replace(/<[^>]+>/g,"").replace(/&#x([0-9a-fA-F]+);/gi,(L,j)=>String.fromCharCode(parseInt(j,16))).replace(/&#(\d+);/g,(L,j)=>String.fromCharCode(Number(j))).replace(/ /g," ").replace(/&/g,"&").replace(/"/g,'"').trim()}function Y(J){return J.replace(/\s+/g," ").trim()}function B(J,L){return`${Y(J)}\x00${Y(L)}`}function A(J){const L=new Map;for(const j of J){const q=Y(j.title);if(!q)continue;L.set(q,(L.get(q)||0)+1)}return L}function R(J){const L=new Map;for(const j of J){const q=B(j.title,j.author);if(!Y(j.title)||!Y(j.author))continue;L.set(q,(L.get(q)||0)+1)}return L}export function strictTitleFromWereadDocumentTitle(J){const L=" - 微信读书",j=String(J||"").trim();if(!j.endsWith(L))return"";const q=j.slice(0,-L.length).trim();return q.includes(" - ")?"":q}export function extractReaderFallbackMetadata(J){const L=(V)=>V?.textContent?.trim()||"",j=(...V)=>{for(const G of V){const Q=L(J.querySelector(G));if(Q)return Q}return""},q=J.body?.innerText?.replace(/\s+/g," ").trim()||"",P=()=>{const V=q.match(/微信读书推荐值\s*([0-9.]+%)/);return V?V[1]:""},Z=()=>{const V=L(J.querySelector(".introDialog_content_pub_line"));return V.startsWith("出版社")?V.replace(/^出版社\s*/,"").trim():""},$=()=>{const V=[".horizontalReaderCoverPage_content_bookInfo_intro",".wr_flyleaf_page_bookIntro_content",".introDialog_content_intro_para"];for(const G of V){const Q=L(J.querySelector(G));if(Q)return Q}return""},F=(Array.from(J.scripts||[]).map((V)=>V.textContent||"").find((V)=>V.includes('"category"'))||"").match(/"category"\s*:\s*"([^"]+)"/),w=j(".horizontalReaderCoverPage_content_bookTitle",".wr_flyleaf_page_bookInfo_bookTitle",".outline_book_detail_header_title",".readerTopBar_title_link")||strictTitleFromWereadDocumentTitle(J.title||""),O=j(".horizontalReaderCoverPage_content_author",".wr_flyleaf_page_bookInfo_author",".outline_book_detail_header_author");return{title:w,author:O,publisher:Z(),intro:$(),category:F?F[1].trim():"",rating:P(),metadataReady:Boolean(w||O)}}async function p(J,L){const j=Y(J),q=Y(L);if(!j)return"";try{const[P,Z]=await Promise.all([E("/search/global",{keyword:j}),(async()=>{const Q=new URL("/web/search/books",_);Q.searchParams.set("keyword",j);const N=await fetch(Q.toString(),{headers:{"User-Agent":g}});if(!N.ok)return[];const U=await N.text();return Array.from(U.matchAll(/<li[^>]*class="wr_bookList_item"[^>]*>([\s\S]*?)<\/li>/g)).map((H)=>{const K=H[1],C=K.match(/<a[^>]*href="([^"]+)"[^>]*class="wr_bookList_item_link"[^>]*>|<a[^>]*class="wr_bookList_item_link"[^>]*href="([^"]+)"[^>]*>/),v=K.match(/<p[^>]*class="wr_bookList_item_title"[^>]*>([\s\S]*?)<\/p>/),M=K.match(/<p[^>]*class="wr_bookList_item_author"[^>]*>([\s\S]*?)<\/p>/),D=C?.[1]||C?.[2]||"";return{title:W(v?.[1]||""),author:W(M?.[1]||""),url:D?new URL(D,_).toString():""}}).filter((H)=>H.title&&H.url)})()]),$=Array.isArray(P?.books)?P.books:[],X=R($.map((Q)=>({title:Q.bookInfo?.title??"",author:Q.bookInfo?.author??""}))),F=R(Z.filter((Q)=>Q.author)),w=B(j,q);if(q&&(X.get(w)||0)===1&&(F.get(w)||0)===1){const Q=Z.find((N)=>B(N.title,N.author)===w);if(Q?.url)return Q.url}const O=Z.filter((Q)=>Y(Q.title)===j);if(q&&O.some((Q)=>Y(Q.author)))return"";const V=A($.map((Q)=>({title:Q.bookInfo?.title??""}))),G=A(Z);if((V.get(j)||0)!==1||(G.get(j)||0)!==1)return"";return Z.find((Q)=>Y(Q.title)===j)?.url||""}catch{return""}}async function z(J,L){await J.goto(L);await J.wait({selector:".horizontalReaderCoverPage_content_bookTitle, .wr_flyleaf_page_bookInfo_bookTitle, .readerTopBar_title_link",timeout:10});const j=await J.evaluate(`
|
|
2
|
+
(${extractReaderFallbackMetadata.toString()})(document)
|
|
3
|
+
`);return{title:String(j?.title||"").trim(),author:String(j?.author||"").trim(),publisher:String(j?.publisher||"").trim(),intro:String(j?.intro||"").trim(),category:String(j?.category||"").trim(),rating:String(j?.rating||"").trim(),metadataReady:j?.metadataReady===!0}}I({site:"weread",name:"book",access:"read",description:"View book details on WeRead",domain:"weread.qq.com",strategy:f.COOKIE,args:[{name:"book-id",positional:!0,required:!0,help:"Book ID from search or shelf results"}],columns:["title","author","publisher","intro","category","rating"],func:async(J,L)=>{const j=String(L["book-id"]||"").trim();try{const q=await S(J,"/book/info",{bookId:j}),P=q.newRating?`${(q.newRating/10).toFixed(1)}%`:"-";return[{title:q.title??"",author:q.author??"",publisher:q.publisher??"",intro:q.intro??"",category:q.category??"",rating:P}]}catch(q){if(!(q instanceof b)||q.code!=="AUTH_REQUIRED")throw q;const{readerUrl:P,snapshot:Z}=await k(J,j);let $=P;if(!$){const F=Z.rawBooks.find((w)=>String(w?.bookId||"").trim()===j);$=await p(String(F?.title||""),String(F?.author||""))}if(!$)throw q;const X=await z(J,$);if(!X.metadataReady||!X.title)throw q;return[{title:X.title,author:X.author,publisher:X.publisher,intro:X.intro,category:X.category,rating:X.rating}]}}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as r,Strategy as i}from"@jackwener/opencli/registry";import{fetchPrivateApi as o,formatDate as s}from"./utils.js";r({site:"weread",name:"highlights",access:"read",description:"List your highlights (underlines) in a book",domain:"weread.qq.com",strategy:i.COOKIE,args:[{name:"book-id",positional:!0,required:!0,help:"Book ID (from shelf or search results)"},{name:"limit",type:"int",default:20,help:"Max results"}],columns:["chapter","text","createTime"],func:async(a,t)=>{return((await o(a,"/book/bookmarklist",{bookId:t["book-id"]}))?.updated??[]).slice(0,Number(t.limit)).map((e)=>({chapter:e.chapterName??"",text:e.markText??"",createTime:s(e.createTime)}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as z,Strategy as B}from"@jackwener/opencli/registry";import{fetchPrivateApi as E}from"./utils.js";z({site:"weread",name:"notebooks",access:"read",description:"List books that have highlights or notes",domain:"weread.qq.com",strategy:B.COOKIE,columns:["title","author","noteCount","bookId"],func:async(x,F)=>{return((await E(x,"/user/notebooks"))?.books??[]).map((q)=>({title:q.book?.title??"",author:q.book?.author??"",noteCount:(q.bookmarkCount??0)+(q.reviewCount??0),bookId:q.bookId??""}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as a,Strategy as i}from"@jackwener/opencli/registry";import{fetchPrivateApi as o,formatDate as s}from"./utils.js";a({site:"weread",name:"notes",access:"read",description:"List your notes (thoughts) on a book",domain:"weread.qq.com",strategy:i.COOKIE,args:[{name:"book-id",positional:!0,required:!0,help:"Book ID (from shelf or search results)"},{name:"limit",type:"int",default:20,help:"Max results"}],columns:["chapter","text","review","createTime"],func:async(r,t)=>{return((await o(r,"/review/list",{bookId:t["book-id"],listType:"11",mine:"1",synckey:"0"}))?.reviews??[]).slice(0,Number(t.limit)).map((e)=>({chapter:e.review?.chapterName??"",text:e.review?.abstract??"",review:e.review?.content??"",createTime:s(e.review?.createTime)}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as r,Strategy as n}from"@jackwener/opencli/registry";import{fetchWebApi as i}from"./utils.js";r({site:"weread",name:"ranking",access:"read",description:"WeRead book rankings by category",domain:"weread.qq.com",strategy:n.PUBLIC,browser:!1,args:[{name:"category",positional:!0,default:"all",help:"Category: all (default), rising, or numeric category ID"},{name:"limit",type:"int",default:20,help:"Max results"}],columns:["rank","title","author","category","readingCount","bookId"],func:async(a)=>{const t=encodeURIComponent(a.category??"all");return((await i(`/bookListInCategory/${t}`,{rank:"1"}))?.books??[]).slice(0,Number(a.limit)).map((o,e)=>({rank:e+1,title:o.bookInfo?.title??"",author:o.bookInfo?.author??"",category:o.bookInfo?.category??"",readingCount:o.readingCount??0,bookId:o.bookInfo?.bookId??""}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as O,Strategy as R}from"@jackwener/opencli/registry";import{CommandExecutionError as _,EmptyResultError as Q}from"@jackwener/opencli/errors";import{fetchWebApi as K,WEREAD_UA as U,WEREAD_WEB_ORIGIN as A}from"./utils.js";function M(Y,V){const F=parseInt(Y,V);if(!Number.isInteger(F)||F<0||F>1114111)return null;try{return String.fromCodePoint(F)}catch{return null}}function W(Y){return Y.replace(/<[^>]+>/g,"").replace(/&#x([0-9a-fA-F]+);/gi,(V,F)=>M(F,16)??V).replace(/&#(\d+);/g,(V,F)=>M(F,10)??V).replace(/ /g," ").replace(/&/g,"&").replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").trim()}function j(Y){return Y.replace(/\s+/g," ").trim()}function f(Y,V){return`${j(Y)}\x00${j(V)}`}function w(Y){const V=new Map;for(const F of Y){const X=j(F.title);if(!X)continue;V.set(X,(V.get(X)||0)+1)}return V}function z(Y){const V=new Map;for(const F of Y){const X=f(F.title,F.author);if(!j(F.title)||!j(F.author))continue;V.set(X,(V.get(X)||0)+1)}return V}function N(Y,V){return(Y.get(V)||0)<=1}function q(Y){const V=new Map,F=new Map;for(const X of Y){const B=j(X.title);if(!B||!X.url)continue;const $=X.author?V:F,J=X.author?f(X.title,X.author):B,L=$.get(J);if(L){L.push(X.url);continue}$.set(J,[X.url])}return{exactQueues:V,titleOnlyQueues:F}}function g(Y){const{exactQueues:V,titleOnlyQueues:F,apiIdentityCounts:X,htmlIdentityCounts:B,apiTitleCounts:$,htmlTitleCounts:J,title:L,author:H}=Y,G=f(L,H);if(N(X,G)&&N(B,G)){const D=V.get(G)?.shift();if(D)return D}const Z=j(L);if(!N($,Z)||!N(J,Z))return"";return F.get(Z)?.shift()??""}async function x(Y){const V=new URL("/web/search/books",A);V.searchParams.set("keyword",Y);let F;try{F=await fetch(V.toString(),{headers:{"User-Agent":U}})}catch($){throw new _(`Failed to fetch WeRead search page: ${$ instanceof Error?$.message:String($)}`)}if(!F.ok)throw new _(`WeRead search page request failed: HTTP ${F.status}`);const X=await F.text();return Array.from(X.matchAll(/<li[^>]*class="wr_bookList_item"[^>]*>([\s\S]*?)<\/li>/g)).map(($)=>{const J=$[1],L=J.match(/<a[^>]*href="([^"]+)"[^>]*class="wr_bookList_item_link"[^>]*>|<a[^>]*class="wr_bookList_item_link"[^>]*href="([^"]+)"[^>]*>/),H=J.match(/<p[^>]*class="wr_bookList_item_title"[^>]*>([\s\S]*?)<\/p>/),G=J.match(/<p[^>]*class="wr_bookList_item_author"[^>]*>([\s\S]*?)<\/p>/),Z=L?.[1]||L?.[2]||"",D=W(H?.[1]||"");return{author:W(G?.[1]||""),url:Z?new URL(Z,A).toString():"",title:D}}).filter(($)=>$.url&&$.title)}O({site:"weread",name:"search",access:"read",description:"Search books on WeRead",domain:"weread.qq.com",strategy:R.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:"Search keyword"},{name:"limit",type:"int",default:10,help:"Max results"}],columns:["rank","title","author","bookId","url"],func:async(Y)=>{const[V,F]=await Promise.all([K("/search/global",{keyword:Y.query}),x(String(Y.query??""))]),X=V?.books??[];if(!Array.isArray(X))throw new _("WeRead search API returned an unreadable books payload");if(X.length===0)throw new Q("weread search",`No books were returned for query ${Y.query}.`);const{exactQueues:B,titleOnlyQueues:$}=q(F),J=z(X.map((Z)=>({title:Z.bookInfo?.title??"",author:Z.bookInfo?.author??""}))),L=z(F.filter((Z)=>Z.author)),H=w(X.map((Z)=>({title:Z.bookInfo?.title??""}))),G=w(F);return X.slice(0,Number(Y.limit)).map((Z,D)=>{const P=Z.bookInfo?.title??"",v=Z.bookInfo?.author??"";return{rank:D+1,title:P,author:v,bookId:Z.bookInfo?.bookId??"",url:g({exactQueues:B,titleOnlyQueues:$,apiIdentityCounts:J,htmlIdentityCounts:L,apiTitleCounts:H,htmlTitleCounts:G,title:P,author:v})}})}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as G,Strategy as H}from"@jackwener/opencli/registry";import{CliError as J}from"@jackwener/opencli/errors";import{log as K}from"@jackwener/opencli/logger";import{buildWebShelfEntries as M,fetchPrivateApi as N,loadWebShelfSnapshot as O}from"./utils.js";function Q(B){if(!Number.isFinite(B))return 0;return Math.max(0,Math.trunc(B))}function T(B,D){return(B?.books??[]).slice(0,D).map((q)=>({title:q.bookInfo?.title??q.title??"",author:q.bookInfo?.author??q.author??"",progress:q.readingProgress!=null?`${q.readingProgress}%`:"-",bookId:q.bookId??q.bookInfo?.bookId??""}))}function U(B,D){if(D<=0)return[];return M(B).map((x)=>({title:x.title,author:x.author,progress:"-",bookId:x.bookId})).filter((x)=>Boolean(x.title||x.bookId)).slice(0,D)}G({site:"weread",name:"shelf",access:"read",description:"List books on your WeRead bookshelf",domain:"weread.qq.com",strategy:H.COOKIE,args:[{name:"limit",type:"int",default:20,help:"Max results"}],columns:["title","author","progress","bookId"],func:async(B,D)=>{const x=Q(Number(D.limit));if(x<=0)return[];try{const q=await N(B,"/shelf/sync",{synckey:"0",lectureSynckey:"0"});return T(q,x)}catch(q){if(!(q instanceof J)||q.code!=="AUTH_REQUIRED")throw q;const F=await O(B);if(!F.cacheFound)throw q;K.warn("WeRead private API auth expired; showing cached shelf data from localStorage. Results may be stale, and detail commands may still require re-login.");return U(F,x)}}});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import{CliError as P}from"@jackwener/opencli/errors";export const WEREAD_DOMAIN="weread.qq.com",WEREAD_WEB_ORIGIN=`https://${WEREAD_DOMAIN}`,WEREAD_SHELF_URL=`${WEREAD_WEB_ORIGIN}/web/shelf`;const v=`${WEREAD_WEB_ORIGIN}/web`,C=`https://i.${WEREAD_DOMAIN}`;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";const D=new Set([-2010,-2012]);function V(J){return J.map((Q)=>`${Q.name}=${Q.value}`).join("; ")}function _(J,Q){return J.status===401||D.has(Number(Q?.errcode))}function w(J){return String(J.find((Q)=>Q.name==="wr_vid")?.value||"").trim()}function N(J){return{rawBooksKey:`shelf:rawBooks:${J}`,shelfIndexesKey:`shelf:shelfIndexes:${J}`}}function O(J){return{cacheFound:J?.cacheFound===!0,rawBooks:Array.isArray(J?.rawBooks)?J.rawBooks:[],shelfIndexes:Array.isArray(J?.shelfIndexes)?J.shelfIndexes:[]}}function T(J,Q){return`
|
|
2
|
+
(() => new Promise((resolve) => {
|
|
3
|
+
const deadline = Date.now() + 5000;
|
|
4
|
+
const rawBooksKey = ${JSON.stringify(J.rawBooksKey)};
|
|
5
|
+
const shelfIndexesKey = ${JSON.stringify(J.shelfIndexesKey)};
|
|
6
|
+
const requireTrustedIndexes = ${JSON.stringify(Q)};
|
|
7
|
+
|
|
8
|
+
const readJson = (raw) => {
|
|
9
|
+
if (typeof raw !== 'string') return null;
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(raw);
|
|
12
|
+
} catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const collectBookIds = (items) => Array.isArray(items)
|
|
18
|
+
? Array.from(new Set(items.map((item) => String(item?.bookId || '').trim()).filter(Boolean)))
|
|
19
|
+
: [];
|
|
20
|
+
|
|
21
|
+
// Mirror of getTrustedIndexedBookIds in Node.js — keep in sync
|
|
22
|
+
const hasTrustedIndexes = (rawBooks, shelfIndexes) => {
|
|
23
|
+
const rawBookIds = collectBookIds(rawBooks);
|
|
24
|
+
if (rawBookIds.length === 0) return false;
|
|
25
|
+
|
|
26
|
+
const rawBookIdSet = new Set(rawBookIds);
|
|
27
|
+
const projectedIndexedBookIds = Array.isArray(shelfIndexes)
|
|
28
|
+
? Array.from(new Set(
|
|
29
|
+
shelfIndexes
|
|
30
|
+
.filter((entry) => Number.isFinite(entry?.idx))
|
|
31
|
+
.sort((left, right) => Number(left?.idx ?? Number.MAX_SAFE_INTEGER) - Number(right?.idx ?? Number.MAX_SAFE_INTEGER))
|
|
32
|
+
.map((entry) => String(entry?.bookId || '').trim())
|
|
33
|
+
.filter((bookId) => rawBookIdSet.has(bookId)),
|
|
34
|
+
))
|
|
35
|
+
: [];
|
|
36
|
+
|
|
37
|
+
return projectedIndexedBookIds.length === rawBookIds.length;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const poll = () => {
|
|
41
|
+
const rawBooks = readJson(localStorage.getItem(rawBooksKey));
|
|
42
|
+
const shelfIndexes = readJson(localStorage.getItem(shelfIndexesKey));
|
|
43
|
+
const cacheFound = Array.isArray(rawBooks);
|
|
44
|
+
const ready = cacheFound && (!requireTrustedIndexes || hasTrustedIndexes(rawBooks, shelfIndexes));
|
|
45
|
+
|
|
46
|
+
if (ready || Date.now() >= deadline) {
|
|
47
|
+
resolve({
|
|
48
|
+
cacheFound,
|
|
49
|
+
rawBooks: Array.isArray(rawBooks) ? rawBooks : [],
|
|
50
|
+
shelfIndexes: Array.isArray(shelfIndexes) ? shelfIndexes : [],
|
|
51
|
+
});
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
setTimeout(poll, 100);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
poll();
|
|
59
|
+
}))
|
|
60
|
+
`}export async function fetchWebApi(J,Q){const Y=new URL(`${v}${J}`);if(Q)for(const[X,z]of Object.entries(Q))Y.searchParams.set(X,z);const Z=await fetch(Y.toString(),{headers:{"User-Agent":WEREAD_UA}});if(!Z.ok)throw new P("FETCH_ERROR",`HTTP ${Z.status} for ${J}`,"WeRead API may be temporarily unavailable");try{return await Z.json()}catch{throw new P("PARSE_ERROR",`Invalid JSON response for ${J}`,"WeRead may have returned an HTML error page")}}export async function fetchPrivateApi(J,Q,Y){const Z=new URL(`${C}${Q}`);if(Y)for(const[$,q]of Object.entries(Y))Z.searchParams.set($,q);const X=Z.toString(),[z,G]=await Promise.all([J.getCookies({url:X}),J.getCookies({domain:WEREAD_DOMAIN})]),L=new Map;for(const $ of G)L.set($.name,$);for(const $ of z)L.set($.name,$);const j=V(Array.from(L.values()));let M;try{M=await fetch(X,{headers:{"User-Agent":WEREAD_UA,Origin:"https://weread.qq.com",Referer:"https://weread.qq.com/",...j?{Cookie:j}:{}}})}catch($){throw new P("FETCH_ERROR",`Failed to fetch ${Q}: ${$ instanceof Error?$.message:String($)}`,"WeRead API may be temporarily unavailable")}let F;try{F=await M.json()}catch{throw new P("PARSE_ERROR",`Invalid JSON response for ${Q}`,"WeRead may have returned an HTML error page")}if(_(M,F))throw new P("AUTH_REQUIRED","Not logged in to WeRead","Please log in to weread.qq.com in Chrome first");if(!M.ok)throw new P("FETCH_ERROR",`HTTP ${M.status} for ${Q}`,"WeRead API may be temporarily unavailable");if(F?.errcode!=null&&F.errcode!==0)throw new P("API_ERROR",F.errmsg??`WeRead API error ${F.errcode}`);return F}function H(J){return Array.from(new Set(J.rawBooks.map((Q)=>String(Q?.bookId||"").trim()).filter(Boolean)))}function K(J){const Q=H(J);if(Q.length===0)return[];const Y=new Set(Q),Z=Array.from(new Set(J.shelfIndexes.filter((X)=>Number.isFinite(X?.idx)).sort((X,z)=>Number(X?.idx??Number.MAX_SAFE_INTEGER)-Number(z?.idx??Number.MAX_SAFE_INTEGER)).map((X)=>String(X?.bookId||"").trim()).filter((X)=>Y.has(X))));return Z.length===Q.length?Z:[]}export function buildWebShelfEntries(J,Q=[]){const Y=H(J),Z=K(J),X=Z.length>0?Z:Y,z=new Map;for(const G of J.rawBooks){const L=String(G?.bookId||"").trim();if(!L||z.has(L))continue;z.set(L,G)}return X.map((G,L)=>{const j=z.get(G);return{bookId:G,title:String(j?.title||"").trim(),author:String(j?.author||"").trim(),readerUrl:String(Q[L]||"").trim()}})}async function U(J){await J.goto(WEREAD_SHELF_URL);const Q=await J.getCookies({domain:WEREAD_DOMAIN}),Y=w(Q);if(!Y)return{snapshot:{cacheFound:!1,rawBooks:[],shelfIndexes:[]},currentVid:""};const Z=await J.evaluate(T(N(Y),!1));return{snapshot:O(Z),currentVid:Y}}export async function loadWebShelfSnapshot(J){const{snapshot:Q}=await U(J);return Q}async function x(J,Q,Y){if(!Q.cacheFound)return Q;if(K(Q).length>0)return Q;if(!Y)return Q;const Z=await J.evaluate(T(N(Y),!0));return O(Z)}export async function resolveShelfReaderUrl(J,Q){return(await resolveShelfReader(J,Q)).readerUrl}export async function resolveShelfReader(J,Q){const{snapshot:Y,currentVid:Z}=await U(J),X=await x(J,Y,Z);if(!X.cacheFound)return{snapshot:X,readerUrl:null};const z=H(X),G=K(X),L=G.length===0&&z.length>0&&X.shelfIndexes.length===0;if(G.length===0&&!L)return{snapshot:X,readerUrl:null};const j=await J.evaluate(`
|
|
61
|
+
(() => Array.from(document.querySelectorAll('a.shelfBook[href]'))
|
|
62
|
+
.map((anchor) => {
|
|
63
|
+
const href = anchor.getAttribute('href') || '';
|
|
64
|
+
return href ? new URL(href, location.origin).toString() : '';
|
|
65
|
+
})
|
|
66
|
+
.filter(Boolean))
|
|
67
|
+
`),M=G.length>0?G.length:z.length;if(j.length!==M)return{snapshot:X,readerUrl:null};const $=buildWebShelfEntries(X,j).find((q)=>q.bookId===Q);return{snapshot:X,readerUrl:$?.readerUrl||null}}export function formatDate(J){if(!Number.isFinite(J)||J<=0)return"-";return new Date(J*1000+28800000).toISOString().slice(0,10)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as S,Strategy as T}from"@jackwener/opencli/registry";import{callGateway as q,emptyResult as G,formatDate as L,formatDuration as U,formatRating as v,makeDeepLink as R,requireBookId as D,truncate as P}from"./utils.js";S({site:"weread-official",name:"book",access:"read",description:"Show WeRead book metadata, chapters, and reading progress",domain:"weread.qq.com",strategy:T.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,required:!0,help:"WeRead bookId (from `weread-official search`)"},{name:"no-chapters",type:"boolean",default:!1,help:"Skip /book/chapterinfo call"},{name:"no-progress",type:"boolean",default:!1,help:"Skip /book/getprogress call"}],columns:["section","idx","key","value","link"],func:async(Q)=>{const E=D(Q.bookId),V=[q("/book/info",{bookId:E})],M={chapters:!Q["no-chapters"],progress:!Q["no-progress"]};if(M.chapters)V.push(q("/book/chapterinfo",{bookId:E}));if(M.progress)V.push(q("/book/getprogress",{bookId:E}));const W=await Promise.all(V);let X=0;const x=W[X++],Y=M.chapters?W[X++]:null,B=M.progress?W[X++]:null,F=[],Z=[["bookId",String(x?.bookId??E)],["title",String(x?.title??"")],["author",String(x?.author??"")],["translator",String(x?.translator??"")],["category",String(x?.category??"")],["publisher",String(x?.publisher??"")],["publishTime",String(x?.publishTime??"")],["isbn",String(x?.isbn??"")],["wordCount",String(x?.wordCount??"")],["rating",v(x?.newRating)],["ratingCount",String(x?.newRatingCount??"")],["intro",P(x?.intro,400)],["cover",String(x?.cover??"")]];for(let z=0;z<Z.length;z+=1){const[A,J]=Z[z];F.push({section:"info",idx:z+1,key:A,value:J,link:""})}F.push({section:"info",idx:Z.length+1,key:"link",value:"",link:R({bookId:E})});if(Y)(Array.isArray(Y?.chapters)?Y.chapters:[]).forEach((A,J)=>{const K=String(A?.chapterUid??"").trim(),_=Number(A?.level??1),N=`${" ".repeat(Math.max(0,_-1))}${String(A?.title??"")}`,H=Number(A?.wordCount??0),$=Number(A?.paid??0)===1,O=Number(A?.price??0),j=[`${H}字`];if(O>0)j.push($?"已购买":`${O}元`);F.push({section:"chapter",idx:Number(A?.chapterIdx??J+1),key:K,value:`${N} (${j.join(" · ")})`,link:K?R({bookId:E,chapterUid:K}):""})});if(B){const z=B?.book??{},A=Number(z?.progress??0),J=L(z?.updateTime),K=A===100?L(z?.finishTime):"",_=U(z?.recordReadingTime),C=Number(z?.isStartReading??0)===1,N=[["progress",`${A}%`],["cumulative",_],["lastReadAt",J],["finishedAt",K],["isStartReading",C?"true":"false"],["currentChapterUid",String(z?.chapterUid??"")]];for(let H=0;H<N.length;H+=1){const[$,O]=N[H];F.push({section:"progress",idx:H+1,key:$,value:O,link:""})}}if(F.length===0)G("book",`No data returned for bookId=${E}`);return F}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as Y,Strategy as Z}from"@jackwener/opencli/registry";import{callGateway as Q,emptyResult as T,formatRating as U,makeDeepLink as V,requireBookId as _,requirePositiveInt as $,truncate as W}from"./utils.js";Y({site:"weread-official",name:"discover",access:"read",description:"Personalized or similar-book recommendations from WeRead",domain:"weread.qq.com",strategy:Z.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,help:"Anchor bookId for similar-book mode; omit for personalized recommendations"},{name:"count",type:"int",default:12,help:"Page size (default 12)"},{name:"max-idx",type:"int",default:0,help:"Pagination cursor (recommend: previous searchIdx; similar: previous idx)"},{name:"session-id",help:"Carry-forward sessionId for /book/similar paging"}],columns:["rank","mode","bookId","title","author","rating","readingCount","category","idx","reason","cover","intro","link"],func:async(z)=>{const F=$(z.count,"count",{defaultValue:12,max:50}),C=Number(z["max-idx"]??0),E=z.bookId!==void 0&&z.bookId!==null&&String(z.bookId).trim()!==""?_(z.bookId):null;if(!E)return v({count:F,maxIdx:C});return P({bookId:E,count:F,maxIdx:C,sessionId:z["session-id"]})}});async function v({count:z,maxIdx:F}){const C=await Q("/book/recommend",{count:z,maxIdx:F}),E=Array.isArray(C?.books)?C.books:[];if(E.length===0)T("discover","No personalized recommendations available.");return E.map((h,J)=>{const H=String(h?.bookId??"").trim();return{rank:J+1,mode:"recommend",bookId:H,title:String(h?.title??""),author:String(h?.author??""),rating:U(h?.newRating),readingCount:Number(h?.readingCount??0),category:String(h?.category??""),idx:Number(h?.searchIdx??0),reason:String(h?.reason??""),cover:String(h?.cover??""),intro:W(h?.intro,200),link:H?V({bookId:H}):""}})}async function P({bookId:z,count:F,maxIdx:C,sessionId:E}){const h={bookId:z,count:F,maxIdx:C},J=String(E??"").trim();if(J)h.sessionId=J;const H=await Q("/book/similar",h),N=H?.booksimilar??H,O=Array.isArray(N?.books)?N.books:[];if(O.length===0)T("discover",`No similar books for bookId=${z}.`);return O.map((K,X)=>{const A=K?.book?.bookInfo??K?.bookInfo??{},M=String(A?.bookId??"").trim();return{rank:X+1,mode:"similar",bookId:M,title:String(A?.title??""),author:String(A?.author??""),rating:U(A?.newRating),readingCount:Number(A?.readingCount??0),category:String(A?.category??""),idx:Number(K?.idx??0),reason:"",cover:String(A?.cover??""),intro:W(A?.intro,200),link:M?V({bookId:M}):""}})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as Y,Strategy as Z}from"@jackwener/opencli/registry";import{callGateway as $,emptyResult as A,SKILL_VERSION as G}from"./utils.js";Y({site:"weread-official",name:"list-apis",access:"read",description:"List every api_name supported by the WeRead agent gateway",domain:"weread.qq.com",strategy:Z.PUBLIC,browser:!1,args:[],columns:["rank","apiName","description","required","optional","extras"],func:async()=>{const B=await $("/_list",{}),D=J(B);if(D.length===0)A("list-apis","Gateway returned no api inventory.");const F=D.map((C,H)=>{const M=Q(C?.required??C?.requiredParams??C?.params?.required),U=Q(C?.optional??C?.optionalParams??C?.params?.optional),W=String(C?.description??C?.help??C?.summary??""),X=T(C,["api_name","apiName","name","description","help","summary","required","optional","requiredParams","optionalParams","params"]);return{rank:H+1,apiName:String(C?.api_name??C?.apiName??C?.name??""),description:W,required:M,optional:U,extras:X}});F.push({rank:F.length+1,apiName:"(client)",description:"Local skill version reported with every gateway request",required:"",optional:"",extras:`SKILL_VERSION=${G}`});return F}});function J(B){if(!B||typeof B!=="object")return[];const D=[B?.apis,B?.list,B?.data,B?.items,B?.endpoints];for(const F of D)if(Array.isArray(F)&&F.length>0)return F;if(Array.isArray(B))return B;return[]}function Q(B){if(!B)return"";if(Array.isArray(B))return B.map((D)=>typeof D==="string"?D:D?.name??D?.param??"").filter(Boolean).join(", ");if(typeof B==="object")return Object.keys(B).filter(Boolean).join(", ");return String(B)}function T(B,D){if(!B||typeof B!=="object")return"";const F=new Set(D),C={};for(const[H,M]of Object.entries(B)){if(F.has(H))continue;C[H]=M}if(Object.keys(C).length===0)return"";try{return JSON.stringify(C)}catch{return""}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as q,Strategy as x}from"@jackwener/opencli/registry";import{callGateway as O,emptyResult as W,formatDate as j,makeDeepLink as V,parseRange as G,requireBookId as N,requirePositiveInt as E,truncate as K}from"./utils.js";q({site:"weread-official",name:"notes",access:"read",description:"List notebooks overview or merged highlights+thoughts for a book",domain:"weread.qq.com",strategy:x.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,help:"Limit to one book; omit for full notebook overview"},{name:"count",type:"int",default:20,help:"Page size for the notebooks overview (1-100)"},{name:"last-sort",type:"int",help:"Cursor: pass previous page sort value to fetch the next page (/user/notebooks)"}],columns:["kind","bookId","title","author","chapter","reviewCount","noteCount","bookmarkCount","totalNotes","progress","finished","sort","range","text","thought","star","createTime","link"],func:async(z)=>{const M=z.bookId!==void 0&&z.bookId!==null&&String(z.bookId).trim()!==""?N(z.bookId):null;if(!M)return P(z);return T(M)}});async function P(z){const X={count:E(z.count,"count",{defaultValue:20,max:100})};if(z["last-sort"]!==void 0&&z["last-sort"]!==null&&z["last-sort"]!=="")X.lastSort=E(z["last-sort"],"last-sort");const Q=await O("/user/notebooks",X),$=Array.isArray(Q?.books)?Q.books:[];if($.length===0)W("notes","No notebooks found.");return $.map((F)=>{const Y=F?.book??{},Z=String(F?.bookId??Y?.bookId??"").trim(),H=Number(F?.reviewCount??0),A=Number(F?.noteCount??0),J=Number(F?.bookmarkCount??0);return{kind:"notebook",bookId:Z,title:String(Y?.title??""),author:String(Y?.author??""),chapter:"",reviewCount:H,noteCount:A,bookmarkCount:J,totalNotes:H+A+J,progress:String(F?.readingProgress??""),finished:Number(F?.markedStatus??0)===1,sort:Number(F?.sort??0),range:"",text:"",thought:"",star:"",createTime:"",link:Z?V({bookId:Z}):""}})}async function T(z){const[M,X]=await Promise.all([O("/book/bookmarklist",{bookId:z}),O("/review/list/mine",{bookid:z})]),Q=new Map,$=Array.isArray(M?.chapters)?M.chapters:[];for(const H of $){const A=String(H?.chapterUid??"").trim();if(!A)continue;Q.set(A,String(H?.title??""))}const F=[],Y=Array.isArray(M?.updated)?M.updated:[];for(const H of Y){const A=String(H?.chapterUid??"").trim(),{rangeStart:J,rangeEnd:_}=G(H?.range);F.push({kind:"highlight",bookId:z,title:"",author:"",chapter:Q.get(A)??"",reviewCount:0,noteCount:0,bookmarkCount:0,totalNotes:0,progress:"",finished:!1,sort:0,range:String(H?.range??""),text:K(H?.markText,400),thought:"",star:"",createTime:j(H?.createTime),link:J&&_&&A?V({bookId:z,chapterUid:A,rangeStart:J,rangeEnd:_}):A?V({bookId:z,chapterUid:A}):V({bookId:z})})}const Z=Array.isArray(X?.reviews)?X.reviews:[];for(const H of Z){const A=H?.review??{},J=String(A?.chapterUid??"").trim(),_=Number(A?.star??-1);F.push({kind:"thought",bookId:z,title:"",author:"",chapter:String(A?.chapterName??"")||(Q.get(J)??""),reviewCount:0,noteCount:0,bookmarkCount:0,totalNotes:0,progress:"",finished:Number(A?.isFinish??0)===1,sort:0,range:String(A?.range??""),text:"",thought:K(A?.content,400),star:_>=0?String(_):"",createTime:j(A?.createTime),link:J?V({bookId:z,chapterUid:J}):V({bookId:z})})}if(F.length===0)W("notes",`No highlights or thoughts saved for bookId=${z}.`);return F}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as H,Strategy as M}from"@jackwener/opencli/registry";import{callGateway as _,emptyResult as S,formatDate as h,formatDuration as N,requireChoice as k,requirePositiveInt as v}from"./utils.js";const MODE_CHOICES=["weekly","monthly","annually","overall"];H({site:"weread-official",name:"readdata",access:"read",description:"Reading statistics: time, streak, preferences, top books",domain:"weread.qq.com",strategy:M.PUBLIC,browser:!1,args:[{name:"mode",default:"monthly",choices:MODE_CHOICES,help:"Stat window: weekly / monthly / annually / overall"},{name:"base-time",type:"int",help:"Optional Unix timestamp inside the target period; default is current period"}],columns:["section","idx","key","value","detail"],func:async(L)=>{const Q=k(L.mode,MODE_CHOICES,"mode","monthly"),U={mode:Q};if(L["base-time"]!==void 0&&L["base-time"]!==null&&L["base-time"]!=="")U.baseTime=v(L["base-time"],"base-time");const z=await _("/readdata/detail",U),F=[],V=Number(z?.totalReadTime??0),W=Number(z?.dayAverageReadTime??0),P=Number(z?.readDays??0),X=z?.compare,Y=Number.isFinite(Number(X))?Number(X):null,Z=[["mode",Q,""],["baseTime",h(z?.baseTime),String(z?.baseTime??"")],["readDays",String(P),""],["totalReadTime",N(V),`${V}s`],["dayAverageReadTime",N(W),`${W}s`],["compareToPrev",Y===null?"":`${(Y*100).toFixed(1)}%`,""],["readRate",z?.readRate!==void 0?`${Number(z.readRate).toFixed(1)}%`:"",""],["preferTimeWord",String(z?.preferTimeWord??""),""],["preferCategoryWord",String(z?.preferCategoryWord??""),""]];for(let x=0;x<Z.length;x+=1){const[B,J,K]=Z[x];F.push({section:"summary",idx:x+1,key:B,value:J,detail:K})}(Array.isArray(z?.readLongest)?z.readLongest:[]).forEach((x,B)=>{const J=x?.book??{},K=x?.albumInfo??null,j=K?String(K?.name??""):String(J?.title??""),q=K?String(K?.authorName??""):String(J?.author??""),G=Array.isArray(x?.tags)?x.tags.join(","):"",A=Number(x?.readTime??0);F.push({section:"longest",idx:B+1,key:j,value:N(A),detail:`${q}${G?` [${G}]`:""}`})});(Array.isArray(z?.readStat)?z.readStat:[]).forEach((x,B)=>{F.push({section:"readStat",idx:B+1,key:String(x?.stat??""),value:String(x?.counts??""),detail:""})});(Array.isArray(z?.preferCategory)?z.preferCategory:[]).forEach((x,B)=>{const J=Number(x?.readingTime??0);F.push({section:"preferCategory",idx:B+1,key:String(x?.categoryTitle??""),value:N(J),detail:`${Number(x?.readingCount??0)}本`})});(Array.isArray(z?.preferAuthor)?z.preferAuthor:[]).forEach((x,B)=>{F.push({section:"preferAuthor",idx:B+1,key:String(x?.name??""),value:String(x?.readTime??""),detail:`${Number(x?.count??0)}本`})});(Array.isArray(z?.preferPublisher)?z.preferPublisher:[]).forEach((x,B)=>{F.push({section:"preferPublisher",idx:B+1,key:String(x?.name??""),value:`${Number(x?.count??0)}本`,detail:""})});const $=Array.isArray(z?.preferTime)?z.preferTime:[];if($.length===24)for(let x=0;x<24;x+=1){const B=(6+x)%24,J=Number($[x]??0);F.push({section:"preferTime",idx:x+1,key:`${String(B).padStart(2,"0")}:00`,value:N(J),detail:`${J}s`})}if(F.length===0)S("readdata",`No reading data for mode=${Q}.`);return F}});export{MODE_CHOICES};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as G,Strategy as R}from"@jackwener/opencli/registry";import{ArgumentError as f}from"@jackwener/opencli/errors";import{callGateway as D,emptyResult as b,formatDate as h,formatStar as j,makeDeepLink as q,requireBookId as K,requirePositiveInt as U,truncate as O}from"./utils.js";const TYPE_ALIASES=Object.freeze({all:0,recommend:1,"thumbs-down":2,newest:3,neutral:4});G({site:"weread-official",name:"review",access:"read",description:"Browse public reviews of a WeRead book",domain:"weread.qq.com",strategy:R.PUBLIC,browser:!1,args:[{name:"bookId",positional:!0,required:!0,help:"WeRead bookId (from `weread-official search`)"},{name:"type",default:"all",choices:Object.keys(TYPE_ALIASES),help:"Review filter (all/recommend/thumbs-down/newest/neutral)"},{name:"count",type:"int",default:20,help:"Page size (1-100, default 20)"},{name:"max-idx",type:"int",default:0,help:"Pagination cursor — pass idx from last row of previous page"},{name:"synckey",type:"int",help:"Sync cursor returned by previous response"}],columns:["rank","idx","reviewId","star","starLabel","author","isFinish","chapter","content","createTime","link"],func:async(x)=>{const C=K(x.bookId),F=String(x.type??"all").trim();if(!Object.prototype.hasOwnProperty.call(TYPE_ALIASES,F))throw new f(`weread-official: type must be one of: ${Object.keys(TYPE_ALIASES).join(", ")}`);const V=TYPE_ALIASES[F],W=U(x.count,"count",{defaultValue:20,max:100}),H={bookId:C,reviewListType:V,count:W,maxIdx:Number(x["max-idx"]??0)};if(x.synckey!==void 0&&x.synckey!==null&&x.synckey!=="")H.synckey=U(x.synckey,"synckey");const J=await D("/review/list",H),M=Array.isArray(J?.reviews)?J.reviews:[];if(M.length===0)b("review",`No public reviews for bookId=${C} (type=${F}).`);return M.map((N,X)=>{const Q=N?.review??{},z=Q?.review??{},Z=z?.author??{},$=String(z?.chapterName??"").trim(),B=String(Q?.reviewId??z?.reviewId??"").trim();return{rank:X+1,idx:Number(N?.idx??0),reviewId:B,star:Number(z?.star??0),starLabel:j(z?.star),author:String(Z?.name??""),isFinish:Number(z?.isFinish??0)===1,chapter:$,content:O(z?.content,300),createTime:h(z?.createTime),link:q({bookId:C})}})}});export{TYPE_ALIASES};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as T,Strategy as q}from"@jackwener/opencli/registry";import{ArgumentError as v}from"@jackwener/opencli/errors";import{callGateway as x,emptyResult as $,formatRating as j,makeDeepLink as h,requirePositiveInt as H,requireText as b,truncate as I}from"./utils.js";export const SEARCH_SCOPES=Object.freeze({all:0,ebook:10,webnovel:16,audio:14,author:6,fulltext:12,booklist:13,mp:2,article:4});const L=Object.freeze({0:"全部",10:"电子书",16:"网文小说",14:"微信听书",6:"作者",12:"全文",13:"书单",2:"公众号",4:"文章"});T({site:"weread-official",name:"search",access:"read",description:"Search WeRead store via the official agent gateway",domain:"weread.qq.com",strategy:q.PUBLIC,browser:!1,args:[{name:"keyword",positional:!0,required:!0,help:"Search keyword"},{name:"scope",default:"ebook",choices:Object.keys(SEARCH_SCOPES),help:"Search type (all/ebook/webnovel/audio/author/fulltext/booklist/mp/article)"},{name:"count",type:"int",help:"Page size (gateway default 15 when omitted)"},{name:"max-idx",type:"int",default:0,help:"Pagination offset, use searchIdx of last item from previous page"}],columns:["rank","scope","bookId","title","author","rating","readingCount","category","searchIdx","cover","intro","link"],func:async(z)=>{const N=b(z.keyword,"keyword"),J=String(z.scope??"ebook").trim();if(!Object.prototype.hasOwnProperty.call(SEARCH_SCOPES,J))throw new v(`weread-official: scope must be one of: ${Object.keys(SEARCH_SCOPES).join(", ")}`);const B=SEARCH_SCOPES[J],W={keyword:N,scope:B,maxIdx:z["max-idx"]??0};if(z.count!==void 0&&z.count!==null&&z.count!=="")W.count=H(z.count,"count",{max:100});const X=await x("/store/search",W),Y=Array.isArray(X?.results)?X.results:[];if(Y.length===0)$("search",`No results for "${N}" (scope=${J}).`);const Q=[];let Z=0;for(const U of Y){const D=L[Number(U?.scope)]??"",G=Array.isArray(U?.books)?U.books:[];for(const M of G){Z+=1;const F=M?.bookInfo??{},V=String(F.bookId??"").trim();Q.push({rank:Z,scope:D,bookId:V,title:String(F.title??""),author:String(F.author??""),rating:j(M?.newRating),readingCount:Number(M?.readingCount??0),category:String(F.category??""),searchIdx:Number(M?.searchIdx??0),cover:String(F.cover??""),intro:I(F.intro,120),link:V?h({bookId:V}):""})}}if(Q.length===0)$("search",`No books found in results for "${N}" (scope=${J}).`);return Q}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as Q,Strategy as T}from"@jackwener/opencli/registry";import{callGateway as U,emptyResult as V,formatDate as F,makeDeepLink as W}from"./utils.js";Q({site:"weread-official",name:"shelf",access:"read",description:"Sync your WeRead shelf (books + albums + article bookmark entry) via the official gateway",domain:"weread.qq.com",strategy:T.PUBLIC,browser:!1,args:[],columns:["kind","id","title","author","category","secret","isTop","finished","updateTime","cover","link"],func:async()=>{const A=await U("/shelf/sync",{}),H=Array.isArray(A?.books)?A.books:[],J=Array.isArray(A?.albums)?A.albums:[],B=A?.mp,N=Boolean(B&&typeof B==="object"&&(Array.isArray(B)?B.length>0:Object.keys(B).length>0)),C=[];for(const q of H){const z=String(q?.bookId??"").trim();C.push({kind:"book",id:z,title:String(q?.title??""),author:String(q?.author??""),category:String(q?.category??""),secret:Number(q?.secret??0)===1,isTop:Number(q?.isTop??0)===1,finished:Number(q?.finishReading??0)===1,updateTime:F(q?.readUpdateTime??q?.updateTime),cover:String(q?.cover??""),link:z?W({bookId:z}):""})}for(const q of J){const z=q?.albumInfo??{},E=q?.albumInfoExtra??{},O=String(z?.albumId??"").trim();C.push({kind:"album",id:O,title:String(z?.name??""),author:String(z?.authorName??""),category:"",secret:Number(E?.secret??0)===1,isTop:Number(E?.isTop??0)===1,finished:Number(z?.finish??0)===1,updateTime:F(E?.lectureReadUpdateTime??z?.updateTime),cover:String(z?.cover??""),link:""})}if(N)C.push({kind:"mp",id:"",title:"文章收藏",author:"",category:"",secret:!0,isTop:!1,finished:!1,updateTime:"",cover:"",link:""});if(C.length===0)V("shelf","Your WeRead shelf is empty.");return C}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ArgumentError as B,AuthRequiredError as q,CommandExecutionError as K,EmptyResultError as W,TimeoutError as C}from"@jackwener/opencli/errors";export const WEREAD_GATEWAY_URL="https://i.weread.qq.com/api/agent/gateway",WEREAD_DOMAIN="weread.qq.com",SKILL_VERSION="1.0.3";const O=30000,U=new Set([-2010,-2012]);export function getApiKey(){const J=String(process.env.WEREAD_API_KEY??"").trim();if(!J)throw new q(WEREAD_DOMAIN,"WEREAD_API_KEY is not set. Export it with `export WEREAD_API_KEY=<wrk-...>`.");return J}export function buildGatewayBody(J,P={}){if(!J||typeof J!=="string")throw new B("weread-official: api_name is required");const z={api_name:J,skill_version:SKILL_VERSION};for(const[Z,Q]of Object.entries(P??{})){if(Q===void 0||Q===null||Q==="")continue;z[Z]=Q}return z}export async function callGateway(J,P={},{timeoutMs:z=O}={}){const Z=getApiKey(),Q=buildGatewayBody(J,P),$=new AbortController,Y=setTimeout(()=>$.abort(),z);let F;try{F=await fetch(WEREAD_GATEWAY_URL,{method:"POST",headers:{Authorization:`Bearer ${Z}`,"Content-Type":"application/json"},body:JSON.stringify(Q),signal:$.signal})}catch(X){if(X?.name==="AbortError")throw new C(`weread-official ${J}`,Math.round(z/1000));const G=X instanceof Error?X.message:String(X);throw new K(`weread-official ${J} request failed`,G)}finally{clearTimeout(Y)}if(!F.ok)throw new K(`weread-official ${J} HTTP ${F.status}`,"Check WeRead gateway availability and that WEREAD_API_KEY is still valid.");let j;try{j=await F.json()}catch(X){const G=X instanceof Error?X.message:String(X);throw new K(`weread-official ${J} returned invalid JSON`,G)}if(j&&typeof j==="object"&&j.upgrade_info){const X=j.upgrade_info,G=X?.required_version??X?.version??"unknown",w=X?.message??"WeRead skill version is outdated";throw new K(`WeRead skill 需升级: ${w}. Required skill_version=${G}, current=${SKILL_VERSION}`,"Pull the latest weread-skills.zip and bump SKILL_VERSION in clis/weread-official/utils.js.")}const H=Number(j?.errcode??0);if(H!==0){const X=String(j?.errmsg??"unknown error");if(U.has(H))throw new q(WEREAD_DOMAIN,`WEREAD_API_KEY rejected (errcode=${H}, ${X}). Regenerate the key and re-export it.`);throw new K(`weread-official ${J} returned errcode=${H}`,X)}return j}export function formatDate(J){const P=Number(J);if(!Number.isFinite(P)||P<=0)return"";const z=new Date(P*1000);if(Number.isNaN(z.getTime()))return"";const Z=z.getUTCFullYear(),Q=String(z.getUTCMonth()+1).padStart(2,"0"),$=String(z.getUTCDate()).padStart(2,"0");return`${Z}-${Q}-${$}`}export function formatDuration(J){if(J===null||J===void 0||J==="")return"";const P=Number(J);if(!Number.isFinite(P)||P<0)return"";const z=Math.floor(P),Z=Math.floor(z/3600),Q=Math.floor(z%3600/60);if(Z>0)return`${Z}小时${Q}分钟`;return`${Q}分钟`}export function formatStar(J){const P=Number(J);if(!Number.isFinite(P)||P<=0)return"无评分";const z=Math.min(5,Math.floor(P/20));if(z<=0)return"无评分";return"⭐".repeat(z)}export function formatRating(J){const P=Number(J);if(!Number.isFinite(P)||P<=0)return"暂无";const z=P/10;if(z>=90)return`神作 ${Math.round(z)}%`;if(z>=80)return`力荐 ${Math.round(z)}%`;if(z>=70)return`好评 ${Math.round(z)}%`;return`${z.toFixed(1)}分`}export function truncate(J,P=200){const z=String(J??"");if(!z)return"";if(z.length<=P)return z;return`${z.slice(0,P)}…`}export function makeDeepLink({bookId:J,chapterUid:P="",rangeStart:z="",rangeEnd:Z="",userVid:Q=""}={}){const $=String(J??"").trim();if(!$)return"";const Y=String(P??"").trim(),F=String(z??"").trim(),j=String(Z??"").trim();if(Y&&F&&j){const H=new URLSearchParams({bookId:$,chapterUid:Y,rangeStart:F,rangeEnd:j}),X=String(Q??"").trim();if(X)H.set("userVid",X);return`weread://bestbookmark?${H.toString()}`}if(Y)return`weread://reading?bId=${$}&chapterUid=${Y}`;return`weread://reading?bId=${$}`}export function parseRange(J){const z=String(J??"").trim().match(/^(\d+)-(\d+)$/);if(!z)return{rangeStart:"",rangeEnd:""};return{rangeStart:z[1],rangeEnd:z[2]}}export function requireText(J,P){const z=String(J??"").trim();if(!z)throw new B(`weread-official: ${P} cannot be empty`);return z}export function requireBookId(J,P="bookId"){const z=requireText(J,P);if(!/^[A-Za-z0-9_-]+$/.test(z))throw new B(`weread-official: ${P} contains invalid characters`,"Pass a bookId from `weread-official search`.");return z}export function requirePositiveInt(J,P,{defaultValue:z,max:Z}={}){if(J===void 0||J===null||J===""){if(z===void 0)throw new B(`weread-official: ${P} is required`);return z}const Q=String(J).trim();if(!/^\d+$/.test(Q))throw new B(`weread-official: ${P} must be a positive integer`);const $=Number(Q);if(!Number.isSafeInteger($)||$<1)throw new B(`weread-official: ${P} must be a positive integer`);if(Z!==void 0&&$>Z)throw new B(`weread-official: ${P} must be <= ${Z}`);return $}export function requireChoice(J,P,z,Z){const Q=String(J??Z??"").trim();if(!P.includes(Q))throw new B(`weread-official: ${z} must be one of: ${P.join(", ")}`);return Q}export function emptyResult(J,P){throw new W(`weread-official ${J}`,P)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as d,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as y}from"@jackwener/opencli/errors";import{WIKIDATA_BASE as l,joinAliases as u,pickLocalised as o,requireEntityId as m,requireLanguage as g,wikidataFetch as k}from"./utils.js";d({site:"wikidata",name:"entity",access:"read",description:"Fetch a Wikidata entity by Q/P/L id (label, description, aliases, claim summary)",domain:"www.wikidata.org",strategy:p.PUBLIC,browser:!1,args:[{name:"id",positional:!0,required:!0,help:"Entity id (e.g. Q937 = Albert Einstein, P31 = instance of)"},{name:"language",default:"en",help:"Display language (ISO 639, falls back to English when missing)"}],columns:["qid","type","label","description","aliases","claimPropertyCount","sitelinkCount","enwikiTitle","modified","url"],func:async(a)=>{const e=m(a.id),t=g(a.language),r=`${l}/wiki/Special:EntityData/${encodeURIComponent(e)}.json`,i=(await k(r,"wikidata entity"))?.entities?.[e];if(!i)throw new y("wikidata entity",`Wikidata entity ${e} returned no payload.`);const c=i.claims&&typeof i.claims==="object"?i.claims:{},s=i.sitelinks&&typeof i.sitelinks==="object"?i.sitelinks:{},n=s?.enwiki?.title;return[{qid:e,type:typeof i.type==="string"?i.type:null,label:o(i.labels,t),description:o(i.descriptions,t),aliases:u(i.aliases,t),claimPropertyCount:Object.keys(c).length,sitelinkCount:Object.keys(s).length,enwikiTitle:typeof n==="string"&&n.trim()?n:null,modified:typeof i.modified==="string"?i.modified:null,url:`${l}/wiki/${e}`}]}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as u,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as h}from"@jackwener/opencli/errors";import{WIKIDATA_BASE as l,requireBoundedInt as m,requireLanguage as y,requireString as g,wikidataFetch as w}from"./utils.js";u({site:"wikidata",name:"search",access:"read",description:"Search Wikidata items by keyword (returns Q-IDs)",domain:"www.wikidata.org",strategy:p.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:"Search keyword (label / alias)"},{name:"language",default:"en",help:"Search & display language (ISO 639, e.g. en, fr, zh)"},{name:"limit",type:"int",default:20,help:"Max items (1-50)"}],columns:["rank","qid","label","description","matchType","matchText","url"],func:async(t)=>{const r=g(t.query,"query"),a=y(t.language),n=m(t.limit,20,50),c=`${l}/w/api.php?action=wbsearchentities&search=${encodeURIComponent(r)}&language=${encodeURIComponent(a)}&uselang=${encodeURIComponent(a)}&type=item&format=json&limit=${n}&origin=*`,o=await w(c,"wikidata search"),s=Array.isArray(o?.search)?o.search:[];if(!s.length)throw new h("wikidata search",`No Wikidata items matched "${r}" in language "${a}".`);return s.slice(0,n).map((e,d)=>{const i=String(e?.id??"").trim();return{rank:d+1,qid:i,label:typeof e?.label==="string"?e.label:null,description:typeof e?.description==="string"?e.description:null,matchType:typeof e?.match?.type==="string"?e.match.type:null,matchText:typeof e?.match?.text==="string"?e.match.text:null,url:i?`${l}/wiki/${i}`:""}})}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ArgumentError as K,CommandExecutionError as L,EmptyResultError as O}from"@jackwener/opencli/errors";export const WIKIDATA_BASE="https://www.wikidata.org";const Q="opencli-wikidata-adapter/1.0 (+https://github.com/jackwener/opencli; mailto:opencli@example.com)",S=/^[QPL]\d+$/;export function requireString(z,F){const B=String(z??"").trim();if(!B)throw new K(`wikidata ${F} cannot be empty`);return B}export function requireBoundedInt(z,F,B,H="limit"){const G=z??F,J=typeof G==="number"?G:Number(G);if(!Number.isInteger(J)||J<=0)throw new K(`wikidata ${H} must be a positive integer`);if(J>B)throw new K(`wikidata ${H} must be <= ${B}`);return J}export function requireEntityId(z){const F=String(z??"").trim().toUpperCase();if(!F)throw new K('wikidata entity id is required (e.g. "Q937")');const B=F.replace(/^HTTPS?:\/\/[^/]+\/WIKI\//i,"");if(!S.test(B))throw new K(`wikidata entity id "${z}" is not a valid Q/P/L identifier`,'Expected format: "Q<digits>" (item), "P<digits>" (property), or "L<digits>" (lexeme).');return B}export function requireLanguage(z,F="en"){const B=String(z??F).trim().toLowerCase();if(!/^[a-z]{2,3}(-[a-z]{2,8})?$/.test(B))throw new K(`wikidata language "${z}" is not a valid language code`,'Expected an ISO 639 language code such as "en", "fr", "zh", "zh-hans".');return B}export async function wikidataFetch(z,F){let B;try{B=await fetch(z,{headers:{"user-agent":Q,accept:"application/json"}})}catch(G){throw new L(`${F} request failed: ${G?.message??G}`,"Check that www.wikidata.org is reachable from this network.")}if(B.status===404)throw new O(F,`Wikidata returned 404 for ${z}.`);if(B.status===429)throw new L(`${F} returned HTTP 429 (rate limited)`,"Wikidata throttles anonymous traffic; back off and retry.");if(!B.ok)throw new L(`${F} returned HTTP ${B.status}`);let H;try{H=await B.json()}catch(G){throw new L(`${F} returned malformed JSON: ${G?.message??G}`)}return H}export function pickLocalised(z,F){if(!z||typeof z!=="object")return null;const B=z[F];if(B&&typeof B.value==="string"&&B.value.trim())return B.value;if(F!=="en"&&z.en&&typeof z.en.value==="string"&&z.en.value.trim())return z.en.value;return null}export function joinAliases(z,F,B=5){if(!z||typeof z!=="object")return"";let H=Array.isArray(z[F])?z[F]:[];if(H.length===0&&F!=="en"&&Array.isArray(z.en))H=z.en;const G=H.map((J)=>J&&typeof J.value==="string"?J.value:"").filter(Boolean);if(G.length===0)return"";if(G.length>B)return[...G.slice(0,B),`(+${G.length-B})`].join(", ");return G.join(", ")}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{cli as u,Strategy as w}from"@jackwener/opencli/registry";import{ArgumentError as c,CommandExecutionError as o,EmptyResultError as m}from"@jackwener/opencli/errors";u({site:"wikipedia",name:"page",access:"read",description:"Full plain-text extract of a Wikipedia article (optional paragraph cap).",domain:"wikipedia.org",strategy:w.PUBLIC,browser:!1,args:[{name:"title",positional:!0,required:!0,type:"string",help:'Article title (e.g. "Transformer (machine learning model)")'},{name:"lang",type:"string",default:"en",help:"Language code (en, zh, ja, de, ...)."},{name:"paragraphs",type:"int",default:0,help:"Cap to first N paragraphs (0 = full article)."}],columns:["title","description","pageId","paragraphs","extract","url"],func:async(i)=>{const l=String(i.title??"").trim();if(!l)throw new c("wikipedia page title cannot be empty");const n=String(i.lang??"en").trim().toLowerCase();if(!/^[a-z]{2,3}(?:-[a-z0-9]+)?$/.test(n))throw new c(`wikipedia lang must be a language code like en, zh, ja (got "${i.lang}")`);const s=Number(i.paragraphs??0);if(!Number.isInteger(s)||s<0)throw new c("paragraphs must be a non-negative integer (0 = full article)");const e=new URL(`https://${n}.wikipedia.org/w/api.php`);e.searchParams.set("action","query");e.searchParams.set("format","json");e.searchParams.set("formatversion","2");e.searchParams.set("prop","extracts|info|description");e.searchParams.set("inprop","url");e.searchParams.set("explaintext","1");e.searchParams.set("redirects","1");e.searchParams.set("titles",l);let p;try{p=await fetch(e,{headers:{"User-Agent":"opencli/1.0 (+https://github.com/jackwener/opencli)",Accept:"application/json"}})}catch(t){throw new o(`wikipedia page request failed: ${t?.message||t}`)}if(!p.ok)throw new o(`wikipedia page failed: HTTP ${p.status}`);let r;try{r=await p.json()}catch(t){throw new o(`wikipedia returned malformed JSON: ${t?.message||t}`)}if(r?.error)throw new o(`wikipedia API error: ${r.error.info||r.error.code}`);const a=(Array.isArray(r?.query?.pages)?r.query.pages:[])[0];if(!a||a.missing)throw new m("wikipedia page",`No article "${l}" on ${n}.wikipedia.org. Try \`opencli wikipedia search\` first.`);const g=String(a.extract??"");if(!g.trim())throw new m("wikipedia page",`Article "${a.title}" exists but has no plain-text extract (likely a disambiguation/redirect page).`);const h=g.split(/\n{2,}/).map((t)=>t.trim()).filter(Boolean),d=s>0?h.slice(0,s):h;return[{title:a.title,description:a.description||"",pageId:a.pageid??null,paragraphs:d.length,extract:d.join(`
|
|
2
|
+
|
|
3
|
+
`),url:a.fullurl||`https://${n}.wikipedia.org/wiki/${encodeURIComponent(a.title.replace(/ /g,"_"))}`}]}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{CliError as t}from"@jackwener/opencli/errors";import{cli as i,Strategy as n}from"@jackwener/opencli/registry";import{formatSummaryRow as o,wikiFetch as m}from"./utils.js";i({site:"wikipedia",name:"random",access:"read",description:"Get a random Wikipedia article",strategy:n.PUBLIC,browser:!1,args:[{name:"lang",default:"en",help:"Language code (e.g. en, zh, ja)"}],columns:["title","description","extract","url"],func:async(e)=>{const a=e.lang||"en",r=await m(a,"/api/rest_v1/page/random/summary");if(!r?.title)throw new t("NOT_FOUND","No random article returned","Try again");return[o(r,a)]}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{CliError as o}from"@jackwener/opencli/errors";import{cli as s,Strategy as l}from"@jackwener/opencli/registry";import{wikiFetch as c}from"./utils.js";s({site:"wikipedia",name:"search",access:"read",description:"Search Wikipedia articles",strategy:l.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:"Search keyword"},{name:"limit",type:"int",default:10,help:"Max results"},{name:"lang",default:"en",help:"Language code (e.g. en, zh, ja)"}],columns:["title","snippet","url"],func:async(e)=>{const r=Math.max(1,Math.min(Number(e.limit),50)),i=e.lang||"en",n=encodeURIComponent(e.query),a=(await c(i,`/w/api.php?action=query&list=search&srsearch=${n}&srlimit=${r}&format=json&utf8=1`))?.query?.search;if(!a?.length)throw new o("NOT_FOUND","No articles found","Try a different keyword");return a.map((t)=>({title:t.title,snippet:t.snippet.replace(/<[^>]+>/g,"").slice(0,120),url:`https://${i}.wikipedia.org/wiki/${encodeURIComponent(t.title.replace(/ /g,"_"))}`}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{CliError as a}from"@jackwener/opencli/errors";import{cli as n,Strategy as o}from"@jackwener/opencli/registry";import{formatSummaryRow as l,wikiFetch as c}from"./utils.js";n({site:"wikipedia",name:"summary",access:"read",description:"Get Wikipedia article summary",strategy:o.PUBLIC,browser:!1,args:[{name:"title",positional:!0,required:!0,help:'Article title (e.g. "Transformer (machine learning model)")'},{name:"lang",default:"en",help:"Language code (e.g. en, zh, ja)"}],columns:["title","description","extract","url"],func:async(e)=>{const t=e.lang||"en",i=encodeURIComponent(e.title.replace(/ /g,"_")),r=await c(t,`/api/rest_v1/page/summary/${i}`);if(!r?.title)throw new a("NOT_FOUND",`Article "${e.title}" not found`,"Try searching first: opencli wikipedia search <keyword>");return[l(r,t)]}});
|