Overhaul of fanart sync download

This commit is contained in:
tomkat83 2017-02-02 12:27:21 +01:00
parent 67668fdaac
commit f2c7578a25
4 changed files with 98 additions and 103 deletions

View file

@ -63,18 +63,57 @@ class Items(object):
return self return self
@CatchExceptions(warnuser=True) @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: if allartworks is None:
allartworks = API.getAllArtwork() allartworks = API.getAllArtwork()
self.artwork.addArtwork(API.getFanartArtwork(allartworks), self.artwork.addArtwork(API.getFanartArtwork(allartworks),
kodiId, kodi_id,
mediaType, kodi_type,
self.kodicursor) self.kodicursor)
# Also get artwork for collections/movie sets # 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(): for setname in API.getCollections():
log.debug('Getting artwork for movie set %s' % setname) log.debug('Getting artwork for movie set %s' % setname)
setid = self.kodi_db.createBoxset(setname) setid = self.kodi_db.createBoxset(setname)
@ -82,7 +121,8 @@ class Items(object):
setid, setid,
v.KODI_TYPE_SET, v.KODI_TYPE_SET,
self.kodicursor) 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): def updateUserdata(self, xml, viewtag=None, viewid=None):
""" """

View file

@ -267,10 +267,9 @@ class ProcessFanartThread(Thread):
queue Queue.Queue() object that you will need to fill with queue Queue.Queue() object that you will need to fill with
dicts of the following form: dicts of the following form:
{ {
'itemId': the Plex id as a string 'plex_id': the Plex id as a string
'class': the itemtypes class, e.g. 'Movies' 'plex_type': the Plex media type, e.g. 'movie'
'mediaType': the kodi media type, e.g. 'movie' 'refresh': True/False if True, will overwrite any 3rd party
'refresh': True/False if true, will overwrite any 3rd party
fanart. If False, will only get missing fanart. If False, will only get missing
} }
""" """
@ -298,57 +297,17 @@ class ProcessFanartThread(Thread):
except Queue.Empty: except Queue.Empty:
xbmc.sleep(200) xbmc.sleep(200)
continue 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' log.debug('Get additional fanart for Plex id %s' % item['plex_id'])
% item['itemId']) with getattr(itemtypes,
# Download Metadata v.ITEMTYPE_FROM_PLEXTYPE[item['plex_type']])() as cls:
xml = GetPlexMetadata(item['itemId']) result = cls.getfanart(item['plex_id'],
if xml is None: refresh=item['refresh'])
# Did not receive a valid XML - skip that item for now if result is True:
log.warn("Could not get metadata for %s. Skipping that item " log.debug('Done getting fanart for Plex id %s'
"for now" % item['itemId']) % item['plex_id'])
queue.task_done() with plexdb.Get_Plex_DB() as plex_db:
continue plex_db.set_fanart_synched(item['plex_id'])
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'])
queue.task_done() queue.task_done()
log.info("---===### Stopped FanartSync ###===---") log.info("---===### Stopped FanartSync ###===---")
@ -1071,15 +1030,11 @@ class LibrarySync(Thread):
log.info("Sync threads finished") log.info("Sync threads finished")
if (settings('FanartTV') == 'true' and if (settings('FanartTV') == 'true' and
itemType in ('Movies', 'TVShows')): 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: 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({ self.fanartqueue.put({
'itemId': item['itemId'], 'plex_id': item['itemId'],
'class': itemType, 'plex_type': item['mediaType'],
'mediaType': typus,
'refresh': False 'refresh': False
}) })
self.updatelist = [] self.updatelist = []
@ -1484,15 +1439,13 @@ class LibrarySync(Thread):
# processing the item. Do it later (excepting deletions) # processing the item. Do it later (excepting deletions)
continue continue
else: else:
successful, item = self.process_newitems(item) successful = self.process_newitems(item)
if successful and settings('FanartTV') == 'true': if successful and settings('FanartTV') == 'true':
if item['mediatype'] in ('movie', 'show'): plex_type = v.PLEX_TYPE_FROM_WEBSOCKET[item['type']]
mediaType = {'movie': 'Movie'}[item['mediatype']] if plex_type in (v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW):
cls = {'movie': 'Movies'}[item['mediatype']]
self.fanartqueue.put({ self.fanartqueue.put({
'itemId': item['ratingKey'], 'plex_id': item['ratingKey'],
'class': cls, 'plex_type': plex_type,
'mediaType': mediaType,
'refresh': False 'refresh': False
}) })
if successful is True: if successful is True:
@ -1518,37 +1471,34 @@ class LibrarySync(Thread):
xbmc.executebuiltin('UpdateLibrary(music)') xbmc.executebuiltin('UpdateLibrary(music)')
def process_newitems(self, item): def process_newitems(self, item):
ratingKey = item['ratingKey'] xml = GetPlexMetadata(item['ratingKey'])
xml = GetPlexMetadata(ratingKey)
try: try:
mediatype = xml[0].attrib['type'] mediatype = xml[0].attrib['type']
except (IndexError, KeyError, TypeError): except (IndexError, KeyError, TypeError):
log.error('Could not download metadata for %s' % ratingKey) log.error('Could not download metadata for %s' % item['ratingKey'])
return False, item return False
log.debug("Processing new/updated PMS item: %s" % ratingKey) log.debug("Processing new/updated PMS item: %s" % item['ratingKey'])
viewtag = xml.attrib.get('librarySectionTitle') viewtag = xml.attrib.get('librarySectionTitle')
viewid = xml.attrib.get('librarySectionID') viewid = xml.attrib.get('librarySectionID')
# Attach mediatype for later if mediatype == v.PLEX_TYPE_MOVIE:
item['mediatype'] = mediatype
if mediatype == 'movie':
self.videoLibUpdate = True self.videoLibUpdate = True
with itemtypes.Movies() as movie: with itemtypes.Movies() as movie:
movie.add_update(xml[0], movie.add_update(xml[0],
viewtag=viewtag, viewtag=viewtag,
viewid=viewid) viewid=viewid)
elif mediatype == 'episode': elif mediatype == v.PLEX_TYPE_EPISODE:
self.videoLibUpdate = True self.videoLibUpdate = True
with itemtypes.TVShows() as show: with itemtypes.TVShows() as show:
show.add_updateEpisode(xml[0], show.add_updateEpisode(xml[0],
viewtag=viewtag, viewtag=viewtag,
viewid=viewid) viewid=viewid)
elif mediatype == 'track': elif mediatype == v.PLEX_TYPE_SONG:
self.musicLibUpdate = True self.musicLibUpdate = True
with itemtypes.Music() as music: with itemtypes.Music() as music:
music.add_updateSong(xml[0], music.add_updateSong(xml[0],
viewtag=viewtag, viewtag=viewtag,
viewid=viewid) viewid=viewid)
return True, item return True
def process_deleteditems(self, item): def process_deleteditems(self, item):
if item.get('type') == 1: if item.get('type') == 1:
@ -1713,20 +1663,15 @@ class LibrarySync(Thread):
refresh=True Force refresh all external fanart refresh=True Force refresh all external fanart
""" """
items = [] items = []
typus = {
v.PLEX_TYPE_MOVIE: 'Movies',
v.PLEX_TYPE_SHOW: 'TVShows'
}
with plexdb.Get_Plex_DB() as plex_db: with plexdb.Get_Plex_DB() as plex_db:
for plextype in typus: for plex_type in (v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW):
items.extend(plex_db.itemsByType(plextype)) items.extend(plex_db.itemsByType(plex_type))
# Shuffle the list to not always start out identically # Shuffle the list to not always start out identically
shuffle(items) shuffle(items)
for item in items: for item in items:
self.fanartqueue.put({ self.fanartqueue.put({
'itemId': item['plexId'], 'plex_id': item['plex_id'],
'mediaType': item['kodi_type'], 'plex_type': item['plex_type'],
'class': typus[item['plex_type']],
'refresh': refresh 'refresh': refresh
}) })
@ -1843,10 +1788,8 @@ class LibrarySync(Thread):
% len(missing_fanart)) % len(missing_fanart))
for item in missing_fanart: for item in missing_fanart:
self.fanartqueue.put({ self.fanartqueue.put({
'itemId': item['plex_id'], 'plex_id': item['plex_id'],
'mediaType': item['kodi_type'], 'plex_type': item['plex_type'],
'class': v.ITEMTYPE_FROM_KODITYPE[
item['kodi_type']],
'refresh': True 'refresh': True
}) })
log.info('Refreshing video nodes and playlists now') log.info('Refreshing video nodes and playlists now')

View file

@ -396,7 +396,7 @@ class Plex_DB_Functions():
""" """
Returns a list of dicts for plex_type: Returns a list of dicts for plex_type:
{ {
'plexId': plex_id 'plex_id': plex_id
'kodiId': kodi_id 'kodiId': kodi_id
'kodi_type': kodi_type 'kodi_type': kodi_type
'plex_type': plex_type 'plex_type': plex_type
@ -411,7 +411,7 @@ class Plex_DB_Functions():
result = [] result = []
for row in self.plexcursor.fetchall(): for row in self.plexcursor.fetchall():
result.append({ result.append({
'plexId': row[0], 'plex_id': row[0],
'kodiId': row[1], 'kodiId': row[1],
'kodi_type': row[2], 'kodi_type': row[2],
'plex_type': plex_type 'plex_type': plex_type
@ -427,13 +427,13 @@ class Plex_DB_Functions():
def get_missing_fanart(self): 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 flag is set to 0
This only for plex_type is either movie or TV show This only for plex_type is either movie or TV show
""" """
query = ''' query = '''
SELECT plex_id, kodi_type FROM plex SELECT plex_id, plex_type FROM plex
WHERE fanart_synced = ? WHERE fanart_synced = ?
AND (plex_type = ? OR plex_type = ?) AND (plex_type = ? OR plex_type = ?)
''' '''
@ -443,5 +443,5 @@ class Plex_DB_Functions():
result = [] result = []
for row in rows: for row in rows:
result.append({'plex_id': row[0], result.append({'plex_id': row[0],
'kodi_type': row[1]}) 'plex_type': row[1]})
return result return result

View file

@ -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: # extensions from:
# http://kodi.wiki/view/Features_and_supported_codecs#Format_support (RAW image # http://kodi.wiki/view/Features_and_supported_codecs#Format_support (RAW image
# formats, BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX and Targa/TGA) # formats, BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX and Targa/TGA)