#!/usr/bin/env node /* * set-webhook.mjs — one-time setWebhook registration (D-16, D-17). * ----------------------------------------------------------------- * Points Telegram at the Worker's /telegram/webhook route and arms the * secret-token channel: the `secret_token` value sent here is the one * Telegram echoes back in X-Telegram-Bot-Api-Secret-Token on every update, * which the Worker's webhook adapter constant-time-compares against * env.WEBHOOK_SECRET (T-02-03). * * Inputs come from bot/.dev.vars (gitignored, D-15): BOT_TOKEN, * WEBHOOK_URL, WEBHOOK_SECRET. The bot token is never echoed — on failure * only the API's error_code/description are printed (T-02-04). * Exit 0 only when Telegram answers ok:true. */ import { readFileSync } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; function readDevVars() { const devVarsPath = path.join(fileURLToPath(new URL(import.meta.url)), "..", "..", ".dev.vars"); let raw = ""; try { raw = readFileSync(devVarsPath, "utf8"); } catch { return {}; } const vars = {}; for (const line of raw.split("\n")) { const trimmed = line.trim(); if (trimmed.length === 0 || trimmed.startsWith("#")) continue; const eq = trimmed.indexOf("="); if (eq === -1) continue; vars[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim(); } return vars; } const devVars = readDevVars(); const token = process.env.BOT_TOKEN ?? devVars.BOT_TOKEN; const webhookUrl = process.env.WEBHOOK_URL ?? devVars.WEBHOOK_URL; const secret = process.env.WEBHOOK_SECRET ?? devVars.WEBHOOK_SECRET; const missing = ["BOT_TOKEN", "WEBHOOK_URL", "WEBHOOK_SECRET"].filter( (name) => !{ BOT_TOKEN: token, WEBHOOK_URL: webhookUrl, WEBHOOK_SECRET: secret }[name], ); if (missing.length > 0) { console.error(`Missing ${missing.join(", ")} — set them in bot/.dev.vars (see .dev.vars.example; never commit).`); process.exit(1); } const payload = { url: webhookUrl, secret_token: secret, allowed_updates: ["message"], }; const res = await fetch(`https://api.telegram.org/bot${token}/setWebhook`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(payload), }); const body = await res.json(); if (!body.ok) { console.error(`setWebhook failed: ${body.error_code ?? "?"} ${body.description ?? "unknown error"}`); process.exit(1); } console.log(`setWebhook ok:true — updates will be delivered to the configured URL with the secret-token header.`); process.exit(0);