mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
feat(groups): per-group webhook log channel (logTarget)
Add an optional Discord channel/thread or Telegram chat/topic (Group.logTarget) that receives a summary message per webhook the group's routes dispatched: event/action, repo, delivery id and per route×target OK/FAIL lines with green/red embed color. Validated by the admin API and editable in the group editor; docs and example config updated.
This commit is contained in:
parent
b35c2c2f90
commit
0b078d938b
17 changed files with 526 additions and 35 deletions
|
|
@ -689,6 +689,29 @@ main {
|
|||
box-shadow: 0 0 0 3px var(--accent-dim);
|
||||
}
|
||||
|
||||
.field select {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: var(--radius-sm);
|
||||
color: var(--text);
|
||||
font-family: var(--ui);
|
||||
font-size: 13.5px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.field select:focus {
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 3px var(--accent-dim);
|
||||
}
|
||||
|
||||
.field select + input[type="text"],
|
||||
.field input[type="text"] + input[type="text"] {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.field .hint {
|
||||
font-size: 11px;
|
||||
color: var(--faint);
|
||||
|
|
|
|||
|
|
@ -106,6 +106,42 @@
|
|||
</div>
|
||||
<div class="hint">{{ t("groupEditor.providersHint") }}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label
|
||||
>{{ t("groupEditor.logTarget") }}
|
||||
<span class="lbl-note">{{ t("groupEditor.logTargetNote") }}</span></label
|
||||
>
|
||||
<select v-model="form.logPlatform">
|
||||
<option value="">{{ t("groupEditor.logDisabled") }}</option>
|
||||
<option value="discord">Discord</option>
|
||||
<option value="telegram">Telegram</option>
|
||||
</select>
|
||||
<template v-if="form.logPlatform === 'discord'">
|
||||
<input
|
||||
v-model="form.logChannelId"
|
||||
type="text"
|
||||
:placeholder="t('routeEditor.channelPlaceholder')"
|
||||
/>
|
||||
<input
|
||||
v-model="form.logThreadId"
|
||||
type="text"
|
||||
:placeholder="t('routeEditor.threadPlaceholder')"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="form.logPlatform === 'telegram'">
|
||||
<input
|
||||
v-model="form.logChatId"
|
||||
type="text"
|
||||
:placeholder="t('routeEditor.chatPlaceholder')"
|
||||
/>
|
||||
<input
|
||||
v-model="form.logTopicId"
|
||||
type="text"
|
||||
:placeholder="t('routeEditor.topicPlaceholder')"
|
||||
/>
|
||||
</template>
|
||||
<div class="hint">{{ t("groupEditor.logTargetHint") }}</div>
|
||||
</div>
|
||||
<div class="err">{{ formError }}</div>
|
||||
</form>
|
||||
<div class="editor-foot">
|
||||
|
|
@ -149,6 +185,11 @@ const form = reactive({
|
|||
providers: [] as ("github" | "gitea")[],
|
||||
emoji: true,
|
||||
lang: "",
|
||||
logPlatform: "" as "" | "discord" | "telegram",
|
||||
logChannelId: "",
|
||||
logThreadId: "",
|
||||
logChatId: "",
|
||||
logTopicId: "",
|
||||
});
|
||||
|
||||
function splitList(text: string): string[] {
|
||||
|
|
@ -170,6 +211,7 @@ watch(
|
|||
(open) => {
|
||||
if (!open) return;
|
||||
const g = props.group;
|
||||
const lt = g?.logTarget;
|
||||
form.id = g?.id ?? "";
|
||||
form.name = g?.name ?? "";
|
||||
form.owners = (g?.owners ?? []).join(", ");
|
||||
|
|
@ -178,6 +220,11 @@ watch(
|
|||
);
|
||||
form.emoji = g?.emoji ?? true;
|
||||
form.lang = g?.lang ?? "";
|
||||
form.logPlatform = lt?.platform ?? "";
|
||||
form.logChannelId = lt?.channelId ?? "";
|
||||
form.logThreadId = lt?.threadId ?? "";
|
||||
form.logChatId = lt?.chatId ?? "";
|
||||
form.logTopicId = lt?.topicId ?? "";
|
||||
formError.value = "";
|
||||
},
|
||||
);
|
||||
|
|
@ -198,6 +245,29 @@ function save(): void {
|
|||
formError.value = t("groupEditor.errName");
|
||||
return;
|
||||
}
|
||||
let logTarget:
|
||||
| { platform: "discord"; channelId: string; threadId?: string }
|
||||
| {
|
||||
platform: "telegram";
|
||||
chatId: string;
|
||||
topicId?: string;
|
||||
}
|
||||
| undefined;
|
||||
if (form.logPlatform === "discord") {
|
||||
const channelId = form.logChannelId.trim();
|
||||
if (!channelId) {
|
||||
formError.value = t("groupEditor.errLogChannel");
|
||||
return;
|
||||
}
|
||||
logTarget = { platform: "discord", channelId, threadId: form.logThreadId.trim() || undefined };
|
||||
} else if (form.logPlatform === "telegram") {
|
||||
const chatId = form.logChatId.trim();
|
||||
if (!chatId) {
|
||||
formError.value = t("groupEditor.errLogChat");
|
||||
return;
|
||||
}
|
||||
logTarget = { platform: "telegram", chatId, topicId: form.logTopicId.trim() || undefined };
|
||||
}
|
||||
const owners = splitList(form.owners);
|
||||
const members = props.group?.members
|
||||
? props.group.members.map((m) => ({ ...m }))
|
||||
|
|
@ -213,6 +283,7 @@ function save(): void {
|
|||
providers: form.providers.length ? form.providers : undefined,
|
||||
emoji: form.emoji,
|
||||
lang: form.lang.trim() || undefined,
|
||||
logTarget,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -168,6 +168,13 @@ const en: Dict = {
|
|||
"groupEditor.providersHint":
|
||||
"Only webhook events from the checked forges (GitHub / Gitea) enter this group's routes.",
|
||||
"groupEditor.emoji": "Show emojis in messages",
|
||||
"groupEditor.logTarget": "Webhook log channel",
|
||||
"groupEditor.logTargetNote": "(optional)",
|
||||
"groupEditor.logDisabled": "— Disabled —",
|
||||
"groupEditor.logTargetHint":
|
||||
"A Discord channel/thread or Telegram chat/topic that receives a summary of every webhook this group's routes dispatch.",
|
||||
"groupEditor.errLogChannel": "Log channel ID is required when Discord is selected",
|
||||
"groupEditor.errLogChat": "Log chat ID is required when Telegram is selected",
|
||||
"groupEditor.cancel": "Cancel",
|
||||
"groupEditor.save": "Save group",
|
||||
"groupEditor.errIdFormat": "ID must be a-z / 0-9 / dashes",
|
||||
|
|
@ -384,6 +391,13 @@ const zh: Dict = {
|
|||
"groupEditor.providersHint":
|
||||
"只有来自所勾选 forge(GitHub / Gitea)的 webhook 事件才会进入本分组的路由。",
|
||||
"groupEditor.emoji": "消息中显示表情符号",
|
||||
"groupEditor.logTarget": "Webhook 日志频道",
|
||||
"groupEditor.logTargetNote": "(可选)",
|
||||
"groupEditor.logDisabled": "— 未启用 —",
|
||||
"groupEditor.logTargetHint":
|
||||
"一个 Discord 频道/子区或 Telegram 群组/话题,本分组路由分发(dispatch)的每个 webhook 都会向其发送摘要。",
|
||||
"groupEditor.errLogChannel": "选择 Discord 时必须填写日志频道 ID",
|
||||
"groupEditor.errLogChat": "选择 Telegram 时必须填写日志群组 ID",
|
||||
"groupEditor.cancel": "取消",
|
||||
"groupEditor.save": "保存分组",
|
||||
"groupEditor.errIdFormat": "ID 只能是 a-z / 0-9 / 短横线",
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ export interface Group {
|
|||
providers?: ("github" | "gitea" | "gitlab")[];
|
||||
emoji?: boolean;
|
||||
lang?: string;
|
||||
logTarget?: RouteTarget;
|
||||
}
|
||||
|
||||
export interface GroupInvite {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue