import { adminApproveSubmission } from "../../../../db/domains"; export default defineEventHandler(async (event) => { const config = useRuntimeConfig(); const adminSecret = getHeader(event, "x-admin-secret"); if (adminSecret !== config.adminSecret) { throw createError({ statusCode: 401, message: "Unauthorized" }); } const id = getRouterParam(event, "id"); if (!id) throw createError({ statusCode: 400, message: "ID fehlt" }); const body = await readBody(event).catch(() => ({})); const result = await adminApproveSubmission(id, body?.note); // Lyra-Post über die neu genehmigte Domain (fire & forget) const domain = (result as any)?.domain ?? null; const submitterUserId = (result as any)?.userId ?? null; const lyraBotUserId = config.lyraBotUserId; console.log( `[approve] domain=${domain}, lyraBotUserId=${lyraBotUserId}, hasGroq=${!!config.groqApiKey}`, ); if (domain && lyraBotUserId && config.groqApiKey) { // db + submitterName VOR der IIFE holen (usePrisma braucht Event-Kontext) const db = usePrisma(); let rawName: string | null = null; if (submitterUserId) { try { // Rebreak Prisma-Modell heißt 'profile' (nicht 'user') const submitter = await db.profile.findUnique({ where: { id: submitterUserId }, select: { nickname: true, username: true }, }); rawName = submitter?.nickname || submitter?.username || null; } catch {} } // Für @mention: Leerzeichen entfernen (Regex matcht nur einzelne Wörter) const mentionName = rawName?.replace(/\s+/g, "") ?? null; const hasMention = !!mentionName; const mentionRef = hasMention ? `@${mentionName}` : "einem Community-Mitglied"; // Stats für Lyra-Text holen let statsLine = ""; try { const stats = await db.blocklistDomain.count({ where: { isActive: true }, }); const startOfMonth = new Date(); startOfMonth.setDate(1); startOfMonth.setHours(0, 0, 0, 0); const monthlyAdded = await db.domainSubmission.count({ where: { status: "approved", reviewedAt: { gte: startOfMonth } }, }); statsLine = `Damit schützen wir gemeinsam vor ${stats.toLocaleString("de-DE")} Domains${monthlyAdded > 0 ? ` (+${monthlyAdded} diesen Monat)` : ""}.`; } catch {} const groqUserPrompt = hasMention ? `Schreibe einen kurzen Community-Post (max. 2 Sätze, auf Deutsch): Die Domain "${domain}" wurde zur ReBreak-Blockliste hinzugefügt – möglich gemacht durch ${mentionRef}. Erwähne ${mentionRef} genau einmal. Füge am Ende diesen Satz exakt ein: "${statsLine}" Warm, direkt, kein doppelter Dank.` : `Schreibe einen kurzen Community-Post (max. 2 Sätze, auf Deutsch): Die Domain "${domain}" wurde zur ReBreak-Blockliste hinzugefügt. Füge am Ende diesen Satz exakt ein: "${statsLine}" Warm, direkt.`; const groqApiKey = config.groqApiKey; (async () => { try { const response = await $fetch<{ choices: { message: { content: string } }[]; }>("https://api.groq.com/openai/v1/chat/completions", { method: "POST", headers: { Authorization: `Bearer ${groqApiKey}`, "Content-Type": "application/json", }, body: { model: "llama-3.3-70b-versatile", max_tokens: 150, messages: [ { role: "system", content: `Du bist Lyra – Recovery-Coach der ReBreak-Community. Tonalität: warm, persönlich, direkt. Schreibe NUR den Post-Text, kein Prefix, keine Anführungszeichen.`, }, { role: "user", content: groqUserPrompt, }, ], }, }); const content = response.choices?.[0]?.message?.content?.trim(); if (content) { const faviconUrl = `https://www.google.com/s2/favicons?domain=${encodeURIComponent(domain)}&sz=64`; await db.communityPost.create({ data: { userId: lyraBotUserId, category: "domain_approved", content, imageUrl: faviconUrl, isAnonymous: false, isModerated: false, }, }); console.log( `[approve] Lyra-Post erstellt für domain=${domain}, submitter=${mentionName ?? "anonym"}`, ); } } catch (err) { console.error(`[approve] Lyra-Post fehlgeschlagen:`, err); } })(); } return { ok: true }; });