mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-23 15:30:34 -04:00
Add a basic xem provider
This commit is contained in:
parent
47e6c5f978
commit
d063bd479c
@ -3,6 +3,7 @@ import logging
|
|||||||
from aiohttp import ClientSession
|
from aiohttp import ClientSession
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Awaitable, Callable, Dict, List, Optional, Any, TypeVar
|
from typing import Awaitable, Callable, Dict, List, Optional, Any, TypeVar
|
||||||
|
from providers.implementations.thexem import TheXem
|
||||||
|
|
||||||
from providers.utils import ProviderError
|
from providers.utils import ProviderError
|
||||||
|
|
||||||
@ -18,9 +19,10 @@ from ..types.collection import Collection, CollectionTranslation
|
|||||||
|
|
||||||
|
|
||||||
class TheMovieDatabase(Provider):
|
class TheMovieDatabase(Provider):
|
||||||
def __init__(self, client: ClientSession, api_key: str) -> None:
|
def __init__(self, client: ClientSession, api_key: str, xem: TheXem) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._client = client
|
self._client = client
|
||||||
|
self._xem = xem
|
||||||
self.base = "https://api.themoviedb.org/3"
|
self.base = "https://api.themoviedb.org/3"
|
||||||
self.api_key = api_key
|
self.api_key = api_key
|
||||||
self.genre_map = {
|
self.genre_map = {
|
||||||
@ -382,6 +384,9 @@ class TheMovieDatabase(Provider):
|
|||||||
if search["original_language"] not in language:
|
if search["original_language"] not in language:
|
||||||
language.append(search["original_language"])
|
language.append(search["original_language"])
|
||||||
|
|
||||||
|
if season is None:
|
||||||
|
season = await self._xem.get_season_override("tvdb", tvdbid, name)
|
||||||
|
|
||||||
if not show_id in self.absolute_episode_cache:
|
if not show_id in self.absolute_episode_cache:
|
||||||
await self.get_absolute_order(show_id)
|
await self.get_absolute_order(show_id)
|
||||||
|
|
||||||
|
67
scanner/providers/implementations/thexem.py
Normal file
67
scanner/providers/implementations/thexem.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
from typing import Dict, List, Literal, Tuple
|
||||||
|
from aiohttp import ClientSession
|
||||||
|
from datetime import timedelta, datetime
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
from providers.types.episode import Episode
|
||||||
|
from providers.utils import ProviderError
|
||||||
|
|
||||||
|
|
||||||
|
def cache(ttl: timedelta):
|
||||||
|
def wrap(func):
|
||||||
|
time, value = None, None
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
async def wrapped(*args, **kw):
|
||||||
|
nonlocal time
|
||||||
|
nonlocal value
|
||||||
|
now = datetime.now()
|
||||||
|
if not time or now - time > ttl:
|
||||||
|
value = await func(*args, **kw)
|
||||||
|
time = now
|
||||||
|
return value
|
||||||
|
|
||||||
|
return wrapped
|
||||||
|
|
||||||
|
return wrap
|
||||||
|
|
||||||
|
|
||||||
|
class TheXem:
|
||||||
|
def __init__(self, client: ClientSession) -> None:
|
||||||
|
self._client = client
|
||||||
|
self.base = "https://thexem.info"
|
||||||
|
|
||||||
|
# TODO: make the cache support different providers and handle concurrent calls to the function.
|
||||||
|
@cache(ttl=timedelta(days=1))
|
||||||
|
async def get_map(
|
||||||
|
self, provider: Literal["tvdb"] | Literal["anidb"]
|
||||||
|
) -> Dict[str, List[Dict[str, int]]]:
|
||||||
|
logging.info("Fetching data from thexem for %s", provider)
|
||||||
|
async with self._client.get(
|
||||||
|
f"{self.base}/map/allNames",
|
||||||
|
params={
|
||||||
|
"origin": provider,
|
||||||
|
"seasonNumbers": True,
|
||||||
|
},
|
||||||
|
) as r:
|
||||||
|
r.raise_for_status()
|
||||||
|
ret = (await r.json())
|
||||||
|
if "data" not in ret or ret["result"] == "failure":
|
||||||
|
logging.error("Could not fetch xem metadata. Error: %s", ret["message"])
|
||||||
|
raise ProviderError("Could not fetch xem metadata")
|
||||||
|
return ret["data"]
|
||||||
|
|
||||||
|
async def get_season_override(
|
||||||
|
self, provider: Literal["tvdb"] | Literal["anidb"], id: str, show_name: str
|
||||||
|
):
|
||||||
|
map = await self.get_map(provider)
|
||||||
|
if id not in map:
|
||||||
|
return None
|
||||||
|
for x in map[id]:
|
||||||
|
[(name, season)] = x.items()
|
||||||
|
# TODO: replace .lower() with something a bit smarter
|
||||||
|
if show_name.lower() == name.lower():
|
||||||
|
return season
|
||||||
|
return None
|
@ -17,13 +17,15 @@ Self = TypeVar("Self", bound="Provider")
|
|||||||
class Provider:
|
class Provider:
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_all(cls: type[Self], client: ClientSession) -> list[Self]:
|
def get_all(cls: type[Self], client: ClientSession) -> list[Self]:
|
||||||
from providers.implementations.themoviedatabase import TheMovieDatabase
|
|
||||||
|
|
||||||
providers = []
|
providers = []
|
||||||
|
|
||||||
|
from providers.implementations.thexem import TheXem
|
||||||
|
xem = TheXem(client)
|
||||||
|
|
||||||
|
from providers.implementations.themoviedatabase import TheMovieDatabase
|
||||||
tmdb = os.environ.get("THEMOVIEDB_APIKEY")
|
tmdb = os.environ.get("THEMOVIEDB_APIKEY")
|
||||||
if tmdb:
|
if tmdb:
|
||||||
providers.append(TheMovieDatabase(client, tmdb))
|
providers.append(TheMovieDatabase(client, tmdb, xem))
|
||||||
|
|
||||||
if not any(providers):
|
if not any(providers):
|
||||||
raise ProviderError(
|
raise ProviderError(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user