mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
docs: document WebUI, optional gateway, routes-only config and slash commands
This commit is contained in:
parent
d68aeb20d5
commit
4349b24d2a
6 changed files with 282 additions and 90 deletions
19
AGENTS.md
19
AGENTS.md
|
|
@ -10,10 +10,11 @@ Core pipeline: GitHub Webhook → Worker (verify + filter + format) → Durable
|
|||
|
||||
- Runtime: Cloudflare Workers
|
||||
- HTTP framework: Hono
|
||||
- Discord Gateway: Durable Object (persistent WebSocket + channel cache)
|
||||
- Storage: Cloudflare KV (tokens, OAuth state, route config)
|
||||
- Discord Gateway: optional (`DISCORD_GATEWAY_ENABLED=true`); only keeps bot online — messages always sent via REST
|
||||
- Storage: Cloudflare KV (tokens, OAuth state, route config, admin sessions)
|
||||
- Signature verification: Web Crypto API (HMAC-SHA256, timing-safe)
|
||||
- GitHub OAuth: octokit + jose (JWT)
|
||||
- Admin WebUI: `/admin` config console, OAuth-session protected via `ADMIN_USER_IDS` whitelist
|
||||
- Local dev: wrangler + Miniflare
|
||||
|
||||
## Architecture
|
||||
|
|
@ -22,15 +23,19 @@ Core pipeline: GitHub Webhook → Worker (verify + filter + format) → Durable
|
|||
src/
|
||||
├── index.ts # CF Workers entry (fetch + scheduled), exports DiscordGateway DO
|
||||
├── types.ts # Env, Config, Route, Filter, WebhookEvent, FormattedMessage
|
||||
├── config.ts # Loads routes from KV (fallback to 7 defaults), builds Config from env
|
||||
├── server.ts # Hono app: /health, /webhook, mounts /auth + /
|
||||
├── config.ts # loadRoutes/saveRoutes (KV config:routes, cache w/ 60s TTL), loadConfig from env
|
||||
├── server.ts # Hono app: /health, /webhook, mounts /auth, /admin + /
|
||||
├── webhook.ts # HMAC verify (Web Crypto), parseEvent, extractBranch, matchRoute
|
||||
├── discord.ts # Dispatch via DO RPC, initGateway (scheduled)
|
||||
├── discord-gateway.ts # Durable Object: Discord Gateway WS, heartbeat, channel cache, send
|
||||
├── discord.ts # Dispatch via REST (or DO RPC when gateway enabled), initGateway (scheduled)
|
||||
├── discord-rest.ts # Discord REST sendMessage with retry + rate-limit handling
|
||||
├── discord-gateway.ts # Optional Durable Object: Discord Gateway WS, heartbeat, channel cache, send
|
||||
├── formatter.ts # 23 event formatters + generic fallback (~1380 lines)
|
||||
├── github-oauth.ts # OAuth URL, callback token exchange, getUserOctokit
|
||||
├── oauth-routes.ts # GET /auth/github, callback, DELETE /token/:userId (KV state)
|
||||
├── oauth-routes.ts # GET /auth/github, callback (sets admin session if redirect=/admin), DELETE /token/:userId
|
||||
├── action-routes.ts # POST /api/comment|merge|react (Bearer token auth via KV lookup)
|
||||
├── admin-routes.ts # /admin UI + GET/PUT /admin/api/routes (session + ADMIN_USER_IDS auth, validation)
|
||||
├── admin-session.ts # Session CRUD (KV session:{id}), isAdminUser, cookie helpers
|
||||
├── admin-ui.ts # ADMIN_HTML: single-file config console (vanilla HTML/CSS/JS)
|
||||
├── token-store.ts # KV-based token CRUD with findUserIdByToken reverse lookup
|
||||
└── log.ts # JSON console logger (info/warn/error/fatal)
|
||||
```
|
||||
|
|
|
|||
80
README.md
80
README.md
|
|
@ -10,6 +10,7 @@ GitHub webhook → Discord dispatcher. Receives webhook events via Cloudflare Wo
|
|||
- Rich Discord embeds with color coding, author avatars, fields, and timestamps
|
||||
- Route to channels or threads
|
||||
- GitHub App OAuth for user actions (comment, merge, react)
|
||||
- **Web UI config console** (`/admin`) — manage routes with GitHub OAuth + admin whitelist
|
||||
- Durable Object for persistent Discord Gateway connection + channel cache
|
||||
- Cloudflare KV for token/state/config storage
|
||||
- Graceful degradation (webhook-only mode if Discord unavailable)
|
||||
|
|
@ -41,19 +42,20 @@ npx wrangler dev # Start local dev server
|
|||
### Secrets (`.dev.vars` for local, Worker Secrets for production)
|
||||
|
||||
| Variable | Description |
|
||||
| ----------------------- | ------------------------------ |
|
||||
| ------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| `GITHUB_WEBHOOK_SECRET` | Webhook secret from GitHub |
|
||||
| `GITHUB_APP_ID` | GitHub App ID |
|
||||
| `GITHUB_PRIVATE_KEY` | App private key (PEM) |
|
||||
| `GITHUB_CLIENT_ID` | OAuth client ID |
|
||||
| `GITHUB_CLIENT_SECRET` | OAuth client secret |
|
||||
| `DISCORD_TOKEN` | Bot token |
|
||||
| `DISCORD_CHANNEL_ID` | Default target channel |
|
||||
| `BASE_URL` | Public URL for OAuth callbacks |
|
||||
| `ADMIN_USER_IDS` | Comma-separated GitHub user IDs (or logins) allowed to access `/admin` |
|
||||
| `DISCORD_GATEWAY_ENABLED` | `true` to enable the Discord Gateway (bot online status); messaging works without it via REST |
|
||||
|
||||
### Routes
|
||||
|
||||
Routes are stored in KV (`config:keys` as JSON). On first boot, 7 default routes are used. To customize, store a JSON array in KV:
|
||||
Routes are stored in KV (`config:routes` as JSON). There are **no default routes** — every route (including its target `channelId` / `threadId`) must be defined explicitly, either via the Web UI (`/admin`) or by storing a JSON array in KV:
|
||||
|
||||
```json
|
||||
[
|
||||
|
|
@ -67,6 +69,18 @@ Routes are stored in KV (`config:keys` as JSON). On first boot, 7 default routes
|
|||
]
|
||||
```
|
||||
|
||||
The `target.channelId` is required and is used as-is; there is no fallback to a default channel.
|
||||
|
||||
### Web UI (`/admin`)
|
||||
|
||||
The built-in config console lets you manage routes in the browser (add / edit / delete / toggle / reorder), no KV access needed:
|
||||
|
||||
1. Set `ADMIN_USER_IDS` to the GitHub user IDs (or logins) allowed to manage the console, e.g. `ADMIN_USER_IDS=12345,RhenCloud`.
|
||||
2. Visit `/admin` and sign in with GitHub. Only users in the whitelist get access.
|
||||
3. Changes are written to KV `config:routes` immediately and picked up by the webhook pipeline.
|
||||
|
||||
Sign out at `/admin/logout`.
|
||||
|
||||
See `config.example.yaml` for full syntax examples.
|
||||
|
||||
### Filter Types
|
||||
|
|
@ -100,6 +114,14 @@ Set `exclude: true` to invert any filter.
|
|||
- `POST /api/merge` — Merge pull request
|
||||
- `POST /api/react` — Add reaction to issue
|
||||
|
||||
### Admin (require admin OAuth session)
|
||||
|
||||
- `GET /admin` — Config console UI
|
||||
- `GET /admin/login` — Start admin sign-in (GitHub OAuth)
|
||||
- `GET /admin/logout` — Sign out
|
||||
- `GET /admin/api/routes` — List routes
|
||||
- `PUT /admin/api/routes` — Replace routes
|
||||
|
||||
## GitHub App Setup
|
||||
|
||||
### 1. Create App
|
||||
|
|
@ -129,6 +151,58 @@ Set `exclude: true` to invert any filter.
|
|||
2. Set **Callback URL**: `https://your-domain/auth/github/callback`
|
||||
3. Copy Client ID and Client Secret to env
|
||||
|
||||
## Discord Bot Setup
|
||||
|
||||
Create a bot at <https://discord.com/developers/applications>, copy its token to `DISCORD_TOKEN`.
|
||||
|
||||
### OAuth2 Invite
|
||||
|
||||
Add the bot to your server with the `bot` scope and the following permissions:
|
||||
|
||||
| Permission | Value | Why |
|
||||
| ------------------------ | -------------- | ----------------------------------------------- |
|
||||
| View Channels | `1024` | See the target channel to post messages |
|
||||
| Send Messages | `2048` | Send embeds/messages to channels |
|
||||
| Send Messages in Threads | `274877906944` | Send to threads when a route targets `threadId` |
|
||||
|
||||
Combined permission integer: `274877910016`
|
||||
|
||||
Invite URL (replace `CLIENT_ID` with your bot's client ID):
|
||||
|
||||
```
|
||||
https://discord.com/oauth2/authorize?client_id=YOUR_BOT_CLIENT_ID&permissions=274877910016&scope=bot
|
||||
```
|
||||
|
||||
### Intents
|
||||
|
||||
The Gateway connection uses the **GUILDS** intent only (`1 << 0`). No privileged intents (e.g. Message Content) are required.
|
||||
|
||||
### Gateway (optional)
|
||||
|
||||
The Discord Gateway connection only keeps the bot showing as **online** — it is **not** required for sending messages. Messages are sent via the Discord REST API, so push works with just `DISCORD_TOKEN`.
|
||||
|
||||
- `DISCORD_GATEWAY_ENABLED=false` (default): messages are sent directly via REST; the Gateway is not connected.
|
||||
- `DISCORD_GATEWAY_ENABLED=true`: the Durable Object connects to the Gateway to keep the bot online; messages are still sent via REST.
|
||||
|
||||
### Bot Command (`!gh`)
|
||||
|
||||
When the Gateway is enabled, reply (quote) a bot-issued issue / PR notification and type:
|
||||
|
||||
```
|
||||
!gh <comment text>
|
||||
```
|
||||
|
||||
The bot posts the text as a GitHub comment on that issue / PR (authenticated as the GitHub App).
|
||||
|
||||
**Extra requirements:**
|
||||
|
||||
| Item | How |
|
||||
| ----------------- | ----------------------------------------------------------------------------------------- |
|
||||
| Gateway enabled | `DISCORD_GATEWAY_ENABLED=true` |
|
||||
| Privileged intent | Enable **Message Content** in Discord Developer Portal → Bot → Privileged Gateway Intents |
|
||||
| Permissions | **Read Message History** (to read the quoted message) in addition to sending |
|
||||
| GitHub App | Installed on the repo with **Issues (write)** permission |
|
||||
|
||||
## Deployment
|
||||
|
||||
```bash
|
||||
|
|
|
|||
80
README.zh.md
80
README.zh.md
|
|
@ -10,6 +10,7 @@ GitHub webhook → Discord 分发服务。通过 Cloudflare Workers 接收 webho
|
|||
- 富 Discord embed:颜色编码、作者头像、字段、时间戳
|
||||
- 路由到频道或子区
|
||||
- GitHub App OAuth 用户授权(评论、合并、反应)
|
||||
- **Web 配置控制台**(`/admin`)— 通过 GitHub OAuth + 管理员白名单管理路由
|
||||
- Durable Object 维持 Discord Gateway WebSocket 连接 + 频道缓存
|
||||
- Cloudflare KV 存储 token/状态/配置
|
||||
- 优雅降级(Discord 不可用时仅 webhook 模式)
|
||||
|
|
@ -41,19 +42,20 @@ npx wrangler dev # 启动本地开发服务器
|
|||
### 密钥(本地用 `.dev.vars`,生产用 Worker Secrets)
|
||||
|
||||
| 变量 | 说明 |
|
||||
| ----------------------- | --------------------------- |
|
||||
| ------------------------- | -------------------------------------------------------------------------- |
|
||||
| `GITHUB_WEBHOOK_SECRET` | GitHub webhook 密钥 |
|
||||
| `GITHUB_APP_ID` | GitHub App ID |
|
||||
| `GITHUB_PRIVATE_KEY` | App 私钥(PEM) |
|
||||
| `GITHUB_CLIENT_ID` | OAuth Client ID |
|
||||
| `GITHUB_CLIENT_SECRET` | OAuth Client Secret |
|
||||
| `DISCORD_TOKEN` | 机器人 token |
|
||||
| `DISCORD_CHANNEL_ID` | 默认目标频道 |
|
||||
| `BASE_URL` | 公网地址(用于 OAuth 回调) |
|
||||
| `ADMIN_USER_IDS` | 允许访问 `/admin` 的 GitHub 用户 ID(或登录名),逗号分隔 |
|
||||
| `DISCORD_GATEWAY_ENABLED` | 设为 `true` 启用 Discord Gateway(bot 在线状态);不启用也能通过 REST 推送 |
|
||||
|
||||
### 路由配置
|
||||
|
||||
路由存储在 KV(`config:routes`,JSON 格式)。首次启动使用 7 个默认路由。自定义时在 KV 中存储 JSON 数组:
|
||||
路由存储在 KV(`config:routes`,JSON 格式)。**没有默认路由**——每条路由(包括目标 `channelId` / `threadId`)都必须显式定义,可通过 Web 控制台(`/admin`)或直接向 KV 存储 JSON 数组:
|
||||
|
||||
```json
|
||||
[
|
||||
|
|
@ -67,6 +69,18 @@ npx wrangler dev # 启动本地开发服务器
|
|||
]
|
||||
```
|
||||
|
||||
`target.channelId` 必填且按原样使用,不存在默认频道回退。
|
||||
|
||||
### Web 控制台(`/admin`)
|
||||
|
||||
内置的配置控制台让你在浏览器中管理路由(新增 / 编辑 / 删除 / 开关),无需操作 KV:
|
||||
|
||||
1. 设置 `ADMIN_USER_IDS` 为允许管理控制台的 GitHub 用户 ID(或登录名),例如 `ADMIN_USER_IDS=12345,RhenCloud`。
|
||||
2. 访问 `/admin` 并用 GitHub 登录,仅白名单内用户可进入。
|
||||
3. 修改会立即写入 KV `config:routes`,webhook 管线随即生效。
|
||||
|
||||
在 `/admin/logout` 退出登录。
|
||||
|
||||
完整语法示例见 `config.example.yaml`。
|
||||
|
||||
### 过滤器类型
|
||||
|
|
@ -100,6 +114,14 @@ npx wrangler dev # 启动本地开发服务器
|
|||
- `POST /api/merge` — 合并 PR
|
||||
- `POST /api/react` — 添加 issue 反应
|
||||
|
||||
### 管理接口(需要管理员 OAuth 会话)
|
||||
|
||||
- `GET /admin` — 配置控制台页面
|
||||
- `GET /admin/login` — 开始管理员登录(GitHub OAuth)
|
||||
- `GET /admin/logout` — 退出登录
|
||||
- `GET /admin/api/routes` — 列出路由
|
||||
- `PUT /admin/api/routes` — 替换路由
|
||||
|
||||
## GitHub App 配置教程
|
||||
|
||||
### 1. 创建 App
|
||||
|
|
@ -128,6 +150,58 @@ npx wrangler dev # 启动本地开发服务器
|
|||
2. 设置 **Callback URL**:`https://your-domain/auth/github/callback`
|
||||
3. 复制 Client ID 和 Client Secret 到环境变量
|
||||
|
||||
## Discord 机器人配置
|
||||
|
||||
在 <https://discord.com/developers/applications> 创建机器人,将 Token 复制到 `DISCORD_TOKEN`。
|
||||
|
||||
### OAuth2 邀请
|
||||
|
||||
使用 `bot` scope 将机器人加入服务器,需要以下权限:
|
||||
|
||||
| 权限 | 数值 | 用途 |
|
||||
| ------------------------------------------- | -------------- | ---------------------------------------- |
|
||||
| 查看频道 (View Channels) | `1024` | 查看目标频道以发送消息 |
|
||||
| 发送消息 (Send Messages) | `2048` | 向频道发送 embed/消息 |
|
||||
| 在线程中发送消息 (Send Messages in Threads) | `274877906944` | 当路由配置了 `threadId` 时向线程发送消息 |
|
||||
|
||||
权限组合整数值:`274877910016`
|
||||
|
||||
邀请链接(将 `CLIENT_ID` 替换为机器人的 Client ID):
|
||||
|
||||
```
|
||||
https://discord.com/oauth2/authorize?client_id=你的机器人CLIENT_ID&permissions=274877910016&scope=bot
|
||||
```
|
||||
|
||||
### Intents
|
||||
|
||||
Gateway 连接仅使用 **GUILDS** intent(`1 << 0`)。无需特权 intent(如 Message Content)。
|
||||
|
||||
### Gateway(可选)
|
||||
|
||||
Discord Gateway 连接仅用于让 bot 显示为**在线**——发送消息**不需要**它。消息通过 Discord REST API 发送,因此只要有 `DISCORD_TOKEN` 即可推送。
|
||||
|
||||
- `DISCORD_GATEWAY_ENABLED=false`(默认):直接通过 REST 发送消息,不建立 Gateway 连接。
|
||||
- `DISCORD_GATEWAY_ENABLED=true`:由 Durable Object 连接 Gateway 以维持 bot 在线状态;消息仍走 REST。
|
||||
|
||||
### Bot 指令(`!gh`)
|
||||
|
||||
启用 Gateway 后,**引用(回复)**一条 bot 推送的 issue / PR 通知,然后输入:
|
||||
|
||||
```
|
||||
!gh <评论内容>
|
||||
```
|
||||
|
||||
bot 会以 GitHub App 的身份把内容发为对该 issue / PR 的评论。
|
||||
|
||||
**额外要求:**
|
||||
|
||||
| 项目 | 说明 |
|
||||
| ------------ | --------------------------------------------------------------------------------------- |
|
||||
| 启用 Gateway | `DISCORD_GATEWAY_ENABLED=true` |
|
||||
| 特权 intent | 在 Discord Developer Portal → Bot → Privileged Gateway Intents 开启 **Message Content** |
|
||||
| 权限 | 除发送外还需 **Read Message History**(读取被引用的消息) |
|
||||
| GitHub App | 已安装到该仓库且有 **Issues (write)** 权限 |
|
||||
|
||||
## 部署
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -20,6 +20,17 @@ https://your-worker.workers.dev
|
|||
| `POST` | `/api/comment` | Bearer token | Create issue comment |
|
||||
| `POST` | `/api/merge` | Bearer token | Merge pull request |
|
||||
| `POST` | `/api/react` | Bearer token | Add reaction to issue |
|
||||
| `GET` | `/admin` | Admin session | Config console UI |
|
||||
| `GET` | `/admin/api/routes` | Admin session | List routes |
|
||||
| `PUT` | `/admin/api/routes` | Admin session | Replace routes |
|
||||
|
||||
## Admin Console
|
||||
|
||||
See [Configuration → Web UI](../guide/configuration.md#web-ui) for setup. Admin endpoints require a session cookie obtained via `GET /admin/login` (GitHub OAuth); the signed-in user must be listed in `ADMIN_USER_IDS`.
|
||||
|
||||
- `GET /admin` — Serves the config console HTML
|
||||
- `GET /admin/api/routes` — Returns `{ "routes": Route[] }`
|
||||
- `PUT /admin/api/routes` — Body `{ "routes": Route[] }`; validates each route (id pattern, unique id, name, enabled, ≥1 valid filter, string `target.channelId`) and persists to KV `config:routes`. Returns `200 { ok, count }` or `400 { error }` / `401 { error }`.
|
||||
|
||||
## Health Check
|
||||
|
||||
|
|
|
|||
|
|
@ -14,19 +14,42 @@ WebHooker requires several secrets to function. For local development, store the
|
|||
| `GITHUB_CLIENT_ID` | OAuth client ID from App settings |
|
||||
| `GITHUB_CLIENT_SECRET` | OAuth client secret from App settings |
|
||||
| `DISCORD_TOKEN` | Discord bot token |
|
||||
| `DISCORD_CHANNEL_ID` | Default Discord channel ID for messages |
|
||||
|
||||
### Optional Secrets
|
||||
|
||||
| Variable | Description | Default |
|
||||
| ---------- | ------------------------------ | ----------------------- |
|
||||
| ------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------- |
|
||||
| `BASE_URL` | Public URL for OAuth callbacks | `http://localhost:8787` |
|
||||
| `ADMIN_USER_IDS` | Comma-separated GitHub user IDs (or logins) allowed to access the Web UI | Disabled |
|
||||
| `DISCORD_GATEWAY_ENABLED` | Set to `true` to connect the Discord Gateway (bot online status); messaging works without it via REST | `false` |
|
||||
|
||||
## Web UI
|
||||
|
||||
WebHooker ships with a built-in config console at `/admin` for managing routes in the browser. It is protected by GitHub OAuth plus an admin whitelist.
|
||||
|
||||
### Setup
|
||||
|
||||
1. Configure `ADMIN_USER_IDS` with the GitHub user IDs allowed to manage routes. Logins are also accepted, e.g. `ADMIN_USER_IDS=12345,RhenCloud`. If unset, the console is disabled.
|
||||
2. Open `/admin` and sign in with GitHub.
|
||||
3. Only users in the whitelist receive a session cookie; everyone else gets `403`.
|
||||
|
||||
### Endpoints
|
||||
|
||||
| Endpoint | Description |
|
||||
| ----------------------- | --------------------------- |
|
||||
| `GET /admin` | Config console UI |
|
||||
| `GET /admin/login` | Start GitHub OAuth sign-in |
|
||||
| `GET /admin/logout` | Destroy session |
|
||||
| `GET /admin/api/routes` | List routes (admin only) |
|
||||
| `PUT /admin/api/routes` | Replace routes (admin only) |
|
||||
|
||||
The console lets you add, edit, delete, and toggle routes. Saved routes are written to KV `config:routes` immediately and the config cache is invalidated so the webhook pipeline picks them up on the next run.
|
||||
|
||||
## Routes
|
||||
|
||||
Routes define which events get forwarded to which Discord channels. They are stored in Cloudflare KV under the key `config:routes` as a JSON array.
|
||||
|
||||
On first boot, 7 default routes are used if no KV config exists.
|
||||
There are **no default routes** — each route must define its own target. If no routes are configured, no events are forwarded.
|
||||
|
||||
### Route Schema
|
||||
|
||||
|
|
@ -40,23 +63,13 @@ On first boot, 7 default routes are used if no KV config exists.
|
|||
{ "type": "repo", "match": "org/repo", "exclude": false }
|
||||
],
|
||||
"target": {
|
||||
"channelId": "DISCORD_CHANNEL_ID",
|
||||
"channelId": "REQUIRED_CHANNEL_ID",
|
||||
"threadId": "OPTIONAL_THREAD_ID"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Default Routes
|
||||
|
||||
| ID | Event(s) | Description |
|
||||
| ----------------- | ------------------ | -------------------------------- |
|
||||
| `all-push` | `push` | All push events |
|
||||
| `pull-requests` | `pull_request` | All PR activity |
|
||||
| `issues` | `issues` | Issue open/close/edit |
|
||||
| `issue-comments` | `issue_comment` | Issue and PR comments |
|
||||
| `workflow-runs` | `workflow_run` | CI/CD workflow completions |
|
||||
| `releases` | `release` | Release publish/edit |
|
||||
| `branch-activity` | `create`, `delete` | Branch/tag creation and deletion |
|
||||
`target.channelId` is required and used as-is; there is no fallback to a default channel.
|
||||
|
||||
### Custom Route Example
|
||||
|
||||
|
|
@ -109,7 +122,8 @@ Filters accept either a single string or an array of strings:
|
|||
## KV Storage Layout
|
||||
|
||||
| Key Pattern | Value | TTL |
|
||||
| ---------------- | ---------------------------- | ------------ |
|
||||
| ---------------- | --------------------------------- | ------------ |
|
||||
| `config:routes` | JSON array of routes | Permanent |
|
||||
| `session:{id}` | Admin session `{ userId, login }` | 7 days |
|
||||
| `token:{userId}` | `{ accessToken, expiresAt }` | Until expiry |
|
||||
| `state:{hex}` | `{ userId, createdAt }` | 600 seconds |
|
||||
|
|
|
|||
|
|
@ -7,26 +7,49 @@ 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 |
|
||||
| `DISCORD_CHANNEL_ID` | 消息发送的默认 Discord 频道 ID |
|
||||
|
||||
### 可选密钥
|
||||
|
||||
| 变量 | 说明 | 默认值 |
|
||||
| --- | --- | --- |
|
||||
| ------------------------- | -------------------------------------------------------------------------- | ----------------------- |
|
||||
| `BASE_URL` | OAuth 回调的公开 URL | `http://localhost:8787` |
|
||||
| `ADMIN_USER_IDS` | 允许访问 WebUI 的 GitHub 用户 ID(或登录名),逗号分隔 | 未设置时 WebUI 关闭 |
|
||||
| `DISCORD_GATEWAY_ENABLED` | 设为 `true` 连接 Discord Gateway(bot 在线状态);不启用也能通过 REST 推送 | `false` |
|
||||
|
||||
## Web 控制台
|
||||
|
||||
WebHooker 内置了位于 `/admin` 的配置控制台,可在浏览器中管理路由。它由 GitHub OAuth 和管理员白名单保护。
|
||||
|
||||
### 设置
|
||||
|
||||
1. 配置 `ADMIN_USER_IDS`,填写允许管理路由的 GitHub 用户 ID,也支持登录名,例如 `ADMIN_USER_IDS=12345,RhenCloud`。未设置时控制台禁用。
|
||||
2. 打开 `/admin` 并使用 GitHub 登录。
|
||||
3. 只有白名单中的用户会获得会话 Cookie;其他人收到 `403`。
|
||||
|
||||
### 端点
|
||||
|
||||
| 端点 | 说明 |
|
||||
| ----------------------- | ---------------------- |
|
||||
| `GET /admin` | 配置控制台页面 |
|
||||
| `GET /admin/login` | 开始 GitHub OAuth 登录 |
|
||||
| `GET /admin/logout` | 销毁会话 |
|
||||
| `GET /admin/api/routes` | 列出路由(仅管理员) |
|
||||
| `PUT /admin/api/routes` | 替换路由(仅管理员) |
|
||||
|
||||
控制台支持新增、编辑、删除和开关路由。保存后立即写入 KV `config:routes` 并使配置缓存失效,下一次 webhook 处理即会生效。
|
||||
|
||||
## 路由
|
||||
|
||||
路由定义了哪些事件被转发到哪些 Discord 频道。它们以 JSON 数组形式存储在 Cloudflare KV 中,键为 `config:routes`。
|
||||
|
||||
首次启动时,如果 KV 中没有配置,则使用 7 条默认路由。
|
||||
**没有默认路由**——每条路由必须自行定义目标频道。若未配置任何路由,则不会转发任何事件。
|
||||
|
||||
### 路由模式
|
||||
|
||||
|
|
@ -40,23 +63,13 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars`
|
|||
{ "type": "repo", "match": "org/repo", "exclude": false }
|
||||
],
|
||||
"target": {
|
||||
"channelId": "DISCORD_CHANNEL_ID",
|
||||
"threadId": "OPTIONAL_THREAD_ID"
|
||||
"channelId": "必填频道ID",
|
||||
"threadId": "可选线程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` | 分支/标签创建和删除 |
|
||||
`target.channelId` 必填且按原样使用,不存在默认频道回退。
|
||||
|
||||
### 自定义路由示例
|
||||
|
||||
|
|
@ -82,7 +95,7 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars`
|
|||
## 过滤器类型
|
||||
|
||||
| 类型 | 匹配对象 | 示例 |
|
||||
| --- | --- | --- |
|
||||
| --------- | ---------------- | -------------------------------- |
|
||||
| `event` | GitHub 事件名称 | `push`, `pull_request`, `issues` |
|
||||
| `repo` | 仓库全名 | `org/repo` |
|
||||
| `actor` | 发送者登录名 | `username`, `[bot]` |
|
||||
|
|
@ -109,7 +122,8 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars`
|
|||
## KV 存储布局
|
||||
|
||||
| 键模式 | 值 | TTL |
|
||||
| --- | --- | --- |
|
||||
| ---------------- | ------------------------------ | ------ |
|
||||
| `config:routes` | JSON 路由数组 | 永久 |
|
||||
| `session:{id}` | 管理员会话 `{ userId, login }` | 7 天 |
|
||||
| `token:{userId}` | `{ accessToken, expiresAt }` | 至过期 |
|
||||
| `state:{hex}` | `{ userId, createdAt }` | 600 秒 |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue