mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
feat: add gitea/forgejo support
This commit is contained in:
parent
ace036c209
commit
aec0d1a257
43 changed files with 683 additions and 130 deletions
|
|
@ -13,7 +13,7 @@ https://your-worker.workers.dev
|
|||
| 方法 | 路径 | 鉴权 | 说明 |
|
||||
| -------- | ------------------------------ | ------------ | ------------------------------------------------ |
|
||||
| `GET` | `/health` | 无 | 健康检查 |
|
||||
| `POST` | `/webhook` | HMAC 签名 | GitHub webhook 接入 |
|
||||
| `POST` | `/webhook` | HMAC 签名 | GitHub / Gitea webhook 接入(自动识别来源) |
|
||||
| `POST` | `/discord/interactions` | Ed25519 签名 | Discord 交互(斜杠命令、按钮、modal) |
|
||||
| `POST` | `/telegram/webhook` | Secret token | Telegram 更新(bot `/gh` 命令) |
|
||||
| `GET` | `/api/richheader` | 无 | 用于 Telegram 头像链接预览卡片的 Open Graph 页面 |
|
||||
|
|
|
|||
|
|
@ -20,10 +20,13 @@ src/
|
|||
├── server.ts # Hono 应用: /health、/webhook、/discord/interactions、/telegram/webhook,挂载 /auth、/admin + /
|
||||
├── core/
|
||||
│ └── dispatch.ts # 平台中立分发:匹配路由 → formatEvent → getDriver().send/edit
|
||||
├── events/ # GitHub webhook 事件流水线:验证签名、解析事件、匹配路由
|
||||
│ ├── verify.ts # HMAC 签名验证 (Web Crypto,时间安全)
|
||||
│ ├── parse.ts # parseEvent (headers + body → WebhookEvent)
|
||||
├── events/ # 与提供方无关的路由匹配
|
||||
│ └── match.ts # matchRoute、eventOwners、extractBranch、关键词过滤
|
||||
├── providers/ # Forge webhook 提供方(验证 + 解析/归一化)
|
||||
│ ├── types.ts # Provider 接口(matches/verify/parse)
|
||||
│ ├── index.ts # detectProvider() 注册表(github、gitea)
|
||||
│ ├── github/ # X-GitHub-Event + X-Hub-Signature-256
|
||||
│ └── gitea/ # X-Gitea-Event + X-Gitea-Signature(归一化载荷)
|
||||
├── formatters/ # 平台中立格式化器(产出 NeutralMessage)
|
||||
│ ├── index.ts # formatEvent:28 事件 switch → NeutralMessage + re-export
|
||||
│ ├── colors.ts # GITHUB_COLORS + WORKFLOW_CONCLUSION_EMOJI
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars`
|
|||
| 变量 | 说明 |
|
||||
| ----------------------- | -------------------------------------------------------- |
|
||||
| `GITHUB_WEBHOOK_SECRET` | GitHub App 设置中的 Webhook 密钥 |
|
||||
| `GITEA_WEBHOOK_SECRET` | Gitea 实例的 Webhook 密钥(仅接收 Gitea webhook 时需要) |
|
||||
| `GITHUB_CLIENT_ID` | App 设置中的 OAuth 客户端 ID |
|
||||
| `GITHUB_CLIENT_SECRET` | App 设置中的 OAuth 客户端密钥 |
|
||||
| `DISCORD_TOKEN` | Discord Bot Token |
|
||||
|
|
@ -30,6 +31,17 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars`
|
|||
| `TELEGRAM_WEBHOOK_SECRET` | `POST /telegram/webhook` 验签密钥(X-Telegram-Bot-Api-Secret-Token) | 未设置时不校验 |
|
||||
| `TELEGRAM_RICH_HEADER_HOST` | 外部 rich-header 服务的基础 URL;未设置时使用内置的 `GET /api/richheader` 生成 Telegram 头像卡片 | 内置 `/api/richheader` |
|
||||
|
||||
## Webhook 提供方
|
||||
|
||||
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` |
|
||||
|
||||
Gitea payload 会被归一化为与 GitHub 相同的内部结构,因此路由、过滤器与 28 个格式化器无需改动即可复用;未知或未映射的 Gitea 事件回退到通用格式化器。仓库/提交/用户链接基于 payload 的 `repository.html_url` 生成,会指向你的 Gitea 实例。
|
||||
|
||||
## Web 控制台
|
||||
|
||||
WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理路由。它由 GitHub OAuth 和管理员白名单保护。
|
||||
|
|
@ -156,17 +168,19 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
"id": "backend-team",
|
||||
"name": "后端团队",
|
||||
"adminIds": ["rhencloud"],
|
||||
"owners": ["myorg"]
|
||||
"owners": ["myorg"],
|
||||
"providers": ["github", "gitea"]
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 必需 | 说明 |
|
||||
| ---------- | -------- | ---- | ----------------------------------------------------- |
|
||||
| `id` | string | 是 | 小写 id(`a-z0-9`、`-`),由每条路由的 `groupId` 引用 |
|
||||
| `name` | string | 是 | 可读的分组名称 |
|
||||
| `adminIds` | string[] | 是 | 可管理该分组路由的 GitHub 用户 ID 或登录名 |
|
||||
| `owners` | string[] | 否 | 允许事件进入该分组的组织/用户登录名;为空表示不限制 |
|
||||
| `emoji` | boolean | 否 | 是否在该分组消息中显示 emoji(默认 `true`) |
|
||||
| 字段 | 类型 | 必需 | 说明 |
|
||||
| ----------- | -------- | ---- | ----------------------------------------------------------- |
|
||||
| `id` | string | 是 | 小写 id(`a-z0-9`、`-`),由每条路由的 `groupId` 引用 |
|
||||
| `name` | string | 是 | 可读的分组名称 |
|
||||
| `adminIds` | string[] | 是 | 可管理该分组路由的 GitHub 用户 ID 或登录名 |
|
||||
| `owners` | string[] | 否 | 允许事件进入该分组的组织/用户登录名;为空表示不限制 |
|
||||
| `providers` | string[] | 否 | 允许进入该分组的来源平台(`github`、`gitea`);为空表示全部 |
|
||||
| `emoji` | boolean | 否 | 是否在该分组消息中显示 emoji(默认 `true`) |
|
||||
|
||||
### 权限模型
|
||||
|
||||
|
|
@ -174,6 +188,7 @@ WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理
|
|||
- **分组管理员**(`adminIds`)只能查看和编辑其管理的分组;提交其分组之外的路由返回 `403`。
|
||||
- 分组管理端点通过 `/admin/api/groups/:id/routes` 一次只操作一个分组;`groupId` 由路径参数强制指定。
|
||||
- `owners` 列表限定哪些事件参与者(发送者登录名)的事件会被该分组的路由投递。
|
||||
- `providers` 列表限定哪个 forge(`github`、`gitea`)的事件会被该分组的路由投递。即使组织/用户同名,也可以借此将 GitHub 与 Gitea 分组区分开。
|
||||
|
||||
## 过滤器类型
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,14 @@ Worker 现在可通过 `https://webhooker.<your-subdomain>.workers.dev` 访问
|
|||
2. 设置 **Webhook URL** 为 `https://webhooker.<your-subdomain>.workers.dev/webhook`
|
||||
3. 设置 **Webhook secret** 与 `GITHUB_WEBHOOK_SECRET` 一致
|
||||
|
||||
### 6.(可选)配置 Gitea Webhook
|
||||
|
||||
1. 在 Gitea 仓库中进入 **设置 → Web 钩子 → 添加 Web 钩子 → Gitea**
|
||||
2. 设置 **目标 URL** 为 `https://webhooker.<your-subdomain>.workers.dev/webhook`
|
||||
3. 设置 **HTTP 方法** 为 `POST`、**Content Type** 为 `application/json`
|
||||
4. 设置 **密钥** 与 `GITEA_WEBHOOK_SECRET` 一致
|
||||
5. 选择要触发的事件(push、议题、拉取请求、发布等)
|
||||
|
||||
## GitHub App 设置
|
||||
|
||||
### 1. 创建 App
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# 简介
|
||||
|
||||
WebHooker 是一个基于 Cloudflare Workers 构建的 GitHub webhook 调度器。它接收 GitHub webhook 事件,应用可配置的过滤器,将事件格式化为富消息,并通过各自 REST API 投递到 Discord 频道/子区(embed)与 Telegram 群组/话题(HTML)。Discord 内的 `/gh` 交互通过 HTTPS Interactions Endpoint(Ed25519 验签)送达;Telegram 的 `/gh` 命令通过 Telegram webhook 送达。路由与分组通过内置的 Web UI 管理。
|
||||
WebHooker 是一个基于 Cloudflare Workers 构建的 GitHub/Gitea webhook 调度器。它接收来自受支持 forge(GitHub、Gitea——更多可通过 `src/providers/` 扩展)的 webhook 事件,应用可配置的过滤器,将事件格式化为富消息,并通过各自 REST API 投递到 Discord 频道/子区(embed)与 Telegram 群组/话题(HTML)。Discord 内的 `/gh` 交互通过 HTTPS Interactions Endpoint(Ed25519 验签)送达;Telegram 的 `/gh` 命令通过 Telegram webhook 送达。路由与分组通过内置的 Web UI 管理。
|
||||
|
||||
## 架构
|
||||
|
||||
```text
|
||||
GitHub Webhook → Cloudflare Worker (Hono)
|
||||
├── POST /webhook → 验证 → 去重 → 过滤 → 格式化 → Discord (REST) / Telegram (Bot API)
|
||||
GitHub / Gitea Webhook → Cloudflare Worker (Hono)
|
||||
├── POST /webhook → 识别提供方 → 验证 → 去重 → 过滤 → 格式化 → Discord (REST) / Telegram (Bot API)
|
||||
├── POST /discord/interactions → 验证 (Ed25519) → 处理 /gh 斜杠与右键命令
|
||||
├── POST /telegram/webhook → 验证 (secret token) → 处理 /gh 命令
|
||||
├── GET /auth/github → OAuth 流程
|
||||
|
|
@ -27,10 +27,10 @@ GitHub Webhook → Cloudflare Worker (Hono)
|
|||
|
||||
### 数据流
|
||||
|
||||
1. GitHub 发送 webhook 到 `POST /webhook`
|
||||
2. Worker 验证 HMAC-SHA256 签名
|
||||
3. Worker 按 `X-GitHub-Delivery` 去重(KV,短 TTL),丢弃重复投递
|
||||
4. Worker 解析事件类型和载荷
|
||||
1. 某个 forge(GitHub 或 Gitea)发送 webhook 到 `POST /webhook`
|
||||
2. Worker 根据请求头识别提供方(`X-GitHub-Event` / `X-Gitea-Event`)并验证对应提供的 HMAC-SHA256 签名
|
||||
3. Worker 按投递 ID 去重(KV,短 TTL),丢弃重复投递
|
||||
4. Worker 解析事件类型并将载荷归一化为 GitHub 形状的事件
|
||||
5. 根据过滤器(event、repo、actor、action、branch、keyword)与分组所有者限制评估路由
|
||||
6. 匹配的路由触发格式化器函数生成平台中立消息
|
||||
7. 每条消息通过 Discord 或 Telegram REST API 发送到对应路由的目标,并处理速率限制重试;`workflow_run` 进度原地更新。每次尝试都记录到 D1 发送日志
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ layout: home
|
|||
|
||||
hero:
|
||||
name: WebHooker
|
||||
text: GitHub Webhook → Discord
|
||||
tagline: 通过 Cloudflare Workers 接收 GitHub 事件,应用过滤器,将格式化消息路由到 Discord 频道/子区与 Telegram 群组/话题。
|
||||
text: GitHub / Gitea Webhook → Discord
|
||||
tagline: 通过 Cloudflare Workers 接收 GitHub 与 Gitea 事件,应用过滤器,将格式化消息路由到 Discord 频道/子区与 Telegram 群组/话题。
|
||||
actions:
|
||||
- theme: brand
|
||||
text: 快速开始
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue