zuotang.ts 4.6 KB
import { getServerSideConfig } from "@/app/config/server";
import type { CreateTaskResponse, GetTaskResponse, GetGenerateTaskResponse, LocalData } from "../types/zuotang";
import { NextRequest, NextResponse } from "next/server";
import { error } from "console";
import { message } from "antd";
import md5 from "spark-md5";


// 类型守卫函数
function isString(value: unknown): value is string {
    return typeof value === "string";
}

// 统一错误响应生成器
function createErrorResponse(
    message: string,
    status: number,
    maxDailyUses?: number
): NextResponse<CreateTaskResponse> {
    const response: CreateTaskResponse = {
        status,
        message,
        data: { task_id: "" },
        maxDailyUses,
    };
    return NextResponse.json(response, { status, headers: { "Content-Type": "application/json" } });
}

// 处理每日使用限制逻辑
function parseDailyUsage(allowNum: string, configMax: number): number {
    if (allowNum === "first") return configMax;
    const parsed = parseInt(allowNum, 10);
    return Number.isNaN(parsed) ? configMax : parsed;
}


export async function handle(
    req: NextRequest,
    { params }: { params: { path: string[] } }
) {
    const config = getServerSideConfig();
    const baseUrl = config.bgRemovalUrl;
    const subPath = params.path.join("/");
    const reqUrl = `${baseUrl}/api/tasks/${subPath}`;

    try {
        if (req.method === "POST") {
            const formData = await req.formData();

            // 验证访问码
            const accessCode = formData.get("accessCode");
            if (!isString(accessCode) || !config.codes.has(md5.hash(accessCode))) {
                return createErrorResponse("无效访问密码!", 401);
            }

            // 解析使用限制数据
            const localData = formData.get("localData");
            if (!isString(localData)) {
                return createErrorResponse("无效请求参数", 400);
            }

            const localDataObj: LocalData = JSON.parse(localData);
            const maxDailyUses = parseDailyUsage(localDataObj.maxDailyUses, config.maxDailyUses);

            if (maxDailyUses <= 0) {
                return createErrorResponse("今日次数已用完!", 429, 0);
            }

            // 准备API请求
            const imageFile = formData.get("image_file");
            if (!(imageFile instanceof Blob)) {
                return createErrorResponse("无效图片文件", 400);
            }

            const headers = new Headers({ "X-API-KEY": config.bgRemovalApiKey });
            const newFormData = new FormData();
            newFormData.append("image_file", imageFile);

            if (subPath === "visual/r-background") {
                newFormData.append("batch_size", "1");
                const prompt = formData.get("prompt") as string;
                const trimmedPrompt = prompt ? prompt.trim() : null;
                if (!trimmedPrompt) {
                    return createErrorResponse("背景提示词不能为空!", 400);
                }
                newFormData.append("prompt", trimmedPrompt);
            }

            const response = await fetch(reqUrl, {
                headers,
                method: "POST",
                body: newFormData,
            });

            if (!response.ok) {
                throw new Error(`API请求失败: ${response.statusText}`);
            }

            const responseData: CreateTaskResponse = await response.json();
            responseData.maxDailyUses = maxDailyUses - 1;

            return NextResponse.json(responseData, {
                status: response.status,
                headers: { "Content-Type": "application/json" },
            });

        } else if (req.method === "GET") {
            const headers = { "X-API-KEY": config.bgRemovalApiKey };
            const response = await fetch(reqUrl, { headers });

            if (!response.ok) {
                throw new Error(`API请求失败: ${response.statusText}`);
            }

            const isVisualRoute = subPath.includes("visual/r-background");
            const responseData = isVisualRoute
                ? (await response.json() as GetTaskResponse)
                : (await response.json() as GetGenerateTaskResponse);

            return NextResponse.json(responseData, {
                status: response.status,
                headers: { "Content-Type": "application/json" },
            });
        }

        return createErrorResponse("方法不允许", 405);

    } catch (error) {
        console.error("请求处理错误:", error);
        return createErrorResponse(
            error instanceof Error ? error.message : "服务器内部错误",
            500
        );
    }
}