mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-23 00:21:28 +00:00
feat: add Telegram push support with multi-target routes
Add a platform-aware route target system so a single route can forward to several destinations at once (e.g. a Discord channel and a Telegram group). Route.target becomes Route.targets[] with per-entry platform, channelId/threadId for Discord and chatId/topicId for Telegram; the legacy single-target format is normalized on load and accepted by the admin API. Implement the Telegram driver with HTML rendering and Bot API sendMessage (chat_id + message_thread_id for topics, retry on 429/5xx), plus /gh commands served over POST /telegram/webhook: login, logout, comment, merge and close. The comment/merge/close commands resolve the issue or PR from the replied-to notification message. OAuth binding now stores a D1 telegram_links mapping and replies with a confirmation. Sync the Telegram webhook from the scheduled trigger via setWebhook.
This commit is contained in:
parent
dcbe93be91
commit
bd7a8f2632
39 changed files with 1165 additions and 162 deletions
45
src/drivers/telegram/updates.ts
Normal file
45
src/drivers/telegram/updates.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import type { Env } from "../../types";
|
||||
import { handleTelegramUpdate } from "./commands";
|
||||
|
||||
const MAX_BODY_SIZE = 1024 * 1024;
|
||||
|
||||
function timingSafeEqual(a: string, b: string): boolean {
|
||||
if (a.length !== b.length) return false;
|
||||
let diff = 0;
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
||||
}
|
||||
return diff === 0;
|
||||
}
|
||||
|
||||
/** Handle a POST to the Telegram webhook endpoint. */
|
||||
export async function handleTelegramWebhookRequest(request: Request, env: Env): Promise<Response> {
|
||||
const contentLength = Number(request.headers.get("content-length") ?? 0);
|
||||
if (contentLength > MAX_BODY_SIZE) {
|
||||
return new Response("Request too large", { status: 413 });
|
||||
}
|
||||
|
||||
const secret = env.TELEGRAM_WEBHOOK_SECRET;
|
||||
if (secret) {
|
||||
const token = request.headers.get("X-Telegram-Bot-Api-Secret-Token");
|
||||
if (!token || !timingSafeEqual(token, secret)) {
|
||||
return new Response("Invalid secret", { status: 401 });
|
||||
}
|
||||
}
|
||||
|
||||
const rawBody = await request.text();
|
||||
if (rawBody.length > MAX_BODY_SIZE) {
|
||||
return new Response("Request too large", { status: 413 });
|
||||
}
|
||||
|
||||
let update: unknown;
|
||||
try {
|
||||
update = JSON.parse(rawBody);
|
||||
} catch {
|
||||
return new Response("Invalid JSON", { status: 400 });
|
||||
}
|
||||
|
||||
// Telegram expects a quick 200; process commands in the background.
|
||||
await handleTelegramUpdate(env, update);
|
||||
return new Response("ok");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue