From 857fca91ba4a3f00a0e708e0175dd0be17627dc1 Mon Sep 17 00:00:00 2001 From: CastagnaIT Date: Sat, 27 Jun 2020 09:48:53 +0200 Subject: [PATCH] Simplified get_metadata and VideoId derive_parent --- resources/lib/api/api_requests.py | 32 ++++++-------- resources/lib/common/misc_utils.py | 8 ++-- resources/lib/common/videoid.py | 42 ++++++++++--------- resources/lib/navigation/player.py | 2 +- .../services/playback/am_stream_continuity.py | 4 +- .../lib/services/playback/am_video_events.py | 3 +- 6 files changed, 43 insertions(+), 48 deletions(-) diff --git a/resources/lib/api/api_requests.py b/resources/lib/api/api_requests.py index 9067477fe..f89c85256 100644 --- a/resources/lib/api/api_requests.py +++ b/resources/lib/api/api_requests.py @@ -220,39 +220,33 @@ def _update_mylist_cache(videoid, operation, params): def get_metadata(videoid, refresh=False): """Retrieve additional metadata for the given VideoId""" metadata_data = {}, None + # Get the parent VideoId (when the 'videoid' is a type of EPISODE/SEASON) + parent_videoid = videoid.derive_parent(common.VideoId.SHOW) # Delete the cache if we need to refresh the all metadata if refresh: - videoid_cache = (videoid.derive_parent(0) - if videoid.mediatype in [common.VideoId.EPISODE, common.VideoId.SEASON] - else videoid) - g.CACHE.delete(cache_utils.CACHE_METADATA, str(videoid_cache)) - if videoid.mediatype not in [common.VideoId.EPISODE, common.VideoId.SEASON]: - # videoid of type tvshow, movie, supplemental - metadata_data = _metadata(video_id=videoid), None - elif videoid.mediatype == common.VideoId.SEASON: - metadata_data = _metadata(video_id=videoid.derive_parent(None)), None - else: # it is an episode + g.CACHE.delete(cache_utils.CACHE_METADATA, str(parent_videoid)) + if videoid.mediatype == common.VideoId.EPISODE: try: - metadata_data = _episode_metadata(videoid) + metadata_data = _episode_metadata(videoid, parent_videoid) except KeyError as exc: - # Episode metadata may not exist if its a new episode and cached - # data is outdated. In this case, delete the cache entry and - # try again safely (if it doesn't exist this time, there is no - # metadata for the episode, so we assign an empty dict). + # The episode metadata not exist (case of new episode and cached data outdated) + # In this case, delete the cache entry and try again safely common.debug('find_episode_metadata raised an error: {}, refreshing cache', exc) try: - metadata_data = _episode_metadata(videoid, refresh_cache=True) + metadata_data = _episode_metadata(videoid, parent_videoid, refresh_cache=True) except KeyError as exc: + # The new metadata does not contain the episode common.error('Episode metadata not found, find_episode_metadata raised an error: {}', exc) + else: + metadata_data = _metadata(video_id=parent_videoid), None return metadata_data -def _episode_metadata(videoid, refresh_cache=False): - tvshow_videoid = videoid.derive_parent(0) +def _episode_metadata(episode_videoid, tvshow_videoid, refresh_cache=False): if refresh_cache: g.CACHE.delete(cache_utils.CACHE_METADATA, str(tvshow_videoid)) show_metadata = _metadata(video_id=tvshow_videoid) - episode_metadata, season_metadata = common.find_episode_metadata(videoid, show_metadata) + episode_metadata, season_metadata = common.find_episode_metadata(episode_videoid, show_metadata) return episode_metadata, season_metadata, show_metadata diff --git a/resources/lib/common/misc_utils.py b/resources/lib/common/misc_utils.py index 34ac22837..3dad238b6 100644 --- a/resources/lib/common/misc_utils.py +++ b/resources/lib/common/misc_utils.py @@ -37,11 +37,11 @@ def find(value_to_find, attribute, search_space): raise KeyError('Metadata for {} does not exist'.format(value_to_find)) -def find_episode_metadata(videoid, metadata): +def find_episode_metadata(episode_videoid, metadata): """Find metadata for a specific episode within a show metadata dict""" - season = find(int(videoid.seasonid), 'id', metadata['seasons']) - return (find(int(videoid.episodeid), 'id', season.get('episodes', {})), - season) + season = find(int(episode_videoid.seasonid), 'id', metadata['seasons']) + episode = find(int(episode_videoid.episodeid), 'id', season.get('episodes', {})) + return episode, season def get_class_methods(class_item=None): diff --git a/resources/lib/common/videoid.py b/resources/lib/common/videoid.py index 2c03b54fe..a459fdac3 100644 --- a/resources/lib/common/videoid.py +++ b/resources/lib/common/videoid.py @@ -22,8 +22,7 @@ class InvalidVideoId(Exception): class VideoId(object): - """Universal representation of a video id. Video IDs can be of multiple - types: + """Universal representation of a video id. Video IDs can be of multiple types: - supplemental: a single identifier only for supplementalid, all other values must be None - movie: a single identifier only for movieid, all other values must be None - show: a single identifier only for tvshowid, all other values must be None @@ -207,8 +206,7 @@ def derive_season(self, seasonid): of this show. Raises InvalidVideoId is this instance does not represent a show.""" if self.mediatype != VideoId.SHOW: - raise InvalidVideoId('Cannot derive season VideoId from {}' - .format(self)) + raise InvalidVideoId('Cannot derive season VideoId from {}'.format(self)) return type(self)(tvshowid=self.tvshowid, seasonid=unicode(seasonid)) def derive_episode(self, episodeid): @@ -216,24 +214,30 @@ def derive_episode(self, episodeid): of this season. Raises InvalidVideoId is this instance does not represent a season.""" if self.mediatype != VideoId.SEASON: - raise InvalidVideoId('Cannot derive episode VideoId from {}' - .format(self)) + raise InvalidVideoId('Cannot derive episode VideoId from {}'.format(self)) return type(self)(tvshowid=self.tvshowid, seasonid=self.seasonid, episodeid=unicode(episodeid)) - def derive_parent(self, depth): - """Returns a new videoid for the parent mediatype (season for episodes, - show for seasons) that is at the depth's level of the mediatype - hierarchy or this instance if there is no parent mediatype.""" - if self.mediatype == VideoId.SEASON: + def derive_parent(self, videoid_type): + """ + Derive a parent VideoId, you can obtain: + [tvshow] from season, episode + [season] from episode + When it is not possible get a derived VideoId, it is returned the same VideoId instance. + + :param videoid_type: The type of VideoId to be derived + :return: The parent VideoId of specified type, or when not match the same VideoId instance. + """ + if videoid_type == VideoId.SHOW: + if self.mediatype not in [VideoId.SEASON, VideoId.EPISODE]: + return self return type(self)(tvshowid=self.tvshowid) - if self.mediatype == VideoId.EPISODE: - if depth == 0: - return type(self)(tvshowid=self.tvshowid) - if depth == 1: - return type(self)(tvshowid=self.tvshowid, - seasonid=self.seasonid) - return self + if videoid_type == VideoId.SEASON: + if self.mediatype != VideoId.SEASON: + return self + return type(self)(tvshowid=self.tvshowid, + seasonid=self.seasonid) + raise InvalidVideoId('VideoId type {} not valid'.format(videoid_type)) def _assigned_id_values(self): """Return a list of all id_values that are not None""" @@ -258,7 +262,7 @@ def __neq__(self, other): def _get_unicode_kwargs(kwargs): - # Example of return value: (None, None, '70084801', None, None, None, None) this is a movieid + # Example of return value: (None, None, '70084801', None, None, None) this is a movieid return tuple((unicode(kwargs[idpart]) if kwargs.get(idpart) else None) diff --git a/resources/lib/navigation/player.py b/resources/lib/navigation/player.py index 6162a9098..059e1ab42 100644 --- a/resources/lib/navigation/player.py +++ b/resources/lib/navigation/player.py @@ -250,7 +250,7 @@ def _get_event_data(videoid): req_videoids = [videoid] if is_episode: # Get also the tvshow data - req_videoids.append(videoid.derive_parent(0)) + req_videoids.append(videoid.derive_parent(common.VideoId.SHOW)) raw_data = api.get_video_raw_data(req_videoids, EVENT_PATHS) if not raw_data: diff --git a/resources/lib/services/playback/am_stream_continuity.py b/resources/lib/services/playback/am_stream_continuity.py index 37bd2f688..b57b1e06c 100644 --- a/resources/lib/services/playback/am_stream_continuity.py +++ b/resources/lib/services/playback/am_stream_continuity.py @@ -63,9 +63,7 @@ def initialize(self, data): if self.videoid.mediatype not in [common.VideoId.MOVIE, common.VideoId.EPISODE]: self.enabled = False return - self.current_videoid = self.videoid \ - if self.videoid.mediatype == common.VideoId.MOVIE \ - else self.videoid.derive_parent(0) + self.current_videoid = self.videoid.derive_parent(common.VideoId.SHOW) self.sc_settings = g.SHARED_DB.get_stream_continuity(g.LOCAL_DB.get_active_profile_guid(), self.current_videoid.value, {}) self.kodi_only_forced_subtitles = common.get_kodi_subtitle_language() == 'forced_only' diff --git a/resources/lib/services/playback/am_video_events.py b/resources/lib/services/playback/am_video_events.py index 3a2500c1e..7b27b6046 100644 --- a/resources/lib/services/playback/am_video_events.py +++ b/resources/lib/services/playback/am_video_events.py @@ -50,8 +50,7 @@ def initialize(self, data): def on_playback_started(self, player_state): # Clear continue watching list data on the cache, to force loading of new data # but only when the videoid not exists in the continue watching list - current_videoid = (self.videoid if self.videoid.mediatype == common.VideoId.MOVIE - else self.videoid.derive_parent(0)) + current_videoid = self.videoid.derive_parent(common.VideoId.SHOW) videoid_exists, list_id = common.make_http_call('get_continuewatching_videoid_exists', {'video_id': str(current_videoid.value)}) if not videoid_exists: