From 5d67d4a602079247bdce8fb54e5222fa3abd092a Mon Sep 17 00:00:00 2001 From: croneter Date: Thu, 5 Nov 2020 15:47:04 +0100 Subject: [PATCH] Support metadata provider ids (e.g. IMDB) for new Plex Movie Agent --- resources/lib/itemtypes/common.py | 24 +++++++++ resources/lib/itemtypes/movies.py | 41 ++++++-------- resources/lib/itemtypes/tvshows.py | 85 +++++++++++------------------- resources/lib/plex_api/artwork.py | 4 +- resources/lib/plex_api/base.py | 54 +++++++++---------- resources/lib/widgets.py | 5 +- 6 files changed, 102 insertions(+), 111 deletions(-) diff --git a/resources/lib/itemtypes/common.py b/resources/lib/itemtypes/common.py index 3188a112..e2d9323f 100644 --- a/resources/lib/itemtypes/common.py +++ b/resources/lib/itemtypes/common.py @@ -145,3 +145,27 @@ class ItemBase(object): encountered by PKC """ return section_id in app.SYNC.section_ids + + def update_provider_ids(self, api, kodi_id): + """ + Updates the unique metadata provider ids (such as the IMDB id). Returns + a dict of the Kodi unique ids + """ + # We might have an old provider id stored! + self.kodidb.remove_uniqueid(kodi_id, api.kodi_type) + return self.add_provider_ids(api, kodi_id) + + def add_provider_ids(self, api, kodi_id): + """ + Adds the unique ids for all metadata providers to the Kodi database, + such as IMDB or The Movie Database TMDB. + Returns a dict of the Kodi ids: {: } + """ + kodi_unique_ids = api.guids.copy() + for provider, provider_id in api.guids.iteritems(): + kodi_unique_ids[provider] = self.kodidb.add_uniqueid( + kodi_id, + api.kodi_type, + provider_id, + provider) + return kodi_unique_ids diff --git a/resources/lib/itemtypes/movies.py b/resources/lib/itemtypes/movies.py index 1c17f395..0d3f7cc5 100644 --- a/resources/lib/itemtypes/movies.py +++ b/resources/lib/itemtypes/movies.py @@ -56,19 +56,7 @@ class Movie(ItemBase): "default", api.rating(), api.votecount()) - if api.provider('imdb') is not None: - uniqueid = self.kodidb.update_uniqueid(kodi_id, - v.KODI_TYPE_MOVIE, - 'imdb', - api.provider('imdb')) - elif api.provider('tmdb') is not None: - uniqueid = self.kodidb.update_uniqueid(kodi_id, - v.KODI_TYPE_MOVIE, - 'tmdb', - api.provider('tmdb')) - else: - self.kodidb.remove_uniqueid(kodi_id, v.KODI_TYPE_MOVIE) - uniqueid = -1 + unique_id = self.update_provider_ids(api, kodi_id) self.kodidb.modify_people(kodi_id, v.KODI_TYPE_MOVIE, api.people()) @@ -86,18 +74,7 @@ class Movie(ItemBase): "default", api.rating(), api.votecount()) - if api.provider('imdb') is not None: - uniqueid = self.kodidb.add_uniqueid(kodi_id, - v.KODI_TYPE_MOVIE, - api.provider('imdb'), - "imdb") - elif api.provider('tmdb') is not None: - uniqueid = self.kodidb.add_uniqueid(kodi_id, - v.KODI_TYPE_MOVIE, - api.provider('tmdb'), - "tmdb") - else: - uniqueid = -1 + unique_id = self.add_provider_ids(api, kodi_id) self.kodidb.add_people(kodi_id, v.KODI_TYPE_MOVIE, api.people()) @@ -106,6 +83,8 @@ class Movie(ItemBase): kodi_id, v.KODI_TYPE_MOVIE) + unique_id = self._prioritize_provider_id(unique_id) + # Update Kodi's main entry self.kodidb.add_movie(kodi_id, file_id, @@ -117,7 +96,7 @@ class Movie(ItemBase): rating_id, api.list_to_string(api.writers()), api.year(), - uniqueid, + unique_id, api.sorttitle(), api.runtime(), api.content_rating(), @@ -246,3 +225,13 @@ class Movie(ItemBase): db_item['kodi_type'], api.userrating()) return True + + @staticmethod + def _prioritize_provider_id(unique_ids): + """ + Prioritize which ID ends up in the SHOW table (there can only be 1) + tvdb > imdb > tmdb + """ + return unique_ids.get('imdb', + unique_ids.get('tmdb', + unique_ids.get('tvdb'))) diff --git a/resources/lib/itemtypes/tvshows.py b/resources/lib/itemtypes/tvshows.py index f1b6ca46..632d7f2c 100644 --- a/resources/lib/itemtypes/tvshows.py +++ b/resources/lib/itemtypes/tvshows.py @@ -194,19 +194,8 @@ class Show(TvShowMixin, ItemBase): "default", api.rating(), api.votecount()) - if api.provider('tvdb') is not None: - uniqueid = self.kodidb.update_uniqueid(kodi_id, - v.KODI_TYPE_SHOW, - 'tvdb', - api.provider('tvdb')) - elif api.provider('tmdb') is not None: - uniqueid = self.kodidb.update_uniqueid(kodi_id, - v.KODI_TYPE_SHOW, - 'tmdb', - api.provider('tmdb')) - else: - self.kodidb.remove_uniqueid(kodi_id, v.KODI_TYPE_SHOW) - uniqueid = -1 + unique_id = self._prioritize_provider_id( + self.update_provider_ids(api, kodi_id)) self.kodidb.modify_people(kodi_id, v.KODI_TYPE_SHOW, api.people()) @@ -221,7 +210,7 @@ class Show(TvShowMixin, ItemBase): api.premiere_date(), api.list_to_string(api.genres()), api.title(), - uniqueid, + unique_id, api.content_rating(), api.list_to_string(api.studios()), api.sorttitle(), @@ -236,18 +225,8 @@ class Show(TvShowMixin, ItemBase): "default", api.rating(), api.votecount()) - if api.provider('tvdb'): - uniqueid = self.kodidb.add_uniqueid(kodi_id, - v.KODI_TYPE_SHOW, - api.provider('tvdb'), - 'tvdb') - if api.provider('tmdb'): - uniqueid = self.kodidb.add_uniqueid(kodi_id, - v.KODI_TYPE_SHOW, - api.provider('tmdb'), - 'tmdb') - else: - uniqueid = -1 + unique_id = self._prioritize_provider_id( + self.add_provider_ids(api, kodi_id)) self.kodidb.add_people(kodi_id, v.KODI_TYPE_SHOW, api.people()) @@ -263,7 +242,7 @@ class Show(TvShowMixin, ItemBase): api.premiere_date(), api.list_to_string(api.genres()), api.title(), - uniqueid, + unique_id, api.content_rating(), api.list_to_string(api.studios()), api.sorttitle()) @@ -281,6 +260,15 @@ class Show(TvShowMixin, ItemBase): kodi_pathid=kodi_pathid, last_sync=self.last_sync) + @staticmethod + def _prioritize_provider_id(unique_ids): + """ + Prioritize which ID ends up in the SHOW table (there can only be 1) + tvdb > imdb > tmdb + """ + return unique_ids.get('tvdb', + unique_ids.get('imdb', + unique_ids.get('tmdb'))) class Season(TvShowMixin, ItemBase): def add_update(self, xml, section_name=None, section_id=None, @@ -459,19 +447,8 @@ class Episode(TvShowMixin, ItemBase): "default", api.rating(), api.votecount()) - if api.provider('tvdb'): - uniqueid = self.kodidb.update_uniqueid(kodi_id, - v.KODI_TYPE_EPISODE, - 'tvdb', - api.provider('tvdb')) - elif api.provider('tmdb'): - uniqueid = self.kodidb.update_uniqueid(kodi_id, - v.KODI_TYPE_EPISODE, - 'tmdb', - api.provider('tmdb')) - else: - self.kodidb.remove_uniqueid(kodi_id, v.KODI_TYPE_EPISODE) - uniqueid = -1 + unique_id = self._prioritize_provider_id( + self.update_provider_ids(api, kodi_id)) self.kodidb.modify_people(kodi_id, v.KODI_TYPE_EPISODE, api.people()) @@ -493,7 +470,7 @@ class Episode(TvShowMixin, ItemBase): airs_before_episode, fullpath, kodi_pathid, - uniqueid, + unique_id, kodi_fileid, # and NOT kodi_fileid_2 parent_id, api.userrating(), @@ -539,18 +516,8 @@ class Episode(TvShowMixin, ItemBase): "default", api.rating(), api.votecount()) - if api.provider('tvdb'): - uniqueid = self.kodidb.add_uniqueid(kodi_id, - v.KODI_TYPE_EPISODE, - api.provider('tvdb'), - "tvdb") - elif api.provider('tmdb'): - uniqueid = self.kodidb.add_uniqueid(kodi_id, - v.KODI_TYPE_EPISODE, - api.provider('tmdb'), - "tmdb") - else: - uniqueid = -1 + unique_id = self._prioritize_provider_id( + self.add_provider_ids(api, kodi_id)) self.kodidb.add_people(kodi_id, v.KODI_TYPE_EPISODE, api.people()) @@ -575,7 +542,7 @@ class Episode(TvShowMixin, ItemBase): airs_before_episode, fullpath, kodi_pathid, - uniqueid, + unique_id, parent_id, api.userrating()) self.kodidb.set_resume(kodi_fileid, @@ -605,3 +572,13 @@ class Episode(TvShowMixin, ItemBase): self.kodidb.modify_streams(kodi_fileid, # and NOT kodi_fileid_2 api.mediastreams(), api.runtime()) + + @staticmethod + def _prioritize_provider_id(unique_ids): + """ + Prioritize which ID ends up in the SHOW table (there can only be 1) + tvdb > imdb > tmdb + """ + return unique_ids.get('tvdb', + unique_ids.get('imdb', + unique_ids.get('tmdb'))) diff --git a/resources/lib/plex_api/artwork.py b/resources/lib/plex_api/artwork.py index c5f3d62d..a44be6f3 100644 --- a/resources/lib/plex_api/artwork.py +++ b/resources/lib/plex_api/artwork.py @@ -186,9 +186,9 @@ class Artwork(object): # Always seek collection's ids since not provided by PMS if collection is False: if media_type == v.PLEX_TYPE_MOVIE: - media_id = self.provider('imdb') + media_id = self.guids.get('imdb') elif media_type == v.PLEX_TYPE_SHOW: - media_id = self.provider('tvdb') + media_id = self.guids.get('tvdb') if media_id is not None: return media_id, None, None LOG.info('Plex did not provide ID for IMDB or TVDB. Start ' diff --git a/resources/lib/plex_api/base.py b/resources/lib/plex_api/base.py index ef98f83f..f20178e7 100644 --- a/resources/lib/plex_api/base.py +++ b/resources/lib/plex_api/base.py @@ -13,6 +13,9 @@ from .. import widgets LOG = getLogger('PLEX.api') +METADATA_PROVIDERS = (('imdb', utils.REGEX_IMDB), + ('tvdb', utils.REGEX_TVDB), + ('tmdb', utils.REGEX_TMDB)) class Base(object): """ @@ -40,6 +43,7 @@ class Base(object): self._writers = [] self._producers = [] self._locations = [] + self._guids = {} self._coll_match = None # Plex DB attributes self._section_id = None @@ -131,6 +135,11 @@ class Base(object): self.check_db() return self._fanart_synced + @property + def guids(self): + self._scan_children() + return self._guids + def check_db(self, plexdb=None): """ Check's whether we synched this item to Kodi. If so, then retrieve the @@ -457,6 +466,24 @@ class Base(object): elif child.tag == 'Collection': self._collections.append((cast(int, child.get('id')), child.get('tag'))) + elif child.tag == 'Guid': + guid = child.get('id') + guid = guid.split('://', 1) + self._guids[guid[0]] = guid[1] + # Plex Movie agent (legacy) or "normal" Plex tv show agent + if not self._guids: + guid = self.xml.get('guid') + if not guid: + return + for provider, regex in METADATA_PROVIDERS: + provider_id = regex.findall(guid) + try: + self._guids[provider] = provider_id[0] + except IndexError: + pass + else: + # There will only ever be one entry + break def cast(self): """ @@ -544,33 +571,6 @@ class Base(object): 'writer': [(x, ) for x in self._writers] } - def provider(self, providername=None): - """ - providername: e.g. 'imdb', 'tvdb' - - Return IMDB, e.g. "tt0903624". Returns None if not found - """ - item = self.xml.get('guid') - if not item: - return - if providername == 'imdb': - regex = utils.REGEX_IMDB - elif providername == 'tvdb': - # originally e.g. com.plexapp.agents.thetvdb://276564?lang=en - regex = utils.REGEX_TVDB - elif providername == 'tmdb': - # originally e.g. com.plexapp.agents.themoviedb://603?lang=en - regex = utils.REGEX_TMDB - else: - raise NotImplementedError('Not implemented: %s' % providername) - - provider = regex.findall(item) - try: - provider = provider[0] - except IndexError: - provider = None - return provider - def extras(self): """ Returns an iterator for etree elements for each extra, e.g. trailers diff --git a/resources/lib/widgets.py b/resources/lib/widgets.py index 0252de12..80805f00 100644 --- a/resources/lib/widgets.py +++ b/resources/lib/widgets.py @@ -168,8 +168,9 @@ def _generate_content(api): 'trailer': api.trailer(), 'tvshowtitle': api.show_title(), 'uniqueid': { - 'imdbnumber': api.provider('imdb') or '', - 'tvdb_id': api.provider('tvdb') or '' + 'imdbnumber': api.guids.get('imdb') or '', + 'tvdb_id': api.guids.get('tvdb') or '', + 'tmdb_id': api.guids.get('tmdb') or '' }, 'votes': '0', # [str]! 'writer': api.writers(), # list of [str]