/* RFC-0168/0181: reference Integration Port adapters. Channel adapters (Telegram, WhatsApp Cloud API). Each is fetch-based, secret-driven, and self-disables when its required secrets are absent. Email is NOT a fetch adapter — it is sent via Cloudflare Email Routing (send_email binding) in the delivery callback (RFC-0181). CRM is handled by the Lagebild destination adapter in lagebild-destination-adapter.ts. Do not import vendor SDKs or astro:env — fetch + injected secrets only. Do not log or echo secrets. RFC-0168: initial implementation. RFC-1097: step 6 — compass.migrate codemod run Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order. RFC-1097: sweep — werkstatt-engine clean Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics. */ import { formatReferrerLine, type IntegrationChannelAdapter, type IntegrationSecrets, type LeadMessage, } from "./port.ts"; function formatMessageText(message: LeadMessage): string { // RFC-1198: referral line — resolved partner name or the raw input. const referrerLine = formatReferrerLine(message.referrer); return [ "Neue Kontaktanfrage (send-message)", `Formular: ${message.formId}`, `Sprache: ${message.locale}`, `Zeit: ${message.submittedAt}`, ...(referrerLine ? [referrerLine] : []), "", message.message, ].join("\n"); } export const telegramChannelAdapter: IntegrationChannelAdapter = { id: "telegram", requiredSecrets: ["INTEGRATION_TELEGRAM_BOT_TOKEN", "INTEGRATION_TELEGRAM_CHAT_ID"], async deliver(message: LeadMessage, secrets: IntegrationSecrets): Promise { const token = secrets.INTEGRATION_TELEGRAM_BOT_TOKEN; const chatId = secrets.INTEGRATION_TELEGRAM_CHAT_ID; if (!token || !chatId) throw new Error("telegram: missing credentials"); const res = await fetch(`https://api.telegram.org/bot${token}/sendMessage`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ chat_id: chatId, text: formatMessageText(message) }), }); if (!res.ok) throw new Error(`telegram: API ${res.status}`); }, }; // RFC-0181: the Resend email channel adapter was removed. Email notifications are // sent via Cloudflare Email Routing (the `send_email` Worker binding), handled in the // delivery callback route — not as a fetch+secret channel adapter. See the email // notification step in chat-widget-section.delivery.api.ts and docs/specs/integration-delivery.md. export const whatsappChannelAdapter: IntegrationChannelAdapter = { id: "whatsapp", requiredSecrets: [ "INTEGRATION_WHATSAPP_TOKEN", "INTEGRATION_WHATSAPP_PHONE_ID", "INTEGRATION_WHATSAPP_TO", ], async deliver(message: LeadMessage, secrets: IntegrationSecrets): Promise { const token = secrets.INTEGRATION_WHATSAPP_TOKEN; const phoneId = secrets.INTEGRATION_WHATSAPP_PHONE_ID; const to = secrets.INTEGRATION_WHATSAPP_TO; if (!token || !phoneId || !to) throw new Error("whatsapp: missing credentials"); const res = await fetch(`https://graph.facebook.com/v21.0/${phoneId}/messages`, { method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" }, body: JSON.stringify({ messaging_product: "whatsapp", to, type: "text", text: { body: formatMessageText(message) }, }), }); if (!res.ok) throw new Error(`whatsapp: Cloud API ${res.status}`); }, };