mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Use jsons for serialization
This commit is contained in:
parent
c3b8595cd7
commit
31a349704b
@ -1,7 +1,7 @@
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
import logging
|
||||
from aiohttp import ClientSession
|
||||
from datetime import datetime
|
||||
from typing import Awaitable, Callable, Dict, Optional, Any, TypeVar
|
||||
|
||||
from ..provider import Provider
|
||||
@ -175,7 +175,7 @@ class TheMovieDatabase(Provider):
|
||||
f"/tv/{show_id}",
|
||||
params={
|
||||
"language": lng,
|
||||
"append_to_response": "alternative_titles,videos,credits,keywords,images",
|
||||
"append_to_response": "alternative_titles,videos,credits,keywords,images,external_ids",
|
||||
},
|
||||
)
|
||||
logging.debug("TMDb responded: %s", show)
|
||||
@ -183,7 +183,7 @@ class TheMovieDatabase(Provider):
|
||||
|
||||
ret = Show(
|
||||
original_language=show["original_language"],
|
||||
aliases=[x["title"] for x in show["alternative_titles"]["titles"]],
|
||||
aliases=[x["title"] for x in show["alternative_titles"]["results"]],
|
||||
start_air=datetime.strptime(show["first_air_date"], "%Y-%m-%d").date(),
|
||||
end_air=datetime.strptime(show["last_air_date"], "%Y-%m-%d").date(),
|
||||
status=ShowStatus.FINISHED
|
||||
@ -202,9 +202,10 @@ class TheMovieDatabase(Provider):
|
||||
show["id"], f"https://www.themoviedb.org/tv/{show['id']}"
|
||||
),
|
||||
"imdb": MetadataID(
|
||||
show["imdb_id"],
|
||||
f"https://www.imdb.com/title/{show['imdb_id']}",
|
||||
show["external_ids"]["imdb_id"],
|
||||
f"https://www.imdb.com/title/{show['external_ids']['imdb_id']}",
|
||||
),
|
||||
"tvdb": MetadataID(show["external_ids"]["tvdb_id"], link=None),
|
||||
},
|
||||
seasons=[
|
||||
self.to_season(x, language=lng, show_id=show["id"])
|
||||
@ -215,7 +216,7 @@ class TheMovieDatabase(Provider):
|
||||
translation = ShowTranslation(
|
||||
name=show["name"],
|
||||
tagline=show["tagline"],
|
||||
keywords=list(map(lambda x: x["name"], show["keywords"]["keywords"])),
|
||||
keywords=list(map(lambda x: x["name"], show["keywords"]["results"])),
|
||||
overview=show["overview"],
|
||||
posters=self.get_image(show["images"]["posters"]),
|
||||
logos=self.get_image(show["images"]["logos"]),
|
||||
@ -257,8 +258,8 @@ class TheMovieDatabase(Provider):
|
||||
) -> Season:
|
||||
return Season(
|
||||
season_number=season["season_number"],
|
||||
start_date=datetime.strptime(season["air_date"], "%Y-%m-%d").date(),
|
||||
end_date=None,
|
||||
start_air=datetime.strptime(season["air_date"], "%Y-%m-%d").date(),
|
||||
end_air=None,
|
||||
external_id={
|
||||
self.name: MetadataID(
|
||||
season["id"],
|
||||
@ -269,10 +270,10 @@ class TheMovieDatabase(Provider):
|
||||
language: SeasonTranslation(
|
||||
name=season["name"],
|
||||
overview=season["overview"],
|
||||
poster=[
|
||||
posters=[
|
||||
f"https://image.tmdb.org/t/p/original{season['poster_path']}"
|
||||
]
|
||||
if "poster_path" in season
|
||||
if season["poster_path"] is not None
|
||||
else [],
|
||||
thumbnails=[],
|
||||
)
|
||||
@ -295,7 +296,9 @@ class TheMovieDatabase(Provider):
|
||||
|
||||
# TODO: Handle absolute episodes
|
||||
if not season or not episode_nbr:
|
||||
raise NotImplementedError("Absolute order episodes not implemented for the movie database")
|
||||
raise NotImplementedError(
|
||||
"Absolute order episodes not implemented for the movie database"
|
||||
)
|
||||
|
||||
async def for_language(lng: str) -> Episode:
|
||||
episode = await self.get(
|
||||
@ -327,7 +330,7 @@ class TheMovieDatabase(Provider):
|
||||
external_id={
|
||||
self.name: MetadataID(
|
||||
episode["id"],
|
||||
f"https://www.themoviedb.org/movie/{episode['id']}",
|
||||
f"https://www.themoviedb.org/tv/{show_id}/season/{episode['season_number']}/episode/{episode['episode_number']}",
|
||||
),
|
||||
},
|
||||
)
|
||||
|
@ -28,7 +28,7 @@ class Episode:
|
||||
season_number: Optional[int]
|
||||
episode_number: Optional[int]
|
||||
absolute_number: Optional[int]
|
||||
release_date: Optional[date]
|
||||
release_date: Optional[date | int]
|
||||
thumbnail: Optional[str]
|
||||
external_id: dict[str, MetadataID]
|
||||
|
||||
@ -43,5 +43,4 @@ class Episode:
|
||||
return {
|
||||
**asdict(self),
|
||||
**asdict(self.translations[default_language]),
|
||||
"release_date": format_date(self.release_date),
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class MetadataID:
|
||||
id: str
|
||||
link: str
|
||||
link: Optional[str]
|
||||
|
@ -56,7 +56,7 @@ class Movie:
|
||||
),
|
||||
"logo": next(iter(self.translations[default_language].logos), None),
|
||||
"trailer": next(iter(self.translations[default_language].trailers), None),
|
||||
"studio": next(iter(x.to_kyoo() for x in self.studios), None),
|
||||
"studio": next(iter(self.studios), None),
|
||||
"release_date": None,
|
||||
"startAir": format_date(self.release_date),
|
||||
"title": self.translations[default_language].name,
|
||||
|
@ -1,7 +1,9 @@
|
||||
import os
|
||||
from datetime import date
|
||||
from dataclasses import dataclass, field
|
||||
from dataclasses import dataclass, field, asdict
|
||||
from typing import Optional
|
||||
|
||||
from ..utils import format_date
|
||||
from .metadataid import MetadataID
|
||||
|
||||
|
||||
@ -9,15 +11,27 @@ from .metadataid import MetadataID
|
||||
class SeasonTranslation:
|
||||
name: Optional[str]
|
||||
overview: Optional[str]
|
||||
poster: list[str]
|
||||
posters: list[str]
|
||||
thumbnails: list[str]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Season:
|
||||
season_number: int
|
||||
start_date: Optional[date | int]
|
||||
end_date: Optional[date | int]
|
||||
start_air: Optional[date | int]
|
||||
end_air: Optional[date | int]
|
||||
external_id: dict[str, MetadataID]
|
||||
|
||||
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]
|
||||
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
|
||||
),
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ from .season import Season
|
||||
from .metadataid import MetadataID
|
||||
from ..utils import format_date
|
||||
|
||||
|
||||
class Status(str, Enum):
|
||||
UNKNOWN = "unknown"
|
||||
FINISHED = "finished"
|
||||
@ -58,9 +59,8 @@ class Show:
|
||||
),
|
||||
"logo": next(iter(self.translations[default_language].logos), None),
|
||||
"trailer": next(iter(self.translations[default_language].trailers), None),
|
||||
"studio": next(iter(x.to_kyoo() for x in self.studios), None),
|
||||
"startAir": format_date(self.start_air),
|
||||
"endAir": format_date(self.end_air),
|
||||
"studio": next(iter(self.studios), None),
|
||||
"title": self.translations[default_language].name,
|
||||
"genres": [x.to_kyoo() for x in self.genres],
|
||||
"seasons": [x.to_kyoo() for x in self.seasons],
|
||||
}
|
||||
|
@ -8,6 +8,3 @@ class Studio:
|
||||
name: str
|
||||
logos: list[str] = field(default_factory=list)
|
||||
external_id: dict[str, MetadataID] = field(default_factory=dict)
|
||||
|
||||
def to_kyoo(self):
|
||||
return asdict(self)
|
||||
|
@ -1,8 +1,9 @@
|
||||
from datetime import date
|
||||
|
||||
|
||||
def format_date(date: date | int | None) -> str | None:
|
||||
if date is None:
|
||||
return None
|
||||
if isinstance(date, int):
|
||||
return f"{date}-01-01T00:00:00Z"
|
||||
return f"{date}-01-01"
|
||||
return date.isoformat()
|
||||
|
@ -1,3 +1,4 @@
|
||||
guessit
|
||||
aiohttp
|
||||
jsons
|
||||
black-with-tabs
|
||||
|
@ -5,7 +5,11 @@ async def main():
|
||||
import os
|
||||
import logging
|
||||
import sys
|
||||
import jsons
|
||||
from datetime import date
|
||||
from typing import Optional
|
||||
from aiohttp import ClientSession
|
||||
from providers.utils import format_date
|
||||
|
||||
path = os.environ.get("LIBRARY_ROOT")
|
||||
if not path:
|
||||
@ -28,7 +32,12 @@ async def main():
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "-vv":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
async with ClientSession() as client:
|
||||
jsons.set_serializer(lambda x, **_: format_date(x), Optional[date | int])
|
||||
async with ClientSession(
|
||||
json_serialize=lambda *args, **kwargs: jsons.dumps(
|
||||
*args, key_transformer=jsons.KEY_TRANSFORMER_CAMELCASE, **kwargs
|
||||
),
|
||||
) as client:
|
||||
await Scanner(client, languages=languages.split(","), api_key=api_key).scan(
|
||||
path
|
||||
)
|
||||
|
@ -1,13 +1,14 @@
|
||||
from functools import wraps
|
||||
import json
|
||||
import os
|
||||
import asyncio
|
||||
import logging
|
||||
import jsons
|
||||
from aiohttp import ClientSession
|
||||
from pathlib import Path
|
||||
from guessit import guessit
|
||||
from providers.provider import Provider
|
||||
from providers.types.episode import PartialShow
|
||||
from providers.types.episode import Episode, PartialShow
|
||||
from providers.types.show import Show
|
||||
|
||||
|
||||
def log_errors(f):
|
||||
@ -81,7 +82,15 @@ class Scanner:
|
||||
|
||||
async def post(self, path: str, *, data: object) -> str:
|
||||
url = os.environ.get("KYOO_URL", "http://back:5000")
|
||||
print(json.dumps(data, indent=4))
|
||||
logging.info(
|
||||
"Sending %s: %s",
|
||||
path,
|
||||
jsons.dumps(
|
||||
data,
|
||||
key_transformer=jsons.KEY_TRANSFORMER_CAMELCASE,
|
||||
jdkwargs={"indent": 4},
|
||||
),
|
||||
)
|
||||
async with self._client.post(
|
||||
f"{url}/{path}", json=data, headers={"X-API-Key": self._api_key}
|
||||
) as r:
|
||||
|
Loading…
x
Reference in New Issue
Block a user