mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-01 04:34:50 -04:00
Fix anilist to use it as a provider
This commit is contained in:
parent
a0a5788683
commit
e1169d1d26
@ -11,7 +11,7 @@ from matcher.cache import cache
|
|||||||
from ..provider import Provider
|
from ..provider import Provider
|
||||||
from ..types.movie import Movie, MovieTranslation, Status as MovieStatus
|
from ..types.movie import Movie, MovieTranslation, Status as MovieStatus
|
||||||
from ..types.season import Season, SeasonTranslation
|
from ..types.season import Season, SeasonTranslation
|
||||||
from ..types.episode import Episode, EpisodeTranslation, PartialShow, EpisodeID
|
from ..types.episode import Episode, EpisodeTranslation, EpisodeID
|
||||||
from ..types.studio import Studio
|
from ..types.studio import Studio
|
||||||
from ..types.genre import Genre
|
from ..types.genre import Genre
|
||||||
from ..types.metadataid import MetadataID
|
from ..types.metadataid import MetadataID
|
||||||
@ -24,15 +24,11 @@ logger = getLogger(__name__)
|
|||||||
class AniList(Provider):
|
class AniList(Provider):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
languages: list[str],
|
|
||||||
client: ClientSession,
|
client: ClientSession,
|
||||||
api_key: str,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._languages = languages
|
|
||||||
self._client = client
|
self._client = client
|
||||||
self.base = "https://graphql.anilist.co"
|
self.base = "https://graphql.anilist.co"
|
||||||
self.api_key = api_key
|
|
||||||
self._genre_map = {
|
self._genre_map = {
|
||||||
"Action": Genre.ACTION,
|
"Action": Genre.ACTION,
|
||||||
"Adventure": Genre.ADVENTURE,
|
"Adventure": Genre.ADVENTURE,
|
||||||
@ -59,18 +55,37 @@ class AniList(Provider):
|
|||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return "anilist"
|
return "anilist"
|
||||||
|
|
||||||
async def get(self, query: str, **variables: Optional[str]):
|
async def get(self, query: str, not_found: str, **variables: Optional[str | int]):
|
||||||
|
logger.error(variables)
|
||||||
async with self._client.post(
|
async with self._client.post(
|
||||||
self.base, json={"query": query, "variables": variables}
|
self.base,
|
||||||
|
json={
|
||||||
|
"query": query,
|
||||||
|
"variables": {k: v for (k, v) in variables.items() if v is not None},
|
||||||
|
},
|
||||||
) as r:
|
) as r:
|
||||||
|
if r.status == 404:
|
||||||
|
raise ProviderError(not_found)
|
||||||
|
ret = await r.json()
|
||||||
|
logger.error(ret)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
return await r.json()
|
if "errors" in ret:
|
||||||
|
logger.error(ret)
|
||||||
|
raise Exception(ret["errors"])
|
||||||
|
return ret["data"]
|
||||||
|
|
||||||
async def query_anime(self, id: Optional[str], search: Optional[str]) -> Show:
|
async def query_anime(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
id: Optional[str] = None,
|
||||||
|
search: Optional[str] = None,
|
||||||
|
year: Optional[int] = None,
|
||||||
|
) -> Show:
|
||||||
query = """
|
query = """
|
||||||
{
|
query SearchAnime($id: Int, $search: String, $year: Int) {
|
||||||
Media(id: $id, search: $search, type: ANIME, format_not: MOVIE) {
|
Media(id: $id, search: $search, type: ANIME, format_not: MOVIE, seasonYear: $year) {
|
||||||
id
|
id
|
||||||
|
siteUrl
|
||||||
idMal
|
idMal
|
||||||
title {
|
title {
|
||||||
romaji
|
romaji
|
||||||
@ -130,11 +145,18 @@ class AniList(Provider):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
ret = await self.get(query, id=id, search=search)
|
q = await self.get(
|
||||||
|
query,
|
||||||
|
id=id,
|
||||||
|
search=search,
|
||||||
|
year=year,
|
||||||
|
not_found=f"Could not find the show {id or ''}{search or ''}",
|
||||||
|
)
|
||||||
|
ret = q["Media"]
|
||||||
return Show(
|
return Show(
|
||||||
translations={
|
translations={
|
||||||
"en": ShowTranslation(
|
"en": ShowTranslation(
|
||||||
name=ret["titles"]["romaji"],
|
name=ret["title"]["romaji"],
|
||||||
tagline=None,
|
tagline=None,
|
||||||
# TODO: unmarkdown the desc
|
# TODO: unmarkdown the desc
|
||||||
overview=ret["description"],
|
overview=ret["description"],
|
||||||
@ -153,12 +175,13 @@ class AniList(Provider):
|
|||||||
logos=[],
|
logos=[],
|
||||||
thumbnails=[],
|
thumbnails=[],
|
||||||
trailers=[f"https://youtube.com/watch?q={ret['trailer']['id']}"]
|
trailers=[f"https://youtube.com/watch?q={ret['trailer']['id']}"]
|
||||||
if ret["trailer"]["site"] == "youtube"
|
if ret["trailer"] is not None
|
||||||
|
and ret["trailer"]["site"] == "youtube"
|
||||||
else [],
|
else [],
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
original_language=ret["countryOfOrigin"],
|
original_language=ret["countryOfOrigin"],
|
||||||
aliases=[ret["titles"]["english"], ret["titles"]["native"]],
|
aliases=[ret["title"]["english"], ret["title"]["native"]],
|
||||||
start_air=date(
|
start_air=date(
|
||||||
year=ret["startDate"]["year"],
|
year=ret["startDate"]["year"],
|
||||||
month=ret["startDate"]["month"],
|
month=ret["startDate"]["month"],
|
||||||
@ -168,7 +191,9 @@ class AniList(Provider):
|
|||||||
year=ret["endDate"]["year"],
|
year=ret["endDate"]["year"],
|
||||||
month=ret["endDate"]["month"],
|
month=ret["endDate"]["month"],
|
||||||
day=ret["endDate"]["day"],
|
day=ret["endDate"]["day"],
|
||||||
),
|
)
|
||||||
|
if ret["endDate"]["year"] is not None
|
||||||
|
else None,
|
||||||
status=ShowStatus.FINISHED
|
status=ShowStatus.FINISHED
|
||||||
if ret["status"] == "FINISHED"
|
if ret["status"] == "FINISHED"
|
||||||
else ShowStatus.AIRING,
|
else ShowStatus.AIRING,
|
||||||
@ -201,8 +226,11 @@ class AniList(Provider):
|
|||||||
year: Optional[int] = None,
|
year: Optional[int] = None,
|
||||||
) -> Movie:
|
) -> Movie:
|
||||||
query = """
|
query = """
|
||||||
{
|
query SearchMovie($id: Int, $search: String, $year: Int) {
|
||||||
Media(id: $id, search: $search, type: ANIME, format: MOVIE, seasonYear: $year) {
|
Media(id: $id, search: $search, type: ANIME, format: MOVIE, seasonYear: $year) {
|
||||||
|
id
|
||||||
|
siteUrl
|
||||||
|
idMal
|
||||||
title {
|
title {
|
||||||
romaji
|
romaji
|
||||||
english
|
english
|
||||||
@ -242,11 +270,18 @@ class AniList(Provider):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
ret = await self.get(query, id=id, search=search)
|
q = await self.get(
|
||||||
|
query,
|
||||||
|
id=id,
|
||||||
|
search=search,
|
||||||
|
year=year,
|
||||||
|
not_found=f"No movie found for {id or ''}{search or ''}",
|
||||||
|
)
|
||||||
|
ret = q["Media"]
|
||||||
return Movie(
|
return Movie(
|
||||||
translations={
|
translations={
|
||||||
"en": MovieTranslation(
|
"en": MovieTranslation(
|
||||||
name=ret["titles"]["romaji"],
|
name=ret["title"]["romaji"],
|
||||||
tagline=None,
|
tagline=None,
|
||||||
# TODO: unmarkdown the desc
|
# TODO: unmarkdown the desc
|
||||||
overview=ret["description"],
|
overview=ret["description"],
|
||||||
@ -265,12 +300,13 @@ class AniList(Provider):
|
|||||||
logos=[],
|
logos=[],
|
||||||
thumbnails=[],
|
thumbnails=[],
|
||||||
trailers=[f"https://youtube.com/watch?q={ret['trailer']['id']}"]
|
trailers=[f"https://youtube.com/watch?q={ret['trailer']['id']}"]
|
||||||
if ret["trailer"]["site"] == "youtube"
|
if ret["trailer"] is not None
|
||||||
|
and ret["trailer"]["site"] == "youtube"
|
||||||
else [],
|
else [],
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
original_language=ret["countryOfOrigin"],
|
original_language=ret["countryOfOrigin"],
|
||||||
aliases=[ret["titles"]["english"], ret["titles"]["native"]],
|
aliases=[ret["title"]["english"], ret["title"]["native"]],
|
||||||
air_date=date(
|
air_date=date(
|
||||||
year=ret["startDate"]["year"],
|
year=ret["startDate"]["year"],
|
||||||
month=ret["startDate"]["month"],
|
month=ret["startDate"]["month"],
|
||||||
@ -311,13 +347,35 @@ class AniList(Provider):
|
|||||||
absolute: Optional[int],
|
absolute: Optional[int],
|
||||||
year: Optional[int],
|
year: Optional[int],
|
||||||
) -> Episode:
|
) -> Episode:
|
||||||
raise NotImplementedError
|
absolute = absolute or episode_nbr
|
||||||
|
if absolute is None:
|
||||||
|
raise ProviderError(
|
||||||
|
f"Could not guess episode number of the episode {name} {season}-{episode_nbr} ({absolute})"
|
||||||
|
)
|
||||||
|
|
||||||
|
show = await self.query_anime(search=name, year=year)
|
||||||
|
|
||||||
|
return Episode(
|
||||||
|
show=show,
|
||||||
|
season_number=1,
|
||||||
|
episode_number=absolute,
|
||||||
|
absolute_number=absolute,
|
||||||
|
runtime=None,
|
||||||
|
release_date=None,
|
||||||
|
thumbnail=None,
|
||||||
|
external_id={
|
||||||
|
self.name: EpisodeID(
|
||||||
|
show.external_id[self.name].data_id, None, absolute, None
|
||||||
|
),
|
||||||
|
"mal": EpisodeID(show.external_id["mal"].data_id, None, absolute, None),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
async def identify_movie(self, movie_id: str) -> Movie:
|
async def identify_movie(self, movie_id: str) -> Movie:
|
||||||
return await self.query_movie(id=movie_id)
|
return await self.query_movie(id=movie_id)
|
||||||
|
|
||||||
async def identify_show(self, show_id: str) -> Show:
|
async def identify_show(self, show_id: str) -> Show:
|
||||||
raise NotImplementedError
|
return await self.query_anime(id=show_id)
|
||||||
|
|
||||||
async def identify_season(self, show_id: str, season: int) -> Season:
|
async def identify_season(self, show_id: str, season: int) -> Season:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@ -329,6 +387,3 @@ class AniList(Provider):
|
|||||||
|
|
||||||
async def identify_collection(self, provider_id: str) -> Collection:
|
async def identify_collection(self, provider_id: str) -> Collection:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
async def get_expected_titles(self) -> list[str]:
|
|
||||||
return []
|
|
||||||
|
@ -22,6 +22,9 @@ class Provider:
|
|||||||
languages = languages.split(",")
|
languages = languages.split(",")
|
||||||
providers = []
|
providers = []
|
||||||
|
|
||||||
|
from providers.implementations.anilist import AniList
|
||||||
|
return AniList(client)
|
||||||
|
|
||||||
from providers.implementations.themoviedatabase import TheMovieDatabase
|
from providers.implementations.themoviedatabase import TheMovieDatabase
|
||||||
|
|
||||||
tmdb = os.environ.get("THEMOVIEDB_APIKEY") or TheMovieDatabase.DEFAULT_API_KEY
|
tmdb = os.environ.get("THEMOVIEDB_APIKEY") or TheMovieDatabase.DEFAULT_API_KEY
|
||||||
@ -29,6 +32,7 @@ class Provider:
|
|||||||
tmdb = TheMovieDatabase(languages, client, tmdb)
|
tmdb = TheMovieDatabase(languages, client, tmdb)
|
||||||
providers.append(tmdb)
|
providers.append(tmdb)
|
||||||
|
|
||||||
|
|
||||||
if not any(providers):
|
if not any(providers):
|
||||||
raise ProviderError(
|
raise ProviderError(
|
||||||
"No provider configured. You probably forgot to specify an API Key"
|
"No provider configured. You probably forgot to specify an API Key"
|
||||||
|
@ -19,7 +19,7 @@ class EpisodeID:
|
|||||||
show_id: str
|
show_id: str
|
||||||
season: Optional[int]
|
season: Optional[int]
|
||||||
episode: int
|
episode: int
|
||||||
link: str
|
link: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
Loading…
x
Reference in New Issue
Block a user