110 lines
2.3 KiB
Python
110 lines
2.3 KiB
Python
# -*- 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
|