Artwork overhaul part 2
This commit is contained in:
parent
b4716ba511
commit
8272a67b5f
5 changed files with 196 additions and 325 deletions
|
@ -54,19 +54,6 @@ LOG = getLogger("PLEX." + __name__)
|
||||||
REGEX_IMDB = re_compile(r'''/(tt\d+)''')
|
REGEX_IMDB = re_compile(r'''/(tt\d+)''')
|
||||||
REGEX_TVDB = re_compile(r'''thetvdb:\/\/(.+?)\?''')
|
REGEX_TVDB = re_compile(r'''thetvdb:\/\/(.+?)\?''')
|
||||||
|
|
||||||
# we need to use a little mapping between fanart.tv arttypes and kodi
|
|
||||||
# artttypes
|
|
||||||
FANART_TV_TYPES = [
|
|
||||||
("logo", "Logo"),
|
|
||||||
("musiclogo", "clearlogo"),
|
|
||||||
("disc", "Disc"),
|
|
||||||
("clearart", "Art"),
|
|
||||||
("banner", "Banner"),
|
|
||||||
("clearlogo", "Logo"),
|
|
||||||
("background", "fanart"),
|
|
||||||
("showbackground", "fanart"),
|
|
||||||
("characterart", "characterart")
|
|
||||||
]
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
@ -755,10 +742,9 @@ class API(object):
|
||||||
'banner'
|
'banner'
|
||||||
'clearart'
|
'clearart'
|
||||||
'clearlogo'
|
'clearlogo'
|
||||||
'landscape'
|
|
||||||
'icon'
|
|
||||||
'fanart'
|
'fanart'
|
||||||
}
|
}
|
||||||
|
'landscape' and 'icon' might be implemented later
|
||||||
"""
|
"""
|
||||||
if kodi_id:
|
if kodi_id:
|
||||||
# in Kodi database, potentially with additional e.g. clearart
|
# in Kodi database, potentially with additional e.g. clearart
|
||||||
|
@ -783,7 +769,7 @@ class API(object):
|
||||||
if art:
|
if art:
|
||||||
artworks['tvshow.poster'] = art
|
artworks['tvshow.poster'] = art
|
||||||
# Get parent item artwork if the main item is missing artwork
|
# Get parent item artwork if the main item is missing artwork
|
||||||
if 'fanart1' not in artworks:
|
if 'fanart' not in artworks:
|
||||||
art = self._one_artwork('parentArt')
|
art = self._one_artwork('parentArt')
|
||||||
if art:
|
if art:
|
||||||
artworks['fanart1'] = art
|
artworks['fanart1'] = art
|
||||||
|
@ -791,39 +777,31 @@ class API(object):
|
||||||
art = self._one_artwork('parentThumb')
|
art = self._one_artwork('parentThumb')
|
||||||
if art:
|
if art:
|
||||||
artworks['poster'] = art
|
artworks['poster'] = art
|
||||||
LOG.debug('artworks: %s', artworks)
|
|
||||||
return artworks
|
return artworks
|
||||||
|
|
||||||
def fanart_artwork(self, allartworks):
|
def fanart_artwork(self, artworks):
|
||||||
"""
|
"""
|
||||||
Downloads additional fanart from third party sources (well, link to
|
Downloads additional fanart from third party sources (well, link to
|
||||||
fanart only).
|
fanart only).
|
||||||
|
|
||||||
allartworks = {
|
|
||||||
'Primary': "",
|
|
||||||
'Art': "",
|
|
||||||
'Banner': "",
|
|
||||||
'Logo': "",
|
|
||||||
'Thumb': "",
|
|
||||||
'Disc': "",
|
|
||||||
'Backdrop': []
|
|
||||||
}
|
|
||||||
"""
|
"""
|
||||||
external_id = self.retrieve_external_item_id()
|
external_id = self.retrieve_external_item_id()
|
||||||
if external_id is not None:
|
if external_id is not None:
|
||||||
allartworks = self.lookup_fanart_tv(external_id, allartworks)
|
artworks = self.lookup_fanart_tv(external_id[0], artworks)
|
||||||
return allartworks
|
LOG.debug('fanart artworks: %s', artworks)
|
||||||
|
return artworks
|
||||||
|
|
||||||
def retrieve_external_item_id(self, collection=False):
|
def retrieve_external_item_id(self, collection=False):
|
||||||
"""
|
"""
|
||||||
Returns the item's IMDB id for movies or tvdb id for TV shows
|
Returns the set
|
||||||
|
media_id [unicode]: the item's IMDB id for movies or tvdb id for
|
||||||
|
TV shows
|
||||||
|
poster [unicode]: path to the item's poster artwork
|
||||||
|
background [unicode]: path to the item's background artwork
|
||||||
|
|
||||||
If not found in item's Plex metadata, check themovidedb.org
|
The last two might be None if not found. Generally None is returned
|
||||||
|
if unsuccessful.
|
||||||
|
|
||||||
collection=True will try to return the three-tuple:
|
If not found in item's Plex metadata, check themovidedb.org.
|
||||||
collection ID, poster-path, background-path
|
|
||||||
|
|
||||||
None is returned if unsuccessful
|
|
||||||
"""
|
"""
|
||||||
item = self.item.attrib
|
item = self.item.attrib
|
||||||
media_type = item.get('type')
|
media_type = item.get('type')
|
||||||
|
@ -836,7 +814,7 @@ class API(object):
|
||||||
elif media_type == v.PLEX_TYPE_SHOW:
|
elif media_type == v.PLEX_TYPE_SHOW:
|
||||||
media_id = self.provider('tvdb')
|
media_id = self.provider('tvdb')
|
||||||
if media_id is not None:
|
if media_id is not None:
|
||||||
return media_id
|
return media_id, None, None
|
||||||
LOG.info('Plex did not provide ID for IMDB or TVDB. Start '
|
LOG.info('Plex did not provide ID for IMDB or TVDB. Start '
|
||||||
'lookup process')
|
'lookup process')
|
||||||
else:
|
else:
|
||||||
|
@ -935,9 +913,8 @@ class API(object):
|
||||||
media_type = entry.get("media_type")
|
media_type = entry.get("media_type")
|
||||||
name = entry.get("name", entry.get("title"))
|
name = entry.get("name", entry.get("title"))
|
||||||
# lookup external tmdb_id and perform artwork lookup on fanart.tv
|
# lookup external tmdb_id and perform artwork lookup on fanart.tv
|
||||||
parameters = {
|
parameters = {'api_key': api_key}
|
||||||
'api_key': api_key
|
media_id, poster, background = None, None, None
|
||||||
}
|
|
||||||
for language in [v.KODILANGUAGE, "en"]:
|
for language in [v.KODILANGUAGE, "en"]:
|
||||||
parameters['language'] = language
|
parameters['language'] = language
|
||||||
if media_type == "movie":
|
if media_type == "movie":
|
||||||
|
@ -985,23 +962,21 @@ class API(object):
|
||||||
data.get('poster_path'))
|
data.get('poster_path'))
|
||||||
background = ('https://image.tmdb.org/t/p/original%s' %
|
background = ('https://image.tmdb.org/t/p/original%s' %
|
||||||
data.get('backdrop_path'))
|
data.get('backdrop_path'))
|
||||||
media_id = media_id, poster, background
|
|
||||||
break
|
break
|
||||||
return media_id
|
return media_id, poster, background
|
||||||
|
|
||||||
def lookup_fanart_tv(self, media_id, allartworks, set_info=False):
|
def lookup_fanart_tv(self, media_id, artworks, set_info=False):
|
||||||
"""
|
"""
|
||||||
perform artwork lookup on fanart.tv
|
perform artwork lookup on fanart.tv
|
||||||
|
|
||||||
media_id: IMDB id for movies, tvdb id for TV shows
|
media_id: IMDB id for movies, tvdb id for TV shows
|
||||||
"""
|
"""
|
||||||
item = self.item.attrib
|
|
||||||
api_key = settings('FanArtTVAPIKey')
|
api_key = settings('FanArtTVAPIKey')
|
||||||
typus = item.get('type')
|
typus = self.plex_type()
|
||||||
if typus == 'show':
|
if typus == v.PLEX_TYPE_SHOW:
|
||||||
typus = 'tv'
|
typus = 'tv'
|
||||||
|
|
||||||
if typus == "movie":
|
if typus == v.PLEX_TYPE_MOVIE:
|
||||||
url = 'http://webservice.fanart.tv/v3/movies/%s?api_key=%s' \
|
url = 'http://webservice.fanart.tv/v3/movies/%s?api_key=%s' \
|
||||||
% (media_id, api_key)
|
% (media_id, api_key)
|
||||||
elif typus == 'tv':
|
elif typus == 'tv':
|
||||||
|
@ -1009,24 +984,20 @@ class API(object):
|
||||||
% (media_id, api_key)
|
% (media_id, api_key)
|
||||||
else:
|
else:
|
||||||
# Not supported artwork
|
# Not supported artwork
|
||||||
return allartworks
|
return artworks
|
||||||
data = DU().downloadUrl(url,
|
data = DU().downloadUrl(url, authenticate=False, timeout=15)
|
||||||
authenticate=False,
|
|
||||||
timeout=15)
|
|
||||||
try:
|
try:
|
||||||
data.get('test')
|
data.get('test')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
LOG.error('Could not download data from FanartTV')
|
LOG.error('Could not download data from FanartTV')
|
||||||
return allartworks
|
return artworks
|
||||||
|
|
||||||
fanart_tv_types = list(FANART_TV_TYPES)
|
fanart_tv_types = list(v.FANART_TV_TO_KODI_TYPE)
|
||||||
|
|
||||||
if typus == "artist":
|
if typus == v.PLEX_TYPE_ARTIST:
|
||||||
fanart_tv_types.append(("thumb", "folder"))
|
fanart_tv_types.append(("thumb", "folder"))
|
||||||
else:
|
else:
|
||||||
fanart_tv_types.append(("thumb", "Thumb"))
|
fanart_tv_types.append(("thumb", "thumb"))
|
||||||
if set_info:
|
|
||||||
fanart_tv_types.append(("poster", "Primary"))
|
|
||||||
|
|
||||||
prefixes = (
|
prefixes = (
|
||||||
"hd" + typus,
|
"hd" + typus,
|
||||||
|
@ -1034,32 +1005,31 @@ class API(object):
|
||||||
typus,
|
typus,
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
for fanarttype in fanart_tv_types:
|
for fanart_tv_type, kodi_type in fanart_tv_types:
|
||||||
# Skip the ones we already have
|
# Skip the ones we already have
|
||||||
if allartworks.get(fanarttype[1]):
|
if kodi_type in artworks:
|
||||||
continue
|
continue
|
||||||
for prefix in prefixes:
|
for prefix in prefixes:
|
||||||
fanarttvimage = prefix + fanarttype[0]
|
fanarttvimage = prefix + fanart_tv_type
|
||||||
if fanarttvimage not in data:
|
if fanarttvimage not in data:
|
||||||
continue
|
continue
|
||||||
# select image in preferred language
|
# select image in preferred language
|
||||||
for entry in data[fanarttvimage]:
|
for entry in data[fanarttvimage]:
|
||||||
if entry.get("lang") == v.KODILANGUAGE:
|
if entry.get("lang") == v.KODILANGUAGE:
|
||||||
allartworks[fanarttype[1]] = \
|
artworks[kodi_type] = \
|
||||||
entry.get("url", "").replace(' ', '%20')
|
entry.get("url", "").replace(' ', '%20')
|
||||||
break
|
break
|
||||||
# just grab the first english OR undefinded one as fallback
|
# just grab the first english OR undefinded one as fallback
|
||||||
# (so we're actually grabbing the more popular one)
|
# (so we're actually grabbing the more popular one)
|
||||||
if not allartworks.get(fanarttype[1]):
|
if kodi_type not in artworks:
|
||||||
for entry in data[fanarttvimage]:
|
for entry in data[fanarttvimage]:
|
||||||
if entry.get("lang") in ("en", "00"):
|
if entry.get("lang") in ("en", "00"):
|
||||||
allartworks[fanarttype[1]] = \
|
artworks[kodi_type] = \
|
||||||
entry.get("url", "").replace(' ', '%20')
|
entry.get("url", "").replace(' ', '%20')
|
||||||
break
|
break
|
||||||
|
|
||||||
# grab extrafanarts in list
|
# grab extrafanarts in list
|
||||||
maxfanarts = 10
|
fanartcount = 1 if 'fanart' in artworks else ''
|
||||||
fanartcount = 0
|
|
||||||
for prefix in prefixes:
|
for prefix in prefixes:
|
||||||
fanarttvimage = prefix + 'background'
|
fanarttvimage = prefix + 'background'
|
||||||
if fanarttvimage not in data:
|
if fanarttvimage not in data:
|
||||||
|
@ -1067,60 +1037,38 @@ class API(object):
|
||||||
for entry in data[fanarttvimage]:
|
for entry in data[fanarttvimage]:
|
||||||
if entry.get("url") is None:
|
if entry.get("url") is None:
|
||||||
continue
|
continue
|
||||||
if fanartcount > maxfanarts:
|
artworks['fanart%s' % fanartcount] = \
|
||||||
break
|
entry['url'].replace(' ', '%20')
|
||||||
allartworks['Backdrop'].append(
|
try:
|
||||||
entry['url'].replace(' ', '%20'))
|
|
||||||
fanartcount += 1
|
fanartcount += 1
|
||||||
return allartworks
|
except TypeError:
|
||||||
|
fanartcount = 1
|
||||||
|
if fanartcount >= v.MAX_BACKGROUND_COUNT:
|
||||||
|
break
|
||||||
|
return artworks
|
||||||
|
|
||||||
def set_artwork(self):
|
def set_artwork(self):
|
||||||
"""
|
"""
|
||||||
Gets the URLs to the Plex artwork, or empty string if not found.
|
Gets the URLs to the Plex artwork, or empty string if not found.
|
||||||
parentInfo=True will check for parent's artwork if None is found
|
|
||||||
|
|
||||||
Only call on movies
|
Only call on movies
|
||||||
|
|
||||||
Output:
|
|
||||||
{
|
|
||||||
'Primary'
|
|
||||||
'Art'
|
|
||||||
'Banner'
|
|
||||||
'Logo'
|
|
||||||
'Thumb'
|
|
||||||
'Disc'
|
|
||||||
'Backdrop' : LIST with the first entry xml key "art"
|
|
||||||
}
|
|
||||||
"""
|
"""
|
||||||
allartworks = {
|
artworks = {}
|
||||||
'Primary': "",
|
|
||||||
'Art': "",
|
|
||||||
'Banner': "",
|
|
||||||
'Logo': "",
|
|
||||||
'Thumb': "",
|
|
||||||
'Disc': "",
|
|
||||||
'Backdrop': []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Plex does not get much artwork - go ahead and get the rest from
|
# Plex does not get much artwork - go ahead and get the rest from
|
||||||
# fanart tv only for movie or tv show
|
# fanart tv only for movie or tv show
|
||||||
external_id = self.retrieve_external_item_id(collection=True)
|
external_id = self.retrieve_external_item_id(collection=True)
|
||||||
if external_id is not None:
|
if external_id is not None:
|
||||||
try:
|
|
||||||
external_id, poster, background = external_id
|
external_id, poster, background = external_id
|
||||||
except TypeError:
|
|
||||||
poster, background = None, None
|
|
||||||
if poster is not None:
|
if poster is not None:
|
||||||
allartworks['Primary'] = poster
|
artworks['poster'] = poster
|
||||||
if background is not None:
|
if background is not None:
|
||||||
allartworks['Backdrop'].append(background)
|
artworks['fanart'] = background
|
||||||
allartworks = self.lookup_fanart_tv(external_id,
|
artworks = self.lookup_fanart_tv(external_id,
|
||||||
allartworks,
|
artworks,
|
||||||
set_info=True)
|
set_info=True)
|
||||||
else:
|
else:
|
||||||
LOG.info('Did not find a set/collection ID on TheMovieDB using %s.'
|
LOG.info('Did not find a set/collection ID on TheMovieDB using %s.'
|
||||||
' Artwork will be missing.', self.titles()[0])
|
' Artwork will be missing.', self.titles()[0])
|
||||||
return allartworks
|
return artworks
|
||||||
|
|
||||||
def should_stream(self):
|
def should_stream(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -21,9 +21,8 @@ LOG = getLogger("PLEX." + __name__)
|
||||||
|
|
||||||
# Disable annoying requests warnings
|
# Disable annoying requests warnings
|
||||||
requests.packages.urllib3.disable_warnings()
|
requests.packages.urllib3.disable_warnings()
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
ARTWORK_QUEUE = Queue()
|
ARTWORK_QUEUE = Queue()
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
def double_urlencode(text):
|
def double_urlencode(text):
|
||||||
|
@ -88,26 +87,25 @@ class Image_Cache_Thread(Thread):
|
||||||
# Server thinks its a DOS attack, ('error 10053')
|
# Server thinks its a DOS attack, ('error 10053')
|
||||||
# Wait before trying again
|
# Wait before trying again
|
||||||
if sleeptime > 5:
|
if sleeptime > 5:
|
||||||
LOG.error('Repeatedly got ConnectionError for url %s'
|
LOG.error('Repeatedly got ConnectionError for url %s',
|
||||||
% double_urldecode(url))
|
double_urldecode(url))
|
||||||
break
|
break
|
||||||
LOG.debug('Were trying too hard to download art, server '
|
LOG.debug('Were trying too hard to download art, server '
|
||||||
'over-loaded. Sleep %s seconds before trying '
|
'over-loaded. Sleep %s seconds before trying '
|
||||||
'again to download %s'
|
'again to download %s',
|
||||||
% (2**sleeptime, double_urldecode(url)))
|
2**sleeptime, double_urldecode(url))
|
||||||
sleep((2**sleeptime)*1000)
|
sleep((2**sleeptime)*1000)
|
||||||
sleeptime += 1
|
sleeptime += 1
|
||||||
continue
|
continue
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.error('Unknown exception for url %s: %s'
|
LOG.error('Unknown exception for url %s: %s'.
|
||||||
% (double_urldecode(url), e))
|
double_urldecode(url), e)
|
||||||
import traceback
|
import traceback
|
||||||
LOG.error("Traceback:\n%s" % traceback.format_exc())
|
LOG.error("Traceback:\n%s", traceback.format_exc())
|
||||||
break
|
break
|
||||||
# We did not even get a timeout
|
# We did not even get a timeout
|
||||||
break
|
break
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
LOG.debug('Cached art: %s' % double_urldecode(url))
|
|
||||||
# Sleep for a bit to reduce CPU strain
|
# Sleep for a bit to reduce CPU strain
|
||||||
sleep(sleep_between)
|
sleep(sleep_between)
|
||||||
LOG.info("---===### Stopped Image_Cache_Thread ###===---")
|
LOG.info("---===### Stopped Image_Cache_Thread ###===---")
|
||||||
|
@ -135,7 +133,7 @@ class Artwork():
|
||||||
path = try_decode(translatePath("special://thumbnails/"))
|
path = try_decode(translatePath("special://thumbnails/"))
|
||||||
if exists_dir(path):
|
if exists_dir(path):
|
||||||
rmtree(path, ignore_errors=True)
|
rmtree(path, ignore_errors=True)
|
||||||
self.restoreCacheDirectories()
|
self.restore_cache_directories()
|
||||||
|
|
||||||
# remove all existing data from texture DB
|
# remove all existing data from texture DB
|
||||||
connection = kodi_sql('texture')
|
connection = kodi_sql('texture')
|
||||||
|
@ -158,167 +156,91 @@ class Artwork():
|
||||||
cursor.execute(query, ('actor', ))
|
cursor.execute(query, ('actor', ))
|
||||||
result = cursor.fetchall()
|
result = cursor.fetchall()
|
||||||
total = len(result)
|
total = len(result)
|
||||||
LOG.info("Image cache sync about to process %s video images" % total)
|
LOG.info("Image cache sync about to process %s video images", total)
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
for url in result:
|
for url in result:
|
||||||
self.cacheTexture(url[0])
|
self.cache_texture(url[0])
|
||||||
# Cache all entries in music DB
|
# Cache all entries in music DB
|
||||||
connection = kodi_sql('music')
|
connection = kodi_sql('music')
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("SELECT url FROM art")
|
cursor.execute("SELECT url FROM art")
|
||||||
result = cursor.fetchall()
|
result = cursor.fetchall()
|
||||||
total = len(result)
|
total = len(result)
|
||||||
LOG.info("Image cache sync about to process %s music images" % total)
|
LOG.info("Image cache sync about to process %s music images", total)
|
||||||
connection.close()
|
connection.close()
|
||||||
for url in result:
|
for url in result:
|
||||||
self.cacheTexture(url[0])
|
self.cache_texture(url[0])
|
||||||
|
|
||||||
def cacheTexture(self, url):
|
def cache_texture(self, url):
|
||||||
# Cache a single image url to the texture cache
|
'''
|
||||||
|
Cache a single image url to the texture cache
|
||||||
|
'''
|
||||||
if url and self.enableTextureCache:
|
if url and self.enableTextureCache:
|
||||||
self.queue.put(double_urlencode(try_encode(url)))
|
self.queue.put(double_urlencode(try_encode(url)))
|
||||||
|
|
||||||
def addArtwork(self, artwork, kodiId, mediaType, cursor):
|
def modify_artwork(self, artworks, kodi_id, kodi_type, cursor):
|
||||||
# Kodi conversion table
|
"""
|
||||||
kodiart = {
|
Pass in an artworks dict (see PlexAPI) to set an items artwork.
|
||||||
'Primary': ["thumb", "poster"],
|
"""
|
||||||
'Banner': "banner",
|
for kodi_art, url in artworks.iteritems():
|
||||||
'Logo': "clearlogo",
|
self.modify_art(url, kodi_id, kodi_type, kodi_art, cursor)
|
||||||
'Art': "clearart",
|
|
||||||
'Thumb': "landscape",
|
|
||||||
'Disc': "discart",
|
|
||||||
'Backdrop': "fanart",
|
|
||||||
'BoxRear': "poster"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Artwork is a dictionary
|
def modify_art(self, url, kodi_id, kodi_type, kodi_art, cursor):
|
||||||
for art in artwork:
|
"""
|
||||||
if art == "Backdrop":
|
Adds or modifies the artwork of kind kodi_art (e.g. 'poster') in the
|
||||||
# Backdrop entry is a list
|
Kodi art table for item kodi_id/kodi_type. Will also cache everything
|
||||||
# Process extra fanart for artwork downloader (fanart, fanart1,
|
except actor portraits.
|
||||||
# fanart2...)
|
"""
|
||||||
backdrops = artwork[art]
|
query = '''
|
||||||
backdropsNumber = len(backdrops)
|
SELECT url FROM art
|
||||||
|
WHERE media_id = ? AND media_type = ? AND type = ?
|
||||||
query = ' '.join((
|
LIMIT 1
|
||||||
"SELECT url",
|
'''
|
||||||
"FROM art",
|
cursor.execute(query, (kodi_id, kodi_type, kodi_art,))
|
||||||
"WHERE media_id = ?",
|
|
||||||
"AND media_type = ?",
|
|
||||||
"AND type LIKE ?"
|
|
||||||
))
|
|
||||||
cursor.execute(query, (kodiId, mediaType, "fanart%",))
|
|
||||||
rows = cursor.fetchall()
|
|
||||||
|
|
||||||
if len(rows) > backdropsNumber:
|
|
||||||
# More backdrops in database. Delete extra fanart.
|
|
||||||
query = ' '.join((
|
|
||||||
"DELETE FROM art",
|
|
||||||
"WHERE media_id = ?",
|
|
||||||
"AND media_type = ?",
|
|
||||||
"AND type LIKE ?"
|
|
||||||
))
|
|
||||||
cursor.execute(query, (kodiId, mediaType, "fanart_",))
|
|
||||||
|
|
||||||
# Process backdrops and extra fanart
|
|
||||||
index = ""
|
|
||||||
for backdrop in backdrops:
|
|
||||||
self.addOrUpdateArt(
|
|
||||||
imageUrl=backdrop,
|
|
||||||
kodiId=kodiId,
|
|
||||||
mediaType=mediaType,
|
|
||||||
imageType="%s%s" % ("fanart", index),
|
|
||||||
cursor=cursor)
|
|
||||||
|
|
||||||
if backdropsNumber > 1:
|
|
||||||
try: # Will only fail on the first try, str to int.
|
|
||||||
index += 1
|
|
||||||
except TypeError:
|
|
||||||
index = 1
|
|
||||||
|
|
||||||
elif art == "Primary":
|
|
||||||
# Primary art is processed as thumb and poster for Kodi.
|
|
||||||
for artType in kodiart[art]:
|
|
||||||
self.addOrUpdateArt(
|
|
||||||
imageUrl=artwork[art],
|
|
||||||
kodiId=kodiId,
|
|
||||||
mediaType=mediaType,
|
|
||||||
imageType=artType,
|
|
||||||
cursor=cursor)
|
|
||||||
|
|
||||||
elif kodiart.get(art):
|
|
||||||
# Process the rest artwork type that Kodi can use
|
|
||||||
self.addOrUpdateArt(
|
|
||||||
imageUrl=artwork[art],
|
|
||||||
kodiId=kodiId,
|
|
||||||
mediaType=mediaType,
|
|
||||||
imageType=kodiart[art],
|
|
||||||
cursor=cursor)
|
|
||||||
|
|
||||||
def addOrUpdateArt(self, imageUrl, kodiId, mediaType, imageType, cursor):
|
|
||||||
if not imageUrl:
|
|
||||||
# Possible that the imageurl is an empty string
|
|
||||||
return
|
|
||||||
|
|
||||||
query = ' '.join((
|
|
||||||
"SELECT url",
|
|
||||||
"FROM art",
|
|
||||||
"WHERE media_id = ?",
|
|
||||||
"AND media_type = ?",
|
|
||||||
"AND type = ?"
|
|
||||||
))
|
|
||||||
cursor.execute(query, (kodiId, mediaType, imageType,))
|
|
||||||
try:
|
try:
|
||||||
# Update the artwork
|
# Update the artwork
|
||||||
url = cursor.fetchone()[0]
|
old_url = cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Add the artwork
|
# Add the artwork
|
||||||
LOG.debug("Adding Art Link for kodiId: %s (%s)"
|
LOG.debug('Adding Art Link for %s kodi_id %s, kodi_type %s: %s',
|
||||||
% (kodiId, imageUrl))
|
kodi_art, kodi_id, kodi_type, url)
|
||||||
query = (
|
query = '''
|
||||||
'''
|
|
||||||
INSERT INTO art(media_id, media_type, type, url)
|
INSERT INTO art(media_id, media_type, type, url)
|
||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
cursor.execute(query, (kodi_id, kodi_type, kodi_art, url))
|
||||||
cursor.execute(query, (kodiId, mediaType, imageType, imageUrl))
|
|
||||||
else:
|
else:
|
||||||
if url == imageUrl:
|
if url == old_url:
|
||||||
# Only cache artwork if it changed
|
# Only cache artwork if it changed
|
||||||
return
|
return
|
||||||
# Only for the main backdrop, poster
|
self.delete_cached_artwork(old_url)
|
||||||
if (window('plex_initialScan') != "true" and
|
LOG.debug("Updating Art url for %s kodi_id %s, kodi_type %s to %s",
|
||||||
imageType in ("fanart", "poster")):
|
kodi_art, kodi_id, kodi_type, url)
|
||||||
# Delete current entry before updating with the new one
|
query = '''
|
||||||
self.deleteCachedArtwork(url)
|
UPDATE art SET url = ?
|
||||||
LOG.debug("Updating Art url for %s kodiId %s %s -> (%s)"
|
WHERE media_id = ? AND media_type = ? AND type = ?
|
||||||
% (imageType, kodiId, url, imageUrl))
|
'''
|
||||||
query = ' '.join((
|
cursor.execute(query, (url, kodi_id, kodi_type, kodi_art))
|
||||||
"UPDATE art",
|
|
||||||
"SET url = ?",
|
|
||||||
"WHERE media_id = ?",
|
|
||||||
"AND media_type = ?",
|
|
||||||
"AND type = ?"
|
|
||||||
))
|
|
||||||
cursor.execute(query, (imageUrl, kodiId, mediaType, imageType))
|
|
||||||
|
|
||||||
# Cache fanart and poster in Kodi texture cache
|
# Cache fanart and poster in Kodi texture cache
|
||||||
if mediaType != 'actor':
|
if kodi_type != 'actor':
|
||||||
self.cacheTexture(imageUrl)
|
self.cache_texture(url)
|
||||||
|
|
||||||
def deleteArtwork(self, kodiId, mediaType, cursor):
|
def delete_artwork(self, kodiId, mediaType, cursor):
|
||||||
query = 'SELECT url FROM art WHERE media_id = ? AND media_type = ?'
|
query = 'SELECT url FROM art WHERE media_id = ? AND media_type = ?'
|
||||||
cursor.execute(query, (kodiId, mediaType,))
|
cursor.execute(query, (kodiId, mediaType,))
|
||||||
for row in cursor.fetchall():
|
for row in cursor.fetchall():
|
||||||
self.deleteCachedArtwork(row[0])
|
self.delete_cached_artwork(row[0])
|
||||||
|
|
||||||
def deleteCachedArtwork(self, url):
|
@staticmethod
|
||||||
# Only necessary to remove and apply a new backdrop or poster
|
def delete_cached_artwork(url):
|
||||||
|
"""
|
||||||
|
Deleted the cached artwork with path url (if it exists)
|
||||||
|
"""
|
||||||
connection = kodi_sql('texture')
|
connection = kodi_sql('texture')
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
try:
|
try:
|
||||||
cursor.execute("SELECT cachedurl FROM texture WHERE url = ?",
|
cursor.execute("SELECT cachedurl FROM texture WHERE url=? LIMIT 1",
|
||||||
(url,))
|
(url,))
|
||||||
cachedurl = cursor.fetchone()[0]
|
cachedurl = cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -327,7 +249,7 @@ class Artwork():
|
||||||
else:
|
else:
|
||||||
# Delete thumbnail as well as the entry
|
# Delete thumbnail as well as the entry
|
||||||
path = translatePath("special://thumbnails/%s" % cachedurl)
|
path = translatePath("special://thumbnails/%s" % cachedurl)
|
||||||
LOG.debug("Deleting cached thumbnail: %s" % path)
|
LOG.debug("Deleting cached thumbnail: %s", path)
|
||||||
if exists(path):
|
if exists(path):
|
||||||
rmtree(try_decode(path), ignore_errors=True)
|
rmtree(try_decode(path), ignore_errors=True)
|
||||||
cursor.execute("DELETE FROM texture WHERE url = ?", (url,))
|
cursor.execute("DELETE FROM texture WHERE url = ?", (url,))
|
||||||
|
@ -336,8 +258,11 @@ class Artwork():
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def restoreCacheDirectories():
|
def restore_cache_directories():
|
||||||
LOG.info("Restoring cache directories...")
|
LOG.info("Restoring cache directories...")
|
||||||
paths = ("","0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","Video","plex")
|
paths = ("", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
for p in paths:
|
"a", "b", "c", "d", "e", "f",
|
||||||
makedirs(try_decode(translatePath("special://thumbnails/%s" % p)))
|
"Video", "plex")
|
||||||
|
for path in paths:
|
||||||
|
makedirs(try_decode(translatePath("special://thumbnails/%s"
|
||||||
|
% path)))
|
||||||
|
|
|
@ -82,11 +82,11 @@ class Items(object):
|
||||||
allartworks = None
|
allartworks = None
|
||||||
else:
|
else:
|
||||||
with kodidb.GetKodiDB('video') as kodi_db:
|
with kodidb.GetKodiDB('video') as kodi_db:
|
||||||
allartworks = kodi_db.existingArt(kodi_id, kodi_type)
|
allartworks = kodi_db.get_art(kodi_id, kodi_type)
|
||||||
# Check if we even need to get additional art
|
# Check if we even need to get additional art
|
||||||
needsupdate = False
|
needsupdate = False
|
||||||
for key, value in allartworks.iteritems():
|
for key in v.ALL_KODI_ARTWORK:
|
||||||
if not value and not key == 'BoxRear':
|
if key not in allartworks:
|
||||||
needsupdate = True
|
needsupdate = True
|
||||||
break
|
break
|
||||||
if needsupdate is False:
|
if needsupdate is False:
|
||||||
|
@ -107,7 +107,7 @@ class Items(object):
|
||||||
api = API(xml[0])
|
api = API(xml[0])
|
||||||
if allartworks is None:
|
if allartworks is None:
|
||||||
allartworks = api.artwork()
|
allartworks = api.artwork()
|
||||||
self.artwork.addArtwork(api.fanart_artwork(allartworks),
|
self.artwork.modify_artwork(api.fanart_artwork(allartworks),
|
||||||
kodi_id,
|
kodi_id,
|
||||||
kodi_type,
|
kodi_type,
|
||||||
self.kodicursor)
|
self.kodicursor)
|
||||||
|
@ -116,7 +116,7 @@ class Items(object):
|
||||||
for setname in api.collection_list():
|
for setname in api.collection_list():
|
||||||
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)
|
||||||
self.artwork.addArtwork(api.set_artwork(),
|
self.artwork.modify_artwork(api.set_artwork(),
|
||||||
setid,
|
setid,
|
||||||
v.KODI_TYPE_SET,
|
v.KODI_TYPE_SET,
|
||||||
self.kodicursor)
|
self.kodicursor)
|
||||||
|
@ -445,7 +445,10 @@ class Movies(Items):
|
||||||
# Process genres
|
# Process genres
|
||||||
self.kodi_db.modify_genres(movieid, v.KODI_TYPE_MOVIE, genres)
|
self.kodi_db.modify_genres(movieid, v.KODI_TYPE_MOVIE, genres)
|
||||||
# Process artwork
|
# Process artwork
|
||||||
artwork.addArtwork(api.artwork(), movieid, "movie", kodicursor)
|
artwork.modify_artwork(api.artwork(),
|
||||||
|
movieid,
|
||||||
|
v.KODI_TYPE_MOVIE,
|
||||||
|
kodicursor)
|
||||||
# Process stream details
|
# Process stream details
|
||||||
self.kodi_db.modify_streams(fileid, api.mediastreams(), runtime)
|
self.kodi_db.modify_streams(fileid, api.mediastreams(), runtime)
|
||||||
# Process studios
|
# Process studios
|
||||||
|
@ -482,7 +485,7 @@ class Movies(Items):
|
||||||
# Remove the plex reference
|
# Remove the plex reference
|
||||||
plex_db.removeItem(itemid)
|
plex_db.removeItem(itemid)
|
||||||
# Remove artwork
|
# Remove artwork
|
||||||
artwork.deleteArtwork(kodi_id, kodi_type, kodicursor)
|
artwork.delete_artwork(kodi_id, kodi_type, kodicursor)
|
||||||
|
|
||||||
if kodi_type == v.KODI_TYPE_MOVIE:
|
if kodi_type == v.KODI_TYPE_MOVIE:
|
||||||
set_id = self.kodi_db.get_set_id(kodi_id)
|
set_id = self.kodi_db.get_set_id(kodi_id)
|
||||||
|
@ -743,7 +746,10 @@ class TVShows(Items):
|
||||||
|
|
||||||
self.kodi_db.modify_people(showid, v.KODI_TYPE_SHOW, api.people_list())
|
self.kodi_db.modify_people(showid, v.KODI_TYPE_SHOW, api.people_list())
|
||||||
self.kodi_db.modify_genres(showid, v.KODI_TYPE_SHOW, genres)
|
self.kodi_db.modify_genres(showid, v.KODI_TYPE_SHOW, genres)
|
||||||
artwork.addArtwork(api.artwork(), showid, v.KODI_TYPE_SHOW, kodicursor)
|
artwork.modify_artwork(api.artwork(),
|
||||||
|
showid,
|
||||||
|
v.KODI_TYPE_SHOW,
|
||||||
|
kodicursor)
|
||||||
# Process studios
|
# Process studios
|
||||||
self.kodi_db.modify_studios(showid, v.KODI_TYPE_SHOW, studios)
|
self.kodi_db.modify_studios(showid, v.KODI_TYPE_SHOW, studios)
|
||||||
# Process tags: view, PMS collection tags
|
# Process tags: view, PMS collection tags
|
||||||
|
@ -784,7 +790,10 @@ class TVShows(Items):
|
||||||
|
|
||||||
# Process artwork
|
# Process artwork
|
||||||
allartworks = api.artwork()
|
allartworks = api.artwork()
|
||||||
artwork.addArtwork(allartworks, seasonid, "season", kodicursor)
|
artwork.modify_artwork(allartworks,
|
||||||
|
seasonid,
|
||||||
|
v.KODI_TYPE_SEASON,
|
||||||
|
kodicursor)
|
||||||
|
|
||||||
if update_item:
|
if update_item:
|
||||||
# Update a reference: checksum in plex table
|
# Update a reference: checksum in plex table
|
||||||
|
@ -1095,8 +1104,8 @@ class TVShows(Items):
|
||||||
if poster:
|
if poster:
|
||||||
poster = api.attach_plex_token_to_url(
|
poster = api.attach_plex_token_to_url(
|
||||||
"%s%s" % (self.server, poster))
|
"%s%s" % (self.server, poster))
|
||||||
artwork.addOrUpdateArt(
|
artwork.modify_art(
|
||||||
poster, episodeid, "episode", "thumb", kodicursor)
|
poster, episodeid, v.KODI_TYPE_EPISODE, "thumb", kodicursor)
|
||||||
|
|
||||||
# Process stream details
|
# Process stream details
|
||||||
streams = api.mediastreams()
|
streams = api.mediastreams()
|
||||||
|
@ -1223,7 +1232,7 @@ class TVShows(Items):
|
||||||
self.kodi_db.modify_genres(kodi_id, v.KODI_TYPE_SHOW)
|
self.kodi_db.modify_genres(kodi_id, v.KODI_TYPE_SHOW)
|
||||||
self.kodi_db.modify_studios(kodi_id, v.KODI_TYPE_SHOW)
|
self.kodi_db.modify_studios(kodi_id, v.KODI_TYPE_SHOW)
|
||||||
self.kodi_db.modify_tags(kodi_id, v.KODI_TYPE_SHOW)
|
self.kodi_db.modify_tags(kodi_id, v.KODI_TYPE_SHOW)
|
||||||
self.artwork.deleteArtwork(kodi_id, v.KODI_TYPE_SHOW, kodicursor)
|
self.artwork.delete_artwork(kodi_id, v.KODI_TYPE_SHOW, kodicursor)
|
||||||
kodicursor.execute("DELETE FROM tvshow WHERE idShow = ?", (kodi_id,))
|
kodicursor.execute("DELETE FROM tvshow WHERE idShow = ?", (kodi_id,))
|
||||||
if v.KODIVERSION >= 17:
|
if v.KODIVERSION >= 17:
|
||||||
self.kodi_db.remove_uniqueid(kodi_id, v.KODI_TYPE_SHOW)
|
self.kodi_db.remove_uniqueid(kodi_id, v.KODI_TYPE_SHOW)
|
||||||
|
@ -1235,7 +1244,7 @@ class TVShows(Items):
|
||||||
Remove a season, and only a season, not the show or episodes
|
Remove a season, and only a season, not the show or episodes
|
||||||
"""
|
"""
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
self.artwork.deleteArtwork(kodi_id, "season", kodicursor)
|
self.artwork.delete_artwork(kodi_id, "season", kodicursor)
|
||||||
kodicursor.execute("DELETE FROM seasons WHERE idSeason = ?",
|
kodicursor.execute("DELETE FROM seasons WHERE idSeason = ?",
|
||||||
(kodi_id,))
|
(kodi_id,))
|
||||||
LOG.info("Removed season: %s.", kodi_id)
|
LOG.info("Removed season: %s.", kodi_id)
|
||||||
|
@ -1248,7 +1257,7 @@ class TVShows(Items):
|
||||||
self.kodi_db.modify_people(kodi_id, v.KODI_TYPE_EPISODE)
|
self.kodi_db.modify_people(kodi_id, v.KODI_TYPE_EPISODE)
|
||||||
self.kodi_db.modify_streams(file_id)
|
self.kodi_db.modify_streams(file_id)
|
||||||
self.kodi_db.delete_playstate(file_id)
|
self.kodi_db.delete_playstate(file_id)
|
||||||
self.artwork.deleteArtwork(kodi_id, "episode", kodicursor)
|
self.artwork.delete_artwork(kodi_id, "episode", kodicursor)
|
||||||
kodicursor.execute("DELETE FROM episode WHERE idEpisode = ?",
|
kodicursor.execute("DELETE FROM episode WHERE idEpisode = ?",
|
||||||
(kodi_id,))
|
(kodi_id,))
|
||||||
kodicursor.execute("DELETE FROM files WHERE idFile = ?", (file_id,))
|
kodicursor.execute("DELETE FROM files WHERE idFile = ?", (file_id,))
|
||||||
|
@ -1359,7 +1368,10 @@ class Music(Items):
|
||||||
dateadded, artistid))
|
dateadded, artistid))
|
||||||
|
|
||||||
# Update artwork
|
# Update artwork
|
||||||
artwork.addArtwork(artworks, artistid, v.KODI_TYPE_ARTIST, kodicursor)
|
artwork.modify_artwork(artworks,
|
||||||
|
artistid,
|
||||||
|
v.KODI_TYPE_ARTIST,
|
||||||
|
kodicursor)
|
||||||
|
|
||||||
@catch_exceptions(warnuser=True)
|
@catch_exceptions(warnuser=True)
|
||||||
def add_updateAlbum(self, item, viewtag=None, viewid=None, children=None,
|
def add_updateAlbum(self, item, viewtag=None, viewid=None, children=None,
|
||||||
|
@ -1553,7 +1565,7 @@ class Music(Items):
|
||||||
# Add genres
|
# Add genres
|
||||||
self.kodi_db.addMusicGenres(albumid, self.genres, v.KODI_TYPE_ALBUM)
|
self.kodi_db.addMusicGenres(albumid, self.genres, v.KODI_TYPE_ALBUM)
|
||||||
# Update artwork
|
# Update artwork
|
||||||
artwork.addArtwork(artworks, albumid, v.KODI_TYPE_ALBUM, kodicursor)
|
artwork.modify_artwork(artworks, albumid, v.KODI_TYPE_ALBUM, kodicursor)
|
||||||
# Add all children - all tracks
|
# Add all children - all tracks
|
||||||
if scan_children:
|
if scan_children:
|
||||||
for child in children:
|
for child in children:
|
||||||
|
@ -1847,10 +1859,11 @@ class Music(Items):
|
||||||
# Add genres
|
# Add genres
|
||||||
if genres:
|
if genres:
|
||||||
self.kodi_db.addMusicGenres(songid, genres, v.KODI_TYPE_SONG)
|
self.kodi_db.addMusicGenres(songid, genres, v.KODI_TYPE_SONG)
|
||||||
artwork.addArtwork(api.artwork(), songid, v.KODI_TYPE_SONG, kodicursor)
|
artworks = api.artwork()
|
||||||
|
artwork.modify_artwork(artworks, songid, v.KODI_TYPE_SONG, kodicursor)
|
||||||
if item.get('parentKey') is None:
|
if item.get('parentKey') is None:
|
||||||
# Update album artwork
|
# Update album artwork
|
||||||
artwork.addArtwork(allart, albumid, v.KODI_TYPE_ALBUM, kodicursor)
|
artwork.modify_artwork(artworks, albumid, v.KODI_TYPE_ALBUM, kodicursor)
|
||||||
|
|
||||||
def remove(self, itemid):
|
def remove(self, itemid):
|
||||||
"""
|
"""
|
||||||
|
@ -1937,7 +1950,7 @@ class Music(Items):
|
||||||
"""
|
"""
|
||||||
Remove song, and only the song
|
Remove song, and only the song
|
||||||
"""
|
"""
|
||||||
self.artwork.deleteArtwork(kodiid, v.KODI_TYPE_SONG, self.kodicursor)
|
self.artwork.delete_artwork(kodiid, v.KODI_TYPE_SONG, self.kodicursor)
|
||||||
self.kodicursor.execute("DELETE FROM song WHERE idSong = ?",
|
self.kodicursor.execute("DELETE FROM song WHERE idSong = ?",
|
||||||
(kodiid,))
|
(kodiid,))
|
||||||
|
|
||||||
|
@ -1945,7 +1958,7 @@ class Music(Items):
|
||||||
"""
|
"""
|
||||||
Remove an album, and only the album
|
Remove an album, and only the album
|
||||||
"""
|
"""
|
||||||
self.artwork.deleteArtwork(kodiid, v.KODI_TYPE_ALBUM, self.kodicursor)
|
self.artwork.delete_artwork(kodiid, v.KODI_TYPE_ALBUM, self.kodicursor)
|
||||||
self.kodicursor.execute("DELETE FROM album WHERE idAlbum = ?",
|
self.kodicursor.execute("DELETE FROM album WHERE idAlbum = ?",
|
||||||
(kodiid,))
|
(kodiid,))
|
||||||
|
|
||||||
|
@ -1953,7 +1966,7 @@ class Music(Items):
|
||||||
"""
|
"""
|
||||||
Remove an artist, and only the artist
|
Remove an artist, and only the artist
|
||||||
"""
|
"""
|
||||||
self.artwork.deleteArtwork(kodiid,
|
self.artwork.delete_artwork(kodiid,
|
||||||
v.KODI_TYPE_ARTIST,
|
v.KODI_TYPE_ARTIST,
|
||||||
self.kodicursor)
|
self.kodicursor)
|
||||||
self.kodicursor.execute("DELETE FROM artist WHERE idArtist = ?",
|
self.kodicursor.execute("DELETE FROM artist WHERE idArtist = ?",
|
||||||
|
|
|
@ -406,7 +406,7 @@ class KodiDBMethods(object):
|
||||||
self.cursor.execute(query_actor_delete, (person[0],))
|
self.cursor.execute(query_actor_delete, (person[0],))
|
||||||
if kind == 'actor':
|
if kind == 'actor':
|
||||||
# Delete any associated artwork
|
# Delete any associated artwork
|
||||||
self.artwork.deleteArtwork(person[0], 'actor', self.cursor)
|
self.artwork.delete_artwork(person[0], 'actor', self.cursor)
|
||||||
# Save new people to Kodi DB by iterating over the remaining entries
|
# Save new people to Kodi DB by iterating over the remaining entries
|
||||||
if kind == 'actor':
|
if kind == 'actor':
|
||||||
query = 'INSERT INTO actor_link VALUES (?, ?, ?, ?, ?)'
|
query = 'INSERT INTO actor_link VALUES (?, ?, ?, ?, ?)'
|
||||||
|
@ -454,10 +454,10 @@ class KodiDBMethods(object):
|
||||||
'VALUES (?, ?)',
|
'VALUES (?, ?)',
|
||||||
(actor_id, name))
|
(actor_id, name))
|
||||||
if art_url:
|
if art_url:
|
||||||
self.artwork.addOrUpdateArt(art_url,
|
self.artwork.modify_art(art_url,
|
||||||
actor_id,
|
actor_id,
|
||||||
'actor',
|
'actor',
|
||||||
"thumb",
|
'thumb',
|
||||||
self.cursor)
|
self.cursor)
|
||||||
return actor_id
|
return actor_id
|
||||||
|
|
||||||
|
@ -468,11 +468,11 @@ class KodiDBMethods(object):
|
||||||
'thumb'
|
'thumb'
|
||||||
'poster'
|
'poster'
|
||||||
'banner'
|
'banner'
|
||||||
'fanart'
|
|
||||||
'clearart'
|
'clearart'
|
||||||
'clearlogo'
|
'clearlogo'
|
||||||
'landscape'
|
'landscape'
|
||||||
'icon'
|
'icon'
|
||||||
|
'fanart' and also potentially more fanart 'fanart1', 2, 3, ...
|
||||||
}
|
}
|
||||||
Missing fanart will not appear in the dict.
|
Missing fanart will not appear in the dict.
|
||||||
"""
|
"""
|
||||||
|
@ -480,48 +480,6 @@ class KodiDBMethods(object):
|
||||||
self.cursor.execute(query, (kodi_id, kodi_type))
|
self.cursor.execute(query, (kodi_id, kodi_type))
|
||||||
return dict(self.cursor.fetchall())
|
return dict(self.cursor.fetchall())
|
||||||
|
|
||||||
def existingArt(self, kodiId, mediaType, refresh=False):
|
|
||||||
"""
|
|
||||||
For kodiId, returns an artwork dict with already existing art from
|
|
||||||
the Kodi db
|
|
||||||
"""
|
|
||||||
# Only get EITHER poster OR thumb (should have same URL)
|
|
||||||
kodiToPKC = {
|
|
||||||
'banner': 'Banner',
|
|
||||||
'clearart': 'Art',
|
|
||||||
'clearlogo': 'Logo',
|
|
||||||
'discart': 'Disc',
|
|
||||||
'landscape': 'Thumb',
|
|
||||||
'thumb': 'Primary'
|
|
||||||
}
|
|
||||||
# BoxRear yet unused
|
|
||||||
result = {'BoxRear': ''}
|
|
||||||
for art in kodiToPKC:
|
|
||||||
query = ' '.join((
|
|
||||||
"SELECT url",
|
|
||||||
"FROM art",
|
|
||||||
"WHERE media_id = ?",
|
|
||||||
"AND media_type = ?",
|
|
||||||
"AND type = ?"
|
|
||||||
))
|
|
||||||
self.cursor.execute(query, (kodiId, mediaType, art,))
|
|
||||||
try:
|
|
||||||
url = self.cursor.fetchone()[0]
|
|
||||||
except TypeError:
|
|
||||||
url = ""
|
|
||||||
result[kodiToPKC[art]] = url
|
|
||||||
# There may be several fanart URLs saved
|
|
||||||
query = ' '.join((
|
|
||||||
"SELECT url",
|
|
||||||
"FROM art",
|
|
||||||
"WHERE media_id = ?",
|
|
||||||
"AND media_type = ?",
|
|
||||||
"AND type LIKE ?"
|
|
||||||
))
|
|
||||||
data = self.cursor.execute(query, (kodiId, mediaType, "fanart%",))
|
|
||||||
result['Backdrop'] = [d[0] for d in data]
|
|
||||||
return result
|
|
||||||
|
|
||||||
def modify_streams(self, fileid, streamdetails=None, runtime=None):
|
def modify_streams(self, fileid, streamdetails=None, runtime=None):
|
||||||
"""
|
"""
|
||||||
Leave streamdetails and runtime empty to delete all stream entries for
|
Leave streamdetails and runtime empty to delete all stream entries for
|
||||||
|
|
|
@ -321,9 +321,36 @@ PLEX_TYPE_FROM_WEBSOCKET = {
|
||||||
KODI_TO_PLEX_ARTWORK = {
|
KODI_TO_PLEX_ARTWORK = {
|
||||||
'poster': 'thumb',
|
'poster': 'thumb',
|
||||||
'banner': 'banner',
|
'banner': 'banner',
|
||||||
'fanart1': 'art'
|
'fanart': 'art'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Might be implemented in the future: 'icon', 'landscape' (16:9)
|
||||||
|
ALL_KODI_ARTWORK = (
|
||||||
|
'thumb',
|
||||||
|
'poster',
|
||||||
|
'banner',
|
||||||
|
'clearart',
|
||||||
|
'clearlogo',
|
||||||
|
'fanart',
|
||||||
|
'discart'
|
||||||
|
)
|
||||||
|
|
||||||
|
# we need to use a little mapping between fanart.tv arttypes and kodi artttypes
|
||||||
|
FANART_TV_TO_KODI_TYPE = [
|
||||||
|
('poster', 'poster'),
|
||||||
|
('logo', 'clearlogo'),
|
||||||
|
('musiclogo', 'clearlogo'),
|
||||||
|
('disc', 'discart'),
|
||||||
|
('clearart', 'clearart'),
|
||||||
|
('banner', 'banner'),
|
||||||
|
('clearlogo', 'clearlogo'),
|
||||||
|
('background', 'fanart'),
|
||||||
|
('showbackground', 'fanart'),
|
||||||
|
('characterart', 'characterart')
|
||||||
|
]
|
||||||
|
# How many different backgrounds do we want to load from fanart.tv?
|
||||||
|
MAX_BACKGROUND_COUNT = 10
|
||||||
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
Loading…
Reference in a new issue