Gmagl
feat: complete Telegram AI Girlfriend mechanics & deduplication
b8b98dd
Raw
History Blame Contribute Delete
4.4 kB
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 });
}
}