From 568e2066432b1d72e5a803a4eb968ac67a725444 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 2 Aug 2026 21:19:33 +0000 Subject: [PATCH] chore: auto-fix lint & formatting [skip ci] --- admin/components/RouteEditor.vue | 1 - admin/components/SendLogs.vue | 4 +++- docs/guide/configuration.md | 30 ++++++++++++------------- docs/zh/guide/configuration.md | 30 ++++++++++++------------- src/__tests__/telegram-commands.test.ts | 16 +++++++++---- src/__tests__/telegram.test.ts | 11 +++++---- src/core/dispatch.ts | 2 +- src/drivers/telegram/commands.ts | 24 ++++++++++++++++---- src/drivers/telegram/rest.ts | 21 ++++++++++++++--- src/github/store.ts | 9 ++++++-- 10 files changed, 98 insertions(+), 50 deletions(-) diff --git a/admin/components/RouteEditor.vue b/admin/components/RouteEditor.vue index bb1fafa..c0f20ed 100644 --- a/admin/components/RouteEditor.vue +++ b/admin/components/RouteEditor.vue @@ -312,5 +312,4 @@ function save(): void { } emit("save", route); } - diff --git a/admin/components/SendLogs.vue b/admin/components/SendLogs.vue index 80f569d..0656392 100644 --- a/admin/components/SendLogs.vue +++ b/admin/components/SendLogs.vue @@ -22,7 +22,9 @@ {{ l.routeId }} {{ l.event }} - {{ l.status }} + {{ + l.status + }} {{ fmtTime(l.ts) }}
diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 000b454..ff577c0 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -6,25 +6,25 @@ WebHooker requires several secrets to function. For local development, store the ### Required Secrets -| Variable | Description | -| ----------------------- | ----------------------------------------------- | -| `GITHUB_WEBHOOK_SECRET` | Webhook secret from your GitHub App settings | -| `GITHUB_APP_ID` | Numeric ID of your GitHub App | -| `GITHUB_PRIVATE_KEY` | App private key (PEM format, with `\n` escapes) | -| `GITHUB_CLIENT_ID` | OAuth client ID from App settings | -| `GITHUB_CLIENT_SECRET` | OAuth client secret from App settings | -| `DISCORD_TOKEN` | Discord bot token | +| Variable | Description | +| ----------------------- | ------------------------------------------------------------------ | +| `GITHUB_WEBHOOK_SECRET` | Webhook secret from your GitHub App settings | +| `GITHUB_APP_ID` | Numeric ID of your GitHub App | +| `GITHUB_PRIVATE_KEY` | App private key (PEM format, with `\n` escapes) | +| `GITHUB_CLIENT_ID` | OAuth client ID from App settings | +| `GITHUB_CLIENT_SECRET` | OAuth client secret from App settings | +| `DISCORD_TOKEN` | Discord bot token | | `TELEGRAM_TOKEN` | Telegram bot token (from BotFather) — required for Telegram routes | ### Optional Secrets -| Variable | Description | Default | -| ------------------------ | ----------------------------------------------------------------------------- | --------------------------------- | -| `DISCORD_PUBLIC_KEY` | Discord application public key (Developer Portal) — required for interactions | Unset → interactions return `401` | -| `DISCORD_APPLICATION_ID` | Discord application id; auto-resolved when omitted | Auto-resolved | -| `TELEGRAM_WEBHOOK_SECRET`| Secret token for `POST /telegram/webhook` verification (X-Telegram-Bot-Api-Secret-Token) | Disabled (no verification) | -| `BASE_URL` | Public URL for OAuth callbacks | `http://localhost:8787` | -| `ADMIN_USER_IDS` | Comma-separated GitHub user IDs (or logins) allowed to access the Web UI | Disabled | +| Variable | Description | Default | +| ------------------------- | ---------------------------------------------------------------------------------------- | --------------------------------- | +| `DISCORD_PUBLIC_KEY` | Discord application public key (Developer Portal) — required for interactions | Unset → interactions return `401` | +| `DISCORD_APPLICATION_ID` | Discord application id; auto-resolved when omitted | Auto-resolved | +| `TELEGRAM_WEBHOOK_SECRET` | Secret token for `POST /telegram/webhook` verification (X-Telegram-Bot-Api-Secret-Token) | Disabled (no verification) | +| `BASE_URL` | Public URL for OAuth callbacks | `http://localhost:8787` | +| `ADMIN_USER_IDS` | Comma-separated GitHub user IDs (or logins) allowed to access the Web UI | Disabled | ## Web UI diff --git a/docs/zh/guide/configuration.md b/docs/zh/guide/configuration.md index 0847be2..f0b5d25 100644 --- a/docs/zh/guide/configuration.md +++ b/docs/zh/guide/configuration.md @@ -6,25 +6,25 @@ WebHooker 需要多个密钥才能运行。本地开发时存储在 `.dev.vars` ### 必需密钥 -| 变量 | 说明 | -| ----------------------- | ---------------------------------- | -| `GITHUB_WEBHOOK_SECRET` | GitHub App 设置中的 Webhook 密钥 | -| `GITHUB_APP_ID` | GitHub App 的数字 ID | -| `GITHUB_PRIVATE_KEY` | App 私钥(PEM 格式,用 `\n` 转义) | -| `GITHUB_CLIENT_ID` | App 设置中的 OAuth 客户端 ID | -| `GITHUB_CLIENT_SECRET` | App 设置中的 OAuth 客户端密钥 | -| `DISCORD_TOKEN` | Discord Bot Token | +| 变量 | 说明 | +| ----------------------- | -------------------------------------------------------- | +| `GITHUB_WEBHOOK_SECRET` | GitHub App 设置中的 Webhook 密钥 | +| `GITHUB_APP_ID` | GitHub App 的数字 ID | +| `GITHUB_PRIVATE_KEY` | App 私钥(PEM 格式,用 `\n` 转义) | +| `GITHUB_CLIENT_ID` | App 设置中的 OAuth 客户端 ID | +| `GITHUB_CLIENT_SECRET` | App 设置中的 OAuth 客户端密钥 | +| `DISCORD_TOKEN` | Discord Bot Token | | `TELEGRAM_TOKEN` | Telegram Bot Token(BotFather 获取)—— Telegram 路由必需 | ### 可选密钥 -| 变量 | 说明 | 默认值 | -| ------------------------ | ------------------------------------------------------ | ----------------------- | -| `BASE_URL` | OAuth 回调的公开 URL | `http://localhost:8787` | -| `ADMIN_USER_IDS` | 允许访问 WebUI 的 GitHub 用户 ID(或登录名),逗号分隔 | 未设置时 WebUI 关闭 | -| `DISCORD_PUBLIC_KEY` | Discord 应用的公钥(开发者门户获取),交互功能必需 | 未设置时交互返回 401 | -| `DISCORD_APPLICATION_ID` | Discord 应用 ID;省略时自动获取 | 自动获取 | -| `TELEGRAM_WEBHOOK_SECRET`| `POST /telegram/webhook` 验签密钥(X-Telegram-Bot-Api-Secret-Token) | 未设置时不校验 | +| 变量 | 说明 | 默认值 | +| ------------------------- | -------------------------------------------------------------------- | ----------------------- | +| `BASE_URL` | OAuth 回调的公开 URL | `http://localhost:8787` | +| `ADMIN_USER_IDS` | 允许访问 WebUI 的 GitHub 用户 ID(或登录名),逗号分隔 | 未设置时 WebUI 关闭 | +| `DISCORD_PUBLIC_KEY` | Discord 应用的公钥(开发者门户获取),交互功能必需 | 未设置时交互返回 401 | +| `DISCORD_APPLICATION_ID` | Discord 应用 ID;省略时自动获取 | 自动获取 | +| `TELEGRAM_WEBHOOK_SECRET` | `POST /telegram/webhook` 验签密钥(X-Telegram-Bot-Api-Secret-Token) | 未设置时不校验 | ## Web 控制台 diff --git a/src/__tests__/telegram-commands.test.ts b/src/__tests__/telegram-commands.test.ts index 7e6912b..a861bd0 100644 --- a/src/__tests__/telegram-commands.test.ts +++ b/src/__tests__/telegram-commands.test.ts @@ -38,14 +38,18 @@ function createMockDB(): D1Database { prepare: (sql: string) => ({ bind: (...args: unknown[]) => ({ run: async (): Promise<{ success: boolean }> => { - const m = sql.match(/INSERT OR REPLACE INTO telegram_links \(telegram_user_id, github_user_id\) VALUES \(\?, \?\)/); + const m = sql.match( + /INSERT OR REPLACE INTO telegram_links \(telegram_user_id, github_user_id\) VALUES \(\?, \?\)/, + ); if (m) links.set(String(args[0]), String(args[1])); const del = sql.match(/DELETE FROM telegram_links WHERE telegram_user_id = \?/); if (del) links.delete(String(args[0])); return { success: true }; }, all: async (): Promise<{ results: Array> }> => { - const sel = sql.match(/SELECT github_user_id FROM telegram_links WHERE telegram_user_id = \?/); + const sel = sql.match( + /SELECT github_user_id FROM telegram_links WHERE telegram_user_id = \?/, + ); if (sel) { const val = links.get(String(args[0])); return { results: val ? [{ github_user_id: val }] : [] }; @@ -146,7 +150,9 @@ describe("telegram-commands /gh comment", () => { mockFetch((url, init) => { calls.push({ url, body: String(init!.body) }); if (String(url).endsWith("/sendMessage")) { - return new Response(JSON.stringify({ ok: true, result: { message_id: 1 } }), { status: 200 }); + return new Response(JSON.stringify({ ok: true, result: { message_id: 1 } }), { + status: 200, + }); } return new Response( JSON.stringify({ html_url: "https://github.com/acme/widget/issues/7#issuecomment-9" }), @@ -185,7 +191,9 @@ describe("telegram-updates webhook", () => { }); it("accepts requests with the correct secret token", async () => { - mockFetch(() => new Response(JSON.stringify({ ok: true, result: { message_id: 1 } }), { status: 200 })); + mockFetch( + () => new Response(JSON.stringify({ ok: true, result: { message_id: 1 } }), { status: 200 }), + ); const env = createEnv(); const res = await handleTelegramWebhookRequest( new Request("https://example.com/telegram/webhook", { diff --git a/src/__tests__/telegram.test.ts b/src/__tests__/telegram.test.ts index 7cf0708..bd9841c 100644 --- a/src/__tests__/telegram.test.ts +++ b/src/__tests__/telegram.test.ts @@ -23,14 +23,16 @@ describe("telegram renderNeutralMessage", () => { footer: "acme/widget", }; const out = renderNeutralMessage(message); - expect(out).toContain('acme/widget: Add feature'); + expect(out).toContain( + 'acme/widget: Add feature', + ); expect(out).toContain("Status: success"); expect(out).toContain("acme/widget"); }); it("escapes HTML special characters", () => { const out = renderNeutralMessage({ - title: "a & \"c\"", + title: 'a & "c"', fields: [{ name: "body", value: "" }], }); expect(out).not.toContain("acme"); @@ -76,8 +78,9 @@ describe("telegram-rest sendMessage", () => { }); it("returns error on non-ok response", async () => { - mockFetch(() => - new Response(JSON.stringify({ ok: false, description: "chat not found" }), { status: 400 }), + mockFetch( + () => + new Response(JSON.stringify({ ok: false, description: "chat not found" }), { status: 400 }), ); const result = await sendMessage("t", "-100123", "hello"); expect(result.ok).toBe(false); diff --git a/src/core/dispatch.ts b/src/core/dispatch.ts index 4218ab8..5be7742 100644 --- a/src/core/dispatch.ts +++ b/src/core/dispatch.ts @@ -72,7 +72,7 @@ export async function dispatchEvent(config: Config, event: WebhookEvent, env: En target: targetStr, deliveryId: event.deliveryId, actor: (event.payload.sender as { login?: string } | undefined)?.login, - action: (event.payload.action as string | undefined), + action: event.payload.action as string | undefined, }; const started = Date.now(); diff --git a/src/drivers/telegram/commands.ts b/src/drivers/telegram/commands.ts index 75dbc82..81657e8 100644 --- a/src/drivers/telegram/commands.ts +++ b/src/drivers/telegram/commands.ts @@ -54,7 +54,12 @@ function extractTarget(msg: TelegramMessage, prOnly = false): Target | null { return null; } -async function reply(env: Env, chatId: string, topicId: string | undefined, text: string): Promise { +async function reply( + env: Env, + chatId: string, + topicId: string | undefined, + text: string, +): Promise { await sendMessage(env.TELEGRAM_TOKEN ?? "", chatId, text, topicId); } @@ -73,7 +78,8 @@ async function cmdLogin(env: Env, msg: TelegramMessage): Promise { const topicId = msg.message_thread_id != null ? String(msg.message_thread_id) : undefined; const clientId = env.GITHUB_CLIENT_ID; - if (!clientId) return reply(env, chatId, topicId, "服务器未配置 GitHub OAuth(GITHUB_CLIENT_ID)。"); + if (!clientId) + return reply(env, chatId, topicId, "服务器未配置 GitHub OAuth(GITHUB_CLIENT_ID)。"); const state = crypto.randomUUID().replace(/-/g, ""); await env.KV.put( @@ -87,7 +93,12 @@ async function cmdLogin(env: Env, msg: TelegramMessage): Promise { { expirationTtl: 600 }, ); const url = getOAuthURL(clientId, state); - await reply(env, chatId, topicId, `点击链接授权 GitHub,即可用**本人身份**评论(10 分钟内有效):\n${url}`); + await reply( + env, + chatId, + topicId, + `点击链接授权 GitHub,即可用**本人身份**评论(10 分钟内有效):\n${url}`, + ); } async function cmdLogout(env: Env, msg: TelegramMessage): Promise { @@ -165,7 +176,12 @@ async function cmdMergeClose(env: Env, msg: TelegramMessage, op: "merge" | "clos await closePullRequestAsUser(env.KV, githubUserId, target.owner, target.repo, target.number); } const label = op === "merge" ? "合并" : "关闭"; - await reply(env, chatId, topicId, `✅ 已${label} PR ${target.owner}/${target.repo}#${target.number}`); + await reply( + env, + chatId, + topicId, + `✅ 已${label} PR ${target.owner}/${target.repo}#${target.number}`, + ); } catch (err) { await reply(env, chatId, topicId, errText(err)); } diff --git a/src/drivers/telegram/rest.ts b/src/drivers/telegram/rest.ts index 217575e..4c67f70 100644 --- a/src/drivers/telegram/rest.ts +++ b/src/drivers/telegram/rest.ts @@ -52,7 +52,10 @@ export async function sendMessage( if (!res.ok) { lastError = data?.description ?? `HTTP ${res.status}`; - log.error({ status: res.status, err: lastError, chatId, attempts: attempt + 1 }, "Telegram API error"); + log.error( + { status: res.status, err: lastError, chatId, attempts: attempt + 1 }, + "Telegram API error", + ); return { ok: false, error: lastError, @@ -72,11 +75,23 @@ export async function sendMessage( lastError = err instanceof Error ? err.message : String(err); log.error({ err, chatId, attempts: attempt + 1 }, "Failed to send Telegram message"); if (attempt === 2) { - return { ok: false, error: lastError, errorCode: "NETWORK", status: lastStatus, attempts: attempt + 1 }; + return { + ok: false, + error: lastError, + errorCode: "NETWORK", + status: lastStatus, + attempts: attempt + 1, + }; } await new Promise((r) => setTimeout(r, 500 * (attempt + 1))); } } - return { ok: false, error: lastError || "Failed to send Telegram message", errorCode: "RETRIES", status: lastStatus, attempts: 3 }; + return { + ok: false, + error: lastError || "Failed to send Telegram message", + errorCode: "RETRIES", + status: lastStatus, + attempts: 3, + }; } diff --git a/src/github/store.ts b/src/github/store.ts index 3a35cea..dd7df4b 100644 --- a/src/github/store.ts +++ b/src/github/store.ts @@ -104,7 +104,9 @@ export async function saveTelegramLink( githubUserId: string, ): Promise { await db - .prepare("INSERT OR REPLACE INTO telegram_links (telegram_user_id, github_user_id) VALUES (?, ?)") + .prepare( + "INSERT OR REPLACE INTO telegram_links (telegram_user_id, github_user_id) VALUES (?, ?)", + ) .bind(telegramUserId, githubUserId) .run(); } @@ -121,5 +123,8 @@ export async function getTelegramLink( } export async function removeTelegramLink(db: D1Database, telegramUserId: string): Promise { - await db.prepare("DELETE FROM telegram_links WHERE telegram_user_id = ?").bind(telegramUserId).run(); + await db + .prepare("DELETE FROM telegram_links WHERE telegram_user_id = ?") + .bind(telegramUserId) + .run(); }