publishport-opencli 1.0.19 → 1.0.21
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/cli-manifest.json +35 -0
- package/clis/12306/me.js +2 -2
- package/clis/12306/orders.js +3 -3
- package/clis/12306/passengers.js +3 -3
- package/clis/12306/price.js +1 -1
- package/clis/12306/stations.js +1 -1
- package/clis/12306/train.js +1 -1
- package/clis/12306/trains.js +1 -1
- package/clis/12306/utils.js +1 -1
- package/clis/1688/download.js +1 -1
- package/clis/1688/item.js +4 -4
- package/clis/1688/search.js +4 -4
- package/clis/1688/store.js +4 -4
- package/clis/1point3acres/forum.js +1 -1
- package/clis/1point3acres/forums.js +1 -1
- package/clis/1point3acres/notifications.js +1 -1
- package/clis/1point3acres/search.js +1 -1
- package/clis/1point3acres/thread.js +2 -2
- package/clis/1point3acres/user.js +1 -1
- package/clis/1point3acres/utils.js +2 -2
- package/clis/36kr/article.js +2 -2
- package/clis/36kr/hot.js +2 -2
- package/clis/36kr/news.js +1 -1
- package/clis/36kr/search.js +2 -2
- package/clis/51job/company.js +2 -2
- package/clis/51job/detail.js +2 -2
- package/clis/51job/hot.js +1 -1
- package/clis/51job/search.js +1 -1
- package/clis/51job/utils.js +7 -7
- package/clis/_atlassian/shared.js +9 -9
- package/clis/_shared/article/auth.js +4 -4
- package/clis/_shared/article/douban-md2draft.js +4 -4
- package/clis/_shared/article/format.js +1 -1
- package/clis/_shared/article/images.js +7 -7
- package/clis/_shared/article/login.js +1 -1
- package/clis/_shared/article/publish.js +11 -11
- package/clis/_shared/common.js +1 -1
- package/clis/_shared/content-guard.js +1 -1
- package/clis/_shared/desktop-commands.js +1 -1
- package/clis/_shared/file-inject.js +12 -12
- package/clis/_shared/self-hosted-sites.js +2 -2
- package/clis/_shared/site-auth.js +1 -1
- package/clis/_shared/token-auth.js +2 -2
- package/clis/_shared/video-publish.js +9 -9
- package/clis/amazon/offer.js +3 -3
- package/clis/amazon/product.js +5 -5
- package/clis/amazon/shared.js +6 -6
- package/clis/antigravity/_actions.js +13 -13
- package/clis/antigravity/audit-extras.js +10 -10
- package/clis/antigravity/delete.js +1 -1
- package/clis/antigravity/model.js +6 -6
- package/clis/antigravity/new.js +2 -2
- package/clis/antigravity/read.js +2 -2
- package/clis/antigravity/rename.js +1 -1
- package/clis/antigravity/send.js +3 -3
- package/clis/antigravity/serve.js +17 -17
- package/clis/antigravity/storage.js +6 -6
- package/clis/antigravity/watch.js +2 -2
- package/clis/apple-podcasts/episodes.js +1 -1
- package/clis/apple-podcasts/top.js +1 -1
- package/clis/apple-podcasts/utils.js +1 -1
- package/clis/archive/item.js +1 -1
- package/clis/archive/search.js +1 -1
- package/clis/archive/snapshots.js +1 -1
- package/clis/archive/wayback.js +1 -1
- package/clis/arxiv/author.js +1 -1
- package/clis/arxiv/utils.js +1 -1
- package/clis/autohome/brand.js +1 -1
- package/clis/autohome/score.js +1 -1
- package/clis/autohome/utils.js +1 -1
- package/clis/baijiahao/article.js +1 -1
- package/clis/baijiahao/lists.js +1 -1
- package/clis/baijiahao/login.js +1 -1
- package/clis/baijiahao/publish.js +9 -9
- package/clis/baijiahao/stats.js +1 -1
- package/clis/baijiahao/whoami.js +1 -1
- package/clis/band/bands.js +2 -2
- package/clis/band/mentions.js +2 -2
- package/clis/band/post.js +4 -4
- package/clis/band/posts.js +3 -3
- package/clis/barchart/flow.js +3 -3
- package/clis/barchart/greeks.js +2 -2
- package/clis/barchart/quote.js +3 -3
- package/clis/bbc/news.js +1 -1
- package/clis/bbc/topic.js +1 -1
- package/clis/bbc/utils.js +1 -1
- package/clis/bilibili/article.js +1 -1
- package/clis/bilibili/categories.js +1 -1
- package/clis/bilibili/coin.js +1 -1
- package/clis/bilibili/comment-del.js +1 -1
- package/clis/bilibili/comment-like.js +1 -1
- package/clis/bilibili/comment.js +1 -1
- package/clis/bilibili/comments.js +1 -1
- package/clis/bilibili/dm-list.js +1 -1
- package/clis/bilibili/dm-read.js +1 -1
- package/clis/bilibili/dm-send.js +1 -1
- package/clis/bilibili/download.js +2 -2
- package/clis/bilibili/drafts.js +1 -1
- package/clis/bilibili/dynamic-post.js +3 -3
- package/clis/bilibili/favorite-add.js +1 -1
- package/clis/bilibili/favorite.js +1 -1
- package/clis/bilibili/feed.js +2 -2
- package/clis/bilibili/follow.js +1 -1
- package/clis/bilibili/following.js +1 -1
- package/clis/bilibili/like.js +1 -1
- package/clis/bilibili/partitions.js +1 -1
- package/clis/bilibili/stats.js +1 -1
- package/clis/bilibili/subtitle.js +3 -3
- package/clis/bilibili/summary.js +1 -1
- package/clis/bilibili/topics.js +1 -1
- package/clis/bilibili/unfollow.js +1 -1
- package/clis/bilibili/upload.js +1 -1
- package/clis/bilibili/utils.js +10 -10
- package/clis/bilibili/video-drafts.js +1 -1
- package/clis/bilibili/video.js +1 -1
- package/clis/bloomberg/businessweek.js +4 -4
- package/clis/bloomberg/news.js +2 -2
- package/clis/bloomberg/utils.js +13 -13
- package/clis/bluesky/post.js +1 -1
- package/clis/bluesky/shared.js +11 -11
- package/clis/bluesky/whoami.js +1 -1
- package/clis/booking/search.js +2 -2
- package/clis/boss/accept.js +1 -1
- package/clis/boss/applied.js +1 -1
- package/clis/boss/auth.js +1 -1
- package/clis/boss/batchgreet.js +1 -1
- package/clis/boss/bossinfo.js +1 -1
- package/clis/boss/chatlist.js +1 -1
- package/clis/boss/chatmsg.js +1 -1
- package/clis/boss/cities.js +1 -1
- package/clis/boss/detail.js +1 -1
- package/clis/boss/exchange.js +1 -1
- package/clis/boss/greet.js +1 -1
- package/clis/boss/interviews.js +1 -1
- package/clis/boss/invite.js +1 -1
- package/clis/boss/joblist.js +1 -1
- package/clis/boss/mark.js +1 -1
- package/clis/boss/me.js +2 -2
- package/clis/boss/recommend.js +1 -1
- package/clis/boss/resumedelete.js +1 -1
- package/clis/boss/resumelist.js +1 -1
- package/clis/boss/resumeupload.js +11 -11
- package/clis/boss/search.js +1 -1
- package/clis/boss/send.js +1 -1
- package/clis/boss/sendresume.js +1 -1
- package/clis/boss/stats.js +1 -1
- package/clis/boss/unread.js +1 -1
- package/clis/boss/utils.js +13 -13
- package/clis/chaoxing/assignments.js +1 -1
- package/clis/chaoxing/exams.js +1 -1
- package/clis/chaoxing/utils.js +9 -9
- package/clis/chatgpt/ask.js +1 -1
- package/clis/chatgpt/auth.js +2 -2
- package/clis/chatgpt/detail.js +1 -1
- package/clis/chatgpt/image.js +1 -1
- package/clis/chatgpt/read.js +1 -1
- package/clis/chatgpt/send.js +1 -1
- package/clis/chatgpt/utils.js +59 -59
- package/clis/chatgpt-app/ask.js +1 -1
- package/clis/chatgpt-app/send.js +1 -1
- package/clis/chatwise/model.js +6 -6
- package/clis/chess/analyze.js +1 -1
- package/clis/chess/game.js +1 -1
- package/clis/chess/games.js +1 -1
- package/clis/chess/stats.js +1 -1
- package/clis/chess/utils.js +1 -1
- package/clis/claude/ask.js +2 -2
- package/clis/claude/detail.js +1 -1
- package/clis/claude/new.js +1 -1
- package/clis/claude/read.js +1 -1
- package/clis/claude/send.js +1 -1
- package/clis/claude/utils.js +23 -23
- package/clis/cnblogs/article.js +1 -1
- package/clis/cnblogs/login.js +1 -1
- package/clis/cnblogs/stats.js +7 -7
- package/clis/cnblogs/whoami.js +1 -1
- package/clis/codex/_actions.js +3 -3
- package/clis/codex/archive.js +1 -1
- package/clis/codex/ask.js +6 -6
- package/clis/codex/model.js +8 -8
- package/clis/codex/pin.js +1 -1
- package/clis/codex/rename.js +4 -4
- package/clis/codex/send.js +3 -3
- package/clis/codex/sidebar.js +1 -1
- package/clis/coingecko/categories.js +1 -1
- package/clis/coingecko/coin.js +1 -1
- package/clis/coingecko/derivatives.js +1 -1
- package/clis/coingecko/exchanges.js +1 -1
- package/clis/coingecko/global.js +1 -1
- package/clis/coingecko/trending.js +1 -1
- package/clis/confluence/search.js +1 -1
- package/clis/coupang/product.js +3 -3
- package/clis/coupang/utils.js +1 -1
- package/clis/crates/crate.js +1 -1
- package/clis/crates/search.js +1 -1
- package/clis/crates/utils.js +1 -1
- package/clis/csdn/article.js +13 -13
- package/clis/csdn/columns.js +1 -1
- package/clis/csdn/login.js +1 -1
- package/clis/csdn/stats.js +4 -4
- package/clis/csdn/whoami.js +1 -1
- package/clis/cto51/article.js +1 -1
- package/clis/cto51/whoami.js +1 -1
- package/clis/ctrip/flight.js +2 -2
- package/clis/ctrip/hotel-search.js +3 -3
- package/clis/ctrip/hotel-suggest.js +1 -1
- package/clis/ctrip/search.js +1 -1
- package/clis/ctrip/utils.js +6 -6
- package/clis/cursor/ask.js +5 -5
- package/clis/cursor/composer.js +2 -2
- package/clis/cursor/model.js +4 -4
- package/clis/cursor/send.js +2 -2
- package/clis/dblp/author.js +1 -1
- package/clis/dblp/paper.js +1 -1
- package/clis/dblp/search.js +1 -1
- package/clis/dblp/utils.js +1 -1
- package/clis/dblp/venue.js +1 -1
- package/clis/deepseek/ask.js +1 -1
- package/clis/deepseek/auth.js +2 -2
- package/clis/deepseek/detail.js +1 -1
- package/clis/deepseek/new.js +1 -1
- package/clis/deepseek/read.js +1 -1
- package/clis/deepseek/send.js +7 -7
- package/clis/deepseek/utils.js +25 -25
- package/clis/defillama/protocol.js +1 -1
- package/clis/defillama/protocols.js +1 -1
- package/clis/defillama/utils.js +1 -1
- package/clis/devto/auth.js +2 -2
- package/clis/devto/latest.js +1 -1
- package/clis/devto/publish.js +5 -5
- package/clis/devto/read.js +2 -2
- package/clis/devto/stats.js +3 -3
- package/clis/dianping/auth.js +2 -2
- package/clis/dianping/cityResolver.js +2 -2
- package/clis/dianping/search.js +1 -1
- package/clis/dianping/shop.js +1 -1
- package/clis/dianping/utils.js +1 -1
- package/clis/discord-app/delete.js +3 -3
- package/clis/discord-app/read.js +1 -1
- package/clis/discord-app/thread-read.js +1 -1
- package/clis/discord-web/auth.js +2 -2
- package/clis/discord-web/send.js +5 -5
- package/clis/dockerhub/image.js +1 -1
- package/clis/dockerhub/search.js +1 -1
- package/clis/dockerhub/utils.js +1 -1
- package/clis/dongchedi/koubei.js +1 -1
- package/clis/dongchedi/models.js +1 -1
- package/clis/dongchedi/score.js +1 -1
- package/clis/dongchedi/search.js +1 -1
- package/clis/dongchedi/series.js +1 -1
- package/clis/dongchedi/specs.js +1 -1
- package/clis/dongchedi/utils.js +1 -1
- package/clis/douban/article.js +3 -3
- package/clis/douban/auth.js +2 -2
- package/clis/douban/download.js +1 -1
- package/clis/douban/utils.js +23 -23
- package/clis/doubao/auth.js +3 -3
- package/clis/doubao/utils.js +39 -39
- package/clis/doubao-app/ask.js +1 -1
- package/clis/doubao-app/utils.js +4 -4
- package/clis/douyin/_shared/browser-fetch.js +7 -7
- package/clis/douyin/_shared/draft-cache.js +1 -1
- package/clis/douyin/_shared/imagex-upload.js +1 -1
- package/clis/douyin/_shared/sts2.js +1 -1
- package/clis/douyin/_shared/text-extra.js +1 -1
- package/clis/douyin/_shared/tos-upload.js +4 -4
- package/clis/douyin/_shared/transcode.js +1 -1
- package/clis/douyin/_shared/vod-upload.js +4 -4
- package/clis/douyin/draft.js +18 -18
- package/clis/douyin/drafts.js +1 -1
- package/clis/douyin/publish-image.js +12 -12
- package/clis/douyin/publish.js +9 -9
- package/clis/douyin/search.js +3 -3
- package/clis/douyin/videos.js +1 -1
- package/clis/eastmoney/_secid.js +1 -1
- package/clis/eastmoney/announcement.js +1 -1
- package/clis/eastmoney/article.js +1 -1
- package/clis/eastmoney/convertible.js +1 -1
- package/clis/eastmoney/etf.js +1 -1
- package/clis/eastmoney/holders.js +1 -1
- package/clis/eastmoney/index-board.js +1 -1
- package/clis/eastmoney/kline.js +1 -1
- package/clis/eastmoney/kuaixun.js +1 -1
- package/clis/eastmoney/longhu.js +1 -1
- package/clis/eastmoney/money-flow.js +1 -1
- package/clis/eastmoney/northbound.js +1 -1
- package/clis/eastmoney/quote.js +1 -1
- package/clis/eastmoney/rank.js +1 -1
- package/clis/eastmoney/sectors.js +1 -1
- package/clis/endoflife/product.js +1 -1
- package/clis/endoflife/utils.js +1 -1
- package/clis/facebook/comment.js +8 -8
- package/clis/facebook/feed.js +4 -4
- package/clis/facebook/like.js +5 -5
- package/clis/facebook/notifications.js +3 -3
- package/clis/facebook/post.js +11 -11
- package/clis/facebook/search.js +3 -3
- package/clis/flathub/app.js +1 -1
- package/clis/flathub/search.js +1 -1
- package/clis/flathub/utils.js +1 -1
- package/clis/flomo/memos.js +1 -1
- package/clis/gemini/deep-research-result.js +4 -4
- package/clis/gemini/deep-research.js +1 -1
- package/clis/gemini/detail.js +1 -1
- package/clis/gemini/history.js +1 -1
- package/clis/gemini/image.js +2 -2
- package/clis/gemini/status.js +1 -1
- package/clis/gemini/utils.js +43 -43
- package/clis/geogebra/hexagon.js +1 -1
- package/clis/geogebra/info.js +3 -3
- package/clis/geogebra/triangle.js +1 -1
- package/clis/geogebra/utils.js +11 -11
- package/clis/ghost/login.js +1 -1
- package/clis/ghost/shared.js +2 -2
- package/clis/gitee/auth.js +2 -2
- package/clis/github-trending/repos.js +1 -1
- package/clis/google/news.js +1 -1
- package/clis/google/search.js +2 -2
- package/clis/google/suggest.js +1 -1
- package/clis/google/trends.js +1 -1
- package/clis/google/utils.js +1 -1
- package/clis/goproxy/module.js +1 -1
- package/clis/goproxy/utils.js +1 -1
- package/clis/goproxy/versions.js +1 -1
- package/clis/gov-policy/recent.js +2 -2
- package/clis/gov-policy/search.js +2 -2
- package/clis/grok/ask.js +1 -1
- package/clis/grok/detail.js +1 -1
- package/clis/grok/image.js +8 -8
- package/clis/grok/pin.js +1 -1
- package/clis/grok/send.js +1 -1
- package/clis/grok/status.js +1 -1
- package/clis/grok/utils.js +21 -21
- package/clis/guazi/browse.js +1 -1
- package/clis/guazi/car.js +1 -1
- package/clis/guazi/utils.js +1 -1
- package/clis/hackernews/auth.js +2 -2
- package/clis/hackernews/comment.js +8 -8
- package/clis/hackernews/read.js +7 -7
- package/clis/hackernews/submit.js +7 -7
- package/clis/hashnode/auth.js +3 -3
- package/clis/hashnode/publish.js +14 -14
- package/clis/hf/auth.js +2 -2
- package/clis/hf/models.js +1 -1
- package/clis/hf/paper.js +1 -1
- package/clis/hf/spaces.js +1 -1
- package/clis/hf/top.js +1 -1
- package/clis/homebrew/cask.js +1 -1
- package/clis/homebrew/formula.js +1 -1
- package/clis/homebrew/popular.js +1 -1
- package/clis/homebrew/utils.js +1 -1
- package/clis/huodongxing/events.js +1 -1
- package/clis/hupu/detail.js +4 -4
- package/clis/hupu/hot.js +3 -3
- package/clis/hupu/reply.js +1 -1
- package/clis/hupu/search.js +1 -1
- package/clis/hupu/unlike.js +1 -1
- package/clis/hupu/utils.js +10 -10
- package/clis/imdb/person.js +2 -2
- package/clis/imdb/reviews.js +3 -3
- package/clis/imdb/search.js +2 -2
- package/clis/imdb/title.js +1 -1
- package/clis/imdb/top.js +1 -1
- package/clis/imdb/trending.js +1 -1
- package/clis/imdb/utils.js +13 -13
- package/clis/imooc/article.js +6 -6
- package/clis/imooc/login.js +1 -1
- package/clis/imooc/whoami.js +1 -1
- package/clis/indeed/job.js +2 -2
- package/clis/indeed/search.js +2 -2
- package/clis/indeed/utils.js +1 -1
- package/clis/infoq/article.js +2 -2
- package/clis/infoq/login.js +1 -1
- package/clis/infoq/whoami.js +1 -1
- package/clis/instagram/_shared/private-publish.js +4 -4
- package/clis/instagram/_shared/protocol-capture.js +9 -9
- package/clis/instagram/detail.js +3 -3
- package/clis/instagram/post.js +25 -25
- package/clis/instagram/reel.js +18 -18
- package/clis/instagram/story.js +4 -4
- package/clis/instagram/user.js +2 -2
- package/clis/jd/item.js +65 -65
- package/clis/jianshu/article.js +1 -1
- package/clis/jianshu/login.js +1 -1
- package/clis/jianshu/notebooks.js +1 -1
- package/clis/jianshu/whoami.js +1 -1
- package/clis/jianyu/search.js +6 -6
- package/clis/jianyu/shared/procurement-contract.js +1 -1
- package/clis/jike/api.js +6 -6
- package/clis/jike/auth.js +3 -3
- package/clis/jike/comment.js +1 -1
- package/clis/jike/create.js +6 -6
- package/clis/jike/feed.js +3 -3
- package/clis/jike/like.js +1 -1
- package/clis/jike/notifications.js +3 -3
- package/clis/jike/repost.js +13 -13
- package/clis/jike/search.js +3 -3
- package/clis/jimeng/auth.js +2 -2
- package/clis/jimeng/generate.js +10 -10
- package/clis/jira/shared.js +1 -1
- package/clis/juejin/article.js +4 -4
- package/clis/juejin/categories.js +1 -1
- package/clis/juejin/hot.js +1 -1
- package/clis/juejin/login.js +1 -1
- package/clis/juejin/recommend.js +1 -1
- package/clis/juejin/stats.js +3 -3
- package/clis/juejin/tags.js +1 -1
- package/clis/juejin/utils.js +1 -1
- package/clis/juejin/whoami.js +1 -1
- package/clis/ke/utils.js +4 -4
- package/clis/kimi/_utils.js +7 -7
- package/clis/kimi/audit-extras.js +14 -14
- package/clis/kimi/auth.js +3 -3
- package/clis/kimi/chat.js +15 -15
- package/clis/kimi/storage.js +5 -5
- package/clis/kimi/ui.js +13 -13
- package/clis/kimi/usage.js +3 -3
- package/clis/kuaishou/auth.js +1 -1
- package/clis/kuaishou/publish.js +6 -6
- package/clis/lesswrong/_helpers.js +5 -5
- package/clis/lesswrong/comments.js +5 -5
- package/clis/lichess/top.js +1 -1
- package/clis/lichess/user.js +1 -1
- package/clis/lichess/utils.js +1 -1
- package/clis/linkedin/comment.js +1 -1
- package/clis/linkedin/connect.js +11 -11
- package/clis/linkedin/create.js +5 -5
- package/clis/linkedin/follow.js +1 -1
- package/clis/linkedin/inbox.js +1 -1
- package/clis/linkedin/job-detail.js +3 -3
- package/clis/linkedin/like.js +1 -1
- package/clis/linkedin/notifications.js +1 -1
- package/clis/linkedin/people-search.js +1 -1
- package/clis/linkedin/post-comments.js +1 -1
- package/clis/linkedin/post-detail.js +1 -1
- package/clis/linkedin/profile-analytics.js +1 -1
- package/clis/linkedin/profile-api.js +13 -13
- package/clis/linkedin/profile-experience.js +1 -1
- package/clis/linkedin/profile-projects.js +1 -1
- package/clis/linkedin/profile-read.js +3 -3
- package/clis/linkedin/reply.js +1 -1
- package/clis/linkedin/repost.js +1 -1
- package/clis/linkedin/safe-send.js +8 -8
- package/clis/linkedin/salesnav-inbox.js +5 -5
- package/clis/linkedin/salesnav-message.js +3 -3
- package/clis/linkedin/salesnav-search.js +4 -4
- package/clis/linkedin/salesnav-thread.js +1 -1
- package/clis/linkedin/search-api.js +3 -3
- package/clis/linkedin/search.js +8 -8
- package/clis/linkedin/social-api.js +31 -31
- package/clis/linkedin/timeline.js +3 -3
- package/clis/linkedin-learning/search.js +2 -2
- package/clis/linkedin-learning/trending.js +2 -2
- package/clis/linux-do/feed.js +4 -4
- package/clis/linux-do/topic-content.js +8 -8
- package/clis/lobsters/domain.js +1 -1
- package/clis/lobsters/read.js +7 -7
- package/clis/maimai/auth.js +2 -2
- package/clis/maimai/search-talents.js +4 -4
- package/clis/manus/_utils.js +1 -1
- package/clis/mastodon/login.js +1 -1
- package/clis/mastodon/post.js +1 -1
- package/clis/mastodon/shared.js +12 -12
- package/clis/mastodon/whoami.js +1 -1
- package/clis/maven/artifact.js +1 -1
- package/clis/maven/search.js +1 -1
- package/clis/maven/utils.js +1 -1
- package/clis/mdn/search.js +1 -1
- package/clis/medium/article.js +5 -5
- package/clis/medium/login.js +1 -1
- package/clis/medium/stats.js +3 -3
- package/clis/medium/tag.js +1 -1
- package/clis/medium/whoami.js +1 -1
- package/clis/mubu/notes.js +1 -1
- package/clis/mubu/utils.js +15 -15
- package/clis/note/auth.js +2 -2
- package/clis/note/note-utils.js +2 -2
- package/clis/note/publish.js +8 -8
- package/clis/notebooklm/add-source.js +8 -8
- package/clis/notebooklm/create.js +1 -1
- package/clis/notebooklm/generate-slides.js +1 -1
- package/clis/notebooklm/notes-get.js +1 -1
- package/clis/notebooklm/rpc.js +8 -8
- package/clis/notebooklm/source-fulltext.js +1 -1
- package/clis/notebooklm/utils.js +10 -10
- package/clis/nowcoder/auth.js +2 -2
- package/clis/nowcoder/comment.js +1 -1
- package/clis/nowcoder/comments.js +1 -1
- package/clis/nowcoder/dm-list.js +1 -1
- package/clis/nowcoder/dm-read.js +1 -1
- package/clis/nowcoder/dm-send.js +1 -1
- package/clis/nowcoder/drafts.js +1 -1
- package/clis/nowcoder/inbox.js +1 -1
- package/clis/nowcoder/like.js +1 -1
- package/clis/nowcoder/my.js +1 -1
- package/clis/nowcoder/post.js +1 -1
- package/clis/nowcoder/utils.js +13 -13
- package/clis/npm/downloads.js +1 -1
- package/clis/npm/package.js +1 -1
- package/clis/npm/search.js +1 -1
- package/clis/npm/utils.js +1 -1
- package/clis/nuget/package.js +1 -1
- package/clis/nuget/search.js +1 -1
- package/clis/nuget/utils.js +1 -1
- package/clis/nvd/cve.js +1 -1
- package/clis/oeis/search.js +1 -1
- package/clis/oeis/sequence.js +1 -1
- package/clis/oeis/utils.js +1 -1
- package/clis/ones/common.js +6 -6
- package/clis/ones/enrich-tasks.js +1 -1
- package/clis/ones/my-tasks.js +1 -1
- package/clis/ones/resolve-labels.js +1 -1
- package/clis/ones/task-helpers.js +1 -1
- package/clis/ones/task.js +1 -1
- package/clis/ones/worklog.js +7 -7
- package/clis/openalex/search.js +1 -1
- package/clis/openalex/utils.js +1 -1
- package/clis/openalex/work.js +1 -1
- package/clis/openfda/drug-label.js +1 -1
- package/clis/openfda/food-recall.js +1 -1
- package/clis/openfda/utils.js +1 -1
- package/clis/openreview/author.js +1 -1
- package/clis/openreview/paper.js +1 -1
- package/clis/openreview/reviews.js +3 -3
- package/clis/openreview/search.js +1 -1
- package/clis/openreview/utils.js +1 -1
- package/clis/openreview/venue.js +1 -1
- package/clis/oschina/article.js +1 -1
- package/clis/oschina/catalogs.js +1 -1
- package/clis/oschina/login.js +1 -1
- package/clis/oschina/stats.js +6 -6
- package/clis/oschina/whoami.js +1 -1
- package/clis/osv/query.js +1 -1
- package/clis/osv/utils.js +1 -1
- package/clis/osv/vulnerability.js +1 -1
- package/clis/packagist/package.js +1 -1
- package/clis/packagist/search.js +1 -1
- package/clis/packagist/utils.js +1 -1
- package/clis/pinterest/api.js +1 -1
- package/clis/pinterest/auth.js +1 -1
- package/clis/pinterest/boards.js +1 -1
- package/clis/pinterest/client.js +6 -6
- package/clis/pinterest/publish.js +5 -5
- package/clis/pixiv/auth.js +2 -2
- package/clis/pixiv/download.js +1 -1
- package/clis/pixiv/illusts.js +1 -1
- package/clis/pixiv/search.js +1 -1
- package/clis/pixiv/utils.js +3 -3
- package/clis/powerchina/auth.js +2 -2
- package/clis/powerchina/search.js +1 -1
- package/clis/producthunt/browse.js +2 -2
- package/clis/producthunt/hot.js +2 -2
- package/clis/producthunt/posts.js +1 -1
- package/clis/producthunt/today.js +1 -1
- package/clis/producthunt/utils.js +1 -1
- package/clis/pypi/downloads.js +1 -1
- package/clis/pypi/package.js +1 -1
- package/clis/pypi/utils.js +1 -1
- package/clis/qiita/auth.js +1 -1
- package/clis/qiita/gql.js +6 -6
- package/clis/qiita/publish.js +4 -4
- package/clis/qiita/stats.js +4 -4
- package/clis/qoder/_utils.js +16 -16
- package/clis/qoder/composer.js +1 -1
- package/clis/qoder/quest.js +1 -1
- package/clis/qoder/ui.js +14 -14
- package/clis/quark/auth.js +2 -2
- package/clis/quark/utils.js +2 -2
- package/clis/quora/answer-comments.js +3 -3
- package/clis/quora/create-answer.js +4 -4
- package/clis/quora/create-question.js +3 -3
- package/clis/quora/shared.js +17 -17
- package/clis/quora/whoami.js +1 -1
- package/clis/qwen/ask.js +1 -1
- package/clis/qwen/auth.js +3 -3
- package/clis/qwen/detail.js +1 -1
- package/clis/qwen/image.js +5 -5
- package/clis/qwen/status.js +1 -1
- package/clis/qwen/utils.js +16 -16
- package/clis/reddit/home.js +3 -3
- package/clis/reddit/read.js +10 -10
- package/clis/reddit/reply.js +4 -4
- package/clis/reddit/submit.js +11 -11
- package/clis/reddit/subreddit-info.js +3 -3
- package/clis/reddit/subscribed.js +4 -4
- package/clis/reddit/whoami.js +2 -2
- package/clis/rednote/comments.js +1 -1
- package/clis/rednote/download.js +1 -1
- package/clis/rednote/feed.js +1 -1
- package/clis/rednote/note.js +1 -1
- package/clis/rednote/notifications.js +2 -2
- package/clis/rednote/search.js +2 -2
- package/clis/rest-countries/country.js +1 -1
- package/clis/rest-countries/region.js +1 -1
- package/clis/rest-countries/utils.js +1 -1
- package/clis/reuters/article-detail.js +1 -1
- package/clis/reuters/auth.js +3 -3
- package/clis/reuters/search.js +1 -1
- package/clis/reuters/utils.js +4 -4
- package/clis/rfc/rfc.js +1 -1
- package/clis/rfc/utils.js +1 -1
- package/clis/rubygems/gem.js +1 -1
- package/clis/rubygems/search.js +1 -1
- package/clis/rubygems/utils.js +1 -1
- package/clis/segmentfault/article.js +3 -3
- package/clis/segmentfault/channels.js +1 -1
- package/clis/segmentfault/login.js +1 -1
- package/clis/segmentfault/stats.js +4 -4
- package/clis/segmentfault/tags.js +1 -1
- package/clis/segmentfault/whoami.js +1 -1
- package/clis/semanticscholar/citations.js +1 -1
- package/clis/semanticscholar/paper.js +1 -1
- package/clis/semanticscholar/recommendations.js +1 -1
- package/clis/semanticscholar/search.js +1 -1
- package/clis/semanticscholar/utils.js +1 -1
- package/clis/sinafinance/news.js +1 -1
- package/clis/sinafinance/stock-rank.js +1 -1
- package/clis/sinafinance/stock.js +1 -1
- package/clis/slock/attachment-download.js +1 -1
- package/clis/slock/attachment-upload.js +7 -7
- package/clis/slock/attachment-url.js +1 -1
- package/clis/slock/auth-verify.js +1 -1
- package/clis/slock/bookmark-add.js +1 -1
- package/clis/slock/bookmark-remove.js +1 -1
- package/clis/slock/channel-action.js +1 -1
- package/clis/slock/channel-create.js +1 -1
- package/clis/slock/channel-files.js +1 -1
- package/clis/slock/channel-list.js +1 -1
- package/clis/slock/channel-mark.js +1 -1
- package/clis/slock/channel-members.js +1 -1
- package/clis/slock/channel-unarchive.js +1 -1
- package/clis/slock/dm-list.js +1 -1
- package/clis/slock/errors.js +1 -1
- package/clis/slock/in-page.js +28 -28
- package/clis/slock/inbox-done.js +5 -5
- package/clis/slock/inbox.js +1 -1
- package/clis/slock/message-read.js +22 -22
- package/clis/slock/message-search.js +10 -10
- package/clis/slock/message-send.js +25 -25
- package/clis/slock/reaction-add.js +1 -1
- package/clis/slock/reaction-remove.js +1 -1
- package/clis/slock/resolve.js +1 -1
- package/clis/slock/server-list.js +2 -2
- package/clis/slock/task-claim.js +4 -4
- package/clis/slock/task-convert.js +13 -13
- package/clis/slock/task-create.js +1 -1
- package/clis/slock/task-delete.js +5 -5
- package/clis/slock/task-get.js +5 -5
- package/clis/slock/task-list-server.js +4 -4
- package/clis/slock/task-list.js +5 -5
- package/clis/slock/task-status.js +3 -3
- package/clis/slock/task-unclaim.js +3 -3
- package/clis/slock/thread-follow.js +1 -1
- package/clis/slock/thread-state.js +1 -1
- package/clis/slock/unread-summary.js +5 -5
- package/clis/slock/whoami.js +1 -1
- package/clis/smzdm/search.js +3 -3
- package/clis/sohu/article.js +1 -1
- package/clis/sohu/attributes.js +1 -1
- package/clis/sohu/categories.js +1 -1
- package/clis/sohu/channels.js +1 -1
- package/clis/sohu/columns.js +1 -1
- package/clis/sohu/login.js +1 -1
- package/clis/sohu/stats.js +3 -3
- package/clis/sohu/topics.js +1 -1
- package/clis/sohu/whoami.js +1 -1
- package/clis/spotify/spotify.js +1 -1
- package/clis/stackoverflow/read.js +6 -6
- package/clis/stackoverflow/related.js +1 -1
- package/clis/stackoverflow/tag.js +1 -1
- package/clis/stackoverflow/user.js +1 -1
- package/clis/stackoverflow/utils.js +1 -1
- package/clis/steam/app.js +1 -1
- package/clis/steam/search.js +1 -1
- package/clis/steam/utils.js +1 -1
- package/clis/substack/auth.js +2 -2
- package/clis/substack/post-utils.js +2 -2
- package/clis/substack/publish.js +5 -5
- package/clis/suno/auth.js +2 -2
- package/clis/suno/download.js +5 -5
- package/clis/suno/generate.js +3 -3
- package/clis/suno/list.js +1 -1
- package/clis/suno/status.js +1 -1
- package/clis/suno/utils.js +29 -29
- package/clis/telegram/send.js +7 -7
- package/clis/telegram/shared.js +2 -2
- package/clis/telegram/whoami.js +1 -1
- package/clis/test-utils.js +1 -1
- package/clis/threads/post.js +23 -23
- package/clis/threads/shared.js +3 -3
- package/clis/threads/whoami.js +1 -1
- package/clis/tieba/hot.js +3 -3
- package/clis/tieba/posts.js +1 -1
- package/clis/tieba/read.js +2 -2
- package/clis/tieba/search.js +3 -3
- package/clis/tieba/utils.js +1 -1
- package/clis/tiktok/comment.js +2 -2
- package/clis/tiktok/creator-videos.js +3 -3
- package/clis/tiktok/explore.js +3 -3
- package/clis/tiktok/follow.js +8 -8
- package/clis/tiktok/following.js +4 -4
- package/clis/tiktok/friends.js +7 -7
- package/clis/tiktok/live.js +3 -3
- package/clis/tiktok/notifications.js +6 -6
- package/clis/tiktok/publish.js +16 -16
- package/clis/tiktok/unfollow.js +4 -4
- package/clis/tiktok/user.js +2 -2
- package/clis/tiktok/utils.js +1 -1
- package/clis/toutiao/article.js +1 -1
- package/clis/toutiao/articles.js +2 -2
- package/clis/toutiao/auth.js +2 -2
- package/clis/toutiao/hot.js +1 -1
- package/clis/toutiao/recommend.js +1 -1
- package/clis/toutiao/utils.js +2 -2
- package/clis/trae-solo/_actions.js +4 -4
- package/clis/trae-solo/_fs.js +5 -5
- package/clis/trae-solo/_state.js +2 -2
- package/clis/trae-solo/automation.js +4 -4
- package/clis/trae-solo/mode.js +4 -4
- package/clis/trae-solo/model.js +4 -4
- package/clis/trae-solo/renderer-storage.js +4 -4
- package/clis/trae-solo/settings.js +1 -1
- package/clis/trae-solo/skill-fs.js +1 -1
- package/clis/trae-solo/skill.js +12 -12
- package/clis/trae-solo/state-fs.js +2 -2
- package/clis/trae-solo/task-fs.js +5 -5
- package/clis/trae-solo/workspaces-fs.js +1 -1
- package/clis/tumblr/auth.js +2 -2
- package/clis/tumblr/publish.js +3 -3
- package/clis/tvmaze/search.js +1 -1
- package/clis/tvmaze/show.js +1 -1
- package/clis/tvmaze/utils.js +1 -1
- package/clis/twitter/accept.js +7 -7
- package/clis/twitter/article.js +7 -7
- package/clis/twitter/bookmark-folder.js +3 -3
- package/clis/twitter/bookmark-folders.js +3 -3
- package/clis/twitter/bookmarks.js +4 -4
- package/clis/twitter/delete.js +5 -5
- package/clis/twitter/device-follow.js +3 -3
- package/clis/twitter/dm-list.js +1 -1
- package/clis/twitter/dm-read.js +1 -1
- package/clis/twitter/dm-send.js +5 -5
- package/clis/twitter/dm-shared.js +3 -3
- package/clis/twitter/download.js +6 -6
- package/clis/twitter/followers.js +5 -5
- package/clis/twitter/following.js +2 -2
- package/clis/twitter/like.js +3 -3
- package/clis/twitter/likes.js +8 -8
- package/clis/twitter/list-add-core.js +9 -9
- package/clis/twitter/list-create.js +5 -5
- package/clis/twitter/list-remove-core.js +9 -9
- package/clis/twitter/list-tweets.js +7 -7
- package/clis/twitter/lists.js +6 -6
- package/clis/twitter/notifications.js +2 -2
- package/clis/twitter/post.js +24 -24
- package/clis/twitter/profile.js +7 -7
- package/clis/twitter/quote.js +7 -7
- package/clis/twitter/reply-dm.js +7 -7
- package/clis/twitter/reply.js +12 -12
- package/clis/twitter/retweet.js +3 -3
- package/clis/twitter/scheduled-delete.js +3 -3
- package/clis/twitter/scheduled-list.js +2 -2
- package/clis/twitter/scheduled-utils.js +3 -3
- package/clis/twitter/search.js +5 -5
- package/clis/twitter/shared.js +6 -6
- package/clis/twitter/thread.js +4 -4
- package/clis/twitter/timeline.js +3 -3
- package/clis/twitter/trending.js +2 -2
- package/clis/twitter/tweets.js +11 -11
- package/clis/twitter/unlike.js +3 -3
- package/clis/twitter/unretweet.js +3 -3
- package/clis/twitter/utils.js +6 -6
- package/clis/upwork/detail.js +2 -2
- package/clis/upwork/feed.js +2 -2
- package/clis/upwork/search.js +2 -2
- package/clis/upwork/utils.js +1 -1
- package/clis/v2ex/auth.js +2 -2
- package/clis/v2ex/daily.js +3 -3
- package/clis/v2ex/me.js +2 -2
- package/clis/v2ex/notifications.js +2 -2
- package/clis/vk/post.js +1 -1
- package/clis/vk/shared.js +2 -2
- package/clis/vk/whoami.js +1 -1
- package/clis/web/read.js +8 -8
- package/clis/wechat-channels/auth.js +2 -2
- package/clis/wechat-channels/publish.js +30 -30
- package/clis/weibo/article.js +1 -1
- package/clis/weibo/auth.js +3 -3
- package/clis/weibo/comments.js +1 -1
- package/clis/weibo/delete.js +2 -2
- package/clis/weibo/feed.js +3 -3
- package/clis/weibo/hot.js +1 -1
- package/clis/weibo/publish.js +10 -10
- package/clis/weibo/search.js +2 -2
- package/clis/weibo/user-posts.js +3 -3
- package/clis/weibo/user.js +2 -2
- package/clis/weibo/utils.js +3 -3
- package/clis/weixin/article.js +1 -1
- package/clis/weixin/create-draft.js +26 -26
- package/clis/weixin/download.js +2 -2
- package/clis/weixin/login.js +1 -1
- package/clis/weixin/search.js +2 -2
- package/clis/weixin/stats.js +3 -3
- package/clis/weixin/whoami.js +1 -1
- package/clis/weread/ai-outline.js +2 -2
- package/clis/weread/book-search.js +2 -2
- package/clis/weread/book.js +2 -2
- package/clis/weread/notebooks.js +1 -1
- package/clis/weread/search.js +1 -1
- package/clis/weread/shelf.js +1 -1
- package/clis/weread/utils.js +6 -6
- package/clis/weread-official/book.js +1 -1
- package/clis/weread-official/discover.js +1 -1
- package/clis/weread-official/list-apis.js +1 -1
- package/clis/weread-official/notes.js +1 -1
- package/clis/weread-official/readdata.js +1 -1
- package/clis/weread-official/review.js +1 -1
- package/clis/weread-official/search.js +1 -1
- package/clis/weread-official/shelf.js +1 -1
- package/clis/weread-official/utils.js +1 -1
- package/clis/wikidata/entity.js +1 -1
- package/clis/wikidata/search.js +1 -1
- package/clis/wikidata/utils.js +1 -1
- package/clis/wikipedia/page.js +1 -1
- package/clis/wikipedia/trending.js +1 -1
- package/clis/wikipedia/utils.js +1 -1
- package/clis/wordpress/login.js +1 -1
- package/clis/wordpress/publish.js +1 -1
- package/clis/wordpress/shared.js +3 -3
- package/clis/wordpress/whoami.js +1 -1
- package/clis/woshipm/article.js +1 -1
- package/clis/woshipm/login.js +1 -1
- package/clis/woshipm/stats.js +4 -4
- package/clis/woshipm/whoami.js +1 -1
- package/clis/wttr/current.js +1 -1
- package/clis/wttr/forecast.js +1 -1
- package/clis/wttr/utils.js +1 -1
- package/clis/xianyu/collect.js +1 -1
- package/clis/xianyu/inbox.js +1 -1
- package/clis/xianyu/item-stats.js +2 -2
- package/clis/xianyu/location.js +1 -1
- package/clis/xianyu/manage.js +1 -1
- package/clis/xianyu/messages.js +1 -1
- package/clis/xianyu/mtop.js +5 -5
- package/clis/xianyu/order.js +1 -1
- package/clis/xianyu/promote-stats.js +2 -2
- package/clis/xianyu/publish.js +17 -17
- package/clis/xianyu/rate.js +1 -1
- package/clis/xianyu/reply.js +1 -1
- package/clis/xianyu/search.js +8 -8
- package/clis/xianyu/seller-data.js +1 -1
- package/clis/xianyu/seller-list.js +1 -1
- package/clis/xianyu/user.js +1 -1
- package/clis/xiaoe/catalog.js +2 -2
- package/clis/xiaoe/content.js +2 -2
- package/clis/xiaoe/courses.js +2 -2
- package/clis/xiaohongshu/ask.js +6 -6
- package/clis/xiaohongshu/comments.js +6 -6
- package/clis/xiaohongshu/creator-note-detail.js +7 -7
- package/clis/xiaohongshu/creator-notes-summary.js +1 -1
- package/clis/xiaohongshu/creator-notes.js +13 -13
- package/clis/xiaohongshu/creator-profile.js +2 -2
- package/clis/xiaohongshu/creator-stats.js +2 -2
- package/clis/xiaohongshu/delete-note.js +7 -7
- package/clis/xiaohongshu/download.js +4 -4
- package/clis/xiaohongshu/feed.js +2 -2
- package/clis/xiaohongshu/follow.js +3 -3
- package/clis/xiaohongshu/human.js +3 -3
- package/clis/xiaohongshu/note-helpers.js +1 -1
- package/clis/xiaohongshu/note.js +2 -2
- package/clis/xiaohongshu/notifications.js +1 -1
- package/clis/xiaohongshu/publish-video.js +8 -8
- package/clis/xiaohongshu/publish.js +59 -59
- package/clis/xiaohongshu/search.js +8 -8
- package/clis/xiaohongshu/unfollow.js +4 -4
- package/clis/xiaohongshu/user-helpers.js +1 -1
- package/clis/xiaohongshu/user.js +2 -2
- package/clis/xiaoyuzhou/auth.js +3 -3
- package/clis/xiaoyuzhou/download.js +1 -1
- package/clis/xiaoyuzhou/utils.js +1 -1
- package/clis/xueqiu/article.js +4 -4
- package/clis/xueqiu/comments.js +4 -4
- package/clis/xueqiu/danjuan-utils.js +4 -4
- package/clis/xueqiu/earnings-date.js +1 -1
- package/clis/xueqiu/events.js +3 -3
- package/clis/xueqiu/hashtags.js +3 -3
- package/clis/xueqiu/stocks.js +3 -3
- package/clis/xueqiu/users.js +3 -3
- package/clis/xueqiu/utils.js +3 -3
- package/clis/yahoo-finance/quote.js +1 -1
- package/clis/yollomi/background.js +1 -1
- package/clis/yollomi/edit.js +1 -1
- package/clis/yollomi/face-swap.js +1 -1
- package/clis/yollomi/generate.js +1 -1
- package/clis/yollomi/object-remover.js +1 -1
- package/clis/yollomi/remove-bg.js +1 -1
- package/clis/yollomi/restore.js +1 -1
- package/clis/yollomi/try-on.js +1 -1
- package/clis/yollomi/upload.js +4 -4
- package/clis/yollomi/upscale.js +1 -1
- package/clis/yollomi/utils.js +4 -4
- package/clis/yollomi/video.js +1 -1
- package/clis/youtube/channel.js +4 -4
- package/clis/youtube/feed.js +2 -2
- package/clis/youtube/like.js +5 -5
- package/clis/youtube/playlist.js +7 -7
- package/clis/youtube/publish.js +11 -11
- package/clis/youtube/search.js +3 -3
- package/clis/youtube/subscribe.js +7 -7
- package/clis/youtube/subscriptions.js +1 -1
- package/clis/youtube/transcript-group.js +2 -2
- package/clis/youtube/transcript.js +13 -13
- package/clis/youtube/unlike.js +5 -5
- package/clis/youtube/unsubscribe.js +7 -7
- package/clis/youtube/utils.js +3 -3
- package/clis/youtube/video.js +4 -4
- package/clis/youtube/watch-later.js +2 -2
- package/clis/yuanbao/ask.js +18 -18
- package/clis/yuanbao/detail.js +1 -1
- package/clis/yuanbao/read.js +1 -1
- package/clis/yuanbao/shared.js +9 -9
- package/clis/yuanbao/status.js +1 -1
- package/clis/yuque/article.js +1 -1
- package/clis/yuque/whoami.js +1 -1
- package/clis/zhihu/answer-comments.js +2 -2
- package/clis/zhihu/answer-detail.js +3 -3
- package/clis/zhihu/answer.js +1 -1
- package/clis/zhihu/article-transform.js +1 -1
- package/clis/zhihu/article.js +1 -1
- package/clis/zhihu/auth.js +2 -2
- package/clis/zhihu/collection.js +3 -3
- package/clis/zhihu/collections.js +3 -3
- package/clis/zhihu/download.js +2 -2
- package/clis/zhihu/image-profile.js +6 -6
- package/clis/zhihu/paginate.js +3 -3
- package/clis/zhihu/pin.js +4 -4
- package/clis/zhihu/question.js +3 -3
- package/clis/zhihu/recommend.js +3 -3
- package/clis/zhihu/search.js +3 -3
- package/clis/zhihu/stats.js +3 -3
- package/clis/zhihu/user-arg.js +1 -1
- package/clis/zhihu/write-shared.js +7 -7
- package/clis/zlibrary/utils.js +6 -6
- package/clis/zsxq/auth.js +3 -3
- package/clis/zsxq/search.js +1 -1
- package/clis/zsxq/topic.js +1 -1
- package/clis/zsxq/utils.js +5 -5
- package/dist/src/adapter-source.js +1 -1
- package/dist/src/browser/analyze.js +1 -1
- package/dist/src/browser/article-extract.js +2 -2
- package/dist/src/browser/ax-snapshot.js +2 -2
- package/dist/src/browser/base-page.js +25 -25
- package/dist/src/browser/bridge.js +1 -1
- package/dist/src/browser/cdp.js +1 -1
- package/dist/src/browser/daemon-client.js +1 -1
- package/dist/src/browser/daemon-lifecycle.js +7 -7
- package/dist/src/browser/dom-helpers.js +35 -35
- package/dist/src/browser/dom-snapshot.js +19 -19
- package/dist/src/browser/errors.js +3 -3
- package/dist/src/browser/extract.js +5 -5
- package/dist/src/browser/find.js +13 -13
- package/dist/src/browser/fingerprint.js +2 -2
- package/dist/src/browser/html-tree.js +6 -6
- package/dist/src/browser/managed-chrome.js +1 -1
- package/dist/src/browser/network-cache.js +1 -1
- package/dist/src/browser/network-key.js +1 -1
- package/dist/src/browser/page.js +7 -7
- package/dist/src/browser/profile.js +2 -2
- package/dist/src/browser/proxy-test.js +8 -8
- package/dist/src/browser/shape-filter.js +1 -1
- package/dist/src/browser/shape.js +1 -1
- package/dist/src/browser/stealth.js +3 -3
- package/dist/src/browser/tabs.js +2 -2
- package/dist/src/browser/target-errors.js +1 -1
- package/dist/src/browser/target-resolver.js +23 -23
- package/dist/src/browser/trace.js +2 -2
- package/dist/src/browser/utils.js +1 -1
- package/dist/src/browser/verify-fixture.js +2 -2
- package/dist/src/browser-session-lock.js +1 -1
- package/dist/src/build-manifest.js +11 -11
- package/dist/src/capabilityRouting.js +1 -1
- package/dist/src/cli-argv-preprocess.js +1 -1
- package/dist/src/cli.js +32 -32
- package/dist/src/commanderAdapter.js +3 -3
- package/dist/src/commands/auth.js +3 -3
- package/dist/src/commands/daemon.js +1 -1
- package/dist/src/completion-fast.js +1 -1
- package/dist/src/completion.js +1 -1
- package/dist/src/constants.js +1 -1
- package/dist/src/convention-audit.js +2 -2
- package/dist/src/daemon-utils.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/discovery.js +2 -2
- package/dist/src/doctor.js +9 -9
- package/dist/src/download/article-download.js +15 -15
- package/dist/src/download/index.js +4 -4
- package/dist/src/download/media-download.js +1 -1
- package/dist/src/download/progress.js +3 -3
- package/dist/src/electron-apps.js +1 -1
- package/dist/src/errors.js +2 -2
- package/dist/src/execution.js +2 -2
- package/dist/src/external.js +1 -1
- package/dist/src/help.js +8 -8
- package/dist/src/hooks.js +1 -1
- package/dist/src/interceptor.js +21 -21
- package/dist/src/launcher.js +7 -7
- package/dist/src/logger.js +8 -8
- package/dist/src/main.js +7 -7
- package/dist/src/observation/artifact.js +5 -5
- package/dist/src/observation/retention.js +1 -1
- package/dist/src/output.js +2 -2
- package/dist/src/package-paths.js +1 -1
- package/dist/src/pipeline/executor.js +1 -1
- package/dist/src/pipeline/registry.js +1 -1
- package/dist/src/pipeline/steps/browser.js +1 -1
- package/dist/src/pipeline/steps/download.js +1 -1
- package/dist/src/pipeline/steps/fetch.js +6 -6
- package/dist/src/pipeline/steps/intercept.js +1 -1
- package/dist/src/pipeline/steps/tap.js +17 -17
- package/dist/src/pipeline/steps/transform.js +1 -1
- package/dist/src/pipeline/template.js +1 -1
- package/dist/src/plugin-manifest.js +1 -1
- package/dist/src/plugin-scaffold.js +19 -19
- package/dist/src/plugin.js +12 -12
- package/dist/src/rate-limit.js +1 -1
- package/dist/src/registry.js +1 -1
- package/dist/src/runtime-detect.js +1 -1
- package/dist/src/runtime.js +1 -1
- package/dist/src/scripts/framework.js +1 -1
- package/dist/src/scripts/interact.js +1 -1
- package/dist/src/scripts/store.js +1 -1
- package/dist/src/serialization.js +2 -2
- package/dist/src/session-lease.js +1 -1
- package/dist/src/snapshotFormatter.js +2 -2
- package/dist/src/tui.js +12 -12
- package/dist/src/user-runtime.js +1 -1
- package/dist/src/utils.d.ts +12 -0
- package/dist/src/utils.js +4 -4
- package/dist/src/validate.js +2 -2
- package/dist/src/verify.js +2 -2
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
package/clis/douyin/draft.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as f from"node:fs";import*as s from"node:path";import{cli as w,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentError as c,CommandExecutionError as l}from"@jackwener/opencli/errors";import{setInputFiles as p}from"../_shared/file-inject.js";const m={public:"公开",friends:"好友可见",private:"仅自己可见"},h="https://creator.douyin.com/creator-micro/content/upload",T=120,A=20,x=20,E=200;async function b(t){await t.evaluate(`() => {
|
|
2
2
|
const targets = ['我知道了', '知道了', '关闭'];
|
|
3
3
|
for (const text of targets) {
|
|
4
4
|
const btn = Array.from(document.querySelectorAll('button,[role="button"]'))
|
|
5
5
|
.find((el) => (el.textContent || '').trim() === text);
|
|
6
6
|
if (btn instanceof HTMLElement) btn.click();
|
|
7
7
|
}
|
|
8
|
-
}`)}async function
|
|
8
|
+
}`)}async function S(t){let n={href:"",ready:!1,bodyText:""};for(let e=0;e<T;e+=1){n=await t.evaluate(`() => ({
|
|
9
9
|
href: location.href,
|
|
10
10
|
ready: !!Array.from(document.querySelectorAll('input')).find(
|
|
11
11
|
(el) => (el.placeholder || '').includes('填写作品标题')
|
|
@@ -13,7 +13,7 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
|
|
|
13
13
|
(el) => (el.textContent || '').includes('暂存离开')
|
|
14
14
|
),
|
|
15
15
|
bodyText: document.body?.innerText || ''
|
|
16
|
-
})`);if(
|
|
16
|
+
})`);if(n.ready)return;await t.wait({time:0.5})}throw new l("等待抖音草稿编辑页超时",`当前页面: ${n.href||"unknown"}`)}async function I(t,n){for(let e=0;e<E;e+=1){const i=await t.evaluate(`() => {
|
|
17
17
|
const text = document.body?.innerText || '';
|
|
18
18
|
const uploading = /上传中|上传\\s*\\d+%|视频上传中|处理中/.test(text);
|
|
19
19
|
const saveBtn = Array.from(document.querySelectorAll('button')).find(
|
|
@@ -24,10 +24,10 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
|
|
|
24
24
|
: false;
|
|
25
25
|
const hasCaptionEditor = !!document.querySelector('[contenteditable="true"]');
|
|
26
26
|
const hasVisibility = !!Array.from(document.querySelectorAll('label')).find(
|
|
27
|
-
(el) => (el.textContent || '').includes(${JSON.stringify(
|
|
27
|
+
(el) => (el.textContent || '').includes(${JSON.stringify(n)})
|
|
28
28
|
);
|
|
29
29
|
return { uploading, saveEnabled, hasSaveBtn: !!saveBtn, hasCaptionEditor, hasVisibility };
|
|
30
|
-
}`);if(
|
|
30
|
+
}`);if(i.hasSaveBtn&&i.saveEnabled&&i.hasCaptionEditor&&i.hasVisibility&&!i.uploading)return;await t.wait({time:0.5})}}async function k(t,n){const e=60;let i=!1;for(let o=0;o<e;o+=1){i=await t.evaluate(`() => {
|
|
31
31
|
const titleInput = Array.from(document.querySelectorAll('input')).find(
|
|
32
32
|
(el) => (el.placeholder || '').includes('填写作品标题')
|
|
33
33
|
);
|
|
@@ -36,12 +36,12 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
|
|
|
36
36
|
const props = propKey ? titleInput[propKey] : null;
|
|
37
37
|
if (props?.onChange) {
|
|
38
38
|
props.onChange({
|
|
39
|
-
target: { value: ${JSON.stringify(
|
|
40
|
-
currentTarget: { value: ${JSON.stringify(
|
|
39
|
+
target: { value: ${JSON.stringify(n.title)} },
|
|
40
|
+
currentTarget: { value: ${JSON.stringify(n.title)} },
|
|
41
41
|
});
|
|
42
42
|
} else {
|
|
43
43
|
titleInput.focus();
|
|
44
|
-
titleInput.value = ${JSON.stringify(
|
|
44
|
+
titleInput.value = ${JSON.stringify(n.title)};
|
|
45
45
|
titleInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
46
46
|
titleInput.dispatchEvent(new Event('change', { bubbles: true }));
|
|
47
47
|
}
|
|
@@ -55,23 +55,23 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
|
|
|
55
55
|
titleInput.dispatchEvent(new Event('blur', { bubbles: true }));
|
|
56
56
|
}
|
|
57
57
|
return true;
|
|
58
|
-
}`);if(
|
|
58
|
+
}`);if(i)break;await t.wait({time:0.5})}if(!i)throw new l("填写抖音草稿表单失败: title-input-missing");if(n.caption){let o=!1;for(let a=0;a<e;a+=1){o=await t.evaluate(`() => {
|
|
59
59
|
const editor = document.querySelector('[contenteditable="true"]');
|
|
60
60
|
if (!(editor instanceof HTMLElement)) return false;
|
|
61
61
|
editor.focus();
|
|
62
62
|
editor.textContent = '';
|
|
63
63
|
document.execCommand('selectAll', false);
|
|
64
|
-
document.execCommand('insertText', false, ${JSON.stringify(
|
|
64
|
+
document.execCommand('insertText', false, ${JSON.stringify(n.caption)});
|
|
65
65
|
editor.dispatchEvent(new Event('input', { bubbles: true }));
|
|
66
66
|
return true;
|
|
67
|
-
}`);if(
|
|
67
|
+
}`);if(o)break;await t.wait({time:0.5})}if(!o)throw new l("填写抖音草稿表单失败: caption-editor-missing")}let r=!1;for(let o=0;o<e;o+=1){r=await t.evaluate(`() => {
|
|
68
68
|
const visibility = Array.from(document.querySelectorAll('label')).find(
|
|
69
|
-
(el) => (el.textContent || '').includes(${JSON.stringify(
|
|
69
|
+
(el) => (el.textContent || '').includes(${JSON.stringify(n.visibilityLabel)})
|
|
70
70
|
);
|
|
71
71
|
if (!(visibility instanceof HTMLElement)) return false;
|
|
72
72
|
visibility.click();
|
|
73
73
|
return true;
|
|
74
|
-
}`);if(
|
|
74
|
+
}`);if(r)break;await t.wait({time:0.5})}if(!r)throw new l("填写抖音草稿表单失败: visibility-missing")}async function C(t){let n="cover-input-missing";const e=await t.evaluate(`() => Array.from(document.querySelectorAll('input[type="file"]')).length`);for(let i=0;i<A;i+=1){const r=await t.evaluate(`() => {
|
|
75
75
|
const coverLabel = Array.from(document.querySelectorAll('label')).find(
|
|
76
76
|
(el) => (el.textContent || '').includes('上传新封面')
|
|
77
77
|
);
|
|
@@ -81,7 +81,7 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
|
|
|
81
81
|
|
|
82
82
|
const inputs = Array.from(document.querySelectorAll('input[type="file"]'));
|
|
83
83
|
const target = inputs
|
|
84
|
-
.slice(${JSON.stringify(
|
|
84
|
+
.slice(${JSON.stringify(e)})
|
|
85
85
|
.find((el) => el instanceof HTMLInputElement && !el.disabled);
|
|
86
86
|
if (!(target instanceof HTMLInputElement)) {
|
|
87
87
|
return { ok: false, reason: 'cover-input-pending' };
|
|
@@ -92,7 +92,7 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
|
|
|
92
92
|
.forEach((el) => el.removeAttribute('data-opencli-cover-input'));
|
|
93
93
|
target.setAttribute('data-opencli-cover-input', '1');
|
|
94
94
|
return { ok: true, selector: '[data-opencli-cover-input="1"]' };
|
|
95
|
-
}`);if(
|
|
95
|
+
}`);if(r?.ok&&r.selector)return r.selector;n=r?.reason||n;await t.wait({time:0.5})}throw new l(`准备抖音自定义封面输入框失败: ${n}`)}export function buildCoverCheckPanelTextJs(){return`() => {
|
|
96
96
|
const normalize = (value) => (value || '').replace(/\\s+/g, ' ').trim();
|
|
97
97
|
const stateTexts = ['检测', '检测中', '封面检测中', '重新检测', '横/竖双封面缺失'];
|
|
98
98
|
const marker = Array.from(document.querySelectorAll('div,span,p,button')).find(
|
|
@@ -110,7 +110,7 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
|
|
|
110
110
|
root = root.parentElement;
|
|
111
111
|
}
|
|
112
112
|
return '';
|
|
113
|
-
}`}async function
|
|
113
|
+
}`}async function _(t){return await t.evaluate(buildCoverCheckPanelTextJs())||""}async function g(t){let n="",e=!1;for(let i=0;i<x;i+=1){const r=await _(t),o=r.includes("检测中"),a=r.includes("重新检测")||r.includes("横/竖双封面缺失");if(o)e=!0;if(e&&a&&!o)return;n=r;await t.wait({time:0.5})}throw new l("等待抖音封面处理完成超时",n||"unknown")}async function L(t){const n=60;let e=null;for(let i=0;i<n;i+=1){e=await t.evaluate(`() => {
|
|
114
114
|
const extractCreationId = () => {
|
|
115
115
|
const titleInput = Array.from(document.querySelectorAll('input')).find(
|
|
116
116
|
(el) => (el.placeholder || '').includes('填写作品标题')
|
|
@@ -160,7 +160,7 @@ import*as W from"node:fs";import*as J from"node:path";import{cli as M,Strategy a
|
|
|
160
160
|
text: (btn.textContent || '').trim(),
|
|
161
161
|
creationId,
|
|
162
162
|
};
|
|
163
|
-
}`);if(
|
|
163
|
+
}`);if(e?.ok)break;await t.wait({time:0.5})}if(!e?.ok)throw new l(`点击草稿按钮失败: ${e?.reason||"unknown"}`);if(!e.creationId)throw new l("点击草稿按钮失败: creation-id-missing");return{text:e.text||"暂存离开",creationId:e.creationId}}async function M(t,n){let e={href:"",bodyText:""};for(let i=0;i<40;i+=1){e=await t.evaluate(`() => ({
|
|
164
164
|
href: location.href,
|
|
165
165
|
bodyText: document.body?.innerText || ''
|
|
166
|
-
})`);const
|
|
166
|
+
})`);const r=e.href||"",o=e.bodyText||"",a=r.includes("/creator-micro/content/upload")&&/继续编辑/.test(o),u=/草稿保存成功|已保存到草稿|存草稿成功|保存成功/.test(o),d=/\/creator-micro\/content\/(manage|drafts|works)/.test(r)||/创作中心/.test(o)&&!r.includes("/content/upload");if(a||u||d)return n;await t.wait({time:1})}throw new l("未检测到抖音草稿保存确认",`当前页面: ${e.href||"unknown"}`)}w({site:"douyin",name:"draft",access:"write",description:"上传视频并保存为草稿",domain:"creator.douyin.com",strategy:v.COOKIE,navigateBefore:!1,defaultWindowMode:"foreground",args:[{name:"video",required:!0,positional:!0,help:"视频文件路径"},{name:"title",required:!0,help:"视频标题(≤30字)"},{name:"caption",fromFile:!0,default:"",help:"正文内容(≤1000字,支持 #话题)"},{name:"cover",default:"",help:"封面图片路径"},{name:"visibility",default:"public",choices:["public","friends","private"]},{name:"timeout",type:"int",default:180,help:"命令超时(秒),视频上传/转码慢时可调大"}],columns:["status","draft_id"],func:async(t,n)=>{const e=s.resolve(n.video);if(!f.existsSync(e))throw new c(`视频文件不存在: ${e}`);const i=s.extname(e).toLowerCase();if(![".mp4",".mov",".avi",".webm"].includes(i))throw new c(`不支持的视频格式: ${i}(支持 mp4/mov/avi/webm)`);const r=n.title;if(r.length>30)throw new c("标题不能超过 30 字");const o=n.caption||"";if(o.length>1000)throw new c("正文不能超过 1000 字");const a=n.cover;if(a){if(!f.existsSync(s.resolve(a)))throw new c(`封面文件不存在: ${s.resolve(a)}`)}const u=m[n.visibility]??m.public;await t.goto(h);await t.wait({selector:'input[type="file"]',timeout:20});await b(t);await p(t,'input[type="file"]',[e]);await S(t);await I(t,u);await b(t);if(a){const y=await C(t);await p(t,y,[s.resolve(a)]);await g(t)}await k(t,{title:r,caption:o,visibilityLabel:u});await t.wait({time:1});const d=await L(t);return[{status:"✅ 草稿已保存,可在创作中心继续编辑",draft_id:await M(t,d.creationId)}]}});
|
package/clis/douyin/drafts.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as s,Strategy as c}from"@jackwener/opencli/registry";import{READ_IMAGE_DRAFT_JS as n,matchImageDraft as l}from"./_shared/draft-cache.js";s({site:"douyin",name:"drafts",access:"read",description:"列出本机浏览器里暂存的图文草稿(抖音图文草稿只存在本地浏览器,换设备/清缓存即失效)",domain:"creator.douyin.com",strategy:c.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:20}],columns:["title","text","images","scope"],func:async(e,i)=>{await e.goto("https://creator.douyin.com/creator-micro/content/upload?default-tab=3");const o=await e.evaluate(n),a=[];for(const r of o||[]){let t=null;try{t=JSON.parse(r.value||"")}catch{continue}if(!t)continue;a.push({title:t.title||"",text:String(t.text||"").slice(0,120),images:Array.isArray(t.files)?t.files.length:0,scope:r.key})}return a.slice(0,i.limit)}});export const __test__={matchImageDraft:l};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as b from"node:fs";import*as y from"node:path";import{cli as k,Strategy as q}from"@jackwener/opencli/registry";import{ArgumentError as a,CommandExecutionError as u}from"@jackwener/opencli/errors";import{assertLiteralContent as j}from"../_shared/content-guard.js";import{setInputFiles as B}from"../_shared/file-inject.js";import{browserFetch as F}from"./_shared/browser-fetch.js";import{READ_IMAGE_DRAFT_JS as D,matchImageDraft as J}from"./_shared/draft-cache.js";const G="https://creator.douyin.com/creator-micro/content/upload?default-tab=3",A=35,C=20,L=1000,X=2500,V={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".bmp":"image/bmp",".webp":"image/webp",".tif":"image/tiff",".tiff":"image/tiff"},O='input[type="file"][accept*="image"]',R=['input[placeholder="添加作品标题"]','input[placeholder*="标题"]'],z='input[placeholder="添加作品标题"]',I='.zone-container[contenteditable="true"]';function Y(t){return t.map((n)=>{const e=y.resolve(n);if(!b.existsSync(e))throw new a(`图片文件不存在: ${e}`);const r=y.extname(e).toLowerCase();if(!V[r])throw new a(`不支持的图片格式 "${r}",支持: jpg, png, bmp, webp, tif`);return e})}async function H(t,n=15000){const e=500,r=Math.max(1,Math.ceil(n/e));for(let o=0;o<r;o++){if(await t.evaluate(`(() => !!document.querySelector(${JSON.stringify(O)}))()`))return!0;if(o<r-1)await t.wait({time:e/1000})}return!1}async function K(t,n){if(!await H(t))return{ok:!1,error:"上传页未渲染出图片输入框(等待 15s 超时)"};try{await B(t,O,n);return{ok:!0}}catch(r){return{ok:!1,error:r instanceof Error?r.message:String(r)}}}async function W(t,n=20000){const e=500,r=Math.ceil(n/e);for(let o=0;o<r;o++){if(await t.evaluate(`(() => {
|
|
2
2
|
const onEditor = location.href.includes('/content/post/image');
|
|
3
|
-
const titleReady = ${JSON.stringify(
|
|
3
|
+
const titleReady = ${JSON.stringify(R)}.some((s) => !!document.querySelector(s));
|
|
4
4
|
return onEditor && titleReady;
|
|
5
|
-
})()`))return!0;await
|
|
5
|
+
})()`))return!0;await t.wait({time:e/1000})}return!1}async function Q(t,n){await t.typeText(z,n);await t.wait({time:0.3});const e=await t.evaluate(`
|
|
6
6
|
((selectors) => {
|
|
7
7
|
const el = selectors.map((s) => document.querySelector(s)).find(Boolean);
|
|
8
8
|
return el ? (el.value || '') : '';
|
|
9
|
-
})(${JSON.stringify(
|
|
10
|
-
`);if(
|
|
9
|
+
})(${JSON.stringify(R)})
|
|
10
|
+
`);if(e.trim()!==n){await t.screenshot({path:"/tmp/douyin_image_title_debug.png"});throw new u(`填写标题失败,期望 "${n}",实际 "${e}"。截图: /tmp/douyin_image_title_debug.png`)}}async function Z(t,n){await t.typeText(I,n);await t.wait({time:0.5});const e=await t.evaluate(`
|
|
11
11
|
((selector) => {
|
|
12
12
|
const el = Array.from(document.querySelectorAll(selector)).find((n) => n && n.offsetParent !== null);
|
|
13
13
|
return el ? (el.innerText || el.textContent || '').replace(/\\u200b/g, '').trim() : '';
|
|
14
|
-
})(${JSON.stringify(
|
|
15
|
-
`),
|
|
14
|
+
})(${JSON.stringify(I)})
|
|
15
|
+
`),r=n.split("#")[0].replace(/\s+/g,"").trim(),o=e.replace(/\s+/g,"");if(r&&!o.includes(r.slice(0,Math.min(r.length,20)))){await t.screenshot({path:"/tmp/douyin_image_body_debug.png"});throw new u(`正文写入校验失败,实际读到 "${e.slice(0,80)}"。截图: /tmp/douyin_image_body_debug.png`)}}async function tt(t,n){const e=n?["暂存离开"]:["发布"];return await t.evaluate(`
|
|
16
16
|
((labels) => {
|
|
17
17
|
const isVisible = (el) => {
|
|
18
18
|
if (!el || el.offsetParent === null) return false;
|
|
@@ -27,8 +27,8 @@ import*as v from"node:fs";import*as N from"node:path";import{cli as h,Strategy a
|
|
|
27
27
|
if (btn) { btn.click(); return { ok: true, text: label }; }
|
|
28
28
|
}
|
|
29
29
|
return { ok: false, seen: btns.filter(isVisible).map((b) => norm(b.innerText || b.textContent)).filter(Boolean).slice(0, 12) };
|
|
30
|
-
})(${JSON.stringify(
|
|
31
|
-
`)}
|
|
30
|
+
})(${JSON.stringify(e)})
|
|
31
|
+
`)}k({site:"douyin",name:"publish-image",access:"write",description:"发布图文(图集)到抖音(UI 自动化,最多 35 张图;话题以 #词 写进正文)",domain:"creator.douyin.com",strategy:q.COOKIE,browser:!0,navigateBefore:!1,defaultWindowMode:"foreground",args:[{name:"content",required:!1,positional:!0,help:"正文(字面文本,不展开 @文件 引用;长正文用 --file)"},{name:"file",required:!1,help:"从本机文件读取正文(UTF-8),与位置参数 <content> 二选一"},{name:"title",required:!0,help:"作品标题(≤20字)"},{name:"images",required:!0,help:"图片路径,逗号分隔,最多35张 (jpg/png/bmp/webp/tif)"},{name:"topics",required:!1,help:"话题标签,逗号分隔,不含 # 号"},{name:"draft",type:"bool",default:!1,help:"暂存为草稿,不直接发布"}],columns:["status","detail"],func:async(t,n)=>{if(!t)throw Error("Browser page required");const e=String(n.title??"").trim(),r=n.file?String(n.file).trim():"";let o=String(n.content??"").trim();if(r){if(o)throw new a("正文位置参数和 --file 只能二选一");const i=y.resolve(r);if(!b.existsSync(i))throw new a(`--file 指向的文件不存在: ${i}`);o=b.readFileSync(i,"utf-8").trim();if(!o)throw new a(`--file 指向的文件内容为空: ${i}`)}const m=String(n.images??"").split(",").map((i)=>i.trim()).filter(Boolean),p=n.topics?String(n.topics).split(",").map((i)=>i.trim().replace(/^#/,"")).filter(Boolean):[],c=Boolean(n.draft);if(!e)throw new a("--title 必填");if(e.length>C)throw new a(`标题 ${e.length} 字,需 ≤ ${C} 字`);if(!o)throw new a("缺少正文:给位置参数 <content>,或用 --file <本机文件路径>");j(o,{fileFlag:"--file"});if(o.length>L)throw new a(`正文 ${o.length} 字,需 ≤ ${L} 字`);if(m.length===0)throw new a("至少提供 1 张图片(--images)");if(m.length>A)throw new a(`图片过多: ${m.length}(最多 ${A} 张)`);const _=Y(m),M=p.length?`${o} ${p.map((i)=>`#${i}`).join(" ")} `:o;await t.goto(G);let d="";for(let i=0;i<30;i++){await t.wait({time:0.5});d=await t.evaluate("() => location.href");if(d.includes("creator.douyin.com/creator-micro/content"))break}if(!d.includes("creator.douyin.com")){await t.screenshot({path:"/tmp/douyin_image_redirect_debug.png"});throw new u(`被重定向离开创作者中心(当前 ${d})——登录态可能已过期。`+"用 ppcli douyin login 重新登录。截图: /tmp/douyin_image_redirect_debug.png")}const S=await K(t,_);if(!S.ok){await t.screenshot({path:"/tmp/douyin_image_upload_debug.png"});throw new u(`图片上传失败: ${S.error??"unknown"}。截图: /tmp/douyin_image_upload_debug.png`)}if(!await W(t)){await t.screenshot({path:"/tmp/douyin_image_form_debug.png"});throw new u("上传后编辑页未就绪(标题输入框未出现),页面结构可能变化。截图: /tmp/douyin_image_form_debug.png")}await t.wait({time:X/1000});await Q(t,e);await t.wait({time:0.4});await Z(t,M);await t.wait({time:0.6});const E=await tt(t,c);if(!E?.ok){await t.screenshot({path:"/tmp/douyin_image_submit_debug.png"});throw new u(`找不到「${c?"暂存离开":"发布"}」按钮。可见按钮: ${(E?.seen||[]).join(" | ")||"无"}。截图: /tmp/douyin_image_submit_debug.png`)}const N=c?["暂存成功","保存成功","存入草稿"]:["发布成功","提交成功"];let l=d,w=!1,g="";for(let i=0;i<24;i++){await t.wait({time:0.5});const s=await t.evaluate(`
|
|
32
32
|
((markers) => {
|
|
33
33
|
const url = location.href;
|
|
34
34
|
let toast = '';
|
|
@@ -39,7 +39,7 @@ import*as v from"node:fs";import*as N from"node:path";import{cli as h,Strategy a
|
|
|
39
39
|
if (text && text.length <= 40 && markers.some((m) => text.includes(m))) { toast = text; break; }
|
|
40
40
|
}
|
|
41
41
|
return { url, toast };
|
|
42
|
-
})(${JSON.stringify(
|
|
43
|
-
`);
|
|
42
|
+
})(${JSON.stringify(N)})
|
|
43
|
+
`);l=s?.url??l;if(s?.toast){g=s.toast;break}if(l.includes("/content/manage")||c&&l.includes("/content/draft")){w=!0;break}}let f=null;if(!w&&!g&&l.includes("creator.douyin.com"))try{if(c){const i=await t.evaluate(D),s=J(i,{title:e,content:o});f=s.hit?s:null}else{const s=await F(t,"GET","https://creator.douyin.com/janus/douyin/creator/pc/work_list?page_size=20&page_num=1&status=0"),P=s.aweme_list??s.data?.work_list??[],T=o.replace(/\s+/g,"").slice(0,20),U=Date.now()/1000;f=P.find((h)=>{const x=String(h.desc??h.title??"").replace(/\s+/g,""),v=Number(h.create_time??0);return v>0&&U-v<900&&(x.includes(e.replace(/\s+/g,""))||T&&x.includes(T))})??null}}catch{}if(!w&&!g&&!f){await t.screenshot({path:"/tmp/douyin_image_verify_debug.png"});throw new u(c?"暂存结果无法确认:未见成功提示,本机草稿缓存里也没找到本次内容——大概率没存下,重试是安全的。"+`当前 URL: ${l}。截图: /tmp/douyin_image_verify_debug.png`:"发布结果无法确认:未跳转作品管理页、未见成功提示,作品列表回查也没找到本次内容。"+`
|
|
44
44
|
⚠️ 禁止直接重试——发布请求可能已经打到抖音,重试会发出重复作品。`+"\n正确做法:先用 `ppcli douyin videos` 按标题回查最近作品,确认没有再重发。"+`
|
|
45
|
-
当前 URL: ${
|
|
45
|
+
当前 URL: ${l}。截图: /tmp/douyin_image_verify_debug.png`)}return[{status:`✅ ${c?"暂存成功":"发布成功"}`,detail:[`"${e}"`,`${_.length}张图片`,p.length?`话题: ${p.map((i)=>`#${i}`).join(" ")}`:"",f?f.aweme_id?`aweme_id: ${f.aweme_id}(作品列表回查坐实)`:"本机草稿缓存回查坐实":"",w?l:g].filter(Boolean).join(" · ")}]}});
|
package/clis/douyin/publish.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as T from"node:fs";import*as u from"node:path";import{cli as Z,Strategy as Q}from"@jackwener/opencli/registry";import{ArgumentError as f,CommandExecutionError as m}from"@jackwener/opencli/errors";import{getUploadAuthV5Credentials as ee,applyVideoUploadInner as te,commitVideoUploadInner as oe}from"./_shared/vod-upload.js";import{tosUpload as ie}from"./_shared/tos-upload.js";import{imagexUpload as se}from"./_shared/imagex-upload.js";import{browserFetch as R}from"./_shared/browser-fetch.js";import{requireObjectEvaluateResult as V}from"./_shared/evaluate-result.js";import{generateCreationId as re}from"./_shared/creation-id.js";import{validateTiming as ne,toUnixSeconds as ae}from"./_shared/timing.js";import{parseTextExtra as ce,extractHashtagNames as le}from"./_shared/text-extra.js";const de={public:0,friends:1,private:2},M="https://imagex.bytedanceapi.com",z="1147",me="aid=1128&cookie_enabled=true&screen_width=1512&screen_height=982&browser_language=zh-CN&browser_platform=MacIntel&browser_name=Mozilla&browser_online=true&timezone_name=Asia%2FTokyo&support_h265=1",pe=JSON.stringify({video_cover_source:2,cover_timestamp:0,recommend_timestamp:0,is_cover_edit:0,is_cover_template:0,cover_template_id:"",is_text_template:0,text_template_id:"",text_template_content:"",is_text:0,text_num:0,text_content:"",is_use_sticker:0,sticker_id:"",is_use_filter:0,filter_id:"",is_cover_modify:0,to_status:0,cover_type:0,initial_cover_uri:"",cut_coordinate:""});function _e(o){const e=o instanceof Error?o.message:String(o);return e.includes("post_assistant/fast_detect")&&(e.includes("Empty response")||e.includes("404")||e.includes("Not Found")||e.includes("Timeout")||e.includes("timed out")||e.includes("Failed to fetch"))}function A(o){return new Promise((e)=>setTimeout(e,o))}function j(o,e){const n=e?.ResponseMetadata?.Error??e?.Error;if(n)throw new m(`${o}失败: ${JSON.stringify(n)}`)}async function B(o,e,n,h){let y;for(let r=1;r<=3;r+=1)try{return{ok:!0,value:await R(o,e,n,h)}}catch(i){if(!_e(i))throw i;y=i;if(r<3)await A(500*r)}return{ok:!1,error:y}}Z({site:"douyin",name:"publish",access:"write",description:"定时发布视频到抖音(必须设置 2h ~ 14天后的发布时间)",domain:"creator.douyin.com",strategy:Q.COOKIE,defaultWindowMode:"foreground",args:[{name:"video",required:!0,positional:!0,help:"视频文件路径"},{name:"title",required:!0,help:"视频标题(≤30字)"},{name:"schedule",required:!0,help:"定时发布时间(ISO8601 或 Unix 秒,2h ~ 14天后)"},{name:"caption",fromFile:!0,default:"",help:"正文内容(≤1000字,支持 #话题)"},{name:"cover",default:"",help:"封面图片路径(不提供时使用视频截帧)"},{name:"visibility",default:"public",choices:["public","friends","private"]},{name:"allow_download",type:"bool",default:!1,help:"允许下载"},{name:"collection",default:"",help:"合集 ID"},{name:"activity",default:"",help:"活动 ID"},{name:"poi_id",default:"",help:"地理位置 ID"},{name:"poi_name",default:"",help:"地理位置名称"},{name:"hotspot",default:"",help:"关联热点词"},{name:"no_safety_check",type:"bool",default:!1,help:"跳过内容安全检测"},{name:"sync_toutiao",type:"bool",default:!1,help:"同步发布到头条"}],columns:["status","aweme_id","url","publish_time"],func:async(o,e)=>{const n=u.resolve(e.video);if(!T.existsSync(n))throw new f(`视频文件不存在: ${n}`);const h=u.extname(n).toLowerCase();if(![".mp4",".mov",".avi",".webm"].includes(h))throw new f(`不支持的视频格式: ${h}(支持 mp4/mov/avi/webm)`);const y=T.statSync(n).size,r=e.title;if(r.length>30)throw new f("标题不能超过 30 字");const i=e.caption||"";if(i.length>1000)throw new f("正文不能超过 1000 字");const g=ae(e.schedule);ne(g);const H=de[e.visibility]??0,x=e.cover;if(x){if(!T.existsSync(u.resolve(x)))throw new f(`封面文件不存在: ${u.resolve(x)}`)}const I=await ee(o),C=await te(y,I);let v="",U=720,O=1280;await ie({filePath:n,uploadInfo:C,credentials:I,onProgress:(t,s)=>{const a=Math.round(t/s*100);process.stderr.write(`\r 上传进度: ${a}%`)}});process.stderr.write(`
|
|
2
2
|
`);process.stderr.write(` 提交上传...
|
|
3
|
-
`);const
|
|
4
|
-
`);
|
|
5
|
-
fetch(${JSON.stringify(
|
|
3
|
+
`);const p=await oe(C,I),E=p.video_id;process.stderr.write(` 上传已提交: ${E}
|
|
4
|
+
`);U=p.width||U;O=p.height||O;if(!v&&p.poster_uri)v=p.poster_uri;if(e.cover){const t=u.resolve(e.cover),s=`${M}/?Action=ApplyImageUpload&ServiceId=${z}&Version=2018-08-01&UploadNum=1`,a=`fetch(${JSON.stringify(s)}, { credentials: 'include' }).then(r => r.json())`,_=V(await o.evaluate(a),"抖音封面申请上传地址响应异常");j("抖音封面申请上传地址",_);const c=_.Result?.UploadAddress?.StoreInfos?.[0];if(!c?.UploadHost||!c?.StoreUri)throw new m(`抖音封面申请上传地址响应缺少 UploadHost/StoreUri: ${JSON.stringify(_).slice(0,500)}`);const S=`https://${c.UploadHost}/${c.StoreUri}`,l=await se(t,{upload_url:S,store_uri:c.StoreUri}),b=`${M}/?Action=CommitImageUpload&ServiceId=${z}&Version=2018-08-01`,d=JSON.stringify({SuccessObjKeys:[l]}),X=`
|
|
5
|
+
fetch(${JSON.stringify(b)}, {
|
|
6
6
|
method: 'POST',
|
|
7
7
|
credentials: 'include',
|
|
8
8
|
headers: { 'Content-Type': 'application/json' },
|
|
9
|
-
body: ${JSON.stringify(
|
|
9
|
+
body: ${JSON.stringify(d)}
|
|
10
10
|
}).then(r => r.json())
|
|
11
|
-
`,
|
|
12
|
-
`);const
|
|
13
|
-
`);else throw new
|
|
14
|
-
`);let
|
|
11
|
+
`,Y=V(await o.evaluate(X),"抖音封面提交上传响应异常");j("抖音封面提交上传",Y);v=l}if(!e.no_safety_check){const t="https://creator.douyin.com/aweme/v1/post_assistant/fast_detect/pre_check",s={video_id:E,title:r,desc:i},a=await B(o,"POST",t,{body:s});if(!a.ok)process.stderr.write(` 内容安全预检接口无响应,继续轮询检测结果。
|
|
12
|
+
`);const _="https://creator.douyin.com/aweme/v1/post_assistant/fast_detect/poll",c=Date.now()+30000;let S=!1,l=0;while(Date.now()<c){const b=await B(o,"POST",_,{body:s});if(!b.ok){l+=1;if(!a.ok&&l>=3)break;await A(2000);continue}l=0;const d=b.value;if(d.status===0||d.has_done===!0&&d.detect_result?.reason_code===0&&(d.detect_list?.length??0)===0){S=!0;break}if(d.status===1)throw new m("内容安全检测不通过,请修改后重试","使用 --no_safety_check 跳过");await A(2000)}if(!S)if(!a.ok&&l>=3)process.stderr.write(` 内容安全预检持续无响应,跳过本地预检,交由 create_v2 后的平台审核。
|
|
13
|
+
`);else throw new m("内容安全检测超时(30s),请稍后重试","如确认要跳过本地预检,可使用 --no_safety_check;提交后仍会走抖音平台审核")}const L=le(i),J=[];let P=0;for(const t of L){const s=i.indexOf(`#${t}`,P);if(s===-1)continue;J.push({name:t,id:0,start:s,end:s+t.length+1});P=s+t.length+1}const F=i?`${r} ${i}`:r,D=i?r.length+1:0,q=ce(F,J.map((t)=>({...t,start:t.start+D,end:t.end+D}))),k={item:{common:{text:F,caption:i,item_title:r,activity:JSON.stringify(e.activity?[e.activity]:[]),text_extra:JSON.stringify(q),challenges:"[]",mentions:"[]",hashtag_source:"",hot_sentence:e.hotspot||"",interaction_stickers:"[]",visibility_type:H,download:e.allow_download?1:0,timing:g,creation_id:re(),media_type:4,video_id:E,music_source:0,music_id:null,...e.poi_id?{poi_id:e.poi_id,poi_name:e.poi_name}:{}},cover:{poster:v,custom_cover_image_height:O,custom_cover_image_width:U,poster_delay:0,cover_tools_info:pe,cover_tools_extend_info:"{}"},mix:e.collection?{mix_id:e.collection,mix_order:0}:{},chapter:{chapter:JSON.stringify({chapter_abstract:"",chapter_details:[],chapter_type:0})},anchor:{},sync:{should_sync:!1,sync_to_toutiao:e.sync_toutiao?1:0},open_platform:{},assistant:{is_preview:0,is_post_assistant:1},declare:{user_declare_info:"{}"}}},G=`https://creator.douyin.com/web/api/media/aweme/create_v2/?read_aid=2906&${me}`;process.stderr.write(` 创建定时发布...
|
|
14
|
+
`);let w;try{w=await R(o,"POST",G,{body:k})}catch(t){if((t instanceof Error?t.message:String(t)).includes("Failed to fetch"))throw new m("提交定时发布请求被浏览器侧拦截(疑似字节安全组件 secsdk)","不要直接重试:先用 `ppcli douyin videos` / 创作者中心确认作品是否已创建,避免重复投稿。"+"确认未创建后,用 `--window foreground` 前台窗口重试(视频已上传成功的部分无需重传)。");throw t}const N=w.aweme_id??w.item_id;if(!N)throw new m(`发布成功但未返回 aweme_id/item_id: ${JSON.stringify(w)}`);const K=`https://www.douyin.com/video/${N}`,W=new Date(g*1000).toLocaleString("zh-CN",{timeZone:"Asia/Tokyo"});return[{status:"✅ 定时发布成功!",aweme_id:N,url:K,publish_time:W}]}});
|
package/clis/douyin/search.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as w,Strategy as p}from"@jackwener/opencli/registry";import{ArgumentError as h,AuthRequiredError as g,CommandExecutionError as l,EmptyResultError as m}from"@jackwener/opencli/errors";export const MAX_SEARCH_LIMIT=30,RENDER_TIMEOUT_MS=15000;export function parseSearchLimit(e){const t=Number(e??10);if(!Number.isFinite(t)||!Number.isInteger(t))throw new h(`--limit must be an integer between 1 and ${MAX_SEARCH_LIMIT}, got ${JSON.stringify(e)}`);if(t<1||t>MAX_SEARCH_LIMIT)throw new h(`--limit must be between 1 and ${MAX_SEARCH_LIMIT}, got ${t}`);return t}export function parseDouyinCount(e){if(typeof e!=="string")return 0;const t=e.replace(/\s/g,"").match(/^(\d+(?:\.\d+)?)([万亿])?$/);if(!t){const r=Number(e.replace(/[,\s]/g,""));return Number.isFinite(r)?Math.round(r):0}const o=Number(t[1]);if(!Number.isFinite(o))return 0;if(t[2]==="万")return Math.round(o*1e4);if(t[2]==="亿")return Math.round(o*1e8);return Math.round(o)}export function extractDouyinVideoId(e){if(typeof e!=="string"||!e)return"";let t=e;if(t.startsWith("//"))t="https:"+t;else if(t.startsWith("/"))t="https://www.douyin.com"+t;try{const o=new URL(t);if(!/(^|\.)douyin\.com$/.test(o.hostname))return"";return o.pathname.match(/^\/video\/(\d+)$/)?.[1]??""}catch{return""}}export function normalizeDouyinVideoUrl(e){const t=extractDouyinVideoId(e);return t?`https://www.douyin.com/video/${t}`:""}function b(e){if(!e)return!0;if(/^\d{1,2}:\d{2}(?::\d{2})?$/.test(e))return!0;if(/^\d+(?:\.\d+)?[万亿]?$/.test(e))return!0;if(/^(合集|视频|作者)$/.test(e))return!0;if(/^(刚刚|今天|昨天|前天)$/.test(e))return!0;if(/^\d+\s*(秒|分钟|小时|天|周|个月|月|年)前$/.test(e))return!0;if(/^\d{4}[-/.年]\d{1,2}(?:[-/.月]\d{1,2}日?)?$/.test(e))return!0;return!1}export function projectCard(e,t){const o=normalizeDouyinVideoUrl(e?.url??e?.href),r=Array.isArray(e?.leafTexts)?e.leafTexts.map((u)=>String(u??"").trim()).filter(Boolean):[],n=/^\d{1,2}:\d{2}(?::\d{2})?$/,i=/^\d+(?:\.\d+)?[万亿]?$/;let s=0,c="",f="";for(let u=0;u<r.length;u++){const a=r[u];if(n.test(a))continue;if(!s&&i.test(a)){s=parseDouyinCount(a);continue}if(a==="@"&&!c){c=(r[u+1]??"").trim();continue}if(a===c)continue;if(b(a))continue;if(a.length>f.length)f=a}let d=f;if(c&&d.startsWith("@"+c))d=d.slice(c.length+1).trim();return{rank:t+1,desc:d,author:c,url:o,plays:0,likes:s,comments:0,shares:0}}function y(e){return Boolean(e?.url&&e?.desc)}export function projectSearchCards(e,t){const r=(Array.isArray(e)?e.slice(0,t):[]).map((i,s)=>projectCard(i,s)),n=r.filter((i)=>!y(i)).length;return{rows:r.filter(y),invalidCount:n}}const v=(e)=>`
|
|
2
2
|
new Promise((resolve) => {
|
|
3
3
|
const collectCards = () => {
|
|
4
4
|
const cards = [];
|
|
@@ -46,6 +46,6 @@ import{cli as O,Strategy as H}from"@jackwener/opencli/registry";import{ArgumentE
|
|
|
46
46
|
observer.disconnect();
|
|
47
47
|
const fallback = detectState();
|
|
48
48
|
resolve(fallback ?? { state: 'timeout' });
|
|
49
|
-
}, ${
|
|
49
|
+
}, ${e});
|
|
50
50
|
})
|
|
51
|
-
`;function
|
|
51
|
+
`;function A(e){if(e&&!Array.isArray(e)&&typeof e==="object"&&"session"in e&&"data"in e)return e.data;return e}w({site:"douyin",name:"search",access:"read",description:"关键词搜索抖音视频",domain:"www.douyin.com",strategy:p.COOKIE,args:[{name:"query",required:!0,positional:!0,help:"搜索关键词"},{name:"limit",type:"int",default:10,help:`结果数量 (1-${MAX_SEARCH_LIMIT})`}],columns:["rank","desc","author","url","plays","likes","comments","shares"],func:async(e,t)=>{const o=parseSearchLimit(t.limit),r=String(t.query??"").trim();if(!r)throw new h("douyin search 需要 <query> 关键词");await e.goto(`https://www.douyin.com/search/${encodeURIComponent(r)}?type=video`);let n;try{n=A(await e.evaluate(v(RENDER_TIMEOUT_MS)))}catch(s){throw new l(`Douyin search extraction failed: ${s instanceof Error?s.message:String(s)}`)}if(!n||typeof n!=="object")throw new l("Douyin search: unexpected evaluator payload shape");if(n.state==="login_wall")throw new g("www.douyin.com","Douyin search results are blocked behind a login wall — log in at https://www.douyin.com in Chrome first.");if(n.state==="empty")throw new m("douyin search",`No Douyin videos matched "${r}".`);if(n.state==="timeout")throw new l("Douyin search did not render result cards within the timeout. Open the same search in Chrome and verify login/security state before retrying.");if(!Array.isArray(n.cards))throw new l("Douyin search: evaluator returned malformed cards payload");if(n.cards.length===0)throw new m("douyin search",`No Douyin videos matched "${r}".`);const i=projectSearchCards(n.cards,o);if(i.invalidCount>0)throw new l("Douyin search parser found result cards without stable video url or description");if(i.rows.length===0)throw new m("douyin search",`No Douyin videos matched "${r}".`);return i.rows}});
|
package/clis/douyin/videos.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as o,Strategy as u}from"@jackwener/opencli/registry";import{browserFetch as c}from"./_shared/browser-fetch.js";function d(t,i){if(typeof t==="number")return t;if(!t)return i&&i>Date.now()/1000?"scheduled":"published";if(t.is_delete)return"deleted";if(t.is_prohibited)return"prohibited";if(t.in_reviewing)return"reviewing";if(t.is_private)return"private";if(i&&i>Date.now()/1000)return"scheduled";return"published"}o({site:"douyin",name:"videos",access:"read",description:"获取作品列表",domain:"creator.douyin.com",strategy:u.COOKIE,args:[{name:"limit",type:"int",default:20,help:"每页数量"},{name:"page",type:"int",default:1,help:"页码"},{name:"status",default:"all",choices:["all","published","reviewing","scheduled"]}],columns:["aweme_id","title","status","play_count","digg_count","create_time"],func:async(t,i)=>{const r={all:0,published:1,reviewing:3,scheduled:0}[i.status]??0,s=`https://creator.douyin.com/janus/douyin/creator/pc/work_list?page_size=${i.limit}&page_num=${i.page}&status=${r}`,n=await c(t,"GET",s);let a=n.data?.work_list??n.aweme_list??[];if(i.status==="scheduled")a=a.filter((e)=>(e.public_time??0)>Date.now()/1000);return a.map((e)=>({aweme_id:e.aweme_id,title:e.desc??"",status:d(e.status,e.public_time),play_count:e.statistics?.play_count??0,digg_count:e.statistics?.digg_count??0,create_time:new Date((e.create_time??e.public_time??0)*1000).toLocaleString("zh-CN",{timeZone:"Asia/Tokyo"})}))}});
|
package/clis/eastmoney/_secid.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const u=(r)=>{if(/^(60|68|90|113|900)/.test(r))return"1";if(/^(00|30|20)/.test(r))return"0";if(/^(4|8|920|83|87)/.test(r))return"0";return"0"},h=new Set(["0","1","100","105","106","107","116","140","150","151","152","155","156"]);export function resolveSecid(r){const t=String(r||"").trim();if(!t)throw Error("empty symbol");const o=t.match(/^(\d{1,3})\.([A-Za-z0-9]+)$/);if(o&&h.has(o[1]))return t;const e=t.toLowerCase(),s=e.match(/^(sh|sz|bj)(\d{6})$/);if(s){const[,a,f]=s;return(a==="sh"?"1":"0")+"."+f}const i=e.match(/^hk(\d{4,5})$/)||e.match(/^(\d{4,5})\.hk$/);if(i)return"116."+i[1].padStart(5,"0");const n=e.match(/^([a-z.\-]+)\.([no])$/);if(n)return(n[2]==="n"?"106":"105")+"."+n[1].toUpperCase();const c=e.match(/^us\.([a-z.\-]+)$/);if(c)return"105."+c[1].toUpperCase();if(/^\d{6}$/.test(t))return u(t)+"."+t;if(/^[A-Z.\-]{1,8}$/.test(t))return"105."+t;throw Error(`Unrecognized symbol: ${r}`)}export function splitSymbols(r){return String(r||"").split(/[,,\s]+/).map((t)=>t.trim()).filter(Boolean)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as d,Strategy as
|
|
1
|
+
import{cli as d,Strategy as h}from"@jackwener/opencli/registry";import{CliError as m}from"@jackwener/opencli/errors";d({site:"eastmoney",name:"announcement",access:"read",description:"上市公司公告(按交易所筛选)",domain:"np-anotice-stock.eastmoney.com",strategy:h.PUBLIC,browser:!1,args:[{name:"market",type:"string",default:"SHA,SZA,BJA",help:"交易所:SHA (沪) / SZA (深) / BJA (北) 可逗号分隔"},{name:"limit",type:"int",default:20,help:"返回数量 (max 100)"}],columns:["time","code","name","title","category","url"],func:async(n)=>{const i=String(n.market??"SHA,SZA,BJA").trim()||"SHA,SZA,BJA",r=Math.max(1,Math.min(Number(n.limit)||20,100)),t=new URL("https://np-anotice-stock.eastmoney.com/api/security/ann");t.searchParams.set("page_size",String(r));t.searchParams.set("page_index","1");t.searchParams.set("ann_type",i);t.searchParams.set("client_source","web");t.searchParams.set("f_node","0");t.searchParams.set("s_node","0");const a=await fetch(t,{headers:{"User-Agent":"Mozilla/5.0"}});if(!a.ok)throw new m("HTTP_ERROR",`announcement failed: HTTP ${a.status}`);const o=await a.json(),c=Array.isArray(o?.data?.list)?o.data.list:[];if(c.length===0)throw new m("NO_DATA","eastmoney returned no announcement data");return c.slice(0,r).map((e)=>{const s=Array.isArray(e.codes)&&e.codes.length>0?e.codes[0]:{},l=Array.isArray(e.columns)&&e.columns.length>0?e.columns[0]?.column_name:"";return{time:String(e.notice_date||e.display_time||"").slice(0,19),code:s.stock_code||"",name:s.short_name||"",title:e.title||e.title_ch||"",category:l||"",url:`https://data.eastmoney.com/notices/detail/${s.stock_code||""}/${e.art_code||""}.html`}})}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CliError as
|
|
1
|
+
import{CliError as d,CommandExecutionError as v}from"@jackwener/opencli/errors";import{cli as x,Strategy as A}from"@jackwener/opencli/registry";import{publishArticle as N}from"../_shared/article/publish.js";import{checkLogin as F}from"../_shared/article/auth.js";export const authProfile={home:"https://mp.eastmoney.com",checkAuth:async(e)=>{const r=e.cookie("ct"),t=e.cookie("ut");if(!r||!t)return{isAuthenticated:!1,error:"未检测到登录 cookie(ct/ut),请先登录东方财富"};try{const o=await fetch(`https://caifuhaoapi.eastmoney.com/api/v2/getauthorinfo?platform=&ctoken=${encodeURIComponent(r)}&utoken=${encodeURIComponent(t)}`,{method:"GET",credentials:"include",headers:{"x-requested-with":"fetch"}});if(!o.ok)return{isAuthenticated:!1,error:`账号接口 HTTP ${o.status}`};const a=await o.json();if(a.Success===1&&a.Result&&a.Result.accountId)return{isAuthenticated:!0,userId:String(a.Result.accountId),username:a.Result.accountName||"",avatar:a.Result.portrait||""};return{isAuthenticated:!1}}catch(o){return{isAuthenticated:!1,error:String(o&&o.message||o)}}}};const T={home:"https://mp.eastmoney.com",outputFormat:"html",preprocessConfig:{removeComments:!0,removeSpecialTags:!0,processCodeBlocks:!0,convertSectionToDiv:!0,removeEmptyLines:!0,removeEmptyDivs:!0,removeNestedEmptyContainers:!0,unwrapSingleChildContainers:!0,unwrapNestedFigures:!0,removeTrailingBr:!0,removeDataAttributes:!0,removeSrcset:!0,removeSizes:!0,compactHtml:!0},image:{skip:["gbres.dfcfw.com"],uploadFn:async(e,r)=>{const t=r.cookie("ct"),o=r.cookie("ut");if(!t||!o)throw Error("东方财富图片上传失败:未检测到登录 cookie(ct/ut),请先登录");if(e.indexOf("data:")===0){const c=e.split(","),m=(c[0].match(/:(.*?);/)||[])[1]||"image/png",p=m.split("/")[1]||"png",u=atob(c[1]),g=new Uint8Array(u.length);for(let f=0;f<u.length;f++)g[f]=u.charCodeAt(f);const k=new Blob([g],{type:m}),I=Date.now()+"."+p,n=new FormData;n.append("file",k,I);n.append("noinlist","1");n.append("utoken",o);n.append("ctoken",t);const l=await(await fetch("https://gbapi.eastmoney.com/iimage/image?platform=",{method:"POST",credentials:"include",body:n})).json();if(l.code===200&&l.data&&l.data.url)return{url:l.data.url};throw Error("东方财富图片二进制上传失败:"+(l.message||"未知错误")+" (code: "+l.code+")")}const a=new URLSearchParams({noinlist:"1",linkUrl:e,ctoken:t,utoken:o}),s=await(await fetch("https://gbapi.eastmoney.com/iimage/image/byLink?platform=",{method:"PUT",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:a.toString()})).json();if(s.code===200&&s.data&&s.data.url)return{url:s.data.url};throw Error("东方财富图片链接上传失败:"+(s.message||"未知错误")+" (code: "+s.code+")")}},publish:async(e,r)=>{const t=r.cookie("ct"),o=r.cookie("ut");if(!t||!o)return{ok:!1,stage:"auth",status:401,message:"未检测到登录 cookie(ct/ut),请先登录东方财富"};const a=new Uint8Array(16);crypto.getRandomValues(a);const i=Array.from(a).map(function(n){return n.toString(16).padStart(2,"0").toUpperCase()}).join("");function s(n){return[{ip:"$IP$"},{deviceid:i},{version:"100"},{plat:"web"},{product:"CFH"},{ctoken:t},{utoken:o},{draftid:n.draftid||""},{drafttype:"0"},{type:"0"},{title:encodeURIComponent(n.title)},{text:encodeURIComponent(n.text)},{columns:"2"},{cover:""},{issimplevideo:"0"},{videos:""},{vods:""},{isoriginal:"0"},{tgProduct:""},{spcolumns:""},{textsource:"0"},{replyauthority:""},{modules:encodeURIComponent("[]")}]}async function c(n,b){const l=b?"https://mp.eastmoney.com/collect/pc_article/index.html#/?id="+b:"https://mp.eastmoney.com/collect/pc_article/index.html#/",f=JSON.stringify({pageUrl:l,path:"draft/api/Article/SaveDraft",parm:JSON.stringify(n)}),y=await fetch("https://emfront.eastmoney.com/apifront/Tran/GetData?platform=",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:f});if(!y.ok)return{ok:!1,stage:"draft_api",status:y.status,message:"草稿 API 请求失败: "+y.status};let h;try{h=await y.json()}catch(_){return{ok:!1,stage:"draft_api",status:y.status,message:"草稿 API 响应不是有效 JSON"}}if(!h.RRquestSuccess||h.RCode!==200)return{ok:!1,stage:"draft_api",status:h.RCode,message:"草稿 API 错误: "+(h.RMsg||"未知错误")};let w;try{w=JSON.parse(h.RData)}catch(_){return{ok:!1,stage:"draft_parse",status:200,message:"无法解析草稿响应数据"}}if(w.error_code!==0)return{ok:!1,stage:"draft_business",status:w.error_code,message:"草稿业务错误: "+(w.me||"未知错误")};return{ok:!0,data:w}}const m=s({title:e.title,text:'<div class="xeditor_content cfh_web"></div>'}),p=await c(m);if(!p.ok)return p;const u=p.data&&p.data.draft_id;if(!u)return{ok:!1,stage:"create",status:200,message:"创建草稿失败:响应缺少 draft_id"};const g=s({draftid:u,title:e.title,text:'<div class="xeditor_content cfh_web">'+e.content+"</div>"}),k=await c(g,u);if(!k.ok)return k;const I="https://mp.eastmoney.com/collect/pc_article/index.html#/?id="+u;return{ok:!0,draft:!0,id:u,url:I}}};import{readFile as S,stat as U}from"node:fs/promises";function R(e){if(!e.execute)throw new d("INVALID_INPUT","此命令需要 --execute 参数才能实际写入。注意:本报错仅表示缺少 --execute,并未校验其余参数,不能当 dry-run 预览用")}async function C(e){const r=typeof e.text==="string"?e.text:void 0,t=typeof e.file==="string"?e.file:void 0;if(r&&t)throw new d("INVALID_INPUT","正文和 --file 只能二选一");let o=r??"";if(t){let a;try{a=await U(t)}catch{throw new d("INVALID_INPUT",`文件不存在:${t}`)}if(!a.isFile())throw new d("INVALID_INPUT",`必须是可读文本文件:${t}`);let i;try{i=await S(t)}catch{throw new d("INVALID_INPUT",`文件无法读取:${t}`)}try{o=new TextDecoder("utf-8",{fatal:!0}).decode(i)}catch{throw new d("INVALID_INPUT",`文件无法以 UTF-8 解码:${t}`)}}if(!o.trim())throw new d("INVALID_INPUT","正文不能为空");return o}function D(e,r,t,o,a={}){return[{status:"success",outcome:o,message:e,target_type:r,target:t,...a}]}x({site:"eastmoney",name:"article",access:"write",description:"发布东方财富财富号文章(草稿)。正文默认 Markdown;图片自动转存到东方财富图床。",domain:"mp.eastmoney.com",strategy:A.COOKIE,browser:!0,args:[{name:"title",positional:!0,required:!0,help:"文章标题"},{name:"text",positional:!0,help:"文章正文(默认 Markdown;--html 表示 HTML)"},{name:"file",help:"正文文件路径(UTF-8,默认 Markdown)"},{name:"html",type:"boolean",help:"正文格式为 HTML 而非 Markdown"},{name:"draft",type:"boolean",help:"仅保存草稿(东方财富 mp 端目前仅支持草稿,默认即草稿)"},{name:"execute",type:"boolean",help:"确认实际写入,不带此参数时拒绝写操作"}],columns:["status","outcome","message","target_type","target","created_target","created_url"],func:async(e,r)=>{if(!e)throw new v("东方财富文章发布需要浏览器会话(browser session required)");R(r);const t=String(r.title??"").trim();if(!t)throw new d("INVALID_INPUT","文章标题不能为空");const o=await C(r),a=!0,i=await N(e,{title:t,body:o,format:r.html?"html":"markdown",draftOnly:a,profile:T}),s=i.images.uploaded.length|0,c=i.images.failed.length|0;let m="已保存东方财富草稿";if(s||c)m+=`(图片:${s} 张已转存${c?`,${c} 张失败`:""})`;return D(m,"article","","draft",{created_target:"article:"+i.id,created_url:i.url})}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as h,Strategy as l}from"@jackwener/opencli/registry";import{CliError as t}from"@jackwener/opencli/errors";const i={change:{fid:"f3",order:"desc"},drop:{fid:"f3",order:"asc"},turnover:{fid:"f6",order:"desc"},price:{fid:"f2",order:"desc"},premium:{fid:"f237",order:"desc"},value:{fid:"f236",order:"desc"},ytm:{fid:"f239",order:"desc"}};h({site:"eastmoney",name:"convertible",access:"read",description:"可转债行情列表(默认按成交额排序)",domain:"push2.eastmoney.com",strategy:l.PUBLIC,browser:!1,args:[{name:"sort",type:"string",default:"turnover",help:"排序:turnover / change / drop / price / premium"},{name:"limit",type:"int",default:20,help:"返回数量 (max 100)"}],columns:["rank","bondCode","bondName","bondPrice","bondChangePct","stockCode","stockName","stockPrice","stockChangePct","convPrice","convValue","convPremiumPct","remainingYears","ytm","listDate"],func:async(o)=>{const n=String(o.sort??"turnover").toLowerCase(),a=i[n];if(!a)throw new t("INVALID_ARGUMENT",`Unknown sort "${n}". Valid: ${Object.keys(i).join(", ")}`);const c=Math.max(1,Math.min(Number(o.limit)||20,100)),r=new URL("https://push2.eastmoney.com/api/qt/clist/get");r.searchParams.set("pn","1");r.searchParams.set("pz",String(c));r.searchParams.set("po",a.order==="desc"?"1":"0");r.searchParams.set("np","1");r.searchParams.set("fltt","2");r.searchParams.set("invt","2");r.searchParams.set("fid",a.fid);r.searchParams.set("fs","b:MK0354");r.searchParams.set("fields","f12,f14,f2,f3,f6,f229,f230,f232,f234,f235,f236,f237,f238,f239,f243");r.searchParams.set("ut","bd1d9ddb04089700cf9c27f6f7426281");const s=await fetch(r,{headers:{"User-Agent":"Mozilla/5.0"}});if(!s.ok)throw new t("HTTP_ERROR",`convertible failed: HTTP ${s.status}`);const f=await s.json(),d=Array.isArray(f?.data?.diff)?f.data.diff:[];if(d.length===0)throw new t("NO_DATA","eastmoney returned no convertible data");return d.slice(0,c).map((e,m)=>({rank:m+1,bondCode:e.f12,bondName:e.f14,bondPrice:e.f2,bondChangePct:e.f3,stockCode:e.f232,stockName:e.f234,stockPrice:e.f229,stockChangePct:e.f230,convPrice:e.f235,convValue:e.f236,convPremiumPct:e.f237,remainingYears:e.f238,ytm:e.f239,listDate:String(e.f243??"")}))}});
|
package/clis/eastmoney/etf.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as h,Strategy as l}from"@jackwener/opencli/registry";import{CliError as s}from"@jackwener/opencli/errors";const
|
|
1
|
+
import{cli as h,Strategy as l}from"@jackwener/opencli/registry";import{CliError as s}from"@jackwener/opencli/errors";const i={turnover:{fid:"f6",order:"desc"},change:{fid:"f3",order:"desc"},drop:{fid:"f3",order:"asc"},volume:{fid:"f5",order:"desc"},rate:{fid:"f8",order:"desc"}};h({site:"eastmoney",name:"etf",access:"read",description:"ETF 列表按成交额/涨跌幅排行",domain:"push2.eastmoney.com",strategy:l.PUBLIC,browser:!1,args:[{name:"sort",type:"string",default:"turnover",help:"排序:turnover / change / drop / volume / rate"},{name:"limit",type:"int",default:20,help:"返回数量 (max 100)"}],columns:["rank","code","name","price","changePercent","change","turnover","volume","turnoverRate"],func:async(n)=>{const o=String(n.sort??"turnover").toLowerCase(),a=i[o];if(!a)throw new s("INVALID_ARGUMENT",`Unknown sort "${o}". Valid: ${Object.keys(i).join(", ")}`);const f=Math.max(1,Math.min(Number(n.limit)||20,100)),e=new URL("https://push2.eastmoney.com/api/qt/clist/get");e.searchParams.set("pn","1");e.searchParams.set("pz",String(f));e.searchParams.set("po",a.order==="desc"?"1":"0");e.searchParams.set("np","1");e.searchParams.set("fltt","2");e.searchParams.set("invt","2");e.searchParams.set("fid",a.fid);e.searchParams.set("fs","b:MK0021");e.searchParams.set("fields","f12,f14,f2,f3,f4,f5,f6,f8");e.searchParams.set("ut","bd1d9ddb04089700cf9c27f6f7426281");const t=await fetch(e,{headers:{"User-Agent":"Mozilla/5.0"}});if(!t.ok)throw new s("HTTP_ERROR",`etf failed: HTTP ${t.status}`);const c=await t.json(),d=Array.isArray(c?.data?.diff)?c.data.diff:[];if(d.length===0)throw new s("NO_DATA","eastmoney returned no ETF data");return d.slice(0,f).map((r,m)=>({rank:m+1,code:r.f12,name:r.f14,price:r.f2,changePercent:r.f3,change:r.f4,turnover:r.f6,volume:r.f5,turnoverRate:r.f8}))}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as l,Strategy as E}from"@jackwener/opencli/registry";import{CliError as c}from"@jackwener/opencli/errors";function h(s){const e=String(s||"").trim().toUpperCase();if(/^\d{6}\.(SH|SZ|BJ)$/.test(e))return e;const a=e.match(/^(SH|SZ|BJ)(\d{6})$/);if(a)return`${a[2]}.${a[1]}`;if(/^\d{6}$/.test(e)){if(/^(60|68|90|113|900)/.test(e))return`${e}.SH`;if(/^(4|8|920|83|87)/.test(e))return`${e}.BJ`;return`${e}.SZ`}throw Error(`Unrecognized A-share symbol: ${s}`)}l({site:"eastmoney",name:"holders",access:"read",description:"十大流通股东(A股 F10 数据)",domain:"datacenter-web.eastmoney.com",strategy:E.PUBLIC,browser:!1,args:[{name:"symbol",required:!0,positional:!0,help:"A股代码(600519 / sh600519 等)"},{name:"limit",type:"int",default:10,help:"返回股东数(默认十大流通股东)"}],columns:["rank","reportDate","name","holdNum","floatRatio","change"],func:async(s)=>{let e;try{e=h(s.symbol)}catch(r){throw new c("INVALID_ARGUMENT",`${r instanceof Error?r.message:r}`)}const a=Math.max(1,Math.min(Number(s.limit)||10,50)),t=new URL("https://datacenter-web.eastmoney.com/api/data/v1/get");t.searchParams.set("sortColumns","END_DATE,HOLDER_RANK");t.searchParams.set("sortTypes","-1,1");t.searchParams.set("pageSize",String(Math.max(a,10)));t.searchParams.set("pageNumber","1");t.searchParams.set("reportName","RPT_F10_EH_FREEHOLDERS");t.searchParams.set("columns","SECUCODE,SECURITY_CODE,END_DATE,HOLDER_RANK,HOLDER_NAME,HOLD_NUM,FREE_HOLDNUM_RATIO,HOLD_NUM_CHANGE");t.searchParams.set("source","HSF10");t.searchParams.set("client","PC");t.searchParams.set("filter",`(SECUCODE="${e}")`);const o=await fetch(t,{headers:{"User-Agent":"Mozilla/5.0"}});if(!o.ok)throw new c("HTTP_ERROR",`holders failed: HTTP ${o.status}`);const m=await o.json(),n=Array.isArray(m?.result?.data)?m.result.data:[];if(n.length===0)throw new c("NO_DATA",`No shareholder data for ${e}`);const i=String(n[0].END_DATE||"").slice(0,10);return n.filter((r)=>String(r.END_DATE||"").slice(0,10)===i).slice(0,a).map((r)=>({rank:r.HOLDER_RANK,reportDate:i,name:r.HOLDER_NAME,holdNum:r.HOLD_NUM,floatRatio:r.FREE_HOLDNUM_RATIO,change:r.HOLD_NUM_CHANGE}))}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as u,Strategy as g}from"@jackwener/opencli/registry";import{CliError as i}from"@jackwener/opencli/errors";const n={main:[["1.000001","上证指数"],["0.399001","深证成指"],["0.399006","创业板指"],["1.000688","科创50"],["1.000300","沪深300"],["1.000905","中证500"]],hk:[["100.HSI","恒生指数"],["100.HSCEI","恒生国企"],["100.HSTECH","恒生科技"]],us:[["100.DJIA","道琼斯"],["100.SPX","标普500"],["100.NDX","纳斯达克100"],["100.IXIC","纳斯达克综指"]]},w="f2,f3,f4,f12,f13,f14,f15,f16,f17,f18";u({site:"eastmoney",name:"index-board",access:"read",description:"主要市场指数行情(A股 / 港股 / 美股)",domain:"push2.eastmoney.com",strategy:g.PUBLIC,browser:!1,args:[{name:"group",type:"string",default:"main",help:"指数分组:main (A股主要), hk (港股), us (美股), all"}],columns:["code","name","price","changePercent","change","open","high","low","prevClose"],func:async(d)=>{const s=String(d.group??"main").toLowerCase();let r;if(s==="all")r=[...n.main,...n.hk,...n.us];else if(n[s])r=n[s];else throw new i("INVALID_ARGUMENT",`Unknown group "${s}". Valid: main, hk, us, all`);const m=r.map(([a])=>a).join(","),t=new URL("https://push2.eastmoney.com/api/qt/ulist.np/get");t.searchParams.set("secids",m);t.searchParams.set("fltt","2");t.searchParams.set("fields",w);t.searchParams.set("ut","bd1d9ddb04089700cf9c27f6f7426281");const o=await fetch(t,{headers:{"User-Agent":"Mozilla/5.0",Accept:"application/json"}});if(!o.ok)throw new i("HTTP_ERROR",`eastmoney index-board failed: HTTP ${o.status}`);const f=await o.json(),c=Array.isArray(f?.data?.diff)?f.data.diff:[];if(c.length===0)throw new i("NO_DATA","eastmoney returned no index data");const p=new Map(c.map((a)=>[String(a.f12),a]));return r.map(([a,h])=>{const l=a.split(".")[1],e=p.get(l);if(!e)return null;return{code:l,name:e.f14||h,price:e.f2,changePercent:e.f3,change:e.f4,open:e.f17,high:e.f15,low:e.f16,prevClose:e.f18}}).filter(Boolean)}});
|
package/clis/eastmoney/kline.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as R,Strategy as
|
|
1
|
+
import{cli as R,Strategy as U}from"@jackwener/opencli/registry";import{CliError as a}from"@jackwener/opencli/errors";import{resolveSecid as S}from"./_secid.js";const c={"1m":1,"5m":5,"15m":15,"30m":30,"60m":60,minute:1,hour:60,day:101,daily:101,week:102,weekly:102,month:103,monthly:103},T={none:0,no:0,off:0,forward:1,front:1,pre:1,backward:2,back:2,post:2};R({site:"eastmoney",name:"kline",access:"read",description:"K线历史数据(分/日/周/月/前复权/后复权)",domain:"push2his.eastmoney.com",strategy:U.PUBLIC,browser:!1,args:[{name:"symbol",required:!0,positional:!0,help:"股票代码(A/HK/US 均可)"},{name:"period",type:"string",default:"day",help:"周期:1m/5m/15m/30m/60m/day/week/month"},{name:"adjust",type:"string",default:"forward",help:"复权:none / forward / backward"},{name:"limit",type:"int",default:30,help:"返回最近 N 根(末尾)"}],columns:["date","open","close","high","low","volume","turnover","amplitude","changePercent","change","turnoverRate"],func:async(t)=>{const d=S(t.symbol),n=String(t.period??"day").toLowerCase(),o=c[n];if(o==null)throw new a("INVALID_ARGUMENT",`Unknown period "${n}". Valid: ${Object.keys(c).join(", ")}`);const s=String(t.adjust??"forward").toLowerCase(),m=T[s];if(m==null)throw new a("INVALID_ARGUMENT",`Unknown adjust "${s}". Valid: none / forward / backward`);const u=Math.max(1,Math.min(Number(t.limit)||30,1000)),e=new URL("https://push2his.eastmoney.com/api/qt/stock/kline/get");e.searchParams.set("secid",d);e.searchParams.set("klt",String(o));e.searchParams.set("fqt",String(m));e.searchParams.set("beg","0");e.searchParams.set("end","20500101");e.searchParams.set("fields1","f1,f2,f3,f4,f5,f6");e.searchParams.set("fields2","f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61");e.searchParams.set("ut","b2884a393a59ad64002292a3e90d46a5");const r=await fetch(e,{headers:{"User-Agent":"Mozilla/5.0"}});if(!r.ok)throw new a("HTTP_ERROR",`eastmoney kline failed: HTTP ${r.status}`);const i=await r.json(),l=Array.isArray(i?.data?.klines)?i.data.klines:[];if(l.length===0)throw new a("NO_DATA",`No kline data for ${t.symbol}`);return l.slice(-u).map((f)=>{const[h,p,w,y,b,k,g,N,P,A,v]=f.split(",");return{date:h,open:Number(p),close:Number(w),high:Number(y),low:Number(b),volume:Number(k),turnover:Number(g),amplitude:Number(N),changePercent:Number(P),change:Number(A),turnoverRate:Number(v)}})}});
|