""" Pydantic schemas for request/response validation. Provides typed data structures for API endpoints. """ from pydantic import BaseModel, EmailStr, Field from typing import Optional, List from datetime import datetime # ===== Authentication Schemas ===== class LoginRequest(BaseModel): """Login request payload.""" username: str = Field(..., min_length=3, max_length=64) password: str = Field(..., min_length=6, max_length=128) class LoginResponse(BaseModel): """Login response payload.""" access_token: str refresh_token: str token_type: str = "bearer" user: dict class RefreshTokenRequest(BaseModel): """Refresh token request.""" refresh_token: str class TokenResponse(BaseModel): """Token response.""" access_token: str token_type: str = "bearer" # ===== User Schemas ===== class UserBase(BaseModel): """User base fields.""" username: str email: Optional[str] = None country: Optional[str] = Field(None, max_length=2) real_name: Optional[str] = None class UserCreate(UserBase): """User registration fields.""" password: str = Field(..., min_length=8) class Config: json_schema_extra = { "example": { "username": "player123", "password": "securepassword123", "email": "player@example.com", "country": "US" } } class UserUpdate(BaseModel): """User update fields.""" email: Optional[str] = None country: Optional[str] = None real_name: Optional[str] = None new_password: Optional[str] = Field(None, min_length=8, max_length=128) class UserResponse(BaseModel): """User response payload.""" id: int username: str email: Optional[str] country: Optional[str] real_name: Optional[str] privlevel: str vip_status: int is_active: bool is_banned: bool ban_reason: Optional[str] creation_date: datetime last_login: Optional[datetime] class Config: from_attributes = True # ===== Deck Schemas ===== class DeckCreate(BaseModel): """Deck creation request.""" name: str = Field(..., min_length=1, max_length=255) content: str = Field(..., min_length=1) folder_id: Optional[int] = None format: str = Field("native", pattern="^(native|plain)$") class DeckUpdate(BaseModel): """Deck update request.""" name: Optional[str] = None content: Optional[str] = None folder_id: Optional[int] = None class DeckResponse(BaseModel): """Deck response payload.""" id: int name: str content: str format: str folder_id: Optional[int] owner_id: int creation_date: datetime class Config: from_attributes = True class FolderCreate(BaseModel): """Folder creation request.""" name: str = Field(..., min_length=1, max_length=255) parent_id: Optional[int] = None class FolderResponse(BaseModel): """Folder response payload.""" id: int name: str parent_id: Optional[int] owner_id: int creation_date: datetime class Config: from_attributes = True # ===== Game Schemas ===== class GameCreate(BaseModel): """Game creation request.""" room_id: int game_type: Optional[str] = None description: Optional[str] = None password: Optional[str] = None class GameResponse(BaseModel): """Game response payload.""" id: int room_id: int game_type: Optional[str] description: Optional[str] with_password: bool max_players: int player_count: int started: bool creation_date: datetime class Config: from_attributes = True # ===== Room Schemas ===== class RoomResponse(BaseModel): """Room response payload.""" id: int name: str description: Optional[str] is_password_protected: bool game_types: List[str] = [] player_count: int = 0 creation_date: datetime class Config: from_attributes = True # ===== Ban Schemas ===== class BanCreate(BaseModel): """Ban creation request.""" user_id: int reason: str = Field(..., min_length=1, max_length=1000) expiration_time: Optional[datetime] = None class BanResponse(BaseModel): """Ban response payload.""" id: int user_id: int reason: str moderators: Optional[str] expiration_time: Optional[datetime] active: bool creation_date: datetime class Config: from_attributes = True # ===== Auth Error Responses ===== class ErrorResponse(BaseModel): """Standard error response.""" detail: str class ValidationErrorResponse(BaseModel): """Validation error response.""" detail: List[dict] # Pydantic validation errors # ===== Pagination Schemas ===== class PaginationParams(BaseModel): """Common pagination parameters.""" page: int = Field(1, ge=1) page_size: int = Field(50, ge=1, le=100) class PaginatedResponse(BaseModel): """Generic paginated response.""" items: List[dict] total: int page: int page_size: int total_pages: int