Handle missing translations in scanner (#493)

This commit is contained in:
Zoe Roux 2024-05-15 00:10:10 +02:00 committed by GitHub
commit 465562b563
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 96 additions and 61 deletions

View File

@ -87,6 +87,7 @@ class Matcher:
async def search_movie(self, title: str, year: Optional[int], path: str):
movie = await self._provider.search_movie(title, year)
movie.file_title = title
movie.path = path
logger.debug("Got movie: %s", movie)
movie_id = await self._client.post("movies", data=movie.to_kyoo())
@ -116,7 +117,7 @@ class Matcher:
)
episode.path = path
logger.debug("Got episode: %s", episode)
episode.show_id = await self.create_or_get_show(episode)
episode.show_id = await self.create_or_get_show(episode, title)
if episode.season_number is not None:
episode.season_id = await self.register_seasons(
@ -140,7 +141,7 @@ class Matcher:
provider_id = collection.external_id[self._provider.name].data_id
return await create_collection(provider_id)
async def create_or_get_show(self, episode: Episode) -> str:
async def create_or_get_show(self, episode: Episode, fallback_name: str) -> str:
@cache(ttl=timedelta(days=1), cache=self._show_cache)
async def create_show(_: str):
# TODO: Check if a show with the same metadata id exists already on kyoo.
@ -151,6 +152,7 @@ class Matcher:
if isinstance(episode.show, PartialShow)
else episode.show
)
show.file_title = fallback_name
# TODO: collections
logger.debug("Got show: %s", episode)
ret = await self._client.post("show", data=show.to_kyoo())

View File

@ -1,7 +1,8 @@
import os
from dataclasses import asdict, dataclass, field
from typing import Optional
from providers.utils import ProviderError, select_translation, select_image
from .metadataid import MetadataID
@ -20,14 +21,15 @@ class Collection:
translations: dict[str, CollectionTranslation] = field(default_factory=dict)
def to_kyoo(self):
# For now, the API of kyoo only support one language so we remove the others.
default_language = os.environ["LIBRARY_LANGUAGES"].split(",")[0]
trans = select_translation(self)
if trans is None:
raise ProviderError(
"Could not find translations for the collection. Aborting"
)
return {
**asdict(self),
**asdict(self.translations[default_language]),
"poster": next(iter(self.translations[default_language].posters), None),
"thumbnail": next(
iter(self.translations[default_language].thumbnails), None
),
"logo": next(iter(self.translations[default_language].logos), None),
**asdict(trans),
"poster": select_image(self, "posters"),
"thumbnail": select_image(self, "thumbnails"),
"logo": select_image(self, "logos"),
}

View File

@ -1,8 +1,9 @@
import os
from datetime import date
from dataclasses import dataclass, field, asdict
from typing import Optional
from providers.utils import select_translation
from .show import Show
from .metadataid import MetadataID
@ -24,8 +25,8 @@ class EpisodeID:
@dataclass
class EpisodeTranslation:
name: str
overview: Optional[str]
name: Optional[str]
overview: Optional[str] = None
@dataclass
@ -45,10 +46,9 @@ class Episode:
translations: dict[str, EpisodeTranslation] = field(default_factory=dict)
def to_kyoo(self):
# For now, the API of kyoo only support one language so we remove the others.
default_language = os.environ["LIBRARY_LANGUAGES"].split(",")[0]
trans = select_translation(self) or EpisodeTranslation("")
return {
**asdict(self),
**asdict(self.translations[default_language]),
**asdict(trans),
"show": None,
}

View File

@ -1,9 +1,10 @@
import os
from dataclasses import asdict, dataclass, field
from datetime import date
from typing import Optional
from enum import Enum
from providers.utils import select_translation, select_image
from .collection import Collection
from .genre import Genre
from .studio import Studio
@ -44,22 +45,22 @@ class Movie:
external_id: dict[str, MetadataID]
path: Optional[str] = None
# The title of this show according to it's filename (None only for ease of use in providers)
file_title: Optional[str] = None
collections: list[Collection] = field(default_factory=list)
translations: dict[str, MovieTranslation] = field(default_factory=dict)
def to_kyoo(self):
from ..utils import select_image
# For now, the API of kyoo only support one language so we remove the others.
default_language = os.environ["LIBRARY_LANGUAGES"].split(",")[0]
trans = select_translation(self) or MovieTranslation(name=self.file_title or "")
return {
**asdict(self),
**asdict(self.translations[default_language]),
**asdict(trans),
"poster": select_image(self, "posters"),
"thumbnail": select_image(self, "thumbnails"),
"logo": select_image(self, "logos"),
"trailer": next(iter(self.translations[default_language].trailers), None),
"trailer": next(iter(trans.trailers), None),
"studio": next((x.to_kyoo() for x in self.studios), None),
"genres": [x.to_kyoo() for x in self.genres],
"collections": None,
"file_title": None,
}

View File

@ -1,8 +1,9 @@
import os
from datetime import date
from dataclasses import dataclass, field, asdict
from typing import Optional
from providers.utils import select_translation, select_image
from .metadataid import MetadataID
@ -28,13 +29,10 @@ class Season:
translations: dict[str, SeasonTranslation] = field(default_factory=dict)
def to_kyoo(self):
# For now, the API of kyoo only support one language so we remove the others.
default_language = os.environ["LIBRARY_LANGUAGES"].split(",")[0]
trans = select_translation(self) or SeasonTranslation()
return {
**asdict(self),
**asdict(self.translations[default_language]),
"poster": next(iter(self.translations[default_language].posters), None),
"thumbnail": next(
iter(self.translations[default_language].thumbnails), None
),
**asdict(trans),
"poster": select_image(self, "posters"),
"thumbnail": select_image(self, "thumbnails"),
}

View File

@ -1,9 +1,10 @@
import os
from dataclasses import asdict, dataclass, field
from datetime import date
from typing import Optional
from enum import Enum
from providers.utils import select_translation, select_image
from .genre import Genre
from .studio import Studio
from .season import Season
@ -20,14 +21,14 @@ class Status(str, Enum):
@dataclass
class ShowTranslation:
name: str
tagline: Optional[str]
tags: list[str]
overview: Optional[str]
tagline: Optional[str] = None
tags: list[str] = field(default_factory=list)
overview: Optional[str] = None
posters: list[str]
logos: list[str]
trailers: list[str]
thumbnails: list[str]
posters: list[str] = field(default_factory=list)
logos: list[str] = field(default_factory=list)
trailers: list[str] = field(default_factory=list)
thumbnails: list[str] = field(default_factory=list)
@dataclass
@ -46,20 +47,21 @@ class Show:
external_id: dict[str, MetadataID]
translations: dict[str, ShowTranslation] = field(default_factory=dict)
# The title of this show according to it's filename (None only for ease of use in providers)
file_title: Optional[str] = None
def to_kyoo(self):
from providers.utils import select_image
# For now, the API of kyoo only support one language so we remove the others.
default_language = os.environ["LIBRARY_LANGUAGES"].split(",")[0]
trans = select_translation(self) or ShowTranslation(name=self.file_title or "")
return {
**asdict(self),
**asdict(self.translations[default_language]),
**asdict(trans),
"rating": self.rating or 0,
"studio": next((x.to_kyoo() for x in self.studios), None),
"seasons": None,
"poster": select_image(self, "posters"),
"thumbnail": select_image(self, "thumbnails"),
"logo": select_image(self, "logos"),
"trailer": next(iter(self.translations[default_language].trailers), None),
"trailer": next(iter(trans.trailers), None),
"genres": [x.to_kyoo() for x in self.genres],
"file_title": None,
}

View File

@ -1,11 +1,16 @@
from __future__ import annotations
import os
from datetime import date
from itertools import chain
from typing import TYPE_CHECKING, Literal, Any, Optional
from typing import Literal
from providers.types.movie import Movie
from providers.types.show import Show
if TYPE_CHECKING:
from providers.types.movie import Movie
from providers.types.show import Show
from providers.types.season import Season
from providers.types.episode import Episode
from providers.types.collection import Collection
def format_date(date: date | int | None) -> str | None:
@ -16,21 +21,46 @@ def format_date(date: date | int | None) -> str | None:
return date.isoformat()
# For now, the API of kyoo only support one language so we remove the others.
default_languages = os.environ["LIBRARY_LANGUAGES"].split(",")
def sort_translations(
value: Movie | Show | Season | Episode | Collection,
*,
prefer_orginal=False,
):
from providers.types.movie import Movie
from providers.types.show import Show
if (
prefer_orginal
and (isinstance(value, Movie) or isinstance(value, Show))
and value.original_language
and value.original_language in value.translations
):
yield value.translations[value.original_language]
for lang in default_languages:
if lang in value.translations:
yield value.translations[lang]
def select_translation(
value: Movie | Show | Season | Episode | Collection, *, prefer_orginal=False
) -> Optional[Any]:
return next(sort_translations(value, prefer_orginal=prefer_orginal), None)
def select_image(
self: Movie | Show,
type: Literal["posters"] | Literal["thumbnails"] | Literal["logos"],
value: Movie | Show | Season | Collection,
kind: Literal["posters"] | Literal["thumbnails"] | Literal["logos"],
) -> str | None:
# For now, the API of kyoo only support one language so we remove the others.
default_language = os.environ["LIBRARY_LANGUAGES"].split(",")[0]
return next(
chain(
(
getattr(self.translations[self.original_language], type)
if self.original_language
else []
),
getattr(self.translations[default_language], type),
*(getattr(x, type) for x in self.translations.values()),
*(
getattr(trans, kind)
for trans in sort_translations(value, prefer_orginal=True)
)
),
None,
)