feat(groups): optional forge source label in message footers

- Group.forgeLabel (default off, editable per group in the console) shows the
  source forge on every message the group's routes dispatch
- Discord embed footer: forge name next to the repo + the site's favicon as
  icon_url (Gitea instance's own favicon from its origin)
- Telegram footer: hyperlinked site name (GitHub or Gitea hostname); custom
  webhooks render a plain 'Custom' label
- forgeInfo() derives branding from event.provider + repository.html_url;
  dispatch attaches it to the NeutralMessage like mentionRoleIds
- validateGroups accepts forgeLabel booleans; GroupEditor gains the toggle
- tests: forgeInfo unit, discord/telegram footer render, dispatch on/off
- docs: groups.md + message-format.md (en/zh), config.example.yaml, AGENTS.md
- fix: wrangler.jsonc compatibility_date was an incomplete '2026-'
This commit is contained in:
RhenCloud 2026-08-14 08:10:04 +08:00
parent a5324fb0ea
commit 3dce114cec
No known key found for this signature in database
GPG key ID: A574A617378C4E0B
19 changed files with 273 additions and 16 deletions

View file

@ -30,6 +30,7 @@ Routes belong to groups. Groups scope admin access and can restrict which events
| `providers` | string[] | No | Source platforms allowed into this group (`github`, `gitea`); empty = all |
| `installationId` | number | No | GitHub App installation id bound to this group; only that installation's events are accepted (empty = all) |
| `emoji` | boolean | No | Whether to include emoji in this group's messages (default `true`) |
| `forgeLabel` | boolean | No | Whether to show the forge source (GitHub / Gitea instance / custom) in the footer of this group's messages (default `false`) |
| `lang` | string | No | Message language for every route in this group (e.g. `en`, `zh`; custom via KV `i18n:<lang>`) — see [Message Language](./i18n) — defaults to `en` |
| `logTarget` | object | No | Webhook log channel: a Discord `{ platform, channelId, threadId? }` or Telegram `{ platform, chatId, topicId? }` target that receives a summary of every webhook the group's routes dispatch |
@ -56,6 +57,16 @@ Every group member has one of three roles. Super admins (`ADMIN_USER_IDS`) alway
A group may set `logTarget` to a Discord channel/thread or Telegram chat/topic. Whenever the group's routes dispatch a webhook, a single summary message is sent there: the event type/action, the repo, the delivery id, and one line per route×target with an ✅/❌ outcome (including the error for failed sends; at most the first 10 lines are listed, the rest is summarized as `+N`). The message is green when every dispatch succeeded and red when any failed. The summary uses the group's message language. Log messages are sent best-effort and are not themselves recorded in the D1 send log.
## Forge Source Label
With `forgeLabel: true`, every message this group's routes send carries the source forge in its footer, so events from GitHub, a self-hosted Gitea instance and custom webhooks are easy to tell apart when they share a channel:
- **Discord** — the embed footer shows the forge name next to the repo (`GitHub · acme/widget`) with the site's favicon as the footer icon (for Gitea the instance's own favicon is fetched from its origin).
- **Telegram** — the footer line starts with the hyperlinked site name (`[GitHub](https://github.com)` or the Gitea instance hostname).
- **Custom** webhooks are labeled `Custom` without a link.
The label is independent of `Group.emoji` and follows every message that group dispatches (including in-place edits of workflow/check messages).
## Invites
Owners (and super admins) can create single-use invite links valid for 7 days from the group's _Members_ panel. Accepting an invite adds the user with the invited role (`admin` or `viewer` — never `owner`); an existing `viewer` is upgraded to `admin`. Invites are stored in KV as `invite:{token}`.

View file

@ -27,6 +27,10 @@ Commit hashes, branches, and tags render as inline code wrapped in a hyperlink (
Event-specific emoji are added by the formatters; per-group `Group.emoji` (default true) strips them all when disabled. Milestone progress bars are exempt. See [Message Language](./i18n).
## Forge Source Label
With `Group.forgeLabel` (default false) the message footer additionally names the source forge — GitHub, the Gitea instance hostname (hyperlinked), or a plain `Custom` — so events from different forges can be told apart. See [Groups → Forge Source Label](./groups#forge-source-label).
## In-Place Updates
`workflow_run` and `check_run` messages are sent once and edited in place as the run progresses (queued → running → success/failure) — no duplicate messages. Tracking uses KV `msg:*` with a stable `updateKey` per run.

View file

@ -30,6 +30,7 @@
| `providers` | string[] | 否 | 允许进入该分组的来源平台(`github``gitea`);空 = 全部 |
| `installationId` | number | 否 | 绑定到该分组的 GitHub App 安装 id仅接受该安装的事件空 = 全部) |
| `emoji` | boolean | 否 | 该分组消息是否包含表情(默认 `true` |
| `forgeLabel` | boolean | 否 | 是否在该分组消息的底部显示来源平台标识GitHub / Gitea 实例 / 自定义)(默认 `false` |
| `lang` | string | 否 | 该分组所有路由的消息语言(如 `en``zh`;可通过 KV `i18n:<lang>` 自定义)——见[消息语言](./i18n)——默认 `en` |
| `logTarget` | object | 否 | Webhook 日志频道Discord 目标 `{ platform, channelId, threadId? }` 或 Telegram 目标 `{ platform, chatId, topicId? }`,接收该分组路由每次分发 webhook 的摘要 |
@ -56,6 +57,16 @@
分组可以设置 `logTarget` 指向一个 Discord 频道/子区或 Telegram 群组/话题。每当该分组的路由分发dispatch一个 webhook就会向那里发送一条摘要消息事件类型/动作、仓库、投递 ID以及每条「路由 × 目标」一行的 ✅/❌ 结果(失败时附带错误信息;最多列出前 10 行,其余以 `+N` 汇总)。全部成功时消息为绿色,任一失败则为红色。摘要使用分组的消息语言。日志消息尽力发送,本身不会被记入 D1 发送日志。
## 来源平台标识
设置 `forgeLabel: true` 后,该分组路由发出的每条消息都会在底部带上来源平台,便于在共享频道中区分来自 GitHub、自建 Gitea 实例与自定义 webhook 的事件:
- **Discord** — embed 底部在仓库名旁显示平台名(`GitHub · acme/widget`),并以站点 favicon 作为底部图标Gitea 会从其实例源站获取自身 favicon
- **Telegram** — 底部行以带超链接的站点名称开头(`[GitHub](https://github.com)` 或 Gitea 实例主机名)。
- **自定义** webhook 显示为无链接的 `Custom`
该标识与 `Group.emoji` 相互独立,并跟随该分组分发的所有消息(包括工作流/检查消息的就地更新)。
## 邀请
Owner与超级管理员可以在分组的 _成员_ 面板创建单次使用、有效期 7 天的邀请链接。接受邀请后,用户以被邀请的角色(`admin``viewer`——绝不会是 `owner`)加入;已有 `viewer` 会被升级为 `admin`。邀请存储在 KV 的 `invite:{token}` 键下。

View file

@ -27,6 +27,10 @@
事件专属表情由格式化器添加;分组级 `Group.emoji`(默认开启)关闭后会全部去除。里程碑进度条不受影响。见[消息语言](./i18n)。
## 来源平台标识
设置 `Group.forgeLabel`默认关闭消息底部还会标注来源平台——GitHub、Gitea 实例主机名(带超链接)或无链接的 `Custom`——便于区分来自不同 forge 的事件。见[分组 → 来源平台标识](./groups#来源平台标识)。
## 原地更新
`workflow_run``check_run` 消息只发送一次随运行进度原地编辑queued → running → success/failure不会重复发消息。追踪使用 KV `msg:*` 与每次运行的稳定 `updateKey`