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