"""Pydantic-схемы для API-запросов и ответов.""" from __future__ import annotations from datetime import datetime from typing import Optional from pydantic import BaseModel, Field # ─── Аутентификация ──────────────────────────────────────────────────────── class ApiKeyRequest(BaseModel): api_key: str = Field(..., description="API-ключ пользователя") # ─── Аккаунты ────────────────────────────────────────────────────────────── class AccountCreateRequest(BaseModel): api_key: str vk_user_id: int = Field(..., description="VK owner_id (положительный — пользователь, отрицательный — сообщество)") display_name: str = Field(..., max_length=255, description="Отображаемое имя аккаунта") access_token: str = Field(..., description="VK OAuth-токен с правами wall") token_type: str = Field(default="user", pattern="^(user|group)$", description="user | group") class AccountResponse(BaseModel): id: int vk_user_id: int display_name: str token_type: str is_active: bool created_at: datetime class AccountListResponse(BaseModel): accounts: list[AccountResponse] # ─── Публикация ──────────────────────────────────────────────────────────── class PublishRequest(BaseModel): api_key: str vk_account_id: int = Field(..., description="ID VK-аккаунта из /api/v1/accounts") message_md: str = Field(..., min_length=1, description="Текст поста в Markdown") publish_date: Optional[datetime] = Field(None, description="ISO datetime для отложенной публикации") friends_only: bool = False attachments: Optional[str] = Field(None, description="VK-вложения через запятую (photo123_456, ...)") signed: Optional[bool] = Field(None, description="Подпись автора (для групп)") class PublishResponse(BaseModel): success: bool publication_id: int vk_post_id: Optional[int] = None vk_owner_id: Optional[int] = None url: Optional[str] = None error: Optional[str] = None # ─── Конвертация ─────────────────────────────────────────────────────────── class ConvertRequest(BaseModel): message_md: str = Field(..., min_length=1, description="Markdown-текст для конвертации") class FormatItemResponse(BaseModel): type: str offset: int length: int url: Optional[str] = None class ConvertResponse(BaseModel): text: str format_data: Optional[dict] = None # ─── Публикации (архив) ──────────────────────────────────────────────────── class PublicationFilterRequest(BaseModel): api_key: str vk_account_id: Optional[int] = None status: Optional[str] = Field(None, pattern="^(draft|scheduled|published|error)$") limit: int = Field(default=20, ge=1, le=100) offset: int = Field(default=0, ge=0) class PublicationItem(BaseModel): id: int vk_account_id: int status: str markdown_original: str vk_post_id: Optional[int] = None vk_owner_id: Optional[int] = None scheduled_at: Optional[datetime] = None published_at: Optional[datetime] = None error_message: Optional[str] = None created_at: datetime class PublicationListResponse(BaseModel): publications: list[PublicationItem] total: int # ─── Ошибки ──────────────────────────────────────────────────────────────── class ErrorResponse(BaseModel): detail: str