74 lines · 3.0 KB
import { createAddress } from "../../core/db.ts";
import { buildCommandConfig } from "../../core/config.ts";
import type { SqlExecutor } from "../../core/storage.ts";
import { createMailtmAddress } from "../../receivers/mailtm/address.ts";
import { sendMessage } from "./telegram-rest.ts";
import { handleUpdate, type TelegramUpdate } from "./commands.ts";

export interface TelegramWebhookEnv {
  DISPOSABLE_DOMAIN?: string;
  // Optional at the type level since a Worker not handling Telegram at all
  // (e.g. Discord-only) has no reason to set it -- but a request that
  // reaches this handler needs a real value, or every secret-token check
  // fails closed, since undefined can never equal a header value.
  TELEGRAM_BOT_TOKEN?: string;
  // Telegram echoes this back on every webhook call so a request can be
  // confirmed as actually coming from Telegram, not just anyone who finds
  // the URL. Set with `wrangler secret put TELEGRAM_WEBHOOK_SECRET`, then
  // pass the same value as setWebhook's own secret_token parameter.
  TELEGRAM_WEBHOOK_SECRET?: string;
  [key: string]: unknown;
}

function usesOwnDomain(env: TelegramWebhookEnv): boolean {
  return !!env.DISPOSABLE_DOMAIN && env.DISPOSABLE_DOMAIN.trim() !== "";
}

// Shared by both src/worker.ts (Telegram-only or Telegram+Discord on one
// Worker) and src/telegram-worker.ts (Telegram split onto its own Worker,
// for whoever wants Discord and Telegram bundle-isolated from each other).
// Same handler either way; only which Worker's fetch() calls it differs.
export async function handleTelegramWebhookRequest(
  request: Request,
  env: TelegramWebhookEnv,
  db: SqlExecutor
): Promise<Response> {
  if (!env.TELEGRAM_BOT_TOKEN || !env.TELEGRAM_WEBHOOK_SECRET) {
    return new Response("Telegram not configured on this Worker", { status: 500 });
  }

  const secretHeader = request.headers.get("X-Telegram-Bot-Api-Secret-Token");