101 lines
2.8 KiB
TypeScript
101 lines
2.8 KiB
TypeScript
// server/api/images/history/[id]/public.post.ts - 生图历史公开接口:将当前用户单条生图记录发布到广场。
|
|
import type { IImagePublicStateData } from "#shared/types/openai";
|
|
import {
|
|
clearNewApiAuthCookies,
|
|
createApiLogger,
|
|
createErrorResponse,
|
|
createSuccessResponse,
|
|
createUpstreamErrorResponse,
|
|
getNewApiUserIdFromCookie,
|
|
isUnauthorizedError,
|
|
publishImageGenerationToPlaza,
|
|
toSafeLogError
|
|
} from "~~/server/utils";
|
|
|
|
/**
|
|
* POST /api/images/history/:id/public
|
|
*
|
|
* 流程:
|
|
* 1. 从 httpOnly cookie 读取当前用户 ID。
|
|
* 2. 只允许公开当前用户、未软删除的生图记录。
|
|
* 3. 允许图片尚未归档时先创建公开记录;广场列表会等 hostedImageUrl 可用后再展示。
|
|
* 4. 不返回上游响应、图床响应或内部错误详情。
|
|
*/
|
|
export default defineEventHandler(async (event) => {
|
|
const logger = createApiLogger("images.history.public.publish");
|
|
logger.info("开始");
|
|
|
|
try {
|
|
const userId = getNewApiUserIdFromCookie(event);
|
|
const recordId = parseRecordId(getRouterParam(event, "id"));
|
|
|
|
logger.info("公开参数", {
|
|
userId,
|
|
recordId: recordId.toString()
|
|
});
|
|
|
|
const result = await publishImageGenerationToPlaza(userId, recordId);
|
|
|
|
if (!result) {
|
|
logger.warn("记录不存在", {
|
|
userId,
|
|
recordId: recordId.toString()
|
|
});
|
|
return createErrorResponse(404, "生图记录不存在");
|
|
}
|
|
|
|
if (result === "REMOVED") {
|
|
logger.warn("记录已下架,不能重新公开", {
|
|
userId,
|
|
recordId: recordId.toString()
|
|
});
|
|
return createErrorResponse(403, "图片已下架,无法公开");
|
|
}
|
|
|
|
logger.done("成功", {
|
|
userId,
|
|
recordId: recordId.toString()
|
|
});
|
|
|
|
return createSuccessResponse<IImagePublicStateData>(result, "图片已公开");
|
|
} catch (error) {
|
|
if (isUnauthorizedError(error)) {
|
|
clearNewApiAuthCookies(event);
|
|
logger.warn("未登录或登录态失效", {
|
|
error: toSafeLogError(error)
|
|
});
|
|
return createErrorResponse(401, "未登录");
|
|
}
|
|
|
|
if (isBadRequestError(error)) {
|
|
return createErrorResponse(400, "生图记录 ID 不正确");
|
|
}
|
|
|
|
logger.error("失败", {
|
|
error: toSafeLogError(error)
|
|
});
|
|
return createUpstreamErrorResponse(error, "公开图片失败");
|
|
}
|
|
});
|
|
|
|
/** 校验并解析路由里的生图记录 ID */
|
|
const parseRecordId = (value: string | undefined): bigint => {
|
|
if (!value || !/^\d+$/.test(value)) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: "生图记录 ID 不正确"
|
|
});
|
|
}
|
|
|
|
return BigInt(value);
|
|
};
|
|
|
|
const isBadRequestError = (error: unknown): boolean => {
|
|
return (
|
|
typeof error === "object" &&
|
|
error !== null &&
|
|
"statusCode" in error &&
|
|
error.statusCode === 400
|
|
);
|
|
};
|