Spaces:
Build error
Build error
| import { NextRequest, NextResponse } from "next/server"; | |
| import { db } from "@/lib/db"; | |
| import ZAI from "z-ai-web-dev-sdk"; | |
| import { generateSocialPost } from "@/lib/content-generator"; | |
| export const maxDuration = 60; // 1 min timeout to allow generation to kick off | |
| export async function POST(request: NextRequest) { | |
| // Basic Security: Protect this route from public abuse via a secret key from n8n | |
| const authHeader = request.headers.get("authorization"); | |
| const secret = process.env.CRON_SECRET || "default_cron_secret_replace_me"; // Set CRON_SECRET in Vercel/VPS | |
| if (authHeader !== `Bearer ${secret}`) { | |
| return NextResponse.json({ success: false, error: "Unauthorized" }, { status: 401 }); | |
| } | |
| try { | |
| const character = await db.character.findFirst({ where: { isActive: true } }); | |
| if (!character) return NextResponse.json({ success: false, error: "No active character" }, { status: 400 }); | |
| // Generate the idea for today's episode | |
| const zai = await ZAI.create(); | |
| const storyPrompt = `Actúa como ${character.name}. Biografía: ${character.shortBio}. | |
| Genera una pequeña actualización de estado sobre tu día de hoy. Debe ser natural, interesante, | |
| como si fuera un diario personal breve. Max 1-2 párrafos.`; | |
| const completion = await zai.chat.completions.create({ | |
| messages: [{ role: "user", content: storyPrompt }] | |
| }); | |
| const storyText = completion.choices[0]?.message?.content || "Hoy fue un día normal."; | |
| // 1. Create a Post (Text) | |
| const socialPost = await generateSocialPost({ character, platform: "instagram", topic: storyText }); | |
| const post = await db.post.create({ | |
| data: { | |
| caption: socialPost.caption, | |
| hashtags: socialPost.hashtags ? socialPost.hashtags.join(",") : null, | |
| type: "text", | |
| status: "draft" | |
| } | |
| }); | |
| // 2. Generate a corresponding Daily Image for Instagram | |
| const imgPrompt = `${character.styleDescription}. ${storyText} selfie, photorealistic.`; | |
| const contentRecord = await db.content.create({ | |
| data: { | |
| type: "image", | |
| title: `Daily Gen: ${new Date().toISOString()}`, | |
| description: storyText, | |
| prompt: imgPrompt, | |
| optimizedPrompt: imgPrompt, | |
| platform: "instagram", | |
| characterId: character.id, | |
| status: "processing" | |
| } | |
| }); | |
| // Fire and Forget Image Generation (Run in background so Vercel doesn't timeout the webhook) | |
| zai.images.generations.create({ prompt: imgPrompt, size: "1024x1024" }) | |
| .then(async (res) => { | |
| const base64 = res.data?.[0]?.base64; | |
| if (base64) { | |
| await db.content.update({ | |
| where: { id: contentRecord.id }, | |
| data: { status: "completed", filePath: "base64-generated" } // In a real storage scenario, upload to S3/Cloudinary here | |
| }); | |
| // Potentially notify n8n here that the generation FINISHED so it can grab it | |
| const webhookUrl = process.env.N8N_WEBHOOK_URL; | |
| if (webhookUrl) { | |
| fetch(webhookUrl, { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ event: "daily_content_ready", contentId: contentRecord.id }) | |
| }).catch(e => console.error("n8n notify error", e)); | |
| } | |
| } | |
| }).catch(async (e) => { | |
| console.error("Cron image gen error:", e); | |
| await db.content.update({ | |
| where: { id: contentRecord.id }, | |
| data: { status: "failed" } | |
| }); | |
| }); | |
| return NextResponse.json({ | |
| success: true, | |
| message: "Daily generation started", | |
| story: storyText, | |
| postId: post.id, | |
| contentId: contentRecord.id | |
| }); | |
| } catch (error) { | |
| console.error("Cron Error:", error); | |
| return NextResponse.json({ success: false, error: "Server Error" }, { status: 500 }); | |
| } | |
| } | |