mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
docs: fix factual errors, fill coverage gaps and align zh mirror
This commit is contained in:
parent
41ad1a036b
commit
db49e1f01c
35 changed files with 912 additions and 316 deletions
|
|
@ -10,40 +10,52 @@ https://your-worker.workers.dev
|
|||
|
||||
## 端点
|
||||
|
||||
| 方法 | 路径 | 鉴权 | 说明 |
|
||||
| -------- | ------------------------------ | ------------ | ---------------------------------------------------- |
|
||||
| `GET` | `/health` | 无 | 健康检查 |
|
||||
| `POST` | `/webhook` | HMAC 签名 | GitHub / Gitea / 自定义 webhook 接入(自动识别来源) |
|
||||
| `POST` | `/webhook/:groupId` | 分组 secret | 分组级 webhook 入口(只触发该分组的路由) |
|
||||
| `POST` | `/discord/interactions` | Ed25519 签名 | Discord 交互(斜杠命令、按钮、modal) |
|
||||
| `POST` | `/telegram/webhook` | Secret token | Telegram 更新(bot `/gh` 命令) |
|
||||
| `GET` | `/api/richheader` | 无 | 用于 Telegram 头像链接预览卡片的 Open Graph 页面 |
|
||||
| `GET` | `/auth/github` | 无 | 启动 GitHub OAuth 流程 |
|
||||
| `GET` | `/auth/github/callback` | 无 | OAuth 回调 |
|
||||
| `DELETE` | `/auth/token/:userId` | 无 | 撤销用户 Token |
|
||||
| `POST` | `/api/comment` | Bearer Token | 创建议题评论 |
|
||||
| `POST` | `/api/merge` | Bearer Token | 合并拉取请求 |
|
||||
| `POST` | `/api/close` | Bearer Token | 关闭拉取请求 |
|
||||
| `POST` | `/api/react` | Bearer Token | 添加议题反应 |
|
||||
| `GET` | `/admin` | 管理员会话 | 配置控制台页面 |
|
||||
| `GET` | `/admin/api/routes` | 管理员会话 | 列出路由 |
|
||||
| `PUT` | `/admin/api/routes` | 管理员会话 | 替换路由 |
|
||||
| `GET` | `/admin/api/groups` | 管理员会话 | 列出分组(按权限过滤) |
|
||||
| `PUT` | `/admin/api/groups` | 管理员会话 | 替换分组(仅超级管理员) |
|
||||
| `GET` | `/admin/api/groups/:id/routes` | 管理员会话 | 列出某分组的路由 |
|
||||
| `PUT` | `/admin/api/groups/:id/routes` | 管理员会话 | 替换某分组的路由 |
|
||||
| `PUT` | `/admin/api/groups/:id/rename` | 管理员会话 | 重命名分组(owner);路由/secret/邀请自动跟随 |
|
||||
| `GET` | `/admin/api/me` | 管理员会话 | 当前会话信息 |
|
||||
| `GET` | `/admin/api/logs` | 管理员会话 | 发送日志(按权限过滤) |
|
||||
| `GET` | `/admin/api/logs/:id` | 管理员会话 | 单条发送日志(按权限过滤) |
|
||||
| 方法 | 路径 | 鉴权 | 说明 |
|
||||
|----------|--------------------------------------------|--------------|------------------------------------------------------|
|
||||
| `GET` | `/health` | 无 | 健康检查 |
|
||||
| `POST` | `/webhook` | HMAC 签名 | GitHub / Gitea / 自定义 webhook 接入(自动识别来源) |
|
||||
| `POST` | `/webhook/:groupId` | 分组 secret | 分组级 webhook 入口(只触发该分组的路由) |
|
||||
| `POST` | `/discord/interactions` | Ed25519 签名 | Discord 交互(斜杠命令、按钮、modal) |
|
||||
| `POST` | `/telegram/webhook` | Secret token | Telegram 更新(bot `/gh` 命令) |
|
||||
| `GET` | `/api/richheader` | 无 | 用于 Telegram 头像链接预览卡片的 Open Graph 页面 |
|
||||
| `GET` | `/auth/github` | 无 | 启动 GitHub OAuth 流程 |
|
||||
| `GET` | `/auth/github/callback` | 无 | OAuth 回调 |
|
||||
| `GET` | `/auth/github/install` | 管理员会话 | 安装后选择页:将安装绑定到某个分组 |
|
||||
| `POST` | `/auth/github/install/bind` | 管理员会话 | 执行选定的安装绑定 |
|
||||
| `DELETE` | `/auth/token/:userId` | 管理员会话 | 撤销用户 Token |
|
||||
| `POST` | `/api/comment` | Bearer Token | 创建议题评论 |
|
||||
| `POST` | `/api/merge` | Bearer Token | 合并拉取请求 |
|
||||
| `POST` | `/api/close` | Bearer Token | 关闭拉取请求 |
|
||||
| `POST` | `/api/react` | Bearer Token | 添加议题反应 |
|
||||
| `GET` | `/admin` | 管理员会话 | 配置控制台页面 |
|
||||
| `GET` | `/admin/login` | 无 | 开始管理员登录(GitHub OAuth) |
|
||||
| `GET` | `/admin/logout` | 管理员会话 | 退出登录并销毁会话 |
|
||||
| `GET` | `/admin/invite` | 管理员会话 | 接受分组邀请(浏览器页面,`?token=…`) |
|
||||
| `GET` | `/admin/api/me` | 管理员会话 | 当前会话、权限范围、分组与角色 |
|
||||
| `GET` | `/admin/api/routes` | 管理员会话 | 列出路由(按权限过滤) |
|
||||
| `PUT` | `/admin/api/routes` | 管理员会话 | 替换路由(按分组 owner/admin) |
|
||||
| `GET` | `/admin/api/groups` | 管理员会话 | 列出分组 + 当前用户在各分组的角色 |
|
||||
| `PUT` | `/admin/api/groups` | 管理员会话 | 替换分组(超级管理员全部;owner 仅自己的) |
|
||||
| `GET` | `/admin/api/groups/:id/routes` | 管理员会话 | 列出某分组的路由 |
|
||||
| `PUT` | `/admin/api/groups/:id/routes` | 管理员会话 | 替换某分组的路由(owner/admin) |
|
||||
| `PUT` | `/admin/api/groups/:id/rename` | 管理员会话 | 重命名分组(owner);路由/secret/邀请自动跟随 |
|
||||
| `GET` | `/admin/api/groups/:id/invites` | 管理员会话 | 列出待处理的邀请(owner) |
|
||||
| `POST` | `/admin/api/groups/:id/invites` | 管理员会话 | 创建邀请链接(owner) |
|
||||
| `DELETE` | `/admin/api/invites/:token` | 管理员会话 | 撤销邀请(owner) |
|
||||
| `GET` | `/admin/api/groups/:id/webhook` | 管理员会话 | 分组 webhook 端点信息(owner) |
|
||||
| `POST` | `/admin/api/groups/:id/webhook/regenerate` | 管理员会话 | 生成/重新生成分组 webhook secret(owner) |
|
||||
| `DELETE` | `/admin/api/groups/:id/webhook` | 管理员会话 | 停用分组 webhook 入口(owner) |
|
||||
| `GET` | `/admin/api/logs` | 管理员会话 | 发送日志(按权限过滤) |
|
||||
| `GET` | `/admin/api/logs/:id` | 管理员会话 | 单条发送日志(按权限过滤) |
|
||||
| `GET` | `/admin/api/audit` | 管理员会话 | 审计日志(按可访问的分组过滤) |
|
||||
|
||||
## 管理控制台
|
||||
|
||||
参见[配置 → Web 控制台](../guide/configuration.md#web-ui)了解设置方法。管理端点需要会话 Cookie,可通过 `GET /admin/login`(GitHub OAuth)获取;登录用户必须列在 `ADMIN_USER_IDS` 中。
|
||||
参见[配置 → Web 控制台](../guide/configuration.md#web-ui)了解设置方法。管理端点需要会话 Cookie,可通过 `GET /admin/login`(GitHub OAuth)获取;登录用户必须列在 `ADMIN_USER_IDS` 中,或管理某个分组。
|
||||
|
||||
- `GET /admin` — 提供配置控制台 HTML
|
||||
- `GET /admin/api/routes` — 返回 `{ "routes": Route[] }`
|
||||
- `PUT /admin/api/routes` — 请求体为 `{ "routes": Route[] }`;校验每条路由(id 格式、唯一 id、name、enabled、groupId、过滤器、可选的 `discordRoleIds`(身份组 id 字符串列表)、平台感知的 targets:Discord 需 `target.channelId`,Telegram 需 `target.chatId`)并持久化到 KV `config:routes`。返回 `200 { ok, count }` 或 `400 { error }` / `401 { error }` / `403 { error }`。
|
||||
- `PUT /admin/api/routes` — 请求体为 `{ "routes": Route[] }`;校验每条路由(id 格式、唯一 id、name、enabled、groupId、过滤器——**仅 `fallback` 路由允许空过滤器**——可选的 `discordRoleIds`(身份组 id 字符串列表)、平台感知的 targets:Discord 需 `target.channelId`,Telegram 需 `target.chatId`)并持久化到 KV `config:routes`。返回 `200 { ok, count }` 或 `400 { error }` / `401 { error }` / `403 { error }`。
|
||||
|
||||
## 健康检查
|
||||
|
||||
|
|
@ -70,7 +82,7 @@ POST /webhook
|
|||
**请求头:**
|
||||
|
||||
| 头部 | 必需 | 说明 |
|
||||
| --------------------- | ---- | ----------------------------- |
|
||||
|-----------------------|------|-------------------------------|
|
||||
| `X-Hub-Signature-256` | 是 | HMAC-SHA256 签名 |
|
||||
| `X-GitHub-Event` | 是 | 事件类型名称 |
|
||||
| `X-GitHub-Delivery` | 否 | 唯一投递 ID(存在时用于去重) |
|
||||
|
|
@ -90,7 +102,7 @@ POST /webhook
|
|||
**错误响应:**
|
||||
|
||||
| 状态码 | 响应体 | 原因 |
|
||||
| ------ | -------------------------------- | ---------------------------- |
|
||||
|--------|----------------------------------|------------------------------|
|
||||
| `401` | `{"error": "Invalid signature"}` | 签名验证失败 |
|
||||
| `400` | `{"error": "Invalid event"}` | 缺少事件头或格式错误的请求体 |
|
||||
| `413` | `{"error": "Request too large"}` | 请求体超过 1MB 限制 |
|
||||
|
|
@ -110,7 +122,7 @@ POST /webhook
|
|||
主要流程是 App 的 **Setup URL** —— 将其设置为 `{BASE_URL}/auth/github/install`。用户安装 App 后浏览器会跳转到:
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
| ------ | --------------------------- | ------------------------------------------------------------- |
|
||||
|--------|-----------------------------|---------------------------------------------------------------|
|
||||
| `GET` | `/auth/github/install` | 选择页:将安装绑定到新分组或登录用户拥有 owner 权限的已有分组 |
|
||||
| `POST` | `/auth/github/install/bind` | 执行绑定(再次校验 owner 角色)并跳转 `/admin?install=ok` |
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ server/ # Nitro 服务器(H3 处理器位于 server/routes/
|
|||
│ ├── github/ # X-GitHub-Event + X-Hub-Signature-256
|
||||
│ └── gitea/ # X-Gitea-Event + X-Gitea-Signature(归一化载荷)
|
||||
├── formatters/ # 平台中立格式化器(产出 NeutralMessage)
|
||||
│ ├── index.ts # formatEvent:29 事件 switch → NeutralMessage + re-export
|
||||
│ ├── index.ts # formatEvent:28 事件 switch + custom → NeutralMessage + re-export
|
||||
│ ├── colors.ts # GITHUB_COLORS + WORKFLOW_CONCLUSION_EMOJI
|
||||
│ ├── helpers.ts # emojiPrefix、T、buildMessage、commitLink/branchLink/tagLink
|
||||
│ └── *.ts # push、pull-request、issues、comments、workflow、release、create、repo、
|
||||
|
|
|
|||
|
|
@ -1,46 +1,47 @@
|
|||
# 支持的事件
|
||||
|
||||
WebHooker 支持 28 种 GitHub webhook 事件类型,每种都有专用的格式化器,生成丰富的 Discord 嵌入消息与 Telegram HTML 消息。不支持的事件会回退到通用格式化器。
|
||||
WebHooker 支持 28 种 GitHub webhook 事件类型,每种都有专用的格式化器,生成丰富的 Discord 嵌入消息与 Telegram HTML 消息——此外还有来自签名自定义 JSON webhook 的 `custom` 事件。不支持的事件会回退到通用格式化器。
|
||||
|
||||
## 事件表
|
||||
|
||||
| 事件 | 说明 | 嵌入亮点 |
|
||||
| ----------------------------- | ---------------------- | ------------------------------------------------ |
|
||||
| `push` | 代码推送到分支 | 提交列表、分支、作者、差异统计 |
|
||||
| `pull_request` | PR 打开/关闭/合并/编辑 | PR 标题、分支、差异统计、标签 |
|
||||
| `issues` | 议题打开/关闭/编辑 | 议题标题、标签、指派人 |
|
||||
| `issue_comment` | 议题或 PR 的评论 | 评论内容、议题引用 |
|
||||
| `workflow_run` | CI/CD 工作流阶段更新 | 工作流状态、结论、耗时;各阶段原地更新同一条消息 |
|
||||
| `workflow_job` | CI 作业阶段更新 | 作业名、状态、结论、工作流 |
|
||||
| `status` | 提交状态更新 | 提交状态、上下文、状态值、提交链接 |
|
||||
| `deployment` | 部署已创建 | 环境、引用、任务 |
|
||||
| `deployment_status` | 部署状态更新 | 环境、状态、提交引用 |
|
||||
| `check_run` | 检查运行阶段更新 | 状态、结论、详情 URL;各阶段原地更新同一条消息 |
|
||||
| `check_suite` | 检查套件完成 | 套件结论、head 分支、提交链接 |
|
||||
| `ping` | Webhook 确认 | Webhook 确认、已订阅的事件类型 |
|
||||
| `release` | 发布创建/编辑 | 标签、内容、附件、预发布标记 |
|
||||
| `create` | 分支或标签已创建 | 引用名称、引用类型 |
|
||||
| `delete` | 分支或标签已删除 | 引用名称、引用类型 |
|
||||
| `star` | 仓库加星/取消星标 | 星标数、操作 |
|
||||
| `fork` | 仓库已复刻 | 源 → 目标复刻 |
|
||||
| `pull_request_review` | PR 审查已提交 | 审查状态(已批准/需修改/已评论)、正文 |
|
||||
| `pull_request_review_comment` | 行内代码审查评论 | 文件路径、行号、评论内容 |
|
||||
| `commit_comment` | 提交的评论 | 提交 SHA、评论内容 |
|
||||
| `member` | 协作者添加/移除 | 成员登录名、操作 |
|
||||
| `label` | 标签创建/编辑/删除 | 标签名称、颜色、描述 |
|
||||
| `milestone` | 里程碑打开/关闭 | 进度条、议题计数、截止日期 |
|
||||
| `discussion` | 讨论创建/回答 | 标题、分类、操作 |
|
||||
| `discussion_comment` | 讨论的评论 | 评论内容、讨论引用 |
|
||||
| `repository` | 仓库重命名/转移 | 旧 → 新名称、变更 |
|
||||
| `code_scanning_alert` | 代码扫描告警 | 严重程度、规则 ID、文件路径 |
|
||||
| `dependabot_alert` | Dependabot 告警 | 严重程度、包、受影响版本、修复版本 |
|
||||
| 事件 | 说明 | 嵌入亮点 |
|
||||
|-------------------------------|---------------------------|----------------------------------------------------------------------------------------------------------------|
|
||||
| `push` | 代码推送到分支 | 提交列表、分支、作者、差异统计 |
|
||||
| `pull_request` | PR 打开/关闭/合并/编辑 | PR 标题、分支、差异统计、标签 |
|
||||
| `issues` | 议题打开/关闭/编辑 | 议题标题、标签、指派人 |
|
||||
| `issue_comment` | 议题或 PR 的评论 | 评论内容、议题引用 |
|
||||
| `workflow_run` | CI/CD 工作流阶段更新 | 工作流状态、结论、耗时;各阶段原地更新同一条消息 |
|
||||
| `workflow_job` | CI 作业阶段更新 | 作业名、状态、结论、工作流 |
|
||||
| `status` | 提交状态更新 | 提交状态、上下文、状态值、提交链接 |
|
||||
| `deployment` | 部署已创建 | 环境、引用、任务 |
|
||||
| `deployment_status` | 部署状态更新 | 环境、状态、提交引用 |
|
||||
| `check_run` | 检查运行阶段更新 | 状态、结论、详情 URL;各阶段原地更新同一条消息 |
|
||||
| `check_suite` | 检查套件完成 | 套件结论、head 分支、提交链接 |
|
||||
| `ping` | Webhook 确认 | Webhook 确认、已订阅的事件类型 |
|
||||
| `release` | 发布创建/编辑 | 标签、内容、附件、预发布标记 |
|
||||
| `create` | 分支或标签已创建 | 引用名称、引用类型 |
|
||||
| `delete` | 分支或标签已删除 | 引用名称、引用类型 |
|
||||
| `star` | 仓库加星/取消星标 | 星标数、操作 |
|
||||
| `fork` | 仓库已复刻 | 源 → 目标复刻 |
|
||||
| `pull_request_review` | PR 审查已提交 | 审查状态(已批准/需修改/已评论)、正文 |
|
||||
| `pull_request_review_comment` | 行内代码审查评论 | 文件路径、行号、评论内容 |
|
||||
| `commit_comment` | 提交的评论 | 提交 SHA、评论内容 |
|
||||
| `member` | 协作者添加/移除 | 成员登录名、操作 |
|
||||
| `label` | 标签创建/编辑/删除 | 标签名称、颜色、描述 |
|
||||
| `milestone` | 里程碑打开/关闭 | 进度条、议题计数、截止日期 |
|
||||
| `discussion` | 讨论创建/回答 | 标题、分类、操作 |
|
||||
| `discussion_comment` | 讨论的评论 | 评论内容、讨论引用 |
|
||||
| `repository` | 仓库重命名/转移 | 旧 → 新名称、变更 |
|
||||
| `code_scanning_alert` | 代码扫描告警 | 严重程度、规则 ID、文件路径 |
|
||||
| `dependabot_alert` | Dependabot 告警 | 严重程度、包、受影响版本、修复版本 |
|
||||
| `custom` | 签名的自定义 JSON webhook | 任意 title/description/color/url/author/fields(见[自定义 webhook](../guide/configuration.md#自定义-webhook)) |
|
||||
|
||||
## 颜色编码
|
||||
|
||||
每种事件类型在 Discord 嵌入中使用不同的颜色(来自 `src/formatters/colors.ts`):
|
||||
每种事件类型在 Discord 嵌入中使用不同的颜色(来自 `server/lib/formatters/colors.ts`):
|
||||
|
||||
| 颜色 | 事件 |
|
||||
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|------------------|---------------------------------------------------------------------------------------------------------------------------------|
|
||||
| 绿色 (`#2da44e`) | push、PR 打开/可审查、issue 打开、工作流成功、发布已发布、检查成功、审查已批准、部署成功、成员添加、里程碑关闭、讨论已回答 |
|
||||
| 红色 (`#f85149`) | PR 关闭、issue 关闭、工作流失败、发布已删除、delete、检查失败、审查请求修改、部署失败、成员移除、代码扫描/Dependabot 严重与高危 |
|
||||
| 紫色 (`#8957e5`) | PR 合并、label、discussion |
|
||||
|
|
@ -53,11 +54,9 @@ WebHooker 支持 28 种 GitHub webhook 事件类型,每种都有专用的格
|
|||
|
||||
没有专用格式化器的事件类型会回退到通用格式化器,生成包含以下内容的基础嵌入:
|
||||
|
||||
- 事件类型作为标题
|
||||
- 操作(如果可用)
|
||||
- 发送者登录名
|
||||
- 仓库名称
|
||||
- 原始载荷作为代码块(截断到 1000 字符)
|
||||
- 事件类型作为标题(可用时附带操作)
|
||||
- 发送者登录名(作者行)
|
||||
- 仓库名称(页脚)
|
||||
|
||||
## 原地消息更新
|
||||
|
||||
|
|
@ -68,7 +67,7 @@ WebHooker 支持 28 种 GitHub webhook 事件类型,每种都有专用的格
|
|||
实操指南见[过滤器教程](../guide/filters),包含完整示例。
|
||||
|
||||
| 过滤器 | 适用事件 |
|
||||
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `event` | 所有事件 |
|
||||
| `repo` | 所有事件 |
|
||||
| `actor` | 所有事件 |
|
||||
|
|
|
|||
62
docs/zh/guide/commands.md
Normal file
62
docs/zh/guide/commands.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# 机器人命令
|
||||
|
||||
[绑定你的 GitHub 账号](#绑定账号)后,即可在 Discord 和 Telegram 上**以本人身份**操作 GitHub——评论使用你自己的 OAuth token 发布,权限由 GitHub 强制校验。若 GitHub 拒绝操作(例如编辑他人的评论),机器人会明确告知。
|
||||
|
||||
## 绑定账号
|
||||
|
||||
使用任何命令前,需先绑定一次 GitHub 账号:
|
||||
|
||||
| 平台 | 命令 | 效果 |
|
||||
|----------|----------------------------------|-------------------------------------------------------------|
|
||||
| Discord | `/gh login` | 返回一条仅你可见的 OAuth 链接,用于授权 GitHub 账号 |
|
||||
| Discord | `/gh logout` | 解除绑定 |
|
||||
| Telegram | `/gh login`(引用一条消息) | 返回 OAuth 链接 |
|
||||
| Telegram | `/gh logout`(引用一条消息) | 解除绑定 |
|
||||
|
||||
链接保存在服务端(KV),并在 D1 中映射到你的 Discord/Telegram 用户 ID。
|
||||
|
||||
## Discord
|
||||
|
||||
Discord 命令为**斜杠命令**与**消息右键菜单命令**,由定时任务同步(每 5 分钟):按服务器即时注册,并全局注册(24h 去重,约 1 小时传播)。所有回复均为临时消息(仅你可见)。
|
||||
|
||||
### 评论 issue / PR
|
||||
|
||||
两种等效方式:
|
||||
|
||||
- **右键通知**(推荐):右键机器人发出的 issue / PR / 评论通知 → **应用** → **GitHub: 添加评论 / 编辑评论 / 删除评论**。目标自动从通知嵌入中提取,无需链接。
|
||||
- **带链接的斜杠命令**:
|
||||
|
||||
```
|
||||
/gh comment add link:<issue 或 PR 链接> 例如 https://github.com/owner/repo/issues/123
|
||||
/gh comment edit link:<评论链接> 链接需包含 #issuecomment-<id>
|
||||
/gh comment del link:<评论链接> 链接需包含 #issuecomment-<id>
|
||||
```
|
||||
|
||||
`edit` / `del` 需要在 GitHub 上复制具体评论链接(评论 ⋯ 菜单 → **复制链接**)。`add` / `edit` 会打开模态框输入/调整评论内容(edit 会预填)。
|
||||
|
||||
### 合并 / 关闭 PR
|
||||
|
||||
开放 PR 的通知附带 **合并 / 关闭** 按钮:
|
||||
|
||||
- 点击按钮即以你绑定的 GitHub 账号合并(squash)或关闭 PR;权限由 GitHub 强制校验。
|
||||
- 成功后按钮会从通知中移除,结果以临时消息展示。
|
||||
|
||||
### 前置条件
|
||||
|
||||
| 项目 | 如何满足 |
|
||||
|--------------|-----------------------------------------------------------------------------------------------------|
|
||||
| 公钥 | 设置 `DISCORD_PUBLIC_KEY` 并配置 Interactions Endpoint URL |
|
||||
| 邀请 scope | 机器人以 `applications.commands` scope 邀请(见 [Discord Bot 设置](./deployment#discord-bot-设置)) |
|
||||
| OAuth | 配置 `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` 与 `BASE_URL` |
|
||||
| 绑定账号 | 每位用户先执行 `/gh login` |
|
||||
|
||||
## Telegram
|
||||
|
||||
Telegram `/gh` 命令通过**引用一条通知消息**来使用:
|
||||
|
||||
- `/gh login` — 绑定 GitHub 账号(返回 OAuth 链接)
|
||||
- `/gh logout` — 解除绑定
|
||||
- `/gh comment <文本>` — 引用 issue/PR 通知以本人身份评论
|
||||
- `/gh merge` / `/gh close` — 引用 PR 通知进行合并/关闭
|
||||
|
||||
目标 issue/PR 从你引用的消息(通知嵌入中的链接)解析。命令通过 Telegram webhook(`POST /telegram/webhook`,可用 `TELEGRAM_WEBHOOK_SECRET` 校验)送达。
|
||||
|
|
@ -7,7 +7,7 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars`
|
|||
### 必需密钥
|
||||
|
||||
| 变量 | 说明 |
|
||||
| ----------------------- | -------------------------------------------------------- |
|
||||
|-------------------------|----------------------------------------------------------|
|
||||
| `GITHUB_WEBHOOK_SECRET` | GitHub App 设置中的 Webhook 密钥 |
|
||||
| `GITEA_WEBHOOK_SECRET` | Gitea 实例的 Webhook 密钥(仅接收 Gitea webhook 时需要) |
|
||||
| `GITHUB_CLIENT_ID` | App 设置中的 OAuth 客户端 ID |
|
||||
|
|
@ -16,18 +16,22 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars`
|
|||
| `TELEGRAM_TOKEN` | Telegram Bot Token(BotFather 获取)—— Telegram 路由必需 |
|
||||
|
||||
> [!NOTE]
|
||||
> `GITHUB_APP_ID` 与 `GITHUB_PRIVATE_KEY` 当前未被代码使用——OAuth 流程只需要
|
||||
> `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`。为兼容性保留在模式中,以备日后启用
|
||||
> GitHub App 认证。
|
||||
> `GITHUB_APP_ID` 与 `GITHUB_PRIVATE_KEY`(PKCS#8 PEM)用于 GitHub App **安装流程**
|
||||
> (`/auth/github/install`),通过 App JWT 解析安装所属账号的登录名。两者均为可选——
|
||||
> 未设置时安装页仍可正常使用,但会显示无账号名的匿名 `inst-{installationId}` 分组。
|
||||
> OAuth 流程本身只需要 `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`。
|
||||
|
||||
### 可选密钥
|
||||
|
||||
| 变量 | 说明 | 默认值 |
|
||||
| --------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------- |
|
||||
|-----------------------------|--------------------------------------------------------------------------------------------------|-------------------------|
|
||||
| `BASE_URL` | OAuth 回调的公开 URL | `http://localhost:8787` |
|
||||
| `ADMIN_USER_IDS` | 允许访问 WebUI 的 GitHub 用户 ID(或登录名),逗号分隔 | 未设置时 WebUI 关闭 |
|
||||
| `ALLOW_SELF_SIGNUP` | 开启(`1`/`true`)后,没有任何分组权限的 GitHub 用户首次登录会自动获得个人分组而非 403 | 关闭 |
|
||||
| `AUDIT_RETENTION_DAYS` | 定时清理时审计日志的保留天数 | `90` |
|
||||
| `NUXT_PUBLIC_DOCS_URL` | 落地页使用的文档站 URL(客户端运行时配置) | 落地页默认值 |
|
||||
| `NUXT_PUBLIC_REPO_URL` | 落地页使用的 GitHub 仓库 URL | 落地页默认值 |
|
||||
| `NUXT_PUBLIC_LEGAL_CONTACT` | `/terms` 与 `/privacy` 页面展示的联系方式 | 未设置时显示占位文本 |
|
||||
| `DISCORD_PUBLIC_KEY` | Discord 应用的公钥(开发者门户获取),交互功能必需 | 未设置时交互返回 401 |
|
||||
| `DISCORD_APPLICATION_ID` | Discord 应用 ID;省略时自动获取 | 自动获取 |
|
||||
| `TELEGRAM_WEBHOOK_SECRET` | `POST /telegram/webhook` 验签密钥(X-Telegram-Bot-Api-Secret-Token) | 未设置时不校验 |
|
||||
|
|
@ -38,10 +42,12 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars`
|
|||
WebHooker 通过同一个 `POST /webhook` 端点接收多个 forge 的 webhook,按请求头自动识别来源;只需把各 forge 的 webhook 指向 `{BASE_URL}/webhook` 即可。
|
||||
|
||||
| 提供方 | 事件请求头 | 签名请求头 | 签名格式 | 密钥 |
|
||||
| ------ | ---------------- | --------------------- | -------------------------- | ----------------------- |
|
||||
|--------|------------------|-----------------------|----------------------------|-------------------------|
|
||||
| GitHub | `X-GitHub-Event` | `X-Hub-Signature-256` | `sha256=<hex>` HMAC-SHA256 | `GITHUB_WEBHOOK_SECRET` |
|
||||
| Gitea | `X-Gitea-Event` | `X-Gitea-Signature` | 纯 hex HMAC-SHA256 | `GITEA_WEBHOOK_SECRET` |
|
||||
|
||||
投递 id 去重使用 `X-GitHub-Delivery`(GitHub)或 `X-Gitea-Delivery`(Gitea)请求头(存在时)。
|
||||
|
||||
Gitea payload 会被归一化为与 GitHub 相同的内部结构,因此路由、过滤器与 28 个格式化器无需改动即可复用;未知或未映射的 Gitea 事件回退到通用格式化器。仓库/提交/用户链接基于 payload 的 `repository.html_url` 生成,会指向你的 Gitea 实例。
|
||||
|
||||
## Web 控制台
|
||||
|
|
@ -50,7 +56,7 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
|
||||
### 设置
|
||||
|
||||
1. 配置 `ADMIN_USER_IDS`,填写允许管理路由的 GitHub 用户 ID,也支持登录名,例如 `ADMIN_USER_IDS=12345,RhenCloud`。未设置时控制台禁用(除非开启 `ALLOW_SELF_SIGNUP`)。
|
||||
1. 配置 `ADMIN_USER_IDS`,填写允许管理一切的 GitHub 用户 ID,也支持登录名,例如 `ADMIN_USER_IDS=12345,RhenCloud`。未设置时控制台禁用(除非开启 `ALLOW_SELF_SIGNUP`)。
|
||||
2. 打开 `/admin` 并使用 GitHub 登录。
|
||||
3. 没有任何权限的用户收到 `403`,除非开启 `ALLOW_SELF_SIGNUP=1`(自动获得个人分组)或通过分组[邀请链接](#邀请)加入。
|
||||
|
||||
|
|
@ -59,7 +65,7 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
控制台以 SPA 形式挂在 `/admin`,各标签页可通过 URL 路径直达(`/admin/groups`、`/admin/logs`、`/admin/audit`)。`/admin` 之外且未匹配下方端点的 URL 直接返回 `404`,不会再被吞进控制台。
|
||||
|
||||
| 端点 | 说明 |
|
||||
| ----------------------------------------------- | -------------------------------------------------------- |
|
||||
|-------------------------------------------------|----------------------------------------------------------|
|
||||
| `GET /admin` | 配置控制台页面 |
|
||||
| `GET /admin/login` | 开始 GitHub OAuth 登录 |
|
||||
| `GET /admin/logout` | 销毁会话 |
|
||||
|
|
@ -82,7 +88,7 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
| `POST /admin/api/groups/:id/webhook/regenerate` | 生成/重新生成分组 webhook secret(owner) |
|
||||
| `DELETE /admin/api/groups/:id/webhook` | 停用分组 webhook 入口(owner) |
|
||||
|
||||
控制台支持新增、编辑、删除和开关路由。保存后立即写入 KV `config:routes` 并使配置缓存失效,下一次 webhook 处理即会生效。
|
||||
控制台支持新增、编辑、删除和开关路由。保存后立即写入 KV `config:routes` 并使配置缓存失效,下一次 webhook 处理即会生效。上限:每个实例最多 **200 条路由** 与 **100 个分组**。
|
||||
|
||||
## Webhook 端点
|
||||
|
||||
|
|
@ -124,7 +130,7 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
| ------------- | -------- | -------------------------------------------------------------------------------------------------------- |
|
||||
|---------------|----------|----------------------------------------------------------------------------------------------------------|
|
||||
| `title` | string | 消息标题(缺失时回退为「自定义消息」) |
|
||||
| `description` | string | 可选的消息正文 |
|
||||
| `color` | string | 可选消息颜色:颜色词(`red`、`green`、`yellow`、`blue`、`purple`、`orange`、`cyan`、`gray`)或 `#rrggbb` |
|
||||
|
|
@ -139,7 +145,7 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
|
||||
GitHub App 安装后,**所有**安装方的事件都会到达全局端点。要让租户互相隔离,请把每个分组绑定到应当为其提供事件的安装 ID:`"installationId": 12345678`。该 ID 可从 App 安装 webhook 载荷(`installation.id`)或 GitHub App 安装页 URL 看到。即使分组的 `owners` 为空,来自其它安装的事件也会被拒绝。未设置 `installationId` 的分组保持旧行为(`owners` 过滤)。
|
||||
|
||||
绑定是**自动配置**的 —— 将 GitHub App 的 _Setup URL_ 指向 `{BASE_URL}/auth/github/install`。用户安装 App 后浏览器立即跳转到该页面,可选择将安装绑定到:**新分组**(`inst-{installationId}`,默认)或任意**自己拥有 owner 权限的已有分组**(提交时再次校验角色;由 `POST /auth/github/install/bind` 完成配置)。无需手动填写 ID。作为兜底(例如未配置 Setup URL 时),`installation.created` webhook 事件也会自动创建/绑定分组 —— `owners` 匹配安装账号的现有分组会被绑定,否则创建独立的 `inst-{installationId}` 分组。之后在控制台为分组添加路由和成员即可。
|
||||
绑定是**自动配置**的 —— 将 GitHub App 的 _Setup URL_ 指向 `{BASE_URL}/auth/github/install`。用户安装 App 后浏览器立即跳转到该页面(页面需要已登录的管理员会话——未登录用户会先被重定向走 OAuth 流程),可选择将安装绑定到:**新分组**(`inst-{installationId}`,默认)或任意**自己拥有 owner 权限的已有分组**(提交时再次校验角色;由 `POST /auth/github/install/bind` 完成配置)。无需手动填写 ID。作为兜底(例如未配置 Setup URL 时),`installation.created` webhook 事件也会自动创建/绑定分组 —— `owners` 匹配安装账号的现有分组会被绑定,否则创建独立的 `inst-{installationId}` 分组。之后在控制台为分组添加路由和成员即可。
|
||||
|
||||
## 路由
|
||||
|
||||
|
|
@ -195,7 +201,7 @@ GitHub App 安装后,**所有**安装方的事件都会到达全局端点。
|
|||
其他路由字段:
|
||||
|
||||
| 字段 | 类型 | 必需 | 说明 |
|
||||
| ---------------- | -------- | ---- | ---------------------------------------------------------------------- |
|
||||
|------------------|----------|------|------------------------------------------------------------------------|
|
||||
| `groupId` | string | 是 | 该路由所属[分组](#分组)的 id |
|
||||
| `fallback` | boolean | 否 | 为 `true` 时,仅当没有其它路由匹配该事件时才发送,其自身过滤器会被忽略 |
|
||||
| `stop` | boolean | 否 | 为 `true` 且该路由匹配时,停止评估后续路由 |
|
||||
|
|
@ -249,7 +255,7 @@ GitHub App 安装后,**所有**安装方的事件都会到达全局端点。
|
|||
```
|
||||
|
||||
| 字段 | 类型 | 必需 | 说明 |
|
||||
| ---------------- | -------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|------------------|----------|------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `id` | string | 是 | 小写 id(`a-z0-9`、`-`),由每条路由的 `groupId` 引用。可修改:重命名分组会同步更新其路由、分组级 webhook secret 与待接受邀请 |
|
||||
| `name` | string | 是 | 可读的分组名称 |
|
||||
| `members` | object[] | 否 | `{ login, role }` 列表;角色为 `owner`、`admin` 或 `viewer` |
|
||||
|
|
@ -266,7 +272,7 @@ GitHub App 安装后,**所有**安装方的事件都会到达全局端点。
|
|||
每个分组成员拥有三种角色之一。超级管理员(`ADMIN_USER_IDS`)始终绕过角色限制。
|
||||
|
||||
| 角色 | 查看路由/日志 | 编辑路由 | 管理成员与邀请 | 编辑分组设置 |
|
||||
| -------- | ------------- | -------- | -------------- | ------------------ |
|
||||
|----------|---------------|----------|----------------|--------------------|
|
||||
| `owner` | ✓ | ✓ | ✓ | ✓(`owners` 除外) |
|
||||
| `admin` | ✓ | ✓ | ✗ | ✗ |
|
||||
| `viewer` | ✓(只读) | ✗ | ✗ | ✗ |
|
||||
|
|
@ -282,7 +288,7 @@ GitHub App 安装后,**所有**安装方的事件都会到达全局端点。
|
|||
|
||||
### Webhook 日志频道
|
||||
|
||||
分组可以设置 `logTarget` 指向一个 Discord 频道/子区或 Telegram 群组/话题。每当该分组的路由分发(dispatch)一个 webhook,就会向那里发送一条摘要消息:事件类型/动作、仓库、投递 ID,以及每条「路由 × 目标」一行的 ✅/❌ 结果(失败时附带错误信息)。全部成功时消息为绿色,任一失败则为红色。摘要使用分组的消息语言。日志消息尽力发送,本身不会被记入 D1 发送日志。
|
||||
分组可以设置 `logTarget` 指向一个 Discord 频道/子区或 Telegram 群组/话题。每当该分组的路由分发(dispatch)一个 webhook,就会向那里发送一条摘要消息:事件类型/动作、仓库、投递 ID,以及每条「路由 × 目标」一行的 ✅/❌ 结果(失败时附带错误信息;最多列出前 10 行,其余以 `+N` 汇总)。全部成功时消息为绿色,任一失败则为红色。摘要使用分组的消息语言。日志消息尽力发送,本身不会被记入 D1 发送日志。
|
||||
|
||||
### 邀请
|
||||
|
||||
|
|
@ -297,13 +303,13 @@ owner(及超级管理员)可在分组的「成员」面板创建一次性邀
|
|||
实操指南见[过滤器教程](./filters),包含完整示例。
|
||||
|
||||
| 类型 | 匹配对象 | 示例 |
|
||||
| --------- | ---------------- | ----------------------------------------- |
|
||||
|-----------|------------------|-------------------------------------------|
|
||||
| `event` | GitHub 事件名称 | `push`, `pull_*`, `pull_request` |
|
||||
| `repo` | 仓库全名 | `org/repo`, `org/*` |
|
||||
| `actor` | 发送者登录名 | `username`, `[bot]`, `*[bot]` |
|
||||
| `action` | 事件操作 | `opened`, `closed`, `published` |
|
||||
| `branch` | 分支名称 | `main`, `feature-?`, `/^release-/` |
|
||||
| `keyword` | 载荷正文中的文本 | `deploy`, `*release-*`, `/fix\s+\d+/` |
|
||||
| `keyword` | 载荷正文中的文本 | `deploy`, `/fix\s+\d+/` |
|
||||
|
||||
### 过滤器行为
|
||||
|
||||
|
|
@ -326,7 +332,7 @@ owner(及超级管理员)可在分组的「成员」面板创建一次性邀
|
|||
## KV 存储布局
|
||||
|
||||
| 键模式 | 值 | TTL |
|
||||
| ------------------------------ | ----------------------------------------------------------------------------- | ------------------ |
|
||||
|--------------------------------|-------------------------------------------------------------------------------|--------------------|
|
||||
| `config:routes` | JSON 路由数组 | 永久 |
|
||||
| `config:groups` | JSON 分组数组 | 永久 |
|
||||
| `session:{id}` | 管理员会话 `{ userId, login }` | 7 天 |
|
||||
|
|
@ -336,6 +342,8 @@ owner(及超级管理员)可在分组的「成员」面板创建一次性邀
|
|||
| `invite:{token}` | `{ groupId, role, expiresAt, createdBy, note? }` | 7 天 |
|
||||
| `invite:group:{id}` | 每组的 Token 索引(保证邀请列表一致性) | 永久 |
|
||||
| `delivery:{id}` | Webhook 投递 id(去重标记) | 300 秒 |
|
||||
| `delivery:{groupId}:{id}` | 分组级 webhook 入口的租户级投递去重 | 300 秒 |
|
||||
| `tenant:{groupId}` | 分组 webhook secret(64 位 hex,控制台生成) | 永久 |
|
||||
| `msg:{routeId}:{key}:{target}` | 原地更新用消息 id 追踪(如 `workflow_run` / `check_run`) | 7 天 |
|
||||
| `cmd:guild:{id}` | 已注册命令的服务器 id(去重标记) | 永久 |
|
||||
| `cmd:registered:global` | 全局命令已注册标记(24h 去重) | 1 天 |
|
||||
|
|
@ -347,7 +355,7 @@ owner(及超级管理员)可在分组的「成员」面板创建一次性邀
|
|||
D1 数据库(`DB` 绑定,数据库 `webhooker`)包含四张表:
|
||||
|
||||
| 表 | 用途 |
|
||||
| ---------------- | ---------------------------------------------------------------------- |
|
||||
|------------------|------------------------------------------------------------------------|
|
||||
| `send_logs` | 每次分发尝试一行(路由 id、事件、目标、成功/失败、耗时、错误码、详情) |
|
||||
| `audit_logs` | 每次管理操作一行(登录/登出、分组/路由/成员/邀请变更) |
|
||||
| `discord_links` | 映射 `discord_user_id` → `github_user_id`,用于 Discord `/gh` 命令 |
|
||||
|
|
|
|||
|
|
@ -37,9 +37,8 @@ bunx wrangler secret put ADMIN_USER_IDS # 逗号分隔的 GitHub ID/登录
|
|||
不存在全局频道密钥。每条路由在 [Web 控制台](/zh/guide/configuration#web-控制台) 中声明各自的目标频道(及可选的子区/thread),因此不需要 `DISCORD_CHANNEL_ID`。
|
||||
:::
|
||||
|
||||
::: tip GitHub App ID / 私钥未使用
|
||||
`GITHUB_APP_ID` 与 `GITHUB_PRIVATE_KEY` 当前未被代码使用——OAuth 流程只需要
|
||||
`GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`。无需设置(也无需进行 PKCS#8 转换)。
|
||||
::: tip GitHub App ID / 私钥为可选
|
||||
`GITHUB_APP_ID` + `GITHUB_PRIVATE_KEY`(PKCS#8 PEM)仅用于 [App 安装流程](#github-app-设置),在安装后选择页解析安装所属账号的登录名。可以跳过不设——页面会显示匿名 `inst-{installationId}` 分组。OAuth 流程只需要 `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`。
|
||||
:::
|
||||
|
||||
Discord 交互通过 HTTPS Interactions Endpoint 送达,需要设置 `DISCORD_PUBLIC_KEY` 并把 **Interactions Endpoint URL** 指向 `https://your-domain/discord/interactions`。参见下方 [Interactions Endpoint](#interactions-endpoint)。
|
||||
|
|
@ -123,7 +122,7 @@ Worker 现在可通过 `https://webhooker.<your-subdomain>.workers.dev` 访问
|
|||
- **Organization permissions**: Members (read) —— 如果需要
|
||||
4. 订阅事件(全部 28 种支持的事件):
|
||||
- Push、Pull request、Issues、Issue comment、Workflow run、Workflow job、Status、Deployment、Deployment status、Ping、Release、Create、Delete、Star、Fork、Check run、Check suite、Pull request review、Pull request review comment、Commit comment、Member、Label、Milestone、Discussion、Discussion comment、Repository、Code scanning alert、Dependabot alert
|
||||
5. 生成私钥 → 将内容保存到 `GITHUB_PRIVATE_KEY` 环境变量
|
||||
5. 生成私钥 — 可选;设置 `GITHUB_APP_ID` + `GITHUB_PRIVATE_KEY` 后,安装后页面会显示安装所属账号的登录名(见上方提示)。
|
||||
|
||||
### 2. 安装 App
|
||||
|
||||
|
|
@ -160,7 +159,7 @@ Worker 现在可通过 `https://webhooker.<your-subdomain>.workers.dev` 访问
|
|||
|
||||
`/gh` 斜杠命令与 `GitHub: 添加/编辑/删除评论` 消息命令由定时任务(每 5 分钟)同步注册:按服务器即时可用,同时全局注册(24h 去重,约 1 小时传播)。Bot 从不连接 Discord Gateway,因此显示为**离线**——消息推送不受影响(始终走 REST)。
|
||||
|
||||
用户运行 `/gh login` 绑定自己的 GitHub 账号,即可以本人身份评论 issue/PR。完整命令说明见 [README](https://github.com/ReCloudStudio/WebHooker#bot-commands-comment-on-github-as-yourself)。
|
||||
用户运行 `/gh login` 绑定自己的 GitHub 账号,即可以本人身份评论 issue/PR。完整命令说明见[机器人命令](/zh/guide/commands)。
|
||||
|
||||
## Telegram 机器人配置
|
||||
|
||||
|
|
@ -169,12 +168,7 @@ Worker 现在可通过 `https://webhooker.<your-subdomain>.workers.dev` 访问
|
|||
3. Worker 会在定时任务中自动同步 webhook(`setWebhook` 指向 `{BASE_URL}/telegram/webhook`),因此无需手动调用 `setWebhook`——只需确保 `BASE_URL` 已设置。
|
||||
4. 将机器人加入群组(或启用话题),在路由配置中用 `chatId` / `topicId` 指定目标。
|
||||
|
||||
在 Telegram 中,`/gh` 命令通过在通知消息上**回复**来使用:
|
||||
|
||||
- `/gh login` — 绑定你的 GitHub 账号(返回 OAuth 链接)
|
||||
- `/gh logout` — 解除绑定
|
||||
- `/gh comment <内容>` — 回复一条 issue/PR 通知,以本人身份评论
|
||||
- `/gh merge` / `/gh close` — 回复一条 PR 通知,合并/关闭该 PR
|
||||
在 Telegram 中,`/gh` 命令(`/gh login`、`/gh logout`、`/gh comment <内容>`、`/gh merge`、`/gh close`)通过在通知消息上**回复**来使用——见[机器人命令](/zh/guide/commands)。
|
||||
|
||||
头像使用内置 `GET /api/richheader` 渲染为链接预览卡片(可用 `TELEGRAM_RICH_HEADER_HOST` 覆盖)。
|
||||
|
||||
|
|
|
|||
37
docs/zh/guide/faq.md
Normal file
37
docs/zh/guide/faq.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# 常见问题与故障排查
|
||||
|
||||
## 为什么 Discord 机器人显示为离线?
|
||||
|
||||
机器人从不连接 Discord Gateway——它始终通过 REST API 发送消息,并通过 HTTPS Interactions Endpoint 接收交互。**离线是正常现象**,不影响消息投递。
|
||||
|
||||
## 我的 webhook 没有被转发
|
||||
|
||||
按顺序检查:
|
||||
|
||||
1. `GET /health` 返回 `{"status":"ok"}`。
|
||||
2. webhook URL 指向 `{BASE_URL}/webhook`,且密钥与 `GITHUB_WEBHOOK_SECRET` / `GITEA_WEBHOOK_SECRET` 一致。
|
||||
3. 存在至少一条**启用**且匹配该事件(`event` 过滤器)的路由,且其分组允许该发送者(见分组的 `owners` / `providers` / `installationId`)。
|
||||
4. 路由至少有一个目标,且频道/群组 id 有效。
|
||||
5. 查看控制台**日志**标签页——每次分发尝试都会记录错误。
|
||||
|
||||
## Discord 机器人不响应命令/按钮
|
||||
|
||||
- 必须设置 `DISCORD_PUBLIC_KEY`,且 **Interactions Endpoint URL** 指向 `{BASE_URL}/discord/interactions`。
|
||||
- 用户需先执行 `/gh login`,且 OAuth 密钥(`GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`、`BASE_URL`)已配置。
|
||||
- 斜杠命令由定时任务每 5 分钟同步;全局注册可能需要约 1 小时传播。
|
||||
|
||||
## 删除分支后收到"0 个提交"的推送消息
|
||||
|
||||
通过 `git push --delete` 删除分支时,事件以 `deleted: true` 的 push 事件到达——会被渲染为正常的删除消息。若仍看到"0 个提交",说明载荷中缺少 `deleted` 标志(例如旧投递)。
|
||||
|
||||
## 如何让分组使用自己的 webhook 端点?
|
||||
|
||||
见[分组端点](./configuration#分组端点)——在分组的 **Webhook 端点**面板(owner 角色)生成密钥,然后用 `POST /webhook/{groupId}` 与分组密钥发送。
|
||||
|
||||
## 可以脱离 Cloudflare Workers 运行吗?
|
||||
|
||||
不能——Worker 依赖 `wrangler.jsonc` 中声明的 KV 与 D1 绑定,并运行在 `cloudflare_module` Nitro preset 上。
|
||||
|
||||
## 数据存储在哪里?
|
||||
|
||||
配置存于 Cloudflare KV(`config:routes`、`config:groups`);发送/审计日志与平台↔GitHub 绑定存于 D1。见[存储布局](./configuration#kv-存储布局)。
|
||||
|
|
@ -157,7 +157,7 @@
|
|||
|
||||
### `keyword` — 载荷中的文本
|
||||
|
||||
匹配整个 JSON 载荷(转为小写)。它是最灵活的过滤器:纯文本在任意位置搜索,`*`/`?` 通配符带通配搜索,`/` 包裹的模式按正则表达式编译(带 `i` 标志)。
|
||||
匹配整个 JSON 载荷(转为小写)。它是最灵活的过滤器:纯文本在任意位置搜索,`*`/`?` 通配符带通配搜索,`//` 包裹的模式按正则表达式编译(带 `i` 标志)。
|
||||
|
||||
```json
|
||||
{ "type": "keyword", "match": "deploy" }
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ BASE_URL=http://localhost:8787
|
|||
```
|
||||
|
||||
::: tip
|
||||
`GITHUB_APP_ID` / `GITHUB_PRIVATE_KEY` 未被代码使用(OAuth 流程只需要 Client ID/Secret),可省略。目标频道在 Web UI 中按路由设置,因此不需要 `DISCORD_CHANNEL_ID`。若要在本地启用 `/gh` 命令,请在开发者门户复制 **Public Key** 填入 `DISCORD_PUBLIC_KEY`,并把 Interactions Endpoint URL 设为 `http://localhost:8787/discord/interactions`。
|
||||
`GITHUB_APP_ID` / `GITHUB_PRIVATE_KEY` 为可选,仅用于 App 安装流程解析安装所属账号的登录名(OAuth 流程只需要 Client ID/Secret)。目标频道在 Web UI 中按路由设置,因此不需要 `DISCORD_CHANNEL_ID`。若要在本地启用 `/gh` 命令,请在开发者门户复制 **Public Key** 填入 `DISCORD_PUBLIC_KEY`,并把 Interactions Endpoint URL 设为 `http://localhost:8787/discord/interactions`。
|
||||
:::
|
||||
|
||||
::: warning
|
||||
|
|
@ -62,14 +62,16 @@ curl http://localhost:8787/health
|
|||
|
||||
## 可用脚本
|
||||
|
||||
| 脚本 | 说明 |
|
||||
| ---------------------- | ----------------------------- |
|
||||
| `bun run dev` | 启动本地开发服务器 (wrangler) |
|
||||
| `bun run deploy` | 部署到 Cloudflare |
|
||||
| `bun run typecheck` | TypeScript 类型检查 |
|
||||
| `bun run lint` | ESLint |
|
||||
| `bun run lint:md` | Markdownlint |
|
||||
| `bun run format` | 使用 Prettier 格式化 |
|
||||
| `bun run format:check` | 检查 Prettier 格式 |
|
||||
| `bun run docs:dev` | 启动文档开发服务器 |
|
||||
| `bun run docs:build` | 构建文档站点 |
|
||||
| 脚本 | 说明 |
|
||||
|------------------------|--------------------------------------|
|
||||
| `bun run dev` | 启动 Nuxt 开发服务器 (HMR) |
|
||||
| `bun run build` | 生产构建(cloudflare_module preset) |
|
||||
| `bun run deploy` | 部署到 Cloudflare |
|
||||
| `bun run typecheck` | TypeScript 类型检查 |
|
||||
| `bun run lint` | ESLint |
|
||||
| `bun run lint:md` | Markdownlint |
|
||||
| `bun run format` | 使用 Prettier 格式化 |
|
||||
| `bun run format:check` | 检查 Prettier 格式 |
|
||||
| `bun test` | 单元测试 |
|
||||
| `bun run docs:dev` | 启动文档开发服务器 |
|
||||
| `bun run docs:build` | 构建文档站点 |
|
||||
|
|
|
|||
24
docs/zh/guide/i18n.md
Normal file
24
docs/zh/guide/i18n.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# 消息语言(i18n)
|
||||
|
||||
消息按每个分组配置的语言渲染。WebHooker 内置**英文**(默认)与**简体中文**两套字典。
|
||||
|
||||
## 分组语言
|
||||
|
||||
设置 `Group.lang`(如 `"zh"`)可为分组内所有路由选择消息语言——见[分组 → 分组模式](./configuration#分组模式)。分组的 webhook 日志频道摘要使用相同的语言。
|
||||
|
||||
## 自定义覆盖
|
||||
|
||||
翻译覆盖从 KV 键 `i18n:<lang>` 读取,值为扁平的「键 → 文本」JSON 对象。内置字典(en/zh)中的任意键都可覆盖;未提供的键回退为英文。
|
||||
|
||||
```jsonc
|
||||
// KV 键:i18n:zh
|
||||
{
|
||||
"events.push.title": "{repo}: 推送了 {count} 个提交到 {ref}"
|
||||
}
|
||||
```
|
||||
|
||||
覆盖对分组消息(以及适用的控制台界面)生效。要新增一种语言,可在 `i18n:<lang>` 存放完整字典——未提供的键都会回退为英文。
|
||||
|
||||
## 表情开关
|
||||
|
||||
`Group.emoji`(默认 `true`)控制该分组消息中是否显示事件表情。关闭后,标题、描述、字段与链接中的所有表情都会被去除。里程碑进度条(🟢🟡🟠⬜)属于数据可视化,不受该开关影响。
|
||||
|
|
@ -41,7 +41,7 @@ GitHub / Gitea Webhook → Cloudflare Worker (Nuxt 4 / Nitro)
|
|||
- **HTTP 框架**: Nuxt 4 / Nitro (H3)
|
||||
- **Discord 投递**: Discord REST API(交互通过 Ed25519 验签的 HTTPS Interactions Endpoint)
|
||||
- **Telegram 投递**: Telegram Bot API(webhook 带可选 secret-token 校验)
|
||||
- **Web UI**: Nuxt 3 静态 SPA,由 Worker 资源托管
|
||||
- **Web UI**: Nuxt 4(Vue 3 + Tailwind CSS v3)——首页/法律页面服务端渲染,`/admin` 控制台客户端渲染
|
||||
- **存储**: Cloudflare KV + D1
|
||||
- **鉴权**: Web Crypto API (HMAC-SHA256、Ed25519)、octokit (GitHub API)
|
||||
- **语言**: TypeScript
|
||||
|
|
|
|||
37
docs/zh/guide/logs.md
Normal file
37
docs/zh/guide/logs.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# 日志
|
||||
|
||||
## 发送日志(`send_logs`)
|
||||
|
||||
每次分发尝试都会记录到 D1 `send_logs` 表,并可在控制台(**日志**标签页)查看。字段:
|
||||
|
||||
| 字段 | 含义 |
|
||||
|--------------|-------------------------------------------------------------|
|
||||
| `routeId` | 匹配的路由 |
|
||||
| `groupId` | 路由所属分组 |
|
||||
| `event` | 事件类型(如 `push`、`pull_request`、`custom`) |
|
||||
| `repo` | 仓库全名(存在时) |
|
||||
| `target` | 消息发送到的目标 id |
|
||||
| `platform` | `discord` 或 `telegram` |
|
||||
| `ok` | 发送是否成功 |
|
||||
| `status` | 平台 API 的 HTTP 状态码(适用时) |
|
||||
| `error` | 失败时的错误信息 |
|
||||
| `errorCode` | 稳定错误码(如 `NO_TARGET`、`NO_TOKEN`、`RATE_LIMITED`) |
|
||||
| `attempts` | 含重试在内的发送次数 |
|
||||
| `durationMs` | 发送耗时 |
|
||||
| `deliveryId` | Webhook 投递 id(提供时) |
|
||||
| `messageId` | 平台消息 id(用于原地编辑) |
|
||||
| `actor` | 发送者登录名 |
|
||||
| `action` | 事件动作(存在时) |
|
||||
| `detail` | 附加 JSON 详情(存在时) |
|
||||
|
||||
控制台的**日志**标签页列出最近记录(可按分组过滤),并可查看单条完整详情。写入为尽力而为——插入失败不会中断分发。
|
||||
|
||||
## 审计日志(`audit_logs`)
|
||||
|
||||
所有管理员操作都会记录到 D1 `audit_logs` 表,并可在控制台(**审计**标签页)查看:登录/登出、分组/路由/成员/邀请变更、Token 撤销、安装绑定等。字段:时间戳、操作者(GitHub id + 登录名)、动作、目标类型/id、分组 id、IP 与详情 JSON。
|
||||
|
||||
记录由定时任务在 `AUDIT_RETENTION_DAYS`(默认 90)后自动清理。与发送日志一样,写入为尽力而为。
|
||||
|
||||
## Webhook 日志频道
|
||||
|
||||
分组还可以在 Discord 频道/子区或 Telegram 群组/话题中接收每条 webhook 的摘要消息——见[分组 → Webhook 日志频道](./configuration#webhook-日志频道)。这些摘要是尽力发送的,**不会**记录到 `send_logs`。
|
||||
32
docs/zh/guide/message-format.md
Normal file
32
docs/zh/guide/message-format.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# 消息格式
|
||||
|
||||
每个事件格式化器都会产出一条平台中立的消息(`NeutralMessage`),由平台驱动渲染为 Discord 嵌入或 Telegram HTML 消息。
|
||||
|
||||
## 标题
|
||||
|
||||
每个标题必须以仓库名开头,随后是可选的 `#number`,再是 `: 描述`:
|
||||
|
||||
```
|
||||
{repo}{#number}: {subject} 例如 acme/widget#7: Add feature
|
||||
```
|
||||
|
||||
仓库名取自 `payload.repository.full_name`(缺失时回退为通用的「repository」标签)。评论、审查与行内评论使用与其父对象相同的 `{repo}{#number}: {title}` 标题——绝不使用 `"Comment on org/repo"` 前缀。
|
||||
|
||||
## 链接
|
||||
|
||||
只有仓库头会被加超链接——整条标题永远不会整体链接:
|
||||
|
||||
- **Discord**(嵌入标题不支持局部链接):标题为仓库头 `{repo}{#number}`,链接到仓库;`: {subject}` 文本作为描述首行渲染,不带链接。
|
||||
- **Telegram**(HTML 支持行内链接):单行标题保留描述文本,仅仓库头被包在链接中。
|
||||
|
||||
标题中不含冒号分隔符(`:` 后跟一个空格)的消息保持旧的整行链接行为。
|
||||
|
||||
提交哈希、分支与标签渲染为带超链接的行内代码(如 ``[`abc123d`](https://…/commit/abc123def456)``),仓库基地址不可用时回退为纯行内代码。
|
||||
|
||||
## 表情
|
||||
|
||||
事件专属表情由格式化器添加;分组级 `Group.emoji`(默认开启)关闭后会全部去除。里程碑进度条不受影响。见[消息语言](./i18n)。
|
||||
|
||||
## 原地更新
|
||||
|
||||
`workflow_run` 与 `check_run` 消息只发送一次,随运行进度原地编辑(queued → running → success/failure),不会重复发消息。追踪使用 KV `msg:*` 与每次运行的稳定 `updateKey`。
|
||||
11
docs/zh/guide/tasks.md
Normal file
11
docs/zh/guide/tasks.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# 定时任务
|
||||
|
||||
WebHooker 通过定时触发器(`*/5 * * * *`,每 5 分钟)运行三个维护任务。它们只在部署后的 Worker 上运行(Cloudflare cron);本地 `wrangler dev` 可用 `wrangler dev --test-scheduled` 触发。
|
||||
|
||||
| 任务 | 用途 |
|
||||
|-----------------|---------------------------------------------------------------------------------------------------------------------|
|
||||
| `discord-sync` | 注册 Discord 斜杠/右键菜单命令:按服务器即时注册,并全局注册(24h 去重,约 1 小时传播) |
|
||||
| `telegram-sync` | 调用 `setWebhook` 指向 `{BASE_URL}/telegram/webhook`(设置了 `TELEGRAM_WEBHOOK_SECRET` 时作为 `secret_token` 传入) |
|
||||
| `audit-prune` | 删除早于 `AUDIT_RETENTION_DAYS`(默认 90)天的 `audit_logs` 记录 |
|
||||
|
||||
除任务用到的密钥(`DISCORD_TOKEN`、`DISCORD_APPLICATION_ID`、`TELEGRAM_TOKEN`、`BASE_URL`、`AUDIT_RETENTION_DAYS`)外无需其他配置。
|
||||
|
|
@ -19,11 +19,11 @@ features:
|
|||
- title: 灵活的过滤器
|
||||
details: 支持按事件类型、仓库、参与者、操作、分支(含 PR)和关键字(支持正则)过滤。支持排除模式。
|
||||
- title: Cloudflare Workers
|
||||
details: 运行在 Cloudflare 边缘网络上。通过 Discord REST API 与 Telegram Bot API 发送消息,并通过 Ed25519 验签的 Interactions Endpoint 支持 `/gh` 命令。
|
||||
details: 运行在 Cloudflare 边缘网络上。通过 Discord REST API 与 Telegram Bot API 发送消息,并通过 Ed25519 验签的 Interactions Endpoint 支持 `/gh` 斜杠命令与按钮。
|
||||
- title: Web UI、分组与命令
|
||||
details: "在内置管理控制台中管理路由、分组与发送日志。绑定你的 GitHub 账号,通过 /gh 命令以本人身份评论 issue/PR(Discord 或 Telegram)。"
|
||||
- title: 签名验证
|
||||
details: 使用 Web Crypto API 进行 HMAC-SHA256 webhook 签名验证与 Ed25519 交互签名验证,支持时间安全比较。
|
||||
details: 按提供方识别进行 HMAC-SHA256 webhook 签名验证(GitHub X-Hub-Signature-256、Gitea X-Gitea-Signature)与 Ed25519 交互签名验证,使用 Web Crypto API 并支持时间安全比较。
|
||||
- title: 原地更新
|
||||
details: workflow_run / check_run 进度在运行推进时于同一条消息上原地更新,Discord 与 Telegram 均支持。
|
||||
---
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue