99 lines
4.3 KiB
TypeScript
99 lines
4.3 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import { WhiskClient } from '@/lib/whisk-client';
|
|
|
|
export async function POST(req: Request) {
|
|
try {
|
|
const { imageBase64, mimeType, category, cookies } = await req.json();
|
|
|
|
if (!imageBase64 || !mimeType || !category || !cookies) {
|
|
const missing = [];
|
|
if (!imageBase64) missing.push('imageBase64');
|
|
if (!mimeType) missing.push('mimeType');
|
|
if (!category) missing.push('category');
|
|
if (!cookies) missing.push('cookies');
|
|
return NextResponse.json({ error: `Missing required fields: ${missing.join(', ')}` }, { status: 400 });
|
|
}
|
|
|
|
// 1. Validate MIME Type
|
|
const allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
|
|
if (!allowedTypes.includes(mimeType)) {
|
|
return NextResponse.json({ error: `Unsupported file type: ${mimeType}. Please use JPG, PNG, or WEBP.` }, { status: 400 });
|
|
}
|
|
|
|
// 2. Normalize and Validate Cookies
|
|
let validCookies = cookies.trim();
|
|
let isJson = false;
|
|
let parsedCookies = "";
|
|
|
|
// Auto-fix: Handle JSON array (e.g. from Cookie-Editor export)
|
|
if (validCookies.startsWith('[') || validCookies.startsWith('{')) {
|
|
isJson = true;
|
|
try {
|
|
const cookieArray = JSON.parse(validCookies);
|
|
|
|
if (Array.isArray(cookieArray)) {
|
|
// Convert ALL cookies to a string, not just 1PSID
|
|
parsedCookies = cookieArray
|
|
.map((c: any) => `${c.name}=${c.value}`)
|
|
.join('; ');
|
|
|
|
console.log(`[API] Successfully parsed ${cookieArray.length} cookies from JSON.`);
|
|
validCookies = parsedCookies;
|
|
|
|
} else if (cookieArray.name && cookieArray.value) {
|
|
validCookies = `${cookieArray.name}=${cookieArray.value}`;
|
|
}
|
|
} catch (e) {
|
|
console.warn("[API] Failed to parse cookie JSON, falling back to raw value:", e);
|
|
// If parsing fails, just use the raw string, maybe it's not JSON after all.
|
|
}
|
|
}
|
|
|
|
// Auto-fix: If user pasted just a raw value (heuristic)
|
|
if (!isJson && !validCookies.includes('=')) {
|
|
// If it's a long string without =, it might be a raw token.
|
|
// We can't know the key, so we might guess `__Secure-1PSID` but that failed before.
|
|
// Let's assume if it's raw, it's garbage unless we know for sure.
|
|
// But actually, we previously tried prepending. Let's keep that only if we are desperate.
|
|
// For now, let's just use what we have.
|
|
if (validCookies.length > 50) {
|
|
validCookies = `__Secure-1PSID=${validCookies}`; // Last resort guess
|
|
}
|
|
}
|
|
|
|
// 3. Relaxed Validation: Don't error if 1PSID is missing, just try.
|
|
// Some users might have different cookie names (e.g. __Secure-3PSID).
|
|
if (!validCookies.includes('=')) {
|
|
return NextResponse.json({
|
|
error: 'Invalid Cookie Format',
|
|
details: 'Cookies must be in "name=value" format or a JSON list.'
|
|
}, { status: 400 });
|
|
}
|
|
|
|
console.log(`[API] Uploading reference image (${category}, ${mimeType})...`);
|
|
console.log(`[API] Using cookies (first 50 chars): ${validCookies.substring(0, 50)}...`);
|
|
|
|
const client = new WhiskClient(validCookies);
|
|
|
|
// Remove header if present for WhiskClient (it expects clean base64 sometimes, or maybe not?
|
|
// whisk-client.ts uploadReferenceImage constructs dataUri itself: `data:${mimeType};base64,${fileBase64}`
|
|
// So we should pass RAW base64 without header.
|
|
|
|
const rawBase64 = imageBase64.replace(/^data:image\/\w+;base64,/, "");
|
|
|
|
const mediaId = await client.uploadReferenceImage(rawBase64, mimeType, category);
|
|
|
|
if (!mediaId) {
|
|
return NextResponse.json({ error: 'Upload returned no ID' }, { status: 500 });
|
|
}
|
|
|
|
return NextResponse.json({ success: true, id: mediaId });
|
|
|
|
} catch (error: any) {
|
|
console.error("Reference Upload API failed:", error);
|
|
return NextResponse.json({
|
|
error: error.message || 'Upload failed',
|
|
details: error.toString()
|
|
}, { status: 500 });
|
|
}
|
|
}
|