From 1bb4200a799d7905cb0fb384acc43b7f50b24b3d Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Mon, 5 May 2025 01:39:03 +0200 Subject: [PATCH] Type `Video` in the scanner --- api/src/models/video.ts | 10 +++-- scanner/scanner/client.py | 4 +- scanner/scanner/models/extra.py | 11 ++++++ scanner/scanner/models/metadataid.py | 12 ++++-- scanner/scanner/models/videos.py | 58 +++++++++++++++++++++++++++- 5 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 scanner/scanner/models/extra.py diff --git a/api/src/models/video.ts b/api/src/models/video.ts index f9cefaf2..8d14e909 100644 --- a/api/src/models/video.ts +++ b/api/src/models/video.ts @@ -21,11 +21,15 @@ export const Guess = t.Recursive((Self) => t.Object( { title: t.String(), - year: t.Optional(t.Array(t.Integer(), { default: [] })), - season: t.Optional(t.Array(t.Integer(), { default: [] })), - episode: t.Optional(t.Array(t.Integer(), { default: [] })), kind: t.Optional(t.UnionEnum(["episode", "movie", "extra"])), extraKind: t.Optional(ExtraType), + years: t.Optional(t.Array(t.Integer(), { default: [] })), + episodes: t.Optional( + t.Array( + t.Object({ season: t.Nullable(t.Integer()), episode: t.Integer() }), + { default: [] }, + ), + ), externalId: t.Optional(ExternalIds), from: t.String({ diff --git a/scanner/scanner/client.py b/scanner/scanner/client.py index 14aedd87..7c42c1b0 100644 --- a/scanner/scanner/client.py +++ b/scanner/scanner/client.py @@ -6,7 +6,7 @@ from logging import getLogger from typing import Optional from .utils import format_date -from .models.videos import VideoInfo +from .models.videos import VideoInfo, Video logger = getLogger(__name__) @@ -44,7 +44,7 @@ class KyooClient: async def create_videos(self, videos: list[Video]): async with self._client.post( f"{self._url}/videos", - json=[x.model_dump() for x in videos] + json=[x.model_dump_json() for x in videos], ) as r: r.raise_for_status() diff --git a/scanner/scanner/models/extra.py b/scanner/scanner/models/extra.py new file mode 100644 index 00000000..627241dc --- /dev/null +++ b/scanner/scanner/models/extra.py @@ -0,0 +1,11 @@ +from typing import Literal + +type ExtraKind = ( + Literal["other"] | + Literal["trailer"] | + Literal["interview"] | + Literal["behind-the-scene"] | + Literal["deleted-scene"] | + Literal["blooper"] +) + diff --git a/scanner/scanner/models/metadataid.py b/scanner/scanner/models/metadataid.py index 87bfc915..c9bc1b17 100644 --- a/scanner/scanner/models/metadataid.py +++ b/scanner/scanner/models/metadataid.py @@ -1,8 +1,14 @@ -from dataclasses import dataclass from typing import Optional +from ..utils import Model -@dataclass -class MetadataID: +class MetadataId(Model): data_id: str link: Optional[str] + + +class EpisodeId(Model): + serie_id: str + season: Optional[int] + episode: int + link: Optional[str] diff --git a/scanner/scanner/models/videos.py b/scanner/scanner/models/videos.py index 3b803fbc..628bf5d8 100644 --- a/scanner/scanner/models/videos.py +++ b/scanner/scanner/models/videos.py @@ -1,7 +1,9 @@ from __future__ import annotations from ..utils import Model -from typing import Optional +from .extra import ExtraKind +from .metadataid import MetadataId, EpisodeId +from typing import Optional, Literal class Resource(Model): @@ -13,3 +15,57 @@ class VideoInfo(Model): paths: set[str] unmatched: set[str] guesses: dict[str, dict[str, Resource]] + + +class Guess(Model): + title: str + kind: Literal["episode"] | Literal["movie"] | Literal["extra"] + extraKind: Optional[ExtraKind] + years: list[int] + episodes: list[Guess.Episode] + external_id: dict[str, MetadataId | EpisodeId] + + from_: str + history: list[Guess] + + class Episode(Model): + season: Optional[int] + episode: int + + +Guess.model_rebuild() + + +class For(Model): + class Slug(Model): + slug: str + + class ExternalId(Model): + external_id: dict[str, MetadataId | EpisodeId] + + class Movie(Model): + movie: str + + class Episode(Model): + serie: str + season: int + episode: int + + class Order(Model): + serie: str + order: float + + class Special(Model): + serie: int + special: int + + +class Video(Model): + path: str + rendering: str + part: Optional[int] + version: int = 1 + guess: Guess + for_: Optional[ + For.Slug | For.ExternalId | For.Movie | For.Episode | For.Order | For.Special + ]