@jackwener/opencli 1.5.4 → 1.5.6
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/README.md +27 -2
- package/README.zh-CN.md +36 -4
- package/dist/browser/daemon-client.d.ts +5 -1
- package/dist/browser/page.d.ts +6 -0
- package/dist/browser/page.js +15 -0
- package/dist/cli-manifest.json +1284 -67
- package/dist/cli.js +14 -14
- package/dist/clis/antigravity/serve.js +2 -2
- package/dist/clis/band/bands.d.ts +1 -0
- package/dist/clis/band/bands.js +72 -0
- package/dist/clis/band/mentions.d.ts +1 -0
- package/dist/clis/band/mentions.js +127 -0
- package/dist/clis/band/post.d.ts +1 -0
- package/dist/clis/band/post.js +175 -0
- package/dist/clis/band/posts.d.ts +1 -0
- package/dist/clis/band/posts.js +94 -0
- package/dist/clis/doubao/detail.d.ts +1 -0
- package/dist/clis/doubao/detail.js +33 -0
- package/dist/clis/doubao/detail.test.d.ts +1 -0
- package/dist/clis/doubao/detail.test.js +42 -0
- package/dist/clis/doubao/history.d.ts +1 -0
- package/dist/clis/doubao/history.js +28 -0
- package/dist/clis/doubao/history.test.d.ts +1 -0
- package/dist/clis/doubao/history.test.js +37 -0
- package/dist/clis/doubao/meeting-summary.d.ts +1 -0
- package/dist/clis/doubao/meeting-summary.js +39 -0
- package/dist/clis/doubao/meeting-transcript.d.ts +1 -0
- package/dist/clis/doubao/meeting-transcript.js +36 -0
- package/dist/clis/doubao/utils.d.ts +27 -0
- package/dist/clis/doubao/utils.js +317 -0
- package/dist/clis/doubao/utils.test.d.ts +1 -0
- package/dist/clis/doubao/utils.test.js +24 -0
- package/dist/clis/douyin/_shared/public-api.d.ts +33 -0
- package/dist/clis/douyin/_shared/public-api.js +29 -0
- package/dist/clis/douyin/user-videos.d.ts +5 -0
- package/dist/clis/douyin/user-videos.js +74 -0
- package/dist/clis/douyin/user-videos.test.d.ts +1 -0
- package/dist/clis/douyin/user-videos.test.js +108 -0
- package/dist/clis/ones/common.d.ts +32 -0
- package/dist/clis/ones/common.js +144 -0
- package/dist/clis/ones/enrich-tasks.d.ts +5 -0
- package/dist/clis/ones/enrich-tasks.js +37 -0
- package/dist/clis/ones/login.d.ts +1 -0
- package/dist/clis/ones/login.js +80 -0
- package/dist/clis/ones/logout.d.ts +1 -0
- package/dist/clis/ones/logout.js +17 -0
- package/dist/clis/ones/me.d.ts +1 -0
- package/dist/clis/ones/me.js +30 -0
- package/dist/clis/ones/my-tasks.d.ts +1 -0
- package/dist/clis/ones/my-tasks.js +120 -0
- package/dist/clis/ones/resolve-labels.d.ts +10 -0
- package/dist/clis/ones/resolve-labels.js +64 -0
- package/dist/clis/ones/task-helpers.d.ts +29 -0
- package/dist/clis/ones/task-helpers.js +212 -0
- package/dist/clis/ones/task-helpers.test.d.ts +1 -0
- package/dist/clis/ones/task-helpers.test.js +12 -0
- package/dist/clis/ones/task.d.ts +1 -0
- package/dist/clis/ones/task.js +66 -0
- package/dist/clis/ones/tasks.d.ts +1 -0
- package/dist/clis/ones/tasks.js +79 -0
- package/dist/clis/ones/token-info.d.ts +1 -0
- package/dist/clis/ones/token-info.js +42 -0
- package/dist/clis/ones/worklog.d.ts +11 -0
- package/dist/clis/ones/worklog.js +267 -0
- package/dist/clis/ones/worklog.test.d.ts +1 -0
- package/dist/clis/ones/worklog.test.js +20 -0
- package/dist/clis/sinafinance/rolling-news.d.ts +4 -0
- package/dist/clis/sinafinance/rolling-news.js +40 -0
- package/dist/clis/sinafinance/stock.d.ts +8 -0
- package/dist/clis/sinafinance/stock.js +117 -0
- package/dist/clis/spotify/spotify.d.ts +1 -0
- package/dist/clis/spotify/spotify.js +316 -0
- package/dist/clis/spotify/utils.d.ts +21 -0
- package/dist/clis/spotify/utils.js +66 -0
- package/dist/clis/spotify/utils.test.d.ts +1 -0
- package/dist/clis/spotify/utils.test.js +67 -0
- package/dist/clis/tieba/commands.test.d.ts +4 -0
- package/dist/clis/tieba/commands.test.js +79 -0
- package/dist/clis/tieba/hot.d.ts +1 -0
- package/dist/clis/tieba/hot.js +48 -0
- package/dist/clis/tieba/posts.d.ts +1 -0
- package/dist/clis/tieba/posts.js +85 -0
- package/dist/clis/tieba/read.d.ts +1 -0
- package/dist/clis/tieba/read.js +140 -0
- package/dist/clis/tieba/search.d.ts +1 -0
- package/dist/clis/tieba/search.js +108 -0
- package/dist/clis/tieba/utils.d.ts +101 -0
- package/dist/clis/tieba/utils.js +240 -0
- package/dist/clis/tieba/utils.test.d.ts +1 -0
- package/dist/clis/tieba/utils.test.js +290 -0
- package/dist/clis/weread/book.js +100 -13
- package/dist/clis/weread/commands.test.js +221 -0
- package/dist/clis/weread/private-api-regression.test.d.ts +1 -0
- package/dist/{weread-private-api-regression.test.js → clis/weread/private-api-regression.test.js} +92 -30
- package/dist/clis/weread/search-regression.test.d.ts +1 -0
- package/dist/clis/weread/search-regression.test.js +407 -0
- package/dist/clis/weread/search.js +143 -7
- package/dist/clis/weread/shelf.js +13 -95
- package/dist/clis/weread/utils.d.ts +46 -0
- package/dist/clis/weread/utils.js +214 -7
- package/dist/clis/weread/utils.test.js +71 -1
- package/dist/clis/xiaohongshu/publish.d.ts +1 -1
- package/dist/clis/xiaohongshu/publish.js +78 -31
- package/dist/clis/xiaohongshu/publish.test.js +66 -1
- package/dist/clis/xiaohongshu/user-helpers.d.ts +1 -0
- package/dist/clis/xiaohongshu/user-helpers.js +2 -0
- package/dist/clis/xiaohongshu/user-helpers.test.js +18 -0
- package/dist/clis/xueqiu/comments.d.ts +118 -0
- package/dist/clis/xueqiu/comments.js +354 -0
- package/dist/clis/xueqiu/comments.test.d.ts +1 -0
- package/dist/clis/xueqiu/comments.test.js +696 -0
- package/dist/clis/youtube/transcript.js +2 -4
- package/dist/clis/youtube/utils.d.ts +9 -0
- package/dist/clis/youtube/utils.js +67 -3
- package/dist/clis/youtube/utils.test.d.ts +1 -0
- package/dist/clis/youtube/utils.test.js +37 -0
- package/dist/clis/youtube/video.js +16 -15
- package/dist/clis/zsxq/dynamics.d.ts +1 -0
- package/dist/clis/zsxq/dynamics.js +47 -0
- package/dist/clis/zsxq/groups.d.ts +1 -0
- package/dist/clis/zsxq/groups.js +32 -0
- package/dist/clis/zsxq/search.d.ts +1 -0
- package/dist/clis/zsxq/search.js +43 -0
- package/dist/clis/zsxq/search.test.d.ts +1 -0
- package/dist/clis/zsxq/search.test.js +24 -0
- package/dist/clis/zsxq/topic.d.ts +1 -0
- package/dist/clis/zsxq/topic.js +47 -0
- package/dist/clis/zsxq/topic.test.d.ts +1 -0
- package/dist/clis/zsxq/topic.test.js +29 -0
- package/dist/clis/zsxq/topics.d.ts +1 -0
- package/dist/clis/zsxq/topics.js +25 -0
- package/dist/clis/zsxq/topics.test.d.ts +1 -0
- package/dist/clis/zsxq/topics.test.js +24 -0
- package/dist/clis/zsxq/utils.d.ts +97 -0
- package/dist/clis/zsxq/utils.js +230 -0
- package/dist/commanderAdapter.js +27 -4
- package/dist/commanderAdapter.test.js +39 -0
- package/dist/daemon.js +5 -4
- package/dist/errors.d.ts +29 -1
- package/dist/errors.js +49 -11
- package/dist/external-clis.yaml +17 -0
- package/dist/external.js +3 -3
- package/dist/main.js +2 -1
- package/dist/tui.js +2 -1
- package/dist/types.d.ts +5 -0
- package/docs/.vitepress/config.mts +3 -0
- package/docs/adapters/browser/band.md +63 -0
- package/docs/adapters/browser/ones.md +59 -0
- package/docs/adapters/browser/sinafinance.md +56 -6
- package/docs/adapters/browser/spotify.md +62 -0
- package/docs/adapters/browser/tieba.md +45 -0
- package/docs/adapters/browser/xueqiu.md +5 -0
- package/docs/adapters/browser/zsxq.md +49 -0
- package/docs/adapters/index.md +5 -2
- package/docs/adapters-doc/ones.md +32 -0
- package/extension/dist/background.js +1 -2
- package/extension/manifest.json +1 -1
- package/extension/package.json +1 -1
- package/extension/src/background.ts +17 -1
- package/extension/src/cdp.ts +42 -0
- package/extension/src/protocol.ts +5 -1
- package/package.json +1 -1
- package/scripts/postinstall.js +16 -0
- package/src/browser/daemon-client.ts +5 -1
- package/src/browser/page.ts +16 -0
- package/src/cli.ts +14 -14
- package/src/clis/antigravity/serve.ts +2 -2
- package/src/clis/band/bands.ts +76 -0
- package/src/clis/band/mentions.ts +134 -0
- package/src/clis/band/post.ts +187 -0
- package/src/clis/band/posts.ts +106 -0
- package/src/clis/doubao/detail.test.ts +53 -0
- package/src/clis/doubao/detail.ts +41 -0
- package/src/clis/doubao/history.test.ts +45 -0
- package/src/clis/doubao/history.ts +32 -0
- package/src/clis/doubao/meeting-summary.ts +53 -0
- package/src/clis/doubao/meeting-transcript.ts +48 -0
- package/src/clis/doubao/utils.test.ts +45 -0
- package/src/clis/doubao/utils.ts +371 -0
- package/src/clis/douyin/_shared/public-api.ts +84 -0
- package/src/clis/douyin/user-videos.test.ts +122 -0
- package/src/clis/douyin/user-videos.ts +101 -0
- package/src/clis/ones/common.ts +187 -0
- package/src/clis/ones/enrich-tasks.ts +47 -0
- package/src/clis/ones/login.ts +103 -0
- package/src/clis/ones/logout.ts +19 -0
- package/src/clis/ones/me.ts +34 -0
- package/src/clis/ones/my-tasks.ts +148 -0
- package/src/clis/ones/resolve-labels.ts +80 -0
- package/src/clis/ones/task-helpers.test.ts +14 -0
- package/src/clis/ones/task-helpers.ts +214 -0
- package/src/clis/ones/task.ts +79 -0
- package/src/clis/ones/tasks.ts +92 -0
- package/src/clis/ones/token-info.ts +46 -0
- package/src/clis/ones/worklog.test.ts +24 -0
- package/src/clis/ones/worklog.ts +306 -0
- package/src/clis/sinafinance/rolling-news.ts +42 -0
- package/src/clis/sinafinance/stock.ts +127 -0
- package/src/clis/spotify/spotify.ts +328 -0
- package/src/clis/spotify/utils.test.ts +87 -0
- package/src/clis/spotify/utils.ts +92 -0
- package/src/clis/tieba/commands.test.ts +86 -0
- package/src/clis/tieba/hot.ts +52 -0
- package/src/clis/tieba/posts.ts +108 -0
- package/src/clis/tieba/read.ts +158 -0
- package/src/clis/tieba/search.ts +119 -0
- package/src/clis/tieba/utils.test.ts +322 -0
- package/src/clis/tieba/utils.ts +348 -0
- package/src/clis/weread/book.ts +116 -13
- package/src/clis/weread/commands.test.ts +249 -0
- package/src/{weread-private-api-regression.test.ts → clis/weread/private-api-regression.test.ts} +108 -30
- package/src/clis/weread/search-regression.test.ts +440 -0
- package/src/clis/weread/search.ts +189 -9
- package/src/clis/weread/shelf.ts +20 -122
- package/src/clis/weread/utils.test.ts +81 -1
- package/src/clis/weread/utils.ts +264 -7
- package/src/clis/xiaohongshu/publish.test.ts +79 -1
- package/src/clis/xiaohongshu/publish.ts +84 -30
- package/src/clis/xiaohongshu/user-helpers.test.ts +23 -0
- package/src/clis/xiaohongshu/user-helpers.ts +4 -0
- package/src/clis/xueqiu/comments.test.ts +823 -0
- package/src/clis/xueqiu/comments.ts +461 -0
- package/src/clis/youtube/transcript.ts +2 -4
- package/src/clis/youtube/utils.test.ts +43 -0
- package/src/clis/youtube/utils.ts +69 -0
- package/src/clis/youtube/video.ts +16 -15
- package/src/clis/zsxq/dynamics.ts +60 -0
- package/src/clis/zsxq/groups.ts +41 -0
- package/src/clis/zsxq/search.test.ts +29 -0
- package/src/clis/zsxq/search.ts +54 -0
- package/src/clis/zsxq/topic.test.ts +34 -0
- package/src/clis/zsxq/topic.ts +68 -0
- package/src/clis/zsxq/topics.test.ts +29 -0
- package/src/clis/zsxq/topics.ts +36 -0
- package/src/clis/zsxq/utils.ts +351 -0
- package/src/commanderAdapter.test.ts +47 -0
- package/src/commanderAdapter.ts +26 -3
- package/src/daemon.ts +5 -4
- package/src/errors.ts +71 -10
- package/src/external-clis.yaml +17 -0
- package/src/external.ts +3 -3
- package/src/main.ts +2 -1
- package/src/tui.ts +2 -1
- package/src/types.ts +5 -0
- package/tests/e2e/band-auth.test.ts +20 -0
- package/tests/e2e/browser-auth-helpers.ts +18 -0
- package/tests/e2e/browser-auth.test.ts +35 -47
- package/tests/e2e/browser-public.test.ts +288 -0
- package/tests/e2e/management.test.ts +1 -1
- package/tests/e2e/plugin-management.test.ts +1 -1
- package/vitest.config.ts +1 -0
- package/SKILL.md +0 -879
- package/dist/weread-private-api-regression.test.d.ts +0 -1
- package/dist/weread-search-regression.test.d.ts +0 -1
- package/dist/weread-search-regression.test.js +0 -39
- package/src/weread-search-regression.test.ts +0 -44
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Band
|
|
2
|
+
|
|
3
|
+
**Mode**: 🔐 Browser · **Domain**: `www.band.us`
|
|
4
|
+
|
|
5
|
+
Read posts, comments, and notifications from [Band](https://www.band.us), a private community platform. Authentication uses your logged-in Chrome session (cookie-based).
|
|
6
|
+
|
|
7
|
+
## Commands
|
|
8
|
+
|
|
9
|
+
| Command | Description |
|
|
10
|
+
|---------|-------------|
|
|
11
|
+
| `opencli band bands` | List all Bands you belong to |
|
|
12
|
+
| `opencli band posts <band_no>` | List posts from a Band |
|
|
13
|
+
| `opencli band post <band_no> <post_no>` | Export full post content including nested comments |
|
|
14
|
+
| `opencli band mentions` | Show notifications where you were @mentioned |
|
|
15
|
+
|
|
16
|
+
## Usage Examples
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# List all your bands (get band_no from here)
|
|
20
|
+
opencli band bands
|
|
21
|
+
|
|
22
|
+
# List recent posts in a band
|
|
23
|
+
opencli band posts 12345678 --limit 10
|
|
24
|
+
|
|
25
|
+
# Export a post with comments
|
|
26
|
+
opencli band post 12345678 987654321
|
|
27
|
+
|
|
28
|
+
# Export post body only (skip comments)
|
|
29
|
+
opencli band post 12345678 987654321 --comments false
|
|
30
|
+
|
|
31
|
+
# Export post and download attached photos
|
|
32
|
+
opencli band post 12345678 987654321 --output ./band-photos
|
|
33
|
+
|
|
34
|
+
# Show recent @mention notifications
|
|
35
|
+
opencli band mentions --limit 20
|
|
36
|
+
|
|
37
|
+
# Show only unread mentions
|
|
38
|
+
opencli band mentions --unread true
|
|
39
|
+
|
|
40
|
+
# Show all notification types
|
|
41
|
+
opencli band mentions --filter all
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### `band mentions` filter options
|
|
45
|
+
|
|
46
|
+
| Filter | Description |
|
|
47
|
+
|--------|-------------|
|
|
48
|
+
| `mentioned` | Only notifications where you were @mentioned (default) |
|
|
49
|
+
| `all` | All notifications |
|
|
50
|
+
| `post` | Post-related notifications |
|
|
51
|
+
| `comment` | Comment-related notifications |
|
|
52
|
+
|
|
53
|
+
## Prerequisites
|
|
54
|
+
|
|
55
|
+
- Chrome running and **logged into** [band.us](https://www.band.us)
|
|
56
|
+
- [Browser Bridge extension](/guide/browser-bridge) installed
|
|
57
|
+
|
|
58
|
+
## Notes
|
|
59
|
+
|
|
60
|
+
- `band_no` is the numeric ID in the Band URL: `band.us/band/{band_no}/post`
|
|
61
|
+
- `band bands` lists all your bands with their `band_no` values
|
|
62
|
+
- `band post` output rows: `type=post` (the post itself), `type=comment` (top-level comment), `type=reply` (nested reply)
|
|
63
|
+
- Photo downloads use the full-resolution URL (thumbnail query params are stripped automatically)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# ONES
|
|
2
|
+
|
|
3
|
+
**Mode**: 🔐 Browser Bridge · **Domain**: `ones.cn` (self-hosted via `ONES_BASE_URL`)
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
| Command | Description |
|
|
8
|
+
|---------|-------------|
|
|
9
|
+
| `opencli ones login` | Login via Project API (`auth/login`) |
|
|
10
|
+
| `opencli ones me` | Current user profile (`users/me`) |
|
|
11
|
+
| `opencli ones token-info` | Token/user/team summary (`auth/token_info`) |
|
|
12
|
+
| `opencli ones tasks` | Team task list with status/project labels and hours |
|
|
13
|
+
| `opencli ones my-tasks` | My tasks (`assign`/`field004`/`owner`/`both`) |
|
|
14
|
+
| `opencli ones task` | Task detail by UUID (`team/:team/task/:id/info`) |
|
|
15
|
+
| `opencli ones worklog` | Log/backfill hours (GraphQL `addManhour` first, then REST fallbacks) |
|
|
16
|
+
| `opencli ones logout` | Logout (`auth/logout`) |
|
|
17
|
+
|
|
18
|
+
## Usage Examples
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Required: your ONES base URL
|
|
22
|
+
export ONES_BASE_URL=https://your-instance.example.com
|
|
23
|
+
|
|
24
|
+
# Optional if your deployment requires auth headers
|
|
25
|
+
# export ONES_USER_ID=...
|
|
26
|
+
# export ONES_AUTH_TOKEN=...
|
|
27
|
+
|
|
28
|
+
# Login/profile
|
|
29
|
+
opencli ones login --email you@company.com --password 'your-password'
|
|
30
|
+
opencli ones me
|
|
31
|
+
opencli ones token-info
|
|
32
|
+
|
|
33
|
+
# Task lists
|
|
34
|
+
opencli ones tasks <teamUUID> --limit 20
|
|
35
|
+
opencli ones tasks <teamUUID> --project <projectUUID> --assign <userUUID>
|
|
36
|
+
opencli ones my-tasks <teamUUID> --limit 100
|
|
37
|
+
opencli ones my-tasks <teamUUID> --mode both
|
|
38
|
+
|
|
39
|
+
# Task detail
|
|
40
|
+
opencli ones task <taskUUID> --team <teamUUID>
|
|
41
|
+
|
|
42
|
+
# Worklog: today / backfill
|
|
43
|
+
opencli ones worklog <taskUUID> 2 --team <teamUUID>
|
|
44
|
+
opencli ones worklog <taskUUID> 1.5 --team <teamUUID> --date 2026-03-23 --note "integration"
|
|
45
|
+
|
|
46
|
+
opencli ones logout
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Prerequisites
|
|
50
|
+
|
|
51
|
+
- Chrome running and logged into your ONES instance
|
|
52
|
+
- [Browser Bridge extension](/guide/browser-bridge) installed
|
|
53
|
+
- `ONES_BASE_URL` set to the same origin opened in Chrome
|
|
54
|
+
|
|
55
|
+
## Notes
|
|
56
|
+
|
|
57
|
+
- This adapter targets legacy ONES Project API deployments.
|
|
58
|
+
- `ONES_TEAM_UUID` can be set to omit `--team` in `tasks` / `my-tasks` / `task`.
|
|
59
|
+
- Hours display and input use `ONES_MANHOUR_SCALE` (default `100000`).
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
# 新浪财经 (Sina Finance)
|
|
2
2
|
|
|
3
|
-
**Mode**: 🌐 Public · **Domain**: `finance.sina.com.cn`
|
|
3
|
+
**Mode**: 🌐 Public / 🔐 Browser · **Domain**: `finance.sina.com.cn`
|
|
4
4
|
|
|
5
5
|
## Commands
|
|
6
6
|
|
|
7
|
-
| Command | Description |
|
|
8
|
-
|
|
9
|
-
| `opencli sinafinance news` | 新浪财经 7×24 小时实时快讯 |
|
|
7
|
+
| Command | Description | Mode |
|
|
8
|
+
|---------|-------------|------|
|
|
9
|
+
| `opencli sinafinance news` | 新浪财经 7×24 小时实时快讯 | 🌐 Public |
|
|
10
|
+
| `opencli sinafinance rolling-news` | 新浪财经滚动新闻 | 🔐 Browser |
|
|
11
|
+
| `opencli sinafinance stock` | 新浪财经行情(A股/港股/美股) | 🌐 Public |
|
|
10
12
|
|
|
11
13
|
## Usage Examples
|
|
12
14
|
|
|
15
|
+
### news - 7×24 实时快讯
|
|
16
|
+
|
|
13
17
|
```bash
|
|
14
18
|
# Latest financial news
|
|
15
19
|
opencli sinafinance news --limit 20
|
|
@@ -23,13 +27,59 @@ opencli sinafinance news --type 6 # 国际
|
|
|
23
27
|
opencli sinafinance news -f json
|
|
24
28
|
```
|
|
25
29
|
|
|
26
|
-
###
|
|
30
|
+
### rolling-news - 滚动新闻
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Rolling news feed
|
|
34
|
+
opencli sinafinance rolling-news
|
|
35
|
+
|
|
36
|
+
# JSON output
|
|
37
|
+
opencli sinafinance rolling-news -f json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### stock - 股票行情
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Search and view A-share stock
|
|
44
|
+
opencli sinafinance stock 贵州茅台 --market cn
|
|
45
|
+
|
|
46
|
+
# Search and view HK stock
|
|
47
|
+
opencli sinafinance stock 腾讯控股 --market hk
|
|
48
|
+
|
|
49
|
+
# Search and view US stock
|
|
50
|
+
opencli sinafinance stock aapl --market us
|
|
51
|
+
|
|
52
|
+
# Auto-detect market (searches cn, hk, us in order)
|
|
53
|
+
opencli sinafinance stock 招商证券
|
|
54
|
+
|
|
55
|
+
# JSON output
|
|
56
|
+
opencli sinafinance stock 贵州茅台 -f json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Options
|
|
60
|
+
|
|
61
|
+
### news
|
|
27
62
|
|
|
28
63
|
| Option | Description |
|
|
29
64
|
|--------|-------------|
|
|
30
65
|
| `--limit` | Max results, up to 50 (default: 20) |
|
|
31
66
|
| `--type` | News type: `0`=全部, `1`=A股, `2`=宏观, `3`=公司, `4`=数据, `5`=市场, `6`=国际, `7`=观点, `8`=央行, `9`=其它 |
|
|
32
67
|
|
|
68
|
+
### stock
|
|
69
|
+
|
|
70
|
+
| Option | Description |
|
|
71
|
+
|--------|-------------|
|
|
72
|
+
| `--market` | Market: `cn`, `hk`, `us`, `auto` (default: auto). When `auto`, searches in cn, hk, us order |
|
|
73
|
+
|
|
33
74
|
## Prerequisites
|
|
34
75
|
|
|
35
|
-
- No browser required — uses public API
|
|
76
|
+
- `news` & `stock`: No browser required — uses public API
|
|
77
|
+
- `rolling-news`: Chrome running and **logged into** `finance.sina.com.cn`
|
|
78
|
+
- For `rolling-news`: [Browser Bridge extension](/guide/browser-bridge) installed
|
|
79
|
+
|
|
80
|
+
## Notes
|
|
81
|
+
|
|
82
|
+
- `news` and `stock` use public APIs — no browser or login needed
|
|
83
|
+
- `stock` supports Chinese names, Chinese codes, and ticker symbols; auto-detects market
|
|
84
|
+
- Market priority for auto-detection: cn (A股) → hk (港股) → us (美股)
|
|
85
|
+
- US stock `High`/`Low` columns show 52-week range; A股/港股 show today's range
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Spotify
|
|
2
|
+
|
|
3
|
+
**Mode**: 🔑 OAuth API · **Domains**: `accounts.spotify.com`, `api.spotify.com`
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
| Command | Description |
|
|
8
|
+
|---------|-------------|
|
|
9
|
+
| `opencli spotify auth` | Authenticate with Spotify and store tokens locally |
|
|
10
|
+
| `opencli spotify status` | Show current playback status |
|
|
11
|
+
| `opencli spotify play [query]` | Resume playback or search-and-play a track |
|
|
12
|
+
| `opencli spotify pause` | Pause playback |
|
|
13
|
+
| `opencli spotify next` | Skip to the next track |
|
|
14
|
+
| `opencli spotify prev` | Skip to the previous track |
|
|
15
|
+
| `opencli spotify volume <0-100>` | Set playback volume |
|
|
16
|
+
| `opencli spotify search <query>` | Search Spotify tracks |
|
|
17
|
+
| `opencli spotify queue <query>` | Add a track to the playback queue |
|
|
18
|
+
| `opencli spotify shuffle <on|off>` | Toggle shuffle |
|
|
19
|
+
| `opencli spotify repeat <off|track|context>` | Set repeat mode |
|
|
20
|
+
|
|
21
|
+
## Usage Examples
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# First-time setup
|
|
25
|
+
opencli spotify auth
|
|
26
|
+
|
|
27
|
+
# What is playing right now?
|
|
28
|
+
opencli spotify status
|
|
29
|
+
|
|
30
|
+
# Resume playback
|
|
31
|
+
opencli spotify play
|
|
32
|
+
|
|
33
|
+
# Search and immediately play a track
|
|
34
|
+
opencli spotify play "Numb Linkin Park"
|
|
35
|
+
|
|
36
|
+
# Search without playing
|
|
37
|
+
opencli spotify search "Daft Punk" --limit 5 -f json
|
|
38
|
+
|
|
39
|
+
# Queue a track
|
|
40
|
+
opencli spotify queue "Get Lucky"
|
|
41
|
+
|
|
42
|
+
# Playback controls
|
|
43
|
+
opencli spotify pause
|
|
44
|
+
opencli spotify next
|
|
45
|
+
opencli spotify prev
|
|
46
|
+
opencli spotify volume 35
|
|
47
|
+
opencli spotify shuffle on
|
|
48
|
+
opencli spotify repeat track
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Setup
|
|
52
|
+
|
|
53
|
+
1. Create a Spotify app at <https://developer.spotify.com/dashboard>
|
|
54
|
+
2. Add `http://127.0.0.1:8888/callback` to the app's Redirect URIs
|
|
55
|
+
3. Fill in `SPOTIFY_CLIENT_ID` and `SPOTIFY_CLIENT_SECRET` in `~/.opencli/spotify.env`
|
|
56
|
+
4. Run `opencli spotify auth`
|
|
57
|
+
|
|
58
|
+
## Notes
|
|
59
|
+
|
|
60
|
+
- Browser Bridge is not required.
|
|
61
|
+
- Tokens are stored locally at `~/.opencli/spotify-tokens.json`.
|
|
62
|
+
- Playback commands work best when you already have an active Spotify device/session.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Tieba
|
|
2
|
+
|
|
3
|
+
**Mode**: 🔐 Browser · **Domain**: `tieba.baidu.com`
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
| Command | Description |
|
|
8
|
+
|---------|-------------|
|
|
9
|
+
| `opencli tieba hot` | Read Tieba trending topics |
|
|
10
|
+
| `opencli tieba posts <forum>` | List threads in one forum |
|
|
11
|
+
| `opencli tieba search <keyword>` | Search threads across Tieba |
|
|
12
|
+
| `opencli tieba read <thread-id>` | Read one thread page |
|
|
13
|
+
|
|
14
|
+
## Usage Examples
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Trending topics
|
|
18
|
+
opencli tieba hot --limit 5
|
|
19
|
+
|
|
20
|
+
# List forum threads
|
|
21
|
+
opencli tieba posts 李毅 --limit 10
|
|
22
|
+
|
|
23
|
+
# Search Tieba
|
|
24
|
+
opencli tieba search 编程 --limit 10
|
|
25
|
+
|
|
26
|
+
# Read one thread
|
|
27
|
+
opencli tieba read 10163164720 --limit 10
|
|
28
|
+
|
|
29
|
+
# Read page 2 of a thread
|
|
30
|
+
opencli tieba read 10163164720 --page 2 --limit 10
|
|
31
|
+
|
|
32
|
+
# JSON output
|
|
33
|
+
opencli tieba hot -f json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Notes
|
|
37
|
+
|
|
38
|
+
- `tieba search` currently supports only `--page 1`
|
|
39
|
+
- `tieba read --limit` counts reply rows; page 1 may also include the main post
|
|
40
|
+
|
|
41
|
+
## Prerequisites
|
|
42
|
+
|
|
43
|
+
- Chrome running and able to open `tieba.baidu.com`
|
|
44
|
+
- [Browser Bridge extension](/guide/browser-bridge) installed
|
|
45
|
+
- For `posts`, `search`, and `read`, a valid Tieba login session in Chrome is recommended
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
| `opencli xueqiu hot` | 获取雪球热门动态 |
|
|
13
13
|
| `opencli xueqiu search` | 搜索雪球股票(代码或名称) |
|
|
14
14
|
| `opencli xueqiu stock` | 获取雪球股票实时行情 |
|
|
15
|
+
| `opencli xueqiu comments` | 获取单只股票的讨论动态(按时间排序) |
|
|
15
16
|
| `opencli xueqiu watchlist` | 获取雪球自选股列表 |
|
|
16
17
|
| `opencli xueqiu fund-holdings` | 获取蛋卷基金持仓明细(可用 `--account` 按子账户过滤) |
|
|
17
18
|
| `opencli xueqiu fund-snapshot` | 获取蛋卷基金快照(总资产、子账户、持仓,推荐 `-f json`) |
|
|
@@ -28,6 +29,9 @@ opencli xueqiu search 茅台
|
|
|
28
29
|
# View one stock
|
|
29
30
|
opencli xueqiu stock SH600519
|
|
30
31
|
|
|
32
|
+
# View recent discussions for one stock
|
|
33
|
+
opencli xueqiu comments SH600519 --limit 5
|
|
34
|
+
|
|
31
35
|
# Upcoming earnings dates
|
|
32
36
|
opencli xueqiu earnings-date SH600519 --next
|
|
33
37
|
|
|
@@ -57,4 +61,5 @@ opencli xueqiu feed -v
|
|
|
57
61
|
|
|
58
62
|
- `fund-holdings` exposes both market value and share fields (`volume`, `usableRemainShare`)
|
|
59
63
|
- `fund-snapshot -f json` is the easiest way to persist a full account snapshot for later analysis or diffing
|
|
64
|
+
- `comments` returns stock-scoped discussion posts from the symbol page, not reply threads under one parent post
|
|
60
65
|
- If the commands return empty data, first confirm the logged-in browser can directly see the Danjuan asset page
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# 知识星球 (ZSXQ)
|
|
2
|
+
|
|
3
|
+
**Mode**: 🔐 Browser · **Domain**: `wx.zsxq.com`
|
|
4
|
+
|
|
5
|
+
Read groups, topics, search results, dynamics, and single-topic details from [知识星球](https://wx.zsxq.com) using your logged-in Chrome session.
|
|
6
|
+
|
|
7
|
+
## Commands
|
|
8
|
+
|
|
9
|
+
| Command | Description |
|
|
10
|
+
|---------|-------------|
|
|
11
|
+
| `opencli zsxq groups` | List the groups your account has joined |
|
|
12
|
+
| `opencli zsxq topics` | List topics in the active group |
|
|
13
|
+
| `opencli zsxq topic <id>` | Fetch a single topic with comments |
|
|
14
|
+
| `opencli zsxq search <keyword>` | Search topics inside a group |
|
|
15
|
+
| `opencli zsxq dynamics` | List recent dynamics across groups |
|
|
16
|
+
|
|
17
|
+
## Usage Examples
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# List your groups
|
|
21
|
+
opencli zsxq groups
|
|
22
|
+
|
|
23
|
+
# List topics from the active group in Chrome
|
|
24
|
+
opencli zsxq topics --limit 20
|
|
25
|
+
|
|
26
|
+
# Search inside the active group
|
|
27
|
+
opencli zsxq search "opencli"
|
|
28
|
+
|
|
29
|
+
# Search inside a specific group explicitly
|
|
30
|
+
opencli zsxq search "opencli" --group_id 123456789
|
|
31
|
+
|
|
32
|
+
# Export a single topic with comments
|
|
33
|
+
opencli zsxq topic 987654321 --comment_limit 20
|
|
34
|
+
|
|
35
|
+
# Read recent dynamics across all joined groups
|
|
36
|
+
opencli zsxq dynamics --limit 20
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Prerequisites
|
|
40
|
+
|
|
41
|
+
- Chrome running and **logged into** [wx.zsxq.com](https://wx.zsxq.com)
|
|
42
|
+
- [Browser Bridge extension](/guide/browser-bridge) installed
|
|
43
|
+
|
|
44
|
+
## Notes
|
|
45
|
+
|
|
46
|
+
- `zsxq topics` and `zsxq search` use the current active group context from Chrome by default
|
|
47
|
+
- If there is no active group context, pass `--group_id <id>` or open the target group in Chrome first
|
|
48
|
+
- `zsxq groups` returns `group_id`, which you can reuse with `--group_id`
|
|
49
|
+
- `zsxq topic` surfaces a missing topic as `NOT_FOUND` instead of a generic fetch error
|
package/docs/adapters/index.md
CHANGED
|
@@ -8,10 +8,11 @@ Run `opencli list` for the live registry.
|
|
|
8
8
|
|------|----------|------|
|
|
9
9
|
| **[twitter](/adapters/browser/twitter)** | `trending` `bookmarks` `profile` `search` `timeline` `thread` `following` `followers` `notifications` `post` `reply` `delete` `like` `article` `follow` `unfollow` `bookmark` `unbookmark` `download` `accept` `reply-dm` `block` `unblock` `hide-reply` | 🔐 Browser |
|
|
10
10
|
| **[reddit](/adapters/browser/reddit)** | `hot` `frontpage` `popular` `search` `subreddit` `read` `user` `user-posts` `user-comments` `upvote` `save` `comment` `subscribe` `saved` `upvoted` | 🔐 Browser |
|
|
11
|
+
| **[tieba](/adapters/browser/tieba)** | `hot` `posts` `search` `read` | 🔐 Browser |
|
|
11
12
|
| **[bilibili](/adapters/browser/bilibili)** | `hot` `search` `me` `favorite` `history` `feed` `subtitle` `dynamic` `ranking` `following` `user-videos` `download` | 🔐 Browser |
|
|
12
13
|
| **[zhihu](/adapters/browser/zhihu)** | `hot` `search` `question` `download` | 🔐 Browser |
|
|
13
14
|
| **[xiaohongshu](/adapters/browser/xiaohongshu)** | `search` `notifications` `feed` `user` `download` `publish` `creator-notes` `creator-note-detail` `creator-notes-summary` `creator-profile` `creator-stats` | 🔐 Browser |
|
|
14
|
-
| **[xueqiu](/adapters/browser/xueqiu)** | `feed` `hot-stock` `hot` `search` `stock` `watchlist` `earnings-date` `fund-holdings` `fund-snapshot` | 🔐 Browser |
|
|
15
|
+
| **[xueqiu](/adapters/browser/xueqiu)** | `feed` `hot-stock` `hot` `search` `stock` `comments` `watchlist` `earnings-date` `fund-holdings` `fund-snapshot` | 🔐 Browser |
|
|
15
16
|
| **[youtube](/adapters/browser/youtube)** | `search` `video` `transcript` | 🔐 Browser |
|
|
16
17
|
| **[v2ex](/adapters/browser/v2ex)** | `hot` `latest` `topic` `node` `user` `member` `replies` `nodes` `daily` `me` `notifications` | 🌐 / 🔐 |
|
|
17
18
|
| **[bloomberg](/adapters/browser/bloomberg)** | `main` `markets` `economics` `industries` `tech` `politics` `businessweek` `opinions` `feeds` `news` | 🌐 / 🔐 |
|
|
@@ -28,7 +29,7 @@ Run `opencli list` for the live registry.
|
|
|
28
29
|
| **[linux-do](/adapters/browser/linux-do)** | `feed` `categories` `tags` `search` `topic` `user-topics` `user-posts` | 🔐 Browser |
|
|
29
30
|
| **[chaoxing](/adapters/browser/chaoxing)** | `assignments` `exams` | 🔐 Browser |
|
|
30
31
|
| **[grok](/adapters/browser/grok)** | `ask` | 🔐 Browser |
|
|
31
|
-
| **[doubao](/adapters/browser/doubao)** | `status` `new` `send` `read` `ask` | 🔐 Browser |
|
|
32
|
+
| **[doubao](/adapters/browser/doubao)** | `status` `new` `send` `read` `ask` `history` `detail` `meeting-summary` `meeting-transcript` | 🔐 Browser |
|
|
32
33
|
| **[weread](/adapters/browser/weread)** | `shelf` `search` `book` `ranking` `notebooks` `highlights` `notes` | 🔐 Browser |
|
|
33
34
|
| **[douban](/adapters/browser/douban)** | `search` `top250` `subject` `photos` `download` `marks` `reviews` `movie-hot` `book-hot` | 🔐 Browser |
|
|
34
35
|
| **[facebook](/adapters/browser/facebook)** | `feed` `profile` `search` `friends` `groups` `events` `notifications` `memories` `add-friend` `join-group` | 🔐 Browser |
|
|
@@ -45,6 +46,7 @@ Run `opencli list` for the live registry.
|
|
|
45
46
|
| **[weixin](/adapters/browser/weixin)** | `download` | 🔐 Browser |
|
|
46
47
|
| **[36kr](/adapters/browser/36kr)** | `news` `hot` `search` `article` | 🌐 / 🔐 |
|
|
47
48
|
| **[producthunt](/adapters/browser/producthunt)** | `posts` `today` `hot` `browse` | 🌐 / 🔐 |
|
|
49
|
+
| **[ones](/adapters/browser/ones)** | `login` `me` `token-info` `tasks` `my-tasks` `task` `worklog` `logout` | 🔐 Browser Bridge + `ONES_BASE_URL` |
|
|
48
50
|
|
|
49
51
|
## Public API Adapters
|
|
50
52
|
|
|
@@ -62,6 +64,7 @@ Run `opencli list` for the live registry.
|
|
|
62
64
|
| **[barchart](/adapters/browser/barchart)** | `quote` `options` `greeks` `flow` | 🌐 Public |
|
|
63
65
|
| **[hf](/adapters/browser/hf)** | `top` | 🌐 Public |
|
|
64
66
|
| **[sinafinance](/adapters/browser/sinafinance)** | `news` | 🌐 Public |
|
|
67
|
+
| **[spotify](/adapters/browser/spotify)** | `auth` `status` `play` `pause` `next` `prev` `volume` `search` `queue` `shuffle` `repeat` | 🔑 OAuth API |
|
|
65
68
|
| **[stackoverflow](/adapters/browser/stackoverflow)** | `hot` `search` `bounties` `unanswered` | 🌐 Public |
|
|
66
69
|
| **[wikipedia](/adapters/browser/wikipedia)** | `search` `summary` `random` `trending` | 🌐 Public |
|
|
67
70
|
| **[lobsters](/adapters/browser/lobsters)** | `hot` `newest` `active` `tag` | 🌐 Public |
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# ONES 项目管理平台(OpenCLI)
|
|
2
|
+
|
|
3
|
+
基于官方 [ONES Project API](https://developer.ones.cn/zh-CN/docs/api/readme/),经 **Chrome + Browser Bridge** 在页面里 `fetch`(`credentials: 'include'`)。
|
|
4
|
+
|
|
5
|
+
## 环境变量
|
|
6
|
+
|
|
7
|
+
| 变量 | 必填 | 说明 |
|
|
8
|
+
|------|------|------|
|
|
9
|
+
| `ONES_BASE_URL` | 是 | 与 Chrome 中访问的 ONES 根 URL 一致 |
|
|
10
|
+
| `ONES_USER_ID` / `ONES_AUTH_TOKEN` | 视部署 | 若接口强制要文档中的 Header,再设置(可先只依赖浏览器登录) |
|
|
11
|
+
| `ONES_EMAIL` / `ONES_PHONE` / `ONES_PASSWORD` | 否 | 供 `ones login` 脚本化 |
|
|
12
|
+
|
|
13
|
+
## 命令
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
export ONES_BASE_URL=https://your-host
|
|
17
|
+
# 安装扩展,Chrome 已登录 ONES
|
|
18
|
+
|
|
19
|
+
opencli ones me
|
|
20
|
+
opencli ones token-info # teams column includes name(uuid), useful for tasks
|
|
21
|
+
opencli ones tasks <teamUUID> --limit 20 --project <optional>
|
|
22
|
+
opencli ones my-tasks <teamUUID> --limit 100 # default assignee=self
|
|
23
|
+
opencli ones my-tasks <teamUUID> --mode field004 # deployments using field004 as assignee
|
|
24
|
+
opencli ones my-tasks <teamUUID> --mode both # assignee OR creator
|
|
25
|
+
opencli ones task <taskUUID> --team <teamUUID> # single task (URL .../task/<uuid>)
|
|
26
|
+
opencli ones worklog <taskUUID> 2 --team <teamUUID> # log hours for today
|
|
27
|
+
opencli ones worklog <taskUUID> 1 --team <teamUUID> --date 2026-03-01 # backfill
|
|
28
|
+
opencli ones login --email you@corp.com --password '***' # optional; stderr prints header export hints
|
|
29
|
+
opencli ones logout
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
更完整的说明见 [docs/adapters/browser/ones.md](../adapters/browser/ones.md)。
|
package/extension/manifest.json
CHANGED
package/extension/package.json
CHANGED
|
@@ -160,13 +160,14 @@ async function getAutomationWindow(workspace: string): Promise<number> {
|
|
|
160
160
|
|
|
161
161
|
// Create a new window with a data: URI that New Tab Override extensions cannot intercept.
|
|
162
162
|
// Using about:blank would be hijacked by extensions like "New Tab Override".
|
|
163
|
+
// Note: Do NOT set `state` parameter here. Chrome 146+ rejects 'normal' as an invalid
|
|
164
|
+
// state value for windows.create(). The window defaults to 'normal' state anyway.
|
|
163
165
|
const win = await chrome.windows.create({
|
|
164
166
|
url: BLANK_PAGE,
|
|
165
167
|
focused: false,
|
|
166
168
|
width: 1280,
|
|
167
169
|
height: 900,
|
|
168
170
|
type: 'normal',
|
|
169
|
-
state: 'normal',
|
|
170
171
|
});
|
|
171
172
|
const session: AutomationSession = {
|
|
172
173
|
windowId: win.id!,
|
|
@@ -251,6 +252,8 @@ async function handleCommand(cmd: Command): Promise<Result> {
|
|
|
251
252
|
return await handleCloseWindow(cmd, workspace);
|
|
252
253
|
case 'sessions':
|
|
253
254
|
return await handleSessions(cmd);
|
|
255
|
+
case 'set-file-input':
|
|
256
|
+
return await handleSetFileInput(cmd, workspace);
|
|
254
257
|
default:
|
|
255
258
|
return { id: cmd.id, ok: false, error: `Unknown action: ${cmd.action}` };
|
|
256
259
|
}
|
|
@@ -578,6 +581,19 @@ async function handleCloseWindow(cmd: Command, workspace: string): Promise<Resul
|
|
|
578
581
|
return { id: cmd.id, ok: true, data: { closed: true } };
|
|
579
582
|
}
|
|
580
583
|
|
|
584
|
+
async function handleSetFileInput(cmd: Command, workspace: string): Promise<Result> {
|
|
585
|
+
if (!cmd.files || !Array.isArray(cmd.files) || cmd.files.length === 0) {
|
|
586
|
+
return { id: cmd.id, ok: false, error: 'Missing or empty files array' };
|
|
587
|
+
}
|
|
588
|
+
const tabId = await resolveTabId(cmd.tabId, workspace);
|
|
589
|
+
try {
|
|
590
|
+
await executor.setFileInputFiles(tabId, cmd.files, cmd.selector);
|
|
591
|
+
return { id: cmd.id, ok: true, data: { count: cmd.files.length } };
|
|
592
|
+
} catch (err) {
|
|
593
|
+
return { id: cmd.id, ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
581
597
|
async function handleSessions(cmd: Command): Promise<Result> {
|
|
582
598
|
const now = Date.now();
|
|
583
599
|
const data = await Promise.all([...automationSessions.entries()].map(async ([workspace, session]) => ({
|
package/extension/src/cdp.ts
CHANGED
|
@@ -147,6 +147,48 @@ export async function screenshot(
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Set local file paths on a file input element via CDP DOM.setFileInputFiles.
|
|
152
|
+
* This bypasses the need to send large base64 payloads through the message channel —
|
|
153
|
+
* Chrome reads the files directly from the local filesystem.
|
|
154
|
+
*
|
|
155
|
+
* @param tabId - Target tab ID
|
|
156
|
+
* @param files - Array of absolute local file paths
|
|
157
|
+
* @param selector - CSS selector to find the file input (optional, defaults to first file input)
|
|
158
|
+
*/
|
|
159
|
+
export async function setFileInputFiles(
|
|
160
|
+
tabId: number,
|
|
161
|
+
files: string[],
|
|
162
|
+
selector?: string,
|
|
163
|
+
): Promise<void> {
|
|
164
|
+
await ensureAttached(tabId);
|
|
165
|
+
|
|
166
|
+
// Enable DOM domain (required for DOM.querySelector and DOM.setFileInputFiles)
|
|
167
|
+
await chrome.debugger.sendCommand({ tabId }, 'DOM.enable');
|
|
168
|
+
|
|
169
|
+
// Get the document root
|
|
170
|
+
const doc = await chrome.debugger.sendCommand({ tabId }, 'DOM.getDocument') as {
|
|
171
|
+
root: { nodeId: number };
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// Find the file input element
|
|
175
|
+
const query = selector || 'input[type="file"]';
|
|
176
|
+
const result = await chrome.debugger.sendCommand({ tabId }, 'DOM.querySelector', {
|
|
177
|
+
nodeId: doc.root.nodeId,
|
|
178
|
+
selector: query,
|
|
179
|
+
}) as { nodeId: number };
|
|
180
|
+
|
|
181
|
+
if (!result.nodeId) {
|
|
182
|
+
throw new Error(`No element found matching selector: ${query}`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Set files directly via CDP — Chrome reads from local filesystem
|
|
186
|
+
await chrome.debugger.sendCommand({ tabId }, 'DOM.setFileInputFiles', {
|
|
187
|
+
files,
|
|
188
|
+
nodeId: result.nodeId,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
150
192
|
export async function detach(tabId: number): Promise<void> {
|
|
151
193
|
if (!attached.has(tabId)) return;
|
|
152
194
|
attached.delete(tabId);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Everything else is just JS code sent via 'exec'.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
export type Action = 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window' | 'sessions';
|
|
8
|
+
export type Action = 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window' | 'sessions' | 'set-file-input';
|
|
9
9
|
|
|
10
10
|
export interface Command {
|
|
11
11
|
/** Unique request ID */
|
|
@@ -32,6 +32,10 @@ export interface Command {
|
|
|
32
32
|
quality?: number;
|
|
33
33
|
/** Whether to capture full page (not just viewport) */
|
|
34
34
|
fullPage?: boolean;
|
|
35
|
+
/** Local file paths for set-file-input action */
|
|
36
|
+
files?: string[];
|
|
37
|
+
/** CSS selector for file input element (set-file-input action) */
|
|
38
|
+
selector?: string;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
export interface Result {
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -196,6 +196,22 @@ function main() {
|
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
// ── Spotify credentials template ────────────────────────────────────
|
|
200
|
+
const opencliDir = join(home, '.opencli');
|
|
201
|
+
const spotifyEnvFile = join(opencliDir, 'spotify.env');
|
|
202
|
+
ensureDir(opencliDir);
|
|
203
|
+
if (!existsSync(spotifyEnvFile)) {
|
|
204
|
+
writeFileSync(spotifyEnvFile,
|
|
205
|
+
`# Spotify credentials — get them at https://developer.spotify.com/dashboard\n` +
|
|
206
|
+
`# Add http://127.0.0.1:8888/callback as a Redirect URI in your Spotify app\n` +
|
|
207
|
+
`SPOTIFY_CLIENT_ID=your_spotify_client_id_here\n` +
|
|
208
|
+
`SPOTIFY_CLIENT_SECRET=your_spotify_client_secret_here\n`,
|
|
209
|
+
'utf8'
|
|
210
|
+
);
|
|
211
|
+
console.log(`✓ Spotify credentials template created at ${spotifyEnvFile}`);
|
|
212
|
+
console.log(` Edit the file and add your Client ID and Secret, then run: opencli spotify auth`);
|
|
213
|
+
}
|
|
214
|
+
|
|
199
215
|
// ── Browser Bridge setup hint ───────────────────────────────────────
|
|
200
216
|
console.log('');
|
|
201
217
|
console.log(' \x1b[1mNext step — Browser Bridge setup\x1b[0m');
|
|
@@ -19,7 +19,7 @@ function generateId(): string {
|
|
|
19
19
|
|
|
20
20
|
export interface DaemonCommand {
|
|
21
21
|
id: string;
|
|
22
|
-
action: 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window' | 'sessions';
|
|
22
|
+
action: 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window' | 'sessions' | 'set-file-input';
|
|
23
23
|
tabId?: number;
|
|
24
24
|
code?: string;
|
|
25
25
|
workspace?: string;
|
|
@@ -30,6 +30,10 @@ export interface DaemonCommand {
|
|
|
30
30
|
format?: 'png' | 'jpeg';
|
|
31
31
|
quality?: number;
|
|
32
32
|
fullPage?: boolean;
|
|
33
|
+
/** Local file paths for set-file-input action */
|
|
34
|
+
files?: string[];
|
|
35
|
+
/** CSS selector for file input element (set-file-input action) */
|
|
36
|
+
selector?: string;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export interface DaemonResult {
|