// app/api/n8n/status/route.ts import { NextRequest, NextResponse } from "next/server"; // Cache für 30 Sekunden, damit wir n8n nicht zuspammen export const revalidate = 30; export async function GET(request: NextRequest) { // Rate limiting for n8n status endpoint const ip = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || 'unknown'; const { checkRateLimit } = await import('@/lib/auth'); if (!checkRateLimit(ip, 30, 60000)) { // 30 requests per minute for status return NextResponse.json( { error: 'Rate limit exceeded. Please try again later.' }, { status: 429 } ); } try { // Check if n8n webhook URL is configured const n8nWebhookUrl = process.env.N8N_WEBHOOK_URL; if (!n8nWebhookUrl) { // Return fallback if n8n is not configured return NextResponse.json({ status: { text: "offline", color: "gray" }, music: null, gaming: null, coding: null, }); } // Rufe den n8n Webhook auf // Add timestamp to query to bypass Cloudflare cache const res = await fetch( `${n8nWebhookUrl}/webhook/denshooter-71242/status?t=${Date.now()}`, { method: "GET", headers: { "Content-Type": "application/json", }, next: { revalidate: 30 }, }, ); if (!res.ok) { throw new Error(`n8n error: ${res.status}`); } const data = await res.json(); // n8n gibt oft ein Array zurück: [{...}]. Wir wollen nur das Objekt. const statusData = Array.isArray(data) ? data[0] : data; // Safety check: if statusData is still undefined/null (e.g. empty array), use fallback if (!statusData) { throw new Error("Empty data received from n8n"); } // Ensure coding object has proper structure if (statusData.coding && typeof statusData.coding === "object") { // Already properly formatted from n8n } else if (statusData.coding === null || statusData.coding === undefined) { // No coding data - keep as null statusData.coding = null; } return NextResponse.json(statusData); } catch (error) { console.error("Error fetching n8n status:", error); // Leeres Fallback-Objekt, damit die Seite nicht abstürzt return NextResponse.json({ status: { text: "offline", color: "gray" }, music: null, gaming: null, coding: null, }); } }