yuque-cli 0.1.0__tar.gz → 0.1.1__tar.gz
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.
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/.claude/settings.local.json +6 -1
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/CONTEXT.md +9 -9
- yuque_cli-0.1.1/PKG-INFO +137 -0
- yuque_cli-0.1.1/README.md +127 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/docs/adr/0001-use-internal-web-api-with-cookie-auth.md +2 -2
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/docs/internal-api.md +4 -4
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/mise.toml +4 -1
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/pyproject.toml +2 -2
- yuque_cli-0.1.1/src/yuque_cli/__init__.py +3 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/appdata.py +1 -1
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/cli.py +113 -35
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/client.py +22 -18
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/config.py +2 -2
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/output.py +33 -13
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/urls.py +15 -15
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/test/test_appdata.py +6 -6
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/test/test_cli.py +113 -22
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/test/test_client.py +10 -10
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/test/test_config.py +8 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/test/test_output.py +3 -3
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/test/test_urls.py +15 -15
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/uv.lock +1 -1
- yuque_cli-0.1.0/PKG-INFO +0 -190
- yuque_cli-0.1.0/README.md +0 -180
- yuque_cli-0.1.0/src/yuque_cli/__init__.py +0 -3
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/.gitignore +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/.python-version +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/.vscode/extensions.json +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/.vscode/settings.json +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/AGENTS.md +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/CLAUDE.md +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/docs/adr/0002-cookie-acquisition-cdp-with-manual-fallback.md +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/docs/adr/0003-doc-update-fetch-then-merge.md +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/main.py +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/__main__.py +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/auth.py +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/errors.py +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/inputs.py +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/src/yuque_cli/session.py +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/test/test_auth.py +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/test/test_inputs.py +0 -0
- {yuque_cli-0.1.0 → yuque_cli-0.1.1}/test/test_session.py +0 -0
|
@@ -10,7 +10,12 @@
|
|
|
10
10
|
"Bash(ps -p 46455 -o command=)",
|
|
11
11
|
"Bash(curl --noproxy '*' -sS -m 3 -i http://127.0.0.1:9222/)",
|
|
12
12
|
"Bash(curl --noproxy '*' -sS -m 3 http://127.0.0.1:9222/json)",
|
|
13
|
-
"Bash(curl --noproxy '*' -sS -m 3 http://127.0.0.1:9222/json/list)"
|
|
13
|
+
"Bash(curl --noproxy '*' -sS -m 3 http://127.0.0.1:9222/json/list)",
|
|
14
|
+
"Bash(python *)",
|
|
15
|
+
"mcp__chrome-devtools__take_snapshot",
|
|
16
|
+
"mcp__chrome-devtools__navigate_page",
|
|
17
|
+
"mcp__chrome-devtools__list_pages",
|
|
18
|
+
"WebSearch"
|
|
14
19
|
]
|
|
15
20
|
}
|
|
16
21
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# 语雀 CLI (yuque-cli)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
针对语雀的通用命令行客户端:以浏览器 cookie 认证、驱动语雀内部 web 接口,提供文档与评论的增删改查。默认连接 `www.yuque.com`,自建实例用环境变量 `YUQUE_HOST` 指定。
|
|
4
4
|
|
|
5
5
|
## Language
|
|
6
6
|
|
|
7
|
-
**知识库 (
|
|
8
|
-
语雀中承载一组文档的容器,对应网页端的「知识库」。内部 API 中称 `
|
|
7
|
+
**知识库 (Repo)**:
|
|
8
|
+
语雀中承载一组文档的容器,对应网页端的「知识库」。内部 API 中称 `repo`;官方开放 API 中称 `repo`。
|
|
9
9
|
_Avoid_: Repo, 仓库, 文档库
|
|
10
10
|
|
|
11
11
|
**文档 (Doc)**:
|
|
@@ -16,14 +16,14 @@ _Avoid_: 文章, Article, Page
|
|
|
16
16
|
挂在某一篇文档上的评论。
|
|
17
17
|
_Avoid_: 回复, Reply
|
|
18
18
|
|
|
19
|
-
**
|
|
20
|
-
用户或团队的唯一标识,位于 URL 第一段(`<host>/{
|
|
21
|
-
_Avoid_: username, 账号, owner
|
|
19
|
+
**space**:
|
|
20
|
+
用户或团队的唯一标识,位于 URL 第一段(`<host>/{space}/...`)。可指个人用户,也可指团队,二者在 URL 中形态一致。
|
|
21
|
+
_Avoid_: login, username, 账号, owner
|
|
22
22
|
|
|
23
23
|
**namespace**:
|
|
24
|
-
定位一个知识库的路径,形如 `{
|
|
25
|
-
_Avoid_: 把单独的
|
|
24
|
+
定位一个知识库的路径,形如 `{space}/{repo}`(语雀官方术语),即知识库的浏览器地址(book URL)。用户可直接用此 URL 指定一个知识库;文档地址在其后再加 `/{slug}`(doc URL)。两种 URL 去掉 host 的路径形态与完整 URL 等价;数字 id 不属于用户语汇,仅内部解析时使用。
|
|
25
|
+
_Avoid_: 把单独的 space 误当作 namespace(URL 第一段只是 space,不是完整 namespace)
|
|
26
26
|
|
|
27
27
|
**slug**:
|
|
28
|
-
文档在其知识库内的可读标识,位于 URL 末段。一篇文档的完整地址即 `{
|
|
28
|
+
文档在其知识库内的可读标识,位于 URL 末段。一篇文档的完整地址即 `{space}/{repo}/{slug}`,也就是其浏览器 URL。
|
|
29
29
|
_Avoid_: 短链, 别名
|
yuque_cli-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yuque-cli
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: 针对语雀的命令行客户端:cookie 认证,驱动内部 web 接口,提供文档与评论的 CRUD
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: httpx>=0.27
|
|
7
|
+
Requires-Dist: typer>=0.12
|
|
8
|
+
Requires-Dist: websocket-client>=1.9.0
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# yuque-cli
|
|
12
|
+
|
|
13
|
+
语雀通用命令行客户端,以浏览器 cookie 认证,驱动语雀内部 web 接口,提供文档与评论的增删改查。
|
|
14
|
+
|
|
15
|
+
> 术语(知识库/文档/评论/space/namespace/slug)见 [CONTEXT.md](./CONTEXT.md);关键设计取舍见 [docs/adr](./docs/adr)。
|
|
16
|
+
|
|
17
|
+
## 安装
|
|
18
|
+
|
|
19
|
+
需要 Python ≥ 3.10 与 [uv](https://docs.astral.sh/uv/)。
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv sync # 安装依赖
|
|
23
|
+
uv run yuque --help # 项目内运行
|
|
24
|
+
uv tool install . # 全局安装
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 快速开始
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
yuque auth login # 登录(自动 CDP 抓取 cookie,失败回退手动粘贴)
|
|
31
|
+
yuque auth status # 查看当前身份
|
|
32
|
+
yuque repo list # 列出我的知识库
|
|
33
|
+
yuque doc list <space>/<repo> # 列出知识库下的文档
|
|
34
|
+
yuque doc get <space>/<repo>/<slug> # 取文档正文(Markdown)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
地址可用完整浏览器 URL 或去掉 host 的路径形态,二者等价。
|
|
38
|
+
|
|
39
|
+
## 认证
|
|
40
|
+
|
|
41
|
+
`yuque auth login` 默认从 Chrome 远程调试端口(9222)自动抓取 cookie。前提是 Chrome 以此端口启动:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
未检测到远程调试时,提示手动粘贴 cookie。也可 `yuque auth login --manual` 跳过 CDP。
|
|
48
|
+
|
|
49
|
+
会话保存在 `~/.config/yuque-cli/session.json`(权限 0600),`yuque auth logout` 清除。
|
|
50
|
+
|
|
51
|
+
## 全局选项
|
|
52
|
+
|
|
53
|
+
置于子命令之前:`yuque --json repo list`。
|
|
54
|
+
|
|
55
|
+
| 选项 | 说明 |
|
|
56
|
+
| --- | --- |
|
|
57
|
+
| `--json` | 输出原始 JSON |
|
|
58
|
+
| `-y`, `--yes` | 跳过确认 |
|
|
59
|
+
| `-v`, `--verbose` | 打印 HTTP 请求到 stderr |
|
|
60
|
+
| `-V`, `--version` | 显示版本 |
|
|
61
|
+
|
|
62
|
+
## 命令
|
|
63
|
+
|
|
64
|
+
### auth
|
|
65
|
+
|
|
66
|
+
| 命令 | 说明 |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| `auth login [--manual]` | 登录 |
|
|
69
|
+
| `auth status` | 显示当前身份 |
|
|
70
|
+
| `auth logout` | 清除会话 |
|
|
71
|
+
|
|
72
|
+
### repo
|
|
73
|
+
|
|
74
|
+
| 命令 | 说明 |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| `repo list` | 列出我的知识库 |
|
|
77
|
+
|
|
78
|
+
### doc
|
|
79
|
+
|
|
80
|
+
| 命令 | 说明 |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| `doc list <space>/<repo>` | 列出文档 |
|
|
83
|
+
| `doc get <space>/<repo>/<slug>` | 取正文(默认 Markdown,`--json` 出详情) |
|
|
84
|
+
| `doc create <space>/<repo> -t <标题> [选项]` | 创建文档 |
|
|
85
|
+
| `doc update <space>/<repo>/<slug> [选项]` | 更新文档(先取后合并,未给的字段保持原值) |
|
|
86
|
+
| `doc delete <space>/<repo>/<slug>` | 删除文档(软删,可回收站恢复) |
|
|
87
|
+
|
|
88
|
+
`doc create` 选项:`-t/--title`(必填)、`--slug`、`--public/--private`、`-b/--body`、`-F/--file`。
|
|
89
|
+
|
|
90
|
+
`doc update` 选项:`-t/--title`、`--public/--private`、`-b/--body`、`-F/--file`;至少给其一。
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
yuque doc create team/handbook -t "上手指南" --body "# 标题\n正文"
|
|
94
|
+
yuque doc create team/handbook -t "周报" -F report.md --private
|
|
95
|
+
yuque doc update team/handbook/getting-started -t "新标题"
|
|
96
|
+
yuque -y doc delete team/handbook/old-draft
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### comment
|
|
100
|
+
|
|
101
|
+
| 命令 | 说明 |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| `comment list <space>/<repo>/<slug>` | 列出评论 |
|
|
104
|
+
| `comment add <space>/<repo>/<slug> [-b/--body \| -F/--file]` | 添加评论 |
|
|
105
|
+
| `comment delete <comment_id>` | 删除评论 |
|
|
106
|
+
|
|
107
|
+
## 正文输入
|
|
108
|
+
|
|
109
|
+
`doc create` / `comment add` 正文来源(`--body` 与 `--file` 互斥):
|
|
110
|
+
|
|
111
|
+
1. `-b/--body` 内联字符串
|
|
112
|
+
2. `-F/--file` 从文件读(`-F -` 读 stdin)
|
|
113
|
+
3. 管道 stdin
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
echo "# 正文" | yuque doc create team/handbook -t "标题"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`doc update` 只有显式给 `-b`/`-F` 才会改正文,裸管道不生效。
|
|
120
|
+
|
|
121
|
+
## 环境变量
|
|
122
|
+
|
|
123
|
+
| 变量 | 作用 | 默认 |
|
|
124
|
+
| --- | --- | --- |
|
|
125
|
+
| `YUQUE_HOST` | 目标语雀 host | `www.yuque.com` |
|
|
126
|
+
| `YUQUE_CONFIG_DIR` | 配置目录 | `~/.config/yuque-cli` |
|
|
127
|
+
| `NO_COLOR` | 禁用彩色输出 | — |
|
|
128
|
+
|
|
129
|
+
## 开发
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
mise run deps # uv sync
|
|
133
|
+
mise run test # pytest
|
|
134
|
+
mise run lint # ruff check && ruff format
|
|
135
|
+
mise run check # pyright
|
|
136
|
+
mise run cli -- --help
|
|
137
|
+
```
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# yuque-cli
|
|
2
|
+
|
|
3
|
+
语雀通用命令行客户端,以浏览器 cookie 认证,驱动语雀内部 web 接口,提供文档与评论的增删改查。
|
|
4
|
+
|
|
5
|
+
> 术语(知识库/文档/评论/space/namespace/slug)见 [CONTEXT.md](./CONTEXT.md);关键设计取舍见 [docs/adr](./docs/adr)。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
需要 Python ≥ 3.10 与 [uv](https://docs.astral.sh/uv/)。
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
uv sync # 安装依赖
|
|
13
|
+
uv run yuque --help # 项目内运行
|
|
14
|
+
uv tool install . # 全局安装
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 快速开始
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
yuque auth login # 登录(自动 CDP 抓取 cookie,失败回退手动粘贴)
|
|
21
|
+
yuque auth status # 查看当前身份
|
|
22
|
+
yuque repo list # 列出我的知识库
|
|
23
|
+
yuque doc list <space>/<repo> # 列出知识库下的文档
|
|
24
|
+
yuque doc get <space>/<repo>/<slug> # 取文档正文(Markdown)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
地址可用完整浏览器 URL 或去掉 host 的路径形态,二者等价。
|
|
28
|
+
|
|
29
|
+
## 认证
|
|
30
|
+
|
|
31
|
+
`yuque auth login` 默认从 Chrome 远程调试端口(9222)自动抓取 cookie。前提是 Chrome 以此端口启动:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
未检测到远程调试时,提示手动粘贴 cookie。也可 `yuque auth login --manual` 跳过 CDP。
|
|
38
|
+
|
|
39
|
+
会话保存在 `~/.config/yuque-cli/session.json`(权限 0600),`yuque auth logout` 清除。
|
|
40
|
+
|
|
41
|
+
## 全局选项
|
|
42
|
+
|
|
43
|
+
置于子命令之前:`yuque --json repo list`。
|
|
44
|
+
|
|
45
|
+
| 选项 | 说明 |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `--json` | 输出原始 JSON |
|
|
48
|
+
| `-y`, `--yes` | 跳过确认 |
|
|
49
|
+
| `-v`, `--verbose` | 打印 HTTP 请求到 stderr |
|
|
50
|
+
| `-V`, `--version` | 显示版本 |
|
|
51
|
+
|
|
52
|
+
## 命令
|
|
53
|
+
|
|
54
|
+
### auth
|
|
55
|
+
|
|
56
|
+
| 命令 | 说明 |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| `auth login [--manual]` | 登录 |
|
|
59
|
+
| `auth status` | 显示当前身份 |
|
|
60
|
+
| `auth logout` | 清除会话 |
|
|
61
|
+
|
|
62
|
+
### repo
|
|
63
|
+
|
|
64
|
+
| 命令 | 说明 |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `repo list` | 列出我的知识库 |
|
|
67
|
+
|
|
68
|
+
### doc
|
|
69
|
+
|
|
70
|
+
| 命令 | 说明 |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `doc list <space>/<repo>` | 列出文档 |
|
|
73
|
+
| `doc get <space>/<repo>/<slug>` | 取正文(默认 Markdown,`--json` 出详情) |
|
|
74
|
+
| `doc create <space>/<repo> -t <标题> [选项]` | 创建文档 |
|
|
75
|
+
| `doc update <space>/<repo>/<slug> [选项]` | 更新文档(先取后合并,未给的字段保持原值) |
|
|
76
|
+
| `doc delete <space>/<repo>/<slug>` | 删除文档(软删,可回收站恢复) |
|
|
77
|
+
|
|
78
|
+
`doc create` 选项:`-t/--title`(必填)、`--slug`、`--public/--private`、`-b/--body`、`-F/--file`。
|
|
79
|
+
|
|
80
|
+
`doc update` 选项:`-t/--title`、`--public/--private`、`-b/--body`、`-F/--file`;至少给其一。
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
yuque doc create team/handbook -t "上手指南" --body "# 标题\n正文"
|
|
84
|
+
yuque doc create team/handbook -t "周报" -F report.md --private
|
|
85
|
+
yuque doc update team/handbook/getting-started -t "新标题"
|
|
86
|
+
yuque -y doc delete team/handbook/old-draft
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### comment
|
|
90
|
+
|
|
91
|
+
| 命令 | 说明 |
|
|
92
|
+
| --- | --- |
|
|
93
|
+
| `comment list <space>/<repo>/<slug>` | 列出评论 |
|
|
94
|
+
| `comment add <space>/<repo>/<slug> [-b/--body \| -F/--file]` | 添加评论 |
|
|
95
|
+
| `comment delete <comment_id>` | 删除评论 |
|
|
96
|
+
|
|
97
|
+
## 正文输入
|
|
98
|
+
|
|
99
|
+
`doc create` / `comment add` 正文来源(`--body` 与 `--file` 互斥):
|
|
100
|
+
|
|
101
|
+
1. `-b/--body` 内联字符串
|
|
102
|
+
2. `-F/--file` 从文件读(`-F -` 读 stdin)
|
|
103
|
+
3. 管道 stdin
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
echo "# 正文" | yuque doc create team/handbook -t "标题"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`doc update` 只有显式给 `-b`/`-F` 才会改正文,裸管道不生效。
|
|
110
|
+
|
|
111
|
+
## 环境变量
|
|
112
|
+
|
|
113
|
+
| 变量 | 作用 | 默认 |
|
|
114
|
+
| --- | --- | --- |
|
|
115
|
+
| `YUQUE_HOST` | 目标语雀 host | `www.yuque.com` |
|
|
116
|
+
| `YUQUE_CONFIG_DIR` | 配置目录 | `~/.config/yuque-cli` |
|
|
117
|
+
| `NO_COLOR` | 禁用彩色输出 | — |
|
|
118
|
+
|
|
119
|
+
## 开发
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
mise run deps # uv sync
|
|
123
|
+
mise run test # pytest
|
|
124
|
+
mise run lint # ruff check && ruff format
|
|
125
|
+
mise run check # pyright
|
|
126
|
+
mise run cli -- --help
|
|
127
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 使用语雀内部 web API + cookie 认证,而非官方 Open API v2
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
目标语雀实例禁用了个人 Token 生成,而官方 Open API v2 以 `X-Auth-Token` 认证,在禁 token 的实例上基本不可用;此外 v2 **完全没有评论接口**(Doc 对象上只有 `commentsCount` 计数)。因此本 CLI 直接驱动语雀网页端 SPA 所用的内部 `/api` 接口,以浏览器会话 cookie(`_yuque_session`)认证,写操作再带 CSRF(cookie 中的 `ctoken` ↔ 请求头 `x-csrf-token`)。
|
|
4
4
|
|
|
5
5
|
## 权衡
|
|
6
6
|
|
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
|
|
12
12
|
- 需要一层 CSRF 处理:读操作仅需 cookie,写操作(POST/PUT/DELETE)须额外带 `x-csrf-token`。
|
|
13
13
|
- cookie 失效(401)需可被识别并提示用户重新登录。
|
|
14
|
-
-
|
|
14
|
+
- 不同部署的 cookie 名可能不同,认证模块不应硬编码假定唯一的 cookie 键名。
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# 语雀内部 Web API 参考(实测)
|
|
2
2
|
|
|
3
3
|
> 本文档记录 `yuque-cli` 所依赖的语雀**内部** web 接口(非官方 Open API v2,原因见 [ADR 0001](./adr/0001-use-internal-web-api-with-cookie-auth.md))。
|
|
4
|
-
> 全部端点于 **2026-06-01**
|
|
4
|
+
> 全部端点于 **2026-06-01** 针对某语雀实例实测通过(discovery + 写链路验证 spike)。
|
|
5
5
|
> 内部接口未公开、无版本承诺,可能随语雀前端升级而变化。
|
|
6
6
|
|
|
7
7
|
## 认证与通用请求头
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
|
|
25
25
|
## URL → id 解析
|
|
26
26
|
|
|
27
|
-
写命令大多需要 `book_id`(部分需要数字 `doc_id`),但**没有干净的 REST 路径**可从 `
|
|
27
|
+
写命令大多需要 `book_id`(部分需要数字 `doc_id`),但**没有干净的 REST 路径**可从 `space/book_slug` 反查(`/api/repos/{ns}`、`/api/books/{id}` 均 404)。
|
|
28
28
|
|
|
29
|
-
通用解法:GET 页面 HTML `https://<host>/{
|
|
29
|
+
通用解法:GET 页面 HTML `https://<host>/{space}/{book}[/{slug}]`,提取其中
|
|
30
30
|
`window.appData = JSON.parse(decodeURIComponent("..."))`,解码后读:
|
|
31
31
|
|
|
32
32
|
- `appData.book.id` → book_id
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
| 能力 | 方法 路径 | 备注 |
|
|
52
52
|
|---|---|---|
|
|
53
53
|
| 列出文档 | `GET /api/books/{book_id}/docs` | 返回 `[{id, slug, title, book_id, ...}]` |
|
|
54
|
-
| 取正文(Markdown) | `GET /{
|
|
54
|
+
| 取正文(Markdown) | `GET /{space}/{book}/{slug}/markdown?plain=true&linebreak=false&anchor=false` | 干净 Markdown,**不需 book_id、非 /api** |
|
|
55
55
|
| 取详情(JSON/Lake) | `GET /api/docs/{slug或id}?book_id={book_id}` | **必须带 `book_id`**,否则 404 |
|
|
56
56
|
| 创建 | `POST /api/docs` body `{book_id, title, slug, format:"markdown", body, public}` | 返回 `data{id, slug, body, body_draft, format, status, ...}` |
|
|
57
57
|
| 更新 | `PUT /api/docs/{id}` body `{title, body, format:"markdown", public}` | |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "yuque-cli"
|
|
3
|
-
version = "0.1.
|
|
4
|
-
description = "
|
|
3
|
+
version = "0.1.1"
|
|
4
|
+
description = "针对语雀的命令行客户端:cookie 认证,驱动内部 web 接口,提供文档与评论的 CRUD"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
7
7
|
dependencies = [
|
|
@@ -25,7 +25,7 @@ def parse_app_data(html: str) -> dict:
|
|
|
25
25
|
raise AppDataError(f"window.appData 解码失败:{exc}") from exc
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def
|
|
28
|
+
def repo_id(app_data: dict) -> int:
|
|
29
29
|
try:
|
|
30
30
|
return int(app_data["book"]["id"])
|
|
31
31
|
except (KeyError, TypeError, ValueError) as exc:
|