Spaces:
Build error
Build error
| import { NextRequest, NextResponse } from "next/server"; | |
| import ZAI from "z-ai-web-dev-sdk"; | |
| import { db } from "@/lib/db"; | |
| import { validateUserCredit, logResourceUsage } from "@/lib/credits"; | |
| const CENSOR_RULES: Record<string, string> = { | |
| youtube: "family friendly, no nudity, no violence", | |
| tiktok: "age appropriate, no suggestive content", | |
| instagram: "community guidelines, no graphic content", | |
| twitter: "content warning if sensitive", | |
| general: "safe for work" | |
| }; | |
| export async function POST(request: NextRequest) { | |
| try { | |
| const body = await request.json(); | |
| const { prompt, optimizedPrompt, platform = "general", style = "realistic", size = "1024x1024", userId, tier = "free" } = body; | |
| if (!prompt && !optimizedPrompt) { | |
| return NextResponse.json({ success: false, error: "Se requiere un prompt" }, { status: 400 }); | |
| } | |
| // Validar créditos | |
| const creditCheck = await validateUserCredit(db, userId || "anonymous", "images_per_month", tier); | |
| if (!creditCheck.allowed) { | |
| return NextResponse.json({ success: false, error: creditCheck.reason, remaining: creditCheck.remaining }, { status: 429 }); | |
| } | |
| let finalPrompt = optimizedPrompt || prompt; | |
| // Inject Character Visual Persona | |
| const character = await db.character.findFirst({ where: { isActive: true } }); | |
| if (character?.styleDescription || character?.referenceImage) { | |
| finalPrompt = `${character.styleDescription || "AI Character"}. ${finalPrompt}`; | |
| } | |
| const censorRule = CENSOR_RULES[platform] || CENSOR_RULES.general; | |
| // Skip censorship for private/exclusive monetization platforms | |
| const uncensoredPlatforms = ["onlyfans", "fansly", "telegram-uncensored", "patreon-uncensored"]; | |
| if (!uncensoredPlatforms.includes(platform)) { | |
| finalPrompt = finalPrompt + ", " + censorRule; | |
| } | |
| const styleMap: Record<string, string> = { | |
| anime: "anime style, manga aesthetic", | |
| realistic: "photorealistic, highly detailed", | |
| artistic: "digital art, creative" | |
| }; | |
| if (styleMap[style]) finalPrompt = finalPrompt + ", " + styleMap[style]; | |
| const contentRecord = await db.content.create({ | |
| data: { | |
| type: "image", | |
| title: prompt.substring(0, 50), | |
| description: prompt, | |
| prompt: prompt, | |
| optimizedPrompt: finalPrompt, | |
| platform: platform, | |
| characterId: character?.id || null, | |
| status: "processing" | |
| } | |
| }); | |
| try { | |
| const zai = await ZAI.create(); | |
| const response = await zai.images.generations.create({ | |
| prompt: finalPrompt, | |
| size: size as "1024x1024" | |
| }); | |
| const imageBase64 = response.data[0]?.base64; | |
| if (!imageBase64) throw new Error("No se recibio imagen"); | |
| await db.content.update({ | |
| where: { id: contentRecord.id }, | |
| data: { status: "completed", filePath: "generated" } | |
| }); | |
| // Log del uso de crédito | |
| await logResourceUsage(db, userId || "anonymous", "images_per_month", contentRecord.id); | |
| await db.agentTask.create({ | |
| data: { type: "generate_image", status: "completed", input: prompt, output: "Imagen generada", completedAt: new Date() } | |
| }); | |
| return NextResponse.json({ | |
| success: true, | |
| image: { id: contentRecord.id, base64: imageBase64, prompt: finalPrompt, platform, size }, | |
| creditsRemaining: creditCheck.remaining ? creditCheck.remaining - 1 : 0 | |
| }); | |
| } catch (genError) { | |
| await db.content.update({ where: { id: contentRecord.id }, data: { status: "failed" } }); | |
| const errorMessage = genError instanceof Error ? genError.message : "Error generando imagen"; | |
| return NextResponse.json({ success: false, error: errorMessage }, { status: 500 }); | |
| } | |
| } catch (error: unknown) { | |
| const errorMessage = error instanceof Error ? error.message : "Error interno"; | |
| return NextResponse.json({ success: false, error: errorMessage }, { status: 500 }); | |
| } | |
| } | |
| export async function GET(request: NextRequest) { | |
| try { | |
| const { searchParams } = new URL(request.url); | |
| const platform = searchParams.get("platform"); | |
| const limit = Number.parseInt(searchParams.get("limit") || "20", 10); | |
| const where: Record<string, any> = { type: "image" }; | |
| if (platform) where.platform = platform; | |
| const images = await db.content.findMany({ where, orderBy: { createdAt: "desc" }, take: limit }); | |
| return NextResponse.json({ success: true, images, total: images.length }); | |
| } catch { | |
| return NextResponse.json({ success: false, error: "Error" }, { status: 500 }); | |
| } | |
| } |