142 lines
4.9 KiB
Python
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)
|