/* ===================================================================== lib/ticketanizer.js — Bewerbungen als echtes Ticket bei Ticketanizer eröffnen (dort in Discord sichtbar, pro Bewerbungsbereich ein eigenes Panel/Board). API-Doku (aus dem Ticketanizer-Dashboard, "API & Webhooks" → "API-Keys" → "So nutzt du sie"): Basis-URL: https://api.ticketanizer.com POST /v1/tickets Header: X-API-Key, Content-Type: application/json Body: { panel_id, visitor_name, first_message } Wir nutzen hier bewusst NUR den ersten Schritt (Ticket eröffnen) — es ist eine einmalige Bewerbung, kein Live-Chat, deshalb kein Nachladen von Staff-Antworten nötig (das würde einen dauerhaft laufenden Prozess brauchen, den ein Cloudflare Worker so nicht hat). panel_id pro Bewerbungsbereich (aus dem Ticketanizer-Dashboard → "Panels", von Dogi am 2026-08-01 abgelesen): 4 = Modi-Bewerbung 5 = Kooperationsbewerbung 6 = Scout-Bewerbung 7 = Manager-Bewerbung (= unsere "Creator"-Bewerbung: Streamer sucht einen Manager bei Spicy Media) Rein informativ, kein Ausfallpunkt: Fehlt der API-Key, oder schlägt der Versand fehl (Ticketanizer down, falscher Key, ...), wird die Bewerbung trotzdem ganz normal in der eigenen Datenbank gespeichert. ===================================================================== */ const TICKETANIZER_BASIS_URL = "https://api.ticketanizer.com"; const PANEL_IDS = { modi: 4, kooperation: 5, scout: 6, creator: 7, // "Manager-Bewerbung" bei Ticketanizer }; // Menschlich lesbare Feldbeschriftungen für alle Formularfelder, die aktuell // auf der Website vorkommen (siehe bewerben-*.html, jeweils name="..."). // Unbekannte Feldnamen (z.B. nach künftigen Formular-Änderungen) werden // einfach unverändert als Beschriftung übernommen statt zu fehlen. const FIELD_LABELS = { name: "Name", email: "E-Mail", kontakt: "Kontakt (Discord/TikTok)", erfahrung: "Erfahrung", verfuegbarkeit: "Verfügbarkeit", warum: "Warum möchtest du dabei sein?", platform: "Plattform", content: "Content-Art", firma: "Firma / Projekt", idee: "Idee / Anliegen", }; function ersteNachrichtAufbauen(type, data) { const zeilen = Object.entries(data || {}) .filter(([, v]) => String(v ?? "").trim() !== "") .map(([key, value]) => `**${FIELD_LABELS[key] || key}:** ${String(value).trim()}`); if (!zeilen.length) zeilen.push("_Keine weiteren Angaben übermittelt._"); // Ticketanizer-Nachrichten sind vermutlich nicht beliebig lang — sicherheitshalber // deckeln, damit ein sehr langer Freitext (z.B. "warum") den Versand nicht sprengt. const text = zeilen.join("\n"); return text.length > 3500 ? text.slice(0, 3500) + "…" : text; } export async function bewerbungAlsTicketAnlegen(env, type, data) { const apiKey = env.TICKETANIZER_API_KEY; const panelId = PANEL_IDS[type]; if (!apiKey) { console.error(`[ticketanizer] TICKETANIZER_API_KEY fehlt — Ticket für "${type}" übersprungen.`); return; } if (!panelId) { console.error(`[ticketanizer] Kein panel_id für Bewerbungstyp "${type}" hinterlegt — übersprungen.`); return; } const visitorName = String(data?.name || data?.firma || "Unbekannt").trim().slice(0, 80) || "Unbekannt"; const firstMessage = ersteNachrichtAufbauen(type, data); try { const antwort = await fetch(`${TICKETANIZER_BASIS_URL}/v1/tickets`, { method: "POST", headers: { "X-API-Key": apiKey, "Content-Type": "application/json", }, body: JSON.stringify({ panel_id: panelId, visitor_name: visitorName, first_message: firstMessage, }), }); const antwortText = await antwort.text().catch(() => ""); if (!antwort.ok) { console.error(`[ticketanizer] Fehler beim Ticket-Anlegen (${type}, panel ${panelId}): HTTP ${antwort.status} — ${antwortText}`); } else { console.log(`[ticketanizer] Ticket angelegt (${type}, panel ${panelId}): ${antwortText}`); } } catch (fehler) { // Ticketanizer nicht erreichbar o.ä. — die Bewerbung selbst ist trotzdem // sicher in der eigenen Datenbank gelandet, das darf hier nicht scheitern. console.error(`[ticketanizer] Ausnahme beim Ticket-Anlegen (${type}, panel ${panelId}):`, fehler && fehler.message); } }