docs: sync documentation with current codebase

- Update event formatter count 23 -> 28 (add ping, workflow_job, status, deployment, check_suite)
- Document Telegram support end-to-end (routes, /gh commands, richheader, secrets)
- Fix route schema to use targets array and group fields (owners, emoji)
- Correct KV/D1 storage layout (msg:*, i18n:*, D1 links/send_logs)
- Note GITHUB_APP_ID/GITHUB_PRIVATE_KEY are unused; drop legacy DISCORD_CHANNEL_ID/PORT/CONFIG_PATH
- Remove stale Docker deployment section
- Update color table, branch filter compatibility, admin API endpoints
- AGENTS.md: add Documentation section requiring doc updates after functional changes
This commit is contained in:
wyf9 2026-08-05 17:22:15 +08:00
parent 68cda9f178
commit afe19795b1
No known key found for this signature in database
GPG key ID: B126966081BFDBE4
25 changed files with 621 additions and 398 deletions

View file

@ -47,6 +47,7 @@ GitHub 授权后重定向到此地址。将 code 交换为访问令牌并存储
- **浏览器流程**`Accept: text/html`):设置管理员会话 Cookie然后重定向到 `redirect` 目标;无管理权限的用户被重定向到 `/admin?error=forbidden`
- **JSON 流程**:返回 `{ "userId": "...", "login": "...", "redirectTo": "..." }`
- **Discord 绑定流程**(以未决的 `discordUserId` 启动时):将 Discord 用户绑定到此 GitHub 账号,返回 `{ "ok": true, "discordUserId": "...", "login": "..." }`——浏览器中则显示成功页面。
- **Telegram 绑定流程**(以未决的 `telegramUserId` 启动时):将 Telegram 用户绑定到此 GitHub 账号,返回 `{ "ok": true, "telegramUserId": "...", "login": "..." }`,并向未决的 `telegramChatId` 发送确认消息。
### 撤销 Token
@ -77,7 +78,7 @@ Token 以键模式 `token:{userId}` 存储在 KV 中:
}
```
`expiresAt` 是毫秒级 Unix 时间戳。KV 条目在 Token 有效期的 90% 时过期(至少 60 秒)。反向索引 `token-reverse:{sha256 of token}` 将访问令牌映射回用户 id使 Bearer 鉴权的端点能解析调用者。与 GitHub 账号绑定的 Discord 用户存储在 D1 的 `discord_links` 表中。
`expiresAt` 是毫秒级 Unix 时间戳。KV 条目在 Token 有效期的 90% 时过期(至少 60 秒)。反向索引 `token-reverse:{sha256 of token}` 将访问令牌映射回用户 id使 Bearer 鉴权的端点能解析调用者。与 GitHub 账号绑定的 Discord 用户存储在 D1 的 `discord_links` 表中Telegram 用户存储在 D1 的 `telegram_links` 表中。
## 使用 Token

View file

@ -33,6 +33,7 @@ https://your-worker.workers.dev
| `PUT` | `/admin/api/groups/:id/routes` | 管理员会话 | 替换某分组的路由 |
| `GET` | `/admin/api/me` | 管理员会话 | 当前会话信息 |
| `GET` | `/admin/api/logs` | 管理员会话 | 发送日志(按权限过滤) |
| `GET` | `/admin/api/logs/:id` | 管理员会话 | 单条发送日志(按权限过滤) |
## 管理控制台
@ -40,7 +41,7 @@ https://your-worker.workers.dev
- `GET /admin` — 提供配置控制台 HTML
- `GET /admin/api/routes` — 返回 `{ "routes": Route[] }`
- `PUT /admin/api/routes` — 请求体为 `{ "routes": Route[] }`校验每条路由id 格式、唯一 id、name、enabled、groupId、过滤器、平台感知的 targetDiscord 需 `target.channelId`Telegram 需 `target.chatId`)并持久化到 KV `config:routes`。返回 `200 { ok, count }``400 { error }` / `401 { error }`。
- `PUT /admin/api/routes` — 请求体为 `{ "routes": Route[] }`校验每条路由id 格式、唯一 id、name、enabled、groupId、过滤器、平台感知的 targetsDiscord 需 `target.channelId`Telegram 需 `target.chatId`)并持久化到 KV `config:routes`。返回 `200 { ok, count }``400 { error }` / `401 { error }` / `403 { error }`。
## 健康检查
@ -66,11 +67,11 @@ POST /webhook
**请求头:**
| 头部 | 必需 | 说明 |
| --------------------- | ---- | ---------------- |
| `X-Hub-Signature-256` | 是 | HMAC-SHA256 签名 |
| `X-GitHub-Event` | 是 | 事件类型名称 |
| `X-GitHub-Delivery` | 是 | 唯一投递 ID |
| 头部 | 必需 | 说明 |
| --------------------- | ---- | ----------------------------- |
| `X-Hub-Signature-256` | 是 | HMAC-SHA256 签名 |
| `X-GitHub-Event` | 是 | 事件类型名称 |
| `X-GitHub-Delivery` | 否 | 唯一投递 ID存在时用于去重 |
**请求体:** GitHub webhook JSON 载荷(最大 1MB
@ -82,6 +83,8 @@ POST /webhook
}
```
`X-GitHub-Delivery` 存在且同一投递在最近 5 分钟内已被处理时Worker 返回 `200 { "ok": true, "duplicate": true }`,不再重复分发。
**错误响应:**
| 状态码 | 响应体 | 原因 |

View file

@ -14,23 +14,25 @@ npm run dev # 启动本地开发服务器
```text
src/
├── index.ts # CF Workers 入口 (fetch + scheduled)scheduled = 命令同步
├── types.ts # Env、Config、Route、Filter、WebhookEvent、NeutralMessage
├── index.ts # CF Workers 入口 (fetch + scheduled)scheduled = Discord 命令同步 + Telegram webhook 同步
├── types.ts # Env、Config、Route、Filter、Group、WebhookEvent、NeutralMessage
├── config.ts # 从 KV 加载路由(未设置时返回 []),从 env 构建 Config
├── server.ts # Hono 应用: /health、/webhook、/discord/interactions挂载 /auth、/admin + /
├── server.ts # Hono 应用: /health、/webhook、/discord/interactions、/telegram/webhook,挂载 /auth、/admin + /
├── core/
│ └── dispatch.ts # 平台中立分发:匹配路由 → formatEvent → getDriver().send
├── events/ # GitHub webhook 事件流水线
│ └── dispatch.ts # 平台中立分发:匹配路由 → formatEvent → getDriver().send/edit
├── events/ # GitHub webhook 事件流水线(旧 src/webhook.ts 为死代码)
│ ├── verify.ts # HMAC 签名验证 (Web Crypto时间安全)
│ ├── parse.ts # parseEvent (headers + body → WebhookEvent)
│ └── match.ts # matchRoute、eventOwners、extractBranch、关键词过滤
├── formatters/ # 平台中立格式化器(产出 NeutralMessage
│ ├── index.ts # formatEvent24 事件 switch → NeutralMessage + re-export
│ ├── index.ts # formatEvent28 事件 switch → NeutralMessage + re-export
│ ├── colors.ts # GITHUB_COLORS + WORKFLOW_CONCLUSION_EMOJI
│ ├── helpers.ts # emojiPrefix、T、buildMessage
│ └── *.ts # push、pull-request、issues、comments、workflow、release、repo 等
│ └── *.ts # push、pull-request、issues、comments、workflow、release、create、repo、
│ # check、review、commit-comment、deployment、member、label、milestone、
│ # discussion、repository、security、generic、ping
├── drivers/ # 平台驱动(可插拔推送目标)
│ ├── types.ts # PlatformDriver 接口 + SendResult
│ ├── types.ts # PlatformDriver 接口 + SendResultsend + edit
│ ├── index.ts # getDriver() 注册表discord + telegram
│ ├── discord/ # index.ts (驱动)、render.ts (NeutralMessage → embed)、
│ │ # rest.ts、interactions.ts、commands.ts
@ -38,21 +40,24 @@ src/
│ # rest.ts (chat_id + message_thread_id)、updates.ts (webhook 验签)、
│ # commands.ts (/gh login|logout|comment|merge|close + 引用消息解析)
├── github/ # GitHub OAuth + 以用户身份操作
│ ├── oauth.ts # OAuth URL、回调 Token 交换、getUserOctokit、操作
│ ├── oauth.ts # OAuth URL、回调 Token 交换、getUserOctokit、评论/合并/关闭操作
│ └── store.ts # KV Token CRUD + D1 discord-link/telegram-link 映射
├── web/ # HTTP UI/API 路由
│ ├── oauth-routes.ts # GET /auth/github、回调、DELETE /token/:userId (KV 状态)
│ ├── oauth-routes.ts # GET /auth/github、回调(管理员会话 / Discord 绑定 / Telegram 绑定)、DELETE /token/:userId
│ ├── action-routes.ts # POST /api/comment|merge|close|react (通过 KV 查找进行 Bearer Token 鉴权)
│ ├── admin-routes.ts # /admin API路由、分组、me、日志会话 + 权限范围鉴权)
│ ├── session.ts # 管理员会话 CRUD (KV session:{id})、Cookie 辅助函数
│ ├── groups.ts # 分组加载、分组管理员权限范围
│ ├── home-routes.ts # 落地页路由
│ └── legal-routes.ts # 法律页面路由
│ ├── legal-routes.ts # 法律页面路由
│ └── richheader-routes.ts # GET /api/richheaderTelegram 头像卡片)
└── lib/ # 共享基础设施
├── i18n.ts # 消息语言覆盖 (en/zh)
├── send-log.ts # 发送日志 (D1 send_logs)
├── log.ts # JSON 控制台日志 (info/warn/error/fatal)
└── locales/ # en.ts、zh.ts 翻译字典
src/__tests__/ # 单元测试 (bun test)
```
## 脚本
@ -93,16 +98,17 @@ curl http://localhost:8787/health
## 添加新事件格式化器
1. 将事件类型添加到 `src/formatters/colors.ts` 中的 `GITHUB_COLORS`(如果需要新颜色)
2. 将操作标签添加到 `ACTION_LABELS`(如果有新操作)
2. 将操作标签添加到 `src/lib/locales/en.ts` 与 `src/lib/locales/zh.ts` 的翻译字典(如果有新操作)
3. 在 `src/formatters/` 中创建 `formatEventType` 函数
4. 将 case 添加到 `src/formatters/index.ts` 中的 `formatEvent` switch 语句
5. 如果事件包含分支信息,更新 `src/events/match.ts` 中的 `extractBranch`
6. 将事件添加到 `docs/events/supported.md` 文档中
7. 在 GitHub App 设置中订阅该事件
6. 将事件添加到 `docs/events/supported.md``docs/zh/events/supported.md` 文档中
7. 将事件添加到 README`README.md``README.zh.md`)的事件表与 GitHub App 事件订阅列表中
8. 在 GitHub App 设置中订阅该事件
## 拉取请求指南
- 保持变更聚焦且原子化
- 为所有函数返回值包含类型注解
- 提交前运行 `npm run typecheck && npm run lint && npm run format:check`
- 添加功能时更新文档
- 添加功能时更新文档(见 `AGENTS.md` → Documentation 的清单README`README.md` / `README.zh.md`、VitePress 文档(`docs/``docs/zh/`)以及示例配置文件

View file

@ -1,6 +1,6 @@
# 支持的事件
WebHooker 支持 23 种 GitHub webhook 事件类型,每种都有专用的格式化器,生成丰富的 Discord 嵌入消息。不支持的事件会回退到通用格式化器。
WebHooker 支持 28 种 GitHub webhook 事件类型,每种都有专用的格式化器,生成丰富的 Discord 嵌入消息与 Telegram HTML 消息。不支持的事件会回退到通用格式化器。
## 事件表
@ -11,16 +11,21 @@ WebHooker 支持 23 种 GitHub webhook 事件类型,每种都有专用的格
| `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` | 仓库已复刻 | 源 → 目标复刻 |
| `check_run` | 检查运行完成 | 状态、结论、详情 URL |
| `pull_request_review` | PR 审查已提交 | 审查状态(已批准/需修改/已评论)、正文 |
| `pull_request_review_comment` | 行内代码审查评论 | 文件路径、行号、评论内容 |
| `commit_comment` | 提交的评论 | 提交 SHA、评论内容 |
| `deployment_status` | 部署状态更新 | 环境、状态、提交引用 |
| `member` | 协作者添加/移除 | 成员登录名、操作 |
| `label` | 标签创建/编辑/删除 | 标签名称、颜色、描述 |
| `milestone` | 里程碑打开/关闭 | 进度条、议题计数、截止日期 |
@ -32,18 +37,17 @@ WebHooker 支持 23 种 GitHub webhook 事件类型,每种都有专用的格
## 颜色编码
每种事件类型在 Discord 嵌入中使用不同的颜色:
每种事件类型在 Discord 嵌入中使用不同的颜色(来自 `src/formatters/colors.ts`
| 颜色 | 事件 |
| ---------------- | ---------------------------------------------------------- |
| 绿色 (`#2ea44f`) | push、issue 打开、PR 打开、release 发布、star、member 添加 |
| 红色 (`#d73a49`) | issue 关闭、PR 关闭、deployment 失败、dependabot 严重 |
| 紫色 (`#7057ff`) | PR 合并、discussion 创建 |
| 蓝色 (`#0366d6`) | PR review 评论、issue 评论、workflow run |
| 黄色 (`#dbab09`) | PR review 请求修改、deployment 待定 |
| 青色 (`#00897b`) | check run、code scanning |
| 橙色 (`#e67e22`) | label、milestone |
| 灰色 (`#6a737d`) | delete、repository、member 移除 |
| 颜色 | 事件 |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| 绿色 (`#2da44e`) | push、PR 打开/可审查、issue 打开、工作流成功、发布已发布、检查成功、审查已批准、部署成功、成员添加、里程碑关闭、讨论已回答 |
| 红色 (`#f85149`) | PR 关闭、issue 关闭、工作流失败、发布已删除、delete、检查失败、审查请求修改、部署失败、成员移除、代码扫描/Dependabot 严重与高危 |
| 紫色 (`#8957e5`) | PR 合并、label、discussion |
| 蓝色 (`#1f6feb`) | PR其他操作、issue 重新打开、fork、里程碑打开 |
| 黄色 (`#d29922`) | 工作流(排队/运行中/其他)、预发布 release、star、检查其他、部署待定、代码扫描/Dependabot 中危 |
| 灰色 (`#6e7681`) | issue 评论、commit 评论、讨论评论 |
| 灰色 (`#8b949e`) | 审查评论、repository、代码扫描/Dependabot 低危、默认 |
## 通用回退
@ -63,11 +67,11 @@ WebHooker 支持 23 种 GitHub webhook 事件类型,每种都有专用的格
实操指南见[过滤器教程](../guide/filters),包含完整示例。
| 过滤器 | 适用事件 |
| --------- | ----------------------------------------------------------------------------------------------------------------------- |
| `event` | 所有事件 |
| `repo` | 所有事件 |
| `actor` | 所有事件 |
| `action` | 载荷中包含 `action` 字段的事件 |
| `branch` | push、pull_request、pull_request_review、pull_request_review_comment、create、delete、workflow_run、code_scanning_alert |
| `keyword` | 所有事件(搜索完整载荷正文) |
| 过滤器 | 适用事件 |
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event` | 所有事件 |
| `repo` | 所有事件 |
| `actor` | 所有事件 |
| `action` | 载荷中包含 `action` 字段的事件 |
| `branch` | push、pull_request、pull_request_review、pull_request_review_comment、create、delete、workflow_run、workflow_job、check_suite、deployment、code_scanning_alert |
| `keyword` | 所有事件(搜索完整载荷正文) |

View file

@ -9,13 +9,16 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars`
| 变量 | 说明 |
| ----------------------- | -------------------------------------------------------- |
| `GITHUB_WEBHOOK_SECRET` | GitHub App 设置中的 Webhook 密钥 |
| `GITHUB_APP_ID` | GitHub App 的数字 ID |
| `GITHUB_PRIVATE_KEY` | App 私钥PEM 格式,用 `\n` 转义) |
| `GITHUB_CLIENT_ID` | App 设置中的 OAuth 客户端 ID |
| `GITHUB_CLIENT_SECRET` | App 设置中的 OAuth 客户端密钥 |
| `DISCORD_TOKEN` | Discord Bot Token |
| `TELEGRAM_TOKEN` | Telegram Bot TokenBotFather 获取)—— Telegram 路由必需 |
> [!NOTE]
> `GITHUB_APP_ID``GITHUB_PRIVATE_KEY` 当前未被代码使用——OAuth 流程只需要
> `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`。为兼容性保留在模式中,以备日后启用
> GitHub App 认证。
### 可选密钥
| 变量 | 说明 | 默认值 |
@ -52,6 +55,7 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
| `GET /admin/api/groups/:id/routes` | 列出某分组的路由 |
| `PUT /admin/api/groups/:id/routes` | 替换某分组的路由 |
| `GET /admin/api/logs` | 发送日志(按可访问路由过滤) |
| `GET /admin/api/logs/:id` | 单条发送日志(按权限过滤) |
控制台支持新增、编辑、删除和开关路由。保存后立即写入 KV `config:routes` 并使配置缓存失效,下一次 webhook 处理即会生效。
@ -140,6 +144,7 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
| `name` | string | 是 | 可读的分组名称 |
| `adminIds` | string[] | 是 | 可管理该分组路由的 GitHub 用户 ID 或登录名 |
| `owners` | string[] | 否 | 允许事件进入该分组的组织/用户登录名;为空表示不限制 |
| `emoji` | boolean | 否 | 是否在该分组消息中显示 emoji默认 `true` |
### 权限模型
@ -167,7 +172,7 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
- 在任何过滤器上设置 `"exclude": true` 可反转匹配逻辑NOT 逻辑)
- 非 keyword 过滤器为**精确、不区分大小写**的匹配——不支持通配符(`repo: "org/*"` 不会匹配任何内容)
- `keyword` 过滤器支持正则表达式——正则有误或超过 200 个字符时回退到子串匹配
- `branch` 过滤器适用于 push、pull_request、pull_request_review、pull_request_review_comment、create/delete、workflow_run 和 code_scanning_alert 事件
- `branch` 过滤器适用于 push、pull_request、pull_request_review、pull_request_review_comment、create/delete、workflow_run、workflow_job、check_suite、deployment 和 code_scanning_alert 事件
### 匹配值
@ -180,17 +185,27 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
## KV 存储布局
| 键模式 | 值 | TTL |
| ------------------------ | --------------------------------------------------- | ------------------ |
| `config:routes` | JSON 路由数组 | 永久 |
| `config:groups` | JSON 分组数组 | 永久 |
| `session:{id}` | 管理员会话 `{ userId, login }` | 7 天 |
| `token:{userId}` | `{ userId, accessToken, expiresAt, refreshToken? }` | 0.9 × Token 有效期 |
| `token-reverse:{sha256}` | 用于按 Token 反查的用户 id | 0.9 × Token 有效期 |
| `discord-link:{userId}` | 与 Discord 用户绑定的 GitHub 用户 id | 永久 |
| `state:{hex}` | `{ redirectTo, expiresAt, discordUserId? }` | 600 秒 |
| `delivery:{id}` | Webhook 投递 id去重标记 | 300 秒 |
| `logs:send:{ts}-{hex}` | 发送记录 | 1 小时 |
| `cmd:guild:{id}` | 已注册命令的服务器 id去重标记 | 永久 |
| `cmd:registered:global` | 全局命令已注册标记24h 去重) | 1 天 |
| `config:discord-app-id` | Discord 应用 id 缓存 | 永久 |
| 键模式 | 值 | TTL |
| ------------------------------ | ----------------------------------------------------------------------------- | ------------------ |
| `config:routes` | JSON 路由数组 | 永久 |
| `config:groups` | JSON 分组数组 | 永久 |
| `session:{id}` | 管理员会话 `{ userId, login }` | 7 天 |
| `token:{userId}` | `{ userId, accessToken, expiresAt, refreshToken? }` | 0.9 × Token 有效期 |
| `token-reverse:{sha256}` | 用于按 Token 反查的用户 id | 0.9 × Token 有效期 |
| `state:{hex}` | `{ redirectTo, expiresAt, discordUserId?, telegramUserId?, telegramChatId? }` | 600 秒 |
| `delivery:{id}` | Webhook 投递 id去重标记 | 300 秒 |
| `msg:{routeId}:{key}:{target}` | 原地更新用消息 id 追踪(如 `workflow_run` | 7 天 |
| `cmd:guild:{id}` | 已注册命令的服务器 id去重标记 | 永久 |
| `cmd:registered:global` | 全局命令已注册标记24h 去重) | 1 天 |
| `config:discord-app-id` | Discord 应用 id 缓存 | 永久 |
| `i18n:{lang}` | 翻译覆盖,合并到英文之上 | 永久 |
## D1 存储布局
D1 数据库(`DB` 绑定,数据库 `webhooker`)包含三张表:
| 表 | 用途 |
| ---------------- | ---------------------------------------------------------------------- |
| `send_logs` | 每次分发尝试一行(路由 id、事件、目标、成功/失败、耗时、错误码、详情) |
| `discord_links` | 映射 `discord_user_id``github_user_id`,用于 Discord `/gh` 命令 |
| `telegram_links` | 映射 `telegram_user_id``github_user_id`,用于 Telegram `/gh` 命令 |

View file

@ -25,8 +25,6 @@ npx wrangler kv namespace create KV
```bash
npx wrangler secret put GITHUB_WEBHOOK_SECRET
npx wrangler secret put GITHUB_APP_ID
npx wrangler secret put GITHUB_PRIVATE_KEY # PKCS#8 PEMBEGIN PRIVATE KEY
npx wrangler secret put GITHUB_CLIENT_ID
npx wrangler secret put GITHUB_CLIENT_SECRET
npx wrangler secret put DISCORD_TOKEN
@ -39,15 +37,9 @@ npx wrangler secret put ADMIN_USER_IDS # 逗号分隔的 GitHub ID/登录
不存在全局频道密钥。每条路由在 [Web 控制台](/zh/guide/configuration#web-控制台) 中声明各自的目标频道(及可选的子区/thread因此不需要 `DISCORD_CHANNEL_ID`
:::
::: warning GitHub App 私钥必须是 PKCS#8
GitHub 下发的私钥为 PKCS#1 格式(`BEGIN RSA PRIVATE KEY`。Cloudflare Workers 的 JWT 签名要求 PKCS#8,需先转换:
```bash
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt \
-in your-app.private-key.pem -out gh_pk_pkcs8.pem
```
然后将 `gh_pk_pkcs8.pem` 作为 `GITHUB_PRIVATE_KEY` 上传。
::: tip GitHub App ID / 私钥未使用
`GITHUB_APP_ID``GITHUB_PRIVATE_KEY` 当前未被代码使用——OAuth 流程只需要
`GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`。无需设置(也无需进行 PKCS#8 转换)。
:::
Discord 交互通过 HTTPS Interactions Endpoint 送达,需要设置 `DISCORD_PUBLIC_KEY` 并把 **Interactions Endpoint URL** 指向 `https://your-domain/discord/interactions`。参见下方 [Interactions Endpoint](#interactions-endpoint)。
@ -79,8 +71,8 @@ Worker 现在可通过 `https://webhooker.<your-subdomain>.workers.dev` 访问
3. 设置权限:
- **Repository permissions**: Contents (read)、Issues (write)、Pull requests (write)、Metadata (read)、Checks (read)、Deployments (read)、Discussions (read)、Code scanning alerts (read)、Dependabot alerts (read)
- **Organization permissions**: Members (read) —— 如果需要
4. 订阅事件(全部 23 种支持的事件):
- Push、Pull request、Issues、Issue comment、Workflow run、Release、Create、Delete、Star、Fork、Check run、Pull request review、Pull request review comment、Commit comment、Deployment status、Member、Label、Milestone、Discussion、Discussion comment、Repository、Code scanning alert、Dependabot alert
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` 环境变量
### 2. 安装 App
@ -120,6 +112,22 @@ Worker 现在可通过 `https://webhooker.<your-subdomain>.workers.dev` 访问
用户运行 `/gh login` 绑定自己的 GitHub 账号,即可以本人身份评论 issue/PR。完整命令说明见 [README](https://github.com/ReCloudStudio/WebHooker#bot-commands-comment-on-github-as-yourself)。
## Telegram 机器人配置
1. 用 [@BotFather](https://t.me/BotFather) 创建机器人,将 Token 复制到 `TELEGRAM_TOKEN`
2. (可选)设置 `TELEGRAM_WEBHOOK_SECRET`webhook 注册时会作为 `secret_token` 传给 Telegram`POST /telegram/webhook` 使用时间安全比较校验。
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
头像使用内置 `GET /api/richheader` 渲染为链接预览卡片(可用 `TELEGRAM_RICH_HEADER_HOST` 覆盖)。
## 自定义域名(可选)
要使用自定义域名替代 `*.workers.dev`
@ -128,13 +136,5 @@ Worker 现在可通过 `https://webhooker.<your-subdomain>.workers.dev` 访问
2. 添加自定义域名或路由
3. 更新 `BASE_URL` 以匹配
## Docker
提供 Dockerfile 用于容器化部署(例如在反向代理后面):
```bash
docker build -t webhooker .
docker run -p 8787:8787 --env-file .env webhooker
```
注意Docker 模式下不包含 KV 等 Cloudflare 存储。完整功能请使用 Cloudflare 部署。
> [!NOTE]
> 本项目是一个 Cloudflare Worker依赖 `wrangler.jsonc` 中声明的 KV 与 D1 绑定,无法作为独立的 Node/容器进程运行。

View file

@ -84,13 +84,16 @@
匹配事件涉及的分支。何种字段算作「分支」取决于事件类型:
| 事件 | 提取的分支 |
| --------------------------- | ------------------------------ |
| `push` | 推送到的目标分支 |
| `pull_request`(及 review | 拉取请求的 **head**(源)分支 |
| `create` / `delete` | 创建/删除的分支或标签 |
| `workflow_run` | 工作流运行所在的 `head_branch` |
| `code_scanning_alert` | 告警所属的分支 |
| 事件 | 提取的分支 |
| --------------------------- | ----------------------------------- |
| `push` | 推送到的目标分支 |
| `pull_request`(及 review | 拉取请求的 **head**(源)分支 |
| `create` / `delete` | 创建/删除的分支或标签 |
| `workflow_run` | 工作流运行所在的 `head_branch` |
| `workflow_job` | 作业运行所在的 `head_branch` |
| `check_suite` | 检查套件的 `head_branch` |
| `deployment` | 部署引用(去除 `refs/heads/` 前缀) |
| `code_scanning_alert` | 告警所属的分支 |
```json
{

View file

@ -29,8 +29,6 @@ cp .env.example .dev.vars
```bash
GITHUB_WEBHOOK_SECRET=your-webhook-secret
GITHUB_APP_ID=your-app-id
GITHUB_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
GITHUB_CLIENT_ID=your-client-id
GITHUB_CLIENT_SECRET=your-client-secret
DISCORD_TOKEN=your-bot-token
@ -40,7 +38,7 @@ BASE_URL=http://localhost:8787
```
::: tip
`GITHUB_PRIVATE_KEY` 必须是 **PKCS#8** 格式(`BEGIN PRIVATE KEY`)。用 `openssl pkcs8 -nocrypt -in app.pem -out pkcs8.pem` 转换 GitHub 下发的 PKCS#1 私钥。目标频道在 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` 未被代码使用OAuth 流程只需要 Client ID/Secret可省略。目标频道在 Web UI 中按路由设置,因此不需要 `DISCORD_CHANNEL_ID`。若要在本地启用 `/gh` 命令,请在开发者门户复制 **Public Key** 填入 `DISCORD_PUBLIC_KEY`,并把 Interactions Endpoint URL 设为 `http://localhost:8787/discord/interactions`
:::
::: warning

View file

@ -1,27 +1,29 @@
# 简介
WebHooker 是一个基于 Cloudflare Workers 构建的 GitHub webhook 调度器。它接收 GitHub webhook 事件,应用可配置的过滤器,将事件格式化为丰富的 Discord 嵌入消息,并通过 Discord REST API 投递到 Discord 频道或帖子。Discord 内的 `/gh` 交互通过 HTTPS Interactions EndpointEd25519 验签)送达。路由通过内置的 Web UI 管理。
WebHooker 是一个基于 Cloudflare Workers 构建的 GitHub webhook 调度器。它接收 GitHub webhook 事件,应用可配置的过滤器,将事件格式化为富消息,并通过各自 REST API 投递到 Discord 频道/子区embed与 Telegram 群组/话题HTML。Discord 内的 `/gh` 交互通过 HTTPS Interactions EndpointEd25519 验签送达Telegram 的 `/gh` 命令通过 Telegram webhook 送达。路由与分组通过内置的 Web UI 管理。
## 架构
```text
GitHub Webhook → Cloudflare Worker (Hono)
├── POST /webhook → 验证 → 去重 → 过滤 → 格式化 → Discord (REST API)
├── POST /webhook → 验证 → 去重 → 过滤 → 格式化 → Discord (REST) / Telegram (Bot API)
├── POST /discord/interactions → 验证 (Ed25519) → 处理 /gh 斜杠与右键命令
├── POST /telegram/webhook → 验证 (secret token) → 处理 /gh 命令
├── GET /auth/github → OAuth 流程
├── GET /api/richheader → Telegram 头像链接预览卡片
├── POST /api/* → 用户操作 (Bearer Token 鉴权)
├── /admin → 路由与发送日志 Web UI管理员会话
├── /admin → 路由、分组与发送日志 Web UI管理员会话
└── GET /health → 健康检查
POST /discord/interactions → 验证 (Ed25519) → 处理 /gh 斜杠与右键命令
```
### 组件
| 组件 | 职责 |
| ------------------------- | --------------------------------------------------------------------------------------------------------- |
| **Cloudflare Worker** | HTTP 入口、签名验证、投递去重、事件解析、路由匹配、REST 发送 |
| **Interactions Endpoint** | 验证 Ed25519 签名并处理 `/gh` 交互斜杠命令、右键菜单、按钮、modal |
| **KV** | Token 存储 (`token:{userId}`)、OAuth 状态 (`state:{hex}`)、路由配置 (`config:routes`)、发送日志、投递去重 |
| 组件 | 职责 |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Cloudflare Worker** | HTTP 入口、签名验证、投递去重、事件解析、路由匹配、平台分发 |
| **Interactions Endpoint** | 验证 Ed25519 签名并处理 `/gh` 交互斜杠命令、右键菜单、按钮、modal |
| **KV** | Token 存储 (`token:{userId}`)、OAuth 状态 (`state:{hex}`)、路由配置 (`config:routes`)、分组配置 (`config:groups`)、管理员会话、投递去重、消息更新追踪 (`msg:*`) |
| **D1** | 发送日志 (`send_logs`)、Discord↔GitHub 绑定 (`discord_links`)、Telegram↔GitHub 绑定 (`telegram_links`) |
### 数据流
@ -29,18 +31,19 @@ POST /discord/interactions → 验证 (Ed25519) → 处理 /gh 斜杠与右键
2. Worker 验证 HMAC-SHA256 签名
3. Worker 按 `X-GitHub-Delivery` 去重KV短 TTL丢弃重复投递
4. Worker 解析事件类型和载荷
5. 根据过滤器评估路由event、repo、actor、action、branch、keyword
6. 匹配的路由触发格式化器函数生成 Discord 嵌入消息
7. 每条消息通过 Discord REST API 发送到对应路由的目标频道/帖子,并处理速率限制重试,结果记录到发送日志
5. 根据过滤器event、repo、actor、action、branch、keyword与分组所有者限制评估路由
6. 匹配的路由触发格式化器函数生成平台中立消息
7. 每条消息通过 Discord 或 Telegram REST API 发送到对应路由的目标,并处理速率限制重试;`workflow_run` 进度原地更新。每次尝试都记录到 D1 发送日志
## 技术栈
- **运行时**: Cloudflare Workers
- **HTTP 框架**: Hono
- **Discord 投递**: Discord REST API交互通过 Ed25519 验签的 HTTPS Interactions Endpoint
- **Telegram 投递**: Telegram Bot APIwebhook 带可选 secret-token 校验)
- **Web UI**: Nuxt 3 静态 SPA由 Worker 资源托管
- **存储**: Cloudflare KV
- **鉴权**: Web Crypto API (HMAC-SHA256)、jose (JWT)、octokit (GitHub API)
- **存储**: Cloudflare KV + D1
- **鉴权**: Web Crypto API (HMAC-SHA256、Ed25519)、octokit (GitHub API)、jose依赖
- **语言**: TypeScript
## 许可证

View file

@ -4,7 +4,7 @@ layout: home
hero:
name: WebHooker
text: GitHub Webhook → Discord
tagline: 通过 Cloudflare Workers 接收 GitHub 事件,应用过滤器,将格式化消息路由到 Discord 频道或帖子
tagline: 通过 Cloudflare Workers 接收 GitHub 事件,应用过滤器,将格式化消息路由到 Discord 频道/子区与 Telegram 群组/话题
actions:
- theme: brand
text: 快速开始
@ -14,16 +14,16 @@ hero:
link: https://github.com/ReCloudStudio/WebHooker
features:
- title: 23 种事件格式化器
details: 为 push、pull_request、issues、release、workflow_run 及其他 18 种事件类型提供丰富的 Discord 嵌入消息,支持颜色编码输出。
- title: 28 种事件格式化器
details: 为 push、pull_request、issues、release、workflow_run 及其他 23 种事件类型提供丰富的 Discord 嵌入与 Telegram HTML 消息,支持颜色编码输出。
- title: 灵活的过滤器
details: 支持按事件类型、仓库、参与者、操作、分支(含 PR和关键字支持正则过滤。支持排除模式。
- title: Cloudflare Workers
details: 运行在 Cloudflare 边缘网络上。通过 Discord REST API 发送消息,并通过 Ed25519 验签的 Interactions Endpoint 支持 `/gh` 命令。
- title: Web UI 与斜杠命令
details: "在内置管理控制台中管理路由、查看发送日志。绑定你的 GitHub 账号,通过 /gh 命令以本人身份评论 issue/PR。"
details: 运行在 Cloudflare 边缘网络上。通过 Discord REST API 与 Telegram Bot API 发送消息,并通过 Ed25519 验签的 Interactions Endpoint 支持 `/gh` 命令。
- title: Web UI、分组与命令
details: "在内置管理控制台中管理路由、分组与发送日志。绑定你的 GitHub 账号,通过 /gh 命令以本人身份评论 issue/PRDiscord 或 Telegram。"
- title: 签名验证
details: 使用 Web Crypto API 进行 HMAC-SHA256 webhook 签名验证与 Ed25519 交互签名验证,支持时间安全比较。
- title: 优雅降级
details: 当 Discord Token 不可用时以 webhook-only 模式运行。提供健康检查端点用于监控
- title: 原地更新
details: workflow_run 进度在运行推进时于同一条消息上原地更新Discord 与 Telegram 均支持
---