257 lines
8.6 KiB
Python
257 lines
8.6 KiB
Python
"""
|
|
Social Media Models
|
|
|
|
소셜 미디어 업로드 관련 SQLAlchemy 모델을 정의합니다.
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from typing import TYPE_CHECKING, Optional
|
|
|
|
from sqlalchemy import BigInteger, DateTime, ForeignKey, Index, Integer, String, Text, func
|
|
from sqlalchemy.dialects.mysql import JSON
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.database.session import Base
|
|
|
|
if TYPE_CHECKING:
|
|
from app.user.models import SocialAccount
|
|
from app.video.models import Video
|
|
|
|
|
|
class SocialUpload(Base):
|
|
"""
|
|
소셜 미디어 업로드 기록 테이블
|
|
|
|
영상의 소셜 미디어 플랫폼별 업로드 상태를 추적합니다.
|
|
|
|
Attributes:
|
|
id: 고유 식별자 (자동 증가)
|
|
user_uuid: 사용자 UUID (User.user_uuid 참조)
|
|
video_id: Video 외래키
|
|
social_account_id: SocialAccount 외래키
|
|
upload_seq: 업로드 순번 (동일 영상+채널 조합 내 순번, 관리자 추적용)
|
|
platform: 플랫폼 구분 (youtube, instagram, facebook, tiktok)
|
|
status: 업로드 상태 (pending, uploading, processing, completed, failed)
|
|
upload_progress: 업로드 진행률 (0-100)
|
|
platform_video_id: 플랫폼에서 부여한 영상 ID
|
|
platform_url: 플랫폼에서의 영상 URL
|
|
title: 영상 제목
|
|
description: 영상 설명
|
|
tags: 태그 목록 (JSON)
|
|
privacy_status: 공개 상태 (public, unlisted, private)
|
|
platform_options: 플랫폼별 추가 옵션 (JSON)
|
|
error_message: 에러 메시지 (실패 시)
|
|
retry_count: 재시도 횟수
|
|
uploaded_at: 업로드 완료 시간
|
|
created_at: 생성 일시
|
|
updated_at: 수정 일시
|
|
|
|
Relationships:
|
|
video: 연결된 Video
|
|
social_account: 연결된 SocialAccount
|
|
"""
|
|
|
|
__tablename__ = "social_upload"
|
|
__table_args__ = (
|
|
Index("idx_social_upload_user_uuid", "user_uuid"),
|
|
Index("idx_social_upload_video_id", "video_id"),
|
|
Index("idx_social_upload_social_account_id", "social_account_id"),
|
|
Index("idx_social_upload_platform", "platform"),
|
|
Index("idx_social_upload_status", "status"),
|
|
Index("idx_social_upload_created_at", "created_at"),
|
|
# 동일 영상+채널 조합 조회용 인덱스 (유니크 아님 - 여러 번 업로드 가능)
|
|
Index("idx_social_upload_video_account", "video_id", "social_account_id"),
|
|
# 순번 조회용 인덱스
|
|
Index("idx_social_upload_seq", "video_id", "social_account_id", "upload_seq"),
|
|
{
|
|
"mysql_engine": "InnoDB",
|
|
"mysql_charset": "utf8mb4",
|
|
"mysql_collate": "utf8mb4_unicode_ci",
|
|
},
|
|
)
|
|
|
|
# ==========================================================================
|
|
# 기본 식별자
|
|
# ==========================================================================
|
|
id: Mapped[int] = mapped_column(
|
|
BigInteger,
|
|
primary_key=True,
|
|
nullable=False,
|
|
autoincrement=True,
|
|
comment="고유 식별자",
|
|
)
|
|
|
|
# ==========================================================================
|
|
# 관계 필드
|
|
# ==========================================================================
|
|
user_uuid: Mapped[str] = mapped_column(
|
|
String(36),
|
|
ForeignKey("user.user_uuid", ondelete="CASCADE"),
|
|
nullable=False,
|
|
comment="사용자 UUID (User.user_uuid 참조)",
|
|
)
|
|
|
|
video_id: Mapped[int] = mapped_column(
|
|
Integer,
|
|
ForeignKey("video.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
comment="Video 외래키",
|
|
)
|
|
|
|
social_account_id: Mapped[int] = mapped_column(
|
|
Integer,
|
|
ForeignKey("social_account.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
comment="SocialAccount 외래키",
|
|
)
|
|
|
|
# ==========================================================================
|
|
# 업로드 순번 (관리자 추적용)
|
|
# ==========================================================================
|
|
upload_seq: Mapped[int] = mapped_column(
|
|
Integer,
|
|
nullable=False,
|
|
default=1,
|
|
comment="업로드 순번 (동일 영상+채널 조합 내 순번, 1부터 시작)",
|
|
)
|
|
|
|
# ==========================================================================
|
|
# 플랫폼 정보
|
|
# ==========================================================================
|
|
platform: Mapped[str] = mapped_column(
|
|
String(20),
|
|
nullable=False,
|
|
comment="플랫폼 구분 (youtube, instagram, facebook, tiktok)",
|
|
)
|
|
|
|
# ==========================================================================
|
|
# 업로드 상태
|
|
# ==========================================================================
|
|
status: Mapped[str] = mapped_column(
|
|
String(20),
|
|
nullable=False,
|
|
default="pending",
|
|
comment="업로드 상태 (pending, uploading, processing, completed, failed)",
|
|
)
|
|
|
|
upload_progress: Mapped[int] = mapped_column(
|
|
Integer,
|
|
nullable=False,
|
|
default=0,
|
|
comment="업로드 진행률 (0-100)",
|
|
)
|
|
|
|
# ==========================================================================
|
|
# 플랫폼 결과
|
|
# ==========================================================================
|
|
platform_video_id: Mapped[Optional[str]] = mapped_column(
|
|
String(100),
|
|
nullable=True,
|
|
comment="플랫폼에서 부여한 영상 ID",
|
|
)
|
|
|
|
platform_url: Mapped[Optional[str]] = mapped_column(
|
|
String(500),
|
|
nullable=True,
|
|
comment="플랫폼에서의 영상 URL",
|
|
)
|
|
|
|
# ==========================================================================
|
|
# 메타데이터
|
|
# ==========================================================================
|
|
title: Mapped[str] = mapped_column(
|
|
String(200),
|
|
nullable=False,
|
|
comment="영상 제목",
|
|
)
|
|
|
|
description: Mapped[Optional[str]] = mapped_column(
|
|
Text,
|
|
nullable=True,
|
|
comment="영상 설명",
|
|
)
|
|
|
|
tags: Mapped[Optional[dict]] = mapped_column(
|
|
JSON,
|
|
nullable=True,
|
|
comment="태그 목록 (JSON 배열)",
|
|
)
|
|
|
|
privacy_status: Mapped[str] = mapped_column(
|
|
String(20),
|
|
nullable=False,
|
|
default="private",
|
|
comment="공개 상태 (public, unlisted, private)",
|
|
)
|
|
|
|
platform_options: Mapped[Optional[dict]] = mapped_column(
|
|
JSON,
|
|
nullable=True,
|
|
comment="플랫폼별 추가 옵션 (JSON)",
|
|
)
|
|
|
|
# ==========================================================================
|
|
# 에러 정보
|
|
# ==========================================================================
|
|
error_message: Mapped[Optional[str]] = mapped_column(
|
|
Text,
|
|
nullable=True,
|
|
comment="에러 메시지 (실패 시)",
|
|
)
|
|
|
|
retry_count: Mapped[int] = mapped_column(
|
|
Integer,
|
|
nullable=False,
|
|
default=0,
|
|
comment="재시도 횟수",
|
|
)
|
|
|
|
# ==========================================================================
|
|
# 시간 정보
|
|
# ==========================================================================
|
|
uploaded_at: Mapped[Optional[datetime]] = mapped_column(
|
|
DateTime,
|
|
nullable=True,
|
|
comment="업로드 완료 시간",
|
|
)
|
|
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime,
|
|
nullable=False,
|
|
server_default=func.now(),
|
|
comment="생성 일시",
|
|
)
|
|
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime,
|
|
nullable=False,
|
|
server_default=func.now(),
|
|
onupdate=func.now(),
|
|
comment="수정 일시",
|
|
)
|
|
|
|
# ==========================================================================
|
|
# Relationships
|
|
# ==========================================================================
|
|
video: Mapped["Video"] = relationship(
|
|
"Video",
|
|
lazy="selectin",
|
|
)
|
|
|
|
social_account: Mapped["SocialAccount"] = relationship(
|
|
"SocialAccount",
|
|
lazy="selectin",
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
return (
|
|
f"<SocialUpload("
|
|
f"id={self.id}, "
|
|
f"video_id={self.video_id}, "
|
|
f"account_id={self.social_account_id}, "
|
|
f"seq={self.upload_seq}, "
|
|
f"platform='{self.platform}', "
|
|
f"status='{self.status}'"
|
|
f")>"
|
|
)
|