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,17 @@
|
|
|
1
|
+
import{cli as L,Strategy as I}from"@jackwener/opencli/registry";import{ArgumentError as a,AuthRequiredError as w,CommandExecutionError as u,EmptyResultError as y}from"@jackwener/opencli/errors";const c="www.linkedin.com";function f(e){return String(e??"").replace(/[ ]/g," ").replace(/\s+/g," ").trim()}function S(e){if(e&&typeof e==="object"&&"data"in e&&"session"in e)return e.data;return e}function m(e){const n=f(e);if(!n)throw new a("<slug> is required");let t=n;if(/^https?:\/\//i.test(n)){let r;try{r=new URL(n)}catch{throw new a(`Invalid LinkedIn Learning URL: "${n}"`)}const i=r.hostname.toLowerCase();if(i!=="linkedin.com"&&i!=="www.linkedin.com")throw new a(`Invalid LinkedIn Learning host: "${r.hostname}"`);const s=r.pathname.match(/^\/learning\/([^/?#]+)/);if(!s)throw new a(`Invalid LinkedIn Learning course URL: "${n}"`);t=s[1]}else{const r=n.match(/^\/?learning\/([^/?#]+)/);t=r?r[1]:n}if(!/^[a-zA-Z0-9-_]+$/.test(t))throw new a(`Invalid LinkedIn Learning slug: "${t}"`);return t}function v(e,n){return String.raw`(async () => {
|
|
2
|
+
try {
|
|
3
|
+
const res = await fetch(${JSON.stringify(e)}, {
|
|
4
|
+
credentials: 'include',
|
|
5
|
+
headers: {
|
|
6
|
+
'csrf-token': ${JSON.stringify(n)},
|
|
7
|
+
'x-restli-protocol-version': '2.0.0',
|
|
8
|
+
accept: 'application/json',
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
if (res.status === 401 || res.status === 403) return { authRequired: true, status: res.status };
|
|
12
|
+
if (!res.ok) return { error: 'HTTP ' + res.status };
|
|
13
|
+
return { json: await res.json() };
|
|
14
|
+
} catch (e) {
|
|
15
|
+
return { error: 'fetch failed: ' + ((e && e.message) || String(e)) };
|
|
16
|
+
}
|
|
17
|
+
})()`}function h(e,n){const t=f(e?.title);if(!t)return null;const r=typeof e?.description==="string"?e.description:e?.description?.text||"",i=e?.duration?.unit==="SECOND"?String(e.duration.duration??""):"",s=e?.activatedAt?new Date(e.activatedAt).toISOString().slice(0,10):"";return{title:t,slug:n,description:r,difficulty:e?.difficultyLevel||"",duration_sec:i,videos_count:e?.videosCount??"",rating:typeof e?.rating?.averageRating==="number"?e.rating.averageRating.toFixed(2):"",rating_count:e?.rating?.ratingCount??"",released:s,url:`https://www.linkedin.com/learning/${n}`}}L({site:"linkedin-learning",name:"course",access:"read",description:"Get LinkedIn Learning course detail by slug or course URL",domain:c,strategy:I.COOKIE,browser:!0,args:[{name:"slug",type:"string",required:!0,positional:!0,help:"Course slug (e.g. agentic-ai-build-your-first-agentic-ai-system) or full /learning/<slug> URL"}],columns:["title","slug","description","difficulty","duration_sec","videos_count","rating","rating_count","released","url"],func:async(e,n)=>{if(!e)throw new u("Browser session required for linkedin-learning course");const t=m(n.slug);await e.goto("https://www.linkedin.com/learning/");await e.wait(3);const i=(await e.getCookies({url:"https://www.linkedin.com"})).find((k)=>k.name==="JSESSIONID")?.value;if(!i)throw new w(c,"LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn in the browser.");const s=i.replace(/^"|"$/g,""),p=`https://www.linkedin.com/learning-api/courses?q=slug&slug=${encodeURIComponent(t)}`,o=S(await e.evaluate(v(p,s)));if(o?.authRequired)throw new w(c,`LinkedIn Learning auth failed (HTTP ${o.status??""}).`);if(!o?.json)throw new u(`LinkedIn Learning courses lookup failed: ${o?.error??"no payload"}`);const l=o.json?.elements;if(!Array.isArray(l))throw new u("LinkedIn Learning courses lookup returned malformed payload: missing elements array");const d=l[0];if(!d)throw new y(`No LinkedIn Learning course found for slug "${t}"`);const g=h(d,t);if(!g)throw new u("LinkedIn Learning courses lookup returned malformed course detail: missing title");return[g]}});export const __test__={parseSlug:m,parseCourse:h};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import{cli as E,Strategy as C}from"@jackwener/opencli/registry";import{ArgumentError as m,AuthRequiredError as g,CommandExecutionError as s,EmptyResultError as N}from"@jackwener/opencli/errors";const c="www.linkedin.com",l=50;function d(e){return String(e??"").replace(/[ ]/g," ").replace(/\s+/g," ").trim()}function h(e){if(e===void 0||e===null||e==="")return 10;const n=Number(e);if(!Number.isInteger(n)||n<1||n>l)throw new m(`--limit must be an integer between 1 and ${l}`);return n}function R(e){if(e&&typeof e==="object"&&"data"in e&&"session"in e)return e.data;return e}function p(e,n){return String.raw`(async () => {
|
|
2
|
+
try {
|
|
3
|
+
const res = await fetch(${JSON.stringify(e)}, {
|
|
4
|
+
credentials: 'include',
|
|
5
|
+
headers: {
|
|
6
|
+
'csrf-token': ${JSON.stringify(n)},
|
|
7
|
+
'x-restli-protocol-version': '2.0.0',
|
|
8
|
+
accept: 'application/json',
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
if (res.status === 401 || res.status === 403) return { authRequired: true, status: res.status };
|
|
12
|
+
if (!res.ok) return { error: 'HTTP ' + res.status };
|
|
13
|
+
return { json: await res.json() };
|
|
14
|
+
} catch (e) {
|
|
15
|
+
return { error: 'fetch failed: ' + ((e && e.message) || String(e)) };
|
|
16
|
+
}
|
|
17
|
+
})()`}function k(e){if(!Array.isArray(e))return"";return e.map((n)=>d((n?.firstName??"")+" "+(n?.lastName??""))).filter(Boolean).join(", ")}function y(e){const n=e?.["com.linkedin.common.TimeSpan"];if(!n||n.unit!=="SECOND")return"";return String(n.duration??"")}function S(e){if(!e)return"";if(typeof e.averageRating==="number")return e.averageRating.toFixed(2);if(typeof e.ratingSum==="number"&&typeof e.ratingCount==="number"&&e.ratingCount>0)return(e.ratingSum/e.ratingCount).toFixed(2);return""}function I(e,n){const r=e?.entityType||"",t=e?.slug||"";if(!t)return null;return{rank:n,type:r,title:e?.headline?.title?.text||"",instructor:k(e?.authors),difficulty:e?.difficultyLevel||"",duration_sec:y(e?.length),rating:S(e?.rating),rating_count:e?.rating?.ratingCount??"",viewers:e?.viewerCount??"",url:t?`https://www.linkedin.com/learning/${t}`:""}}E({site:"linkedin-learning",name:"search",access:"read",description:"Search LinkedIn Learning courses, videos, and learning paths by keyword",domain:c,strategy:C.COOKIE,browser:!0,args:[{name:"keywords",type:"string",required:!0,positional:!0,help:'Search keywords, e.g. "AI agent"'},{name:"limit",type:"int",default:10,help:`Maximum results to return (1-${l})`}],columns:["rank","type","title","instructor","difficulty","duration_sec","rating","rating_count","viewers","url"],func:async(e,n)=>{if(!e)throw new s("Browser session required for linkedin-learning search");const r=d(n.keywords);if(!r)throw new m("--keywords is required");const t=h(n.limit);await e.goto("https://www.linkedin.com/learning/");await e.wait(3);const w=(await e.getCookies({url:"https://www.linkedin.com"})).find((u)=>u.name==="JSESSIONID")?.value;if(!w)throw new g(c,"LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn in the browser.");const L=w.replace(/^"|"$/g,""),b=`https://www.linkedin.com/learning-api/searchV2?keywords=${encodeURIComponent(r)}&q=keywords`,i=R(await e.evaluate(p(b,L)));if(i?.authRequired)throw new g(c,`LinkedIn Learning auth failed (HTTP ${i.status??""}).`);if(!i?.json)throw new s(`LinkedIn Learning searchV2 failed: ${i?.error??"no payload"}`);const a=i.json?.elements;if(!Array.isArray(a))throw new s("LinkedIn Learning searchV2 returned malformed payload: missing elements array");if(a.length===0)throw new N(`No LinkedIn Learning results for "${r}"`);const o=[];for(const u of a){if(o.length>=t)break;const f=I(u,o.length+1);if(f)o.push(f)}if(o.length===0)throw new s("LinkedIn Learning searchV2 returned no parseable rows with slug identity");return o}});export const __test__={normalizeWhitespace:d,parseLimit:h,parseAuthors:k,durationSeconds:y,averageRating:S,parseRow:I,buildFetchScript:p};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import{cli as R,Strategy as $}from"@jackwener/opencli/registry";import{ArgumentError as x,AuthRequiredError as y,CommandExecutionError as a,EmptyResultError as C}from"@jackwener/opencli/errors";const c="www.linkedin.com",d=50,N=25;function L(e){if(e===void 0||e===null||e==="")return 10;const n=Number(e);if(!Number.isInteger(n)||n<1||n>d)throw new x(`--limit must be an integer between 1 and ${d}`);return n}function O(e){if(e&&typeof e==="object"&&"data"in e&&"session"in e)return e.data;return e}function T(e,n){return String.raw`(async () => {
|
|
2
|
+
try {
|
|
3
|
+
const res = await fetch(${JSON.stringify(e)}, {
|
|
4
|
+
credentials: 'include',
|
|
5
|
+
headers: {
|
|
6
|
+
'csrf-token': ${JSON.stringify(n)},
|
|
7
|
+
'x-restli-protocol-version': '2.0.0',
|
|
8
|
+
accept: 'application/json',
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
if (res.status === 401 || res.status === 403) return { authRequired: true, status: res.status };
|
|
12
|
+
if (!res.ok) return { error: 'HTTP ' + res.status };
|
|
13
|
+
return { json: await res.json() };
|
|
14
|
+
} catch (e) {
|
|
15
|
+
return { error: 'fetch failed: ' + ((e && e.message) || String(e)) };
|
|
16
|
+
}
|
|
17
|
+
})()`}function I(e,n,r){const s=e?.slug||"";if(!s)return null;return{rank:r,group:n?.title?.text||n?.annotation||"",type:e?.entityType||e?.localizedEntityName||"",title:e?.title?.text||e?.headline?.title?.text||e?.headline?.text||"",difficulty:e?.difficultyLevel||"",viewers:e?.viewerCount??"",url:s?`https://www.linkedin.com/learning/${s}`:""}}R({site:"linkedin-learning",name:"trending",access:"read",description:"Browse LinkedIn Learning recommended courses across personalized carousels",domain:c,strategy:$.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:10,help:`Maximum results to return (1-${d})`}],columns:["rank","group","type","title","difficulty","viewers","url"],func:async(e,n)=>{if(!e)throw new a("Browser session required for linkedin-learning trending");const r=L(n.limit);await e.goto("https://www.linkedin.com/learning/");await e.wait(3);const f=(await e.getCookies({url:"https://www.linkedin.com"})).find((o)=>o.name==="JSESSIONID")?.value;if(!f)throw new y(c,"LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn in the browser.");const S=f.replace(/^"|"$/g,""),E=`https://www.linkedin.com/learning-api/feedRecommendationGroups?countPerCarousel=${N}&q=learner`,i=O(await e.evaluate(T(E,S)));if(i?.authRequired)throw new y(c,`LinkedIn Learning auth failed (HTTP ${i.status??""}).`);if(!i?.json)throw new a(`LinkedIn Learning feedRecommendationGroups failed: ${i?.error??"no payload"}`);const m=i.json?.elements;if(!Array.isArray(m))throw new a("LinkedIn Learning feedRecommendationGroups returned malformed payload: missing elements array");const t=[],w=new Set;let g=1,h=!1;for(const o of m){const b=Array.isArray(o?.carousels)?o.carousels:[];for(const u of b){const A=Array.isArray(u?.cards)?u.cards:[];for(const p of A){h=!0;if(t.length>=r)break;const l=p?.slug;if(!l||w.has(l))continue;w.add(l);const k=I(p,u,g);if(!k)continue;t.push(k);g+=1}if(t.length>=r)break}if(t.length>=r)break}if(t.length===0){if(h)throw new a("LinkedIn Learning feedRecommendationGroups returned no parseable cards with slug identity");throw new C("LinkedIn Learning returned no personalized recommendations")}return t}});export const __test__={parseLimit:L,parseCard:I};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import{AuthRequiredError as n,CommandExecutionError as i}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as s}from"../_shared/site-auth.js";async function o(t){return(await t.getCookies({url:"https://linux.do"})).some((r)=>r.name==="_t"&&r.value)}async function u(t){if(!await o(t))throw new n("linux.do","Linux.do _t cookie missing — anonymous");await t.goto("https://linux.do/");await t.wait(2);const e=await t.evaluate(`(async () => {
|
|
2
|
+
try {
|
|
3
|
+
const u = document.querySelector('meta[name="current-user-username"]')?.getAttribute('content') || '';
|
|
4
|
+
if (!u) return { kind: 'auth', detail: 'Linux.do meta[current-user-username] missing — anonymous' };
|
|
5
|
+
const r = await fetch('/u/' + encodeURIComponent(u) + '.json', {
|
|
6
|
+
credentials: 'include',
|
|
7
|
+
headers: { Accept: 'application/json' },
|
|
8
|
+
});
|
|
9
|
+
if (r.status === 401 || r.status === 403) {
|
|
10
|
+
return { kind: 'auth', detail: 'Linux.do /u/<self>.json HTTP ' + r.status };
|
|
11
|
+
}
|
|
12
|
+
if (!r.ok) return { kind: 'http', httpStatus: r.status };
|
|
13
|
+
const d = await r.json();
|
|
14
|
+
const user = d?.user;
|
|
15
|
+
if (!user || !user.id) return { kind: 'auth', detail: 'Linux.do /u/<self>.json missing user.id' };
|
|
16
|
+
return { ok: true, user_id: String(user.id), username: String(user.username || u), name: String(user.name || '') };
|
|
17
|
+
} catch (e) {
|
|
18
|
+
return { kind: 'exception', detail: String(e && e.message || e) };
|
|
19
|
+
}
|
|
20
|
+
})()`);if(e?.kind==="auth")throw new n("linux.do",e.detail);if(e?.kind==="http")throw new i(`HTTP ${e.httpStatus} from Linux.do /u/<self>.json`);if(e?.kind==="exception")throw new i(`Linux.do whoami failed: ${e.detail}`);if(!e?.ok)throw new i(`Unexpected Linux.do probe: ${JSON.stringify(e)}`);return{user_id:e.user_id,username:e.username,name:e.name}}s({site:"linux-do",domain:"linux.do",loginUrl:"https://linux.do/login",columns:["user_id","username","name"],quickCheck:o,verify:u,poll:async(t)=>{if(!await o(t))throw new n("linux.do","Waiting for Linux.do _t cookie");return u(t)}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as l,Strategy as d}from"@jackwener/opencli/registry";import{fetchLinuxDoJson as c}from"./feed.js";l({site:"linux-do",name:"categories",access:"read",description:"linux.do 分类列表",domain:"linux.do",strategy:d.COOKIE,browser:!0,args:[{name:"subcategories",type:"boolean",default:!1,help:"Include subcategories"},{name:"limit",type:"int",default:20,help:"Number of categories"}],columns:["name","slug","id","topics","description"],func:async(i,o)=>{const n=(await c(i,"/categories.json"))?.category_list?.categories||[],r=!!o.subcategories,a=o.limit,e=[];for(const t of n){if(e.length>=a)break;e.push({name:t.name,slug:t.slug,id:t.id,topics:t.topic_count,description:(t.description_text||"").slice(0,80)});if(r&&Array.isArray(t.subcategory_ids)&&t.subcategory_ids.length>0){const u=(await c(i,`/categories.json?parent_category_id=${t.id}`,{skipNavigate:!0}))?.category_list?.categories||[];for(const s of u){if(e.length>=a)break;e.push({name:t.name+" / "+s.name,slug:s.slug,id:s.id,topics:s.topic_count,description:(s.description_text||"").slice(0,80)})}}}return e}});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import*as q from"node:fs";import*as k from"node:os";import*as V from"node:path";import{ArgumentError as A,AuthRequiredError as h,CommandExecutionError as I}from"@jackwener/opencli/errors";import{cli as C,Strategy as w}from"@jackwener/opencli/registry";const v="https://linux.do",y=86400000;let G=null,N=null,b=null,R=null,M=null;function F(Q){return Q.trim().replace(/\s+/g," ").toLowerCase()}function m(){return process.env.HOME||process.env.USERPROFILE||k.homedir()}function O(){return M??V.join(m(),".opencli","cache","linux-do")}function S(Q){return V.join(O(),`${Q}.json`)}async function x(Q){try{const W=await q.promises.readFile(S(Q),"utf-8"),Y=JSON.parse(W);if(!Y||!Array.isArray(Y.data)||typeof Y.fetchedAt!=="string")return null;const $=new Date(Y.fetchedAt).getTime(),Z=Number.isFinite($)&&Date.now()-$<y;return{data:Y.data,fresh:Z}}catch{return null}}async function E(Q,W){try{const Y=O();await q.promises.mkdir(Y,{recursive:!0});const $={fetchedAt:new Date().toISOString(),data:W};await q.promises.writeFile(S(Q),JSON.stringify($,null,2)+`
|
|
2
|
+
`)}catch{}}async function f(Q){if(!Q)throw new I("Browser page required");await Q.goto(v);await Q.wait(2)}export async function fetchLinuxDoJson(Q,W,Y={}){if(!Y.skipNavigate)await f(Q);if(!Q)throw new I("Browser page required");const $=JSON.stringify(W),Z=await Q.evaluate(`(async () => {
|
|
3
|
+
try {
|
|
4
|
+
const res = await fetch(${$}, { credentials: 'include' });
|
|
5
|
+
let data = null;
|
|
6
|
+
try { data = await res.json(); } catch {}
|
|
7
|
+
return {
|
|
8
|
+
ok: res.ok,
|
|
9
|
+
status: res.status,
|
|
10
|
+
data,
|
|
11
|
+
error: data === null ? 'Response is not valid JSON' : '',
|
|
12
|
+
};
|
|
13
|
+
} catch (error) {
|
|
14
|
+
return {
|
|
15
|
+
ok: false,
|
|
16
|
+
error: error instanceof Error ? error.message : String(error),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
})()`);if(!Z)throw new I("linux.do returned an empty browser response");if(Z.status===401||Z.status===403)throw new h("linux.do","linux.do requires an active signed-in browser session");if(!Z.ok)throw new I(Z.error||`linux.do request failed: HTTP ${Z.status??"unknown"}`);if(Z.error)throw new I(Z.error,"Please verify your linux.do session is still valid");return Z.data}function n(Q,W){const Y=W.trim(),$=F(W);return/^\d+$/.test(Y)?Q.find((Z)=>Z.id===Number(Y))??null:Q.find((Z)=>F(Z.name)===$)??Q.find((Z)=>F(Z.slug)===$)??null}function p(Q,W){const Y=W.trim(),$=F(W);return/^\d+$/.test(Y)?Q.find((Z)=>Z.id===Number(Y))??null:Q.find((Z)=>d(Z).includes($))??null}function d(Q){const W=[Q.name,Q.slug];if(Q.parent)W.push(`${Q.parent.name} / ${Q.name}`,`${Q.parent.name}/${Q.name}`,`${Q.parent.name}, ${Q.name}`);return W.map(F)}function P(Q,W){return{id:Q.id,name:Q.name??"",description:Q.description_text??Q.description??"",slug:Q.slug??"",parentCategoryId:W?.id??null,parent:W}}async function l(Q){if(b)return b;if(!G)G=(async()=>{const W=await x("tags");if(W?.fresh)return W.data;try{const Y=await fetchLinuxDoJson(Q,"/tags.json",{skipNavigate:!0}),$=(Array.isArray(Y?.tags)?Y.tags:[]).filter((Z)=>!!Z&&typeof Z.id==="number").map((Z)=>({id:Z.id,slug:Z.slug??`${Z.id}-tag`,name:Z.name??String(Z.id)}));await E("tags",$);return $}catch(Y){if(W)return W.data;G=null;throw Y}})().catch((W)=>{G=null;throw W});return G}async function u(Q){if(R)return R;if(!N)N=(async()=>{const W=await x("categories");if(W?.fresh)return W.data;try{const Y=await fetchLinuxDoJson(Q,"/categories.json",{skipNavigate:!0}),$=Array.isArray(Y?.category_list?.categories)?Y.category_list.categories:[],Z=$.map((B)=>P(B,null)),U=new Map(Z.map((B)=>[B.id,B])),X=await Promise.allSettled($.filter((B)=>Array.isArray(B.subcategory_ids)&&B.subcategory_ids.length>0).map(async(B)=>{const j=await fetchLinuxDoJson(Q,`/categories.json?parent_category_id=${B.id}`,{skipNavigate:!0}),J=Array.isArray(j?.category_list?.categories)?j.category_list.categories:[],z=U.get(B.id)??null;return J.map((H)=>P(H,z))})),K=[...Z,...X.flatMap((B)=>B.status==="fulfilled"?B.value:[])];await E("categories",K);return K}catch(Y){if(W)return W.data;throw Y}})().catch((W)=>{N=null;throw W});return N}function c(Q){if(!Q)return"";const W=new Date(Q);if(isNaN(W.getTime()))return Q;return W.toLocaleString()}function i(Q){return Math.max(0,(typeof Q==="number"?Q:1)-1)}function s(Q,W){return(Q?.topic_list?.topics??[]).slice(0,W).map(($)=>({title:$.fancy_title??$.title??"",replies:i($.posts_count),created:c($.created_at),likes:$.like_count??0,views:$.views??0,url:`https://linux.do/t/topic/${$.id}`}))}async function g(Q,W){const Y=n(await l(Q),W);if(Y)return Y;throw new A(`Unknown tag: ${W}`,'Use "opencli linux-do tags" to list available tags')}async function o(Q,W){const Y=p(await u(Q),W);if(Y)return Y;throw new A(`Unknown category: ${W}`,'Use "opencli linux-do categories" to list available categories')}async function D(Q,W){const Y=W.view||"latest",$=W.period||"weekly";if(W.period&&Y!=="top")throw new A("--period is only valid with --view top");const Z=new URLSearchParams;if(W.order&&W.order!=="default")Z.set("order",W.order);if(W.ascending)Z.set("ascending","true");if(W.limit)Z.set("per_page",String(W.limit));const U=typeof W.tag==="string"?W.tag.trim():"",X=typeof W.category==="string"?W.category.trim():"";if(!U&&!X){const _=new URLSearchParams(Z);if(Y==="top")_.set("period",$);const T=_.toString()?`?${_.toString()}`:"";return{url:`${Y==="latest"?"/latest.json":Y==="hot"?"/hot.json":"/top.json"}${T}`}}const K=U?await g(Q,U):null,B=X?await o(Q,X):null,j=B?(B.parent?[B.parent.slug,B.slug,String(B.id)]:[B.slug,String(B.id)]).map(encodeURIComponent).join("/"):"",J=K?`${encodeURIComponent(K.slug||`${K.id}-tag`)}/${K.id}`:"",z=B&&K?`/tags/c/${j}/${J}`:B?`/c/${j}`:`/tag/${J}`,H=new URLSearchParams(Z);if(Y==="top")H.set("period",$);const L=H.toString()?`?${H.toString()}`:"";return{url:`${z}${Y==="latest"?".json":`/l/${Y}.json`}${L}`}}export const LINUX_DO_FEED_ARGS=[{name:"view",type:"str",default:"latest",help:"View type",choices:["latest","hot","top"]},{name:"tag",type:"str",help:"Tag name, slug, or id"},{name:"category",type:"str",help:"Category name, slug, id, or parent/name path"},{name:"limit",type:"int",default:20,help:"Number of items (per_page)"},{name:"order",type:"str",default:"default",help:"Sort order",choices:["default","created","activity","views","posts","category","likes","op_likes","posters"]},{name:"ascending",type:"boolean",default:!1,help:"Sort ascending (default: desc)"},{name:"period",type:"str",help:"Time period (only for --view top)",choices:["all","daily","weekly","monthly","quarterly","yearly"]}];async function t(Q,W){const Y=W.limit||20;await f(Q);const $=await D(Q,W),Z=await fetchLinuxDoJson(Q,$.url,{skipNavigate:!0});return s(Z,Y)}C({site:"linux-do",name:"feed",access:"read",description:"linux.do 话题列表(需登录;支持全站、标签、分类)",domain:"linux.do",strategy:w.COOKIE,browser:!0,columns:["title","replies","created","likes","views","url"],args:LINUX_DO_FEED_ARGS,func:t});export const __test__={resetMetadataCaches(){G=null;N=null;b=null;R=null;M=null},setLiveMetadataForTests({tags:Q,categories:W}){G=null;N=null;b=Q??null;R=W??null},setCacheDirForTests(Q){M=Q},resolveFeedRequest:D};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as o,Strategy as n}from"@jackwener/opencli/registry";import{fetchLinuxDoJson as l}from"./feed.js";o({site:"linux-do",name:"search",access:"read",description:"搜索 linux.do",domain:"linux.do",strategy:n.COOKIE,browser:!0,args:[{name:"query",required:!0,positional:!0,help:"Search query"},{name:"limit",type:"int",default:20,help:"Number of results"}],columns:["rank","title","views","likes","replies","url"],func:async(i,t)=>{const r=encodeURIComponent(String(t.query));return((await l(i,`/search.json?q=${r}`))?.topics||[]).slice(0,t.limit).map((e,s)=>({rank:s+1,title:e.title,views:e.views,likes:e.like_count,replies:(e.posts_count||1)-1,url:"https://linux.do/t/topic/"+e.id}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as i,Strategy as u}from"@jackwener/opencli/registry";import{fetchLinuxDoJson as e}from"./feed.js";i({site:"linux-do",name:"tags",access:"read",description:"linux.do 标签列表",domain:"linux.do",strategy:u.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:30,help:"Number of tags"}],columns:["rank","name","slug","count","url"],func:async(s,o)=>{const n=(await e(s,"/tags.json"))?.tags||[];n.sort((t,a)=>(a.count||0)-(t.count||0));return n.slice(0,o.limit).map((t,a)=>({rank:a+1,name:t.name||t.id,count:t.count||0,slug:t.slug,id:t.id,url:"https://linux.do/tag/"+t.slug}))}});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import{AuthRequiredError as Y,CommandExecutionError as W,EmptyResultError as q}from"@jackwener/opencli/errors";import{cli as X,Strategy as h}from"@jackwener/opencli/registry";import{htmlToMarkdown as b,isRecord as $}from"@jackwener/opencli/utils";const H="linux.do",f="https://linux.do";function z(F){if(!F)return"";const G=new Date(F);return Number.isNaN(G.getTime())?F:G.toLocaleString()}function Q(F){if(!$(F))return null;const G=$(F.post_stream)?{posts:Array.isArray(F.post_stream.posts)?F.post_stream.posts.filter($).map((B)=>({post_number:typeof B.post_number==="number"?B.post_number:void 0,username:typeof B.username==="string"?B.username:void 0,raw:typeof B.raw==="string"?B.raw:void 0,cooked:typeof B.cooked==="string"?B.cooked:void 0,like_count:typeof B.like_count==="number"?B.like_count:void 0,created_at:typeof B.created_at==="string"?B.created_at:void 0})):void 0}:void 0;return{title:typeof F.title==="string"?F.title:void 0,post_stream:G}}function j(F){const G=[],B=[["title",F.title||void 0],["author",F.author||void 0],["likes",typeof F.likes==="number"&&Number.isFinite(F.likes)?F.likes:void 0],["createdAt",F.createdAt||void 0],["url",F.url||void 0]];for(const[J,K]of B){if(K===void 0)continue;if(typeof K==="number")G.push(`${J}: ${K}`);else{const Z=/[#{}[\],&*?|>!%@`'"]/.test(K)||/: /.test(K)||/:$/.test(K)||K.includes(`
|
|
2
|
+
`);G.push(`${J}: ${Z?`'${K.replace(/'/g,"''")}'`:K}`)}}const V=G.join(`
|
|
3
|
+
`);return[V?`---
|
|
4
|
+
${V}
|
|
5
|
+
---`:"",F.body.trim()].filter(Boolean).join(`
|
|
6
|
+
|
|
7
|
+
`).trim()}function U(F,G){const B=Q(F);if(!B)throw new W("linux.do returned an unexpected topic payload");const J=(B.post_stream?.posts??[]).find((Z)=>Z.post_number===1);if(!J)throw new q("linux-do/topic-content",`Could not find the main post for topic ${G}.`);const K=typeof J.raw==="string"&&J.raw.trim()?J.raw.trim():b(J.cooked??"");if(!K)throw new q("linux-do/topic-content",`Topic ${G} does not contain a readable main post body.`);return{content:j({title:B.title?.trim()??"",author:J.username?.trim()??"",likes:typeof J.like_count==="number"?J.like_count:void 0,createdAt:z(J.created_at??""),url:`${f}/t/${G}`,body:K})}}async function A(F,G){const B=await F.evaluate(`(async () => {
|
|
8
|
+
try {
|
|
9
|
+
const res = await fetch('/t/${G}.json?include_raw=true', { credentials: 'include' });
|
|
10
|
+
let data = null;
|
|
11
|
+
try {
|
|
12
|
+
data = await res.json();
|
|
13
|
+
} catch (_error) {
|
|
14
|
+
data = null;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
ok: res.ok,
|
|
18
|
+
status: res.status,
|
|
19
|
+
data,
|
|
20
|
+
error: data === null ? 'Response is not valid JSON' : '',
|
|
21
|
+
};
|
|
22
|
+
} catch (error) {
|
|
23
|
+
return {
|
|
24
|
+
ok: false,
|
|
25
|
+
error: error instanceof Error ? error.message : String(error),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
})()`);if(!B)throw new W("linux.do returned an empty browser response");if(B.status===401||B.status===403)throw new Y(H,"linux.do requires an active signed-in browser session");if(B.error==="Response is not valid JSON")throw new Y(H,"linux.do requires an active signed-in browser session");if(!B.ok)throw new W(B.error||`linux.do request failed: HTTP ${B.status??"unknown"}`);if(B.error)throw new W(B.error,"Please verify your linux.do session is still valid");return B.data}X({site:"linux-do",name:"topic-content",access:"read",description:"Get the main topic body as Markdown",domain:H,strategy:h.COOKIE,browser:!0,defaultFormat:"plain",args:[{name:"id",positional:!0,type:"int",required:!0,help:"Topic ID"}],columns:["content"],func:async(F,G)=>{const B=Number(G.id);if(!Number.isInteger(B)||B<=0)throw new W(`Invalid linux.do topic id: ${String(G.id??"")}`);const V=await A(F,B);return[U(V,B)]}});export const __test__={buildTopicMarkdownDocument:j,extractTopicContent:U,normalizeTopicPayload:Q,toLocalTime:z};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as o,Strategy as n}from"@jackwener/opencli/registry";import{fetchLinuxDoJson as c}from"./feed.js";function s(e){if(!e)return"";const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()}function l(e){return(e||"").replace(/<br\s*\/?>/gi," ").replace(/<\/(p|div|li|blockquote|h[1-6])>/gi," ").replace(/<[^>]+>/g,"").replace(/ /g," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/&#(?:(\d+)|x([0-9a-fA-F]+));/g,(t,a,i)=>{try{return String.fromCodePoint(a!==void 0?Number(a):parseInt(i,16))}catch{return""}}).replace(/\s+/g," ").trim()}o({site:"linux-do",name:"topic",access:"read",description:"linux.do 帖子首页摘要和回复(首屏)",domain:"linux.do",strategy:n.COOKIE,browser:!0,args:[{name:"id",type:"int",required:!0,positional:!0,help:"Topic ID"},{name:"limit",type:"int",default:20,help:"Number of posts"}],columns:["author","content","likes","created_at"],func:async(e,t)=>{return((await c(e,`/t/${t.id}.json`))?.post_stream?.posts||[]).slice(0,t.limit).map((r)=>({author:r.username,content:l(r.cooked).slice(0,200),likes:r.like_count,created_at:s(r.created_at)}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as s,Strategy as a}from"@jackwener/opencli/registry";import{fetchLinuxDoJson as c}from"./feed.js";function u(e){if(!e)return"";const r=new Date(e);return Number.isNaN(r.getTime())?e:r.toLocaleString()}function l(e){return(e||"").replace(/<br\s*\/?>/gi," ").replace(/<\/(p|div|li|blockquote|h[1-6])>/gi," ").replace(/<[^>]+>/g,"").replace(/ /g," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/&#(?:(\d+)|x([0-9a-fA-F]+));/g,(r,i,n)=>{try{return String.fromCodePoint(i!==void 0?Number(i):parseInt(n,16))}catch{return""}}).replace(/\s+/g," ").trim()}s({site:"linux-do",name:"user-posts",access:"read",description:"linux.do 用户的帖子",domain:"linux.do",strategy:a.COOKIE,browser:!0,args:[{name:"username",required:!0,positional:!0,help:"Username"},{name:"limit",type:"int",default:20,help:"Number of posts"}],columns:["index","topic_user","topic","reply","time","url"],func:async(e,r)=>{const i=String(r.username),n=r.limit;return((await c(e,`/user_actions.json?username=${encodeURIComponent(i)}&filter=5&offset=0&limit=${n}`))?.user_actions||[]).slice(0,n).map((t,o)=>({index:o+1,topic_user:t.acting_username||t.username||"",topic:t.title||"",reply:l(t.excerpt).slice(0,200),time:u(t.created_at),url:"https://linux.do/t/topic/"+t.topic_id+"/"+t.post_number}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as r,Strategy as a}from"@jackwener/opencli/registry";import{fetchLinuxDoJson as c}from"./feed.js";function l(t){if(!t)return"";const i=new Date(t);return Number.isNaN(i.getTime())?t:i.toLocaleString()}r({site:"linux-do",name:"user-topics",access:"read",description:"linux.do 用户创建的话题",domain:"linux.do",strategy:a.COOKIE,browser:!0,args:[{name:"username",required:!0,positional:!0,help:"Username"},{name:"limit",type:"int",default:20,help:"Number of topics"}],columns:["rank","title","replies","created_at","likes","views","url"],func:async(t,i)=>{const n=String(i.username),o=i.limit;return((await c(t,`/topics/created-by/${encodeURIComponent(n)}.json`))?.topic_list?.topics||[]).slice(0,o).map((e,s)=>({rank:s+1,title:e.fancy_title||e.title||"",replies:e.posts_count||0,created_at:l(e.created_at),likes:e.like_count||0,views:e.views||0,url:"https://linux.do/t/topic/"+e.id}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as t,Strategy as e}from"@jackwener/opencli/registry";t({site:"lobsters",name:"active",access:"read",description:"Lobste.rs most active discussions",domain:"lobste.rs",strategy:e.PUBLIC,browser:!1,args:[{name:"limit",type:"int",default:20,help:"Number of stories"}],columns:["rank","id","title","score","author","comments","created_at","tags","url"],pipeline:[{fetch:{url:"https://lobste.rs/active.json"}},{map:{rank:"${{ index + 1 }}",id:"${{ item.short_id }}",title:"${{ item.title }}",score:"${{ item.score }}",author:"${{ item.submitter_user }}",comments:"${{ item.comment_count }}",created_at:"${{ item.created_at }}",tags:"${{ item.tags | join(', ') }}",url:"${{ item.comments_url }}"}},{limit:"${{ args.limit }}"}]});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as d,Strategy as b}from"@jackwener/opencli/registry";import{ArgumentError as i,CommandExecutionError as m,EmptyResultError as u}from"@jackwener/opencli/errors";const h=/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)+$/i;function g(o){const e=String(o??"").trim().toLowerCase();if(!e)throw new i('lobsters domain is required (e.g. "github.com" or "arxiv.org")');if(!h.test(e))throw new i(`lobsters domain "${o}" is not a valid hostname`);return e}function f(o,e,n){const s=o??e,r=typeof s==="number"?s:Number(s);if(!Number.isInteger(r)||r<=0)throw new i("lobsters limit must be a positive integer");if(r>n)throw new i(`lobsters limit must be <= ${n}`);return r}d({site:"lobsters",name:"domain",access:"read",description:"Lobste.rs stories submitted from a specific domain",domain:"lobste.rs",strategy:b.PUBLIC,browser:!1,args:[{name:"domain",positional:!0,required:!0,help:"Source domain (e.g. github.com, arxiv.org, blog.cloudflare.com)"},{name:"limit",type:"int",default:20,help:"Number of stories (1-25 — single page)"}],columns:["rank","id","title","score","author","comments","created_at","tags","submission_url","comments_url"],func:async(o)=>{const e=g(o.domain),n=f(o.limit,20,25),s=`https://lobste.rs/domains/${encodeURIComponent(e)}.json`;let r;try{r=await fetch(s,{headers:{"user-agent":"opencli-lobsters-adapter (+https://github.com/jackwener/opencli)"}})}catch(t){throw new m(`lobsters domain request failed: ${t?.message??t}`,"Check that lobste.rs is reachable from this network.")}if(r.status===404)throw new u("lobsters domain",`No Lobste.rs stories found for domain "${e}".`);if(!r.ok)throw new m(`lobsters domain returned HTTP ${r.status}`);let a;try{a=await r.json()}catch(t){throw new m(`lobsters domain returned malformed JSON: ${t?.message??t}`)}const l=Array.isArray(a)?a:[];if(!l.length)throw new u("lobsters domain",`No Lobste.rs stories found for domain "${e}".`);return l.slice(0,n).map((t,c)=>({rank:c+1,id:String(t.short_id??""),title:String(t.title??""),score:t.score!=null?Number(t.score):null,author:String(t.submitter_user??""),comments:t.comment_count!=null?Number(t.comment_count):null,created_at:String(t.created_at??"").slice(0,10),tags:Array.isArray(t.tags)?t.tags.join(", "):"",submission_url:String(t.url??""),comments_url:String(t.comments_url??"")}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as t,Strategy as e}from"@jackwener/opencli/registry";t({site:"lobsters",name:"hot",access:"read",description:"Lobste.rs hottest stories",domain:"lobste.rs",strategy:e.PUBLIC,browser:!1,args:[{name:"limit",type:"int",default:20,help:"Number of stories"}],columns:["rank","id","title","score","author","comments","created_at","tags","url"],pipeline:[{fetch:{url:"https://lobste.rs/hottest.json"}},{map:{rank:"${{ index + 1 }}",id:"${{ item.short_id }}",title:"${{ item.title }}",score:"${{ item.score }}",author:"${{ item.submitter_user }}",comments:"${{ item.comment_count }}",created_at:"${{ item.created_at }}",tags:"${{ item.tags | join(', ') }}",url:"${{ item.comments_url }}"}},{limit:"${{ args.limit }}"}]});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as t,Strategy as e}from"@jackwener/opencli/registry";t({site:"lobsters",name:"newest",access:"read",description:"Lobste.rs newest stories",domain:"lobste.rs",strategy:e.PUBLIC,browser:!1,args:[{name:"limit",type:"int",default:20,help:"Number of stories"}],columns:["rank","id","title","score","author","comments","created_at","tags","url"],pipeline:[{fetch:{url:"https://lobste.rs/newest.json"}},{map:{rank:"${{ index + 1 }}",id:"${{ item.short_id }}",title:"${{ item.title }}",score:"${{ item.score }}",author:"${{ item.submitter_user }}",comments:"${{ item.comment_count }}",created_at:"${{ item.created_at }}",tags:"${{ item.tags | join(', ') }}",url:"${{ item.comments_url }}"}},{limit:"${{ args.limit }}"}]});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import{cli as T,Strategy as E}from"@jackwener/opencli/registry";import{ArgumentError as Y,CommandExecutionError as w,EmptyResultError as P}from"@jackwener/opencli/errors";const R="https://lobste.rs/s";async function x(z){const F=await fetch(`${R}/${z}.json`);if(F.status===404)throw new P(`lobsters/${z}`,"Story not found");if(!F.ok)throw new w(`Lobsters API HTTP ${F.status} for story ${z}`,"Check the short id");return F.json()}function j(z,F){if(!Number.isInteger(z)||z<=0)throw new Y(`${F} must be a positive integer`);return z}function I(z,F,U){if(!Number.isInteger(z)||z<F)throw new Y(`${U} must be an integer >= ${F}`);return z}function k(z){if(!z)return"";return String(z).replace(/<p>/gi,`
|
|
2
|
+
|
|
3
|
+
`).replace(/<\/p>/gi,"").replace(/<br\s*\/?>/gi,`
|
|
4
|
+
`).replace(/<i>(.*?)<\/i>/gi,"$1").replace(/<em>(.*?)<\/em>/gi,"$1").replace(/<strong>(.*?)<\/strong>/gi,"$1").replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gi,"$2 ($1)").replace(/<pre><code>([\s\S]*?)<\/code><\/pre>/gi,`
|
|
5
|
+
$1
|
|
6
|
+
`).replace(/<code>(.*?)<\/code>/gi,"`$1`").replace(/<[^>]+>/g,"").replace(/'/g,"'").replace(/'/g,"'").replace(/"/g,'"').replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&").replace(/ /g," ").replace(///g,"/").trim()}function v(z,F){if(F===0)return z;const X=`${" ".repeat(F)}> `;return z.split(`
|
|
7
|
+
`).map((Z)=>X+Z).join(`
|
|
8
|
+
`)}function B(z){return" ".repeat(z+1)}T({site:"lobsters",name:"read",access:"read",description:"Read a Lobste.rs story and its comment tree",domain:"lobste.rs",strategy:E.PUBLIC,browser:!1,args:[{name:"id",required:!0,positional:!0,help:"Lobste.rs short_id (e.g. 6cmh6h)"},{name:"limit",type:"int",default:25,help:"Max top-level comments"},{name:"depth",type:"int",default:2,help:"Max reply depth (1=no replies, 2=one level of replies, etc.)"},{name:"replies",type:"int",default:5,help:"Max replies shown per comment at each level"},{name:"max-length",type:"int",default:2000,help:"Max characters per comment body (min 100)"}],columns:["type","author","score","text"],func:async(z)=>{const F=String(z.id||"").trim();if(!/^[a-z0-9]+$/.test(F))throw new Y(`Invalid Lobsters short_id: ${z.id}`,"Pass a lowercase alphanumeric id like 6cmh6h");const U=j(z.limit??25,"lobsters read --limit"),X=j(z.depth??2,"lobsters read --depth"),Z=j(z.replies??5,"lobsters read --replies"),V=I(z["max-length"]??2000,100,"lobsters read --max-length"),J=await x(F);if(!J||!J.short_id)throw new P(`lobsters/${F}`,"Story not found");const K=[],$=(J.description_plain||k(J.description||"")).trim(),C=$.length>V?$.slice(0,V)+`
|
|
9
|
+
... [truncated]`:$,D=[J.title||""];if(C)D.push(`
|
|
10
|
+
`+C);if(J.url)D.push(`
|
|
11
|
+
`+J.url);K.push({type:"POST",author:J.submitter_user||"[deleted]",score:J.score??0,text:D.join("").trim()});const b=Array.isArray(J.comments)?J.comments:[],Q=new Map;for(const G of b){const H=G.parent_comment||null;if(!Q.has(H))Q.set(H,[]);Q.get(H).push(G)}function O(G,H){if(!G||G.is_deleted||G.is_moderated)return;const N=(G.comment_plain||k(G.comment||"")).trim(),L=N.length>V?N.slice(0,V)+"...":N;K.push({type:H===0?"L0":`L${H}`,author:G.commenting_user||"[deleted]",score:G.score??"",text:v(L,H)});const W=Q.get(G.short_id)||[];if(H+1>=X){if(W.length>0)K.push({type:`L${H+1}`,author:"",score:"",text:`${B(H)}[+${W.length} more replies]`});return}const A=W.slice(0,Z);for(const S of A)O(S,H+1);const M=W.length-A.length;if(M>0)K.push({type:`L${H+1}`,author:"",score:"",text:`${B(H)}[+${M} more replies]`})}const _=Q.get(null)||[],q=_.slice(0,U);for(const G of q)O(G,0);const f=_.length-q.length;if(f>0)K.push({type:"",author:"",score:"",text:`[+${f} more top-level comments]`});return K}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as t,Strategy as e}from"@jackwener/opencli/registry";t({site:"lobsters",name:"tag",access:"read",description:"Lobste.rs stories by tag",domain:"lobste.rs",strategy:e.PUBLIC,browser:!1,args:[{name:"tag",required:!0,positional:!0,help:"Tag name (e.g. programming, rust, security, ai)"},{name:"limit",type:"int",default:20,help:"Number of stories"}],columns:["rank","id","title","score","author","comments","created_at","tags","url"],pipeline:[{fetch:{url:"https://lobste.rs/t/${{ args.tag }}.json"}},{map:{rank:"${{ index + 1 }}",id:"${{ item.short_id }}",title:"${{ item.title }}",score:"${{ item.score }}",author:"${{ item.submitter_user }}",comments:"${{ item.comment_count }}",created_at:"${{ item.created_at }}",tags:"${{ item.tags | join(', ') }}",url:"${{ item.comments_url }}"}},{limit:"${{ args.limit }}"}]});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import{AuthRequiredError as J,CommandExecutionError as F}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as K}from"../_shared/site-auth.js";const L=`(async () => {
|
|
2
|
+
try {
|
|
3
|
+
const scripts = Array.from(document.querySelectorAll('script')).map(s => s.textContent || '');
|
|
4
|
+
let user = null;
|
|
5
|
+
for (const s of scripts) {
|
|
6
|
+
const m = s.match(/userObj\\s*=\\s*JSON\\.parse\\('(\\{[\\s\\S]*?\\})'\\)/);
|
|
7
|
+
if (m) { try { user = JSON.parse(m[1]); } catch {} break; }
|
|
8
|
+
}
|
|
9
|
+
if (!user || !user.id) return { kind: 'auth', detail: 'Maimai userObj missing from page (anonymous)' };
|
|
10
|
+
return {
|
|
11
|
+
ok: true,
|
|
12
|
+
user_id: String(user.id),
|
|
13
|
+
name: String(user.name || ''),
|
|
14
|
+
company: String(user.company || ''),
|
|
15
|
+
};
|
|
16
|
+
} catch (e) {
|
|
17
|
+
return { kind: 'exception', detail: String(e && e.message || e) };
|
|
18
|
+
}
|
|
19
|
+
})()`;async function G(D){await D.goto("https://maimai.cn/");await D.wait(2);const z=await D.evaluate(L);if(z?.kind==="auth")throw new J("maimai.cn",z.detail);if(z?.kind==="http")throw new F(`HTTP ${z.httpStatus} from Maimai`);if(z?.kind==="exception")throw new F(`Maimai whoami failed: ${z.detail}`);if(!z?.ok)throw new F(`Unexpected Maimai probe: ${JSON.stringify(z)}`);return{user_id:z.user_id,name:z.name,company:z.company}}K({site:"maimai",domain:"maimai.cn",loginUrl:"https://maimai.cn/",columns:["user_id","name","company"],verify:G,poll:G});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import{cli as k,Strategy as C}from"@jackwener/opencli/registry";import{CommandExecutionError as T,EmptyResultError as y}from"@jackwener/opencli/errors";k({site:"maimai",name:"search-talents",access:"read",description:"Search for candidates on Maimai with multi-dimensional filters",domain:"maimai.cn",strategy:C.COOKIE,browser:!0,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g., "Java", "产品经理")'},{name:"page",type:"int",default:0,help:"Page number (0-based)"},{name:"size",type:"int",default:20,help:"Results per page"},{name:"positions",help:'Positions (e.g., "运营", "Java 开发工程师")'},{name:"companies",help:'Companies, comma-separated (e.g., "百度", "字节跳动,阿里巴巴")'},{name:"schools",help:'Schools, comma-separated (e.g., "北京大学", "清华大学,复旦大学")'},{name:"provinces",help:'Provinces (e.g., "北京", "上海")'},{name:"cities",help:'Cities (e.g., "北京市", "上海市")'},{name:"worktimes",help:"Work years: 1=1-3y, 2=3-5y, 3=5-10y, 4=10+y"},{name:"degrees",help:"Education: 1=大专,2=本科,3=硕士,4=博士,5=MBA"},{name:"professions",help:"Industries: 01=互联网,02=金融,03=电子,04=通信"},{name:"is_211",type:"int",help:"211 university: 0=any, 1=211"},{name:"is_985",type:"int",help:"985 university: 0=any, 1=985"},{name:"sortby",type:"int",default:0,help:"Sort: 0=relevance, 1=activity, 2=work_years, 3=education"},{name:"is_direct_chat",type:"int",default:0,help:"Direct chat: 0=any, 1=available"}],columns:["name","job_title","company","historical_companies","location","work_year","school","degree","active_status","age","tags","mutual_friends"],func:async(H,U)=>{const{query:M,page:V=0,size:W=20,positions:X="",companies:Z="",schools:$="",provinces:b="",cities:z="",worktimes:B="",degrees:N="",professions:R="",is_211:S=0,is_985:Y=0,sortby:j=0,is_direct_chat:q=0}=U;await H.goto("https://maimai.cn/ent/talents/discover/search_v2",{waitUntil:"networkidle"});await H.waitForTimeout(5000);const v="b92d0fb5-f3fd-1f4b-fcdc-"+Math.random().toString(16).slice(2,14),x="ae907d75-315c-8db7-2cc7-"+Math.random().toString(16).slice(2,14),I={search:{page:V,size:W,sessionid:v,deletesessionid:x,worktimes:B,degrees:N,professions:R,schools:$,positions:X,companyscope:0,sortby:j,is_direct_chat:q,query:M,cities:z,provinces:b,is_211:S,is_985:Y,allcompanies:Z}},F=(await H.getCookies({url:"https://maimai.cn"})).find((A)=>A.name==="csrftoken")?.value||"",G=await H.evaluate(`async () => {
|
|
2
|
+
// Prefer cookie-derived csrftoken (hoisted from CDP); fall back to meta tag
|
|
3
|
+
let csrftoken = ${JSON.stringify(F)};
|
|
4
|
+
|
|
5
|
+
if (!csrftoken) {
|
|
6
|
+
const meta = document.querySelector('meta[name="csrf-token"]');
|
|
7
|
+
if (meta) csrftoken = meta.getAttribute('content') || '';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const body = ${JSON.stringify(I)};
|
|
11
|
+
|
|
12
|
+
const res = await fetch('https://maimai.cn/api/ent/discover/search?channel=www&data_version=3.0&version=1.0.0', {
|
|
13
|
+
method: 'POST',
|
|
14
|
+
headers: {
|
|
15
|
+
'accept': '*/*',
|
|
16
|
+
'content-type': 'text/plain;charset=UTF-8',
|
|
17
|
+
'origin': 'https://maimai.cn',
|
|
18
|
+
'referer': 'https://maimai.cn/ent/talents/discover/search_v2',
|
|
19
|
+
'x-csrf-token': csrftoken,
|
|
20
|
+
},
|
|
21
|
+
credentials: 'include',
|
|
22
|
+
body: JSON.stringify(body),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const result = await res.json();
|
|
26
|
+
|
|
27
|
+
// Check login status
|
|
28
|
+
if (res.status === 401 || res.status === 403 || result.error_code === 20002) {
|
|
29
|
+
throw new Error('需要登录!请先在浏览器中访问 maimai.cn 并登录');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (result.code !== 200 && result.code !== 0) {
|
|
33
|
+
throw new Error(result.message || result.error || 'API 请求失败');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result;
|
|
37
|
+
}`);if(!G||typeof G!=="object"||Array.isArray(G))throw new T("Maimai search returned malformed API payload");const K=[G.data?.list,G.data?.talent_list,G.list,G.talent_list].find((A)=>Array.isArray(A));if(!K)throw new T("Maimai search API payload missing talent list");if(K.length===0)throw new y("maimai search-talents",`未找到匹配 "${M}" 的候选人`);return K.map((A)=>{const J=A.edu&&A.edu.length>0?A.edu[0]:{},L=A.work_time||A.worktime||"",O=A.company||"",_=(A.exp||[]).map((D)=>D.company).filter((D)=>D&&D.trim()!==""&&D!==O).filter((D,h,E)=>E.indexOf(D)===h).join(" / "),w=(A.tag_list||A.tags||[]).filter((D)=>D&&D.trim()!=="").join(", "),P=A.friends_cnt||A.common_friends_count||0,Q=(A.friends||A.common_friends||[]).map((D)=>D.name||D.user_name||D).slice(0,3).join(", ");return{name:A.name||"",job_title:A.position||A.job_title||"",company:O,historical_companies:_,location:(A.province||"")+(A.city?"·"+A.city:""),work_year:L,school:J.school||J.hover?.name||"",degree:J.sdegree||J.hover?.school_level||"",active_status:A.active_state_v2||A.active_state_v1||A.active_state||"",age:A.age||"",tags:w,mutual_friends:P>0?`${P}人${Q?" ("+Q+")":""}`:""}})}});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import{ArgumentError as Q,AuthRequiredError as V,CommandExecutionError as K}from"@jackwener/opencli/errors";export const MANUS_DOMAIN="manus.im",MANUS_URL="https://manus.im/app",API_HOST="https://api.manus.im";export function isManusUrl(z){try{const G=new URL(String(z||"")),B=G.hostname.toLowerCase();return G.protocol==="https:"&&(B===MANUS_DOMAIN||B===`www.${MANUS_DOMAIN}`)}catch{return!1}}export function validatedLimit(z,G,B=1000){const J=z==null?G:Number(z);if(!Number.isFinite(J)||!Number.isInteger(J)||J<1||J>B)throw new Q("limit",`must be a positive integer ≤ ${B}`);return J}export function unwrapEvaluateResult(z){if(z&&typeof z==="object"&&!Array.isArray(z)&&Object.prototype.hasOwnProperty.call(z,"session")&&Object.prototype.hasOwnProperty.call(z,"data"))return z.data;return z}function W(z){if(!z||typeof z!=="object")return"";return[z.message,z.error,z.errorMessage,z.details].find((B)=>typeof B==="string"&&B.trim())?.trim()||""}export function requireObject(z,G){const B=unwrapEvaluateResult(z);if(B?.__authRequired)throw new V(MANUS_DOMAIN,B.message||"Authentication required — please sign in to Manus in the browser");if(B?.__httpError){const J=W(B);throw new K(J?`Manus ${G} failed (HTTP ${B.__httpError}): ${J}`:`Manus ${G} failed (HTTP ${B.__httpError})`)}if(B?.__error)throw new K(`Manus ${G} failed: ${B.message||B.__error}`);if(!B||typeof B!=="object"||Array.isArray(B))throw new K(`Manus ${G} returned a malformed API payload`);return B}export function requireArray(z,G){if(!Array.isArray(z))throw new K(`Manus ${G} returned a malformed API payload`);return z}export function requireString(z,G){const B=String(z??"").trim();if(!B)throw new K(`Manus ${G} returned a malformed API payload`);return B}export async function ensureOnManus(z){const G=unwrapEvaluateResult(await z.evaluate("window.location.href").catch(()=>""));if(isManusUrl(G))return;await z.goto(MANUS_URL);await z.wait(2)}export const MANUS_API_CALL_JS=`
|
|
2
|
+
const callManusAPI = async (rpcPath, body) => {
|
|
3
|
+
const jwt = document.cookie.split('session_id=')[1]?.split(';')[0];
|
|
4
|
+
if (!jwt) return { __authRequired: true, message: 'session_id cookie missing' };
|
|
5
|
+
const r = await fetch('${API_HOST}/' + rpcPath, {
|
|
6
|
+
method: 'POST',
|
|
7
|
+
credentials: 'include',
|
|
8
|
+
headers: {
|
|
9
|
+
'Content-Type': 'application/json',
|
|
10
|
+
'Authorization': 'Bearer ' + jwt,
|
|
11
|
+
'Connect-Protocol-Version': '1',
|
|
12
|
+
},
|
|
13
|
+
body: JSON.stringify(body || {}),
|
|
14
|
+
});
|
|
15
|
+
if (!r.ok) {
|
|
16
|
+
const t = await r.text();
|
|
17
|
+
return {
|
|
18
|
+
__httpError: r.status,
|
|
19
|
+
message: t.slice(0, 200),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
return await r.json();
|
|
24
|
+
} catch (error) {
|
|
25
|
+
return { __error: 'invalid_json', message: error?.message || String(error) };
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
`;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import{AuthRequiredError as i,CommandExecutionError as n}from"@jackwener/opencli/errors";import{registerSiteAuthCommands as o}from"../_shared/site-auth.js";async function a(s){return(await s.getCookies({url:"https://manus.im"})).some((e)=>/^(auth_session|manus_token|_session|session)$/.test(e.name)&&e.value)}async function u(s){if(!await a(s))throw new i("manus.im","Manus session cookies missing — anonymous");await s.goto("https://manus.im/");await s.wait(3);const t=await s.evaluate(`(async () => {
|
|
2
|
+
try {
|
|
3
|
+
const r = await fetch('/api/auth/session', { credentials: 'include', headers: { Accept: 'application/json' } });
|
|
4
|
+
if (r.status === 401 || r.status === 403) {
|
|
5
|
+
return { kind: 'auth', detail: 'Manus /api/auth/session HTTP ' + r.status };
|
|
6
|
+
}
|
|
7
|
+
if (r.status === 503) {
|
|
8
|
+
return { kind: 'http', httpStatus: 503 };
|
|
9
|
+
}
|
|
10
|
+
if (!r.ok) return { kind: 'http', httpStatus: r.status };
|
|
11
|
+
const d = await r.json();
|
|
12
|
+
const u = d?.user || d;
|
|
13
|
+
if (!u || !(u.id || u.userId)) {
|
|
14
|
+
return { kind: 'auth', detail: 'Manus /api/auth/session 200 but no user' };
|
|
15
|
+
}
|
|
16
|
+
return { ok: true, user_id: String(u.id || u.userId), name: String(u.name || u.displayName || '') };
|
|
17
|
+
} catch (e) {
|
|
18
|
+
return { kind: 'exception', detail: String(e && e.message || e) };
|
|
19
|
+
}
|
|
20
|
+
})()`);if(t?.kind==="auth")throw new i("manus.im",t.detail);if(t?.kind==="http")throw new n(`HTTP ${t.httpStatus} from Manus /api/auth/session`);if(t?.kind==="exception")throw new n(`Manus whoami failed: ${t.detail}`);if(!t?.ok)throw new n(`Unexpected Manus probe: ${JSON.stringify(t)}`);return{user_id:t.user_id,name:t.name}}o({site:"manus",domain:"manus.im",loginUrl:"https://manus.im/login",columns:["user_id","name"],verify:u,poll:async(s)=>{if(!await a(s))throw new i("manus.im","Waiting for Manus session cookies");return u(s)}});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{cli as a,Strategy as m}from"@jackwener/opencli/registry";import{EmptyResultError as u}from"@jackwener/opencli/errors";import{MANUS_DOMAIN as l,ensureOnManus as f,MANUS_API_CALL_JS as d,requireArray as p,requireObject as y,requireString as o,validatedLimit as A}from"./_utils.js";a({site:"manus",name:"connectors",access:"read",description:"List available Manus connectors (integrations).",domain:l,strategy:m.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!0,args:[{name:"limit",type:"int",default:50,help:"Max connectors to return"}],columns:["UID","Name","Brief"],func:async(n,s)=>{const c=A(s?.limit,50,500);await f(n);const i=y(await n.evaluate(`(async () => {
|
|
2
|
+
${d}
|
|
3
|
+
return callManusAPI('connectors.v1.ConnectorsService/ListConnectors', {});
|
|
4
|
+
})()`),"connectors"),t=p(i.connectors,"connectors");if(!t.length)throw new u("manus connectors","No connectors found.");return t.slice(0,c).map((e,r)=>({UID:o(e?.uid,`connector ${r+1}`),Name:o(e?.name,`connector ${r+1}`),Brief:(e.brief||"—").slice(0,60)}))}});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{cli as i,Strategy as s}from"@jackwener/opencli/registry";import{CommandExecutionError as a}from"@jackwener/opencli/errors";import{MANUS_DOMAIN as d,ensureOnManus as l,MANUS_API_CALL_JS as n,requireObject as o}from"./_utils.js";i({site:"manus",name:"credits",access:"read",description:"Show Manus credit balance and refresh details.",domain:d,strategy:s.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!0,args:[],columns:["Field","Value"],func:async(r)=>{await l(r);const e=o(await r.evaluate(`(async () => {
|
|
2
|
+
${n}
|
|
3
|
+
return callManusAPI('user.v1.UserService/GetAvailableCredits', {});
|
|
4
|
+
})()`),"credits");if(!["totalCredits","freeCredits","periodicCredits","refreshCredits"].some((t)=>e[t]!=null))throw new a("Manus credits returned a malformed API payload");return[{Field:"Total Credits",Value:e.totalCredits??"—"},{Field:"Free Credits",Value:e.freeCredits??"—"},{Field:"Periodic Credits",Value:e.periodicCredits??"—"},{Field:"Pro Monthly Credits",Value:e.proMonthlyCredits??"—"},{Field:"Refresh Credits",Value:e.refreshCredits??"—"},{Field:"Max Refresh Credits",Value:e.maxRefreshCredits??"—"},{Field:"Next Refresh",Value:e.nextRefreshTime||"—"},{Field:"Refresh Interval",Value:e.refreshInterval||"—"}]}});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{cli as u,Strategy as l}from"@jackwener/opencli/registry";import{EmptyResultError as d}from"@jackwener/opencli/errors";import{MANUS_DOMAIN as c,ensureOnManus as m,MANUS_API_CALL_JS as S,requireArray as f,requireObject as p,requireString as h,validatedLimit as g}from"./_utils.js";function y(e){if(!e)return"—";try{return new Date(e).toLocaleDateString("en-US",{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return e}}function A(e){if(!e)return"—";return e.replace("SESSION_STATUS_","").toLowerCase()}u({site:"manus",name:"list",access:"read",description:"List Manus sessions (tasks).",domain:c,strategy:l.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!0,args:[{name:"limit",type:"int",default:20,help:"Max sessions to return"},{name:"archived",type:"bool",default:!1,help:"Include archived sessions"}],columns:["id","Title","Status","Last Message","Last Updated","Credits"],func:async(e,i)=>{const r=g(i?.limit,20,200),a=i?.archived===!0;await m(e);const n=p(await e.evaluate(`(async () => {
|
|
2
|
+
${S}
|
|
3
|
+
return callManusAPI('session.v1.SessionService/ListSessions', {
|
|
4
|
+
page: 1,
|
|
5
|
+
pageSize: ${r},
|
|
6
|
+
});
|
|
7
|
+
})()`),"list sessions");let s=f(n.sessions,"list sessions");if(!a)s=s.filter((t)=>!t.isArchived);if(!s.length)throw new d("manus list","No sessions found.");return s.slice(0,r).map((t,o)=>({id:h(t?.uid,`list session ${o+1}`),Title:(t.title||"—").slice(0,80),Status:A(t.status),"Last Message":(t.lastDisplayMessage||"—").slice(0,80),"Last Updated":y(t.updatedAt),Credits:String(t.costedCredits??"0")}))}});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{cli as o,Strategy as u}from"@jackwener/opencli/registry";import{ArgumentError as d,EmptyResultError as l}from"@jackwener/opencli/errors";import{MANUS_DOMAIN as c,ensureOnManus as m,MANUS_API_CALL_JS as S,requireArray as p,requireObject as f}from"./_utils.js";function i(s){if(!s)return"—";try{return new Date(s).toLocaleString("en-US",{month:"short",day:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return s}}o({site:"manus",name:"read",access:"read",description:"Show details for a specific Manus session.",domain:c,strategy:u.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!0,args:[{name:"uid",positional:!0,required:!0,help:"Session UID"}],columns:["Field","Value"],func:async(s,r)=>{const t=String(r?.uid||"").trim();if(!t)throw new d("uid","must be a non-empty session UID");await m(s);const a=f(await s.evaluate(`(async () => {
|
|
2
|
+
${S}
|
|
3
|
+
return callManusAPI('session.v1.SessionService/ListSessions', {
|
|
4
|
+
page: 1,
|
|
5
|
+
pageSize: 100,
|
|
6
|
+
});
|
|
7
|
+
})()`),"read session"),e=p(a.sessions,"read session").find((n)=>n.uid===t);if(!e)throw new l("manus read",`Session not found: ${t}`);return[{Field:"UID",Value:e.uid||"—"},{Field:"Title",Value:e.title||"—"},{Field:"Status",Value:e.status||"—"},{Field:"Mode",Value:e.agentTaskMode??"—"},{Field:"Credits",Value:e.costedCredits??0},{Field:"Created",Value:i(e.createdAt)},{Field:"Updated",Value:i(e.updatedAt)},{Field:"Last Display Message",Value:e.lastDisplayMessage||"—"}]}});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{cli as m,Strategy as k}from"@jackwener/opencli/registry";import{CommandExecutionError as p,EmptyResultError as y}from"@jackwener/opencli/errors";import{MANUS_DOMAIN as d,ensureOnManus as S,MANUS_API_CALL_JS as O,requireArray as i,requireObject as f,requireString as l}from"./_utils.js";m({site:"manus",name:"skills",access:"read",description:"List Manus skills (user-added and system).",domain:d,strategy:k.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!0,args:[],columns:["ID","Name","Description","Source"],func:async(o)=>{await S(o);const e=f(await o.evaluate(`(async () => {
|
|
2
|
+
${O}
|
|
3
|
+
return callManusAPI('skill.v1.SkillService/ListSkills', {});
|
|
4
|
+
})()`),"skills"),t=[],n=Object.prototype.hasOwnProperty.call(e,"userAddedSkills"),a=Object.prototype.hasOwnProperty.call(e,"systemSkills")||Object.prototype.hasOwnProperty.call(e,"skills");if(!n&&!a)throw new p("Manus skills returned a malformed API payload");const c=n?i(e.userAddedSkills,"user skills"):[];for(const[r,s]of c.entries())t.push({ID:l(s?.id||s?.uid,`user skill ${r+1}`),Name:l(s?.name,`user skill ${r+1}`),Description:(s.description||"—").slice(0,80),Source:"user"});const u=Object.prototype.hasOwnProperty.call(e,"systemSkills")?i(e.systemSkills,"system skills"):Object.prototype.hasOwnProperty.call(e,"skills")?i(e.skills,"system skills"):[];for(const[r,s]of u.entries())t.push({ID:l(s?.id||s?.uid,`system skill ${r+1}`),Name:l(s?.name,`system skill ${r+1}`),Description:(s.description||"—").slice(0,80),Source:"system"});if(!t.length)throw new y("manus skills","No skills found.");return t}});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import{cli as u,Strategy as l}from"@jackwener/opencli/registry";import{MANUS_DOMAIN as d,ensureOnManus as n,MANUS_API_CALL_JS as c,requireObject as r,requireString as o}from"./_utils.js";u({site:"manus",name:"status",access:"read",description:"Show current Manus user profile and credit summary.",domain:d,strategy:l.COOKIE,browser:!0,siteSession:"persistent",navigateBefore:!0,args:[],columns:["Field","Value"],func:async(i)=>{await n(i);const t=r(await i.evaluate(`(async () => {
|
|
2
|
+
${c}
|
|
3
|
+
const [userInfo, credits] = await Promise.all([
|
|
4
|
+
callManusAPI('user.v1.UserService/UserInfo', {}),
|
|
5
|
+
callManusAPI('user.v1.UserService/GetAvailableCredits', {}),
|
|
6
|
+
]);
|
|
7
|
+
return { userInfo, credits };
|
|
8
|
+
})()`),"status"),e=r(t.userInfo,"status user info"),s=r(t.credits,"status credits"),a=e.email||e.userId||e.uid;o(a,"status user identity");return[{Field:"Email",Value:e.email||"—"},{Field:"Display Name",Value:e.displayname||e.displayName||"—"},{Field:"User ID",Value:e.userId||e.uid||"—"},{Field:"Membership Tier",Value:e.membershipTier||"—"},{Field:"Total Credits",Value:s.totalCredits??"—"},{Field:"Periodic Credits",Value:s.periodicCredits??"—"},{Field:"Refresh Credits",Value:s.refreshCredits??"—"},{Field:"Next Refresh",Value:s.nextRefreshTime||"—"}]}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as j from"node:fs";import*as v from"node:path";import{randomUUID as X}from"node:crypto";import{cli as B,Strategy as P}from"@jackwener/opencli/registry";import{ArgumentError as q,CommandExecutionError as D}from"@jackwener/opencli/errors";import{assertLiteralContent as U}from"../_shared/content-guard.js";import{apiErrorText as Y,mastoFormRequest as y,normalizeInstanceUrl as T,readAccessToken as _,uploadMedia as b}from"./shared.js";const C=4,F=["public","unlisted","private","direct"],L={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".mp4":"video/mp4",".mov":"video/quicktime",".m4v":"video/mp4"};function A(K){const G=String(K).split(",").map((N)=>N.trim()).filter(Boolean);if(G.length>C)throw new q(`媒体过多: ${G.length}(上限 ${C})`);return G.map((N)=>{const H=v.resolve(N),W=v.extname(H).toLowerCase(),O=L[W];if(!O)throw new q(`不支持的媒体格式 "${W}"。支持: ${Object.keys(L).join(", ")}`);const Z=j.statSync(H,{throwIfNoEntry:!1});if(!Z||!Z.isFile())throw new q(`不是有效文件: ${H}`);return{name:v.basename(H),mime:O,base64:j.readFileSync(H).toString("base64")}})}B({site:"mastodon",name:"post",access:"write",description:"发一条嘟文(status)到你登录的 Mastodon 实例。零配置:凭证从浏览器登录态自动获取,无需 API key。"+" 用 --instance 指定实例网址(如 https://mastodon.social)。支持图片/视频、可见范围、内容警告、回复。",domain:"mastodon.social",strategy:P.UI,browser:!0,navigateBefore:!1,args:[{name:"instance",type:"string",required:!0,help:"实例网址,如 https://mastodon.social(你已登录的那个)"},{name:"status",type:"string",positional:!0,help:"嘟文正文(纯文本发帖必填;仅发媒体时可省)"},{name:"media",type:"string",required:!1,help:"媒体路径,逗号分隔,最多 4 个(jpg/png/gif/webp/mp4/mov)"},{name:"visibility",type:"string",default:"public",choices:F,help:"可见范围(默认 public)"},{name:"spoiler",type:"string",required:!1,help:"内容警告文本(CW);设了会自动标记为敏感"},{name:"sensitive",type:"boolean",required:!1,help:"把媒体标记为敏感内容"},{name:"language",type:"string",required:!1,help:"ISO 639 语言码,如 zh、en"},{name:"reply-to",type:"string",required:!1,help:"回复的目标 status id(in_reply_to_id)"}],columns:["status","id","url","visibility"],func:async(K,G)=>{if(!K)throw new D("mastodon post 需要浏览器会话");const N=T(G.instance),H=String(G.status??"").trim();U(H,{label:"嘟文正文"});const W=G.media?A(G.media):[];if(!H&&W.length===0)throw new q("嘟文为空:请传正文,或用 --media 附带媒体。");const O=String(G.visibility??"public");if(!F.includes(O))throw new q(`--visibility 只能是 ${F.join("/")}`);const{token:Z}=await _(K,N),V=[];for(const Q of W){const{id:S}=await b(K,{token:Z,file:Q});V.push(S)}const J=[];if(H)J.push(["status",H]);J.push(["visibility",O]);for(const Q of V)J.push(["media_ids[]",Q]);if(G.spoiler)J.push(["spoiler_text",String(G.spoiler)]);if(G.sensitive||G.spoiler)J.push(["sensitive","true"]);if(G.language)J.push(["language",String(G.language)]);if(G["reply-to"])J.push(["in_reply_to_id",String(G["reply-to"])]);const $=await y(K,{path:"/api/v1/statuses",method:"POST",token:Z,form:J,headers:{"Idempotency-Key":X()}});if(!$.ok){const Q=Y($.json)||$.text?.slice(0,200)||"";throw new D(`发嘟失败(HTTP ${$.httpStatus})${Q?": "+Q:""}`)}const z=$.json,R=String(z?.id??"").trim();if(!R)throw new D("发嘟响应缺少 status id;请回查后再决定是否重试。");return[{status:"success",id:R,url:z?.url??z?.uri??`${N}/@me/${R}`,visibility:z?.visibility??O}]}});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import{ArgumentError as W,AuthRequiredError as Y,CommandExecutionError as X}from"@jackwener/opencli/errors";export function normalizeInstanceUrl(B){const G=String(B??"").trim();if(!G)throw new W("缺少 --instance:请传实例网址,如 https://mastodon.social");let H;try{H=new URL(G.includes("://")?G:`https://${G}`)}catch{throw new W(`--instance 不是合法网址: ${G};示例 https://mastodon.social`)}if(H.protocol!=="http:"&&H.protocol!=="https:")throw new W(`--instance 必须是 http(s) 网址: ${G}`);return H.origin}export async function readAccessToken(B,G){await B.goto(`${G}/home`,{waitUntil:"load",settleMs:800});const H=await B.evaluate(`(() => {
|
|
2
|
+
const el = document.getElementById('initial-state');
|
|
3
|
+
if (!el) return { ok: false, error: 'no-initial-state' };
|
|
4
|
+
let state;
|
|
5
|
+
try { state = JSON.parse(el.textContent); }
|
|
6
|
+
catch (e) { return { ok: false, error: 'parse-failed:' + String(e && e.message || e) }; }
|
|
7
|
+
const meta = state && state.meta;
|
|
8
|
+
const token = meta && meta.access_token;
|
|
9
|
+
if (!token) return { ok: false, error: 'no-access-token' };
|
|
10
|
+
return { ok: true, token: token, version: (meta && meta.version) || null };
|
|
11
|
+
})()`);if(!H?.ok||!H.token)throw new Y(G,`未在 ${G} 检测到登录态(${H?.error??"unknown"});请先在浏览器登录该实例。`);return{token:H.token,version:H.version??null}}export async function mastoFormRequest(B,{path:G,method:H="GET",token:L,form:J=[],headers:K={}}){const Q=J.length>0?new URLSearchParams(J).toString():"",V={Authorization:`Bearer ${L}`,Accept:"application/json",...Q?{"Content-Type":"application/x-www-form-urlencoded"}:{},...K};return D(B,{path:G,method:H,headers:V,body:Q||null})}export async function uploadMedia(B,{token:G,file:H,description:L}){const J=await O(B,{path:"/api/v2/media",token:G,file:H,description:L??null});if(J.httpStatus!==200&&J.httpStatus!==202)throw new X(`媒体上传失败(HTTP ${J.httpStatus}): ${apiErrorText(J.json)||J.text?.slice(0,200)||""}`);const K=String(J.json?.id??"").trim();if(!K)throw new X("媒体上传响应缺少 attachment id");if(J.httpStatus===200&&J.json?.url)return{id:K,url:J.json.url};const Q=1000,V=60000,$=Date.now()+V;while(Date.now()<$){await B.wait(1);const N=await mastoFormRequest(B,{path:`/api/v1/media/${K}`,method:"GET",token:G});if(N.httpStatus===200&&N.json?.url)return{id:K,url:N.json.url};if(N.httpStatus!==200&&N.httpStatus!==206)throw new X(`媒体处理查询失败(HTTP ${N.httpStatus})`)}return{id:K,url:null}}export function apiErrorText(B){if(!B||typeof B!=="object")return"";if(typeof B.error==="string")return B.error;if(B.error_description)return String(B.error_description);return""}async function D(B,{path:G,method:H,headers:L,body:J}){const K=await B.evaluate(`(async () => {
|
|
12
|
+
try {
|
|
13
|
+
const r = await fetch(${JSON.stringify(G)}, {
|
|
14
|
+
method: ${JSON.stringify(H)},
|
|
15
|
+
headers: ${JSON.stringify(L)},
|
|
16
|
+
credentials: 'include',
|
|
17
|
+
body: ${J===null?"undefined":JSON.stringify(J)},
|
|
18
|
+
});
|
|
19
|
+
const text = await r.text();
|
|
20
|
+
let json = null;
|
|
21
|
+
try { json = JSON.parse(text); } catch (e) {}
|
|
22
|
+
return { httpStatus: r.status, ok: r.ok, json, text };
|
|
23
|
+
} catch (e) {
|
|
24
|
+
return { httpStatus: 0, ok: false, json: null, text: String(e && e.message || e) };
|
|
25
|
+
}
|
|
26
|
+
})()`);return Z(K,G)}async function O(B,{path:G,token:H,file:L,description:J}){const K=await B.evaluate(`(async () => {
|
|
27
|
+
try {
|
|
28
|
+
const f = ${JSON.stringify(L)};
|
|
29
|
+
const bin = atob(f.base64);
|
|
30
|
+
const bytes = new Uint8Array(bin.length);
|
|
31
|
+
for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
|
|
32
|
+
const fd = new FormData();
|
|
33
|
+
fd.append('file', new File([bytes], f.name, { type: f.mime }), f.name);
|
|
34
|
+
${J?`fd.append('description', ${JSON.stringify(String(J))});`:""}
|
|
35
|
+
const r = await fetch(${JSON.stringify(G)}, {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: { 'Authorization': 'Bearer ' + ${JSON.stringify(H)}, 'Accept': 'application/json' },
|
|
38
|
+
credentials: 'include',
|
|
39
|
+
body: fd,
|
|
40
|
+
});
|
|
41
|
+
const text = await r.text();
|
|
42
|
+
let json = null;
|
|
43
|
+
try { json = JSON.parse(text); } catch (e) {}
|
|
44
|
+
return { httpStatus: r.status, ok: r.ok, json, text };
|
|
45
|
+
} catch (e) {
|
|
46
|
+
return { httpStatus: 0, ok: false, json: null, text: String(e && e.message || e) };
|
|
47
|
+
}
|
|
48
|
+
})()`);return Z(K,G)}function Z(B,G){if(B?.httpStatus===401||B?.httpStatus===403)throw new Y("mastodon",`Mastodon API ${G} 返回 HTTP ${B.httpStatus}(登录态失效或缺 write scope)`);return{httpStatus:B?.httpStatus??0,ok:!!B?.ok,json:B?.json??null,text:B?.text??""}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as r,Strategy as c}from"@jackwener/opencli/registry";import{AuthRequiredError as m}from"@jackwener/opencli/errors";import{mastoFormRequest as l,normalizeInstanceUrl as d,readAccessToken as u}from"./shared.js";r({site:"mastodon",name:"whoami",access:"read",description:"检测 Mastodon 实例的登录状态,返回是否登录及账号信息。用 --instance 指定实例网址。",domain:"mastodon.social",strategy:c.UI,browser:!0,navigateBefore:!1,args:[{name:"instance",type:"string",required:!0,help:"实例网址,如 https://mastodon.social"}],columns:["logged_in","account","display_name","instance"],func:async(t,i)=>{const e=d(i.instance);let s;try{({token:s}=await u(t,e))}catch(o){if(o instanceof m)return[{logged_in:!1,account:"",display_name:"",instance:e}];throw o}const a=await l(t,{path:"/api/v1/accounts/verify_credentials",method:"GET",token:s});if(!a.ok||!a.json?.username)return[{logged_in:!1,account:"",display_name:"",instance:e}];const n=a.json;return[{logged_in:!0,account:n.acct||n.username||"",display_name:n.display_name||"",instance:e}]}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as d,Strategy as m}from"@jackwener/opencli/registry";import{EmptyResultError as f}from"@jackwener/opencli/errors";import{MAVEN_BASE as v,mavenFetch as h,epochMsToIso as I,requireBoundedInt as $,requireCoord as y}from"./utils.js";d({site:"maven",name:"artifact",access:"read",description:"Fetch a Maven Central artifact's version history (groupId:artifactId[:version])",domain:"search.maven.org",strategy:m.PUBLIC,browser:!1,args:[{name:"coordinate",positional:!0,required:!0,help:'Maven coord "groupId:artifactId" or "groupId:artifactId:version"'},{name:"limit",type:"int",default:20,help:"Max versions (1-200, ignored when version is pinned)"}],columns:["groupId","artifactId","version","packaging","publishedAt","tags","url"],func:async(i)=>{const{groupId:t,artifactId:e,version:a}=y(i.coordinate),c=$(i.limit,20,200),o=[`g:${t}`,`a:${e}`];if(a)o.push(`v:${a}`);const p=o.join(" AND "),g=a?1:c,l=`${v}?q=${encodeURIComponent(p)}&core=gav&rows=${g}&wt=json`,n=await h(l,"maven artifact"),s=Array.isArray(n?.response?.docs)?n.response.docs:[],u=a?`${t}:${e}:${a}`:`${t}:${e}`;if(!s.length)throw new f("maven artifact",`Maven Central has no published versions for ${u}.`);return s.map((r)=>({groupId:String(r.g??t).trim(),artifactId:String(r.a??e).trim(),version:String(r.v??"").trim(),packaging:String(r.p??"").trim(),publishedAt:I(r.timestamp),tags:Array.isArray(r.tags)?r.tags.filter(Boolean).join(", "):"",url:`https://central.sonatype.com/artifact/${t}/${e}/${r.v??""}`.replace(/\/$/,"")}))}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as u,Strategy as p}from"@jackwener/opencli/registry";import{EmptyResultError as g}from"@jackwener/opencli/errors";import{MAVEN_BASE as d,mavenFetch as h,epochMsToIso as y,requireBoundedInt as v,requireString as f}from"./utils.js";u({site:"maven",name:"search",access:"read",description:"Search Maven Central by keyword (artifact name, groupId, tag)",domain:"search.maven.org",strategy:p.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g. "jackson", "guava", "ai.koog")'},{name:"limit",type:"int",default:30,help:"Max artifacts (1-200)"}],columns:["rank","coordinate","groupId","artifactId","latestVersion","packaging","versions","lastPublished","repository","url"],func:async(a)=>{const o=f(a.query,"query"),n=v(a.limit,30,200),l=`${d}?q=${encodeURIComponent(o)}&rows=${n}&wt=json`,s=await h(l,"maven search"),i=Array.isArray(s?.response?.docs)?s.response.docs:[];if(!i.length)throw new g("maven search",`No Maven Central artifacts matched "${o}".`);return i.slice(0,n).map((r,m)=>{const t=String(r.g??"").trim(),e=String(r.a??"").trim(),c=t&&e?`${t}:${e}`:"";return{rank:m+1,coordinate:c,groupId:t,artifactId:e,latestVersion:String(r.latestVersion??"").trim(),packaging:String(r.p??"").trim(),versions:r.versionCount!=null?Number(r.versionCount):null,lastPublished:y(r.timestamp),repository:String(r.repositoryId??"").trim(),url:c?`https://central.sonatype.com/artifact/${t}/${e}`:""}})}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ArgumentError as J,CommandExecutionError as L,EmptyResultError as Q}from"@jackwener/opencli/errors";export const MAVEN_BASE="https://search.maven.org/solrsearch/select",MAVEN_REPO_BASE="https://repo1.maven.org/maven2";const W="opencli-maven-adapter (+https://github.com/jackwener/opencli)",P=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;export function requireString(B,q){const z=String(B??"").trim();if(!z)throw new J(`maven ${q} cannot be empty`);return z}export function requireBoundedInt(B,q,z,G="limit"){const F=B??q,H=typeof F==="number"?F:Number(F);if(!Number.isInteger(H)||H<=0)throw new J(`maven ${G} must be a positive integer`);if(H>z)throw new J(`maven ${G} must be <= ${z}`);return H}export function requireCoord(B){const q=String(B??"").trim();if(!q)throw new J('maven coordinate is required (e.g. "com.fasterxml.jackson.core:jackson-databind")');const z=q.split(":");if(z.length<2||z.length>3)throw new J(`maven coordinate "${B}" must be "groupId:artifactId" or "groupId:artifactId:version"`);const[G,F,H]=z;if(!G||!F)throw new J(`maven coordinate "${B}" is missing groupId or artifactId`);if(G.length>200||!P.test(G))throw new J(`maven groupId "${G}" is not a valid token`,'Use letters / digits / "_-." (max 200 chars), starting with a letter or digit.');if(F.length>200||!P.test(F))throw new J(`maven artifactId "${F}" is not a valid token`,'Use letters / digits / "_-." (max 200 chars), starting with a letter or digit.');if(H!=null&&H.length>200)throw new J(`maven version "${H}" is too long (max 200 chars).`);return{groupId:G,artifactId:F,version:H??null}}export async function mavenFetch(B,q){let z;try{z=await fetch(B,{headers:{"user-agent":W,accept:"application/json"}})}catch(F){throw new L(`${q} request failed: ${F?.message??F}`,"Check that search.maven.org is reachable from this network.")}if(z.status===404)throw new Q(q,`Maven Central returned 404 for ${B}.`);if(z.status===429)throw new L(`${q} returned HTTP 429 (rate limited)`,"Maven Central throttles bursts; wait a few seconds and retry.");if(!z.ok)throw new L(`${q} returned HTTP ${z.status}`);let G;try{G=await z.json()}catch(F){throw new L(`${q} returned malformed JSON: ${F?.message??F}`)}return G}export function epochMsToIso(B){if(B==null)return null;const q=typeof B==="number"?B:Number(B);if(!Number.isFinite(q)||q<=0)return null;return new Date(q).toISOString().replace(/\.\d+Z$/,"Z")}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cli as p,Strategy as w}from"@jackwener/opencli/registry";import{ArgumentError as i,CommandExecutionError as l,EmptyResultError as f}from"@jackwener/opencli/errors";const u="https://developer.mozilla.org",y="opencli-mdn-adapter (+https://github.com/jackwener/opencli)",d=new Set(["en-US","de","es","fr","ja","ko","pt-BR","ru","zh-CN","zh-TW"]);function g(r,t){const n=String(r??"").trim();if(!n)throw new i(`mdn ${t} cannot be empty`);return n}function S(r,t,n){const o=r??t,a=typeof o==="number"?o:Number(o);if(!Number.isInteger(a)||a<=0)throw new i("mdn limit must be a positive integer");if(a>n)throw new i(`mdn limit must be <= ${n}`);return a}function $(r){const t=String(r??"en-US").trim();if(!d.has(t))throw new i(`mdn locale "${r}" is not supported`,`Allowed locales: ${[...d].join(" / ")}`);return t}p({site:"mdn",name:"search",access:"read",description:"Search MDN Web Docs by keyword",domain:"developer.mozilla.org",strategy:w.PUBLIC,browser:!1,args:[{name:"query",positional:!0,required:!0,help:'Search keyword (e.g. "fetch", "flexbox", "Array.prototype.map")'},{name:"limit",type:"int",default:10,help:"Max results (1-50)"},{name:"locale",default:"en-US",help:"Doc locale (en-US default; de / es / fr / ja / ko / pt-BR / ru / zh-CN / zh-TW)"}],columns:["rank","title","slug","locale","summary","url"],func:async(r)=>{const t=g(r.query,"query"),n=S(r.limit,10,50),o=$(r.locale),a=`${u}/api/v1/search?q=${encodeURIComponent(t)}&locale=${encodeURIComponent(o)}&size=${n}`;let s;try{s=await fetch(a,{headers:{"user-agent":y,accept:"application/json"}})}catch(e){throw new l(`mdn search request failed: ${e?.message??e}`)}if(s.status===429)throw new l("mdn search returned HTTP 429 (rate limited)","MDN throttles bursty traffic; wait a few seconds and retry.");if(!s.ok)throw new l(`mdn search returned HTTP ${s.status}`);let c;try{c=await s.json()}catch(e){throw new l(`mdn search returned malformed JSON: ${e?.message??e}`)}const m=Array.isArray(c?.documents)?c.documents:[];if(!m.length)throw new f("mdn search",`No MDN results matched "${t}" (locale ${o}).`);return m.slice(0,n).map((e,h)=>({rank:h+1,title:String(e.title??""),slug:String(e.slug??""),locale:String(e.locale??o),summary:String(e.summary??"").replace(/\s+/g," ").trim(),url:e.mdn_url?`${u}${e.mdn_url}`:""}))}});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import{cli as a,Strategy as zz}from"@jackwener/opencli/registry";import{CliError as L,CommandExecutionError as Gz}from"@jackwener/opencli/errors";import{readFile as Jz,stat as Kz}from"node:fs/promises";import{publishArticle as Qz}from"../_shared/article/publish.js";export const mediumProfile={home:"https://medium.com/new-story",outputFormat:"markdown",checkAuth:async(K)=>{try{const W=await(await fetch("https://medium.com/_/graphql",{method:"POST",credentials:"include",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({operationName:"ViewerQuery",query:"query ViewerQuery { viewer { id name username imageId } }",variables:{}})})).json(),$=W&&W.data&&W.data.viewer;if($&&$.id)return{isAuthenticated:!0,userId:$.id,username:$.username||$.name||"",avatar:$.imageId?"https://miro.medium.com/v2/resize:fill:96:96/"+$.imageId:""};return{isAuthenticated:!1}}catch(Q){return{isAuthenticated:!1,error:String(Q&&Q.message||Q)}}},publish:async(K,Q)=>{const W=(z)=>z.replace(/^\s*\]\)\}while\(1\);(<\/x>)?/,""),$=document.documentElement.outerHTML.match(/"xsrfToken":"([^"]+)"/),q=$?$[1]:null;if(!q)return{ok:!1,stage:"xsrf",message:"未能从编辑器页提取 xsrfToken(请确认已登录 medium.com 且停留在 /new-story)"};const P={accept:"application/json","x-requested-with":"XMLHttpRequest","x-xsrf-token":q},D=async(z,J,A)=>{const X=Object.assign({},P);if(A!==void 0)X["content-type"]="application/json";const Z=await fetch("https://medium.com"+z,{method:J||"GET",credentials:"include",headers:X,body:A!==void 0?JSON.stringify(A):void 0});let F=W(await Z.text()),G=null;try{G=JSON.parse(F)}catch(U){}return{status:Z.status,json:G,text:F}},H=(z)=>{const J=[];let A=0,X="";const Z=(F)=>{if(F)X+=F};while(A<z.length){const G=z.slice(A).match(/^(\[([^\]]+)\]\(([^)]+)\)|\*\*([^*]+)\*\*|`([^`]+)`|\*([^*]+)\*|(https?:\/\/[^\s<]+[^\s<.,;:!?")\]]))/);if(!G){Z(z[A]);A+=1;continue}const U=A+(G.index||0);if(U>A)Z(z.slice(A,U));const S=G[1],O=X.length;if(G[2]!==void 0&&G[3]!==void 0){Z(G[2]);J.push({type:3,start:O,end:X.length,href:G[3],title:"",rel:"nofollow",anchorType:0})}else if(G[4]!==void 0){Z(G[4]);J.push({type:1,start:O,end:X.length})}else if(G[5]!==void 0)Z(G[5]);else if(G[6]!==void 0){Z(G[6]);J.push({type:2,start:O,end:X.length})}else if(G[7]!==void 0){Z(G[7]);J.push({type:3,start:O,end:X.length,href:G[7],title:"",rel:"nofollow",anchorType:0})}else Z(S);A=U+S.length}return{text:X,markups:J}},x=(z)=>{const J={paragraph:1,h1:12,h2:2,h3:3,h4:13,blockquote:6,code:8,"ul-li":9,"ol-li":10},A=(z||"").replace(/\r\n/g,`
|
|
2
|
+
`).split(`
|
|
3
|
+
`),X=[];let Z=[],F,G=[],U=!1;const S=(V,T,N)=>{const Y=(V||"").trim();if(!Y)return;const B=J[T]||J.paragraph,l=B===J.code?{text:Y,markups:[]}:H(Y);X.push(Object.assign({type:B,text:l.text,markups:l.markups},N?{codeLang:N}:{}))},O=()=>{if(!Z.length)return;const V=Z.join(" ").trim();Z=[];if(!V)return;const T=V.match(/^(#{1,4})\s+(.*)$/);if(T){S(T[2].trim(),"h"+T[1].length);return}const N=V.match(/^>\s?(.*)$/);if(N){S(N[1].trim(),"blockquote");return}const Y=V.match(/^\d+\.\s+(.*)$/);if(Y){S(Y[1].trim(),"ol-li");return}const B=V.match(/^[-*]\s+(.*)$/);if(B){S(B[1].trim(),"ul-li");return}S(V,"paragraph")},o=()=>{if(!G.length){F=void 0;return}X.push(Object.assign({type:J.code,text:G.join(`
|
|
4
|
+
`),markups:[]},F?{codeLang:F}:{}));G=[];F=void 0};for(const V of A){const T=V.trim().match(/^!\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)$/i),N=V.trim().match(/^<img\b[^>]*?\bsrc=["']([^"']+)["'][^>]*>$/i);if(T){O();X.push({image:!0,imageUrl:T[2],imageAlt:T[1]||""});continue}if(N){O();const B=V.match(/\balt=["']([^"']+)["']/i);X.push({image:!0,imageUrl:N[1],imageAlt:B&&B[1]||""});continue}const Y=V.match(/^```(\S+)?\s*$/);if(Y){if(U){o();U=!1}else{O();U=!0;F=Y[1]||void 0}continue}if(U){G.push(V);continue}if(!V.trim()){O();continue}if(/^(#{1,4})\s+/.test(V)||/^>\s?/.test(V)||/^\d+\.\s+/.test(V)||/^[-*]\s+/.test(V)){O();Z.push(V);O();continue}Z.push(V.trim())}O();if(U)o();return X},C=async(z)=>{let J,A="image.png";if(/^data:/i.test(z)){J=Q.dataUriToBlob(z);A="image."+(((J.type||"").split("/")[1]||"png").split("+")[0].split(";")[0]||"png")}else{const U=await fetch(z,{credentials:"omit"});if(!U.ok)throw Error("拉取图片失败 HTTP "+U.status);J=await U.blob();try{const O=new URL(z).pathname.split("/").filter(Boolean).pop()||"image.png";A=/\.[a-z0-9]+$/i.test(O)?O:O+".png"}catch(S){}}const X=new FormData;X.append("uploadedFile",J,A);const Z=await fetch("https://medium.com/_/upload?is2x=true",{method:"POST",credentials:"include",headers:{accept:"application/json","x-requested-with":"XMLHttpRequest","x-xsrf-token":q},body:X}),F=JSON.parse(W(await Z.text())),G=F&&F.payload&&F.payload.value||{};if(!G.fileId||!G.imgWidth||!G.imgHeight)throw Error("上传响应缺 fileId/尺寸");return{fileId:G.fileId,w:G.imgWidth,h:G.imgHeight}},j=[],M=[],y=await D("/new-story","POST",{}),w=y.json&&y.json.payload||{},_=w.id||w.value&&w.value.id;if(!_)return{ok:!1,stage:"create",status:y.status,message:"Medium 未返回草稿 postId:"+y.text.slice(0,160)};const n=await D("/_/api/posts/"+_+"/draft"),v=n.json&&n.json.payload||{},m=Array.isArray(v.normalizingDeltas)?v.normalizingDeltas:[],u=v.value&&typeof v.value.latestRev==="number"?v.value.latestRev:0;if(u<0&&m.length){const z=await D("/p/"+_+"/deltas","POST",{baseRev:u,deltas:m});if(z.status>=400)return{ok:!1,stage:"init",status:z.status,message:"初始化草稿失败"}}const b=await D("/_/api/posts/"+_),p=b.json&&b.json.payload&&b.json.payload.value||{},t=typeof p.latestRev==="number"?p.latestRev:0,R=K.params||{};let E=x(K.markdown||K.content||"");if(K.title&&E.length&&!E[0].image&&E[0].type===12&&(E[0].text||"").trim()===K.title.trim())E=E.slice(1);const c=[];if(K.title&&K.title.trim())c.push({type:3,text:K.title.trim(),markups:[]});if(R.subtitle&&String(R.subtitle).trim())c.push({type:4,text:String(R.subtitle).trim(),markups:[]});const r=c.concat(E),I=[];let h=0;for(const z of r){if(z.image){try{const J=await C(z.imageUrl);I.push({type:1,index:h,paragraph:{type:4,text:z.imageAlt||"",markups:[],layout:1,metadata:{id:J.fileId,originalWidth:J.w,originalHeight:J.h}}});j.push(z.imageUrl);h+=1}catch(J){M.push({src:z.imageUrl,error:String(J&&J.message||J)})}continue}I.push(Object.assign({type:1,index:h,paragraph:Object.assign({type:z.type,text:z.text,markups:z.markups||[]},z.codeLang?{codeLang:z.codeLang}:{})}));h+=1}if(!I.length)return{ok:!1,stage:"content",message:"正文为空,无可写入的段落"};const f=await D("/p/"+_+"/deltas","POST",{baseRev:t,deltas:I});if(f.status>=400)return{ok:!1,stage:"write",status:f.status,message:"写入正文失败:"+f.text.slice(0,160),uploaded:j,failed:M};const d=Array.isArray(R.tags)?R.tags.filter(Boolean).slice(0,5):[];if(d.length){const z=await D("/_/graphql","POST",{operationName:"SetPostTagsMutation",query:`mutation SetPostTagsMutation($targetPostId: ID!, $tagNames: [String!]!) {
|
|
5
|
+
setPostTags(targetPostId: $targetPostId, tagNames: $tagNames) {
|
|
6
|
+
id
|
|
7
|
+
}
|
|
8
|
+
}`,variables:{targetPostId:_,tagNames:d}});if(z.status>=400||z.json&&z.json.errors)M.push({src:"tags",error:"设置标签失败:"+(z.text||"").slice(0,120)})}if(R.canonicalUrl&&String(R.canonicalUrl).trim())await D("/_/graphql","POST",{operationName:"UpdateCanonicalUrl",query:`mutation UpdateCanonicalUrl($input: UpdateCanonicalUrlInput!) {
|
|
9
|
+
updateCanonicalUrl(input: $input) {
|
|
10
|
+
__typename
|
|
11
|
+
}
|
|
12
|
+
}`,variables:{input:{postId:_,url:String(R.canonicalUrl).trim()}}});const s="https://medium.com/p/"+_+"/edit";if(K.draftOnly)return{ok:!0,id:_,url:s,draft:!0,uploaded:j,failed:M};const k=await D("/p/"+_+"/publish","POST",{});if(k.status>=400)return{ok:!1,stage:"publish",status:k.status,message:"发布失败:"+k.text.slice(0,200),uploaded:j,failed:M};const g=await D("/_/api/posts/"+_),i=g.json&&g.json.payload&&g.json.payload.value||{},e=i.mediumUrl||(i.uniqueSlug?"https://medium.com/p/"+_:"https://medium.com/p/"+_);return{ok:!0,id:_,url:e,draft:!1,uploaded:j,failed:M}}},mediumAuthProfile={home:"https://medium.com/",checkAuth:mediumProfile.checkAuth};function Vz(K){if(!K.execute)throw new L("INVALID_INPUT","此命令需要 --execute 参数才能执行写操作。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}async function Wz(K){const Q=typeof K.text==="string"?K.text:void 0,W=typeof K.file==="string"?K.file:void 0;if(Q&&W)throw new L("INVALID_INPUT","不能同时指定正文参数和 --file,请二选一");let $=Q??"";if(W){let q;try{q=await Kz(W)}catch{throw new L("INVALID_INPUT","文件不存在: "+W)}if(!q.isFile())throw new L("INVALID_INPUT","必须是可读的文本文件: "+W);let P;try{P=await Jz(W)}catch{throw new L("INVALID_INPUT","无法读取文件: "+W)}try{$=new TextDecoder("utf-8",{fatal:!0}).decode(P)}catch{throw new L("INVALID_INPUT","文件必须是 UTF-8 编码: "+W)}}if(!$.trim())throw new L("INVALID_INPUT","正文不能为空");return $}function Xz(K,Q,W,$,q={}){return[{status:"success",outcome:$,message:K,target_type:"article",target:Q,...q}]}a({site:"medium",name:"article",access:"write",description:"发布 Medium 文章(走 medium.com 内部编辑器端点,非官方 API)。默认正式发布;加 --draft 仅存草稿。正文 Markdown,图片自动转存 Medium 图床。可选 --tags/--subtitle/--canonical-url。",domain:"medium.com",strategy:zz.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题(作为 Medium 文章标题)"},{name:"text",positional:!0,help:"文章正文(Markdown)"},{name:"file",help:"正文文件路径(UTF-8,Markdown)"},{name:"tags",help:'Medium 话题标签,逗号分隔,最多 5 个(如 "AI,Programming,Open Source")'},{name:"subtitle",help:"副标题(可选,显示在标题下方)"},{name:"canonical-url",help:"原文规范链接(可选,内容首发别处时填,避免 SEO 重复)"},{name:"draft",type:"boolean",help:"仅保存草稿,不正式发布"},{name:"execute",type:"boolean",help:"确认执行写操作。不加此参数则拒绝写入。"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(K,Q)=>{if(!K)throw new Gz("Medium 文章发布需要浏览器会话");Vz(Q);const W=String(Q.title??"").trim();if(!W)throw new L("INVALID_INPUT","文章标题不能为空");const $=await Wz(Q),q=Boolean(Q.draft),D={tags:String(Q.tags??"").split(",").map((y)=>y.trim()).filter(Boolean),subtitle:typeof Q.subtitle==="string"?Q.subtitle:"",canonicalUrl:typeof Q["canonical-url"]==="string"?Q["canonical-url"]:""},H=await Qz(K,{title:W,body:$,format:"markdown",draftOnly:q,profile:mediumProfile,publishParams:D}),x=H.images.uploaded.length|0,C=H.images.failed.length|0;let j=H.draft?"Medium 草稿已保存(可在编辑器内手动发布)":"Medium 文章已正式发布";if(x||C)j+=";图片:"+x+" 张已转存"+(C?","+C+" 张失败(失败明细见 images_failed)":"");const M=Xz(j,"",H.url,H.draft?"draft":"publish",{created_target:"article:"+H.id,created_url:H.url});if(C){M[0].status="partial";M[0].images_failed=JSON.stringify(H.images.failed)}return M}});
|