""" Pydantic модели для ответов Kwork API. Все модели соответствуют структуре, найденной при анализе HAR дампа. Используются для валидации и типизации ответов API. """ from datetime import datetime from typing import Any, Optional from pydantic import BaseModel, Field class KworkUser(BaseModel): """ Информация о пользователе Kwork. Attributes: id: Уникальный ID пользователя. username: Имя пользователя (логин). avatar_url: URL аватара или None. is_online: Статус онлайн. rating: Рейтинг пользователя (0-5). Example: user = KworkUser(id=123, username="seller", rating=4.9) print(f"{user.username}: {user.rating} ★") """ id: int username: str avatar_url: Optional[str] = None is_online: bool = False rating: Optional[float] = None class KworkCategory(BaseModel): """ Категория кворков. Attributes: id: Уникальный ID категории. name: Название категории. slug: URL-safe идентификатор. parent_id: ID родительской категории для вложенности. """ id: int name: str slug: str parent_id: Optional[int] = None class Kwork(BaseModel): """ Кворк — услуга на Kwork. Базовая модель кворка с основной информацией. Attributes: id: Уникальный ID кворка. title: Заголовок кворка. description: Краткое описание. price: Цена в рублях. currency: Валюта (по умолчанию RUB). category_id: ID категории. seller: Информация о продавце. images: Список URL изображений. rating: Рейтинг кворка (0-5). reviews_count: Количество отзывов. created_at: Дата создания. updated_at: Дата последнего обновления. """ id: int title: str description: Optional[str] = None price: float currency: str = "RUB" category_id: Optional[int] = None seller: Optional[KworkUser] = None images: list[str] = Field(default_factory=list) rating: Optional[float] = None reviews_count: int = 0 created_at: Optional[datetime] = None updated_at: Optional[datetime] = None class KworkDetails(Kwork): """ Расширенная информация о кворке. Наследует все поля Kwork плюс дополнительные детали. Attributes: full_description: Полное описание услуги. requirements: Требования к заказчику. delivery_time: Срок выполнения в днях. revisions: Количество бесплатных правок. features: Список дополнительных опций. faq: Список вопросов и ответов. """ full_description: Optional[str] = None requirements: Optional[str] = None delivery_time: Optional[int] = None revisions: Optional[int] = None features: list[str] = Field(default_factory=list) faq: list[dict[str, str]] = Field(default_factory=list) class PaginationInfo(BaseModel): """ Информация о пагинации. Attributes: current_page: Текущая страница (начиная с 1). total_pages: Общее количество страниц. total_items: Общее количество элементов. items_per_page: Элементов на странице. has_next: Есть ли следующая страница. has_prev: Есть ли предыдущая страница. """ current_page: int = 1 total_pages: int = 1 total_items: int = 0 items_per_page: int = 20 has_next: bool = False has_prev: bool = False class CatalogResponse(BaseModel): """ Ответ API каталога кворков. Attributes: kworks: Список кворков на странице. pagination: Информация о пагинации. filters: Доступные фильтры. sort_options: Доступные опции сортировки. """ kworks: list[Kwork] = Field(default_factory=list) pagination: Optional[PaginationInfo] = None filters: Optional[dict[str, Any]] = None sort_options: list[str] = Field(default_factory=list) class Project(BaseModel): """ Проект (заказ на бирже фриланса). Attributes: id: Уникальный ID проекта. title: Заголовок проекта. description: Описание задачи. budget: Бюджет проекта. budget_type: Тип бюджета: "fixed" (фиксированный) или "hourly" (почасовой). category_id: ID категории. customer: Информация о заказчике. status: Статус проекта: "open", "in_progress", "completed", "cancelled". created_at: Дата создания. updated_at: Дата обновления. bids_count: Количество откликов. skills: Требуемые навыки. """ id: int title: str description: Optional[str] = None budget: Optional[float] = None budget_type: str = "fixed" category_id: Optional[int] = None customer: Optional[KworkUser] = None status: str = "open" created_at: Optional[datetime] = None updated_at: Optional[datetime] = None bids_count: int = 0 skills: list[str] = Field(default_factory=list) class ProjectsResponse(BaseModel): """ Ответ API списка проектов. Attributes: projects: Список проектов. pagination: Информация о пагинации. """ projects: list[Project] = Field(default_factory=list) pagination: Optional[PaginationInfo] = None class Review(BaseModel): """ Отзыв о кворке или проекте. Attributes: id: Уникальный ID отзыва. rating: Оценка от 1 до 5. comment: Текст отзыва. author: Автор отзыва. kwork_id: ID кворка (если отзыв о кворке). created_at: Дата создания. """ id: int rating: int = Field(ge=1, le=5) comment: Optional[str] = None author: Optional[KworkUser] = None kwork_id: Optional[int] = None created_at: Optional[datetime] = None class ReviewsResponse(BaseModel): """ Ответ API списка отзывов. Attributes: reviews: Список отзывов. pagination: Информация о пагинации. average_rating: Средний рейтинг. """ reviews: list[Review] = Field(default_factory=list) pagination: Optional[PaginationInfo] = None average_rating: Optional[float] = None class Notification(BaseModel): """ Уведомление пользователя. Attributes: id: Уникальный ID уведомления. type: Тип уведомления: "message", "order", "system", etc. title: Заголовок уведомления. message: Текст уведомления. is_read: Прочитано ли уведомление. created_at: Дата создания. link: Ссылка для перехода (если есть). """ id: int type: str title: str message: str is_read: bool = False created_at: Optional[datetime] = None link: Optional[str] = None class NotificationsResponse(BaseModel): """ Ответ API списка уведомлений. Attributes: notifications: Список уведомлений. unread_count: Количество непрочитанных уведомлений. """ notifications: list[Notification] = Field(default_factory=list) unread_count: int = 0 class Dialog(BaseModel): """ Диалог (чат) с пользователем. Attributes: id: Уникальный ID диалога. participant: Собеседник. last_message: Текст последнего сообщения. unread_count: Количество непрочитанных сообщений. updated_at: Время последнего сообщения. """ id: int participant: Optional[KworkUser] = None last_message: Optional[str] = None unread_count: int = 0 updated_at: Optional[datetime] = None class AuthResponse(BaseModel): """ Ответ API аутентификации. Attributes: success: Успешность аутентификации. user_id: ID пользователя. username: Имя пользователя. web_auth_token: Токен для последующих запросов. message: Сообщение (например, об ошибке). """ success: bool user_id: Optional[int] = None username: Optional[str] = None web_auth_token: Optional[str] = None message: Optional[str] = None class ErrorDetail(BaseModel): """ Детали ошибки API. Attributes: code: Код ошибки. message: Сообщение об ошибке. field: Поле, вызвавшее ошибку (если применимо). """ code: str message: str field: Optional[str] = None class APIErrorResponse(BaseModel): """ Стандартный ответ API об ошибке. Attributes: success: Всегда False для ошибок. errors: Список деталей ошибок. message: Общее сообщение об ошибке. """ success: bool = False errors: list[ErrorDetail] = Field(default_factory=list) message: Optional[str] = None class City(BaseModel): """ Город из справочника. Attributes: id: Уникальный ID города. name: Название города. country_id: ID страны. """ id: int name: str country_id: Optional[int] = None class Country(BaseModel): """ Страна из справочника. Attributes: id: Уникальный ID страны. name: Название страны. code: Код страны (ISO). cities: Список городов в стране. """ id: int name: str code: Optional[str] = None cities: list[City] = Field(default_factory=list) class TimeZone(BaseModel): """ Часовой пояс. Attributes: id: Уникальный ID. name: Название пояса. offset: Смещение от UTC (например, "+03:00"). """ id: int name: str offset: str class Feature(BaseModel): """ Дополнительная функция (feature) для кворка. Attributes: id: Уникальный ID функции. name: Название. description: Описание. price: Стоимость в рублях. type: Тип: "extra", "premium", etc. """ id: int name: str description: Optional[str] = None price: float type: str class Badge(BaseModel): """ Значок (достижение) пользователя. Attributes: id: Уникальный ID значка. name: Название значка. description: Описание достижения. icon_url: URL иконки значка. """ id: int name: str description: Optional[str] = None icon_url: Optional[str] = None # Generic response wrapper class DataResponse(BaseModel): """ Универсальный ответ API с данными. Используется как обёртка для различных ответов API. Attributes: success: Успешность запроса. data: Полезные данные (словарь). message: Дополнительное сообщение. """ success: bool = True data: Optional[dict[str, Any]] = None message: Optional[str] = None class ValidationIssue(BaseModel): """ Проблема, найденная при валидации текста. Attributes: type: Тип проблемы: "error", "warning", "suggestion". code: Код ошибки (например, "SPELLING", "GRAMMAR", "LENGTH"). message: Описание проблемы. position: Позиция в тексте (если применимо). suggestion: Предлагаемое исправление (если есть). """ type: str = "error" code: str message: str position: Optional[int] = None suggestion: Optional[str] = None class ValidationResponse(BaseModel): """ Ответ API валидации текста. Используется для эндпоинта /api/validation/checktext. Attributes: success: Успешность валидации. is_valid: Текст проходит валидацию (нет критических ошибок). issues: Список найденных проблем. score: Оценка качества текста (0-100, если доступна). message: Дополнительное сообщение. """ success: bool = True is_valid: bool = True issues: list[ValidationIssue] = Field(default_factory=list) score: Optional[int] = None message: Optional[str] = None