aiconductor-cli 1.2.1 → 1.2.2
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/CLAUDE.md +76 -0
- package/README.md +266 -108
- package/package.json +4 -3
- package/src/api.js +42 -26
- package/src/commands/douyin.js +109 -151
- package/src/commands/html_publish.js +54 -91
- package/src/commands/md_publish.js +87 -118
- package/src/commands/web_search.js +84 -120
- package/src/lib/cli-utils.js +80 -0
- package/AGENTS.md +0 -79
- package/AIC /346/212/226/351/237/263/347/263/273/345/210/227API/346/216/245/345/217/243.txt" +0 -417
- package/CODEBUDDY.md +0 -79
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
### 本地运行
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
node bin/aiconductor-cli.js --help # 查看所有命令
|
|
11
|
+
node bin/aiconductor-cli.js <command> --help # 查看子命令选项
|
|
12
|
+
node bin/aiconductor-cli.js search web "关键词" -n 3 -f text # 真实调用示例
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### 发布到 npm
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm version patch|minor|major # 升版本号
|
|
19
|
+
npm pkg fix # 修复 package.json 格式
|
|
20
|
+
npm publish # 发布
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
发布前须对本轮新增/修改的每个命令逐条执行真实调用,确认 exit 0 且输出格式正确。
|
|
24
|
+
|
|
25
|
+
## Architecture
|
|
26
|
+
|
|
27
|
+
### 分层结构
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
bin/aiconductor-cli.js ← 入口层:commander 注册子命令树,不含业务逻辑
|
|
31
|
+
src/api.js ← API 层:HTTPS 请求封装 + API Key 解析
|
|
32
|
+
src/lib/cli-utils.js ← 共享工具:output/outputError/key/error 统一处理
|
|
33
|
+
src/commands/<topic>.js ← 命令层:参数组装、调用 API、格式化输出
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**`bin/aiconductor-cli.js`** — 纯聚合入口,action 回调只做参数传递。
|
|
37
|
+
|
|
38
|
+
**`src/api.js`** — 所有外部 API 调用的底层封装:
|
|
39
|
+
- `resolveApiKey(optionKey)` — 三级优先级:`-k` 参数 > `AICONDUCTOR_API_KEY` 环境变量 > `.env` 文件
|
|
40
|
+
- `httpPost()` — 通用 HTTPS POST(端口 443),统一处理 HTTP 错误和网络错误
|
|
41
|
+
- 每个 API 端点对应一个独立函数,通过 `stripBilling()` 过滤计费信息
|
|
42
|
+
- 新增 API 端点只改此文件
|
|
43
|
+
|
|
44
|
+
**`src/lib/cli-utils.js`** — 所有 command 文件共享的工具模块:
|
|
45
|
+
- `outputResult(data, format, textFormatter?)` — 统一成功输出(JSON: `{success: true, data}`)
|
|
46
|
+
- `outputError(err, format)` — 统一错误输出(JSON: `{success: false, error}` 到 stderr)
|
|
47
|
+
- `resolveKeyOrExit(optionKey, format)` — 解析 API Key,失败自动输出错误并 exit(1)
|
|
48
|
+
- `handleApiError(err, format)` — 统一处理 http_error / network_error / 未知错误
|
|
49
|
+
- `safeParseInt(value, defaultValue)` — 安全整数解析,防 NaN
|
|
50
|
+
|
|
51
|
+
**`src/commands/<topic>.js`** — 命令编排层,每个文件对应一个子命令组:
|
|
52
|
+
- 导入 `cli-utils` 的 4 个共享函数,消除重复代码
|
|
53
|
+
- 业务逻辑函数接收 argument + options,组装参数 → 调 API → `outputResult`
|
|
54
|
+
- 成功 `exit(0)`,失败 `exit(1)`
|
|
55
|
+
|
|
56
|
+
### 输出格式约定
|
|
57
|
+
|
|
58
|
+
所有命令支持 `-f json|text`:
|
|
59
|
+
- **JSON(默认)**:成功 stdout `{ success: true, data: {...} }`,失败 stderr `{ success: false, error: "..." }`
|
|
60
|
+
- **text**:人类可读格式,成功以 `✓` 开头
|
|
61
|
+
|
|
62
|
+
### API Key 鉴权
|
|
63
|
+
|
|
64
|
+
两种模式共存(由 API 端决定,不要自行统一):
|
|
65
|
+
- Body 模式:`api_key` 放入请求 body(多数端点)
|
|
66
|
+
- Bearer 模式:`Authorization: Bearer <api_key>` HTTP 头(web_search、douyin_video_search)
|
|
67
|
+
|
|
68
|
+
### 扩展新 API 的标准流程
|
|
69
|
+
|
|
70
|
+
1. `src/api.js`:添加 API 端点常量和调用函数(~10 行)
|
|
71
|
+
2. `src/commands/<新主题>.js`:新建文件,导入 `cli-utils`,写命令函数(~10 行/命令)
|
|
72
|
+
3. `bin/aiconductor-cli.js`:引入模块并注册子命令组
|
|
73
|
+
|
|
74
|
+
### Skills 依赖
|
|
75
|
+
|
|
76
|
+
`.codebuddy/skills/` 下 3 个 skills(`aic-web-search`、`webpage-publish`、`douyin-toolbox`)依赖此 CLI。修改命令签名或输出格式会破坏它们。`.codebuddy/` 已被 `.npmignore` 排除。
|
package/README.md
CHANGED
|
@@ -1,108 +1,266 @@
|
|
|
1
|
-
# AIConductor CLI
|
|
2
|
-
|
|
3
|
-
AIConductor
|
|
4
|
-
|
|
5
|
-
## 安装
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install -g aiconductor-cli
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
**Node.js >= 16.0.0** 环境。
|
|
12
|
-
|
|
13
|
-
## 配置 API Key
|
|
14
|
-
|
|
15
|
-
前往 [https://dev.aiconductor.fun/register](https://dev.aiconductor.fun/register) 注册获取 API Key,然后配置环境变量:
|
|
16
|
-
|
|
17
|
-
**macOS / Linux:**
|
|
18
|
-
```bash
|
|
19
|
-
echo 'export AICONDUCTOR_API_KEY="your-api-key"' >> ~/.zshrc && source ~/.zshrc
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
**Windows PowerShell:**
|
|
23
|
-
```powershell
|
|
24
|
-
[Environment]::SetEnvironmentVariable("AICONDUCTOR_API_KEY", "your-api-key", "User")
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
> 也可在项目目录创建 `.env` 文件写入 `AICONDUCTOR_API_KEY=your-api-key`。
|
|
28
|
-
|
|
29
|
-
## 命令
|
|
30
|
-
|
|
31
|
-
### 发布 HTML 网页
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
aiconductor-cli html publish <HTML代码或文件路径>
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
| 选项 | 说明 |
|
|
38
|
-
|------|------|
|
|
39
|
-
| `-t, --title` |
|
|
40
|
-
| `-k, --api-key` | API Key(可选,默认读取环境变量) |
|
|
41
|
-
| `-f, --format` | 输出格式:`json`(默认)或 `text` |
|
|
42
|
-
|
|
43
|
-
示例:
|
|
44
|
-
```bash
|
|
45
|
-
aiconductor-cli html publish index.html -t my-page
|
|
46
|
-
aiconductor-cli html publish "<h1>Hello</h1>" -t hello-page -f text
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
###
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
|
58
|
-
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
| `--
|
|
62
|
-
| `--
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
1
|
+
# AIConductor CLI
|
|
2
|
+
|
|
3
|
+
AIConductor 平台命令行工具箱,提供网页发布、搜索和抖音数据功能。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g aiconductor-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Node.js >= 16.0.0** 环境。
|
|
12
|
+
|
|
13
|
+
## 配置 API Key
|
|
14
|
+
|
|
15
|
+
前往 [https://dev.aiconductor.fun/register](https://dev.aiconductor.fun/register) 注册获取 API Key,然后配置环境变量:
|
|
16
|
+
|
|
17
|
+
**macOS / Linux:**
|
|
18
|
+
```bash
|
|
19
|
+
echo 'export AICONDUCTOR_API_KEY="your-api-key"' >> ~/.zshrc && source ~/.zshrc
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Windows PowerShell:**
|
|
23
|
+
```powershell
|
|
24
|
+
[Environment]::SetEnvironmentVariable("AICONDUCTOR_API_KEY", "your-api-key", "User")
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
> 也可在项目目录创建 `.env` 文件写入 `AICONDUCTOR_API_KEY=your-api-key`。
|
|
28
|
+
|
|
29
|
+
## 命令
|
|
30
|
+
|
|
31
|
+
### 发布 HTML 网页
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
aiconductor-cli html publish <HTML代码或文件路径> [选项]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| 选项 | 说明 |
|
|
38
|
+
|------|------|
|
|
39
|
+
| `-t, --title` | 文档标题,用作文件名基础 |
|
|
40
|
+
| `-k, --api-key` | API Key(可选,默认读取环境变量) |
|
|
41
|
+
| `-f, --format` | 输出格式:`json`(默认)或 `text` |
|
|
42
|
+
|
|
43
|
+
示例:
|
|
44
|
+
```bash
|
|
45
|
+
aiconductor-cli html publish index.html -t my-page
|
|
46
|
+
aiconductor-cli html publish "<h1>Hello</h1>" -t hello-page -f text
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 发布 Markdown/HTML 网页(推荐)
|
|
50
|
+
|
|
51
|
+
`webpage publish` 是统一的网页发布命令,自动识别 Markdown 和 HTML 并发布为在线网页。
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
aiconductor-cli webpage publish <Markdown/HTML代码或文件路径> [选项]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
| 选项 | 说明 | 默认值 |
|
|
58
|
+
|------|------|--------|
|
|
59
|
+
| `-t, --title` | 文件名(不含 .html 后缀) | 自动生成 |
|
|
60
|
+
| `-k, --api-key` | API Key(可选) | 环境变量 |
|
|
61
|
+
| `--type` | 强制指定类型:`md` 或 `html` | 自动识别 |
|
|
62
|
+
| `--copy-button` | 为代码块添加复制按钮(仅 Markdown) | 关闭 |
|
|
63
|
+
| `-f, --format` | 输出格式:`json` 或 `text` | json |
|
|
64
|
+
|
|
65
|
+
示例:
|
|
66
|
+
```bash
|
|
67
|
+
# 发布 Markdown 文件
|
|
68
|
+
aiconductor-cli webpage publish README.md -t docs
|
|
69
|
+
|
|
70
|
+
# 发布 Markdown 并添加代码复制按钮
|
|
71
|
+
aiconductor-cli webpage publish article.md -t article --copy-button
|
|
72
|
+
|
|
73
|
+
# 发布 HTML 文件
|
|
74
|
+
aiconductor-cli webpage publish index.html -t my-page
|
|
75
|
+
|
|
76
|
+
# 直接传入内容字符串
|
|
77
|
+
aiconductor-cli webpage publish "# Hello\n\nThis is **markdown**" -t hello
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 网页搜索
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
aiconductor-cli search web <关键词> [选项]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| 选项 | 说明 | 默认值 |
|
|
87
|
+
|------|------|--------|
|
|
88
|
+
| `-n, --count` | 返回条数(最多50) | 5 |
|
|
89
|
+
| `--time-range` | 时间范围:预设 `OneDay`/`OneWeek`/`OneMonth`/`OneYear`,或自定义 `YYYY-MM-DD..YYYY-MM-DD` | 无 |
|
|
90
|
+
| `--no-summary` | 不返回内容摘要 | 默认返回 |
|
|
91
|
+
| `--content-format` | 内容格式:`Text` 或 `Markdown` | Text |
|
|
92
|
+
| `--auth-level` | 权威过滤:0=不过滤,1=优先权威来源 | 0 |
|
|
93
|
+
| `--query-rewrite` | 开启 Query 改写 | 关闭 |
|
|
94
|
+
| `-f, --format` | 输出格式:`json` 或 `text` | json |
|
|
95
|
+
|
|
96
|
+
示例:
|
|
97
|
+
```bash
|
|
98
|
+
aiconductor-cli search web "北京今日天气" -n 3 --auth-level 1
|
|
99
|
+
aiconductor-cli search web "AI 最新进展" --time-range OneWeek --content-format Markdown
|
|
100
|
+
aiconductor-cli search web "技术文章" --time-range 2025-01-01..2025-06-30 -n 10
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 图片搜索
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
aiconductor-cli search image <关键词> [选项]
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
| 选项 | 说明 | 默认值 |
|
|
110
|
+
|------|------|--------|
|
|
111
|
+
| `-n, --count` | 返回条数(最多5) | 5 |
|
|
112
|
+
| `--time-range` | 时间范围:预设或自定义日期范围 | 无 |
|
|
113
|
+
| `-f, --format` | 输出格式:`json` 或 `text` | json |
|
|
114
|
+
|
|
115
|
+
示例:
|
|
116
|
+
```bash
|
|
117
|
+
aiconductor-cli search image "长城风景" -n 3 -f text
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 抖音数据工具箱
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
aiconductor-cli douyin <子命令> [参数] [选项]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### 获取作品详情
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
aiconductor-cli douyin video-info <分享链接> [选项]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
示例:
|
|
133
|
+
```bash
|
|
134
|
+
aiconductor-cli douyin video-info "https://v.douyin.com/xxxxx/"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### 获取作品评论
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
aiconductor-cli douyin video-comments <视频URL> [选项]
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
| 选项 | 说明 | 默认值 |
|
|
144
|
+
|------|------|--------|
|
|
145
|
+
| `--max-count` | 获取评论数量 | 50 |
|
|
146
|
+
| `-f, --format` | 输出格式 | json |
|
|
147
|
+
|
|
148
|
+
示例:
|
|
149
|
+
```bash
|
|
150
|
+
aiconductor-cli douyin video-comments "https://www.douyin.com/video/xxxxx" --max-count 100
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### 获取用户视频列表
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
aiconductor-cli douyin user-videos <用户主页URL> [选项]
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
| 选项 | 说明 | 默认值 |
|
|
160
|
+
|------|------|--------|
|
|
161
|
+
| `--max-pages` | 最大页数 | 1 |
|
|
162
|
+
| `--max-seconds` | 最长运行时间(秒),最大 180 | 50 |
|
|
163
|
+
| `-f, --format` | 输出格式 | json |
|
|
164
|
+
|
|
165
|
+
示例:
|
|
166
|
+
```bash
|
|
167
|
+
aiconductor-cli douyin user-videos "https://www.douyin.com/user/xxxxx" --max-pages 3
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### 获取用户详情
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
aiconductor-cli douyin user-detail <用户主页URL> [选项]
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
示例:
|
|
177
|
+
```bash
|
|
178
|
+
aiconductor-cli douyin user-detail "https://www.douyin.com/user/xxxxx"
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### 搜索用户
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
aiconductor-cli douyin user-search <关键词> [选项]
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
| 选项 | 说明 | 默认值 |
|
|
188
|
+
|------|------|--------|
|
|
189
|
+
| `--max-pages` | 最大页数,0=不限制 | 1 |
|
|
190
|
+
| `--max-seconds` | 最长运行时间(秒),最大 180 | 50 |
|
|
191
|
+
| `--fans-range` | 粉丝数筛选:`0_1k`/`1k_1w`/`1w_10w`/`10w_100w`/`100w_` | 无 |
|
|
192
|
+
| `--user-type` | 用户类型:`common_user`/`enterprise_user`/`personal_user` | 无 |
|
|
193
|
+
| `-f, --format` | 输出格式 | json |
|
|
194
|
+
|
|
195
|
+
示例:
|
|
196
|
+
```bash
|
|
197
|
+
aiconductor-cli douyin user-search "美食博主" --fans-range 10w_100w --user-type personal_user
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### 搜索视频
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
aiconductor-cli douyin video-search <关键词> [选项]
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
| 选项 | 说明 | 默认值 |
|
|
207
|
+
|------|------|--------|
|
|
208
|
+
| `--max-pages` | 最大页数,0=不限制 | 1 |
|
|
209
|
+
| `--max-seconds` | 最长运行时间(秒),最大 50 | 50 |
|
|
210
|
+
| `--sort-type` | 排序:0=综合,1=最多点赞,2=最新发布 | 0 |
|
|
211
|
+
| `--publish-time` | 发布时间:0=不限,1=一天,7=一周,180=半年 | 0 |
|
|
212
|
+
| `--filter-duration` | 时长:0=不限,0-1=1分钟内,1-5=1-5分钟,5-10000=5分钟以上 | 0 |
|
|
213
|
+
| `--content-type` | 内容类型:0=不限,1=视频,2=图片,3=文章 | 0 |
|
|
214
|
+
| `-f, --format` | 输出格式 | json |
|
|
215
|
+
|
|
216
|
+
示例:
|
|
217
|
+
```bash
|
|
218
|
+
aiconductor-cli douyin video-search "编程教程" --sort-type 2 --publish-time 7 --content-type 1
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### 视频链接转文字
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
aiconductor-cli douyin link-to-text <视频URL> [选项]
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
示例:
|
|
228
|
+
```bash
|
|
229
|
+
aiconductor-cli douyin link-to-text "https://www.douyin.com/video/xxxxx"
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### 通用选项
|
|
233
|
+
|
|
234
|
+
所有命令支持:
|
|
235
|
+
- `-k, --api-key <key>` — API Key(优先级:参数 > 环境变量 > .env 文件)
|
|
236
|
+
- `-f, --format <json|text>` — 输出格式,默认 JSON
|
|
237
|
+
|
|
238
|
+
## 计费
|
|
239
|
+
|
|
240
|
+
| 功能 | 价格 |
|
|
241
|
+
|------|------|
|
|
242
|
+
| HTML 发布 | 0.01 元/次 |
|
|
243
|
+
| Markdown/HTML 网页发布 | 0.01 元/次 |
|
|
244
|
+
| 网页/图片搜索 | 0.03 元/次 |
|
|
245
|
+
| 抖音作品详情 | 0.01 元/次 |
|
|
246
|
+
| 抖音作品评论 | 0.01 元/次 |
|
|
247
|
+
| 抖音用户视频列表 | 0.03 元/页 |
|
|
248
|
+
| 抖音用户详情 | 0.03 元/次 |
|
|
249
|
+
| 抖音用户搜索 | 0.15 元/页 |
|
|
250
|
+
| 抖音视频搜索 | 0.15 元/页 |
|
|
251
|
+
| 抖音链接转文字 | 0.01 元/次 + 0.0003 元/秒 |
|
|
252
|
+
|
|
253
|
+
> 搜索/调用失败不扣费,仅成功时计费。
|
|
254
|
+
|
|
255
|
+
## 开发
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
git clone https://github.com/huyi9531/aiconductor-cli.git
|
|
259
|
+
cd aiconductor-cli
|
|
260
|
+
npm install
|
|
261
|
+
node bin/aiconductor-cli.js --help # 本地运行
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## License
|
|
265
|
+
|
|
266
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiconductor-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "AIConductor CLI 工具箱",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aiconductor",
|
|
7
7
|
"html",
|
|
8
8
|
"publish",
|
|
9
9
|
"deploy",
|
|
10
|
-
"cli"
|
|
10
|
+
"cli",
|
|
11
|
+
"douyin",
|
|
12
|
+
"search"
|
|
11
13
|
],
|
|
12
14
|
"author": "",
|
|
13
15
|
"license": "MIT",
|
|
14
|
-
"main": "src/index.js",
|
|
15
16
|
"bin": {
|
|
16
17
|
"aiconductor-cli": "bin/aiconductor-cli.js"
|
|
17
18
|
},
|
package/src/api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const https = require("https");
|
|
2
2
|
const fs = require("fs");
|
|
3
3
|
const path = require("path");
|
|
4
4
|
|
|
@@ -40,6 +40,31 @@ function resolveApiKey(optionKey) {
|
|
|
40
40
|
return null;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* 过滤响应中的计费信息
|
|
45
|
+
* @param {object} resp
|
|
46
|
+
* @returns {object}
|
|
47
|
+
*/
|
|
48
|
+
function stripBilling(resp) {
|
|
49
|
+
if (!resp || typeof resp !== "object") return resp;
|
|
50
|
+
const result = { ...resp };
|
|
51
|
+
delete result.billing;
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 校验整数参数,非有效正整数时报错
|
|
57
|
+
* @param {*} value
|
|
58
|
+
* @param {string} name
|
|
59
|
+
*/
|
|
60
|
+
function validateInt(value, name) {
|
|
61
|
+
if (value === undefined || value === null) return;
|
|
62
|
+
const n = Number(value);
|
|
63
|
+
if (!Number.isInteger(n) || n < 0) {
|
|
64
|
+
throw Object.assign(new Error(`${name} 须为非负整数,收到: ${value}`), { type: "validation_error" });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
43
68
|
/**
|
|
44
69
|
* HTTP POST 请求封装
|
|
45
70
|
* @param {string} host
|
|
@@ -53,7 +78,7 @@ function httpPost(host, path, body, headers = {}) {
|
|
|
53
78
|
|
|
54
79
|
const options = {
|
|
55
80
|
hostname: host,
|
|
56
|
-
port:
|
|
81
|
+
port: 443,
|
|
57
82
|
path: path,
|
|
58
83
|
method: "POST",
|
|
59
84
|
headers: {
|
|
@@ -63,7 +88,7 @@ function httpPost(host, path, body, headers = {}) {
|
|
|
63
88
|
},
|
|
64
89
|
};
|
|
65
90
|
|
|
66
|
-
const req =
|
|
91
|
+
const req = https.request(options, (res) => {
|
|
67
92
|
let chunks = [];
|
|
68
93
|
res.on("data", (chunk) => chunks.push(chunk));
|
|
69
94
|
res.on("end", () => {
|
|
@@ -112,10 +137,7 @@ async function publishHtml(apiKey, htmlCode, title) {
|
|
|
112
137
|
if (title) reqBody.title = title;
|
|
113
138
|
|
|
114
139
|
const resp = await httpPost(API_HOST, API_PATH, reqBody);
|
|
115
|
-
|
|
116
|
-
// 过滤计费信息
|
|
117
|
-
const { billing, ...safe } = resp;
|
|
118
|
-
return safe;
|
|
140
|
+
return stripBilling(resp);
|
|
119
141
|
}
|
|
120
142
|
|
|
121
143
|
/**
|
|
@@ -125,6 +147,10 @@ async function publishHtml(apiKey, htmlCode, title) {
|
|
|
125
147
|
* @returns {Promise<object>}
|
|
126
148
|
*/
|
|
127
149
|
async function webSearch(apiKey, params) {
|
|
150
|
+
// 输入校验
|
|
151
|
+
validateInt(params.count, "count");
|
|
152
|
+
validateInt(params.authLevel, "authLevel");
|
|
153
|
+
|
|
128
154
|
const reqBody = {
|
|
129
155
|
query: params.query,
|
|
130
156
|
search_type: params.searchType,
|
|
@@ -140,9 +166,7 @@ async function webSearch(apiKey, params) {
|
|
|
140
166
|
Authorization: `Bearer ${apiKey}`,
|
|
141
167
|
});
|
|
142
168
|
|
|
143
|
-
|
|
144
|
-
const { billing, ...safe } = resp;
|
|
145
|
-
return safe;
|
|
169
|
+
return stripBilling(resp);
|
|
146
170
|
}
|
|
147
171
|
|
|
148
172
|
/**
|
|
@@ -163,8 +187,7 @@ async function publishMdToHtml(apiKey, mdText, filename, addCopyButton = false)
|
|
|
163
187
|
|
|
164
188
|
const resp = await httpPost(API_HOST, MD_TO_HTML_API_PATH, reqBody);
|
|
165
189
|
|
|
166
|
-
|
|
167
|
-
return safe;
|
|
190
|
+
return stripBilling(resp);
|
|
168
191
|
}
|
|
169
192
|
|
|
170
193
|
/**
|
|
@@ -178,8 +201,7 @@ async function douyinVideoInfo(apiKey, shareUrl) {
|
|
|
178
201
|
api_key: apiKey,
|
|
179
202
|
share_url: shareUrl,
|
|
180
203
|
});
|
|
181
|
-
|
|
182
|
-
return safe;
|
|
204
|
+
return stripBilling(resp);
|
|
183
205
|
}
|
|
184
206
|
|
|
185
207
|
/**
|
|
@@ -193,8 +215,7 @@ async function douyinVideoComments(apiKey, videoUrl, maxCount) {
|
|
|
193
215
|
const body = { api_key: apiKey, video_url: videoUrl };
|
|
194
216
|
if (maxCount !== undefined && maxCount !== null) body.max_count = maxCount;
|
|
195
217
|
const resp = await httpPost(API_HOST, DOUYIN_VIDEO_COMMENTS_PATH, body);
|
|
196
|
-
|
|
197
|
-
return safe;
|
|
218
|
+
return stripBilling(resp);
|
|
198
219
|
}
|
|
199
220
|
|
|
200
221
|
/**
|
|
@@ -210,8 +231,7 @@ async function douyinUserVideos(apiKey, homePage, maxSeconds, maxPages) {
|
|
|
210
231
|
if (maxSeconds !== undefined && maxSeconds !== null) body.max_seconds = maxSeconds;
|
|
211
232
|
if (maxPages !== undefined && maxPages !== null) body.max_pages = maxPages;
|
|
212
233
|
const resp = await httpPost(API_HOST, DOUYIN_USER_VIDEOS_PATH, body);
|
|
213
|
-
|
|
214
|
-
return safe;
|
|
234
|
+
return stripBilling(resp);
|
|
215
235
|
}
|
|
216
236
|
|
|
217
237
|
/**
|
|
@@ -225,8 +245,7 @@ async function douyinUserDetail(apiKey, homePage) {
|
|
|
225
245
|
api_key: apiKey,
|
|
226
246
|
home_page: homePage,
|
|
227
247
|
});
|
|
228
|
-
|
|
229
|
-
return safe;
|
|
248
|
+
return stripBilling(resp);
|
|
230
249
|
}
|
|
231
250
|
|
|
232
251
|
/**
|
|
@@ -243,8 +262,7 @@ async function douyinUserSearch(apiKey, keyword, opts = {}) {
|
|
|
243
262
|
if (opts.fansRange) body.douyin_user_fans = opts.fansRange;
|
|
244
263
|
if (opts.userType) body.douyin_user_type = opts.userType;
|
|
245
264
|
const resp = await httpPost(API_HOST, DOUYIN_USER_SEARCH_PATH, body);
|
|
246
|
-
|
|
247
|
-
return safe;
|
|
265
|
+
return stripBilling(resp);
|
|
248
266
|
}
|
|
249
267
|
|
|
250
268
|
/**
|
|
@@ -265,8 +283,7 @@ async function douyinVideoSearch(apiKey, keyword, opts = {}) {
|
|
|
265
283
|
const resp = await httpPost(API_HOST, DOUYIN_VIDEO_SEARCH_PATH, body, {
|
|
266
284
|
Authorization: `Bearer ${apiKey}`,
|
|
267
285
|
});
|
|
268
|
-
|
|
269
|
-
return safe;
|
|
286
|
+
return stripBilling(resp);
|
|
270
287
|
}
|
|
271
288
|
|
|
272
289
|
/**
|
|
@@ -280,8 +297,7 @@ async function douyinLinkToText(apiKey, videoUrl) {
|
|
|
280
297
|
api_key: apiKey,
|
|
281
298
|
video_url: videoUrl,
|
|
282
299
|
});
|
|
283
|
-
|
|
284
|
-
return safe;
|
|
300
|
+
return stripBilling(resp);
|
|
285
301
|
}
|
|
286
302
|
|
|
287
303
|
module.exports = {
|