mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Compute absolute ordering from normal seasons
This commit is contained in:
parent
d10eb66542
commit
f9d6a816b0
@ -3,9 +3,10 @@ import logging
|
|||||||
from aiohttp import ClientSession
|
from aiohttp import ClientSession
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Awaitable, Callable, Dict, List, Optional, Any, TypeVar
|
from typing import Awaitable, Callable, Dict, List, Optional, Any, TypeVar
|
||||||
|
from itertools import accumulate
|
||||||
|
|
||||||
from providers.idmapper import IdMapper
|
from providers.idmapper import IdMapper
|
||||||
from providers.implementations.thexem import TheXem
|
from providers.implementations.thexem import TheXem
|
||||||
|
|
||||||
from providers.utils import ProviderError
|
from providers.utils import ProviderError
|
||||||
from scanner.cache import cache
|
from scanner.cache import cache
|
||||||
|
|
||||||
@ -134,7 +135,6 @@ class TheMovieDatabase(Provider):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
logging.debug("TMDb responded: %s", movie)
|
logging.debug("TMDb responded: %s", movie)
|
||||||
# TODO: Use collection data
|
|
||||||
|
|
||||||
ret = Movie(
|
ret = Movie(
|
||||||
original_language=movie["original_language"],
|
original_language=movie["original_language"],
|
||||||
@ -350,6 +350,7 @@ class TheMovieDatabase(Provider):
|
|||||||
) -> Season:
|
) -> Season:
|
||||||
return Season(
|
return Season(
|
||||||
season_number=season["season_number"],
|
season_number=season["season_number"],
|
||||||
|
episodes_count=season["episode_count"],
|
||||||
start_air=datetime.strptime(season["air_date"], "%Y-%m-%d").date()
|
start_air=datetime.strptime(season["air_date"], "%Y-%m-%d").date()
|
||||||
if season["air_date"]
|
if season["air_date"]
|
||||||
else None,
|
else None,
|
||||||
@ -458,12 +459,13 @@ class TheMovieDatabase(Provider):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if season is None or episode_nbr is None:
|
if season is None or episode_nbr is None:
|
||||||
# Some shows don't have absolute numbering because the default one is absolute on tmdb (for example detetive conan)
|
raise ProviderError(
|
||||||
season = 1
|
"Could not guess season or episode number of the episode %s %d-%d (%d)",
|
||||||
episode_nbr = absolute
|
name,
|
||||||
|
season,
|
||||||
if season is None or episode_nbr is None:
|
episode_nbr,
|
||||||
raise ProviderError("Could not guess season or episode number of the episode %s %d-%d (%d)", name, season, episode_nbr, absolute)
|
absolute,
|
||||||
|
)
|
||||||
|
|
||||||
if absolute is None:
|
if absolute is None:
|
||||||
absolute = await self.get_absolute_number(show_id, season, episode_nbr)
|
absolute = await self.get_absolute_number(show_id, season, episode_nbr)
|
||||||
@ -575,6 +577,7 @@ class TheMovieDatabase(Provider):
|
|||||||
logging.exception(
|
logging.exception(
|
||||||
"Could not retrieve absolute ordering information", exc_info=e
|
"Could not retrieve absolute ordering information", exc_info=e
|
||||||
)
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
async def get_episode_from_absolute(self, show_id: str, absolute: int):
|
async def get_episode_from_absolute(self, show_id: str, absolute: int):
|
||||||
absgrp = await self.get_absolute_order(show_id)
|
absgrp = await self.get_absolute_order(show_id)
|
||||||
@ -584,16 +587,26 @@ class TheMovieDatabase(Provider):
|
|||||||
season = absgrp[absolute - 1]["season_number"]
|
season = absgrp[absolute - 1]["season_number"]
|
||||||
episode_nbr = absgrp[absolute - 1]["episode_number"]
|
episode_nbr = absgrp[absolute - 1]["episode_number"]
|
||||||
return (season, episode_nbr)
|
return (season, episode_nbr)
|
||||||
# TODO: if no group exist, simulate one by checking each season ep count and substracting the right amount to get an ep
|
# We assume that each season should be played in order with no special episodes.
|
||||||
# This means that we assume that each season should be played in order with no special episodes.
|
show = await self.identify_show(show_id, original_language=None, language=[])
|
||||||
return (None, None)
|
seasons = [x.episodes_count for x in show.seasons]
|
||||||
|
# enumerate(accumulate(season)) return [(0, 12), (1, 24)] if the show has two seasons with 12 eps
|
||||||
|
# we take the last group that has less total episodes than the absolute number.
|
||||||
|
(season, total_ep_count) = next(
|
||||||
|
(snbr, ep_cnt)
|
||||||
|
for snbr, ep_cnt in reversed(list(enumerate(accumulate(seasons))))
|
||||||
|
if ep_cnt <= absolute
|
||||||
|
)
|
||||||
|
return (show.seasons[season].season_number, absolute - total_ep_count)
|
||||||
|
|
||||||
async def get_absolute_number(self, show_id: str, season: int, episode_nbr: int):
|
async def get_absolute_number(self, show_id: str, season: int, episode_nbr: int):
|
||||||
absgrp = await self.get_absolute_order(show_id)
|
absgrp = await self.get_absolute_order(show_id)
|
||||||
if absgrp is None:
|
if absgrp is None:
|
||||||
# TODO: if no group exist, simulate one by checking each season ep count and adding the right amount to get an ep
|
# We assume that each season should be played in order with no special episodes.
|
||||||
# This means that we assume that each season should be played in order with no special episodes.
|
show = await self.identify_show(
|
||||||
return None
|
show_id, original_language=None, language=[]
|
||||||
|
)
|
||||||
|
return sum(x.episodes_count for x in show.seasons[:season]) + episode_nbr
|
||||||
return next(
|
return next(
|
||||||
(
|
(
|
||||||
# The + 1 is to go from 0based index to 1based absolute number
|
# The + 1 is to go from 0based index to 1based absolute number
|
||||||
|
@ -17,6 +17,9 @@ class SeasonTranslation:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class Season:
|
class Season:
|
||||||
season_number: int
|
season_number: int
|
||||||
|
# This is not used by kyoo, this is just used internaly by the TMDB provider.
|
||||||
|
# maybe this should be moved?
|
||||||
|
episodes_count: int
|
||||||
start_air: Optional[date | int] = None
|
start_air: Optional[date | int] = None
|
||||||
end_air: Optional[date | int] = None
|
end_air: Optional[date | int] = None
|
||||||
external_id: dict[str, MetadataID] = field(default_factory=dict)
|
external_id: dict[str, MetadataID] = field(default_factory=dict)
|
||||||
|
@ -29,7 +29,7 @@ def cache(ttl: timedelta, cache: Cache={}, typed=False):
|
|||||||
ret = cache.get(key, (None, None, None))
|
ret = cache.get(key, (None, None, None))
|
||||||
if ret[2] is None:
|
if ret[2] is None:
|
||||||
# ret[2] can be None if the cached method failed. if that is the case, run again.
|
# ret[2] can be None if the cached method failed. if that is the case, run again.
|
||||||
return wrapper(*args, **kwargs)
|
return await wrapper(*args, **kwargs)
|
||||||
return ret[2]
|
return ret[2]
|
||||||
# Return the cached result if it exits and is not expired
|
# Return the cached result if it exits and is not expired
|
||||||
if (
|
if (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user