91 lines
2.6 KiB
TypeScript
91 lines
2.6 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { prisma, resolvePersona } from "@/lib/db";
|
|
import { getActiveAccountProfile } from "@/lib/account-context";
|
|
import { getOrCreateSettings } from "@/lib/user-settings";
|
|
import { optimizePost, type OptimizeMode } from "@/lib/ai/optimize-post";
|
|
import { parseProviderApiKeys } from "@/lib/ai/keys";
|
|
import { THREADS_MAX_CHARS } from "@/lib/utils";
|
|
import { trackAiTask } from "@/lib/jobs/track";
|
|
|
|
export const maxDuration = 60;
|
|
|
|
const VALID_MODES: OptimizeMode[] = ["polish", "hook", "shorter", "engaging", "custom"];
|
|
|
|
export async function POST(request: Request) {
|
|
try {
|
|
const body = await request.json();
|
|
const {
|
|
draftId,
|
|
text,
|
|
mode = "polish",
|
|
instruction,
|
|
save = false,
|
|
} = body as {
|
|
draftId?: string;
|
|
text?: string;
|
|
mode?: OptimizeMode;
|
|
instruction?: string;
|
|
save?: boolean;
|
|
};
|
|
|
|
if (!VALID_MODES.includes(mode)) {
|
|
return NextResponse.json({ error: "無效的優化模式" }, { status: 400 });
|
|
}
|
|
|
|
let sourceText = text?.trim();
|
|
let angle: string | null | undefined;
|
|
let draftRecord = null;
|
|
|
|
if (draftId) {
|
|
draftRecord = await prisma.draft.findUnique({ where: { id: draftId } });
|
|
if (!draftRecord) {
|
|
return NextResponse.json({ error: "找不到草稿" }, { status: 404 });
|
|
}
|
|
sourceText = sourceText || draftRecord.text;
|
|
angle = draftRecord.angle;
|
|
}
|
|
|
|
if (!sourceText) {
|
|
return NextResponse.json({ error: "缺少貼文內容" }, { status: 400 });
|
|
}
|
|
|
|
if (sourceText.length > THREADS_MAX_CHARS) {
|
|
return NextResponse.json({ error: `原文超過 ${THREADS_MAX_CHARS} 字上限` }, { status: 400 });
|
|
}
|
|
|
|
const settings = await getOrCreateSettings();
|
|
const account = await getActiveAccountProfile();
|
|
const apiKeys = parseProviderApiKeys(settings.providerApiKeys);
|
|
|
|
const result = await trackAiTask("AI 優化貼文", () => optimizePost({
|
|
text: sourceText,
|
|
mode,
|
|
instruction,
|
|
persona: resolvePersona(settings, account),
|
|
angle,
|
|
aiProvider: settings.aiProvider,
|
|
aiModel: settings.aiModel,
|
|
apiKeys,
|
|
}));
|
|
|
|
if (save && draftRecord) {
|
|
await prisma.draft.update({
|
|
where: { id: draftRecord.id },
|
|
data: {
|
|
text: result.text,
|
|
status: "EDITED",
|
|
},
|
|
});
|
|
}
|
|
|
|
return NextResponse.json({
|
|
text: result.text,
|
|
summary: result.summary,
|
|
saved: save && !!draftRecord,
|
|
});
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : "AI 優化失敗";
|
|
return NextResponse.json({ error: message }, { status: 500 });
|
|
}
|
|
}
|