WebHooker/README.zh.md

14 KiB
Raw Blame History

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 statestate:{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 Gatewaybot 在线状态);不启用也能通过 REST 推送

路由配置

路由存储在 KVconfig:routesJSON 格式)。没有默认路由——每条路由(包括目标 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

  1. 设置 ADMIN_USER_IDS 为允许管理控制台的 GitHub 用户 ID或登录名例如 ADMIN_USER_IDS=12345,RhenCloud
  2. 访问 /admin 并用 GitHub 登录,仅白名单内用户可进入。
  3. 修改会立即写入 KV config:routeswebhook 管线随即生效。

/admin/logout 退出登录。

完整语法示例见 config.example.yaml

过滤器类型

类型 匹配内容 备注
event pushpull_requestissues GitHub 事件名
repo org/repo 全名
actor 发送者登录名
action openedclosedpublished
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 — 合并 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

  1. 访问 https://github.com/settings/apps/new
  2. 填写信息:
    • GitHub App nameWebHooker(或自定义名称)
    • Homepage URL:你的域名
    • Webhook URLhttps://your-domain/webhook
    • Webhook secret:生成并复制到 GITHUB_WEBHOOK_SECRET
  3. 设置权限:
    • Repository permissionsContents (read)、Issues (write)、Pull requests (write)、Metadata (read)
    • Organization permissionsMembers (read) — 如需要
  4. 订阅事件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 settings
  2. 设置 Callback URLhttps://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。需要 applications.commands scope否则无法注册斜杠 / 右键菜单命令:

https://discord.com/oauth2/authorize?client_id=你的机器人CLIENT_ID&permissions=274877910016&scope=bot+applications.commands

Intents

Gateway 连接仅使用 GUILDS intent1 << 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 / 评论通知 → 应用AppsGitHub: 添加评论 / 编辑评论 / 删除评论。目标会从通知 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 让你输入 / 修改评论内容(编辑时预填原文)。

3. 合并 / 关闭 PR —— 打开状态的 PR 通知会附带 合并 / 关闭 按钮:

  • 点击按钮后以你绑定的 GitHub 账号执行合并squash或关闭操作权限交由 GitHub 判定。操作成功后通知上的按钮会被移除,结果以 ephemeral 回复显示。

要求:

项目 说明
启用 Gateway DISCORD_GATEWAY_ENABLED=true(交互通过 Gateway 送达)
邀请 scope 邀请时带上 applications.commands(见上方邀请链接)
OAuth 已配置 GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRETBASE_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