o2o-castad-backend/app/social/api/routers/v1/upload.py

142 lines
4.9 KiB
Python

"""
소셜 업로드 API 라우터
소셜 미디어 영상 업로드 관련 엔드포인트를 제공합니다.
비즈니스 로직은 SocialUploadService에 위임합니다.
"""
import logging
from typing import Optional
from fastapi import APIRouter, BackgroundTasks, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession
from app.database.session import get_session
from app.social.constants import SocialPlatform
from app.social.schemas import (
MessageResponse,
SocialUploadHistoryResponse,
SocialUploadRequest,
SocialUploadResponse,
SocialUploadStatusResponse,
)
from app.social.services import SocialUploadService, social_account_service
from app.user.dependencies import get_current_user
from app.user.models import User
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/upload", tags=["Social Upload"])
upload_service = SocialUploadService(account_service=social_account_service)
@router.post(
"",
response_model=SocialUploadResponse,
summary="소셜 플랫폼에 영상 업로드 요청",
description="""
영상을 소셜 미디어 플랫폼에 업로드합니다.
## 사전 조건
- 해당 플랫폼에 계정이 연동되어 있어야 합니다
- 영상이 completed 상태여야 합니다 (result_movie_url 필요)
## 요청 필드
- **video_id**: 업로드할 영상 ID
- **social_account_id**: 업로드할 소셜 계정 ID (연동 계정 목록 조회 API에서 확인)
- **title**: 영상 제목 (최대 100자)
- **description**: 영상 설명 (최대 5000자)
- **tags**: 태그 목록
- **privacy_status**: 공개 상태 (public, unlisted, private)
- **scheduled_at**: 예약 게시 시간 (선택사항)
## 업로드 상태
업로드는 백그라운드에서 처리되며, 상태를 폴링하여 확인할 수 있습니다:
- `pending`: 업로드 대기 중
- `uploading`: 업로드 진행 중
- `processing`: 플랫폼에서 처리 중
- `completed`: 업로드 완료
- `failed`: 업로드 실패
""",
)
async def upload_to_social(
body: SocialUploadRequest,
background_tasks: BackgroundTasks,
current_user: User = Depends(get_current_user),
session: AsyncSession = Depends(get_session),
) -> SocialUploadResponse:
return await upload_service.request_upload(body, current_user, session, background_tasks)
@router.get(
"/{upload_id}/status",
response_model=SocialUploadStatusResponse,
summary="업로드 상태 조회",
description="특정 업로드 작업의 상태를 조회합니다.",
)
async def get_upload_status(
upload_id: int,
current_user: User = Depends(get_current_user),
session: AsyncSession = Depends(get_session),
) -> SocialUploadStatusResponse:
return await upload_service.get_upload_status(upload_id, current_user, session)
@router.get(
"/history",
response_model=SocialUploadHistoryResponse,
summary="업로드 이력 조회",
description="""
사용자의 소셜 미디어 업로드 이력을 조회합니다.
## tab 파라미터
- `all`: 전체 (기본값)
- `completed`: 완료된 업로드
- `scheduled`: 예약 업로드 (pending + scheduled_at 있음)
- `failed`: 실패한 업로드
""",
)
async def get_upload_history(
current_user: User = Depends(get_current_user),
session: AsyncSession = Depends(get_session),
tab: str = Query("all", description="탭 필터 (all/completed/scheduled/failed)"),
platform: Optional[SocialPlatform] = Query(None, description="플랫폼 필터"),
year: Optional[int] = Query(None, description="조회 연도 (없으면 현재 연도)"),
month: Optional[int] = Query(None, ge=1, le=12, description="조회 월 (없으면 현재 월)"),
page: int = Query(1, ge=1, description="페이지 번호"),
size: int = Query(20, ge=1, le=100, description="페이지 크기"),
) -> SocialUploadHistoryResponse:
return await upload_service.get_upload_history(
current_user, session, tab, platform, year, month, page, size
)
@router.post(
"/{upload_id}/retry",
response_model=SocialUploadResponse,
summary="업로드 재시도",
description="실패한 업로드를 재시도합니다.",
)
async def retry_upload(
upload_id: int,
background_tasks: BackgroundTasks,
current_user: User = Depends(get_current_user),
session: AsyncSession = Depends(get_session),
) -> SocialUploadResponse:
return await upload_service.retry_upload(upload_id, current_user, session, background_tasks)
@router.delete(
"/{upload_id}",
response_model=MessageResponse,
summary="업로드 취소",
description="대기 중인 업로드를 취소합니다.",
)
async def cancel_upload(
upload_id: int,
current_user: User = Depends(get_current_user),
session: AsyncSession = Depends(get_session),
) -> MessageResponse:
return await upload_service.cancel_upload(upload_id, current_user, session)