Document the /gh login, /gh logout and /gh comment add|edit|del commands plus the right-click message context-menu equivalents, and require the applications.commands invite scope. Comments are posted as the linked user's own GitHub account, so the old GitHub App identity, Message Content intent and Read Message History requirements are gone.
14 KiB
WebHooker
GitHub webhook → Discord 分发服务。通过 Cloudflare Workers 接收 webhook 事件,应用过滤器,将格式化消息路由到 Discord 频道或子区。
功能特性
- 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(+ 通用回退)
- HMAC-SHA256 签名验证(Web Crypto API)
- 按事件类型、仓库、操作人、操作、分支(含 PR)、关键词(支持正则)过滤
- 富 Discord embed:颜色编码、作者头像、字段、时间戳
- 路由到频道或子区
- GitHub App OAuth 用户授权(评论、合并、反应)
- Web 配置控制台(
/admin)— 通过 GitHub OAuth + 管理员白名单管理路由 - Durable Object 维持 Discord Gateway WebSocket 连接 + 频道缓存
- Cloudflare KV 存储 token/状态/配置
- 优雅降级(Discord 不可用时仅 webhook 模式)
架构
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(state:{hex})、路由配置(config:routes)
快速开始
npm install # 或 bun install
cp .env.example .dev.vars # 填写本地开发密钥
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 |
BASE_URL |
公网地址(用于 OAuth 回调) |
ADMIN_USER_IDS |
允许访问 /admin 的 GitHub 用户 ID(或登录名),逗号分隔 |
DISCORD_GATEWAY_ENABLED |
设为 true 启用 Discord Gateway(bot 在线状态);不启用也能通过 REST 推送 |
路由配置
路由存储在 KV(config:routes,JSON 格式)。没有默认路由——每条路由(包括目标 channelId / threadId)都必须显式定义,可通过 Web 控制台(/admin)或直接向 KV 存储 JSON 数组:
[
{
"id": "all-push",
"name": "Push 事件",
"enabled": true,
"filters": [{ "type": "event", "match": "push" }],
"target": { "channelId": "频道ID" }
}
]
target.channelId 必填且按原样使用,不存在默认频道回退。
Web 控制台(/admin)
内置的配置控制台让你在浏览器中管理路由(新增 / 编辑 / 删除 / 开关),无需操作 KV:
- 设置
ADMIN_USER_IDS为允许管理控制台的 GitHub 用户 ID(或登录名),例如ADMIN_USER_IDS=12345,RhenCloud。 - 访问
/admin并用 GitHub 登录,仅白名单内用户可进入。 - 修改会立即写入 KV
config:routes,webhook 管线随即生效。
在 /admin/logout 退出登录。
完整语法示例见 config.example.yaml。
过滤器类型
| 类型 | 匹配内容 | 备注 |
|---|---|---|
event |
push、pull_request、issues 等 |
GitHub 事件名 |
repo |
org/repo 全名 |
|
actor |
发送者登录名 | |
action |
opened、closed、published 等 |
|
branch |
分支名 | 支持 push、PR、create/delete、workflow_run、code_scanning_alert |
keyword |
payload 中的文本 | 支持正则表达式;无效正则回退为子串匹配 |
设置 exclude: true 可取反过滤器。
API
健康检查
GET /health— 返回{"status": "ok"}
OAuth
GET /auth/github— 发起 GitHub OAuth 授权(重定向到 GitHub)GET /auth/github/callback— OAuth 回调(交换 code 为 token)DELETE /auth/token/:userId— 撤销用户 token
操作接口(需要 Authorization: Bearer <token> 头)
POST /api/comment— 创建 issue 评论POST /api/merge— 合并 PRPOST /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
- 访问 https://github.com/settings/apps/new
- 填写信息:
- GitHub App name:
WebHooker(或自定义名称) - Homepage URL:你的域名
- Webhook URL:
https://your-domain/webhook - Webhook secret:生成并复制到
GITHUB_WEBHOOK_SECRET
- GitHub App name:
- 设置权限:
- Repository permissions:Contents (read)、Issues (write)、Pull requests (write)、Metadata (read)
- Organization permissions:Members (read) — 如需要
- 订阅事件: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
- 生成私钥 → 将内容保存到
GITHUB_PRIVATE_KEY环境变量
2. 安装 App
- 创建后进入 App 设置页
- 点击 "Install App" → 选择组织/用户
- 选择要监控的仓库
3. 配置 OAuth
- 进入 App → OAuth settings
- 设置 Callback URL:
https://your-domain/auth/github/callback - 复制 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)。需要 applications.commands scope,否则无法注册斜杠 / 右键菜单命令:
https://discord.com/oauth2/authorize?client_id=你的机器人CLIENT_ID&permissions=274877910016&scope=bot+applications.commands
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 指令(以本人身份评论 GitHub)
启用 Gateway 后,bot 会在连接时为每个服务器注册原生的斜杠命令与消息右键菜单命令。评论以你本人绑定的 GitHub 账号(OAuth)发出,权限交由 GitHub 判定——若 GitHub 拒绝(例如去修改他人评论),bot 会提示你无权限。所有回复均为 ephemeral(仅你可见)。
1. 绑定账号(一次即可):
/gh login → 返回一个 ephemeral 授权链接,用于绑定你的 GitHub 账号
/gh logout → 解除绑定
2. 添加 / 编辑 / 删除评论 —— 两种等价方式:
-
右键点击通知(推荐):右键一条 bot 推送的 issue / PR / 评论通知 → 应用(Apps) → GitHub: 添加评论 / 编辑评论 / 删除评论。目标会从通知 embed 中自动提取,无需粘贴链接。
-
斜杠命令 + 链接:
/gh comment add link:<issue 或 PR 链接> 例如 https://github.com/owner/repo/issues/123 /gh comment edit link:<评论链接> 链接需包含 #issuecomment-<id> /gh comment del link:<评论链接> 链接需包含 #issuecomment-<id>edit/del需要具体的评论链接(在 GitHub 上:评论 ⋯ 菜单 → Copy link)。add/edit会弹出 modal 让你输入 / 修改评论内容(编辑时预填原文)。
要求:
| 项目 | 说明 |
|---|---|
| 启用 Gateway | DISCORD_GATEWAY_ENABLED=true(交互通过 Gateway 送达) |
| 邀请 scope | 邀请时带上 applications.commands(见上方邀请链接) |
| OAuth | 已配置 GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET 与 BASE_URL |
| 用户绑定 | 每个用户先执行 /gh login |
部署
# 在 Cloudflare 设置密钥
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
# 创建 KV 命名空间
npx wrangler kv namespace create KV
# 更新 wrangler.jsonc 中的 KV namespace ID
# 部署
npx wrangler deploy
开发命令
npx wrangler dev # 本地开发服务器(Miniflare)
npm run typecheck # 类型检查
npm run lint # ESLint
支持的事件
| 事件 | 格式化内容 |
|---|---|
push |
提交列表、分支、作者 |
pull_request |
PR 标题、分支、差异统计 |
issues |
Issue 标题、标签、指派人 |
issue_comment |
评论内容、Issue 引用 |
workflow_run |
工作流状态、结论、耗时 |
release |
Tag、内容、资产 |
create / delete |
分支/tag 创建或删除 |
star |
Star 数量、仓库 |
fork |
Fork 来源 → 目标 |
check_run |
状态、结论、详情链接 |
pull_request_review |
审查状态、内容预览 |
pull_request_review_comment |
行内代码评论、文件路径、行号 |
commit_comment |
Commit SHA、评论内容 |
deployment_status |
环境、状态、commit ref |
member |
协作者添加/移除 |
label |
标签名、颜色、描述 |
milestone |
进度条、open/closed 计数、截止日期 |
discussion |
讨论标题、分类、操作 |
discussion_comment |
评论内容、讨论引用 |
repository |
仓库重命名/转移详情 |
code_scanning_alert |
严重程度、规则 ID、文件路径 |
dependabot_alert |
严重程度、包名、受影响范围、修复版本 |
许可证
MIT