import type { AlertSchwere } from "@/generated/prisma/enums"; import { formatDatum } from "@/lib/format"; import type { Nachricht } from "./kanaele"; /** * Textbausteine für Benachrichtigungen. Bewusst schlichtes HTML mit Inline-Stilen – * E-Mail-Programme ignorieren Stylesheets. */ export interface AlertNachrichtDaten { id: string; regel: string; schwere: AlertSchwere; titel: string; beschreibung: string; hostId: string | null; } const FARBE: Record = { GEFAHR: "#C82333", WARNUNG: "#FFC107", INFO: "#138496", }; const SCHWERE_TEXT: Record = { GEFAHR: "Gefahr", WARNUNG: "Warnung", INFO: "Hinweis", }; function rahmen(inhalt: string, appUrl: string): string { return `
ProxLedger · Proxmox Subscription Dashboard
${inhalt}

Dashboard öffnen

`; } /** Eine einzelne neue Warnung. */ export function alertNachricht(alert: AlertNachrichtDaten, appUrl: string): Nachricht { const betreff = `[ProxLedger] ${SCHWERE_TEXT[alert.schwere]}: ${alert.titel}`; const text = `${SCHWERE_TEXT[alert.schwere]}: ${alert.titel}\n${alert.beschreibung}\n\nRegel: ${alert.regel}\n${appUrl}/warnungen`; const html = rahmen( `

${SCHWERE_TEXT[alert.schwere]}

${alert.titel}

${alert.beschreibung}

Regel: ${alert.regel}

`, appUrl, ); return { betreff, text, html, daten: { art: "warnung", alertId: alert.id, regel: alert.regel, schwere: alert.schwere, titel: alert.titel, beschreibung: alert.beschreibung, hostId: alert.hostId, }, }; } export interface ZusammenfassungDaten { zeitraum: "taeglich" | "woechentlich"; offeneAlerts: AlertNachrichtDaten[]; neueAlerts: AlertNachrichtDaten[]; baldAblaufend: { hostname: string; kunde: string; datum: Date; tage: number }[]; offeneRechnungspunkte: number; hostsOhneMeldung: number; } /** Tägliche oder wöchentliche Zusammenfassung. */ export function zusammenfassungNachricht(daten: ZusammenfassungDaten, appUrl: string): Nachricht { const titel = daten.zeitraum === "taeglich" ? "Tagesübersicht" : "Wochenübersicht"; const betreff = `[ProxLedger] ${titel}: ${daten.offeneAlerts.length} offene Warnungen`; const zeilen = [ `${titel} vom ${formatDatum(new Date())}`, "", `Offene Warnungen: ${daten.offeneAlerts.length} (davon neu: ${daten.neueAlerts.length})`, `Offene Rechnungspunkte: ${daten.offeneRechnungspunkte}`, `Hosts ohne Meldung: ${daten.hostsOhneMeldung}`, "", "Bald ablaufende Subscriptions:", ...(daten.baldAblaufend.length > 0 ? daten.baldAblaufend.map( (e) => ` · ${e.hostname} (${e.kunde}) – ${formatDatum(e.datum)}, in ${e.tage} Tagen`, ) : [" keine in den nächsten 30 Tagen"]), "", "Offene Warnungen:", ...(daten.offeneAlerts.length > 0 ? daten.offeneAlerts.map((a) => ` · [${SCHWERE_TEXT[a.schwere]}] ${a.titel} – ${a.beschreibung}`) : [" keine"]), "", `${appUrl}/warnungen`, ]; const liste = (eintraege: string[]) => eintraege.length > 0 ? `` : `

keine

`; const html = rahmen( `

${titel}

Offene Warnungen${daten.offeneAlerts.length} (neu: ${daten.neueAlerts.length})
Offene Rechnungspunkte${daten.offeneRechnungspunkte}
Hosts ohne Meldung${daten.hostsOhneMeldung}

Bald ablaufende Subscriptions

${liste( daten.baldAblaufend.map( (e) => `${e.hostname} (${e.kunde}) – ${formatDatum(e.datum)}, in ${e.tage} Tagen`, ), )}

Offene Warnungen

${liste( daten.offeneAlerts.map( (a) => `${SCHWERE_TEXT[a.schwere]} – ${a.titel}: ${a.beschreibung}`, ), )}`, appUrl, ); return { betreff, text: zeilen.join("\n"), html, daten: { art: "zusammenfassung", zeitraum: daten.zeitraum, offeneAlerts: daten.offeneAlerts.length, neueAlerts: daten.neueAlerts.length, offeneRechnungspunkte: daten.offeneRechnungspunkte, hostsOhneMeldung: daten.hostsOhneMeldung, baldAblaufend: daten.baldAblaufend.map((e) => ({ hostname: e.hostname, kunde: e.kunde, datum: e.datum.toISOString().slice(0, 10), tage: e.tage, })), }, }; } /** Testnachricht für den Knopf „Test senden“. */ export function testNachricht(appUrl: string): Nachricht { return { betreff: "[ProxLedger] Testnachricht", text: `Diese Testnachricht bestätigt, dass der Versand funktioniert.\n${appUrl}`, html: rahmen( `

Testnachricht

Der Versand funktioniert.

`, appUrl, ), daten: { art: "test" }, }; }