initial commit

This commit is contained in:
RhenCloud 2026-07-24 21:48:50 +08:00
commit 512d4b01d5
No known key found for this signature in database
GPG key ID: A574A617378C4E0B
55 changed files with 6430 additions and 0 deletions

View 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
View 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 部署。

View 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` | 构建文档站点 |

View 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