from __future__ import annotations from fastapi import HTTPException, UploadFile from sqlalchemy.ext.asyncio import AsyncSession from app.enums.private_portrait import ( PrivatePortraitEventSource, PrivatePortraitEventStatus, PrivatePortraitEventType, PrivatePortraitLibraryType, ) from app.enums.upload_resource import UploadResourceModuleEnum, UploadResourceTypeEnum from app.models.user import User from app.schemas.private_portrait import PrivatePortraitUploadOut from app.services.operation_log_service import log_operation_error, log_operation_event from app.services.upload_resource import upload_reference_file DOMAIN = "private_portrait" PRIVATE_PORTRAIT_IMAGE_MAX_BYTES = 10 * 1024 * 1024 PRIVATE_PORTRAIT_VIDEO_MAX_BYTES = 100 * 1024 * 1024 def private_portrait_upload_module(library_type: str) -> str: if library_type == PrivatePortraitLibraryType.REAL_PERSON.value: return UploadResourceModuleEnum.PRIVATE_PORTRAIT_REAL.value if library_type == PrivatePortraitLibraryType.AIGC_VIRTUAL.value: return UploadResourceModuleEnum.PRIVATE_PORTRAIT_VIRTUAL.value raise HTTPException(status_code=400, detail="素材库类型不支持") async def upload_private_portrait_asset_file( db: AsyncSession, *, file: UploadFile, current_user: User, library_type: str, resource_type: str, duration_seconds: float | None = None, ) -> PrivatePortraitUploadOut: if resource_type not in {UploadResourceTypeEnum.IMAGE.value, UploadResourceTypeEnum.VIDEO.value}: raise HTTPException(status_code=400, detail="私域素材上传仅支持图片或视频") module = private_portrait_upload_module(library_type) max_bytes = PRIVATE_PORTRAIT_VIDEO_MAX_BYTES if resource_type == UploadResourceTypeEnum.VIDEO.value else PRIVATE_PORTRAIT_IMAGE_MAX_BYTES log_operation_event( domain=DOMAIN, event_type=PrivatePortraitEventType.ASSET_UPLOAD_START.value, event_status=PrivatePortraitEventStatus.PENDING.value, source=PrivatePortraitEventSource.API.value, user_id=current_user.id, detail={ "module": module, "library_type": library_type, "resource_type": resource_type, "filename": file.filename, "content_type": file.content_type, "duration_seconds": duration_seconds, }, ) try: result = await upload_reference_file( db, file=file, current_user=current_user, module=module, resource_type=resource_type, gen_type="private_portrait", duration_seconds=duration_seconds, max_bytes=max_bytes, ) out = PrivatePortraitUploadOut( url=result.url, filename=result.filename, type=result.resource_type, module=result.module, resource_id=result.resource_id, file_size_bytes=result.file_size_bytes, duration_seconds=result.duration_seconds, ) log_operation_event( domain=DOMAIN, event_type=PrivatePortraitEventType.ASSET_UPLOAD_SUCCESS.value, event_status=PrivatePortraitEventStatus.SUCCESS.value, source=PrivatePortraitEventSource.API.value, user_id=current_user.id, detail={ "module": module, "library_type": library_type, "resource_type": resource_type, "resource_id": result.resource_id, "url": result.url, "file_size_bytes": result.file_size_bytes, "duration_seconds": result.duration_seconds, }, ) return out except Exception as exc: # noqa: BLE001 log_operation_error( domain=DOMAIN, event_type=PrivatePortraitEventType.ASSET_UPLOAD_FAILED.value, source=PrivatePortraitEventSource.API.value, user_id=current_user.id, exc=exc, detail={ "module": module, "library_type": library_type, "resource_type": resource_type, "filename": file.filename, }, ) raise