# -*- coding: utf-8 -*- """Pydantic 스키마 + 공통 페이지네이션 응답.""" from datetime import datetime from typing import Generic, TypeVar from pydantic import BaseModel T = TypeVar("T") class PaginatedResponse(BaseModel, Generic[T]): items: list[T] total: int page: int page_size: int total_pages: int has_next: bool has_prev: bool @classmethod def create(cls, items: list[T], total: int, page: int, page_size: int) -> "PaginatedResponse[T]": total_pages = (total + page_size - 1) // page_size if page_size else 0 return cls( items=items, total=total, page=page, page_size=page_size, total_pages=total_pages, has_next=page < total_pages, has_prev=page > 1, ) # ---- auth ---- class UserOut(BaseModel): user_uuid: str nickname: str email: str | None = None profile_image_url: str | None = None bio: str | None = None credits: int is_admin: bool = False class ProfileUpdate(BaseModel): nickname: str | None = None profile_image_url: str | None = None # data URL 또는 외부 URL, ""=기본으로 되돌림 bio: str | None = None class TokenResponse(BaseModel): access_token: str refresh_token: str token_type: str = "bearer" # ---- content / feed ---- class FeedItem(BaseModel): id: str sc: str title: str video: str | None views: int likes: int liked: bool = False comments: int = 0 mine: bool = False createdAt: datetime | None = None # ---- create ---- class CreateReq(BaseModel): scenario: str input: str scenes: int = 12 seconds: int = 45 # ---- comment ---- class CommentReq(BaseModel): body: str parent_id: int | None = None nickname: str | None = None class ReplyItem(BaseModel): id: int body: str | None nickname: str is_mine: bool created_at: datetime class CommentItem(BaseModel): id: int body: str | None nickname: str is_mine: bool created_at: datetime replies: list[ReplyItem] = [] # ---- credit ---- class CreditTx(BaseModel): amount: int balance_after: int type: str reason: str | None created_at: datetime class ChargeReq(BaseModel): amount: int message: str | None = None