chore: auto-fix lint & formatting [skip ci]

This commit is contained in:
github-actions[bot] 2026-08-13 22:46:35 +00:00
parent 6f1a334150
commit 811f8646e0
26 changed files with 304 additions and 306 deletions

View file

@ -6,12 +6,12 @@
使用任何命令前,需先绑定一次 GitHub 账号:
| 平台 | 命令 | 效果 |
|----------|----------------------------------|-------------------------------------------------------------|
| Discord | `/gh login` | 返回一条仅你可见的 OAuth 链接,用于授权 GitHub 账号 |
| Discord | `/gh logout` | 解除绑定 |
| Telegram | `/gh login`(引用一条消息) | 返回 OAuth 链接 |
| Telegram | `/gh logout`(引用一条消息) | 解除绑定 |
| 平台 | 命令 | 效果 |
| -------- | ---------------------------- | --------------------------------------------------- |
| Discord | `/gh login` | 返回一条仅你可见的 OAuth 链接,用于授权 GitHub 账号 |
| Discord | `/gh logout` | 解除绑定 |
| Telegram | `/gh login`(引用一条消息) | 返回 OAuth 链接 |
| Telegram | `/gh logout`(引用一条消息) | 解除绑定 |
链接保存在服务端KV并在 D1 中映射到你的 Discord/Telegram 用户 ID。
@ -43,12 +43,12 @@ Discord 命令为**斜杠命令**与**消息右键菜单命令**,由定时任
### 前置条件
| 项目 | 如何满足 |
|--------------|-----------------------------------------------------------------------------------------------------|
| 公钥 | 设置 `DISCORD_PUBLIC_KEY` 并配置 Interactions Endpoint URL |
| 邀请 scope | 机器人以 `applications.commands` scope 邀请(见 [Discord Bot 设置](./deployment#discord-bot-设置) |
| OAuth | 配置 `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET``BASE_URL` |
| 绑定账号 | 每位用户先执行 `/gh login` |
| 项目 | 如何满足 |
| ---------- | --------------------------------------------------------------------------------------------------- |
| 公钥 | 设置 `DISCORD_PUBLIC_KEY` 并配置 Interactions Endpoint URL |
| 邀请 scope | 机器人以 `applications.commands` scope 邀请(见 [Discord Bot 设置](./deployment#discord-bot-设置) |
| OAuth | 配置 `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET``BASE_URL` |
| 绑定账号 | 每位用户先执行 `/gh login` |
## Telegram

View file

@ -63,7 +63,7 @@ curl http://localhost:8787/health
## 可用脚本
| 脚本 | 说明 |
|------------------------|--------------------------------------|
| ---------------------- | ------------------------------------ |
| `bun run dev` | 启动 Nuxt 开发服务器 (HMR) |
| `bun run build` | 生产构建cloudflare_module preset |
| `bun run deploy` | 部署到 Cloudflare |

View file

@ -21,7 +21,7 @@
```
| 字段 | 类型 | 必需 | 说明 |
|------------------|----------|------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ---------------- | -------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `id` | string | 是 | 小写 id`a-z0-9``-`);被每条路由的 `groupId` 引用。可编辑:重命名分组会同步其路由、分组 webhook secret 与待处理邀请 |
| `name` | string | 是 | 人类可读的分组名 |
| `members` | object[] | 否 | `{ login, role }` 条目;角色为 `owner``admin``viewer` |
@ -38,7 +38,7 @@
每个分组成员拥有三种角色之一。超级管理员(`ADMIN_USER_IDS`)始终绕过这些限制。
| 角色 | 查看路由/日志 | 编辑路由 | 管理成员与邀请 | 编辑分组设置 |
|----------|---------------|----------|----------------|------------------|
| -------- | ------------- | -------- | -------------- | ---------------- |
| `owner` | ✓ | ✓ | ✓ | ✓(除 `owners` |
| `admin` | ✓ | ✓ | ✗ | ✗ |
| `viewer` | ✓(只读) | ✗ | ✗ | ✗ |

View file

@ -13,7 +13,7 @@
```jsonc
// KV 键i18n:zh
{
"events.push.title": "{repo}: 推送了 {count} 个提交到 {ref}"
"events.push.title": "{repo}: 推送了 {count} 个提交到 {ref}",
}
```

View file

@ -5,7 +5,7 @@
WebHooker 通过同一个 `POST /webhook` 端点接收多个 forge 的 webhook按请求头自动识别来源只需把各 forge 的 webhook 指向 `{BASE_URL}/webhook` 即可。
| 提供方 | 事件请求头 | 签名请求头 | 签名格式 | 密钥 |
|--------|------------------|-----------------------|----------------------------|-------------------------|
| ------ | ---------------- | --------------------- | -------------------------- | ----------------------- |
| GitHub | `X-GitHub-Event` | `X-Hub-Signature-256` | `sha256=<hex>` HMAC-SHA256 | `GITHUB_WEBHOOK_SECRET` |
| Gitea | `X-Gitea-Event` | `X-Gitea-Signature` | 纯 hex HMAC-SHA256 | `GITEA_WEBHOOK_SECRET` |
@ -51,7 +51,7 @@ Gitea 载荷会被归一化为与 GitHub 事件相同的内部结构,因此路
```
| 字段 | 类型 | 说明 |
|---------------|----------|----------------------------------------------------------------------------------------------------------|
| ------------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `title` | string | 消息标题(缺省时为 "Custom message" |
| `description` | string | 可选消息正文 |
| `color` | string | 可选嵌入颜色:颜色词(`red``green``yellow``blue``purple``orange``cyan``gray`)或 `#rrggbb` |

View file

@ -4,25 +4,25 @@
每次分发尝试都会记录到 D1 `send_logs` 表,并可在控制台(**日志**标签页)查看。字段:
| 字段 | 含义 |
|--------------|-------------------------------------------------------------|
| `routeId` | 匹配的路由 |
| `groupId` | 路由所属分组 |
| `event` | 事件类型(如 `push``pull_request``custom` |
| `repo` | 仓库全名(存在时) |
| `target` | 消息发送到的目标 id |
| `platform` | `discord``telegram` |
| `ok` | 发送是否成功 |
| `status` | 平台 API 的 HTTP 状态码(适用时) |
| `error` | 失败时的错误信息 |
| `errorCode` | 稳定错误码(如 `NO_TARGET``NO_TOKEN``RATE_LIMITED` |
| `attempts` | 含重试在内的发送次数 |
| `durationMs` | 发送耗时 |
| `deliveryId` | Webhook 投递 id提供时 |
| `messageId` | 平台消息 id用于原地编辑 |
| `actor` | 发送者登录名 |
| `action` | 事件动作(存在时) |
| `detail` | 附加 JSON 详情(存在时) |
| 字段 | 含义 |
| ------------ | -------------------------------------------------------- |
| `routeId` | 匹配的路由 |
| `groupId` | 路由所属分组 |
| `event` | 事件类型(如 `push``pull_request``custom` |
| `repo` | 仓库全名(存在时) |
| `target` | 消息发送到的目标 id |
| `platform` | `discord``telegram` |
| `ok` | 发送是否成功 |
| `status` | 平台 API 的 HTTP 状态码(适用时) |
| `error` | 失败时的错误信息 |
| `errorCode` | 稳定错误码(如 `NO_TARGET``NO_TOKEN``RATE_LIMITED` |
| `attempts` | 含重试在内的发送次数 |
| `durationMs` | 发送耗时 |
| `deliveryId` | Webhook 投递 id提供时 |
| `messageId` | 平台消息 id用于原地编辑 |
| `actor` | 发送者登录名 |
| `action` | 事件动作(存在时) |
| `detail` | 附加 JSON 详情(存在时) |
控制台的**日志**标签页列出最近记录(可按分组过滤),并可查看单条完整详情。写入为尽力而为——插入失败不会中断分发。

View file

@ -31,12 +31,12 @@
`targets` 的每一项都是一个推送目标,因此一条路由可同时转发到多个频道(例如一个 Discord 频道**和**一个 Telegram 群组)。`target.platform` 选择平台:`discord`(默认)或 `telegram`。**Discord** 目标要求 `target.channelId`(可选 `target.threadId` 指定子区);**Telegram** 目标要求 `target.chatId`(群组/超级群组 id`-1001234567890`),可选 `target.topicId`(话题的 `message_thread_id`,相当于 Discord 子区)。没有默认频道回退。
| 字段 | 类型 | 必需 | 说明 |
|------------------|----------|------|-----------------------------------------------------------------------------|
| `groupId` | string | 是 | 路由所属[分组](./groups)的 id |
| `fallback` | boolean | 否 | 为 `true` 时仅在没有其他非 fallback 路由匹配时才触发;其自身过滤器被忽略 |
| `stop` | boolean | 否 | 为 `true` 且该路由匹配时,不再评估后续路由 |
| `discordRoleIds` | string[] | 否 | 路由触发时要提醒的 Discord 身份组 id仅对 Discord 目标生效 |
| 字段 | 类型 | 必需 | 说明 |
| ---------------- | -------- | ---- | ------------------------------------------------------------------------ |
| `groupId` | string | 是 | 路由所属[分组](./groups)的 id |
| `fallback` | boolean | 否 | 为 `true` 时仅在没有其他非 fallback 路由匹配时才触发;其自身过滤器被忽略 |
| `stop` | boolean | 否 | 为 `true` 且该路由匹配时,不再评估后续路由 |
| `discordRoleIds` | string[] | 否 | 路由触发时要提醒的 Discord 身份组 id仅对 Discord 目标生效 |
## Discord 身份组提醒

View file

@ -2,34 +2,34 @@
## KV 存储布局
| 键模式 | 值 | TTL |
|---------------------------------|--------------------------------------------------------------------------------|--------------------|
| `config:routes` | 路由 JSON 数组 | 永久 |
| `config:groups` | 分组 JSON 数组 | 永久 |
| `session:{id}` | 管理员会话 `{ userId, login }` | 7 天 |
| `token:{userId}` | `{ userId, accessToken, expiresAt, refreshToken? }` | 0.9 × Token 有效期 |
| `token-reverse:{sha256}` | 用于按 Token 反查的用户 id | 0.9 × Token 有效期 |
| `state:{hex}` | `{ redirectTo, expiresAt, discordUserId?, telegramUserId?, telegramChatId? }` | 600 秒 |
| `invite:{token}` | `{ groupId, role, expiresAt, createdBy, note? }` | 7 天 |
| `invite:group:{id}` | 每组的 Token 索引(保证邀请列表一致性) | 永久 |
| `delivery:{id}` | Webhook 投递 id去重标记 | 300 秒 |
| `delivery:{groupId}:{id}` | 分组级 webhook 入口的租户级投递去重 | 300 秒 |
| `tenant:{groupId}` | 分组 webhook secret64 位 hex控制台生成 | 永久 |
| `msg:{routeId}:{key}:{target}` | 原地更新用消息 id 追踪(如 `workflow_run` / `check_run` | 7 天 |
| `cmd:guild:{id}` | 已注册命令的服务器 id去重 | 永久 |
| `cmd:registered:global` | 全局命令注册标记(去重) | 1 天 |
| `config:discord-app-id` | 缓存的 Discord 应用 id | 永久 |
| `i18n:{lang}` | 叠加在英文之上的翻译覆盖 | 永久 |
| 键模式 | 值 | TTL |
| ------------------------------ | ----------------------------------------------------------------------------- | ------------------ |
| `config:routes` | 路由 JSON 数组 | 永久 |
| `config:groups` | 分组 JSON 数组 | 永久 |
| `session:{id}` | 管理员会话 `{ userId, login }` | 7 天 |
| `token:{userId}` | `{ userId, accessToken, expiresAt, refreshToken? }` | 0.9 × Token 有效期 |
| `token-reverse:{sha256}` | 用于按 Token 反查的用户 id | 0.9 × Token 有效期 |
| `state:{hex}` | `{ redirectTo, expiresAt, discordUserId?, telegramUserId?, telegramChatId? }` | 600 秒 |
| `invite:{token}` | `{ groupId, role, expiresAt, createdBy, note? }` | 7 天 |
| `invite:group:{id}` | 每组的 Token 索引(保证邀请列表一致性) | 永久 |
| `delivery:{id}` | Webhook 投递 id去重标记 | 300 秒 |
| `delivery:{groupId}:{id}` | 分组级 webhook 入口的租户级投递去重 | 300 秒 |
| `tenant:{groupId}` | 分组 webhook secret64 位 hex控制台生成 | 永久 |
| `msg:{routeId}:{key}:{target}` | 原地更新用消息 id 追踪(如 `workflow_run` / `check_run` | 7 天 |
| `cmd:guild:{id}` | 已注册命令的服务器 id去重 | 永久 |
| `cmd:registered:global` | 全局命令注册标记(去重) | 1 天 |
| `config:discord-app-id` | 缓存的 Discord 应用 id | 永久 |
| `i18n:{lang}` | 叠加在英文之上的翻译覆盖 | 永久 |
## D1 存储布局
D1 数据库(`DB` 绑定,数据库 `webhooker`)包含四张表:
| 表 | 用途 |
|-------------------|--------------------------------------------------------------------------------------------------|
| `send_logs` | 每次分发尝试一行(路由 id、事件、目标、ok/error、耗时、错误码、详情 |
| `audit_logs` | 每次管理员操作一行(登录/登出、分组/路由/成员/邀请变更) |
| `discord_links` | 映射 `discord_user_id``github_user_id`,供 `/gh` Discord 命令使用 |
| `telegram_links` | 映射 `telegram_user_id``github_user_id`,供 `/gh` Telegram 命令使用 |
| 表 | 用途 |
| ---------------- | ---------------------------------------------------------------------- |
| `send_logs` | 每次分发尝试一行(路由 id、事件、目标、ok/error、耗时、错误码、详情 |
| `audit_logs` | 每次管理员操作一行(登录/登出、分组/路由/成员/邀请变更) |
| `discord_links` | 映射 `discord_user_id``github_user_id`,供 `/gh` Discord 命令使用 |
| `telegram_links` | 映射 `telegram_user_id``github_user_id`,供 `/gh` Telegram 命令使用 |
`audit_logs` 由定时任务在 `AUDIT_RETENTION_DAYS`(默认 90后自动清理。行字段说明见[日志](./logs)。

View file

@ -3,7 +3,7 @@
WebHooker 通过定时触发器(`*/5 * * * *`,每 5 分钟)运行三个维护任务。它们只在部署后的 Worker 上运行Cloudflare cron本地 `wrangler dev` 可用 `wrangler dev --test-scheduled` 触发。
| 任务 | 用途 |
|-----------------|---------------------------------------------------------------------------------------------------------------------|
| --------------- | ------------------------------------------------------------------------------------------------------------------- |
| `discord-sync` | 注册 Discord 斜杠/右键菜单命令按服务器即时注册并全局注册24h 去重,约 1 小时传播) |
| `telegram-sync` | 调用 `setWebhook` 指向 `{BASE_URL}/telegram/webhook`(设置了 `TELEGRAM_WEBHOOK_SECRET` 时作为 `secret_token` 传入) |
| `audit-prune` | 删除早于 `AUDIT_RETENTION_DAYS`(默认 90天的 `audit_logs` 记录 |