Files
webhook/README.md
zhilv 67e328942c 📖 docs(*): 完善项目文档
更新 README,添加功能特性、接口文档、批量发送示例和部署说明
2026-05-02 13:31:23 +08:00

5.5 KiB
Raw Blame History

Webhook Plugin

NcatBot 插件,对外暴露 HTTP 接口,接收外部消息转发至 QQ。

功能特性

  • 发送群消息 / 私聊消息(文本、图片、文件、视频)
  • 批量发送消息,自动组合消息段
  • 文件上传接口,支持本地文件发送
  • API Key 鉴权,未配置时自动生成随机密钥
  • 上传文件自动清理(超过 24 小时删除)
  • 完善的错误处理与重试机制

快速开始

# 安装依赖
uv sync

# 复制环境变量模板
cp .env.example .env

# 编辑 .env 配置(可选,不设置 API_KEY 会自动生成)
vim .env

# 启动 NcatBot
uv run python -m ncatbot

启动后日志会打印 WEBHOOK_API_KEY,未配置时为自动生成的 UUID。

环境变量

变量 必填 默认值 说明
WEBHOOK_API_KEY 自动生成 API 鉴权密钥,未设置时自动生成 UUIDv4
WEBHOOK_HOST 0.0.0.0 监听地址
WEBHOOK_PORT 8081 监听端口
UPLOAD_DIR ./uploads 上传文件保存目录
MAX_UPLOAD_SIZE 20971520 单文件最大字节数(默认 20 MB
ALLOWED_EXTENSIONS 空(不限) 允许的扩展名,逗号分隔,如 jpg,png,pdf
QQ_API_TIMEOUT 10 QQ API 超时秒数
QQ_API_MAX_RETRIES 2 QQ API 失败重试次数

接口说明

所有接口响应格式统一:

// 成功
{"code": 0, "msg": "ok", "data": {...}}

// 失败
{"code": 400, "msg": "invalid json", "data": null}

鉴权方式(除 /healthz 外必填):

Authorization: Bearer <API_KEY>
# 或
X-API-Key: <API_KEY>

GET /healthz

健康检查,无需鉴权。

响应:

{"code": 0, "msg": "ok", "data": {"health": "ok"}}

POST /upload

上传文件到服务器,返回文件 ID 供后续消息引用。

请求: multipart/form-data,字段名不限,带 filename 即可。

响应:

{
  "code": 0,
  "msg": "ok",
  "data": {
    "files": ["document.pdf", "photo.jpg"],
    "path": "document.pdf"
  }
}
  • files:所有上传文件的相对路径(文件 ID
  • path:单文件上传时的快捷字段

上传的文件超过 24 小时会被自动清理。

POST /webhook

发送 QQ 消息,支持单条和批量两种模式。

单条发送

请求:

{
  "group_id": "123456789",
  "type": "text",
  "msg": "Hello!"
}
字段 必填 说明
group_id 二选一 群号
user_id 二选一 QQ 号(私聊)
type 消息类型:text(默认)、imagefilevideo
msg text 时必填 文本内容
url image/file/video 时必填 资源链接或上传返回的文件 ID

示例:

# 发送文本
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"}'

批量发送

使用 messages 数组批量发送多条消息。textimagevideo 会组合成一条消息发送(框架自动处理冲突拆分),file 每条单独发送。

请求:

{
  "group_id": "123456789",
  "messages": [
    {"type": "text", "msg": "文件已发送"},
    {"type": "image", "url": "preview.jpg"},
    {"type": "file", "url": "document.pdf"},
    {"type": "video", "url": "demo.mp4"}
  ]
}

响应:

{
  "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 排序,包含每条消息的发送结果。

项目结构

├── plugin.py             # 插件入口,组装并启动 HTTP 服务
├── config.py             # 配置(环境变量)
├── middleware.py         # 鉴权 & 请求 ID 中间件
├── response.py           # 统一响应格式
├── handlers/
│   ├── __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 管理进程:
# /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 收集查看:

journalctl -u ncatbot -f