/** * Notification ntfy.sh — remplace Resend (abandonné le 15/07, domaine non vérifié). * POST https://ntfy.sh/${NTFY_TOPIC} * * RÈGLE : un topic ntfy est une URL, pas un coffre — le message ne contient * JAMAIS l'email du contributeur ni le texte libre soumis. Seulement des * métadonnées de modération (id NocoDB, nom suggéré, type, nb de liens). * * Si NTFY_TOPIC est absent : log et continue (pas d'erreur bloquante). */ export interface NtfyNotifyInput { title: string message: string /** Priorité ntfy 1-5 (3 = défaut) */ priority?: number tags?: string[] /** Lien cliqué depuis la notif (ex : NocoDB) */ clickUrl?: string } export async function notifyNtfy(topic: string | undefined, input: NtfyNotifyInput): Promise { if (!topic) { console.warn('[notify] NTFY_TOPIC absent — notification skippée:', input.title) return } try { const headers: Record = { Title: encodeHeaderValue(input.title), Priority: String(input.priority ?? 3), } if (input.tags?.length) headers.Tags = input.tags.join(',') if (input.clickUrl) headers.Click = input.clickUrl const res = await fetch(`https://ntfy.sh/${topic}`, { method: 'POST', headers, body: input.message, }) if (!res.ok) { console.warn('[notify] ntfy erreur HTTP:', res.status, await res.text()) } } catch (e: any) { console.warn('[notify] ntfy exception:', e?.message ?? e) } } /** * Construit le message de notification pour une nouvelle soumission. * N'inclut jamais l'email ni le texte libre du contributeur. */ export function buildSubmissionNotif(input: { submissionId: number | string | null nomSuggere: string typeSuggere: string nbLiens: number nocodbAdminUrl?: string }): NtfyNotifyInput { const { submissionId, nomSuggere, typeSuggere, nbLiens, nocodbAdminUrl } = input return { title: '[AEP] Nouvelle fiche soumise', message: [ `Id NocoDB : ${submissionId ?? '—'}`, `Nom suggéré : ${nomSuggere}`, `Type suggéré : ${typeSuggere}`, `Liens : ${nbLiens}`, ].join('\n'), tags: ['inbox_tray'], clickUrl: nocodbAdminUrl, } } function encodeHeaderValue(v: string): string { // ntfy accepte l'UTF-8 dans les headers mais certains proxies sont capricieux // avec les accents en header brut — on reste simple, ntfy gère nativement. return v }