mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
docs: align VitePress site with REST send, optional gateway and slash commands
- deployment: drop DISCORD_CHANNEL_ID, add ADMIN_USER_IDS, PKCS#8 key note, applications.commands invite scope, and an optional Gateway section - getting-started: PKCS#8 .dev.vars example, remove channel ID - introduction: REST delivery, optional DiscordGateway DO, delivery dedup, /admin Web UI in architecture and data flow - index: refresh Workers feature, add Web UI & slash commands feature
This commit is contained in:
parent
f456c979f7
commit
d996dbe45d
8 changed files with 133 additions and 55 deletions
|
|
@ -26,13 +26,30 @@ This outputs a namespace ID. Update `wrangler.jsonc` with the ID:
|
|||
```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_PRIVATE_KEY # PKCS#8 PEM (BEGIN 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
|
||||
npx wrangler secret put ADMIN_USER_IDS # comma-separated GitHub IDs/logins allowed into the Web UI
|
||||
```
|
||||
|
||||
::: tip Target channels are configured per route
|
||||
There is no global channel secret. Each route in the [Web UI](/guide/configuration#web-ui) declares its own target channel (and optional thread), so `DISCORD_CHANNEL_ID` is not needed.
|
||||
:::
|
||||
|
||||
::: warning GitHub App private key must be PKCS#8
|
||||
GitHub issues private keys in PKCS#1 format (`BEGIN RSA PRIVATE KEY`). Cloudflare Workers' JWT signing requires PKCS#8. Convert first:
|
||||
|
||||
```bash
|
||||
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt \
|
||||
-in your-app.private-key.pem -out gh_pk_pkcs8.pem
|
||||
```
|
||||
|
||||
Then upload `gh_pk_pkcs8.pem` as `GITHUB_PRIVATE_KEY`.
|
||||
:::
|
||||
|
||||
The Discord Gateway is optional. Set `DISCORD_GATEWAY_ENABLED` in `wrangler.jsonc` `vars` (`"false"` by default). See [Gateway (optional)](#gateway-optional) below.
|
||||
|
||||
### 3. Deploy
|
||||
|
||||
```bash
|
||||
|
|
@ -81,8 +98,22 @@ Your worker is now live at `https://webhooker.<your-subdomain>.workers.dev`.
|
|||
1. Go to <https://discord.com/developers/applications>
|
||||
2. Create a new application → go to Bot section
|
||||
3. Copy the bot token to `DISCORD_TOKEN`
|
||||
4. Invite the bot to your server with `bot` scope and `Send Messages` permission
|
||||
5. Copy the target channel ID to `DISCORD_CHANNEL_ID`
|
||||
4. Invite the bot with the `bot` and `applications.commands` scopes and the `View Channels` + `Send Messages` + `Send Messages in Threads` permissions (combined integer `274877910016`):
|
||||
|
||||
```text
|
||||
https://discord.com/oauth2/authorize?client_id=YOUR_BOT_CLIENT_ID&permissions=274877910016&scope=bot+applications.commands
|
||||
```
|
||||
|
||||
5. Configure target channels **per route** in the Web UI (`/admin`) — no global channel ID is required.
|
||||
|
||||
### Gateway (optional)
|
||||
|
||||
Messages are sent via the Discord **REST API**, so pushing works with just `DISCORD_TOKEN`. The Gateway connection is only needed to (a) show the bot as **online** and (b) enable the in-Discord slash / context-menu commands.
|
||||
|
||||
- `DISCORD_GATEWAY_ENABLED=false` (default): REST-only, no Gateway connection.
|
||||
- `DISCORD_GATEWAY_ENABLED=true`: a Durable Object holds the Gateway connection and registers the `/gh` slash command plus the `GitHub: 添加/编辑/删除评论` message commands per guild.
|
||||
|
||||
When enabled, users run `/gh login` to link their GitHub account and can then comment on issues/PRs as themselves. See the [README](https://github.com/ReCloudStudio/WebHooker#bot-commands-comment-on-github-as-yourself) for the full command reference.
|
||||
|
||||
## Custom Domain (Optional)
|
||||
|
||||
|
|
|
|||
|
|
@ -30,14 +30,18 @@ Edit `.dev.vars` with your actual values:
|
|||
```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_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END 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
|
||||
ADMIN_USER_IDS=your-github-id,your-github-login
|
||||
BASE_URL=http://localhost:8787
|
||||
```
|
||||
|
||||
::: tip
|
||||
`GITHUB_PRIVATE_KEY` must be in **PKCS#8** format (`BEGIN PRIVATE KEY`). Convert a GitHub-issued PKCS#1 key with `openssl pkcs8 -topk8 -nocrypt -in app.pem -out pkcs8.pem`. Target channels are set per route in the Web UI, so no `DISCORD_CHANNEL_ID` is needed. To keep the bot online and enable `/gh` slash commands locally, also set `DISCORD_GATEWAY_ENABLED=true`.
|
||||
:::
|
||||
|
||||
::: warning
|
||||
`.dev.vars` is gitignored and contains secrets. Never commit it.
|
||||
:::
|
||||
|
|
|
|||
|
|
@ -1,40 +1,44 @@
|
|||
# Introduction
|
||||
|
||||
WebHooker is a GitHub webhook dispatcher built on Cloudflare Workers. It receives GitHub webhook events, applies configurable filters, formats them into rich Discord embeds, and routes messages to Discord channels or threads via a Durable Object-maintained Gateway connection.
|
||||
WebHooker is a GitHub webhook dispatcher built on Cloudflare Workers. It receives GitHub webhook events, applies configurable filters, formats them into rich Discord embeds, and delivers them to Discord channels or threads through the Discord REST API. An optional Durable Object holds a Gateway connection to keep the bot online and power the in-Discord `/gh` commands. Routes are managed through a built-in Web UI.
|
||||
|
||||
## Architecture
|
||||
|
||||
```text
|
||||
GitHub Webhook → Cloudflare Worker (Hono)
|
||||
├── POST /webhook → verify → filter → format → DO (Discord Gateway) → Discord
|
||||
├── POST /webhook → verify → dedup → filter → format → Discord (REST API)
|
||||
├── GET /auth/github → OAuth flow
|
||||
├── POST /api/* → user actions (Bearer token auth)
|
||||
├── /admin → routes & send-log Web UI (admin session)
|
||||
└── GET /health → status check
|
||||
|
||||
(optional) Durable Object ⇄ Discord Gateway → bot online + /gh slash & context commands
|
||||
```
|
||||
|
||||
### Components
|
||||
|
||||
| Component | Role |
|
||||
| ----------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| **Cloudflare Worker** | HTTP ingress, signature verification, event parsing, route matching |
|
||||
| **Durable Object (DiscordGateway)** | Persistent WebSocket to Discord Gateway, channel cache, message dispatch with retry |
|
||||
| **KV** | Token storage (`token:{userId}`), OAuth state (`state:{hex}`), route config (`config:routes`) |
|
||||
| Component | Role |
|
||||
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **Cloudflare Worker** | HTTP ingress, signature verification, delivery dedup, event parsing, route matching, REST send |
|
||||
| **Durable Object (DiscordGateway)** | _Optional._ Keeps the Gateway connection alive (bot online) and handles `/gh` interactions |
|
||||
| **KV** | Token storage (`token:{userId}`), OAuth state (`state:{hex}`), route config (`config:routes`), send logs, delivery dedup |
|
||||
|
||||
### Data Flow
|
||||
|
||||
1. GitHub sends a webhook to `POST /webhook`
|
||||
2. Worker verifies the HMAC-SHA256 signature
|
||||
3. Worker parses the event type and payload
|
||||
4. Routes are evaluated against filters (event, repo, actor, action, branch, keyword)
|
||||
5. Matching routes trigger formatter functions that produce Discord embeds
|
||||
6. Messages are dispatched to the Durable Object, which maintains the Gateway connection
|
||||
7. DO sends messages to Discord via REST API with rate-limit retry
|
||||
3. Worker deduplicates by `X-GitHub-Delivery` (KV, short TTL) to drop repeat deliveries
|
||||
4. Worker parses the event type and payload
|
||||
5. Routes are evaluated against filters (event, repo, actor, action, branch, keyword)
|
||||
6. Matching routes trigger formatter functions that produce Discord embeds
|
||||
7. Each message is sent to its route's target channel/thread via the Discord REST API with rate-limit retry, and the result is recorded in the send log
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Runtime**: Cloudflare Workers
|
||||
- **HTTP Framework**: Hono
|
||||
- **Discord Gateway**: Durable Object (persistent WebSocket + channel cache)
|
||||
- **Discord delivery**: Discord REST API (Gateway via optional Durable Object for online status + `/gh` commands)
|
||||
- **Web UI**: Nuxt 3 static SPA served from Worker assets
|
||||
- **Storage**: Cloudflare KV
|
||||
- **Auth**: Web Crypto API (HMAC-SHA256), jose (JWT), octokit (GitHub API)
|
||||
- **Language**: TypeScript
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue