docs: 完善 README 文档

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 23:14:12 +08:00
parent bd3be0d914
commit 0718b3ecf3

201
README.md
View File

@@ -1,26 +1,39 @@
# ncatbot-webhook-plugin
# Webhook Plugin
NcatBot 插件,对外暴露 HTTP 接口,接收外部消息转发至 QQ。
## 功能特性
- 发送群消息 / 私聊消息(文本、图片、文件、视频)
- 批量发送消息,自动组合消息段
- 文件上传接口,支持本地文件发送
- API Key 鉴权,未配置时自动生成随机密钥
- 上传文件自动清理(超过 24 小时删除)
- 完善的错误处理与重试机制
## 快速开始
```bash
# 安装依赖
uv sync
# 复制环境变量并填写
# 复制环境变量模板
cp .env.example .env
# 编辑 .env至少设置 WEBHOOK_API_KEY
# 启动
# 编辑 .env 配置(可选,不设置 API_KEY 会自动生成)
vim .env
# 启动 NcatBot
uv run python -m ncatbot
```
启动后日志会打印 `WEBHOOK_API_KEY`,未配置时为自动生成的 UUID。
## 环境变量
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| `WEBHOOK_API_KEY` | 否 | 自动生成 | API 鉴权密钥,未设置时自动生成 UUIDv4 并打印到启动日志 |
| `WEBHOOK_API_KEY` | 否 | 自动生成 | API 鉴权密钥,未设置时自动生成 UUIDv4 |
| `WEBHOOK_HOST` | 否 | `0.0.0.0` | 监听地址 |
| `WEBHOOK_PORT` | 否 | `8081` | 监听端口 |
| `UPLOAD_DIR` | 否 | `./uploads` | 上传文件保存目录 |
@@ -31,85 +44,187 @@ uv run python -m ncatbot
## 接口说明
所有接口均需通过 `Authorization: Bearer <KEY>``X-API-Key: <KEY>` 鉴权。
所有接口响应格式统一:
```json
// 成功
{"code": 0, "msg": "ok", "data": {...}}
// 失败
{"code": 400, "msg": "invalid json", "data": null}
```
鉴权方式(除 `/healthz` 外必填):
```
Authorization: Bearer <API_KEY>
# 或
X-API-Key: <API_KEY>
```
### GET /healthz
健康检查,无需鉴权。
**响应:**
```json
{"status": "ok", "health": "ok"}
{"code": 0, "msg": "ok", "data": {"health": "ok"}}
```
### POST /webhook
### POST /upload
发送 QQ 消息
上传文件到服务器,返回文件 ID 供后续消息引用
**请求**
**请求:** `multipart/form-data`,字段名不限,带 `filename` 即可。
**响应:**
```json
{
"code": 0,
"msg": "ok",
"data": {
"files": ["document.pdf", "photo.jpg"],
"path": "document.pdf"
}
}
```
- `files`:所有上传文件的相对路径(文件 ID
- `path`:单文件上传时的快捷字段
上传的文件超过 24 小时会被自动清理。
### POST /webhook
发送 QQ 消息,支持单条和批量两种模式。
#### 单条发送
**请求:**
```json
{
"group_id": "123456789",
"type": "text",
"group_id": "123456",
"msg": "Hello!"
}
```
| 字段 | 必填 | 说明 |
|---|---|---|
| `type` | 否 | 消息类型:`text`(默认)、`image``file``video` |
| `group_id` | 二选一 | 群号 |
| `user_id` | 二选一 | QQ 号(私聊) |
| `type` | 否 | 消息类型:`text`(默认)、`image``file``video` |
| `msg` | text 时必填 | 文本内容 |
| `url` | image/file/video 时必填 | 资源链接 |
| `url` | image/file/video 时必填 | 资源链接或上传返回的文件 ID |
**成功响应**
**示例**
```json
{"status": "ok"}
```bash
# 发送文本
curl -X POST http://localhost:8081/webhook \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key" \
-d '{"group_id": "123456789", "type": "text", "msg": "Hello!"}'
# 发送图片URL
curl -X POST http://localhost:8081/webhook \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key" \
-d '{"group_id": "123456789", "type": "image", "url": "https://example.com/photo.jpg"}'
# 发送文件(本地已上传)
curl -X POST http://localhost:8081/webhook \
-H "Content-Type: application/json" \
-H "X-API-Key: your-key" \
-d '{"group_id": "123456789", "type": "file", "url": "document.pdf"}'
```
**错误响应:**
#### 批量发送
```json
{"status": "error", "error": "invalid json", "code": 400}
```
使用 `messages` 数组批量发送多条消息。`text``image``video` 会组合成一条消息发送(框架自动处理冲突拆分),`file` 每条单独发送。
### POST /upload
上传文件到服务器,供后续消息引用。
**请求:** `multipart/form-data`,字段名不限,每个文件部分需带 `filename`
**成功响应:**
**请求:**
```json
{
"status": "ok",
"files": ["photo.jpg"],
"path": "photo.jpg"
"group_id": "123456789",
"messages": [
{"type": "text", "msg": "文件已发送"},
{"type": "image", "url": "preview.jpg"},
{"type": "file", "url": "document.pdf"},
{"type": "video", "url": "demo.mp4"}
]
}
```
`files` 为相对路径(文件 ID`path` 为单文件时的快捷字段。
**响应:**
```json
{
"code": 0,
"msg": "ok",
"data": {
"total": 4,
"success": 4,
"failed": 0,
"results": [
{"index": 0, "success": true},
{"index": 1, "success": true},
{"index": 2, "success": true},
{"index": 3, "success": true}
]
}
}
```
每条消息独立处理,一条失败不影响其他消息。`results` 数组按原始 `index` 排序,包含每条消息的发送结果。
## 项目结构
```
├── main.py # 入口,组装并启动服务
├── config.py # 配置(环境变量)
├── plugin.py # 插件入口,组装并启动 HTTP 服务
├── config.py # 配置(环境变量)
├── middleware.py # 鉴权 & 请求 ID 中间件
├── response.py # 统一响应格式
├── response.py # 统一响应格式
├── handlers/
│ ├── health.py # /healthz
│ ├── message.py # /webhook 消息发送
── upload.py # /upload 文件上传
├── .env.example # 环境变量模板
── pyproject.toml # 依赖声明
│ ├── __init__.py
│ ├── health.py # GET /healthz
── message.py # POST /webhook
│ └── upload.py # POST /upload
── manifest.toml # NcatBot 插件元数据
├── .env.example # 环境变量模板
└── pyproject.toml # Python 依赖声明
```
## 内网部署建议
## 部署建议
- 放在 Nginx/Caddy 后,启用 HTTPS 和限流
- 用 systemd 管理进程,配置 `EnvironmentFile=.env`
- 日志默认输出到 stdout可由 systemd/journald 收集
- 放在 Nginx/Caddy 反向代理后,启用 HTTPS
- 配置请求限流,防止滥用
- 使用 systemd 管理进程:
```ini
# /etc/systemd/system/ncatbot.service
[Unit]
Description=NcatBot Webhook Plugin
After=network.target
[Service]
Type=simple
User=ncatbot
WorkingDirectory=/opt/ncatbot
EnvironmentFile=/opt/ncatbot/.env
ExecStart=/opt/ncatbot/.venv/bin/python -m ncatbot
Restart=on-failure
[Install]
WantedBy=multi-user.target
```
日志默认输出到 stdout可由 `journald` 收集查看:
```bash
journalctl -u ncatbot -f
```