# anime_etl/models.py from __future__ import annotations from enum import Enum from typing import Dict, List, Optional from pydantic import BaseModel class Source(str, Enum): ANILIST = "anilist" JIKAN = "jikan" SHIKIMORI = "shikimori" class Studio(BaseModel): id: Optional[int] = None name: str poster: Optional["Image"] = None description: Optional[str] = None class Image(BaseModel): id: Optional[int] = None storage_type: Optional[str] = None # для БД: storage_type_t image_path: str # для внешнего постера – URL class Tag(BaseModel): # локализованный тег, как в Tag.yaml: { "en": "Shojo", "ru": "Сёдзё", ... } names: Dict[str, str] class SourceTitle(BaseModel): """ Нормализованная инфа из одного источника (AniList/Jikan/...). """ source: Source external_id: str title_names: Dict[str, List[str]] studio: Optional[Studio] = None tags: List[Tag] = [] poster: Optional[Image] = None title_status: Optional[str] = None rating: Optional[float] = None rating_count: Optional[int] = None release_year: Optional[int] = None release_season: Optional[str] = None season: Optional[int] = None episodes_aired: Optional[int] = None episodes_all: Optional[int] = None episodes_len: Optional[Dict[str, float]] = None class CanonicalTitle(BaseModel): """ То, что пойдёт в нашу БД + будет соответствовать Title.yaml. """ id: Optional[int] = None title_names: Dict[str, List[str]] studio: Optional[Studio] = None tags: List[Tag] = [] poster: Optional[Image] = None title_status: Optional[str] = None rating: Optional[float] = None rating_count: Optional[int] = None release_year: Optional[int] = None release_season: Optional[str] = None season: Optional[int] = None episodes_aired: Optional[int] = None episodes_all: Optional[int] = None episodes_len: Optional[Dict[str, float]] = None