publishport-opencli 1.0.20 → 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/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 +17 -17
- 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/linkedin/inbox.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as L,Strategy as M}from"@jackwener/opencli/registry";import{ArgumentError as U,AuthRequiredError as y,CommandExecutionError as f,EmptyResultError as E}from"@jackwener/opencli/errors";const I="linkedin.com",R="https://www.linkedin.com/messaging/",k=1,v=100,b=40;function _(n){if(n&&typeof n==="object"&&"data"in n&&"session"in n)return n.data;return n}function A(n){return n?`https://www.linkedin.com/messaging/thread/${n}/`:""}function x(){if(/\/(login|checkpoint|authwall|uas)/i.test(location.pathname))return{loginRequired:!0};const n=performance.getEntriesByType("resource").map((r)=>r.name),s=(r)=>n.find((d)=>/messengerConversations\.[a-f0-9]+/i.test(d)&&r.test(d)),t=s(/PRIMARY_INBOX/i)||s(/conversationCategoryPredicate/i)||n.find((r)=>/messengerConversations\.[a-f0-9]+/i.test(r)&&/mailboxUrn/i.test(r));if(!t)return{url:null};const u=t.match(/mailboxUrn:(urn[^,)&]+)/i);return{url:t,mailboxUrn:u?decodeURIComponent(u[1]):""}}async function T(n,s){try{const t=await fetch(n,{credentials:"include",headers:{"csrf-token":s,accept:"application/vnd.linkedin.normalized+json+2.1","x-restli-protocol-version":"2.0.0"}});if(t.status===401||t.status===403)return{authRequired:!0,error:"HTTP "+t.status};if(!t.ok)return{error:"HTTP "+t.status};return{json:await t.json()}}catch(t){return{error:"fetch failed: "+(t&&t.message||String(t))}}}function N(n,s){if(!n||typeof n!=="object"||Array.isArray(n)||!Array.isArray(n.included))throw new f("LinkedIn messaging API returned malformed normalized payload: missing included array");const t=n.included,u=new Map;for(const e of t)if(e&&e.entityUrn)u.set(e.entityUrn,e);const r=(e)=>String(e==null?"":e).replace(/\s+/g," ").trim(),d=(e)=>{if(!e)return{name:"",kind:""};const i=e.participantType||{};if(i.organization&&i.organization.name)return{name:r(i.organization.name.text),kind:"organization"};if(i.member){const a=i.member.firstName&&i.member.firstName.text,c=i.member.lastName&&i.member.lastName.text;return{name:r([a,c].filter(Boolean).join(" ")),kind:"member"}}if(i.agent&&i.agent.name)return{name:r(i.agent.name.text),kind:"agent"};return{name:"",kind:""}},m=[];for(const e of t){if(!e||e.$type!=="com.linkedin.messenger.Conversation")continue;const i=String(e.backendUrn||"").replace(/^urn:li:messagingThread:/,"");if(!i)throw new f("LinkedIn messaging API returned a conversation without thread id");const a=[];let c="";for(const S of e["*conversationParticipants"]||[]){const w=u.get(S);if(!w)continue;if(s&&w.hostIdentityUrn===s)continue;const h=d(w);if(h.name){a.push(h.name);if(!c)c=h.kind}}const o=e.messages&&e.messages["*elements"]||[],l=u.get(o[0]);let g=l&&l.body?r(l.body.text):"";if(!g)g=r(e.descriptionText||"");const p=Number(e.lastActivityAt||0);m.push({activityMs:p,row:{thread_id:i,person_name:e.title?r(e.title):a.join(", "),last_message_preview:g.slice(0,300),unread:Number(e.unreadCount||0)>0||e.read===!1,counterparty_type:c,category:Array.isArray(e.categories)?e.categories.join(","):"",timestamp:p?new Date(p).toISOString():""}})}m.sort((e,i)=>i.activityMs-e.activityMs);return m.map((e)=>e.row)}L({site:"linkedin",name:"inbox",access:"read",description:"List LinkedIn messaging inbox conversations and unread messages",domain:"www.linkedin.com",strategy:M.COOKIE,browser:!0,args:[{name:"limit",type:"int",default:b,help:"Maximum conversations to return (1-100)"},{name:"unread-only",type:"bool",default:!1,help:"Return only conversations with unread messages"}],columns:["rank","thread_url","thread_id","person_name","last_message_preview","unread","counterparty_type","category","timestamp"],func:async(n,s)=>{let t=b;if(s.limit!==void 0&&s.limit!==null&&s.limit!==""){t=Number(s.limit);if(!Number.isInteger(t)||t<k||t>v)throw new U(`--limit must be an integer between ${k} and ${v}`)}const u=Boolean(s["unread-only"]);await n.goto(R);await n.wait(10);let r=_(await n.evaluate(`(${x.toString()})()`));if(r&&r.loginRequired)throw new y(I,"LinkedIn requires an active signed-in browser session.");if(!r||!r.url){await n.wait(6);r=_(await n.evaluate(`(${x.toString()})()`))}if(!r||!r.url)throw new f("LinkedIn did not issue a messaging API request; the inbox may have failed to load.");const m=(await n.getCookies({url:"https://www.linkedin.com"})).find((o)=>o.name==="JSESSIONID")?.value;if(!m)throw new y(I,"LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn.");const e=m.replace(/^"|"$/g,""),i=r.url.replace(/count:\d+/,"count:"+t),a=_(await n.evaluate(`(${T.toString()})(${JSON.stringify(i)}, ${JSON.stringify(e)})`));if(a&&a.authRequired)throw new y(I,"LinkedIn messaging API authentication failed: "+a.error);if(!a||a.error||!a.json)throw new f("LinkedIn messaging API returned an unexpected response: "+(a&&a.error||"no data"));let c=N(a.json,r.mailboxUrn||"");if(u)c=c.filter((o)=>o.unread);if(c.length===0){if(u)return[];throw new E("linkedin inbox","No LinkedIn conversations were found in the inbox.")}return c.slice(0,t).map((o,l)=>({rank:l+1,thread_url:A(o.thread_id),thread_id:o.thread_id,person_name:o.person_name,last_message_preview:o.last_message_preview,unread:o.unread,counterparty_type:o.counterparty_type,category:o.category,timestamp:o.timestamp}))}});export const __test__={parseConversations:N,threadUrl:A};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as l,Strategy as p}from"@jackwener/opencli/registry";import{AuthRequiredError as c,ArgumentError as d,CommandExecutionError as a,EmptyResultError as u}from"@jackwener/opencli/errors";import{assertSafeLinkedinUrl as m,normalizeWhitespace as t,unwrapEvaluateResult as y}from"./shared.js";const w="com.linkedin.voyager.deco.jobs.web.shared.WebFullJobPosting-65";function i(o){const r=m(o,"job-url"),n=new URL(r),e=n.pathname.match(/^\/jobs\/view\/(?:[^/]+-)?(\d+)/)||n.search.match(/[?&]currentJobId=(\d+)/);if(!e)throw new d("job-url must be a https://www.linkedin.com/jobs/view/<id> URL");return e[1]}function b(o,r){return`(async () => {
|
|
2
2
|
const norm = (s) => String(s == null ? '' : s).replace(/[ ]+/g, ' ').replace(/\\s+/g, ' ').trim();
|
|
3
3
|
const csrf = ((document.cookie.split('; ').find((c) => c.startsWith('JSESSIONID=')) || '').split('=')[1] || '').replace(/^"|"$/g, '');
|
|
4
4
|
if (!csrf) return { ok: false, auth: true };
|
|
5
|
-
const res = await fetch('/voyager/api/jobs/jobPostings/' + ${JSON.stringify(
|
|
5
|
+
const res = await fetch('/voyager/api/jobs/jobPostings/' + ${JSON.stringify(o)} + '?decorationId=' + ${JSON.stringify(r)}, { credentials: 'include', headers: {
|
|
6
6
|
'csrf-token': csrf,
|
|
7
7
|
'accept': 'application/vnd.linkedin.normalized+json+2.1',
|
|
8
8
|
'x-restli-protocol-version': '2.0.0',
|
|
@@ -37,4 +37,4 @@ import{cli as V,Strategy as X}from"@jackwener/opencli/registry";import{AuthRequi
|
|
|
37
37
|
apply_url: applyUrl,
|
|
38
38
|
description: textOf(d.description),
|
|
39
39
|
};
|
|
40
|
-
})()`}
|
|
40
|
+
})()`}l({site:"linkedin",name:"job-detail",access:"read",description:"Read one LinkedIn job via the Voyager API: description, apply URL, workplace type, applicants, and company metadata",domain:"www.linkedin.com",strategy:p.COOKIE,browser:!0,args:[{name:"job-url",type:"string",required:!0,positional:!0,help:"Exact LinkedIn job URL, e.g. https://www.linkedin.com/jobs/view/123/"}],columns:["title","company","location","workplace_type","job_type","applicants","listed","apply_url","company_url","url","description"],func:async(o,r)=>{if(!o)throw new a("Browser session required for linkedin job-detail");const n=i(r["job-url"]);await o.goto("https://www.linkedin.com/jobs/");await o.wait(2);const e=y(await o.evaluate(b(n,w)));if(e?.auth)throw new c("linkedin.com","LinkedIn job-detail requires an active signed-in browser session");if(!e?.ok)throw new a(`LinkedIn job-detail: jobPostings API returned HTTP ${e?.status||"?"}`);if(!t(e.title))throw new u("linkedin job-detail",`No job posting found for id ${n} (it may be closed or removed).`);const s=e.listed_at?new Date(e.listed_at).toISOString().slice(0,10):"";return[{title:t(e.title),company:t(e.company),location:t(e.location),workplace_type:t(e.workplace_type),job_type:t(e.job_type),applicants:e.applicants||0,listed:s,apply_url:t(e.apply_url),company_url:t(e.company_url),url:`https://www.linkedin.com/jobs/view/${n}`,description:t(e.description)}]}});export const __test__={extractJobId:i};
|
package/clis/linkedin/like.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as c,Strategy as l}from"@jackwener/opencli/registry";import{AuthRequiredError as d,CommandExecutionError as s}from"@jackwener/opencli/errors";import{LINKEDIN_DOMAIN as m,unwrapEvaluateResult as p}from"./shared.js";import{buildCommentReactScript as f,buildReactScript as k,looksLikeCommentUrn as h,normalizeCommentUrn as w,normalizeThreadUrn as y,parseReactionType as g,REACTION_CREATE_QID as v,REACTION_DELETE_QID as R}from"./social-api.js";c({site:"linkedin",name:"like",access:"write",description:"React to a LinkedIn post OR comment (like by default; also celebrate/support/love/insightful/funny), or remove your reaction. Takes a post URL / activity urn, or a comment_urn from `linkedin post-comments`.",domain:m,strategy:l.COOKIE,browser:!0,args:[{name:"target",type:"string",required:!0,positional:!0,help:"What to react to: a LinkedIn post URL (…/feed/update/…) or activity/ugcPost urn, OR a comment_urn (urn:li:comment:(…)) from `linkedin post-comments`."},{name:"reaction",type:"string",required:!1,default:"like",help:"Reaction type: like (default), celebrate, support, love, insightful, funny. Ignored when --remove true."},{name:"remove",type:"bool",required:!1,default:!1,help:"Remove your existing reaction instead of adding one."}],columns:["status","target_urn","target_type","reaction"],func:async(n,t)=>{if(!n)throw new s("Browser session required for linkedin like");const r=t?.remove===!0||t?.remove==="true",o=r?"":g(t?.reaction),i=h(t?.target),a=i?w(t?.target):y(t?.target);await n.goto("https://www.linkedin.com/feed/");await n.wait(2);const u=i?f({commentUrn:a,reactionType:o,remove:r,createQid:v,deleteQid:R}):k({threadUrn:a,reactionType:o,remove:r}),e=p(await n.evaluate(u));if(!e?.ok){if(e?.stage==="auth"||e?.httpStatus===401||e?.httpStatus===403)throw new d(m,`LinkedIn like requires an active signed-in LinkedIn browser session (${e?.error||"auth"}).`);throw new s(`LinkedIn like failed: stage=${e?.stage||"unknown"} http=${e?.httpStatus||"?"} ${e?.error||""}`.trim())}return[{status:r?"reaction_removed":"reacted",target_urn:a,target_type:i?"comment":"post",reaction:r?"":o}]}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as y,Strategy as I}from"@jackwener/opencli/registry";import{ArgumentError as g,AuthRequiredError as k,CommandExecutionError as m,EmptyResultError as E}from"@jackwener/opencli/errors";import{LINKEDIN_DOMAIN as w,normalizeWhitespace as l,parseLimit as L,unwrapEvaluateResult as b}from"./shared.js";import{buildNotificationsScript as S}from"./social-api.js";const h=20,c=100,u=20,A={all:"all",mentions:"mentions",posts:"my_posts_all",jobs:"job_alerts"};y({site:"linkedin",name:"notifications",access:"read",description:"Read your LinkedIn notifications via the Voyager API: who reacted to / commented on / mentioned your posts, profile views, follows, and more. Read-only.",domain:w,strategy:I.COOKIE,browser:!0,args:[{name:"limit",type:"int",required:!1,default:h,help:`Maximum notifications to return (1-${c}).`},{name:"filter",type:"string",required:!1,default:"all",help:"Which notifications: all (default), mentions, posts (activity on your posts), jobs."},{name:"unread-only",type:"bool",required:!1,default:!1,help:"Only return unread notifications."}],columns:["rank","unread","headline","content","when","target"],func:async(i,e)=>{if(!i)throw new m("Browser session required for linkedin notifications");const r=L(e?.limit,h,c),p=String(e?.filter??"all").trim().toLowerCase(),f=A[p];if(!f)throw new g(`--filter 只能是 all / mentions / posts / jobs(收到 "${e?.filter}")`);const d=e?.["unread-only"]===!0||e?.["unread-only"]==="true";await i.goto("https://www.linkedin.com/feed/");await i.wait(2);const a=[];for(let o=0;a.length<r&&o<c;o+=u){const t=b(await i.evaluate(S({count:u,start:o,filter:f})));if(!t?.ok){if(t?.stage==="auth"||t?.httpStatus===401||t?.httpStatus===403)throw new k(w,`LinkedIn notifications requires an active signed-in LinkedIn browser session (${t?.error||"auth"}).`);throw new m(`LinkedIn notifications failed: stage=${t?.stage||"read"} http=${t?.httpStatus||"?"} ${t?.error||""}`.trim())}const s=Array.isArray(t.rows)?t.rows:[];if(s.length===0)break;for(const n of s){if(d&&n.read)continue;a.push({unread:n.read?"":"yes",headline:l(n.headline),content:l(n.content),when:n.when?new Date(n.when).toISOString():"",target:R(n.target)})}if(s.length<u)break}if(a.length===0)throw new E("linkedin notifications",d?"No unread notifications.":"No notifications were returned for this filter.");return a.slice(0,r).map((o,t)=>({rank:t+1,...o}))}});function R(i){const e=l(i);if(!e)return"";try{const r=new URL(e,"https://www.linkedin.com");if(r.protocol!=="https:")return"";return r.toString()}catch{return""}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as I,Strategy as L}from"@jackwener/opencli/registry";import{ArgumentError as l,CommandExecutionError as C,EmptyResultError as E}from"@jackwener/opencli/errors";import{fetchSearchClusters as N}from"./search-api.js";const b="www.linkedin.com",u=10;function p(e){return String(e??"").replace(/[ ]/g," ").replace(/\s+/g," ").trim()}function O(e,t,r=t){const n=p(e[t]);if(!n)throw new l(`${r} is required`);return n}function f(e){if(e===void 0||e===null||e==="")return 5;const t=Number(e);if(!Number.isInteger(t)||t<1||t>u)throw new l(`--limit must be an integer between 1 and ${u}`);return t}const S={"1":"F","2":"S","3":"O"},A=new Set(["proBono","boardMember"]);function d(e){if(!e)return[];return String(e).split(",").map((t)=>t.trim()).filter(Boolean)}function h(e){if(!e)return[];const t=d(e),r=[];for(const n of t){const o=S[n];if(!o)throw new l(`--network values must be one or more of 1,2,3 (got "${n}")`);if(!r.includes(o))r.push(o)}return r}function y(e){if(!e)return[];const t=d(e).map((r)=>r.toLowerCase());for(const r of t)if(!/^[a-z]{2}$/.test(r))throw new l(`--profile-language values must be ISO 639-1 2-letter codes (got "${r}")`);return t}function w(e){if(!e)return[];const t=d(e);for(const r of t)if(!A.has(r))throw new l(`--open-to values must be one or more of proBono,boardMember (got "${r}")`);return t}function c(e,t){if(!e)return[];const r=d(e).map((n)=>n.replace(/^urn:li:[a-z_]+:/,""));for(const n of r)if(!/^\d+$/.test(n))throw new l(`${t} values must be numeric IDs (got "${n}")`);return r}function g(e){const t=["(key:resultType,value:List(PEOPLE))"],r=(o,i)=>{if(Array.isArray(i)&&i.length)t.push(`(key:${o},value:List(${i.join(",")}))`)},n=(o,i)=>{const a=p(i);if(a)t.push(`(key:${o},value:List(${encodeURIComponent(a)}))`)};n("firstName",e.firstName);n("lastName",e.lastName);n("title",e.title);n("school",e.schoolKeyword);r("network",e.network);r("profileLanguage",e.profileLanguage);r("serviceCategory",e.openTo);r("currentCompany",e.currentCompanyIds);r("pastCompany",e.pastCompanyIds);r("industry",e.industryIds);r("geoUrn",e.geoIds);r("schools",e.schoolIds);return t}function k(e){const t=p(e);if(!t)return"";try{const r=new URL(t,"https://www.linkedin.com"),n=r.hostname.toLowerCase();if(r.protocol!=="https:"||r.username||r.password||r.port)return"";if(n!=="linkedin.com"&&n!=="www.linkedin.com")return"";const o=r.pathname.match(/^\/in\/([^/?#]+)\/?$/);if(!o||!o[1])return"";return`https://www.linkedin.com/in/${o[1]}/`}catch{return""}}I({site:"linkedin",name:"people-search",access:"read",description:"Search standard LinkedIn (not Sales Navigator) for people by keyword via the Voyager search API. Each invocation consumes against LinkedIn's monthly Commercial Use Limit on people search; throttle accordingly.",domain:b,strategy:L.COOKIE,browser:!0,args:[{name:"keywords",type:"string",required:!0,positional:!0,help:'People search keywords, e.g. "site reliability engineer berlin"'},{name:"limit",type:"int",default:5,help:`Maximum people to return (1-${u}); each query counts toward LinkedIn's monthly CUL`},{name:"first-name",type:"string",required:!1,help:"Filter to people whose first name matches this text (LinkedIn KEYWORDS / FIRST NAME filter)."},{name:"last-name",type:"string",required:!1,help:"Filter to people whose last name matches this text (LinkedIn KEYWORDS / LAST NAME filter)."},{name:"title",type:"string",required:!1,help:"Filter to people whose current title contains this text (LinkedIn KEYWORDS / TITLE filter)."},{name:"school-keyword",type:"string",required:!1,help:"Free-text school filter (LinkedIn SCHOOL filter, name match)."},{name:"network",type:"string",required:!1,help:'Comma-separated connection degrees: 1, 2, 3 (where 3 means 3rd+). E.g. "1,2" for 1st and 2nd-degree only.'},{name:"profile-language",type:"string",required:!1,help:'Comma-separated ISO 639-1 codes for profile language, e.g. "en,fr".'},{name:"open-to",type:"string",required:!1,help:"Comma-separated open-to values: proBono, boardMember."},{name:"current-company-id",type:"string",required:!1,help:'Comma-separated LinkedIn company IDs for CURRENT COMPANY filter (e.g. "1441" for Google). A full URN like `urn:li:fs_company:1441` is also accepted.'},{name:"past-company-id",type:"string",required:!1,help:"Comma-separated LinkedIn company IDs for PAST COMPANY filter. Same lookup pattern as --current-company-id."},{name:"industry-id",type:"string",required:!1,help:'Comma-separated LinkedIn industry IDs (e.g. "4" for Computer Software).'},{name:"location-id",type:"string",required:!1,help:'Comma-separated LinkedIn location IDs (geoUrn numeric tail; e.g. "105214831" for Bengaluru area).'},{name:"school-id",type:"string",required:!1,help:"Comma-separated LinkedIn school IDs (numeric tail of urn:li:fs_school:<id>). For free-text school name matching, use --school-keyword instead."}],columns:["rank","name","headline","location","profile_url"],func:async(e,t)=>{if(!e)throw new C("Browser session required for linkedin people-search");const r=O(t,"keywords","--keywords"),n=f(t.limit),o=g({firstName:t["first-name"],lastName:t["last-name"],title:t.title,schoolKeyword:t["school-keyword"],network:h(t.network),profileLanguage:y(t["profile-language"]),openTo:w(t["open-to"]),currentCompanyIds:c(t["current-company-id"],"--current-company-id"),pastCompanyIds:c(t["past-company-id"],"--past-company-id"),industryIds:c(t["industry-id"],"--industry-id"),geoIds:c(t["location-id"],"--location-id"),schoolIds:c(t["school-id"],"--school-id")});await e.goto("https://www.linkedin.com/feed/");await e.wait(2);const{rows:i}=await N(e,{keywords:r,filters:o,start:0,count:Math.max(n,10)},"people-search"),a=[];for(const s of i){const m=k(s.nav);if(!s.name||!m)continue;a.push({name:s.name,headline:s.headline,location:s.location,profile_url:m})}if(a.length===0)throw new E(`No people found for "${r}". The search may have returned zero results, or your monthly Commercial Use Limit may be reached (resets on the 1st).`);return a.slice(0,n).map((s,m)=>({rank:m+1,...s}))}});export const __test__={normalizeWhitespace:p,parseLimit:f,buildPeopleFilters:g,normalizeProfileUrl:k,parseNetworkArg:h,parseProfileLanguageArg:y,parseOpenToArg:w,parseIdListArg:c};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as g,Strategy as L}from"@jackwener/opencli/registry";import{ArgumentError as I,AuthRequiredError as E,CommandExecutionError as w,EmptyResultError as v}from"@jackwener/opencli/errors";import{LINKEDIN_DOMAIN as f,normalizeWhitespace as c,parseLimit as A,unwrapEvaluateResult as S}from"./shared.js";import{buildReadCommentsScript as R,normalizeThreadUrn as b}from"./social-api.js";const y=20,p=100,_=50;g({site:"linkedin",name:"post-comments",access:"read",description:"List the comments (and nested replies) on a LinkedIn post via the Voyager API. Emits each comment_urn so you can reply to it. Takes a post URL or activity/ugcPost urn.",domain:f,strategy:L.COOKIE,browser:!0,args:[{name:"post",type:"string",required:!0,positional:!0,help:"Post to read comments from: a LinkedIn post URL (…/feed/update/… or …/posts/…) or a raw urn:li:activity:… / urn:li:ugcPost:… urn."},{name:"limit",type:"int",required:!1,default:y,help:`Maximum comments to return (1-${p}).`},{name:"sort",type:"string",required:!1,default:"relevance",help:"Comment order: relevance (default) or recent (chronological)."}],columns:["rank","comment_urn","author","headline","text","created_at","is_reply","parent_comment_urn","reactions","permalink"],func:async(r,n)=>{if(!r)throw new w("Browser session required for linkedin post-comments");const o=b(n?.post),m=A(n?.limit,y,p),u=String(n?.sort??"relevance").trim().toLowerCase();if(u!=="relevance"&&u!=="recent")throw new I("--sort 只能是 relevance 或 recent");const k=u==="recent"?"CHRONOLOGICAL":"RELEVANCE";await r.goto(`https://www.linkedin.com/feed/update/${o}/`);await r.wait(2);const a=[],d=new Set;for(let i=0;a.length<m&&i<p;i+=_){const s=Math.min(_,m-a.length),e=S(await r.evaluate(R({activityUrn:o,count:s,start:i,sortOrder:k})));if(!e?.ok){if(e?.stage==="auth"||e?.httpStatus===401||e?.httpStatus===403)throw new E(f,`LinkedIn post-comments requires an active signed-in LinkedIn browser session (${e?.error||"auth"}).`);throw new w(`LinkedIn post-comments failed: stage=${e?.stage||"read"} http=${e?.httpStatus||"?"} ${e?.error||""}`.trim())}const l=Array.isArray(e.rows)?e.rows:[];if(l.length===0)break;for(const t of l){const h=t.comment_urn||`${t.author}::${t.created_at}::${(t.text||"").slice(0,40)}`;if(d.has(h))continue;d.add(h);a.push({comment_urn:t.comment_urn||"",author:c(t.author),headline:c(t.headline),text:c(t.text),created_at:t.created_at?new Date(t.created_at).toISOString():"",is_reply:t.is_reply?"yes":"",parent_comment_urn:t.parent_comment_urn||"",reactions:Number(t.reactions)||0,permalink:C(t.permalink)})}if(l.length<s)break}if(a.length===0)throw new v("linkedin post-comments","This post has no comments, or comments are not visible to your account.");return a.slice(0,m).map((i,s)=>({rank:s+1,...i}))}});function C(r){const n=c(r);if(!n)return"";try{const o=new URL(n,"https://www.linkedin.com");if(o.protocol!=="https:")return"";return o.toString()}catch{return""}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as u,Strategy as p}from"@jackwener/opencli/registry";import{AuthRequiredError as d,CommandExecutionError as i,EmptyResultError as m}from"@jackwener/opencli/errors";import{LINKEDIN_DOMAIN as n,normalizeWhitespace as r,unwrapEvaluateResult as c}from"./shared.js";import{buildPostDetailScript as l,normalizeThreadUrn as h}from"./social-api.js";u({site:"linkedin",name:"post-detail",access:"read",description:"Read one LinkedIn post via the Voyager API: author, body text, reactions/comments/reposts/impressions, and whether it is a repost. Takes a post URL or activity/ugcPost urn.",domain:n,strategy:p.COOKIE,browser:!0,args:[{name:"post",type:"string",required:!0,positional:!0,help:"Post to read: a LinkedIn post URL (…/feed/update/… or …/posts/…) or a raw urn:li:activity:… / urn:li:ugcPost:… urn."}],columns:["post_urn","author","author_type","author_url","posted","text","content_type","is_repost","reactions","comments","reposts","impressions","url"],func:async(o,a)=>{if(!o)throw new i("Browser session required for linkedin post-detail");const s=h(a?.post);await o.goto("https://www.linkedin.com/feed/");await o.wait(2);const e=c(await o.evaluate(l({activityUrn:s})));if(!e?.ok){if(e?.stage==="auth"||e?.httpStatus===401||e?.httpStatus===403)throw new d(n,`LinkedIn post-detail requires an active signed-in LinkedIn browser session (${e?.error||"auth"}).`);throw new i(`LinkedIn post-detail failed: stage=${e?.stage||"read"} http=${e?.httpStatus||"?"} ${e?.error||""}`.trim())}const t=e.post||{};if(!t.author&&!t.text)throw new m("linkedin post-detail","The post was not found or is not visible to your account.");return[{post_urn:t.post_urn||s,author:r(t.author),author_type:t.author_type||"",author_url:r(t.author_url),posted:r(t.posted).replace(/[•·|\s]+$/,""),text:r(t.text),content_type:t.content_type||"",is_repost:t.is_repost||"",reactions:Number(t.reactions)||0,comments:Number(t.comments)||0,reposts:Number(t.reposts)||0,impressions:Number(t.impressions)||0,url:r(t.url)}]}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as s,Strategy as a}from"@jackwener/opencli/registry";import{CommandExecutionError as l,EmptyResultError as t}from"@jackwener/opencli/errors";import{normalizeWhitespace as o}from"./shared.js";import{fetchSelfAnalytics as c,normalizeProfileInputUrl as p}from"./profile-api.js";s({site:"linkedin",name:"profile-analytics",access:"read",description:"Read your own LinkedIn analytics via the Voyager API: profile views, search appearances, followers, and connections (self only)",domain:"www.linkedin.com",strategy:a.COOKIE,browser:!0,args:[{name:"profile-url",type:"string",required:!1,help:"Ignored beyond validation — analytics are only visible for the signed-in account."}],columns:["profile_url","profile_views","post_impressions","search_appearances","followers","connections"],func:async(i,n)=>{if(!i)throw new l("Browser session required for linkedin profile-analytics");if(n["profile-url"])p(n["profile-url"],"profile-analytics");const r=await c(i,"profile-analytics"),e={profile_url:"https://www.linkedin.com/in/me/",profile_views:o(r.profile_views),post_impressions:"",search_appearances:o(r.search_appearances),followers:o(r.followers),connections:o(r.connections)};if(!e.profile_views&&!e.search_appearances&&!e.followers&&!e.connections)throw new t("linkedin profile-analytics","No LinkedIn analytics counters were returned by the Voyager API.");return[e]}});export const __test__={};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{AuthRequiredError as
|
|
1
|
+
import{AuthRequiredError as s,CommandExecutionError as a}from"@jackwener/opencli/errors";import{assertSafeLinkedinUrl as m,normalizeWhitespace as y,unwrapEvaluateResult as l}from"./shared.js";const u="com.linkedin.voyager.dash.deco.identity.profile.FullProfileWithEntities-101",f="com.linkedin.voyager.dash.deco.identity.profile.FullProfilePositionGroup-58",w=/^\/in\/[^/?#]+\/?$/;export function normalizeProfileInputUrl(e,o){const n=m(e||"https://www.linkedin.com/in/me/","profile-url","/in/me/"),t=new URL(n);if(!w.test(t.pathname))throw new a(`LinkedIn ${o} requires a /in/<handle>/ profile URL`);return t.toString()}const h=String.raw`
|
|
2
2
|
const norm = (s) => String(s == null ? '' : s).replace(/[ ]+/g, ' ').replace(/\s+/g, ' ').trim();
|
|
3
3
|
const csrf = ((document.cookie.split('; ').find((c) => c.startsWith('JSESSIONID=')) || '').split('=')[1] || '').replace(/^"|"$/g, '');
|
|
4
4
|
const H = {
|
|
@@ -60,18 +60,18 @@ import{AuthRequiredError as Z,CommandExecutionError as $}from"@jackwener/opencli
|
|
|
60
60
|
const dateRange = start || endLabel ? norm((start + ' – ' + endLabel).replace(/^ – | – $/g, '').trim()) : '';
|
|
61
61
|
return { startDate: start, endDate: endLabel, dateRange };
|
|
62
62
|
}
|
|
63
|
-
`;function
|
|
63
|
+
`;function c(e,o){const n=Object.entries(e).map(([t,i])=>`const ${t} = ${JSON.stringify(i)};`).join(`
|
|
64
64
|
`);return`(async () => {
|
|
65
|
-
${
|
|
66
|
-
${
|
|
67
|
-
${
|
|
68
|
-
})()`}async function
|
|
65
|
+
${h}
|
|
66
|
+
${n}
|
|
67
|
+
${o}
|
|
68
|
+
})()`}async function p(e,o,n){await e.goto(o);await e.wait(3);const t=l(await e.evaluate(String.raw`(() => {
|
|
69
69
|
const path = String(location.pathname || '');
|
|
70
70
|
const authWall = /linkedin\.com\/(?:login|checkpoint|authwall|uas)/i.test(location.href)
|
|
71
71
|
|| Boolean(document.querySelector('input[name="session_key"], form.login__form'));
|
|
72
72
|
const m = path.match(/^\/in\/([^/?#]+)\/?$/);
|
|
73
73
|
return { publicId: m ? decodeURIComponent(m[1]) : '', authWall };
|
|
74
|
-
})()`));if(
|
|
74
|
+
})()`));if(t?.authWall)throw new s("linkedin.com",`LinkedIn ${n} requires an active signed-in browser session`);const i=y(t?.publicId);if(!i||i==="me")throw new a(`LinkedIn ${n} could not resolve the profile handle from ${o}`);return{publicId:i,profileUrl:`https://www.linkedin.com/in/${i}/`}}export async function fetchFullProfile(e,o,n){const{publicId:t,profileUrl:i}=await p(e,o,n),r=l(await e.evaluate(c({PUBLIC_ID:t,DECO:u},String.raw`
|
|
75
75
|
const r = await voyagerGet('/identity/dash/profiles?q=memberIdentity&memberIdentity=' + encodeURIComponent(PUBLIC_ID) + '&decorationId=' + DECO);
|
|
76
76
|
if (!r.ok) return { ok: false, auth: r.auth || false, status: r.status || 0 };
|
|
77
77
|
const byUrn = indexIncluded(r.json);
|
|
@@ -120,13 +120,13 @@ ${X}
|
|
|
120
120
|
},
|
|
121
121
|
positions, educations,
|
|
122
122
|
};
|
|
123
|
-
`)));if(
|
|
123
|
+
`)));if(r?.auth)throw new s("linkedin.com",`LinkedIn ${n} requires an active signed-in browser session`);if(!r?.ok)throw new a(`LinkedIn ${n}: profile API returned ${r?.empty?"no profile entity":"HTTP "+(r?.status||"?")}`);return{...r,profileUrl:i,publicId:t}}export async function fetchExperience(e,o,n){const{publicId:t,profileUrl:i}=await p(e,o,n),r=l(await e.evaluate(c({PUBLIC_ID:t,DECO:u},String.raw`
|
|
124
124
|
const r = await voyagerGet('/identity/dash/profiles?q=memberIdentity&memberIdentity=' + encodeURIComponent(PUBLIC_ID) + '&decorationId=' + DECO);
|
|
125
125
|
if (!r.ok) return { ok: false, auth: r.auth || false, status: r.status || 0 };
|
|
126
126
|
const byUrn = indexIncluded(r.json);
|
|
127
127
|
const profile = pickType(byUrn, 'identity.profile.Profile')[0] || null;
|
|
128
128
|
return { ok: !!profile, profileUrn: profile ? profile.entityUrn : '' };
|
|
129
|
-
`)));if(
|
|
129
|
+
`)));if(r?.auth)throw new s("linkedin.com",`LinkedIn ${n} requires an active signed-in browser session`);if(!r?.ok||!r?.profileUrn)throw new a(`LinkedIn ${n}: could not resolve profile urn (HTTP ${r?.status||"?"})`);const d=l(await e.evaluate(c({PROFILE_URN:r.profileUrn,DECO:f},String.raw`
|
|
130
130
|
const r = await voyagerGet('/identity/dash/profilePositionGroups?q=viewee&profileUrn=' + encodeURIComponent(PROFILE_URN) + '&decorationId=' + DECO);
|
|
131
131
|
if (!r.ok) return { ok: false, auth: r.auth || false, status: r.status || 0 };
|
|
132
132
|
const byUrn = indexIncluded(r.json);
|
|
@@ -152,7 +152,7 @@ ${X}
|
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
return { ok: true, rows };
|
|
155
|
-
`)));if(
|
|
155
|
+
`)));if(d?.auth)throw new s("linkedin.com",`LinkedIn ${n} requires an active signed-in browser session`);if(!d?.ok)throw new a(`LinkedIn ${n}: positionGroups API returned HTTP ${d?.status||"?"}`);return{rows:Array.isArray(d.rows)?d.rows:[],profileUrl:i,publicId:t}}export async function fetchProjects(e,o,n){const{profileUrl:t}=await p(e,o,n),i=l(await e.evaluate(c({DECO:u},String.raw`
|
|
156
156
|
const path = String(location.pathname || '').match(/^\/in\/([^/?#]+)/);
|
|
157
157
|
const pid = path ? decodeURIComponent(path[1]) : '';
|
|
158
158
|
const r = await voyagerGet('/identity/dash/profiles?q=memberIdentity&memberIdentity=' + encodeURIComponent(pid) + '&decorationId=' + DECO);
|
|
@@ -160,7 +160,7 @@ ${X}
|
|
|
160
160
|
const byUrn = indexIncluded(r.json);
|
|
161
161
|
const profile = pickType(byUrn, 'identity.profile.Profile')[0] || null;
|
|
162
162
|
return { ok: !!profile, profileUrn: profile ? profile.entityUrn : '' };
|
|
163
|
-
`)));if(
|
|
163
|
+
`)));if(i?.auth)throw new s("linkedin.com",`LinkedIn ${n} requires an active signed-in browser session`);if(!i?.ok||!i?.profileUrn)throw new a(`LinkedIn ${n}: could not resolve profile urn (HTTP ${i?.status||"?"})`);const r=l(await e.evaluate(c({PROFILE_URN:i.profileUrn},String.raw`
|
|
164
164
|
const r = await voyagerGet('/identity/dash/profileProjects?q=viewee&profileUrn=' + encodeURIComponent(PROFILE_URN) + '&count=50');
|
|
165
165
|
if (!r.ok) return { ok: false, auth: r.auth || false, status: r.status || 0 };
|
|
166
166
|
const byUrn = indexIncluded(r.json);
|
|
@@ -176,7 +176,7 @@ ${X}
|
|
|
176
176
|
};
|
|
177
177
|
});
|
|
178
178
|
return { ok: true, rows };
|
|
179
|
-
`)));if(
|
|
179
|
+
`)));if(r?.auth)throw new s("linkedin.com",`LinkedIn ${n} requires an active signed-in browser session`);if(!r?.ok)throw new a(`LinkedIn ${n}: profileProjects API returned HTTP ${r?.status||"?"}`);return{rows:Array.isArray(r.rows)?r.rows:[],profileUrl:t}}export async function fetchSelfAnalytics(e,o){await e.goto("https://www.linkedin.com/feed/");await e.wait(2);if(l(await e.evaluate(String.raw`(() => /linkedin\.com\/(?:login|checkpoint|authwall|uas)/i.test(location.href) || Boolean(document.querySelector('input[name="session_key"]')))()`)))throw new s("linkedin.com",`LinkedIn ${o} requires an active signed-in browser session`);const t=l(await e.evaluate(c({DECO:u},String.raw`
|
|
180
180
|
const result = { profile_views: '', search_appearances: '', followers: '', connections: '' };
|
|
181
181
|
// 资料浏览量 / 搜索出现次数
|
|
182
182
|
const wvmp = await voyagerGet('/identity/wvmpCards');
|
|
@@ -215,4 +215,4 @@ ${X}
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
return { ok: true, result };
|
|
218
|
-
`)));if(
|
|
218
|
+
`)));if(t?.auth)throw new s("linkedin.com",`LinkedIn ${o} requires an active signed-in browser session`);if(!t?.ok)throw new a(`LinkedIn ${o}: analytics API unavailable`);return t.result}export const __test__={normalizeProfileInputUrl,DECO_FULL_PROFILE:u,DECO_POSITION_GROUPS:f};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as c,Strategy as d}from"@jackwener/opencli/registry";import{CommandExecutionError as m,EmptyResultError as f}from"@jackwener/opencli/errors";import{normalizeWhitespace as t}from"./shared.js";import{fetchExperience as u,normalizeProfileInputUrl as _}from"./profile-api.js";function p(e,r,n,o){const i=t(e.title);return{rank:r+1,total_count:n,title:i,employment_type:"",company:t(e.company),date_range:t(e.dateRange),start_date:t(e.startDate),end_date:t(e.endDate),location:t(e.location),location_type:"",description:t(e.description),skills:"",media:"",urls:"",skill_url:"",media_url:"",profile_url:o,raw_text:[i,t(e.company),t(e.dateRange),t(e.location),t(e.description)].filter(Boolean).join(" | ")}}c({site:"linkedin",name:"profile-experience",access:"read",description:"Read LinkedIn profile experience entries via the Voyager API: titles, companies, dates, locations, and descriptions",domain:"www.linkedin.com",strategy:d.COOKIE,browser:!0,args:[{name:"profile-url",type:"string",required:!1,help:"LinkedIn /in/<handle>/ profile URL. Defaults to /in/me/."}],columns:["rank","total_count","title","employment_type","company","date_range","start_date","end_date","location","location_type","description","skills","media","urls","skill_url","media_url","profile_url","raw_text"],func:async(e,r)=>{if(!e)throw new m("Browser session required for linkedin profile-experience");const n=_(r["profile-url"],"profile-experience"),{rows:o,profileUrl:i}=await u(e,n,"profile-experience"),l=o.filter((a)=>t(a.title));if(l.length===0)throw new f("linkedin profile-experience","No LinkedIn profile experience entries were returned by the Voyager API.");return l.map((a,s)=>p(a,s,l.length,i))}});export const __test__={buildRow:p};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as d,Strategy as c}from"@jackwener/opencli/registry";import{CommandExecutionError as f,EmptyResultError as m}from"@jackwener/opencli/errors";import{normalizeWhitespace as r}from"./shared.js";import{fetchProjects as u,normalizeProfileInputUrl as w}from"./profile-api.js";function s(e,i,o){const t=r(e.title);return{rank:i+1,title:t,date_range:r(e.dateRange),associated_with:"",description:r(e.description),skills:"",media:"",urls:"",profile_url:o,raw_text:[t,r(e.dateRange),r(e.description)].filter(Boolean).join(" | ")}}d({site:"linkedin",name:"profile-projects",access:"read",description:"Read LinkedIn profile projects via the Voyager API: titles, dates, and descriptions",domain:"www.linkedin.com",strategy:c.COOKIE,browser:!0,args:[{name:"profile-url",type:"string",required:!1,help:"LinkedIn /in/<handle>/ profile URL. Defaults to /in/me/."}],columns:["rank","title","date_range","associated_with","description","skills","media","urls","profile_url","raw_text"],func:async(e,i)=>{if(!e)throw new f("Browser session required for linkedin profile-projects");const o=w(i["profile-url"],"profile-projects"),{rows:t,profileUrl:a}=await u(e,o,"profile-projects"),l=t.filter((n)=>r(n.title));if(l.length===0)throw new m("linkedin profile-projects","No LinkedIn profile projects were returned by the Voyager API.");return l.map((n,p)=>s(n,p,a))}});export const __test__={buildRow:s};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{cli as
|
|
2
|
-
`),education:
|
|
3
|
-
`),services:"",featured:""}]}});export const __test__={fmtPosition:
|
|
1
|
+
import{cli as p,Strategy as h}from"@jackwener/opencli/registry";import{CommandExecutionError as c}from"@jackwener/opencli/errors";import{compactRepeatedText as s,normalizeWhitespace as o}from"./shared.js";import{fetchFullProfile as _,normalizeProfileInputUrl as w}from"./profile-api.js";function f(e){const i=[o(e.title),o(e.company)].filter(Boolean).join(" — "),n=[o(e.location),o(e.dateRange)].filter(Boolean).join(" · ");return[i,n].filter(Boolean).join(" (")+(n?")":"")}function d(e){const i=o(e.school),t=[[o(e.degree),o(e.field)].filter(Boolean).join(", "),o(e.dateRange)].filter(Boolean).join(" · ");return[i,t].filter(Boolean).join(" (")+(t?")":"")}p({site:"linkedin",name:"profile-read",access:"read",description:"Read LinkedIn profile sections via the Voyager API: name, headline, location, About, experience, and education",domain:"www.linkedin.com",strategy:h.COOKIE,browser:!0,args:[{name:"profile-url",type:"string",required:!1,help:"LinkedIn /in/<handle>/ profile URL. Defaults to /in/me/."}],columns:["profile_url","name","headline","location","about","about_character_count","about_skills","experience","education","services","featured"],func:async(e,i)=>{if(!e)throw new c("Browser session required for linkedin profile-read");const n=w(i["profile-url"],"profile-read"),t=await _(e,n,"profile-read"),{profile:r,positions:u,educations:m}=t,a=s([r.firstName,r.lastName].filter(Boolean).join(" "));if(!a)throw new c("LinkedIn profile-read could not find a profile name");const l=o(r.summary);return[{profile_url:t.profileUrl,name:a,headline:s(r.headline),location:o(r.location),about:l,about_character_count:`${l.length}/2,600`,about_skills:"",experience:u.map(f).filter(Boolean).join(`
|
|
2
|
+
`),education:m.map(d).filter(Boolean).join(`
|
|
3
|
+
`),services:"",featured:""}]}});export const __test__={fmtPosition:f,fmtEducation:d};
|
package/clis/linkedin/reply.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as d,Strategy as p}from"@jackwener/opencli/registry";import{ArgumentError as m,AuthRequiredError as h,CommandExecutionError as u}from"@jackwener/opencli/errors";import{assertLinkedInAuthenticated as y,LINKEDIN_DOMAIN as l,unwrapEvaluateResult as w}from"./shared.js";import{buildCommentScript as f,NORM_COMMENT_DECORATION as _,normalizeCommentUrn as g}from"./social-api.js";const i=1250;d({site:"linkedin",name:"reply",access:"write",description:"Reply to a comment on a LinkedIn post via the Voyager API. Dry-run by default; pass --send true to actually publish. The comment urn comes from `linkedin post-comments`.",domain:l,strategy:p.COOKIE,browser:!0,args:[{name:"comment",type:"string",required:!0,positional:!0,help:"The comment to reply to: a comment_urn from `linkedin post-comments` (urn:li:comment:(activity:…,…) or urn:li:fsd_comment:(…))."},{name:"text",fromFile:!0,type:"string",required:!0,help:`Reply body (max ${i} chars).`},{name:"send",type:"bool",required:!1,default:!1,help:"Actually post the reply. Default false = dry-run (validates the session only; nothing is posted)."}],columns:["status","parent_comment_urn","reply_urn","text_chars"],func:async(r,n)=>{if(!r)throw new u("Browser session required for linkedin reply");const o=g(n?.comment),e=String(n?.text??"").replace(/ /g," ").trim();if(!e)throw new m("--text is required");if(e.length>i)throw new m(`--text must be ${i} characters or fewer (got ${e.length})`);const c=n?.send===!0||n?.send==="true",s=o.match(/urn:li:comment:\((activity|ugcPost):(\d+),/),a=s?`urn:li:${s[1]}:${s[2]}`:"";await r.goto(a?`https://www.linkedin.com/feed/update/${a}/`:"https://www.linkedin.com/feed/");await r.wait(2);if(!c){await y(r,"LinkedIn reply");return[{status:"dry_run",parent_comment_urn:o,reply_urn:"(not posted — pass --send true to publish)",text_chars:e.length}]}const t=w(await r.evaluate(f({threadUrn:o,text:e,decorationId:_})));if(!t?.ok){if(t?.stage==="auth"||t?.httpStatus===401||t?.httpStatus===403)throw new h(l,`LinkedIn reply requires an active signed-in LinkedIn browser session (${t?.error||"auth"}).`);throw new u(`LinkedIn reply failed: stage=${t?.stage||"unknown"} http=${t?.httpStatus||"?"} ${t?.error||""}`.trim())}return[{status:"replied",parent_comment_urn:o,reply_urn:t.commentUrn||"",text_chars:e.length}]}});
|
package/clis/linkedin/repost.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as p,Strategy as d}from"@jackwener/opencli/registry";import{ArgumentError as l,AuthRequiredError as h,CommandExecutionError as i}from"@jackwener/opencli/errors";import{assertLinkedInAuthenticated as m,LINKEDIN_DOMAIN as a,unwrapEvaluateResult as c}from"./shared.js";import{buildRepostScript as w,normalizeThreadUrn as f,REPOST_CREATE_QID as y}from"./social-api.js";const o=3000;p({site:"linkedin",name:"repost",access:"write",description:"Repost (reshare) a LinkedIn post to your own feed via the Voyager API. Plain repost by default; pass --text to quote-repost with your commentary. Dry-run unless --send true.",domain:a,strategy:d.COOKIE,browser:!0,args:[{name:"post",type:"string",required:!0,positional:!0,help:"Post to repost: a LinkedIn post URL (…/feed/update/… or …/posts/…) or a raw urn:li:activity:… / urn:li:ugcPost:… urn."},{name:"text",fromFile:!0,type:"string",required:!1,help:`Optional commentary to quote-repost with (max ${o} chars). Omit for a plain repost.`},{name:"send",type:"bool",required:!1,default:!1,help:"Actually repost. Default false = dry-run (validates the session only; nothing is posted)."}],columns:["status","shared_urn","repost_urn","quote"],func:async(e,r)=>{if(!e)throw new i("Browser session required for linkedin repost");const n=f(r?.post),s=String(r?.text??"").replace(/ /g," ").trim();if(s.length>o)throw new l(`--text must be ${o} characters or fewer (got ${s.length})`);const u=r?.send===!0||r?.send==="true";await e.goto("https://www.linkedin.com/feed/");await e.wait(2);if(!u){await m(e,"LinkedIn repost");return[{status:"dry_run",shared_urn:n,repost_urn:"(not posted — pass --send true to repost)",quote:s?"yes":""}]}const t=c(await e.evaluate(w({activityUrn:n,commentary:s,repostQid:y})));if(!t?.ok){if(t?.stage==="auth"||t?.httpStatus===401||t?.httpStatus===403)throw new h(a,`LinkedIn repost requires an active signed-in LinkedIn browser session (${t?.error||"auth"}).`);throw new i(`LinkedIn repost failed: stage=${t?.stage||"unknown"} http=${t?.httpStatus||"?"} ${t?.error||""}`.trim())}return[{status:"reposted",shared_urn:t.shared_urn||"",repost_urn:t.repost_urn||"",quote:t.quote?"yes":""}]}});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as N,Strategy as A}from"@jackwener/opencli/registry";import{ArgumentError as b,AuthRequiredError as R,CommandExecutionError as c}from"@jackwener/opencli/errors";import{createHash as q}from"node:crypto";const v="www.linkedin.com";function o(e){return String(e??"").replace(/[\u00a0\u202f]/g," ").replace(/\s+/g," ").trim()}function d(e){if(e&&typeof e==="object"&&"data"in e&&"session"in e)return e.data;return e}function m(e){return o(e).replace(/\s*[•·]\s*(?:1st|2nd|3rd\+?|degree connection).*$/i,"").replace(/\s+LinkedIn.*$/i,"").toLowerCase()}function M(e){const n=String(e||"").toLowerCase();return n==="linkedin.com"||n.endsWith(".linkedin.com")}function p(e){const n=o(e);if(!n)return"";try{const t=new URL(n);if(t.protocol!=="https:"||t.username||t.password||t.port||!M(t.hostname))return"";const r=t.pathname.match(/^\/messaging\/thread\/([^/]+)\/?$/i);if(!r||!r[1])return"";t.hostname="www.linkedin.com";t.hash="";t.search="";if(!t.pathname.endsWith("/"))t.pathname+="/";return t.toString()}catch{return""}}function T(e){return q("sha256").update(o(e)).digest("hex")}function y(e,n){const t=o(e).toLowerCase(),r=o(n).toLowerCase();return!r||t.includes(r)}function L(e){return/\r|\n/.test(String(e??""))}function U(e,n){const t=m(n),r=(Array.isArray(e)?e:[]).map(o).filter(Boolean);return r.find((i)=>m(i)===t)||r[0]||""}function x(e,n){const t=o(n.expectedName),r=U(e?.headerNames,t),i=p(n.threadUrl),a=p(e?.url||""),u=String(e?.bodyText||"");if(e?.authRequired)return{ok:!1,blockReason:"auth_required",expectedValue:t,actualValue:r,observedUrl:a};if(e?.searchFailure||/we didn't find anything|no results found|no results for/i.test(u))return{ok:!1,blockReason:"search_failure_visible",expectedValue:t,actualValue:r,observedUrl:a};if(i&&a&&i!==a)return{ok:!1,blockReason:"thread_url_mismatch",expectedValue:i,actualValue:a,observedUrl:a};if(!r||m(r)!==m(t))return{ok:!1,blockReason:"recipient_header_mismatch",expectedValue:t,actualValue:r,observedUrl:a};if(!e?.composerFound)return{ok:!1,blockReason:"composer_not_found",expectedValue:t,actualValue:r,observedUrl:a};const s=o(n.expectedLastHash);if(s&&s!==e?.latestMessageHash)return{ok:!1,blockReason:"latest_message_mismatch",expectedValue:s,actualValue:e?.latestMessageHash||"",observedUrl:a};const l=o(n.expectedLastText);if(l&&!y(u,l))return{ok:!1,blockReason:"latest_message_mismatch",expectedValue:l,actualValue:"",observedUrl:a};return{ok:!0,blockReason:"verified",expectedValue:t,actualValue:r,observedUrl:a}}function C(e,n,t=n){const r=o(e[n]);if(!r)throw new b(`${t} is required`);return r}function S(e,n,t=n){const r=String(e[n]??"");if(!o(r))throw new b(`${t} is required`);return r}function V(e,n){const t=p(e);if(!t)throw new b(`${n} must be an exact https://www.linkedin.com/messaging/thread/<id>/ URL`);return t}function B(){return String.raw`(() => {
|
|
2
2
|
const marker = '__OPENCLI_LINKEDIN_PROBE__';
|
|
3
3
|
void marker;
|
|
4
4
|
const clean = (s) => String(s || '').replace(/[\u00a0\u202f]/g, ' ').replace(/\s+/g, ' ').trim();
|
|
@@ -53,7 +53,7 @@ import{cli as U,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentE
|
|
|
53
53
|
latestMessageText: lastMeaningfulLine,
|
|
54
54
|
latestMessageHash: '',
|
|
55
55
|
};
|
|
56
|
-
})()`}function
|
|
56
|
+
})()`}function P(){return String.raw`(() => {
|
|
57
57
|
const marker = '__OPENCLI_LINKEDIN_FOCUS_COMPOSER__';
|
|
58
58
|
void marker;
|
|
59
59
|
const clean = (s) => String(s || '').replace(/[\u00a0\u202f]/g, ' ').replace(/\s+/g, ' ').trim();
|
|
@@ -64,17 +64,17 @@ import{cli as U,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentE
|
|
|
64
64
|
composer.innerHTML = '';
|
|
65
65
|
composer.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'deleteContentBackward', data: null }));
|
|
66
66
|
return { ok: true, composerText: clean(composer.innerText || composer.textContent) };
|
|
67
|
-
})()`}function
|
|
67
|
+
})()`}function D(){return String.raw`(() => {
|
|
68
68
|
const marker = '__OPENCLI_LINKEDIN_READ_COMPOSER__';
|
|
69
69
|
void marker;
|
|
70
70
|
const clean = (s) => String(s || '').replace(/[\u00a0\u202f]/g, ' ').replace(/\s+/g, ' ').trim();
|
|
71
71
|
const composer = Array.from(document.querySelectorAll('[contenteditable="true"][role="textbox"], div.msg-form__contenteditable[contenteditable="true"], [aria-label*="Write a message" i]'))
|
|
72
72
|
.find((el) => !el.closest('[aria-hidden="true"]') && el.offsetParent !== null);
|
|
73
73
|
return { ok: Boolean(composer), composerText: composer ? clean(composer.innerText || composer.textContent) : '' };
|
|
74
|
-
})()`}function
|
|
74
|
+
})()`}function I(e){return`(() => {
|
|
75
75
|
const marker = '__OPENCLI_LINKEDIN_FILL_COMPOSER_MULTILINE__';
|
|
76
76
|
void marker;
|
|
77
|
-
const message = ${JSON.stringify(String(
|
|
77
|
+
const message = ${JSON.stringify(String(e??""))};
|
|
78
78
|
const normalize = (s) => String(s || '').replace(/[\\u00a0\\u202f]/g, ' ').replace(/\\s+/g, ' ').trim();
|
|
79
79
|
const composer = Array.from(document.querySelectorAll('[contenteditable="true"][role="textbox"], div.msg-form__contenteditable[contenteditable="true"], [aria-label*="Write a message" i]'))
|
|
80
80
|
.find((el) => !el.closest('[aria-hidden="true"]') && el.offsetParent !== null);
|
|
@@ -139,7 +139,7 @@ import{cli as U,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentE
|
|
|
139
139
|
method,
|
|
140
140
|
renderedBreaks: brCount + childBlockCount,
|
|
141
141
|
};
|
|
142
|
-
})()`}function
|
|
142
|
+
})()`}function O(){return String.raw`(() => {
|
|
143
143
|
const marker = '__OPENCLI_LINKEDIN_CLICK_SEND__';
|
|
144
144
|
void marker;
|
|
145
145
|
const buttons = Array.from(document.querySelectorAll('button'));
|
|
@@ -151,5 +151,5 @@ import{cli as U,Strategy as v}from"@jackwener/opencli/registry";import{ArgumentE
|
|
|
151
151
|
if (send.disabled || send.getAttribute('aria-disabled') === 'true') return { ok: false, error: 'send_button_disabled', sent: false };
|
|
152
152
|
send.click();
|
|
153
153
|
return { ok: true, sent: true };
|
|
154
|
-
})()`}async function
|
|
155
|
-
`);throw new
|
|
154
|
+
})()`}async function _(e){const n=d(await e.evaluate(B())),t=o(n?.latestMessageText||"");return{...n||{},latestMessageText:t,latestMessageHash:t?T(t):""}}async function F(e,n){if(!L(n)){await e.insertText(n);return{method:"insert_text",renderedBreaks:0}}const t=d(await e.evaluate(I(n)));if(t?.ok)return{method:t.method||"dom_multiline",renderedBreaks:Number(t.renderedBreaks||0)};await e.insertText(n);return{method:"insert_text_fallback",renderedBreaks:0}}N({site:"linkedin",name:"safe-send",access:"write",description:"Fail-closed LinkedIn message sender that verifies exact thread, recipient, and latest message before filling/sending",domain:v,strategy:A.UI,browser:!0,args:[{name:"thread-url",required:!0,help:"Exact LinkedIn messaging thread URL to open and verify"},{name:"expected-name",required:!0,help:"Expected visible recipient name in the active thread header"},{name:"message",fromFile:!0,required:!0,help:"Message body to send or dry-run"},{name:"expected-last-text",help:"Substring expected in the currently visible latest conversation context"},{name:"expected-last-hash",help:"SHA-256 hash of expected latest visible message text"},{name:"send",type:"bool",default:!1,help:"Actually click Send. Default is dry-run verification only."},{name:"screenshot",type:"bool",default:!1,help:"Capture a screenshot during verification"}],columns:["status","recipient","reason","thread_url","message_chars","screenshot"],func:async(e,n)=>{if(!e)throw new c("Browser session required for linkedin safe-send");const t=V(C(n,"thread-url","--thread-url"),"--thread-url"),r=C(n,"expected-name","--expected-name"),i=S(n,"message","--message");await e.goto("https://www.linkedin.com/messaging/");await e.wait(4);await e.goto(t);await e.wait(12);let a=await _(e);const u=o(n["expected-last-text"]);for(let f=0;u&&f<6&&!y(a.bodyText,u);f+=1){await e.wait(2);a=await _(e)}const s=x(a,{expectedName:r,threadUrl:t,expectedLastText:n["expected-last-text"],expectedLastHash:n["expected-last-hash"]});if(s.blockReason==="auth_required")throw new R(v,"LinkedIn safe-send requires an active signed-in LinkedIn browser session.");if(!s.ok){const f=[`Expected ${s.expectedValue}; actual ${s.actualValue||"not_visible"} at ${s.observedUrl||"url_not_available"}`,`Observed headers: ${(a.headerNames||[]).join(" | ")||"no_visible_headers"}`,`Title: ${a.title||"title_not_available"}`,`Body: ${o(a.bodyText||"").slice(0,500)}`].join(`
|
|
155
|
+
`);throw new c(`LinkedIn safe-send blocked: ${s.blockReason}`,f)}let l="";if(n.screenshot&&typeof e.screenshot==="function")l=await e.screenshot({fullPage:!1});if(!n.send)return[{status:"verified_dry_run",recipient:s.actualValue,reason:s.blockReason,thread_url:s.observedUrl,message_chars:i.length,screenshot:l?"captured":""}];const g=d(await e.evaluate(P()));if(!g?.ok)throw new c(`LinkedIn safe-send blocked: ${g?.error||"composer_focus_failed"}`);await F(e,i);await e.wait(0.6+Math.random()*0.8);const w=d(await e.evaluate(D()));if(!w?.ok||o(w.composerText)!==o(i))throw new c("LinkedIn safe-send blocked: composer_text_mismatch",`Composer text did not exactly match intended message for ${r}.`);const E=await _(e),k=x(E,{expectedName:r,threadUrl:t,expectedLastText:n["expected-last-text"],expectedLastHash:n["expected-last-hash"]});if(!k.ok)throw new c(`LinkedIn safe-send blocked after fill: ${k.blockReason}`);const h=d(await e.evaluate(O()));if(!h?.ok||!h.sent)throw new c(`LinkedIn safe-send blocked: ${h?.error||"send_click_failed"}`);await e.wait(0.8+Math.random()*1.2);return[{status:"sent",recipient:s.actualValue,reason:s.blockReason,thread_url:s.observedUrl,message_chars:i.length,screenshot:l?"captured":""}]}});export const __test__={normalizeWhitespace:o,unwrapEvaluateResult:d,normalizeName:m,canonicalizeLinkedInThreadUrl:p,hashText:T,hasLineBreaks:L,requireRawStringArg:S,buildFillComposerMultilineScript:I,assessThreadSafety:x};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{cli as
|
|
1
|
+
import{cli as b,Strategy as A}from"@jackwener/opencli/registry";import{ArgumentError as I,AuthRequiredError as w,CommandExecutionError as o,EmptyResultError as v}from"@jackwener/opencli/errors";const m="www.linkedin.com",k="https://www.linkedin.com/sales/inbox/",THREADS_BASE="https://www.linkedin.com/sales-api/salesApiMessagingThreads",h=20,g=40,_=500,THREAD_DECORATION="(id,restrictions,archived,unreadMessageCount,nextPageStartsAt,totalMessageCount,messages*(id,type,contentFlag,deliveredAt,lastEditedAt,subject,body,footerText,blockCopy,attachments,author,systemMessageContent),participants*~fs_salesProfile(entityUrn,firstName,lastName,fullName,degree,profilePictureDisplayImage,objectUrn,inmailRestriction))";export function normalizeWhitespace(e){return String(e??"").replace(/[\u00a0\u202f]/g," ").replace(/\s+/g," ").trim()}export function parseLimit(e,t=g){if(e===void 0||e===null||e==="")return t;const n=Number(e);if(!Number.isInteger(n)||n<1||n>_)throw new I(`--limit must be an integer between 1 and ${_}`);return n}function j(e){if(e&&typeof e==="object"&&"data"in e&&"session"in e)return e.data;return e}export function encodeRestliDecoration(e){return encodeURIComponent(e).replace(/\(/g,"%28").replace(/\)/g,"%29")}function S(e){return e?`https://www.linkedin.com/sales/inbox/${encodeURIComponent(e)}`:""}function y({count:e=h,pageStartsAt:t=""}={}){let n=`${THREADS_BASE}?decoration=${encodeRestliDecoration(THREAD_DECORATION)}&count=${e}&filter=INBOX&q=filter`;if(t)n+=`&pageStartsAt=${encodeURIComponent(t)}`;return n}function N(e){const t=e?.participantsResolutionResults||{};return(Array.isArray(e?.participants)?e.participants:Object.keys(t)).map((r)=>t[r]||{entityUrn:r}).filter(Boolean)}function E(e){return String(e?.degree??"").trim()==="0"}function P(e){const t=N(e),n=t.find((r)=>!E(r))||t[0];return normalizeWhitespace(n?.fullName||[n?.firstName,n?.lastName].filter(Boolean).join(" "))}function x(e){if(!e||typeof e!=="object"||!Array.isArray(e.elements))throw new o("Sales Navigator messaging threads API returned malformed payload");return e.elements.map((t)=>{if(!t||typeof t!=="object")throw new o("Sales Navigator messaging threads API returned malformed thread row");const n=Array.isArray(t?.messages)?t.messages:[],r=n[0]||{},s=Number(r.deliveredAt||t?.nextPageStartsAt||0),i=normalizeWhitespace(t?.id||"");if(!i)throw new o("Sales Navigator messaging thread row missing id");return{thread_id:i,thread_url:S(i),person_name:P(t),last_message_snippet:normalizeWhitespace(r.body||r.subject||"").slice(0,300),last_activity_time:s?new Date(s).toISOString():"",unread:Number(t?.unreadMessageCount||0)>0,unread_count:Number(t?.unreadMessageCount||0),total_message_count:Number(t?.totalMessageCount||n.length||0),archived:Boolean(t?.archived),next_page_starts_at:normalizeWhitespace(t?.nextPageStartsAt||""),participants:N(t).map((a)=>({name:normalizeWhitespace(a.fullName||[a.firstName,a.lastName].filter(Boolean).join(" ")),entity_urn:normalizeWhitespace(a.entityUrn||""),object_urn:normalizeWhitespace(a.objectUrn||""),degree:normalizeWhitespace(a.degree??"")}))}})}function R(e,t){return String.raw`(async () => {
|
|
2
2
|
try {
|
|
3
|
-
const res = await fetch(${JSON.stringify(
|
|
3
|
+
const res = await fetch(${JSON.stringify(e)}, {
|
|
4
4
|
credentials: 'include',
|
|
5
5
|
headers: {
|
|
6
|
-
'csrf-token': ${JSON.stringify(
|
|
6
|
+
'csrf-token': ${JSON.stringify(t)},
|
|
7
7
|
'x-restli-protocol-version': '2.0.0',
|
|
8
8
|
accept: 'application/json',
|
|
9
9
|
},
|
|
@@ -17,5 +17,5 @@ import{cli as y,Strategy as M}from"@jackwener/opencli/registry";import{ArgumentE
|
|
|
17
17
|
} catch (e) {
|
|
18
18
|
return { error: 'fetch failed: ' + ((e && e.message) || String(e)) };
|
|
19
19
|
}
|
|
20
|
-
})()`}export async function getCsrf(
|
|
21
|
-
${normalizeWhitespace(
|
|
20
|
+
})()`}export async function getCsrf(e){const n=(await e.getCookies({url:"https://www.linkedin.com"})).find((r)=>r.name==="JSESSIONID")?.value;if(!n)throw new w(m,"LinkedIn JSESSIONID cookie not found. Please sign in to LinkedIn.");return n.replace(/^\"|\"$/g,"")}export async function fetchSalesnavJson(e,t,n,r){const s=j(await e.evaluate(R(n,t)));if(s?.authRequired)throw new w(m,`${r} authentication failed (HTTP ${s.status||"auth_required"}).`);if(s?.error||!s?.json)throw new o(`${r} returned an unexpected response`,`${s?.error||"no_json"}
|
|
21
|
+
${normalizeWhitespace(s?.text||"").slice(0,500)}`);return s.json}export async function fetchInboxRows(e,{limit:t=g,maxPages:n=30}={}){const r=await getCsrf(e),s=[],i=new Set;let a="",u=0,p=!1;while(s.length<t&&u<n){const d=await fetchSalesnavJson(e,r,y({count:h,pageStartsAt:a}),"Sales Navigator messaging threads API");u+=1;const c=x(d);if(c.length===0)break;for(const f of c){if(i.has(f.thread_id))continue;i.add(f.thread_id);s.push(f);if(s.length>=t)break}const l=c[c.length-1]?.next_page_starts_at;p=Boolean(l);if(!l)break;if(l===a)throw new o("Sales Navigator messaging threads API returned the same cursor twice");a=l}if(s.length<t&&p&&u>=n)throw new o(`Sales Navigator messaging threads API reached the ${n}-page safety cap before collecting ${t} conversations`);return s.slice(0,t).map((d,c)=>({...d,rank:c+1}))}export{THREAD_DECORATION,THREADS_BASE};b({site:"linkedin",name:"salesnav-inbox",access:"read",description:"List LinkedIn Sales Navigator message conversations with API pagination",domain:m,strategy:A.UI,browser:!0,args:[{name:"limit",type:"number",default:g,help:"Maximum conversations to return (1-500)"},{name:"max-pages",type:"number",default:30,help:"Maximum Sales Navigator API pages to fetch"},{name:"unread-only",type:"bool",default:!1,help:"Return only unread conversations"}],columns:["rank","thread_id","thread_url","person_name","last_message_snippet","last_activity_time","unread","unread_count","total_message_count","archived","participants","next_page_starts_at"],func:async(e,t)=>{if(!e)throw new o("Browser session required for linkedin salesnav-inbox");const n=parseLimit(t.limit),r=parseLimit(t["max-pages"],30);await e.goto(k);await e.wait(4);let s=await fetchInboxRows(e,{limit:n,maxPages:r});if(t["unread-only"])s=s.filter((i)=>i.unread);if(s.length===0){if(t["unread-only"])return[];throw new v("linkedin salesnav-inbox","No Sales Navigator conversations were found.")}return s.slice(0,n).map((i,a)=>({...i,rank:a+1}))}});export const __test__={THREAD_DECORATION,normalizeWhitespace,parseLimit,encodeRestliDecoration,salesnavThreadUrl:S,threadListUrl:y,parseSalesnavThreads:x,fetchInboxRows};
|