149 lines
3.9 KiB
Python
149 lines
3.9 KiB
Python
"""
|
|
SNS API Schemas
|
|
|
|
Instagram 업로드 관련 Pydantic 스키마를 정의합니다.
|
|
"""
|
|
from datetime import datetime
|
|
from typing import Any, Optional
|
|
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
|
|
|
|
class InstagramUploadRequest(BaseModel):
|
|
"""Instagram 업로드 요청 스키마
|
|
|
|
Usage:
|
|
POST /sns/instagram/upload/{task_id}
|
|
Instagram에 비디오를 업로드합니다.
|
|
|
|
Example Request:
|
|
{
|
|
"caption": "Test video from Instagram POC #test",
|
|
"share_to_feed": true
|
|
}
|
|
"""
|
|
|
|
model_config = ConfigDict(
|
|
json_schema_extra={
|
|
"example": {
|
|
"caption": "Test video from Instagram POC #test",
|
|
"share_to_feed": True,
|
|
}
|
|
}
|
|
)
|
|
|
|
caption: str = Field(
|
|
default="",
|
|
description="게시물 캡션",
|
|
max_length=2200,
|
|
)
|
|
share_to_feed: bool = Field(
|
|
default=True,
|
|
description="피드에 공유 여부",
|
|
)
|
|
|
|
|
|
class InstagramUploadResponse(BaseModel):
|
|
"""Instagram 업로드 응답 스키마
|
|
|
|
Usage:
|
|
POST /sns/instagram/upload/{task_id}
|
|
Instagram 업로드 작업의 결과를 반환합니다.
|
|
|
|
Example Response (성공):
|
|
{
|
|
"task_id": "0694b716-dbff-7219-8000-d08cb5fce431",
|
|
"state": "completed",
|
|
"message": "Instagram 업로드 완료",
|
|
"media_id": "17841405822304914",
|
|
"permalink": "https://www.instagram.com/p/ABC123/",
|
|
"error": null
|
|
}
|
|
"""
|
|
|
|
model_config = ConfigDict(
|
|
json_schema_extra={
|
|
"example": {
|
|
"task_id": "0694b716-dbff-7219-8000-d08cb5fce431",
|
|
"state": "completed",
|
|
"message": "Instagram 업로드 완료",
|
|
"media_id": "17841405822304914",
|
|
"permalink": "https://www.instagram.com/p/ABC123/",
|
|
"error": None,
|
|
}
|
|
}
|
|
)
|
|
|
|
task_id: str = Field(..., description="작업 고유 식별자")
|
|
state: str = Field(..., description="업로드 상태 (pending, processing, completed, failed)")
|
|
message: str = Field(..., description="상태 메시지")
|
|
media_id: Optional[str] = Field(default=None, description="Instagram 미디어 ID (성공 시)")
|
|
permalink: Optional[str] = Field(default=None, description="Instagram 게시물 URL (성공 시)")
|
|
error: Optional[str] = Field(default=None, description="에러 메시지 (실패 시)")
|
|
|
|
|
|
class Media(BaseModel):
|
|
"""Instagram 미디어 정보"""
|
|
|
|
id: str
|
|
media_type: Optional[str] = None
|
|
media_url: Optional[str] = None
|
|
thumbnail_url: Optional[str] = None
|
|
caption: Optional[str] = None
|
|
timestamp: Optional[datetime] = None
|
|
permalink: Optional[str] = None
|
|
like_count: int = 0
|
|
comments_count: int = 0
|
|
children: Optional[list["Media"]] = None
|
|
|
|
|
|
class MediaList(BaseModel):
|
|
"""미디어 목록 응답"""
|
|
|
|
data: list[Media] = Field(default_factory=list)
|
|
paging: Optional[dict[str, Any]] = None
|
|
|
|
@property
|
|
def next_cursor(self) -> Optional[str]:
|
|
"""다음 페이지 커서"""
|
|
if self.paging and "cursors" in self.paging:
|
|
return self.paging["cursors"].get("after")
|
|
return None
|
|
|
|
|
|
class MediaContainer(BaseModel):
|
|
"""미디어 컨테이너 상태"""
|
|
|
|
id: str
|
|
status_code: Optional[str] = None
|
|
status: Optional[str] = None
|
|
|
|
@property
|
|
def is_finished(self) -> bool:
|
|
return self.status_code == "FINISHED"
|
|
|
|
@property
|
|
def is_error(self) -> bool:
|
|
return self.status_code == "ERROR"
|
|
|
|
@property
|
|
def is_in_progress(self) -> bool:
|
|
return self.status_code == "IN_PROGRESS"
|
|
|
|
|
|
class APIError(BaseModel):
|
|
"""API 에러 응답"""
|
|
|
|
message: str
|
|
type: Optional[str] = None
|
|
code: Optional[int] = None
|
|
error_subcode: Optional[int] = None
|
|
fbtrace_id: Optional[str] = None
|
|
|
|
|
|
class ErrorResponse(BaseModel):
|
|
"""에러 응답 래퍼"""
|
|
|
|
error: APIError
|