@jackwener/opencli 1.1.0 → 1.1.1
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/.agents/skills/cross-project-adapter-migration/SKILL.md +2 -2
- package/.github/pull_request_template.md +7 -0
- package/.github/workflows/doc-check.yml +36 -0
- package/.github/workflows/docs.yml +7 -42
- package/CHANGELOG.md +23 -0
- package/CLI-EXPLORER.md +9 -8
- package/README.md +25 -10
- package/README.zh-CN.md +26 -11
- package/SKILL.md +95 -31
- package/dist/browser/cdp.js +6 -1
- package/dist/browser/page.d.ts +4 -1
- package/dist/browser/page.js +7 -1
- package/dist/build-manifest.js +23 -16
- package/dist/cli-manifest.json +431 -276
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +189 -162
- package/dist/clis/apple-podcasts/commands.test.d.ts +2 -0
- package/dist/clis/apple-podcasts/commands.test.js +76 -0
- package/dist/clis/apple-podcasts/search.js +2 -2
- package/dist/clis/apple-podcasts/top.js +9 -2
- package/dist/clis/arxiv/search.js +1 -1
- package/dist/clis/bilibili/dynamic.js +1 -1
- package/dist/clis/bilibili/favorite.js +1 -1
- package/dist/clis/bilibili/feed.js +1 -1
- package/dist/clis/bilibili/following.js +1 -1
- package/dist/clis/bilibili/history.js +1 -1
- package/dist/clis/bilibili/me.js +1 -1
- package/dist/clis/bilibili/ranking.js +1 -1
- package/dist/clis/bilibili/search.js +3 -3
- package/dist/clis/bilibili/subtitle.js +1 -1
- package/dist/clis/bilibili/user-videos.js +1 -1
- package/dist/{bilibili.d.ts → clis/bilibili/utils.d.ts} +1 -1
- package/dist/clis/bloomberg/businessweek.js +17 -0
- package/dist/clis/bloomberg/economics.js +17 -0
- package/dist/clis/bloomberg/feeds.d.ts +1 -0
- package/dist/clis/bloomberg/feeds.js +15 -0
- package/dist/clis/bloomberg/industries.d.ts +1 -0
- package/dist/clis/bloomberg/industries.js +17 -0
- package/dist/clis/bloomberg/main.d.ts +1 -0
- package/dist/clis/bloomberg/main.js +17 -0
- package/dist/clis/bloomberg/markets.d.ts +1 -0
- package/dist/clis/bloomberg/markets.js +17 -0
- package/dist/clis/bloomberg/news.d.ts +1 -0
- package/dist/clis/bloomberg/news.js +105 -0
- package/dist/clis/bloomberg/opinions.d.ts +1 -0
- package/dist/clis/bloomberg/opinions.js +17 -0
- package/dist/clis/bloomberg/politics.d.ts +1 -0
- package/dist/clis/bloomberg/politics.js +17 -0
- package/dist/clis/bloomberg/tech.d.ts +1 -0
- package/dist/clis/bloomberg/tech.js +17 -0
- package/dist/clis/bloomberg/utils.d.ts +34 -0
- package/dist/clis/bloomberg/utils.js +364 -0
- package/dist/clis/bloomberg/utils.test.d.ts +1 -0
- package/dist/clis/bloomberg/utils.test.js +129 -0
- package/dist/clis/boss/batchgreet.js +2 -2
- package/dist/clis/boss/chatlist.js +2 -2
- package/dist/clis/boss/detail.js +2 -2
- package/dist/clis/boss/greet.js +4 -4
- package/dist/clis/boss/search.js +1 -1
- package/dist/clis/boss/send.js +1 -1
- package/dist/clis/boss/stats.js +2 -2
- package/dist/clis/chaoxing/assignments.js +1 -1
- package/dist/clis/chaoxing/exams.js +1 -1
- package/dist/{chaoxing.d.ts → clis/chaoxing/utils.d.ts} +1 -1
- package/dist/{chaoxing.js → clis/chaoxing/utils.js} +0 -2
- package/dist/clis/chaoxing/utils.test.d.ts +1 -0
- package/dist/{chaoxing.test.js → clis/chaoxing/utils.test.js} +1 -1
- package/dist/clis/chatgpt/read.js +1 -1
- package/dist/clis/chatwise/export.js +1 -1
- package/dist/clis/chatwise/model.js +2 -2
- package/dist/clis/chatwise/screenshot.js +1 -1
- package/dist/clis/codex/export.js +1 -1
- package/dist/clis/codex/model.js +2 -2
- package/dist/clis/codex/screenshot.js +1 -1
- package/dist/clis/coupang/add-to-cart.js +3 -4
- package/dist/clis/coupang/search.js +2 -4
- package/dist/clis/coupang/utils.test.d.ts +1 -0
- package/dist/{coupang.test.js → clis/coupang/utils.test.js} +1 -1
- package/dist/clis/ctrip/search.js +1 -1
- package/dist/clis/cursor/export.js +1 -1
- package/dist/clis/cursor/model.js +2 -2
- package/dist/clis/cursor/screenshot.js +1 -1
- package/dist/clis/jike/comment.js +2 -3
- package/dist/clis/jike/create.js +1 -2
- package/dist/clis/jike/feed.js +0 -1
- package/dist/clis/jike/like.js +1 -2
- package/dist/clis/jike/notifications.js +0 -1
- package/dist/clis/jike/post.yaml +1 -0
- package/dist/clis/jike/repost.js +1 -2
- package/dist/clis/jike/search.js +2 -3
- package/dist/clis/jike/topic.yaml +1 -0
- package/dist/clis/jike/user.yaml +1 -0
- package/dist/clis/jimeng/history.yaml +0 -1
- package/dist/clis/linkedin/search.js +7 -7
- package/dist/clis/linux-do/category.yaml +1 -0
- package/dist/clis/linux-do/search.yaml +4 -3
- package/dist/clis/linux-do/topic.yaml +1 -0
- package/dist/clis/notion/export.js +1 -1
- package/dist/clis/reddit/comment.js +3 -4
- package/dist/clis/reddit/read.js +4 -5
- package/dist/clis/reddit/save.js +2 -3
- package/dist/clis/reddit/saved.js +0 -1
- package/dist/clis/reddit/search.yaml +1 -0
- package/dist/clis/reddit/subscribe.js +0 -1
- package/dist/clis/reddit/upvote.js +2 -3
- package/dist/clis/reddit/upvoted.js +0 -1
- package/dist/clis/reddit/user-comments.yaml +1 -0
- package/dist/clis/reddit/user-posts.yaml +1 -0
- package/dist/clis/reddit/user.yaml +1 -0
- package/dist/clis/reuters/search.js +1 -1
- package/dist/clis/smzdm/search.js +2 -3
- package/dist/clis/stackoverflow/search.yaml +1 -0
- package/dist/clis/steam/top-sellers.yaml +29 -0
- package/dist/clis/twitter/accept.js +2 -2
- package/dist/clis/twitter/article.js +2 -2
- package/dist/clis/twitter/block.d.ts +1 -0
- package/dist/clis/twitter/block.js +88 -0
- package/dist/clis/twitter/delete.js +1 -1
- package/dist/clis/twitter/hide-reply.d.ts +1 -0
- package/dist/clis/twitter/hide-reply.js +66 -0
- package/dist/clis/twitter/like.js +1 -1
- package/dist/clis/twitter/post.js +1 -1
- package/dist/clis/twitter/reply-dm.js +1 -1
- package/dist/clis/twitter/reply.js +2 -2
- package/dist/clis/twitter/search.js +1 -1
- package/dist/clis/twitter/thread.js +2 -2
- package/dist/clis/twitter/trending.d.ts +1 -0
- package/dist/clis/twitter/trending.js +91 -0
- package/dist/clis/twitter/unblock.d.ts +1 -0
- package/dist/clis/twitter/unblock.js +71 -0
- package/dist/clis/v2ex/topic.yaml +1 -0
- package/dist/clis/weibo/hot.js +0 -1
- package/dist/clis/weread/book.js +1 -1
- package/dist/clis/weread/highlights.js +1 -1
- package/dist/clis/weread/notes.js +1 -1
- package/dist/clis/weread/search.js +1 -1
- package/dist/clis/wikipedia/search.js +1 -1
- package/dist/clis/xiaohongshu/creator-note-detail.d.ts +15 -0
- package/dist/clis/xiaohongshu/creator-note-detail.js +69 -5
- package/dist/clis/xiaohongshu/creator-note-detail.test.js +80 -33
- package/dist/clis/xiaohongshu/creator-notes.js +35 -5
- package/dist/clis/xiaohongshu/creator-notes.test.js +35 -6
- package/dist/clis/xiaohongshu/creator-profile.js +0 -1
- package/dist/clis/xiaohongshu/creator-stats.js +0 -1
- package/dist/clis/xiaohongshu/download.js +2 -3
- package/dist/clis/xiaohongshu/feed.yaml +0 -1
- package/dist/clis/xiaohongshu/notifications.yaml +0 -1
- package/dist/clis/xiaohongshu/search.js +2 -2
- package/dist/clis/xiaohongshu/user.js +1 -2
- package/dist/clis/yahoo-finance/quote.js +0 -1
- package/dist/clis/youtube/search.js +1 -1
- package/dist/clis/youtube/transcript.js +1 -1
- package/dist/clis/youtube/video.js +1 -1
- package/dist/clis/zhihu/download.js +1 -2
- package/dist/clis/zhihu/question.js +1 -1
- package/dist/clis/zhihu/search.yaml +4 -3
- package/dist/commanderAdapter.d.ts +21 -0
- package/dist/commanderAdapter.js +111 -0
- package/dist/{engine.d.ts → discovery.d.ts} +0 -6
- package/dist/{engine.js → discovery.js} +1 -98
- package/dist/download/index.d.ts +2 -6
- package/dist/download/index.js +19 -46
- package/dist/engine.test.d.ts +1 -1
- package/dist/engine.test.js +8 -7
- package/dist/execution.d.ts +22 -0
- package/dist/execution.js +129 -0
- package/dist/explore.js +121 -107
- package/dist/external-clis.yaml +48 -0
- package/dist/external.d.ts +7 -2
- package/dist/external.js +11 -14
- package/dist/main.js +1 -1
- package/dist/pipeline/steps/browser.js +8 -2
- package/dist/registry.d.ts +2 -0
- package/dist/registry.js +2 -0
- package/dist/runtime.d.ts +5 -0
- package/dist/runtime.js +8 -0
- package/dist/serialization.d.ts +34 -0
- package/dist/serialization.js +63 -0
- package/dist/types.d.ts +4 -1
- package/docs/.vitepress/config.mts +14 -3
- package/docs/adapters/browser/arxiv.md +27 -0
- package/docs/adapters/browser/barchart.md +32 -0
- package/docs/adapters/browser/bloomberg.md +70 -0
- package/docs/adapters/browser/chaoxing.md +39 -0
- package/docs/adapters/browser/grok.md +35 -0
- package/docs/adapters/browser/hf.md +42 -0
- package/docs/adapters/browser/jike.md +45 -0
- package/docs/adapters/browser/jimeng.md +39 -0
- package/docs/adapters/browser/linux-do.md +45 -0
- package/docs/adapters/browser/sinafinance.md +35 -0
- package/docs/adapters/browser/stackoverflow.md +35 -0
- package/docs/adapters/browser/steam.md +26 -0
- package/docs/adapters/browser/twitter.md +3 -0
- package/docs/adapters/browser/weread.md +48 -0
- package/docs/adapters/browser/wikipedia.md +30 -0
- package/docs/adapters/browser/xiaohongshu.md +5 -1
- package/docs/adapters/desktop/chatgpt.md +3 -3
- package/docs/adapters/index.md +13 -0
- package/docs/advanced/download.md +4 -4
- package/docs/developer/architecture.md +17 -4
- package/package.json +1 -1
- package/scripts/check-doc-coverage.sh +69 -0
- package/scripts/copy-yaml.cjs +7 -0
- package/src/browser/cdp.ts +6 -1
- package/src/browser/page.ts +7 -1
- package/src/build-manifest.ts +25 -19
- package/src/cli.ts +218 -139
- package/src/clis/apple-podcasts/commands.test.ts +95 -0
- package/src/clis/apple-podcasts/search.ts +2 -2
- package/src/clis/apple-podcasts/top.ts +12 -2
- package/src/clis/arxiv/search.ts +1 -1
- package/src/clis/bilibili/dynamic.ts +1 -1
- package/src/clis/bilibili/favorite.ts +1 -1
- package/src/clis/bilibili/feed.ts +1 -1
- package/src/clis/bilibili/following.ts +1 -1
- package/src/clis/bilibili/history.ts +1 -1
- package/src/clis/bilibili/me.ts +1 -1
- package/src/clis/bilibili/ranking.ts +1 -1
- package/src/clis/bilibili/search.ts +3 -3
- package/src/clis/bilibili/subtitle.ts +1 -1
- package/src/clis/bilibili/user-videos.ts +1 -1
- package/src/{bilibili.ts → clis/bilibili/utils.ts} +1 -1
- package/src/clis/bloomberg/businessweek.ts +18 -0
- package/src/clis/bloomberg/economics.ts +18 -0
- package/src/clis/bloomberg/feeds.ts +16 -0
- package/src/clis/bloomberg/industries.ts +18 -0
- package/src/clis/bloomberg/main.ts +18 -0
- package/src/clis/bloomberg/markets.ts +18 -0
- package/src/clis/bloomberg/news.ts +136 -0
- package/src/clis/bloomberg/opinions.ts +18 -0
- package/src/clis/bloomberg/politics.ts +18 -0
- package/src/clis/bloomberg/tech.ts +18 -0
- package/src/clis/bloomberg/utils.test.ts +135 -0
- package/src/clis/bloomberg/utils.ts +429 -0
- package/src/clis/boss/batchgreet.ts +2 -2
- package/src/clis/boss/chatlist.ts +2 -2
- package/src/clis/boss/detail.ts +2 -2
- package/src/clis/boss/greet.ts +4 -4
- package/src/clis/boss/search.ts +1 -1
- package/src/clis/boss/send.ts +1 -1
- package/src/clis/boss/stats.ts +2 -2
- package/src/clis/chaoxing/assignments.ts +1 -1
- package/src/clis/chaoxing/exams.ts +1 -1
- package/src/{chaoxing.test.ts → clis/chaoxing/utils.test.ts} +1 -1
- package/src/{chaoxing.ts → clis/chaoxing/utils.ts} +1 -3
- package/src/clis/chatgpt/README.zh-CN.md +3 -3
- package/src/clis/chatgpt/read.ts +1 -1
- package/src/clis/chatwise/export.ts +1 -1
- package/src/clis/chatwise/model.ts +2 -2
- package/src/clis/chatwise/screenshot.ts +1 -1
- package/src/clis/codex/export.ts +1 -1
- package/src/clis/codex/model.ts +2 -2
- package/src/clis/codex/screenshot.ts +1 -1
- package/src/clis/coupang/add-to-cart.ts +3 -4
- package/src/clis/coupang/search.ts +2 -4
- package/src/{coupang.test.ts → clis/coupang/utils.test.ts} +1 -1
- package/src/clis/ctrip/search.ts +1 -1
- package/src/clis/cursor/export.ts +1 -1
- package/src/clis/cursor/model.ts +2 -2
- package/src/clis/cursor/screenshot.ts +1 -1
- package/src/clis/jike/comment.ts +2 -3
- package/src/clis/jike/create.ts +1 -2
- package/src/clis/jike/feed.ts +0 -1
- package/src/clis/jike/like.ts +1 -2
- package/src/clis/jike/notifications.ts +0 -1
- package/src/clis/jike/post.yaml +1 -0
- package/src/clis/jike/repost.ts +1 -2
- package/src/clis/jike/search.ts +2 -3
- package/src/clis/jike/topic.yaml +1 -0
- package/src/clis/jike/user.yaml +1 -0
- package/src/clis/jimeng/history.yaml +0 -1
- package/src/clis/linkedin/search.ts +7 -7
- package/src/clis/linux-do/category.yaml +1 -0
- package/src/clis/linux-do/search.yaml +4 -3
- package/src/clis/linux-do/topic.yaml +1 -0
- package/src/clis/notion/export.ts +1 -1
- package/src/clis/reddit/comment.ts +3 -4
- package/src/clis/reddit/read.ts +4 -5
- package/src/clis/reddit/save.ts +2 -3
- package/src/clis/reddit/saved.ts +0 -1
- package/src/clis/reddit/search.yaml +1 -0
- package/src/clis/reddit/subscribe.ts +0 -1
- package/src/clis/reddit/upvote.ts +2 -3
- package/src/clis/reddit/upvoted.ts +0 -1
- package/src/clis/reddit/user-comments.yaml +1 -0
- package/src/clis/reddit/user-posts.yaml +1 -0
- package/src/clis/reddit/user.yaml +1 -0
- package/src/clis/reuters/search.ts +1 -1
- package/src/clis/smzdm/search.ts +2 -3
- package/src/clis/stackoverflow/search.yaml +1 -0
- package/src/clis/steam/top-sellers.yaml +29 -0
- package/src/clis/twitter/accept.ts +2 -2
- package/src/clis/twitter/article.ts +2 -2
- package/src/clis/twitter/block.ts +92 -0
- package/src/clis/twitter/delete.ts +1 -1
- package/src/clis/twitter/hide-reply.ts +70 -0
- package/src/clis/twitter/like.ts +1 -1
- package/src/clis/twitter/post.ts +1 -1
- package/src/clis/twitter/reply-dm.ts +1 -1
- package/src/clis/twitter/reply.ts +2 -2
- package/src/clis/twitter/search.ts +1 -1
- package/src/clis/twitter/thread.ts +2 -2
- package/src/clis/twitter/trending.ts +113 -0
- package/src/clis/twitter/unblock.ts +75 -0
- package/src/clis/v2ex/topic.yaml +1 -0
- package/src/clis/weibo/hot.ts +0 -1
- package/src/clis/weread/book.ts +1 -1
- package/src/clis/weread/highlights.ts +1 -1
- package/src/clis/weread/notes.ts +1 -1
- package/src/clis/weread/search.ts +1 -1
- package/src/clis/wikipedia/search.ts +1 -1
- package/src/clis/xiaohongshu/creator-note-detail.test.ts +82 -33
- package/src/clis/xiaohongshu/creator-note-detail.ts +89 -5
- package/src/clis/xiaohongshu/creator-notes.test.ts +39 -6
- package/src/clis/xiaohongshu/creator-notes.ts +44 -5
- package/src/clis/xiaohongshu/creator-profile.ts +0 -1
- package/src/clis/xiaohongshu/creator-stats.ts +0 -1
- package/src/clis/xiaohongshu/download.ts +2 -3
- package/src/clis/xiaohongshu/feed.yaml +0 -1
- package/src/clis/xiaohongshu/notifications.yaml +0 -1
- package/src/clis/xiaohongshu/search.ts +2 -2
- package/src/clis/xiaohongshu/user.ts +1 -2
- package/src/clis/yahoo-finance/quote.ts +0 -1
- package/src/clis/youtube/search.ts +1 -1
- package/src/clis/youtube/transcript.ts +1 -1
- package/src/clis/youtube/video.ts +1 -1
- package/src/clis/zhihu/download.ts +1 -2
- package/src/clis/zhihu/question.ts +1 -1
- package/src/clis/zhihu/search.yaml +4 -3
- package/src/commanderAdapter.ts +113 -0
- package/src/{engine.ts → discovery.ts} +1 -108
- package/src/download/index.ts +21 -54
- package/src/engine.test.ts +8 -7
- package/src/execution.ts +138 -0
- package/src/explore.ts +135 -109
- package/src/external-clis.yaml +9 -0
- package/src/external.ts +15 -12
- package/src/main.ts +1 -1
- package/src/pipeline/steps/browser.ts +7 -2
- package/src/registry.ts +5 -0
- package/src/runtime.ts +9 -0
- package/src/serialization.ts +79 -0
- package/src/types.ts +1 -1
- package/tests/e2e/browser-public.test.ts +25 -0
- package/tests/e2e/public-commands.test.ts +55 -1
- package/dist/clis/twitter/trending.yaml +0 -46
- package/docs/public/CNAME +0 -1
- package/src/clis/twitter/trending.yaml +0 -46
- /package/dist/{bilibili.js → clis/bilibili/utils.js} +0 -0
- /package/dist/{chaoxing.test.d.ts → clis/bloomberg/businessweek.d.ts} +0 -0
- /package/dist/{coupang.test.d.ts → clis/bloomberg/economics.d.ts} +0 -0
- /package/dist/{coupang.d.ts → clis/coupang/utils.d.ts} +0 -0
- /package/dist/{coupang.js → clis/coupang/utils.js} +0 -0
- /package/src/{coupang.ts → clis/coupang/utils.ts} +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
site: steam
|
|
2
|
+
name: top-sellers
|
|
3
|
+
description: Steam top selling games
|
|
4
|
+
domain: store.steampowered.com
|
|
5
|
+
strategy: public
|
|
6
|
+
browser: false
|
|
7
|
+
|
|
8
|
+
args:
|
|
9
|
+
limit:
|
|
10
|
+
type: int
|
|
11
|
+
default: 10
|
|
12
|
+
description: Number of games
|
|
13
|
+
|
|
14
|
+
pipeline:
|
|
15
|
+
- fetch:
|
|
16
|
+
url: https://store.steampowered.com/api/featuredcategories/
|
|
17
|
+
|
|
18
|
+
- select: top_sellers.items
|
|
19
|
+
|
|
20
|
+
- map:
|
|
21
|
+
rank: ${{ index + 1 }}
|
|
22
|
+
name: ${{ item.name }}
|
|
23
|
+
price: ${{ item.final_price }}
|
|
24
|
+
discount: ${{ item.discount_percent }}
|
|
25
|
+
url: https://store.steampowered.com/app/${{ item.id }}
|
|
26
|
+
|
|
27
|
+
- limit: ${{ args.limit }}
|
|
28
|
+
|
|
29
|
+
columns: [rank, name, price, discount, url]
|
|
@@ -8,14 +8,14 @@ cli({
|
|
|
8
8
|
browser: true,
|
|
9
9
|
timeoutSeconds: 600, // 10 min — batch operation iterating many conversations
|
|
10
10
|
args: [
|
|
11
|
-
{ name: '
|
|
11
|
+
{ name: 'query', type: 'string', required: true, positional: true, help: 'Keywords to match (comma-separated for OR, e.g. "群,微信")' },
|
|
12
12
|
{ name: 'max', type: 'int', required: false, default: 20, help: 'Maximum number of requests to accept (default: 20)' },
|
|
13
13
|
],
|
|
14
14
|
columns: ['index', 'status', 'user', 'message'],
|
|
15
15
|
func: async (page, kwargs) => {
|
|
16
16
|
if (!page)
|
|
17
17
|
throw new Error('Requires browser');
|
|
18
|
-
const keywords = kwargs.
|
|
18
|
+
const keywords = kwargs.query.split(',').map((k) => k.trim()).filter(Boolean);
|
|
19
19
|
const maxAccepts = kwargs.max ?? 20;
|
|
20
20
|
const results = [];
|
|
21
21
|
let acceptCount = 0;
|
|
@@ -7,12 +7,12 @@ cli({
|
|
|
7
7
|
strategy: Strategy.COOKIE,
|
|
8
8
|
browser: true,
|
|
9
9
|
args: [
|
|
10
|
-
{ name: '
|
|
10
|
+
{ name: 'tweet-id', type: 'string', positional: true, required: true, help: 'Tweet ID or URL containing the article' },
|
|
11
11
|
],
|
|
12
12
|
columns: ['title', 'author', 'content', 'url'],
|
|
13
13
|
func: async (page, kwargs) => {
|
|
14
14
|
// Extract tweet ID from URL if needed
|
|
15
|
-
let tweetId = kwargs
|
|
15
|
+
let tweetId = kwargs['tweet-id'];
|
|
16
16
|
const urlMatch = tweetId.match(/\/(?:status|article)\/(\d+)/);
|
|
17
17
|
if (urlMatch)
|
|
18
18
|
tweetId = urlMatch[1];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
cli({
|
|
3
|
+
site: 'twitter',
|
|
4
|
+
name: 'block',
|
|
5
|
+
description: 'Block a Twitter user',
|
|
6
|
+
domain: 'x.com',
|
|
7
|
+
strategy: Strategy.UI,
|
|
8
|
+
browser: true,
|
|
9
|
+
args: [
|
|
10
|
+
{ name: 'username', type: 'string', positional: true, required: true, help: 'Twitter screen name (without @)' },
|
|
11
|
+
],
|
|
12
|
+
columns: ['status', 'message'],
|
|
13
|
+
func: async (page, kwargs) => {
|
|
14
|
+
if (!page)
|
|
15
|
+
throw new Error('Requires browser');
|
|
16
|
+
const username = kwargs.username.replace(/^@/, '');
|
|
17
|
+
await page.goto(`https://x.com/${username}`);
|
|
18
|
+
await page.wait(5);
|
|
19
|
+
const result = await page.evaluate(`(async () => {
|
|
20
|
+
try {
|
|
21
|
+
let attempts = 0;
|
|
22
|
+
|
|
23
|
+
// Check if already blocked (profile shows "Blocked" / unblock button)
|
|
24
|
+
while (attempts < 20) {
|
|
25
|
+
const blockedIndicator = document.querySelector('[data-testid$="-unblock"]');
|
|
26
|
+
if (blockedIndicator) {
|
|
27
|
+
return { ok: true, message: 'Already blocking @${username}.' };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const moreBtn = document.querySelector('[data-testid="userActions"]');
|
|
31
|
+
if (moreBtn) break;
|
|
32
|
+
|
|
33
|
+
await new Promise(r => setTimeout(r, 500));
|
|
34
|
+
attempts++;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const moreBtn = document.querySelector('[data-testid="userActions"]');
|
|
38
|
+
if (!moreBtn) {
|
|
39
|
+
return { ok: false, message: 'Could not find user actions menu. Are you logged in?' };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Open the more actions menu
|
|
43
|
+
moreBtn.click();
|
|
44
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
45
|
+
|
|
46
|
+
// Find the Block menu item
|
|
47
|
+
const menuItems = document.querySelectorAll('[role="menuitem"]');
|
|
48
|
+
let blockItem = null;
|
|
49
|
+
for (const item of menuItems) {
|
|
50
|
+
if (item.textContent && item.textContent.includes('Block')) {
|
|
51
|
+
blockItem = item;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!blockItem) {
|
|
57
|
+
return { ok: false, message: 'Could not find Block option in menu.' };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
blockItem.click();
|
|
61
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
62
|
+
|
|
63
|
+
// Confirm the block in the dialog
|
|
64
|
+
const confirmBtn = document.querySelector('[data-testid="confirmationSheetConfirm"]');
|
|
65
|
+
if (confirmBtn) {
|
|
66
|
+
confirmBtn.click();
|
|
67
|
+
await new Promise(r => setTimeout(r, 1500));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Verify
|
|
71
|
+
const verify = document.querySelector('[data-testid$="-unblock"]');
|
|
72
|
+
if (verify) {
|
|
73
|
+
return { ok: true, message: 'Successfully blocked @${username}.' };
|
|
74
|
+
} else {
|
|
75
|
+
return { ok: false, message: 'Block action initiated but UI did not update.' };
|
|
76
|
+
}
|
|
77
|
+
} catch (e) {
|
|
78
|
+
return { ok: false, message: e.toString() };
|
|
79
|
+
}
|
|
80
|
+
})()`);
|
|
81
|
+
if (result.ok)
|
|
82
|
+
await page.wait(2);
|
|
83
|
+
return [{
|
|
84
|
+
status: result.ok ? 'success' : 'failed',
|
|
85
|
+
message: result.message
|
|
86
|
+
}];
|
|
87
|
+
}
|
|
88
|
+
});
|
|
@@ -7,7 +7,7 @@ cli({
|
|
|
7
7
|
strategy: Strategy.UI, // Utilizes internal DOM flows for interaction
|
|
8
8
|
browser: true,
|
|
9
9
|
args: [
|
|
10
|
-
{ name: 'url', type: 'string', required: true, help: 'The URL of the tweet to delete' },
|
|
10
|
+
{ name: 'url', type: 'string', required: true, positional: true, help: 'The URL of the tweet to delete' },
|
|
11
11
|
],
|
|
12
12
|
columns: ['status', 'message'],
|
|
13
13
|
func: async (page, kwargs) => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
cli({
|
|
3
|
+
site: 'twitter',
|
|
4
|
+
name: 'hide-reply',
|
|
5
|
+
description: 'Hide a reply on your tweet (useful for hiding bot/spam replies)',
|
|
6
|
+
domain: 'x.com',
|
|
7
|
+
strategy: Strategy.UI,
|
|
8
|
+
browser: true,
|
|
9
|
+
args: [
|
|
10
|
+
{ name: 'url', type: 'string', required: true, positional: true, help: 'The URL of the reply tweet to hide' },
|
|
11
|
+
],
|
|
12
|
+
columns: ['status', 'message'],
|
|
13
|
+
func: async (page, kwargs) => {
|
|
14
|
+
if (!page)
|
|
15
|
+
throw new Error('Requires browser');
|
|
16
|
+
await page.goto(kwargs.url);
|
|
17
|
+
await page.wait(5);
|
|
18
|
+
const result = await page.evaluate(`(async () => {
|
|
19
|
+
try {
|
|
20
|
+
let attempts = 0;
|
|
21
|
+
let moreMenu = null;
|
|
22
|
+
|
|
23
|
+
while (attempts < 20) {
|
|
24
|
+
moreMenu = document.querySelector('[aria-label="More"]');
|
|
25
|
+
if (moreMenu) break;
|
|
26
|
+
await new Promise(r => setTimeout(r, 500));
|
|
27
|
+
attempts++;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!moreMenu) {
|
|
31
|
+
return { ok: false, message: 'Could not find the "More" menu on this tweet. Are you logged in?' };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
moreMenu.click();
|
|
35
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
36
|
+
|
|
37
|
+
// Look for the "Hide reply" menu item
|
|
38
|
+
const items = document.querySelectorAll('[role="menuitem"]');
|
|
39
|
+
let hideItem = null;
|
|
40
|
+
for (const item of items) {
|
|
41
|
+
if (item.textContent && item.textContent.includes('Hide reply')) {
|
|
42
|
+
hideItem = item;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!hideItem) {
|
|
48
|
+
return { ok: false, message: 'Could not find "Hide reply" option. This may not be a reply on your tweet.' };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
hideItem.click();
|
|
52
|
+
await new Promise(r => setTimeout(r, 1500));
|
|
53
|
+
|
|
54
|
+
return { ok: true, message: 'Reply successfully hidden.' };
|
|
55
|
+
} catch (e) {
|
|
56
|
+
return { ok: false, message: e.toString() };
|
|
57
|
+
}
|
|
58
|
+
})()`);
|
|
59
|
+
if (result.ok)
|
|
60
|
+
await page.wait(2);
|
|
61
|
+
return [{
|
|
62
|
+
status: result.ok ? 'success' : 'failed',
|
|
63
|
+
message: result.message
|
|
64
|
+
}];
|
|
65
|
+
}
|
|
66
|
+
});
|
|
@@ -7,7 +7,7 @@ cli({
|
|
|
7
7
|
strategy: Strategy.UI, // Utilizes internal DOM flows for interaction
|
|
8
8
|
browser: true,
|
|
9
9
|
args: [
|
|
10
|
-
{ name: 'url', type: 'string', required: true, help: 'The URL of the tweet to like' },
|
|
10
|
+
{ name: 'url', type: 'string', required: true, positional: true, help: 'The URL of the tweet to like' },
|
|
11
11
|
],
|
|
12
12
|
columns: ['status', 'message'],
|
|
13
13
|
func: async (page, kwargs) => {
|
|
@@ -7,7 +7,7 @@ cli({
|
|
|
7
7
|
strategy: Strategy.UI,
|
|
8
8
|
browser: true,
|
|
9
9
|
args: [
|
|
10
|
-
{ name: 'text', type: 'string', required: true, help: 'The text content of the tweet' },
|
|
10
|
+
{ name: 'text', type: 'string', required: true, positional: true, help: 'The text content of the tweet' },
|
|
11
11
|
],
|
|
12
12
|
columns: ['status', 'message', 'text'],
|
|
13
13
|
func: async (page, kwargs) => {
|
|
@@ -8,7 +8,7 @@ cli({
|
|
|
8
8
|
browser: true,
|
|
9
9
|
timeoutSeconds: 600, // 10 min — batch operation
|
|
10
10
|
args: [
|
|
11
|
-
{ name: 'text', type: 'string', required: true, help: 'Message text to send (e.g. "我的微信 wxkabi")' },
|
|
11
|
+
{ name: 'text', type: 'string', required: true, positional: true, help: 'Message text to send (e.g. "我的微信 wxkabi")' },
|
|
12
12
|
{ name: 'max', type: 'int', required: false, default: 20, help: 'Maximum number of conversations to reply to (default: 20)' },
|
|
13
13
|
{ name: 'skip-replied', type: 'boolean', required: false, default: true, help: 'Skip conversations where you already sent the same text (default: true)' },
|
|
14
14
|
],
|
|
@@ -7,8 +7,8 @@ cli({
|
|
|
7
7
|
strategy: Strategy.UI, // Uses the UI directly to input and click post
|
|
8
8
|
browser: true,
|
|
9
9
|
args: [
|
|
10
|
-
{ name: 'url', type: 'string', required: true, help: 'The URL of the tweet to reply to' },
|
|
11
|
-
{ name: 'text', type: 'string', required: true, help: 'The text content of your reply' },
|
|
10
|
+
{ name: 'url', type: 'string', required: true, positional: true, help: 'The URL of the tweet to reply to' },
|
|
11
|
+
{ name: 'text', type: 'string', required: true, positional: true, help: 'The text content of your reply' },
|
|
12
12
|
],
|
|
13
13
|
columns: ['status', 'message', 'text'],
|
|
14
14
|
func: async (page, kwargs) => {
|
|
@@ -7,7 +7,7 @@ cli({
|
|
|
7
7
|
strategy: Strategy.INTERCEPT, // Use intercept strategy
|
|
8
8
|
browser: true,
|
|
9
9
|
args: [
|
|
10
|
-
{ name: 'query', type: 'string', required: true },
|
|
10
|
+
{ name: 'query', type: 'string', required: true, positional: true },
|
|
11
11
|
{ name: 'limit', type: 'int', default: 15 },
|
|
12
12
|
],
|
|
13
13
|
columns: ['id', 'author', 'text', 'likes', 'views', 'url'],
|
|
@@ -97,12 +97,12 @@ cli({
|
|
|
97
97
|
strategy: Strategy.COOKIE,
|
|
98
98
|
browser: true,
|
|
99
99
|
args: [
|
|
100
|
-
{ name: '
|
|
100
|
+
{ name: 'tweet-id', type: 'string', required: true },
|
|
101
101
|
{ name: 'limit', type: 'int', default: 50 },
|
|
102
102
|
],
|
|
103
103
|
columns: ['id', 'author', 'text', 'likes', 'retweets', 'url'],
|
|
104
104
|
func: async (page, kwargs) => {
|
|
105
|
-
let tweetId = kwargs
|
|
105
|
+
let tweetId = kwargs['tweet-id'];
|
|
106
106
|
const urlMatch = tweetId.match(/\/status\/(\d+)/);
|
|
107
107
|
if (urlMatch)
|
|
108
108
|
tweetId = urlMatch[1];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
// ── Twitter GraphQL constants ──────────────────────────────────────────
|
|
3
|
+
const BEARER_TOKEN = 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA';
|
|
4
|
+
// ── CLI definition ────────────────────────────────────────────────────
|
|
5
|
+
cli({
|
|
6
|
+
site: 'twitter',
|
|
7
|
+
name: 'trending',
|
|
8
|
+
description: 'Twitter/X trending topics',
|
|
9
|
+
domain: 'x.com',
|
|
10
|
+
strategy: Strategy.COOKIE,
|
|
11
|
+
browser: true,
|
|
12
|
+
args: [
|
|
13
|
+
{ name: 'limit', type: 'int', default: 20, help: 'Number of trends to show' },
|
|
14
|
+
],
|
|
15
|
+
columns: ['rank', 'topic', 'tweets', 'category'],
|
|
16
|
+
func: async (page, kwargs) => {
|
|
17
|
+
const limit = kwargs.limit || 20;
|
|
18
|
+
// Navigate to trending page
|
|
19
|
+
await page.goto('https://x.com/explore/tabs/trending');
|
|
20
|
+
await page.wait(3);
|
|
21
|
+
// Extract CSRF token to verify login
|
|
22
|
+
const ct0 = await page.evaluate(`(() => {
|
|
23
|
+
return document.cookie.split(';').map(c=>c.trim()).find(c=>c.startsWith('ct0='))?.split('=')[1] || null;
|
|
24
|
+
})()`);
|
|
25
|
+
if (!ct0)
|
|
26
|
+
throw new Error('Not logged into x.com (no ct0 cookie)');
|
|
27
|
+
// Try legacy guide.json API first (faster than DOM scraping)
|
|
28
|
+
let trends = [];
|
|
29
|
+
const apiData = await page.evaluate(`(async () => {
|
|
30
|
+
const ct0 = document.cookie.split(';').map(c=>c.trim()).find(c=>c.startsWith('ct0='))?.split('=')[1] || '';
|
|
31
|
+
const r = await fetch('/i/api/2/guide.json?include_page_configuration=true', {
|
|
32
|
+
credentials: 'include',
|
|
33
|
+
headers: {
|
|
34
|
+
'x-twitter-active-user': 'yes',
|
|
35
|
+
'x-csrf-token': ct0,
|
|
36
|
+
'authorization': 'Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA'
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
return r.ok ? await r.json() : null;
|
|
40
|
+
})()`);
|
|
41
|
+
if (apiData) {
|
|
42
|
+
const instructions = apiData?.timeline?.instructions || [];
|
|
43
|
+
const entries = instructions.flatMap((inst) => inst?.addEntries?.entries || inst?.entries || []);
|
|
44
|
+
const apiTrends = entries
|
|
45
|
+
.filter((e) => e.content?.timelineModule)
|
|
46
|
+
.flatMap((e) => e.content.timelineModule.items || [])
|
|
47
|
+
.map((t) => t?.item?.content?.trend)
|
|
48
|
+
.filter(Boolean);
|
|
49
|
+
trends = apiTrends.map((t, i) => ({
|
|
50
|
+
rank: i + 1,
|
|
51
|
+
topic: t.name,
|
|
52
|
+
tweets: t.tweetCount ? String(t.tweetCount) : 'N/A',
|
|
53
|
+
category: t.trendMetadata?.domainContext || '',
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
// Fallback: scrape from the loaded DOM
|
|
57
|
+
if (trends.length === 0) {
|
|
58
|
+
await page.wait(2);
|
|
59
|
+
const domTrends = await page.evaluate(`(() => {
|
|
60
|
+
const items = [];
|
|
61
|
+
const cells = document.querySelectorAll('[data-testid="trend"]');
|
|
62
|
+
cells.forEach((cell) => {
|
|
63
|
+
const text = cell.textContent || '';
|
|
64
|
+
if (text.includes('Promoted')) return;
|
|
65
|
+
const container = cell.querySelector(':scope > div');
|
|
66
|
+
if (!container) return;
|
|
67
|
+
const divs = container.children;
|
|
68
|
+
// Structure: divs[0] = rank + category, divs[1] = topic name, divs[2] = extra
|
|
69
|
+
const topicEl = divs.length >= 2 ? divs[1] : null;
|
|
70
|
+
const topic = topicEl ? topicEl.textContent.trim() : '';
|
|
71
|
+
const catEl = divs.length >= 1 ? divs[0] : null;
|
|
72
|
+
const catText = catEl ? catEl.textContent.trim() : '';
|
|
73
|
+
const category = catText.replace(/^\\d+\\s*/, '').replace(/^\\xB7\\s*/, '').trim();
|
|
74
|
+
const extraEl = divs.length >= 3 ? divs[2] : null;
|
|
75
|
+
const extra = extraEl ? extraEl.textContent.trim() : '';
|
|
76
|
+
if (topic) {
|
|
77
|
+
items.push({ rank: items.length + 1, topic, tweets: extra || 'N/A', category });
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return items;
|
|
81
|
+
})()`);
|
|
82
|
+
if (Array.isArray(domTrends) && domTrends.length > 0) {
|
|
83
|
+
trends = domTrends;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (trends.length === 0) {
|
|
87
|
+
throw new Error('No trending data found. API may have changed or login may be required.');
|
|
88
|
+
}
|
|
89
|
+
return trends.slice(0, limit);
|
|
90
|
+
},
|
|
91
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { cli, Strategy } from '../../registry.js';
|
|
2
|
+
cli({
|
|
3
|
+
site: 'twitter',
|
|
4
|
+
name: 'unblock',
|
|
5
|
+
description: 'Unblock a Twitter user',
|
|
6
|
+
domain: 'x.com',
|
|
7
|
+
strategy: Strategy.UI,
|
|
8
|
+
browser: true,
|
|
9
|
+
args: [
|
|
10
|
+
{ name: 'username', type: 'string', positional: true, required: true, help: 'Twitter screen name (without @)' },
|
|
11
|
+
],
|
|
12
|
+
columns: ['status', 'message'],
|
|
13
|
+
func: async (page, kwargs) => {
|
|
14
|
+
if (!page)
|
|
15
|
+
throw new Error('Requires browser');
|
|
16
|
+
const username = kwargs.username.replace(/^@/, '');
|
|
17
|
+
await page.goto(`https://x.com/${username}`);
|
|
18
|
+
await page.wait(5);
|
|
19
|
+
const result = await page.evaluate(`(async () => {
|
|
20
|
+
try {
|
|
21
|
+
let attempts = 0;
|
|
22
|
+
let unblockBtn = null;
|
|
23
|
+
|
|
24
|
+
while (attempts < 20) {
|
|
25
|
+
// Check if not blocked (follow button visible means not blocked)
|
|
26
|
+
const followBtn = document.querySelector('[data-testid$="-follow"]');
|
|
27
|
+
if (followBtn) {
|
|
28
|
+
return { ok: true, message: 'Not blocking @${username} (already unblocked).' };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
unblockBtn = document.querySelector('[data-testid$="-unblock"]');
|
|
32
|
+
if (unblockBtn) break;
|
|
33
|
+
|
|
34
|
+
await new Promise(r => setTimeout(r, 500));
|
|
35
|
+
attempts++;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!unblockBtn) {
|
|
39
|
+
return { ok: false, message: 'Could not find Unblock button. Are you logged in?' };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Click the unblock button — this opens a confirmation dialog
|
|
43
|
+
unblockBtn.click();
|
|
44
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
45
|
+
|
|
46
|
+
// Confirm the unblock in the dialog
|
|
47
|
+
const confirmBtn = document.querySelector('[data-testid="confirmationSheetConfirm"]');
|
|
48
|
+
if (confirmBtn) {
|
|
49
|
+
confirmBtn.click();
|
|
50
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Verify
|
|
54
|
+
const verify = document.querySelector('[data-testid$="-follow"]');
|
|
55
|
+
if (verify) {
|
|
56
|
+
return { ok: true, message: 'Successfully unblocked @${username}.' };
|
|
57
|
+
} else {
|
|
58
|
+
return { ok: false, message: 'Unblock action initiated but UI did not update.' };
|
|
59
|
+
}
|
|
60
|
+
} catch (e) {
|
|
61
|
+
return { ok: false, message: e.toString() };
|
|
62
|
+
}
|
|
63
|
+
})()`);
|
|
64
|
+
if (result.ok)
|
|
65
|
+
await page.wait(2);
|
|
66
|
+
return [{
|
|
67
|
+
status: result.ok ? 'success' : 'failed',
|
|
68
|
+
message: result.message
|
|
69
|
+
}];
|
|
70
|
+
}
|
|
71
|
+
});
|
package/dist/clis/weibo/hot.js
CHANGED
|
@@ -16,7 +16,6 @@ cli({
|
|
|
16
16
|
func: async (page, kwargs) => {
|
|
17
17
|
const count = Math.min(kwargs.limit || 30, 50);
|
|
18
18
|
await page.goto('https://weibo.com');
|
|
19
|
-
await page.wait(2);
|
|
20
19
|
const data = await page.evaluate(`
|
|
21
20
|
(async () => {
|
|
22
21
|
const resp = await fetch('/ajax/statuses/hot_band', {credentials: 'include'});
|
package/dist/clis/weread/book.js
CHANGED
|
@@ -7,7 +7,7 @@ cli({
|
|
|
7
7
|
domain: 'weread.qq.com',
|
|
8
8
|
strategy: Strategy.COOKIE,
|
|
9
9
|
args: [
|
|
10
|
-
{ name: '
|
|
10
|
+
{ name: 'book-id', positional: true, required: true, help: 'Book ID (numeric, from search or shelf results)' },
|
|
11
11
|
],
|
|
12
12
|
columns: ['title', 'author', 'publisher', 'intro', 'category', 'rating'],
|
|
13
13
|
func: async (page, args) => {
|
|
@@ -7,7 +7,7 @@ cli({
|
|
|
7
7
|
domain: 'weread.qq.com',
|
|
8
8
|
strategy: Strategy.COOKIE,
|
|
9
9
|
args: [
|
|
10
|
-
{ name: '
|
|
10
|
+
{ name: 'book-id', positional: true, required: true, help: 'Book ID (from shelf or search results)' },
|
|
11
11
|
{ name: 'limit', type: 'int', default: 20, help: 'Max results' },
|
|
12
12
|
],
|
|
13
13
|
columns: ['chapter', 'text', 'createTime'],
|
|
@@ -7,7 +7,7 @@ cli({
|
|
|
7
7
|
domain: 'weread.qq.com',
|
|
8
8
|
strategy: Strategy.COOKIE,
|
|
9
9
|
args: [
|
|
10
|
-
{ name: '
|
|
10
|
+
{ name: 'book-id', positional: true, required: true, help: 'Book ID (from shelf or search results)' },
|
|
11
11
|
{ name: 'limit', type: 'int', default: 20, help: 'Max results' },
|
|
12
12
|
],
|
|
13
13
|
columns: ['chapter', 'text', 'review', 'createTime'],
|
|
@@ -8,7 +8,7 @@ cli({
|
|
|
8
8
|
strategy: Strategy.PUBLIC,
|
|
9
9
|
browser: false,
|
|
10
10
|
args: [
|
|
11
|
-
{ name: '
|
|
11
|
+
{ name: 'query', positional: true, required: true, help: 'Search keyword' },
|
|
12
12
|
{ name: 'limit', type: 'int', default: 10, help: 'Max results' },
|
|
13
13
|
],
|
|
14
14
|
columns: ['rank', 'title', 'author', 'bookId'],
|
|
@@ -8,7 +8,7 @@ cli({
|
|
|
8
8
|
strategy: Strategy.PUBLIC,
|
|
9
9
|
browser: false,
|
|
10
10
|
args: [
|
|
11
|
-
{ name: '
|
|
11
|
+
{ name: 'query', positional: true, required: true, help: 'Search keyword' },
|
|
12
12
|
{ name: 'limit', type: 'int', default: 10, help: 'Max results' },
|
|
13
13
|
{ name: 'lang', default: 'en', help: 'Language code (e.g. en, zh, ja)' },
|
|
14
14
|
],
|
|
@@ -16,6 +16,20 @@ type CreatorNoteDetailRow = {
|
|
|
16
16
|
extra: string;
|
|
17
17
|
};
|
|
18
18
|
export type { CreatorNoteDetailRow };
|
|
19
|
+
type CreatorNoteDetailDomMetric = {
|
|
20
|
+
label: string;
|
|
21
|
+
value: string;
|
|
22
|
+
extra: string;
|
|
23
|
+
};
|
|
24
|
+
type CreatorNoteDetailDomSection = {
|
|
25
|
+
title: string;
|
|
26
|
+
metrics: CreatorNoteDetailDomMetric[];
|
|
27
|
+
};
|
|
28
|
+
type CreatorNoteDetailDomData = {
|
|
29
|
+
title: string;
|
|
30
|
+
infoText: string;
|
|
31
|
+
sections: CreatorNoteDetailDomSection[];
|
|
32
|
+
};
|
|
19
33
|
type AudienceSourceItem = {
|
|
20
34
|
title?: string;
|
|
21
35
|
value_with_double?: number;
|
|
@@ -64,6 +78,7 @@ type NoteDetailApiPayload = {
|
|
|
64
78
|
};
|
|
65
79
|
};
|
|
66
80
|
export declare function parseCreatorNoteDetailText(bodyText: string, noteId: string): CreatorNoteDetailRow[];
|
|
81
|
+
export declare function parseCreatorNoteDetailDomData(dom: CreatorNoteDetailDomData | null | undefined, noteId: string): CreatorNoteDetailRow[];
|
|
67
82
|
export declare function appendAudienceRows(rows: CreatorNoteDetailRow[], payload?: NoteDetailApiPayload): CreatorNoteDetailRow[];
|
|
68
83
|
export declare function appendTrendRows(rows: CreatorNoteDetailRow[], payload?: NoteDetailApiPayload): CreatorNoteDetailRow[];
|
|
69
84
|
export declare function fetchCreatorNoteDetailRows(page: IPage, noteId: string): Promise<CreatorNoteDetailRow[]>;
|