diff --git a/resources/lib/itemtypes.py b/resources/lib/itemtypes.py index cc217b90..f1f86251 100644 --- a/resources/lib/itemtypes.py +++ b/resources/lib/itemtypes.py @@ -63,18 +63,57 @@ class Items(object): return self @CatchExceptions(warnuser=True) - def getfanart(self, item, kodiId, mediaType, allartworks=None): + def getfanart(self, plex_id, refresh=False): """ + Tries to get additional fanart for movies (+sets) and TV shows. + + Returns True if successful, False otherwise """ - API = PlexAPI.API(item) + with plexdb.Get_Plex_DB() as plex_db: + db_item = plex_db.getItem_byId(plex_id) + try: + kodi_id = db_item[0] + kodi_type = db_item[4] + except TypeError: + log.error('Could not get Kodi id for plex id %s, abort getfanart' + % plex_id) + return False + if refresh is True: + # Leave the Plex art untouched + allartworks = None + else: + with kodidb.GetKodiDB('video') as kodi_db: + allartworks = kodi_db.existingArt(kodi_id, kodi_type) + # Check if we even need to get additional art + needsupdate = False + for key, value in allartworks.iteritems(): + if not value and not key == 'BoxRear': + needsupdate = True + break + if needsupdate is False: + log.debug('Already got all fanart for Plex id %s' % plex_id) + return True + + xml = GetPlexMetadata(plex_id) + if xml is None: + # Did not receive a valid XML - skip that item for now + log.error("Could not get metadata for %s. Skipping that item " + "for now" % plex_id) + return False + elif xml == 401: + log.error('HTTP 401 returned by PMS. Too much strain? ' + 'Cancelling sync for now') + # Kill remaining items in queue (for main thread to cont.) + return False + API = PlexAPI.API(xml[0]) if allartworks is None: allartworks = API.getAllArtwork() self.artwork.addArtwork(API.getFanartArtwork(allartworks), - kodiId, - mediaType, + kodi_id, + kodi_type, self.kodicursor) # Also get artwork for collections/movie sets - if mediaType == v.KODI_TYPE_MOVIE: + if kodi_type == v.KODI_TYPE_MOVIE: for setname in API.getCollections(): log.debug('Getting artwork for movie set %s' % setname) setid = self.kodi_db.createBoxset(setname) @@ -82,7 +121,8 @@ class Items(object): setid, v.KODI_TYPE_SET, self.kodicursor) - self.kodi_db.assignBoxset(setid, kodiId) + self.kodi_db.assignBoxset(setid, kodi_id) + return True def updateUserdata(self, xml, viewtag=None, viewid=None): """ diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index d86fc5e5..5430c704 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -267,10 +267,9 @@ class ProcessFanartThread(Thread): queue Queue.Queue() object that you will need to fill with dicts of the following form: { - 'itemId': the Plex id as a string - 'class': the itemtypes class, e.g. 'Movies' - 'mediaType': the kodi media type, e.g. 'movie' - 'refresh': True/False if true, will overwrite any 3rd party + 'plex_id': the Plex id as a string + 'plex_type': the Plex media type, e.g. 'movie' + 'refresh': True/False if True, will overwrite any 3rd party fanart. If False, will only get missing } """ @@ -298,57 +297,17 @@ class ProcessFanartThread(Thread): except Queue.Empty: xbmc.sleep(200) continue - with plexdb.Get_Plex_DB() as plex_db: - try: - kodiId = plex_db.getItem_byId(item['itemId'])[0] - except TypeError: - log.error('Could not get Kodi id for plex id %s' - % item['itemId']) - queue.task_done() - continue - if item['refresh'] is True: - # Leave the Plex art untouched - allartworks = None - else: - with kodidb.GetKodiDB('video') as kodi_db: - allartworks = kodi_db.existingArt(kodiId, - item['mediaType']) - # Check if we even need to get additional art - needsupdate = False - for key, value in allartworks.iteritems(): - if not value and not key == 'BoxRear': - needsupdate = True - break - if needsupdate is False: - log.debug('Already got all art for Plex id %s' - % item['itemId']) - queue.task_done() - continue - log.debug('Getting additional fanart for Plex id %s' - % item['itemId']) - # Download Metadata - xml = GetPlexMetadata(item['itemId']) - if xml is None: - # Did not receive a valid XML - skip that item for now - log.warn("Could not get metadata for %s. Skipping that item " - "for now" % item['itemId']) - queue.task_done() - continue - elif xml == 401: - log.warn('HTTP 401 returned by PMS. Too much strain? ' - 'Cancelling sync for now') - # Kill remaining items in queue (for main thread to cont.) - queue.task_done() - continue - - # Do the work - with getattr(itemtypes, item['class'])() as cls: - cls.getfanart(xml[0], kodiId, item['mediaType'], allartworks) - # signals to queue job is done - log.debug('Done getting fanart for Plex id %s' % item['itemId']) - with plexdb.Get_Plex_DB() as plex_db: - plex_db.set_fanart_synched(item['itemId']) + log.debug('Get additional fanart for Plex id %s' % item['plex_id']) + with getattr(itemtypes, + v.ITEMTYPE_FROM_PLEXTYPE[item['plex_type']])() as cls: + result = cls.getfanart(item['plex_id'], + refresh=item['refresh']) + if result is True: + log.debug('Done getting fanart for Plex id %s' + % item['plex_id']) + with plexdb.Get_Plex_DB() as plex_db: + plex_db.set_fanart_synched(item['plex_id']) queue.task_done() log.info("---===### Stopped FanartSync ###===---") @@ -1071,15 +1030,11 @@ class LibrarySync(Thread): log.info("Sync threads finished") if (settings('FanartTV') == 'true' and itemType in ('Movies', 'TVShows')): - # Save to queue for later processing - typus = {'Movies': v.KODI_TYPE_MOVIE, - 'TVShows': v.KODI_TYPE_SHOW}[itemType] for item in self.updatelist: - if item['mediaType'] in (v.KODI_TYPE_MOVIE, v.KODI_TYPE_SHOW): + if item['mediaType'] in (v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW): self.fanartqueue.put({ - 'itemId': item['itemId'], - 'class': itemType, - 'mediaType': typus, + 'plex_id': item['itemId'], + 'plex_type': item['mediaType'], 'refresh': False }) self.updatelist = [] @@ -1484,15 +1439,13 @@ class LibrarySync(Thread): # processing the item. Do it later (excepting deletions) continue else: - successful, item = self.process_newitems(item) + successful = self.process_newitems(item) if successful and settings('FanartTV') == 'true': - if item['mediatype'] in ('movie', 'show'): - mediaType = {'movie': 'Movie'}[item['mediatype']] - cls = {'movie': 'Movies'}[item['mediatype']] + plex_type = v.PLEX_TYPE_FROM_WEBSOCKET[item['type']] + if plex_type in (v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW): self.fanartqueue.put({ - 'itemId': item['ratingKey'], - 'class': cls, - 'mediaType': mediaType, + 'plex_id': item['ratingKey'], + 'plex_type': plex_type, 'refresh': False }) if successful is True: @@ -1518,37 +1471,34 @@ class LibrarySync(Thread): xbmc.executebuiltin('UpdateLibrary(music)') def process_newitems(self, item): - ratingKey = item['ratingKey'] - xml = GetPlexMetadata(ratingKey) + xml = GetPlexMetadata(item['ratingKey']) try: mediatype = xml[0].attrib['type'] except (IndexError, KeyError, TypeError): - log.error('Could not download metadata for %s' % ratingKey) - return False, item - log.debug("Processing new/updated PMS item: %s" % ratingKey) + log.error('Could not download metadata for %s' % item['ratingKey']) + return False + log.debug("Processing new/updated PMS item: %s" % item['ratingKey']) viewtag = xml.attrib.get('librarySectionTitle') viewid = xml.attrib.get('librarySectionID') - # Attach mediatype for later - item['mediatype'] = mediatype - if mediatype == 'movie': + if mediatype == v.PLEX_TYPE_MOVIE: self.videoLibUpdate = True with itemtypes.Movies() as movie: movie.add_update(xml[0], viewtag=viewtag, viewid=viewid) - elif mediatype == 'episode': + elif mediatype == v.PLEX_TYPE_EPISODE: self.videoLibUpdate = True with itemtypes.TVShows() as show: show.add_updateEpisode(xml[0], viewtag=viewtag, viewid=viewid) - elif mediatype == 'track': + elif mediatype == v.PLEX_TYPE_SONG: self.musicLibUpdate = True with itemtypes.Music() as music: music.add_updateSong(xml[0], viewtag=viewtag, viewid=viewid) - return True, item + return True def process_deleteditems(self, item): if item.get('type') == 1: @@ -1713,20 +1663,15 @@ class LibrarySync(Thread): refresh=True Force refresh all external fanart """ items = [] - typus = { - v.PLEX_TYPE_MOVIE: 'Movies', - v.PLEX_TYPE_SHOW: 'TVShows' - } with plexdb.Get_Plex_DB() as plex_db: - for plextype in typus: - items.extend(plex_db.itemsByType(plextype)) + for plex_type in (v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW): + items.extend(plex_db.itemsByType(plex_type)) # Shuffle the list to not always start out identically shuffle(items) for item in items: self.fanartqueue.put({ - 'itemId': item['plexId'], - 'mediaType': item['kodi_type'], - 'class': typus[item['plex_type']], + 'plex_id': item['plex_id'], + 'plex_type': item['plex_type'], 'refresh': refresh }) @@ -1843,10 +1788,8 @@ class LibrarySync(Thread): % len(missing_fanart)) for item in missing_fanart: self.fanartqueue.put({ - 'itemId': item['plex_id'], - 'mediaType': item['kodi_type'], - 'class': v.ITEMTYPE_FROM_KODITYPE[ - item['kodi_type']], + 'plex_id': item['plex_id'], + 'plex_type': item['plex_type'], 'refresh': True }) log.info('Refreshing video nodes and playlists now') diff --git a/resources/lib/plexdb_functions.py b/resources/lib/plexdb_functions.py index ee187009..179518dc 100644 --- a/resources/lib/plexdb_functions.py +++ b/resources/lib/plexdb_functions.py @@ -396,7 +396,7 @@ class Plex_DB_Functions(): """ Returns a list of dicts for plex_type: { - 'plexId': plex_id + 'plex_id': plex_id 'kodiId': kodi_id 'kodi_type': kodi_type 'plex_type': plex_type @@ -411,7 +411,7 @@ class Plex_DB_Functions(): result = [] for row in self.plexcursor.fetchall(): result.append({ - 'plexId': row[0], + 'plex_id': row[0], 'kodiId': row[1], 'kodi_type': row[2], 'plex_type': plex_type @@ -427,13 +427,13 @@ class Plex_DB_Functions(): def get_missing_fanart(self): """ - Returns a list of {'plex_id': x, 'kodi_type': y} where fanart_synced + Returns a list of {'plex_id': x, 'plex_type': y} where fanart_synced flag is set to 0 This only for plex_type is either movie or TV show """ query = ''' - SELECT plex_id, kodi_type FROM plex + SELECT plex_id, plex_type FROM plex WHERE fanart_synced = ? AND (plex_type = ? OR plex_type = ?) ''' @@ -443,5 +443,5 @@ class Plex_DB_Functions(): result = [] for row in rows: result.append({'plex_id': row[0], - 'kodi_type': row[1]}) + 'plex_type': row[1]}) return result diff --git a/resources/lib/variables.py b/resources/lib/variables.py index 47cd4a9e..ff9a1126 100644 --- a/resources/lib/variables.py +++ b/resources/lib/variables.py @@ -221,6 +221,18 @@ REMAP_TYPE_FROM_PLEXTYPE = { } +PLEX_TYPE_FROM_WEBSOCKET = { + 1: PLEX_TYPE_MOVIE, + 2: PLEX_TYPE_SHOW, + 3: PLEX_TYPE_SEASON, + 4: PLEX_TYPE_EPISODE, + 8: PLEX_TYPE_ARTIST, + 9: PLEX_TYPE_ALBUM, + 10: PLEX_TYPE_SONG, + 12: PLEX_TYPE_CLIP +} + + # extensions from: # http://kodi.wiki/view/Features_and_supported_codecs#Format_support (RAW image # formats, BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX and Targa/TGA)