From 67e328942ce171ccd093071b7c1e998f328302e2 Mon Sep 17 00:00:00 2001 From: zhilv Date: Fri, 1 May 2026 23:14:12 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=96=20docs(*):=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新 README,添加功能特性、接口文档、批量发送示例和部署说明 --- README.md | 201 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 158 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 71e8ed0..7bca71d 100644 --- a/README.md +++ b/README.md @@ -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 ` 或 `X-API-Key: ` 鉴权。 +所有接口响应格式统一: + +```json +// 成功 +{"code": 0, "msg": "ok", "data": {...}} + +// 失败 +{"code": 400, "msg": "invalid json", "data": null} +``` + +鉴权方式(除 `/healthz` 外必填): + +``` +Authorization: Bearer +# 或 +X-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 +```