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
@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):
"""

View file

@ -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'])
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['itemId'])
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')

View file

@ -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

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