mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
initial commit
This commit is contained in:
commit
512d4b01d5
55 changed files with 6430 additions and 0 deletions
111
docs/zh/api/actions.md
Normal file
111
docs/zh/api/actions.md
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
# 用户操作
|
||||
|
||||
用户操作端点支持评论议题、合并 PR 和添加反应。所有操作端点都需要来自 OAuth 流程的有效 Bearer Token。
|
||||
|
||||
## 鉴权
|
||||
|
||||
所有操作端点都需要 `Authorization` 头:
|
||||
|
||||
```
|
||||
Authorization: Bearer <github-access-token>
|
||||
```
|
||||
|
||||
如果 Token 缺失或无效,端点返回 `401`。
|
||||
|
||||
## 端点
|
||||
|
||||
### 评论议题
|
||||
|
||||
```
|
||||
POST /api/comment
|
||||
```
|
||||
|
||||
在议题或拉取请求上创建评论。
|
||||
|
||||
**请求体:**
|
||||
|
||||
```json
|
||||
{
|
||||
"owner": "org",
|
||||
"repo": "repo",
|
||||
"issueNumber": 42,
|
||||
"body": "评论内容"
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 必需 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `owner` | string | 是 | 仓库所有者 |
|
||||
| `repo` | string | 是 | 仓库名称 |
|
||||
| `issueNumber` | number | 是 | 议题或 PR 编号 |
|
||||
| `body` | string | 是 | 评论内容(支持 Markdown) |
|
||||
|
||||
**响应:** `200` 与 GitHub API 响应。
|
||||
|
||||
### 合并拉取请求
|
||||
|
||||
```
|
||||
POST /api/merge
|
||||
```
|
||||
|
||||
合并拉取请求。
|
||||
|
||||
**请求体:**
|
||||
|
||||
```json
|
||||
{
|
||||
"owner": "org",
|
||||
"repo": "repo",
|
||||
"pullNumber": 42,
|
||||
"mergeMethod": "squash"
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 必需 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `owner` | string | 是 | 仓库所有者 |
|
||||
| `repo` | string | 是 | 仓库名称 |
|
||||
| `pullNumber` | number | 是 | 拉取请求编号 |
|
||||
| `mergeMethod` | string | 否 | `merge`、`squash` 或 `rebase`(默认:`merge`) |
|
||||
|
||||
**响应:** `200` 与 GitHub 合并响应。
|
||||
|
||||
### 添加反应
|
||||
|
||||
```
|
||||
POST /api/react
|
||||
```
|
||||
|
||||
为议题或评论添加表情反应。
|
||||
|
||||
**请求体:**
|
||||
|
||||
```json
|
||||
{
|
||||
"owner": "org",
|
||||
"repo": "repo",
|
||||
"issueNumber": 42,
|
||||
"content": "rocket"
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 必需 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `owner` | string | 是 | 仓库所有者 |
|
||||
| `repo` | string | 是 | 仓库名称 |
|
||||
| `issueNumber` | number | 是 | 议题、PR 或评论编号 |
|
||||
| `content` | string | 是 | 反应类型(见下方) |
|
||||
|
||||
**反应类型:**
|
||||
|
||||
`+1`、`-1`、`laugh`、`confused`、`heart`、`hooray`、`rocket`、`eyes`
|
||||
|
||||
**响应:** `200` 与 GitHub 反应响应。
|
||||
|
||||
## 错误响应
|
||||
|
||||
| 状态码 | 响应体 | 原因 |
|
||||
| --- | --- | --- |
|
||||
| `401` | `{"error": "Unauthorized"}` | 缺少或无效的 Bearer Token |
|
||||
| `400` | `{"error": "..."}` | 无效的请求体 |
|
||||
| `500` | `{"error": "..."}` | GitHub API 错误 |
|
||||
85
docs/zh/api/oauth.md
Normal file
85
docs/zh/api/oauth.md
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# OAuth
|
||||
|
||||
WebHooker 实现 GitHub OAuth2 以支持用户发起的操作(评论、合并、反应)。
|
||||
|
||||
## 流程
|
||||
|
||||
```text
|
||||
用户 → GET /auth/github → 重定向到 GitHub → 授权 →
|
||||
→ GET /auth/github/callback → 交换 code 获取 Token → 存储到 KV
|
||||
```
|
||||
|
||||
## 端点
|
||||
|
||||
### 启动 OAuth
|
||||
|
||||
```
|
||||
GET /auth/github
|
||||
```
|
||||
|
||||
将用户重定向到 GitHub 的授权页面。
|
||||
|
||||
**查询参数:**
|
||||
|
||||
| 参数 | 说明 |
|
||||
| --- | --- |
|
||||
| `userId` | 你的应用用户标识符 |
|
||||
|
||||
**响应:** `302` 重定向到 GitHub OAuth 授权 URL。
|
||||
|
||||
### OAuth 回调
|
||||
|
||||
```
|
||||
GET /auth/github/callback
|
||||
```
|
||||
|
||||
GitHub 授权后重定向到此地址。将 code 交换为访问令牌并存储到 KV。
|
||||
|
||||
**查询参数(来自 GitHub):**
|
||||
|
||||
| 参数 | 说明 |
|
||||
| --- | --- |
|
||||
| `code` | 授权码 |
|
||||
| `state` | CSRF 保护的状态参数 |
|
||||
|
||||
**响应:** 重定向到你的 `BASE_URL`,附带成功/失败指示。
|
||||
|
||||
### 撤销 Token
|
||||
|
||||
```
|
||||
DELETE /auth/token/:userId
|
||||
```
|
||||
|
||||
删除用户存储的 OAuth Token。
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true
|
||||
}
|
||||
```
|
||||
|
||||
## Token 存储
|
||||
|
||||
Token 以键模式 `token:{userId}` 存储在 KV 中:
|
||||
|
||||
```json
|
||||
{
|
||||
"accessToken": "gho_...",
|
||||
"expiresAt": "2025-01-01T00:00:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
Token 会根据 `expiresAt` 时间戳自动过期。
|
||||
|
||||
## 使用 Token
|
||||
|
||||
OAuth 完成后,在操作 API 调用的 `Authorization` 头中包含访问令牌:
|
||||
|
||||
```bash
|
||||
curl -X POST https://your-worker/api/comment \
|
||||
-H "Authorization: Bearer gho_..." \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"owner": "org", "repo": "repo", "issueNumber": 1, "body": "你好!"}'
|
||||
```
|
||||
80
docs/zh/api/overview.md
Normal file
80
docs/zh/api/overview.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# API 概览
|
||||
|
||||
WebHooker 通过 Hono 在 Cloudflare Workers 上提供 HTTP API。
|
||||
|
||||
## 基础 URL
|
||||
|
||||
```
|
||||
https://your-worker.workers.dev
|
||||
```
|
||||
|
||||
## 端点
|
||||
|
||||
| 方法 | 路径 | 鉴权 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `GET` | `/health` | 无 | 健康检查 |
|
||||
| `POST` | `/webhook` | HMAC 签名 | GitHub webhook 接入 |
|
||||
| `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/react` | Bearer Token | 添加议题反应 |
|
||||
|
||||
## 健康检查
|
||||
|
||||
```
|
||||
GET /health
|
||||
```
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
## Webhook 接入
|
||||
|
||||
```
|
||||
POST /webhook
|
||||
```
|
||||
|
||||
接受 GitHub webhook 载荷。需要有效的 `X-Hub-Signature-256` 头部。
|
||||
|
||||
**请求头:**
|
||||
|
||||
| 头部 | 必需 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `X-Hub-Signature-256` | 是 | HMAC-SHA256 签名 |
|
||||
| `X-GitHub-Event` | 是 | 事件类型名称 |
|
||||
| `X-GitHub-Delivery` | 是 | 唯一投递 ID |
|
||||
|
||||
**请求体:** GitHub webhook JSON 载荷(最大 1MB)。
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true
|
||||
}
|
||||
```
|
||||
|
||||
**错误响应:**
|
||||
|
||||
| 状态码 | 响应体 | 原因 |
|
||||
| --- | --- | --- |
|
||||
| `401` | `{"error": "Invalid signature"}` | 签名验证失败 |
|
||||
| `400` | `{"error": "Invalid event"}` | 缺少事件头或格式错误的请求体 |
|
||||
| `413` | `{"error": "Request too large"}` | 请求体超过 1MB 限制 |
|
||||
|
||||
## 错误格式
|
||||
|
||||
所有错误响应都遵循以下格式:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "错误的说明"
|
||||
}
|
||||
```
|
||||
81
docs/zh/contributing.md
Normal file
81
docs/zh/contributing.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# 贡献
|
||||
|
||||
## 开发环境设置
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ReCloudStudio/WebHooker.git
|
||||
cd WebHooker
|
||||
npm install
|
||||
cp .env.example .dev.vars # 填入密钥
|
||||
npm run dev # 启动本地开发服务器
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
```text
|
||||
src/
|
||||
├── index.ts # CF Workers 入口 (fetch + scheduled),导出 DiscordGateway DO
|
||||
├── types.ts # Env、Config、Route、Filter、WebhookEvent、FormattedMessage
|
||||
├── config.ts # 从 KV 加载路由(回退到 7 条默认),从 env 构建 Config
|
||||
├── server.ts # Hono 应用: /health、/webhook,挂载 /auth + /
|
||||
├── webhook.ts # HMAC 验证 (Web Crypto)、parseEvent、extractBranch、matchRoute
|
||||
├── discord.ts # 通过 DO RPC 分发、initGateway (scheduled)
|
||||
├── discord-gateway.ts # Durable Object: Discord Gateway WS、心跳、频道缓存、发送
|
||||
├── formatter.ts # 23 种事件格式化器 + 通用回退
|
||||
├── github-oauth.ts # OAuth URL、回调 Token 交换、getUserOctokit
|
||||
├── oauth-routes.ts # GET /auth/github、回调、DELETE /token/:userId (KV 状态)
|
||||
├── action-routes.ts # POST /api/comment|merge|react (通过 KV 查找进行 Bearer Token 鉴权)
|
||||
├── token-store.ts # 基于 KV 的 Token CRUD,带 findUserIdByToken 反向查找
|
||||
└── log.ts # JSON 控制台日志 (info/warn/error/fatal)
|
||||
```
|
||||
|
||||
## 脚本
|
||||
|
||||
| 命令 | 说明 |
|
||||
| --- | --- |
|
||||
| `npm run dev` | 启动 wrangler dev 服务器 |
|
||||
| `npm run typecheck` | TypeScript 类型检查 |
|
||||
| `npm run lint` | ESLint (TypeScript) |
|
||||
| `npm run lint:md` | Markdownlint (Markdown) |
|
||||
| `npm run format` | 使用 Prettier 格式化所有文件 |
|
||||
| `npm run format:check` | 检查 Prettier 格式 |
|
||||
| `npm run docs:dev` | 启动 VitePress 文档开发服务器 |
|
||||
| `npm run docs:build` | 构建文档站点 |
|
||||
|
||||
## 代码风格
|
||||
|
||||
- **TypeScript** 严格模式
|
||||
- **双引号** 字符串
|
||||
- **分号** 必需
|
||||
- **尾逗号** 所有位置
|
||||
- **100 字符** 打印宽度
|
||||
- **ESLint** 使用 `@typescript-eslint` 推荐规则
|
||||
- **Prettier** 格式化
|
||||
- **Markdownlint** 用于 Markdown 文件
|
||||
|
||||
## 测试
|
||||
|
||||
```bash
|
||||
# 功能测试(需要正在运行的 wrangler dev)
|
||||
bash /tmp/test-webhooker.sh
|
||||
|
||||
# 或手动
|
||||
curl http://localhost:8787/health
|
||||
```
|
||||
|
||||
## 添加新事件格式化器
|
||||
|
||||
1. 将事件类型添加到 `formatter.ts` 中的 `GITHUB_COLORS`(如果需要新颜色)
|
||||
2. 将操作标签添加到 `ACTION_LABELS`(如果有新操作)
|
||||
3. 在 `formatter.ts` 中创建 `formatEventType` 函数
|
||||
4. 将 case 添加到 `formatEvent` switch 语句
|
||||
5. 如果事件包含分支信息,更新 `webhook.ts` 中的 `extractBranch`
|
||||
6. 将事件添加到 `docs/events/supported.md` 文档中
|
||||
7. 在 GitHub App 设置中订阅该事件
|
||||
|
||||
## 拉取请求指南
|
||||
|
||||
- 保持变更聚焦且原子化
|
||||
- 为所有函数返回值包含类型注解
|
||||
- 提交前运行 `npm run typecheck && npm run lint && npm run format:check`
|
||||
- 添加功能时更新文档
|
||||
67
docs/zh/events/supported.md
Normal file
67
docs/zh/events/supported.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# 支持的事件
|
||||
|
||||
WebHooker 支持 23 种 GitHub webhook 事件类型,每种都有专用的格式化器,生成丰富的 Discord 嵌入消息。不支持的事件会回退到通用格式化器。
|
||||
|
||||
## 事件表
|
||||
|
||||
| 事件 | 说明 | 嵌入亮点 |
|
||||
| --- | --- | --- |
|
||||
| `push` | 代码推送到分支 | 提交列表、分支、作者、差异统计 |
|
||||
| `pull_request` | PR 打开/关闭/合并/编辑 | PR 标题、分支、差异统计、标签 |
|
||||
| `issues` | 议题打开/关闭/编辑 | 议题标题、标签、指派人 |
|
||||
| `issue_comment` | 议题或 PR 的评论 | 评论内容、议题引用 |
|
||||
| `workflow_run` | CI/CD 工作流完成 | 工作流状态、结论、耗时 |
|
||||
| `release` | 发布创建/编辑 | 标签、内容、附件、预发布标记 |
|
||||
| `create` | 分支或标签已创建 | 引用名称、引用类型 |
|
||||
| `delete` | 分支或标签已删除 | 引用名称、引用类型 |
|
||||
| `star` | 仓库加星/取消星标 | 星标数、操作 |
|
||||
| `fork` | 仓库已复刻 | 源 → 目标复刻 |
|
||||
| `check_run` | 检查运行完成 | 状态、结论、详情 URL |
|
||||
| `pull_request_review` | PR 审查已提交 | 审查状态(已批准/需修改/已评论)、正文 |
|
||||
| `pull_request_review_comment` | 行内代码审查评论 | 文件路径、行号、评论内容 |
|
||||
| `commit_comment` | 提交的评论 | 提交 SHA、评论内容 |
|
||||
| `deployment_status` | 部署状态更新 | 环境、状态、提交引用 |
|
||||
| `member` | 协作者添加/移除 | 成员登录名、操作 |
|
||||
| `label` | 标签创建/编辑/删除 | 标签名称、颜色、描述 |
|
||||
| `milestone` | 里程碑打开/关闭 | 进度条、议题计数、截止日期 |
|
||||
| `discussion` | 讨论创建/回答 | 标题、分类、操作 |
|
||||
| `discussion_comment` | 讨论的评论 | 评论内容、讨论引用 |
|
||||
| `repository` | 仓库重命名/转移 | 旧 → 新名称、变更 |
|
||||
| `code_scanning_alert` | 代码扫描告警 | 严重程度、规则 ID、文件路径 |
|
||||
| `dependabot_alert` | Dependabot 告警 | 严重程度、包、受影响版本、修复版本 |
|
||||
|
||||
## 颜色编码
|
||||
|
||||
每种事件类型在 Discord 嵌入中使用不同的颜色:
|
||||
|
||||
| 颜色 | 事件 |
|
||||
| --- | --- |
|
||||
| 绿色 (`#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 移除 |
|
||||
|
||||
## 通用回退
|
||||
|
||||
没有专用格式化器的事件类型会回退到通用格式化器,生成包含以下内容的基础嵌入:
|
||||
|
||||
- 事件类型作为标题
|
||||
- 操作(如果可用)
|
||||
- 发送者登录名
|
||||
- 仓库名称
|
||||
- 原始载荷作为代码块(截断到 1000 字符)
|
||||
|
||||
## 过滤器兼容性
|
||||
|
||||
| 过滤器 | 适用事件 |
|
||||
| --- | --- |
|
||||
| `event` | 所有事件 |
|
||||
| `repo` | 所有事件 |
|
||||
| `actor` | 所有事件 |
|
||||
| `action` | 载荷中包含 `action` 字段的事件 |
|
||||
| `branch` | push、pull_request、pull_request_review、pull_request_review_comment、create、delete、workflow_run、code_scanning_alert |
|
||||
| `keyword` | 所有事件(搜索完整载荷正文) |
|
||||
115
docs/zh/guide/configuration.md
Normal file
115
docs/zh/guide/configuration.md
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# 配置
|
||||
|
||||
## 密钥
|
||||
|
||||
WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars` 中,生产环境使用 Cloudflare Worker Secrets。
|
||||
|
||||
### 必需密钥
|
||||
|
||||
| 变量 | 说明 |
|
||||
| --- | --- |
|
||||
| `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 |
|
||||
| `DISCORD_CHANNEL_ID` | 消息发送的默认 Discord 频道 ID |
|
||||
|
||||
### 可选密钥
|
||||
|
||||
| 变量 | 说明 | 默认值 |
|
||||
| --- | --- | --- |
|
||||
| `BASE_URL` | OAuth 回调的公开 URL | `http://localhost:8787` |
|
||||
|
||||
## 路由
|
||||
|
||||
路由定义了哪些事件被转发到哪些 Discord 频道。它们以 JSON 数组形式存储在 Cloudflare KV 中,键为 `config:routes`。
|
||||
|
||||
首次启动时,如果 KV 中没有配置,则使用 7 条默认路由。
|
||||
|
||||
### 路由模式
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "unique-route-id",
|
||||
"name": "可读名称",
|
||||
"enabled": true,
|
||||
"filters": [
|
||||
{ "type": "event", "match": "push" },
|
||||
{ "type": "repo", "match": "org/repo", "exclude": false }
|
||||
],
|
||||
"target": {
|
||||
"channelId": "DISCORD_CHANNEL_ID",
|
||||
"threadId": "OPTIONAL_THREAD_ID"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 默认路由
|
||||
|
||||
| ID | 事件 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `all-push` | `push` | 所有推送事件 |
|
||||
| `pull-requests` | `pull_request` | 所有 PR 活动 |
|
||||
| `issues` | `issues` | 议题打开/关闭/编辑 |
|
||||
| `issue-comments` | `issue_comment` | 议题和 PR 评论 |
|
||||
| `workflow-runs` | `workflow_run` | CI/CD 工作流完成 |
|
||||
| `releases` | `release` | 发布创建/编辑 |
|
||||
| `branch-activity` | `create`, `delete` | 分支/标签创建和删除 |
|
||||
|
||||
### 自定义路由示例
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "backend-prs",
|
||||
"name": "后端 PR",
|
||||
"enabled": true,
|
||||
"filters": [
|
||||
{ "type": "repo", "match": "myorg/backend" },
|
||||
{ "type": "event", "match": "pull_request" },
|
||||
{ "type": "actor", "match": "[bot]", "exclude": true }
|
||||
],
|
||||
"target": {
|
||||
"channelId": "1234567890",
|
||||
"threadId": "9876543210"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## 过滤器类型
|
||||
|
||||
| 类型 | 匹配对象 | 示例 |
|
||||
| --- | --- | --- |
|
||||
| `event` | GitHub 事件名称 | `push`, `pull_request`, `issues` |
|
||||
| `repo` | 仓库全名 | `org/repo` |
|
||||
| `actor` | 发送者登录名 | `username`, `[bot]` |
|
||||
| `action` | 事件操作 | `opened`, `closed`, `published` |
|
||||
| `branch` | 分支名称 | `main`, `feature/*` |
|
||||
| `keyword` | 载荷正文中的文本 | `deploy`, `/fix\s+\d+/` (正则) |
|
||||
|
||||
### 过滤器行为
|
||||
|
||||
- 路由中的所有过滤器必须都匹配才触发路由(AND 逻辑)
|
||||
- 在任何过滤器上设置 `"exclude": true` 可反转匹配逻辑(NOT 逻辑)
|
||||
- `keyword` 过滤器支持正则表达式——如果正则有误,回退到子串匹配
|
||||
- `branch` 过滤器适用于 push、pull_request、create/delete、workflow_run 和 code_scanning_alert 事件
|
||||
|
||||
### 匹配值
|
||||
|
||||
过滤器接受单个字符串或字符串数组:
|
||||
|
||||
```json
|
||||
{ "type": "event", "match": "push" }
|
||||
{ "type": "event", "match": ["push", "pull_request"] }
|
||||
```
|
||||
|
||||
## KV 存储布局
|
||||
|
||||
| 键模式 | 值 | TTL |
|
||||
| --- | --- | --- |
|
||||
| `config:routes` | JSON 路由数组 | 永久 |
|
||||
| `token:{userId}` | `{ accessToken, expiresAt }` | 至过期 |
|
||||
| `state:{hex}` | `{ userId, createdAt }` | 600 秒 |
|
||||
104
docs/zh/guide/deployment.md
Normal file
104
docs/zh/guide/deployment.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# 部署
|
||||
|
||||
## Cloudflare 设置
|
||||
|
||||
### 1. 创建 KV 命名空间
|
||||
|
||||
```bash
|
||||
npx wrangler kv namespace create KV
|
||||
```
|
||||
|
||||
这会输出一个命名空间 ID。更新 `wrangler.jsonc`,填入 ID:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"kv_namespaces": [
|
||||
{
|
||||
"binding": "KV",
|
||||
"id": "your-namespace-id",
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 设置密钥
|
||||
|
||||
```bash
|
||||
npx wrangler secret put GITHUB_WEBHOOK_SECRET
|
||||
npx wrangler secret put GITHUB_APP_ID
|
||||
npx wrangler secret put GITHUB_PRIVATE_KEY
|
||||
npx wrangler secret put GITHUB_CLIENT_ID
|
||||
npx wrangler secret put GITHUB_CLIENT_SECRET
|
||||
npx wrangler secret put DISCORD_TOKEN
|
||||
npx wrangler secret put DISCORD_CHANNEL_ID
|
||||
```
|
||||
|
||||
### 3. 部署
|
||||
|
||||
```bash
|
||||
npx wrangler deploy
|
||||
```
|
||||
|
||||
Worker 现在可通过 `https://webhooker.<your-subdomain>.workers.dev` 访问。
|
||||
|
||||
### 4. 配置 GitHub Webhook
|
||||
|
||||
1. 进入 GitHub App 设置页面
|
||||
2. 设置 **Webhook URL** 为 `https://webhooker.<your-subdomain>.workers.dev/webhook`
|
||||
3. 设置 **Webhook secret** 与 `GITHUB_WEBHOOK_SECRET` 一致
|
||||
|
||||
## GitHub App 设置
|
||||
|
||||
### 1. 创建 App
|
||||
|
||||
1. 打开 <https://github.com/settings/apps/new>
|
||||
2. 填写:
|
||||
- **GitHub App name**: `WebHooker`(或自定义名称)
|
||||
- **Homepage URL**: 你的域名
|
||||
- **Webhook URL**: `https://your-domain/webhook`
|
||||
- **Webhook secret**: 生成并复制到 `GITHUB_WEBHOOK_SECRET`
|
||||
3. 设置权限:
|
||||
- **Repository permissions**: Contents (read)、Issues (write)、Pull requests (write)、Metadata (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
|
||||
5. 生成私钥 → 将内容保存到 `GITHUB_PRIVATE_KEY` 环境变量
|
||||
|
||||
### 2. 安装 App
|
||||
|
||||
1. 创建后,进入 App 设置页面
|
||||
2. 点击 "Install App" → 选择组织/用户
|
||||
3. 选择要监控的仓库
|
||||
|
||||
### 3. 配置 OAuth
|
||||
|
||||
1. 进入 App → OAuth 设置
|
||||
2. 设置 **Callback URL**: `https://your-domain/auth/github/callback`
|
||||
3. 将 Client ID 和 Client Secret 复制到环境变量
|
||||
|
||||
## Discord Bot 设置
|
||||
|
||||
1. 打开 <https://discord.com/developers/applications>
|
||||
2. 创建新应用 → 进入 Bot 部分
|
||||
3. 将 Bot Token 复制到 `DISCORD_TOKEN`
|
||||
4. 使用 `bot` 权限范围邀请 Bot 到你的服务器,并勾选 `Send Messages` 权限
|
||||
5. 将目标频道 ID 复制到 `DISCORD_CHANNEL_ID`
|
||||
|
||||
## 自定义域名(可选)
|
||||
|
||||
要使用自定义域名替代 `*.workers.dev`:
|
||||
|
||||
1. 进入 Cloudflare Worker 设置
|
||||
2. 添加自定义域名或路由
|
||||
3. 更新 `BASE_URL` 以匹配
|
||||
|
||||
## Docker
|
||||
|
||||
提供 Dockerfile 用于容器化部署(例如在反向代理后面):
|
||||
|
||||
```bash
|
||||
docker build -t webhooker .
|
||||
docker run -p 8787:8787 --env-file .env webhooker
|
||||
```
|
||||
|
||||
注意:Docker 模式下不包含 Durable Objects 和 KV。完整功能请使用 Cloudflare 部署。
|
||||
72
docs/zh/guide/getting-started.md
Normal file
72
docs/zh/guide/getting-started.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# 快速开始
|
||||
|
||||
## 前置要求
|
||||
|
||||
- [Node.js](https://nodejs.org/) 18+
|
||||
- [Cloudflare 账号](https://dash.cloudflare.com/)(免费套餐即可)
|
||||
- [GitHub App](https://github.com/settings/apps/new)(参见 [GitHub App 设置](/zh/guide/deployment#github-app-设置))
|
||||
- Discord Bot Token(参见 [Discord Bot 设置](/zh/guide/deployment#discord-bot-设置))
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ReCloudStudio/WebHooker.git
|
||||
cd WebHooker
|
||||
npm install
|
||||
```
|
||||
|
||||
## 本地开发
|
||||
|
||||
### 1. 配置密钥
|
||||
|
||||
复制示例环境变量文件并填入你的密钥:
|
||||
|
||||
```bash
|
||||
cp .env.example .dev.vars
|
||||
```
|
||||
|
||||
编辑 `.dev.vars`,填入实际值:
|
||||
|
||||
```bash
|
||||
GITHUB_WEBHOOK_SECRET=your-webhook-secret
|
||||
GITHUB_APP_ID=your-app-id
|
||||
GITHUB_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
|
||||
GITHUB_CLIENT_ID=your-client-id
|
||||
GITHUB_CLIENT_SECRET=your-client-secret
|
||||
DISCORD_TOKEN=your-bot-token
|
||||
DISCORD_CHANNEL_ID=your-channel-id
|
||||
BASE_URL=http://localhost:8787
|
||||
```
|
||||
|
||||
::: warning
|
||||
`.dev.vars` 已被 gitignore,包含敏感信息,请勿提交。
|
||||
:::
|
||||
|
||||
### 2. 启动开发服务器
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
这将在 `http://localhost:8787` 启动本地 Miniflare 环境。
|
||||
|
||||
### 3. 验证
|
||||
|
||||
```bash
|
||||
curl http://localhost:8787/health
|
||||
# → {"status":"ok"}
|
||||
```
|
||||
|
||||
## 可用脚本
|
||||
|
||||
| 脚本 | 说明 |
|
||||
| --- | --- |
|
||||
| `npm run dev` | 启动本地开发服务器 (wrangler) |
|
||||
| `npm run deploy` | 部署到 Cloudflare |
|
||||
| `npm run typecheck` | TypeScript 类型检查 |
|
||||
| `npm run lint` | ESLint |
|
||||
| `npm run lint:md` | Markdownlint |
|
||||
| `npm run format` | 使用 Prettier 格式化 |
|
||||
| `npm run format:check` | 检查 Prettier 格式 |
|
||||
| `npm run docs:dev` | 启动文档开发服务器 |
|
||||
| `npm run docs:build` | 构建文档站点 |
|
||||
44
docs/zh/guide/introduction.md
Normal file
44
docs/zh/guide/introduction.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# 简介
|
||||
|
||||
WebHooker 是一个基于 Cloudflare Workers 构建的 GitHub webhook 调度器。它接收 GitHub webhook 事件,应用可配置的过滤器,将事件格式化为丰富的 Discord 嵌入消息,并通过 Durable Object 维护的 Gateway 连接将消息路由到 Discord 频道或帖子。
|
||||
|
||||
## 架构
|
||||
|
||||
```text
|
||||
GitHub Webhook → Cloudflare Worker (Hono)
|
||||
├── POST /webhook → 验证 → 过滤 → 格式化 → DO (Discord Gateway) → Discord
|
||||
├── GET /auth/github → OAuth 流程
|
||||
├── POST /api/* → 用户操作 (Bearer Token 鉴权)
|
||||
└── GET /health → 健康检查
|
||||
```
|
||||
|
||||
### 组件
|
||||
|
||||
| 组件 | 职责 |
|
||||
| --- | --- |
|
||||
| **Cloudflare Worker** | HTTP 入口、签名验证、事件解析、路由匹配 |
|
||||
| **Durable Object (DiscordGateway)** | 持久 WebSocket 连接 Discord Gateway、频道缓存、带重试的消息分发 |
|
||||
| **KV** | Token 存储 (`token:{userId}`)、OAuth 状态 (`state:{hex}`)、路由配置 (`config:routes`) |
|
||||
|
||||
### 数据流
|
||||
|
||||
1. GitHub 发送 webhook 到 `POST /webhook`
|
||||
2. Worker 验证 HMAC-SHA256 签名
|
||||
3. Worker 解析事件类型和载荷
|
||||
4. 根据过滤器评估路由(event、repo、actor、action、branch、keyword)
|
||||
5. 匹配的路由触发格式化器函数生成 Discord 嵌入消息
|
||||
6. 消息被分发到 Durable Object,由其维护 Gateway 连接
|
||||
7. DO 通过 REST API 将消息发送到 Discord,并处理速率限制重试
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **运行时**: Cloudflare Workers
|
||||
- **HTTP 框架**: Hono
|
||||
- **Discord Gateway**: Durable Object (持久 WebSocket + 频道缓存)
|
||||
- **存储**: Cloudflare KV
|
||||
- **鉴权**: Web Crypto API (HMAC-SHA256)、jose (JWT)、octokit (GitHub API)
|
||||
- **语言**: TypeScript
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT
|
||||
29
docs/zh/index.md
Normal file
29
docs/zh/index.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
layout: home
|
||||
|
||||
hero:
|
||||
name: WebHooker
|
||||
text: GitHub Webhook → Discord
|
||||
tagline: 通过 Cloudflare Workers 接收 GitHub 事件,应用过滤器,将格式化消息路由到 Discord 频道或帖子。
|
||||
actions:
|
||||
- theme: brand
|
||||
text: 快速开始
|
||||
link: /zh/guide/getting-started
|
||||
- theme: alt
|
||||
text: 在 GitHub 上查看
|
||||
link: https://github.com/ReCloudStudio/WebHooker
|
||||
|
||||
features:
|
||||
- title: 23 种事件格式化器
|
||||
details: 为 push、pull_request、issues、release、workflow_run 及其他 18 种事件类型提供丰富的 Discord 嵌入消息,支持颜色编码输出。
|
||||
- title: 灵活的过滤器
|
||||
details: 支持按事件类型、仓库、参与者、操作、分支(含 PR)和关键字(支持正则)过滤。支持排除模式。
|
||||
- title: Cloudflare Workers
|
||||
details: 运行在 Cloudflare 边缘网络上,使用 Durable Objects 维持持久的 Discord Gateway 连接,使用 KV 进行存储。
|
||||
- title: OAuth 与用户操作
|
||||
details: "GitHub App OAuth 流程支持用户发起操作:评论议题、合并 PR、添加反应 — 全部通过 Bearer Token 鉴权。"
|
||||
- title: 签名验证
|
||||
details: 使用 Web Crypto API 进行 HMAC-SHA256 webhook 签名验证,支持时间安全比较。
|
||||
- title: 优雅降级
|
||||
details: 当 Discord Token 不可用时以 webhook-only 模式运行。提供健康检查端点用于监控。
|
||||
---
|
||||
Loading…
Add table
Add a link
Reference in a new issue