Merge branch 'develop' of git://github.com/Boehemyth/CouchPotatoServer into Boehemyth-develop
This commit is contained in:
@@ -26,7 +26,14 @@ class MovieResultModifier(Plugin):
|
||||
'backdrop': [],
|
||||
'poster_original': [],
|
||||
'backdrop_original': [],
|
||||
'actors': {}
|
||||
'actors': {},
|
||||
'landscape': [],
|
||||
'logo': [],
|
||||
'clearart': [],
|
||||
'discart': [],
|
||||
'banner': [],
|
||||
'extrathumbs': [],
|
||||
'extrafanart': []
|
||||
},
|
||||
'runtime': 0,
|
||||
'plot': '',
|
||||
|
||||
168
couchpotato/core/media/movie/providers/info/fanarttv.py
Normal file
168
couchpotato/core/media/movie/providers/info/fanarttv.py
Normal file
@@ -0,0 +1,168 @@
|
||||
import os
|
||||
import traceback
|
||||
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.media.movie.providers.base import MovieProvider
|
||||
from couchpotato.core.plugins.quality import QualityPlugin
|
||||
|
||||
from libs.fanarttv.movie import Movie
|
||||
import libs.fanarttv.errors as fanarttv_errors
|
||||
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
autoload = 'FanartTV'
|
||||
|
||||
|
||||
class FanartTV(MovieProvider):
|
||||
MAX_EXTRAFANART = 20
|
||||
|
||||
def __init__(self):
|
||||
addEvent('movie.extraart', self.getArt, priority=2)
|
||||
|
||||
# Configure fanarttv API settings
|
||||
os.environ.setdefault('FANART_APIKEY', self.conf('api_key'))
|
||||
|
||||
def getArt(self, identifier):
|
||||
# FIXME: I believe I should be registering a cache here... I need to look into that.
|
||||
log.debug("Getting Extra Artwork from Fanart.tv...")
|
||||
if not identifier:
|
||||
return {}
|
||||
|
||||
images = {}
|
||||
|
||||
try:
|
||||
try:
|
||||
exists = True
|
||||
movie = Movie.get(id=identifier)
|
||||
except (fanarttv_errors.FanartError, IOError):
|
||||
exists = False
|
||||
|
||||
if exists:
|
||||
images = self._parseMovie(movie, True)
|
||||
|
||||
except:
|
||||
log.error('Failed getting extra art for %s: %s',
|
||||
(identifier, traceback.format_exc()))
|
||||
return {}
|
||||
|
||||
return images
|
||||
|
||||
def _parseMovie(self, movie, isHD):
|
||||
images = {
|
||||
'landscape': [],
|
||||
'logo': [],
|
||||
'discart': [],
|
||||
'clearart': [],
|
||||
'banner': [],
|
||||
'extrafanart': []
|
||||
}
|
||||
|
||||
images['landscape'] = self._getMultImages(movie.thumbs, 1)
|
||||
images['banner'] = self._getMultImages(movie.banners, 1)
|
||||
images['discart'] = self._getMultImages(self._trimDiscs(movie.discs, isHD), 1)
|
||||
|
||||
images['clearart'] = self._getMultImages(movie.hdarts, 1)
|
||||
if len(images['clearart']) is 0:
|
||||
images['clearart'] = self._getMultImages(movie.arts, 1)
|
||||
|
||||
images['logo'] = self._getMultImages(movie.hdlogos, 1)
|
||||
if len(images['logo']) is 0:
|
||||
images['logo'] = self._getMultImages(movie.logos, 1)
|
||||
|
||||
fanarts = self._getMultImages(movie.backgrounds, self.MAX_EXTRAFANART + 1)
|
||||
|
||||
if fanarts:
|
||||
images['backdrop_original'] = fanarts[0]
|
||||
images['extrafanart'] = fanarts[1:]
|
||||
|
||||
# TODO: Add support for extra backgrounds
|
||||
#extraFanart = self._getMultImages(movie.backgrounds, -1)
|
||||
|
||||
return images
|
||||
|
||||
def _trimDiscs(self, discImages, isHD):
|
||||
'''
|
||||
Return a subset of discImages based on isHD. If isHD is true, only
|
||||
bluray disc images will be returned. If isHD is false, only dvd disc
|
||||
images will be returned. If the resulting list would be an empty list,
|
||||
then the original list is returned instead.
|
||||
'''
|
||||
trimmed = []
|
||||
for disc in discImages:
|
||||
if isHD and disc.disc_type == u'bluray':
|
||||
trimmed.append(disc)
|
||||
elif not isHD and disc.disc_type == u'dvd':
|
||||
trimmed.append(disc)
|
||||
|
||||
if len(trimmed) is 0:
|
||||
return discImages
|
||||
else:
|
||||
return trimmed
|
||||
|
||||
def _getImage(self, images):
|
||||
image_url = None
|
||||
highscore = -1
|
||||
for image in images:
|
||||
if image.likes > highscore:
|
||||
highscore = image.likes
|
||||
image_url = image.url
|
||||
|
||||
return image_url
|
||||
|
||||
def _getMultImages(self, images, n):
|
||||
'''
|
||||
Chooses the best n images and returns them as a list.
|
||||
If n<0, all images will be returned.
|
||||
'''
|
||||
image_urls = []
|
||||
pool = []
|
||||
for image in images:
|
||||
if image.lang == u'en':
|
||||
pool.append(image)
|
||||
origPoolSize = len(pool)
|
||||
|
||||
while len(pool) > 0 and (n < 0 or origPoolSize - len(pool) < n):
|
||||
best = None
|
||||
highscore = -1
|
||||
for image in pool:
|
||||
if image.likes > highscore:
|
||||
highscore = image.likes
|
||||
best = image
|
||||
image_urls.append(best.url)
|
||||
pool.remove(best)
|
||||
|
||||
return image_urls
|
||||
|
||||
def isDisabled(self):
|
||||
if self.conf('api_key') == '':
|
||||
log.error('No API key provided.')
|
||||
return True
|
||||
return False
|
||||
|
||||
def _determineHD(self, quality):
|
||||
for qualityDef in QualityPlugin.qualities:
|
||||
if quality == qualityDef.get('identifier'):
|
||||
return bool(qualityDef.get('hd'))
|
||||
return False
|
||||
|
||||
config = [{
|
||||
'name': 'fanarttv',
|
||||
'groups': [
|
||||
{
|
||||
'tab': 'providers',
|
||||
'name': 'fanarttv',
|
||||
'label': 'fanart.tv',
|
||||
'hidden': True,
|
||||
'description': 'Used for all calls to fanart.tv.',
|
||||
'options': [
|
||||
{
|
||||
'name': 'api_key',
|
||||
'default': 'd788b4822b9e1f44068026e05557e5d9',
|
||||
'label': 'API Key',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}]
|
||||
@@ -1,6 +1,6 @@
|
||||
import traceback
|
||||
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.helpers.encoding import simplifyString, toUnicode, ss
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
@@ -13,6 +13,7 @@ autoload = 'TheMovieDb'
|
||||
|
||||
|
||||
class TheMovieDb(MovieProvider):
|
||||
MAX_EXTRATHUMBS = 4
|
||||
|
||||
def __init__(self):
|
||||
addEvent('movie.info', self.getInfo, priority = 2)
|
||||
@@ -87,6 +88,13 @@ class TheMovieDb(MovieProvider):
|
||||
except:
|
||||
log.error('Failed getting info for %s: %s', (identifier, traceback.format_exc()))
|
||||
|
||||
# Get extra artwork via Fanart.TV and merge into images dict
|
||||
try:
|
||||
extraArt = fireEvent('movie.extraart', identifier)[0]
|
||||
result['images'] = dict(result['images'].items() + extraArt.items())
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
def parseMovie(self, movie, extended = True):
|
||||
@@ -100,13 +108,15 @@ class TheMovieDb(MovieProvider):
|
||||
poster = self.getImage(movie, type = 'poster', size = 'poster')
|
||||
poster_original = self.getImage(movie, type = 'poster', size = 'original')
|
||||
backdrop_original = self.getImage(movie, type = 'backdrop', size = 'original')
|
||||
extrathumbs = self.getMultImages(movie, type='backdrops', size='original', n=self.MAX_EXTRATHUMBS, skipfirst=True)
|
||||
|
||||
images = {
|
||||
'poster': [poster] if poster else [],
|
||||
#'backdrop': [backdrop] if backdrop else [],
|
||||
'poster_original': [poster_original] if poster_original else [],
|
||||
'backdrop_original': [backdrop_original] if backdrop_original else [],
|
||||
'actors': {}
|
||||
'actors': {},
|
||||
'extrathumbs': extrathumbs
|
||||
}
|
||||
|
||||
# Genres
|
||||
@@ -171,6 +181,28 @@ class TheMovieDb(MovieProvider):
|
||||
log.debug('Failed getting %s.%s for "%s"', (type, size, ss(str(movie))))
|
||||
|
||||
return image_url
|
||||
|
||||
def getMultImages(self, movie, type='backdrops', size='original', n=-1, skipfirst=False):
|
||||
'''
|
||||
If n < 0, return all images. Otherwise return n images.
|
||||
If n > len(getattr(movie, type)), then return all images.
|
||||
If skipfirst is True, then it will skip getattr(movie, type)[0]. This
|
||||
is because backdrops[0] is typically backdrop.
|
||||
'''
|
||||
image_urls = []
|
||||
try:
|
||||
images = getattr(movie, type)
|
||||
if n < 0 or n > len(images):
|
||||
numImages = len(images)
|
||||
else:
|
||||
numImages = n
|
||||
for i in range(int(skipfirst), numImages + int(skipfirst)):
|
||||
image_urls.append(images[i].geturl(size=size))
|
||||
|
||||
except:
|
||||
log.debug('Failed getting %i %s.%s for "%s"', (n, type, size, ss(str(movie))))
|
||||
|
||||
return image_urls
|
||||
|
||||
def isDisabled(self):
|
||||
if self.conf('api_key') == '':
|
||||
|
||||
@@ -37,76 +37,150 @@ class MovieMetaData(MetaDataBase):
|
||||
root = os.path.dirname(root_name)
|
||||
|
||||
movie_info = group['media'].get('info')
|
||||
|
||||
for file_type in ['nfo', 'thumbnail', 'fanart']:
|
||||
|
||||
for file_type in ['nfo']:
|
||||
try:
|
||||
# Get file path
|
||||
name = getattr(self, 'get' + file_type.capitalize() + 'Name')(meta_name, root)
|
||||
self._createType(meta_name, root, movie_info, group, file_type, 0)
|
||||
except:
|
||||
log.error('Unable to create %s file: %s', ('nfo', traceback.format_exc()))
|
||||
|
||||
if name and (self.conf('meta_' + file_type) or self.conf('meta_' + file_type) is None):
|
||||
|
||||
# Get file content
|
||||
content = getattr(self, 'get' + file_type.capitalize())(movie_info = movie_info, data = group)
|
||||
if content:
|
||||
log.debug('Creating %s file: %s', (file_type, name))
|
||||
if os.path.isfile(content):
|
||||
content = sp(content)
|
||||
name = sp(name)
|
||||
|
||||
shutil.copy2(content, name)
|
||||
shutil.copyfile(content, name)
|
||||
|
||||
# Try and copy stats seperately
|
||||
try: shutil.copystat(content, name)
|
||||
except: pass
|
||||
else:
|
||||
self.createFile(name, content)
|
||||
group['renamed_files'].append(name)
|
||||
|
||||
try:
|
||||
os.chmod(sp(name), Env.getPermission('file'))
|
||||
except:
|
||||
log.debug('Failed setting permissions for %s: %s', (name, traceback.format_exc()))
|
||||
for file_type in ['thumbnail', 'fanart', 'banner', 'discart', 'logo', 'clearart', 'landscape', 'extrathumbs', 'extrafanart']:
|
||||
try:
|
||||
if file_type == 'thumbnail':
|
||||
numImages = len(movie_info['images']['poster_original'])
|
||||
elif file_type == 'fanart':
|
||||
numImages = len(movie_info['images']['backdrop_original'])
|
||||
else:
|
||||
numImages = len(movie_info['images'][file_type])
|
||||
|
||||
for i in range(numImages):
|
||||
self._createType(meta_name, root, movie_info, group, file_type, i)
|
||||
except:
|
||||
log.error('Unable to create %s file: %s', (file_type, traceback.format_exc()))
|
||||
|
||||
def _createType(self, meta_name, root, movie_info, group, file_type, i):# Get file path
|
||||
name = getattr(self, 'get' + file_type.capitalize() + 'Name')(meta_name, root, i)
|
||||
|
||||
if name and (self.conf('meta_' + file_type) or self.conf('meta_' + file_type) is None):
|
||||
|
||||
# Get file content
|
||||
content = getattr(self, 'get' + file_type.capitalize())(movie_info=movie_info, data=group, i=i)
|
||||
if content:
|
||||
log.debug('Creating %s file: %s', (file_type, name))
|
||||
if os.path.isfile(content):
|
||||
content = sp(content)
|
||||
name = sp(name)
|
||||
|
||||
if not os.path.exists(os.path.dirname(name)):
|
||||
os.makedirs(os.path.dirname(name))
|
||||
|
||||
shutil.copy2(content, name)
|
||||
shutil.copyfile(content, name)
|
||||
|
||||
# Try and copy stats seperately
|
||||
try: shutil.copystat(content, name)
|
||||
except: pass
|
||||
else:
|
||||
self.createFile(name, content)
|
||||
group['renamed_files'].append(name)
|
||||
|
||||
try:
|
||||
os.chmod(sp(name), Env.getPermission('file'))
|
||||
except:
|
||||
log.debug('Failed setting permissions for %s: %s', (name, traceback.format_exc()))
|
||||
|
||||
def getRootName(self, data = None):
|
||||
if not data: data = {}
|
||||
return os.path.join(data['destination_dir'], data['filename'])
|
||||
|
||||
def getFanartName(self, name, root):
|
||||
def getFanartName(self, name, root, i):
|
||||
return
|
||||
|
||||
def getThumbnailName(self, name, root):
|
||||
def getThumbnailName(self, name, root, i):
|
||||
return
|
||||
|
||||
def getNfoName(self, name, root):
|
||||
def getBannerName(self, name, root, i):
|
||||
return
|
||||
|
||||
def getNfo(self, movie_info = None, data = None):
|
||||
def getClearartName(self, name, root, i):
|
||||
return
|
||||
|
||||
def getLogoName(self, name, root, i):
|
||||
return
|
||||
|
||||
def getDiscartName(self, name, root, i):
|
||||
return
|
||||
|
||||
def getLandscapeName(self, name, root, i):
|
||||
return
|
||||
|
||||
def getExtrathumbsName(self, name, root, i):
|
||||
return
|
||||
|
||||
def getExtrafanartName(self, name, root, i):
|
||||
return
|
||||
|
||||
def getNfoName(self, name, root, i):
|
||||
return
|
||||
|
||||
def getNfo(self, movie_info=None, data=None, i=0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
|
||||
def getThumbnail(self, movie_info = None, data = None, wanted_file_type = 'poster_original'):
|
||||
def getThumbnail(self, movie_info = None, data = None, wanted_file_type = 'poster_original', i = 0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
|
||||
# See if it is in current files
|
||||
files = data['media'].get('files')
|
||||
if files.get('image_' + wanted_file_type):
|
||||
if os.path.isfile(files['image_' + wanted_file_type][0]):
|
||||
return files['image_' + wanted_file_type][0]
|
||||
if os.path.isfile(files['image_' + wanted_file_type][i]):
|
||||
return files['image_' + wanted_file_type][i]
|
||||
|
||||
# Download using existing info
|
||||
try:
|
||||
images = movie_info['images'][wanted_file_type]
|
||||
file_path = fireEvent('file.download', url = images[0], single = True)
|
||||
file_path = fireEvent('file.download', url = images[i], single = True)
|
||||
return file_path
|
||||
except:
|
||||
pass
|
||||
|
||||
def getFanart(self, movie_info = None, data = None):
|
||||
def getFanart(self, movie_info = None, data = None, i = 0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
return self.getThumbnail(movie_info = movie_info, data = data, wanted_file_type = 'backdrop_original')
|
||||
return self.getThumbnail(movie_info=movie_info, data=data, wanted_file_type='backdrop_original', i=i)
|
||||
|
||||
def getBanner(self, movie_info=None, data=None, i=0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
return self.getThumbnail(movie_info=movie_info, data=data, wanted_file_type='banner', i=i)
|
||||
|
||||
def getClearart(self, movie_info=None, data=None, i=0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
return self.getThumbnail(movie_info=movie_info, data=data, wanted_file_type='clearart', i=i)
|
||||
|
||||
def getLogo(self, movie_info=None, data=None, i=0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
return self.getThumbnail(movie_info=movie_info, data=data, wanted_file_type='logo', i=i)
|
||||
|
||||
def getDiscart(self, movie_info=None, data=None, i=0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
return self.getThumbnail(movie_info=movie_info, data=data, wanted_file_type='discart', i=i)
|
||||
|
||||
def getLandscape(self, movie_info=None, data=None, i=0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
return self.getThumbnail(movie_info=movie_info, data=data, wanted_file_type='landscape', i=i)
|
||||
|
||||
def getExtrathumbs(self, movie_info=None, data=None, i=0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
return self.getThumbnail(movie_info=movie_info, data=data, wanted_file_type='extrathumbs', i=i)
|
||||
|
||||
def getExtrafanart(self, movie_info=None, data=None, i=0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
return self.getThumbnail(movie_info=movie_info, data=data, wanted_file_type='extrafanart', i=i)
|
||||
|
||||
@@ -17,19 +17,43 @@ autoload = 'XBMC'
|
||||
|
||||
class XBMC(MovieMetaData):
|
||||
|
||||
def getFanartName(self, name, root):
|
||||
def getFanartName(self, name, root, i):
|
||||
return self.createMetaName(self.conf('meta_fanart_name'), name, root)
|
||||
|
||||
def getThumbnailName(self, name, root):
|
||||
def getThumbnailName(self, name, root, i):
|
||||
return self.createMetaName(self.conf('meta_thumbnail_name'), name, root)
|
||||
|
||||
def getNfoName(self, name, root):
|
||||
def getNfoName(self, name, root, i):
|
||||
return self.createMetaName(self.conf('meta_nfo_name'), name, root)
|
||||
|
||||
def getBannerName(self, name, root, i):
|
||||
return self.createMetaName(self.conf('meta_banner_name'), name, root)
|
||||
|
||||
def getClearartName(self, name, root, i):
|
||||
return self.createMetaName(self.conf('meta_clearart_name'), name, root)
|
||||
|
||||
def getLogoName(self, name, root, i):
|
||||
return self.createMetaName(self.conf('meta_logo_name'), name, root)
|
||||
|
||||
def getDiscartName(self, name, root, i):
|
||||
return self.createMetaName(self.conf('meta_discart_name'), name, root)
|
||||
|
||||
def getLandscapeName(self, name, root, i):
|
||||
return self.createMetaName(self.conf('meta_landscape_name'), name, root)
|
||||
|
||||
def getExtrathumbsName(self, name, root, i):
|
||||
return self.createMetaNameMult(self.conf('meta_extrathumbs_name'), name, root, i)
|
||||
|
||||
def getExtrafanartName(self, name, root, i):
|
||||
return self.createMetaNameMult(self.conf('meta_extrafanart_name'), name, root, i)
|
||||
|
||||
def createMetaName(self, basename, name, root):
|
||||
return os.path.join(root, basename.replace('%s', name))
|
||||
|
||||
def getNfo(self, movie_info = None, data = None):
|
||||
def createMetaNameMult(self, basename, name, root, i):
|
||||
return os.path.join(root, basename.replace('%s', name).replace('%i', str(i + 1)))
|
||||
|
||||
def getNfo(self, movie_info=None, data=None, i=0):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
|
||||
@@ -133,6 +157,35 @@ class XBMC(MovieMetaData):
|
||||
for image_url in movie_info['images']['backdrop_original']:
|
||||
image = SubElement(fanart, 'thumb')
|
||||
image.text = toUnicode(image_url)
|
||||
banner = SubElement(nfoxml, 'banner')
|
||||
for image_url in movie_info['images']['banner']:
|
||||
image = SubElement(banner, 'thumb')
|
||||
image.text = toUnicode(image_url)
|
||||
discart = SubElement(nfoxml, 'discart')
|
||||
for image_url in movie_info['images']['discart']:
|
||||
image = SubElement(discart, 'thumb')
|
||||
image.text = toUnicode(image_url)
|
||||
logo = SubElement(nfoxml, 'logo')
|
||||
for image_url in movie_info['images']['logo']:
|
||||
image = SubElement(logo, 'thumb')
|
||||
image.text = toUnicode(image_url)
|
||||
clearart = SubElement(nfoxml, 'clearart')
|
||||
for image_url in movie_info['images']['clearart']:
|
||||
image = SubElement(clearart, 'thumb')
|
||||
image.text = toUnicode(image_url)
|
||||
landscape = SubElement(nfoxml, 'landscape')
|
||||
for image_url in movie_info['images']['landscape']:
|
||||
image = SubElement(landscape, 'thumb')
|
||||
image.text = toUnicode(image_url)
|
||||
extrathumb = SubElement(nfoxml, 'extrathumb')
|
||||
for image_url in movie_info['images']['extrathumbs']:
|
||||
image = SubElement(extrathumb, 'thumb')
|
||||
image.text = toUnicode(image_url)
|
||||
extrafanart = SubElement(nfoxml, 'extrafanart')
|
||||
for image_url in movie_info['images']['extrafanart']:
|
||||
image = SubElement(extrafanart, 'thumb')
|
||||
image.text = toUnicode(image_url)
|
||||
|
||||
|
||||
# Add trailer if found
|
||||
trailer_found = False
|
||||
@@ -239,6 +292,90 @@ config = [{
|
||||
'default': '%s.tbn',
|
||||
'advanced': True,
|
||||
},
|
||||
{
|
||||
'name': 'meta_banner',
|
||||
'label': 'Banner',
|
||||
'default': True,
|
||||
'type': 'bool'
|
||||
},
|
||||
{
|
||||
'name': 'meta_banner_name',
|
||||
'label': 'Banner filename',
|
||||
'default': 'banner.jpg',
|
||||
'advanced': True,
|
||||
},
|
||||
{
|
||||
'name': 'meta_clearart',
|
||||
'label': 'ClearArt',
|
||||
'default': True,
|
||||
'type': 'bool'
|
||||
},
|
||||
{
|
||||
'name': 'meta_clearart_name',
|
||||
'label': 'ClearArt filename',
|
||||
'default': 'clearart.png',
|
||||
'advanced': True,
|
||||
},
|
||||
{
|
||||
'name': 'meta_disc',
|
||||
'label': 'DiscArt',
|
||||
'default': True,
|
||||
'type': 'bool'
|
||||
},
|
||||
{
|
||||
'name': 'meta_discart_name',
|
||||
'label': 'DiscArt filename',
|
||||
'default': 'disc.png',
|
||||
'advanced': True,
|
||||
},
|
||||
{
|
||||
'name': 'meta_landscape',
|
||||
'label': 'Landscape',
|
||||
'default': True,
|
||||
'type': 'bool'
|
||||
},
|
||||
{
|
||||
'name': 'meta_landscape_name',
|
||||
'label': 'Landscape filename',
|
||||
'default': 'landscape.jpg',
|
||||
'advanced': True,
|
||||
},
|
||||
{
|
||||
'name': 'meta_logo',
|
||||
'label': 'ClearLogo',
|
||||
'default': True,
|
||||
'type': 'bool'
|
||||
},
|
||||
{
|
||||
'name': 'meta_logo_name',
|
||||
'label': 'ClearLogo filename',
|
||||
'default': 'logo.png',
|
||||
'advanced': True,
|
||||
},
|
||||
{
|
||||
'name': 'meta_extrathumbs',
|
||||
'label': 'Extrathumbs',
|
||||
'default': True,
|
||||
'type': 'bool'
|
||||
},
|
||||
{
|
||||
'name': 'meta_extrathumbs_name',
|
||||
'label': 'Extrathumbs filename (%i is the image number, and must be included to have multiple images).',
|
||||
'default': 'extrathumbs/thumb%i.jpg',
|
||||
'advanced': True
|
||||
},
|
||||
{
|
||||
'name': 'meta_extrafanart',
|
||||
'lavel': 'Extrafanart',
|
||||
'default': True,
|
||||
'type': 'bool'
|
||||
},
|
||||
{
|
||||
'name': 'meta_extrafanart_name',
|
||||
'label': 'Extrafanart filename (%i is the image number, and must be included to have multiple images).',
|
||||
'default': 'extrafanart/extrafanart%i.jpg',
|
||||
'advanced': True
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -3,6 +3,8 @@ import json
|
||||
import socket
|
||||
import traceback
|
||||
import urllib
|
||||
import time
|
||||
import os
|
||||
|
||||
from couchpotato.core.helpers.variable import splitString, getTitle
|
||||
from couchpotato.core.logger import CPLog
|
||||
@@ -36,7 +38,7 @@ class XBMC(Notification):
|
||||
|
||||
if self.use_json_notifications.get(host):
|
||||
calls = [
|
||||
('GUI.ShowNotification', {'title': self.default_title, 'message': message, 'image': self.getNotificationImage('small')}),
|
||||
('GUI.ShowNotification', None, {'title': self.default_title, 'message': message, 'image': self.getNotificationImage('small')}),
|
||||
]
|
||||
|
||||
if data and data.get('destination_dir') and (not self.conf('only_first') or hosts.index(host) == 0):
|
||||
@@ -44,7 +46,7 @@ class XBMC(Notification):
|
||||
if not self.conf('force_full_scan') and (self.conf('remote_dir_scan') or socket.getfqdn('localhost') == socket.getfqdn(host.split(':')[0])):
|
||||
param = {'directory': data['destination_dir']}
|
||||
|
||||
calls.append(('VideoLibrary.Scan', param))
|
||||
calls.append(('VideoLibrary.Scan', None, param))
|
||||
|
||||
max_successful += len(calls)
|
||||
response = self.request(host, calls)
|
||||
@@ -66,6 +68,50 @@ class XBMC(Notification):
|
||||
|
||||
except:
|
||||
log.error('Failed parsing results: %s', traceback.format_exc())
|
||||
|
||||
if self.conf('run_artwork_downloader') and data and self.use_json_notifications.get(host):
|
||||
time.sleep(self.conf('run_artwork_downloader_delay'))
|
||||
|
||||
if self.conf('force_full_scan'):
|
||||
calls = [('Addons.ExecuteAddon', None, {'addonid': 'script.artwork.downloader'})]
|
||||
max_successful += len(calls)
|
||||
response = self.request(host, calls)
|
||||
|
||||
try:
|
||||
if response[0].get('result') and result['result'] == 'OK':
|
||||
successful += 1
|
||||
elif response[0].get('error'):
|
||||
log.error('XBMC error; %s: %s (%s)', (result['id'], result['error']['message'], result['error']['code']))
|
||||
except:
|
||||
log.error('Failed parsing results: %s', traceback.format_exc())
|
||||
else:
|
||||
calls = [('VideoLibrary.GetMovies', 'libMovies', {"filter":{"field": "title", "operator": "is", "value": data['media']['title'], "year": data['media']['info']['year']}})]
|
||||
max_successful += len(calls)
|
||||
response = self.request(host, calls)
|
||||
|
||||
dbid = None
|
||||
try:
|
||||
if response[0].get('result'):
|
||||
successful += 1
|
||||
dbid = response[0]['result']['movies'][-1]['movieid']
|
||||
elif response[0].get('error'):
|
||||
log.error('XBMC error; %s: %s (%s)', (result['id'], result['error']['message'], result['error']['code']))
|
||||
except:
|
||||
log.error('Failed parsing results: %s', traceback.format_exc())
|
||||
|
||||
if dbid is not None:
|
||||
calls = [('Addons.ExecuteAddon', None, {'addonid': 'script.artwork.downloader', 'params':{'media_type': 'movie', 'dbid': str(dbid)}})]
|
||||
|
||||
max_successful += len(calls)
|
||||
response = self.request(host, calls)
|
||||
|
||||
try:
|
||||
if response[0].get('result') and result['result'] == 'OK':
|
||||
successful += 1
|
||||
elif response[0].get('error'):
|
||||
log.error('XBMC error; %s: %s (%s)', (result['id'], result['error']['message'], result['error']['code']))
|
||||
except:
|
||||
log.error('Failed parsing results: %s', traceback.format_exc())
|
||||
|
||||
return successful == max_successful
|
||||
|
||||
@@ -75,7 +121,7 @@ class XBMC(Notification):
|
||||
|
||||
# XBMC JSON-RPC version request
|
||||
response = self.request(host, [
|
||||
('JSONRPC.Version', {})
|
||||
('JSONRPC.Version', None, {})
|
||||
])
|
||||
for result in response:
|
||||
if result.get('result') and type(result['result']['version']).__name__ == 'int':
|
||||
@@ -112,7 +158,7 @@ class XBMC(Notification):
|
||||
self.use_json_notifications[host] = True
|
||||
|
||||
# send the text message
|
||||
resp = self.request(host, [('GUI.ShowNotification', {'title':self.default_title, 'message':message, 'image': self.getNotificationImage('small')})])
|
||||
resp = self.request(host, [('GUI.ShowNotification', None, {'title':self.default_title, 'message':message, 'image': self.getNotificationImage('small')})])
|
||||
for r in resp:
|
||||
if r.get('result') and r['result'] == 'OK':
|
||||
log.debug('Message delivered successfully!')
|
||||
@@ -184,12 +230,16 @@ class XBMC(Notification):
|
||||
|
||||
data = []
|
||||
for req in do_requests:
|
||||
method, kwargs = req
|
||||
method, id, kwargs = req
|
||||
|
||||
if id is None:
|
||||
id = method
|
||||
|
||||
data.append({
|
||||
'method': method,
|
||||
'params': kwargs,
|
||||
'jsonrpc': '2.0',
|
||||
'id': method,
|
||||
'id': id,
|
||||
})
|
||||
data = json.dumps(data)
|
||||
|
||||
@@ -273,6 +323,22 @@ config = [{
|
||||
'advanced': True,
|
||||
'description': 'Also send message when movie is snatched.',
|
||||
},
|
||||
{
|
||||
'name': 'run_artwork_downloader',
|
||||
'label': 'Run the Artwork Downloader',
|
||||
'default': 0,
|
||||
'type': 'bool',
|
||||
'advanced': True,
|
||||
'description': 'Runs the Artwork Downloader script to initialize/download artwork. (Requires the Artwork Downloader addon and XBMC Frodo or later)'
|
||||
},
|
||||
{
|
||||
'name': 'run_artwork_downloader_delay',
|
||||
'label': 'Artwork Downloader delay',
|
||||
'default': 5,
|
||||
'type': 'int',
|
||||
'advanced': True,
|
||||
'description': 'Number of seconds to wait to start the Artwork Downloader script after notifying XBMC.',
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
|
||||
110
libs/fanarttv/__init__.py
Normal file
110
libs/fanarttv/__init__.py
Normal file
@@ -0,0 +1,110 @@
|
||||
__author__ = 'Andrea De Marco <24erre@gmail.com>'
|
||||
__version__ = '1.4.0'
|
||||
__classifiers__ = [
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: Apache Software License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Topic :: Internet :: WWW/HTTP',
|
||||
'Topic :: Software Development :: Libraries',
|
||||
]
|
||||
__copyright__ = "2012, %s " % __author__
|
||||
__license__ = """
|
||||
Copyright %s.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
""" % __copyright__
|
||||
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
__doc__ = """
|
||||
:abstract: Python interface to fanart.tv API
|
||||
:version: %s
|
||||
:author: %s
|
||||
:contact: http://z4r.github.com/
|
||||
:date: 2012-04-04
|
||||
:copyright: %s
|
||||
""" % (__version__, __author__, __license__)
|
||||
|
||||
|
||||
def values(obj):
|
||||
return [v for k, v in obj.__dict__.iteritems() if not k.startswith('_')]
|
||||
|
||||
BASEURL = 'http://api.fanart.tv/webservice'
|
||||
|
||||
|
||||
class FORMAT(object):
|
||||
JSON = 'JSON'
|
||||
XML = 'XML'
|
||||
PHP = 'PHP'
|
||||
|
||||
|
||||
class WS(object):
|
||||
MUSIC = 'artist'
|
||||
MOVIE = 'movie'
|
||||
TV = 'series'
|
||||
|
||||
|
||||
class TYPE(object):
|
||||
ALL = 'all'
|
||||
|
||||
class TV(object):
|
||||
ART = 'clearart'
|
||||
LOGO = 'clearlogo'
|
||||
CHARACTER = 'characterart'
|
||||
THUMB = 'tvthumb'
|
||||
SEASONTHUMB = 'seasonthumb'
|
||||
BACKGROUND = 'showbackground'
|
||||
HDLOGO = 'hdtvlogo'
|
||||
HDART = 'hdclearart'
|
||||
POSTER = 'tvposter'
|
||||
BANNER = 'tvbanner'
|
||||
|
||||
class MUSIC(object):
|
||||
DISC = 'cdart'
|
||||
LOGO = 'musiclogo'
|
||||
BACKGROUND = 'artistbackground'
|
||||
COVER = 'albumcover'
|
||||
THUMB = 'artistthumb'
|
||||
|
||||
class MOVIE(object):
|
||||
ART = 'movieart'
|
||||
LOGO = 'movielogo'
|
||||
DISC = 'moviedisc'
|
||||
POSTER = 'movieposter'
|
||||
BACKGROUND = 'moviebackground'
|
||||
HDLOGO = 'hdmovielogo'
|
||||
HDART = 'hdmovieclearart'
|
||||
BANNER = 'moviebanner'
|
||||
THUMB = 'moviethumb'
|
||||
|
||||
|
||||
class SORT(object):
|
||||
POPULAR = 1
|
||||
NEWEST = 2
|
||||
OLDEST = 3
|
||||
|
||||
|
||||
class LIMIT(object):
|
||||
ONE = 1
|
||||
ALL = 2
|
||||
|
||||
FORMAT_LIST = values(FORMAT)
|
||||
WS_LIST = values(WS)
|
||||
TYPE_LIST = values(TYPE.MUSIC) + values(TYPE.TV) + values(TYPE.MOVIE) + [TYPE.ALL]
|
||||
MUSIC_TYPE_LIST = values(TYPE.MUSIC) + [TYPE.ALL]
|
||||
TV_TYPE_LIST = values(TYPE.TV) + [TYPE.ALL]
|
||||
MOVIE_TYPE_LIST = values(TYPE.MOVIE) + [TYPE.ALL]
|
||||
SORT_LIST = values(SORT)
|
||||
LIMIT_LIST = values(LIMIT)
|
||||
44
libs/fanarttv/core.py
Normal file
44
libs/fanarttv/core.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import libs.requests as requests
|
||||
import libs.fanarttv as fanart
|
||||
from libs.fanarttv.errors import RequestFanartError, ResponseFanartError
|
||||
|
||||
|
||||
class Request(object):
|
||||
def __init__(self, apikey, id, ws, type=None, sort=None, limit=None):
|
||||
self._apikey = apikey
|
||||
self._id = id
|
||||
self._ws = ws
|
||||
self._type = type or fanart.TYPE.ALL
|
||||
self._sort = sort or fanart.SORT.POPULAR
|
||||
self._limit = limit or fanart.LIMIT.ALL
|
||||
self.validate()
|
||||
self._response = None
|
||||
|
||||
def validate(self):
|
||||
for attribute_name in ('ws', 'type', 'sort', 'limit'):
|
||||
attribute = getattr(self, '_' + attribute_name)
|
||||
choices = getattr(fanart, attribute_name.upper() + '_LIST')
|
||||
if attribute not in choices:
|
||||
raise RequestFanartError('Not allowed {0}: {1} [{2}]'.format(attribute_name, attribute, ', '.join(choices)))
|
||||
|
||||
def __str__(self):
|
||||
return '/'.join(map(str, [
|
||||
fanart.BASEURL,
|
||||
self._ws,
|
||||
self._apikey,
|
||||
self._id,
|
||||
fanart.FORMAT.JSON,
|
||||
self._type,
|
||||
self._sort,
|
||||
self._limit,
|
||||
]))
|
||||
|
||||
def response(self):
|
||||
try:
|
||||
response = requests.get(str(self))
|
||||
rjson = response.json()
|
||||
if not isinstance(rjson, dict):
|
||||
raise Exception(response.text)
|
||||
return rjson
|
||||
except Exception as e:
|
||||
raise ResponseFanartError(str(e))
|
||||
15
libs/fanarttv/errors.py
Normal file
15
libs/fanarttv/errors.py
Normal file
@@ -0,0 +1,15 @@
|
||||
class FanartError(Exception):
|
||||
def __str__(self):
|
||||
return ', '.join(map(str, self.args))
|
||||
|
||||
def __repr__(self):
|
||||
name = self.__class__.__name__
|
||||
return '%s%r' % (name, self.args)
|
||||
|
||||
|
||||
class ResponseFanartError(FanartError):
|
||||
pass
|
||||
|
||||
|
||||
class RequestFanartError(FanartError):
|
||||
pass
|
||||
46
libs/fanarttv/immutable.py
Normal file
46
libs/fanarttv/immutable.py
Normal file
@@ -0,0 +1,46 @@
|
||||
class Immutable(object):
|
||||
_mutable = False
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if self._mutable or name == '_mutable':
|
||||
super(Immutable, self).__setattr__(name, value)
|
||||
else:
|
||||
raise TypeError("Can't modify immutable instance")
|
||||
|
||||
def __delattr__(self, name):
|
||||
if self._mutable:
|
||||
super(Immutable, self).__delattr__(name)
|
||||
else:
|
||||
raise TypeError("Can't modify immutable instance")
|
||||
|
||||
def __eq__(self, other):
|
||||
return hash(self) == hash(other)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (
|
||||
self.__class__.__name__,
|
||||
', '.join(['{0}={1}'.format(k, repr(v)) for k, v in self])
|
||||
)
|
||||
|
||||
def __iter__(self):
|
||||
l = self.__dict__.keys()
|
||||
l.sort()
|
||||
for k in l:
|
||||
if not k.startswith('_'):
|
||||
yield k, getattr(self, k)
|
||||
|
||||
@staticmethod
|
||||
def mutablemethod(f):
|
||||
def func(self, *args, **kwargs):
|
||||
if isinstance(self, Immutable):
|
||||
old_mutable = self._mutable
|
||||
self._mutable = True
|
||||
res = f(self, *args, **kwargs)
|
||||
self._mutable = old_mutable
|
||||
else:
|
||||
res = f(self, *args, **kwargs)
|
||||
return res
|
||||
return func
|
||||
68
libs/fanarttv/items.py
Normal file
68
libs/fanarttv/items.py
Normal file
@@ -0,0 +1,68 @@
|
||||
import json
|
||||
import os
|
||||
import libs.requests as requests
|
||||
from libs.fanarttv.core import Request
|
||||
from libs.fanarttv.immutable import Immutable
|
||||
|
||||
|
||||
class LeafItem(Immutable):
|
||||
KEY = NotImplemented
|
||||
|
||||
@Immutable.mutablemethod
|
||||
def __init__(self, id, url, likes):
|
||||
self.id = int(id)
|
||||
self.url = url
|
||||
self.likes = int(likes)
|
||||
self._content = None
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, resource):
|
||||
return cls(**dict([(str(k), v) for k, v in resource.iteritems()]))
|
||||
|
||||
@classmethod
|
||||
def extract(cls, resource):
|
||||
return [cls.from_dict(i) for i in resource.get(cls.KEY, {})]
|
||||
|
||||
@Immutable.mutablemethod
|
||||
def content(self):
|
||||
if not self._content:
|
||||
self._content = requests.get(self.url).content
|
||||
return self._content
|
||||
|
||||
def __str__(self):
|
||||
return self.url
|
||||
|
||||
|
||||
class ResourceItem(Immutable):
|
||||
WS = NotImplemented
|
||||
request_cls = Request
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, map):
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def get(cls, id):
|
||||
map = cls.request_cls(
|
||||
apikey=os.environ.get('FANART_APIKEY'),
|
||||
id=id,
|
||||
ws=cls.WS
|
||||
).response()
|
||||
return cls.from_dict(map)
|
||||
|
||||
def json(self, **kw):
|
||||
return json.dumps(
|
||||
self,
|
||||
default=lambda o: dict([(k, v) for k, v in o.__dict__.items() if not k.startswith('_')]),
|
||||
**kw
|
||||
)
|
||||
|
||||
|
||||
class CollectableItem(Immutable):
|
||||
@classmethod
|
||||
def from_dict(cls, key, map):
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def collection_from_dict(cls, map):
|
||||
return [cls.from_dict(k, v) for k, v in map.iteritems()]
|
||||
103
libs/fanarttv/movie.py
Normal file
103
libs/fanarttv/movie.py
Normal file
@@ -0,0 +1,103 @@
|
||||
import libs.fanarttv as fanart
|
||||
from libs.fanarttv.items import LeafItem, Immutable, ResourceItem
|
||||
__all__ = (
|
||||
'ArtItem',
|
||||
'DiscItem',
|
||||
'LogoItem',
|
||||
'PosterItem',
|
||||
'BackgroundItem',
|
||||
'HdLogoItem',
|
||||
'HdArtItem',
|
||||
'BannerItem',
|
||||
'ThumbItem',
|
||||
'Movie',
|
||||
)
|
||||
|
||||
|
||||
class MovieItem(LeafItem):
|
||||
|
||||
@Immutable.mutablemethod
|
||||
def __init__(self, id, url, likes, lang):
|
||||
super(MovieItem, self).__init__(id, url, likes)
|
||||
self.lang = lang
|
||||
|
||||
|
||||
class DiscItem(MovieItem):
|
||||
KEY = fanart.TYPE.MOVIE.DISC
|
||||
|
||||
@Immutable.mutablemethod
|
||||
def __init__(self, id, url, likes, lang, disc, disc_type):
|
||||
super(DiscItem, self).__init__(id, url, likes, lang)
|
||||
self.disc = int(disc)
|
||||
self.disc_type = disc_type
|
||||
|
||||
|
||||
class ArtItem(MovieItem):
|
||||
KEY = fanart.TYPE.MOVIE.ART
|
||||
|
||||
|
||||
class LogoItem(MovieItem):
|
||||
KEY = fanart.TYPE.MOVIE.LOGO
|
||||
|
||||
|
||||
class PosterItem(MovieItem):
|
||||
KEY = fanart.TYPE.MOVIE.POSTER
|
||||
|
||||
|
||||
class BackgroundItem(MovieItem):
|
||||
KEY = fanart.TYPE.MOVIE.BACKGROUND
|
||||
|
||||
|
||||
class HdLogoItem(MovieItem):
|
||||
KEY = fanart.TYPE.MOVIE.HDLOGO
|
||||
|
||||
|
||||
class HdArtItem(MovieItem):
|
||||
KEY = fanart.TYPE.MOVIE.HDART
|
||||
|
||||
|
||||
class BannerItem(MovieItem):
|
||||
KEY = fanart.TYPE.MOVIE.BANNER
|
||||
|
||||
|
||||
class ThumbItem(MovieItem):
|
||||
KEY = fanart.TYPE.MOVIE.THUMB
|
||||
|
||||
|
||||
class Movie(ResourceItem):
|
||||
WS = fanart.WS.MOVIE
|
||||
|
||||
@Immutable.mutablemethod
|
||||
def __init__(self, name, imdbid, tmdbid, arts, logos, discs, posters, backgrounds, hdlogos, hdarts,
|
||||
banners, thumbs):
|
||||
self.name = name
|
||||
self.imdbid = imdbid
|
||||
self.tmdbid = tmdbid
|
||||
self.arts = arts
|
||||
self.posters = posters
|
||||
self.logos = logos
|
||||
self.discs = discs
|
||||
self.backgrounds = backgrounds
|
||||
self.hdlogos = hdlogos
|
||||
self.hdarts = hdarts
|
||||
self.banners = banners
|
||||
self.thumbs = thumbs
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, resource):
|
||||
assert len(resource) == 1, 'Bad Format Map'
|
||||
name, resource = resource.items()[0]
|
||||
return cls(
|
||||
name=name,
|
||||
imdbid=resource['imdb_id'],
|
||||
tmdbid=resource['tmdb_id'],
|
||||
arts=ArtItem.extract(resource),
|
||||
logos=LogoItem.extract(resource),
|
||||
discs=DiscItem.extract(resource),
|
||||
posters=PosterItem.extract(resource),
|
||||
backgrounds=BackgroundItem.extract(resource),
|
||||
hdlogos=HdLogoItem.extract(resource),
|
||||
hdarts=HdArtItem.extract(resource),
|
||||
banners=BannerItem.extract(resource),
|
||||
thumbs=ThumbItem.extract(resource),
|
||||
)
|
||||
80
libs/fanarttv/music.py
Normal file
80
libs/fanarttv/music.py
Normal file
@@ -0,0 +1,80 @@
|
||||
from libs.fanarttv.items import Immutable, LeafItem, ResourceItem, CollectableItem
|
||||
import libs.fanarttv as fanart
|
||||
__all__ = (
|
||||
'BackgroundItem',
|
||||
'CoverItem',
|
||||
'LogoItem',
|
||||
'ThumbItem',
|
||||
'DiscItem',
|
||||
'Artist',
|
||||
'Album',
|
||||
)
|
||||
|
||||
|
||||
class BackgroundItem(LeafItem):
|
||||
KEY = fanart.TYPE.MUSIC.BACKGROUND
|
||||
|
||||
|
||||
class CoverItem(LeafItem):
|
||||
KEY = fanart.TYPE.MUSIC.COVER
|
||||
|
||||
|
||||
class LogoItem(LeafItem):
|
||||
KEY = fanart.TYPE.MUSIC.LOGO
|
||||
|
||||
|
||||
class ThumbItem(LeafItem):
|
||||
KEY = fanart.TYPE.MUSIC.THUMB
|
||||
|
||||
|
||||
class DiscItem(LeafItem):
|
||||
KEY = fanart.TYPE.MUSIC.DISC
|
||||
|
||||
@Immutable.mutablemethod
|
||||
def __init__(self, id, url, likes, disc, size):
|
||||
super(DiscItem, self).__init__(id, url, likes)
|
||||
self.disc = int(disc)
|
||||
self.size = int(size)
|
||||
|
||||
|
||||
class Artist(ResourceItem):
|
||||
WS = fanart.WS.MUSIC
|
||||
|
||||
@Immutable.mutablemethod
|
||||
def __init__(self, name, mbid, albums, backgrounds, logos, thumbs):
|
||||
self.name = name
|
||||
self.mbid = mbid
|
||||
self.albums = albums
|
||||
self.backgrounds = backgrounds
|
||||
self.logos = logos
|
||||
self.thumbs = thumbs
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, resource):
|
||||
assert len(resource) == 1, 'Bad Format Map'
|
||||
name, resource = resource.items()[0]
|
||||
return cls(
|
||||
name=name,
|
||||
mbid=resource['mbid_id'],
|
||||
albums=Album.collection_from_dict(resource.get('albums', {})),
|
||||
backgrounds=BackgroundItem.extract(resource),
|
||||
thumbs=ThumbItem.extract(resource),
|
||||
logos=LogoItem.extract(resource),
|
||||
)
|
||||
|
||||
|
||||
class Album(CollectableItem):
|
||||
|
||||
@Immutable.mutablemethod
|
||||
def __init__(self, mbid, covers, arts):
|
||||
self.mbid = mbid
|
||||
self.covers = covers
|
||||
self.arts = arts
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, key, resource):
|
||||
return cls(
|
||||
mbid=key,
|
||||
covers=CoverItem.extract(resource),
|
||||
arts=DiscItem.extract(resource),
|
||||
)
|
||||
108
libs/fanarttv/tv.py
Normal file
108
libs/fanarttv/tv.py
Normal file
@@ -0,0 +1,108 @@
|
||||
import libs.fanarttv as fanart
|
||||
from libs.fanarttv.items import LeafItem, Immutable, ResourceItem
|
||||
__all__ = (
|
||||
'CharacterItem',
|
||||
'ArtItem',
|
||||
'LogoItem',
|
||||
'BackgroundItem',
|
||||
'SeasonItem',
|
||||
'ThumbItem',
|
||||
'HdLogoItem',
|
||||
'HdArtItem',
|
||||
'PosterItem',
|
||||
'BannerItem',
|
||||
'TvShow',
|
||||
)
|
||||
|
||||
|
||||
class TvItem(LeafItem):
|
||||
@Immutable.mutablemethod
|
||||
def __init__(self, id, url, likes, lang):
|
||||
super(TvItem, self).__init__(id, url, likes)
|
||||
self.lang = lang
|
||||
|
||||
|
||||
class SeasonedTvItem(TvItem):
|
||||
@Immutable.mutablemethod
|
||||
def __init__(self, id, url, likes, lang, season):
|
||||
super(SeasonedTvItem, self).__init__(id, url, likes, lang)
|
||||
self.season = 0 if season == 'all' else int(season or 0)
|
||||
|
||||
|
||||
class CharacterItem(TvItem):
|
||||
KEY = fanart.TYPE.TV.CHARACTER
|
||||
|
||||
|
||||
class ArtItem(TvItem):
|
||||
KEY = fanart.TYPE.TV.ART
|
||||
|
||||
|
||||
class LogoItem(TvItem):
|
||||
KEY = fanart.TYPE.TV.LOGO
|
||||
|
||||
|
||||
class BackgroundItem(SeasonedTvItem):
|
||||
KEY = fanart.TYPE.TV.BACKGROUND
|
||||
|
||||
|
||||
class SeasonItem(SeasonedTvItem):
|
||||
KEY = fanart.TYPE.TV.SEASONTHUMB
|
||||
|
||||
|
||||
class ThumbItem(TvItem):
|
||||
KEY = fanart.TYPE.TV.THUMB
|
||||
|
||||
|
||||
class HdLogoItem(TvItem):
|
||||
KEY = fanart.TYPE.TV.HDLOGO
|
||||
|
||||
|
||||
class HdArtItem(TvItem):
|
||||
KEY = fanart.TYPE.TV.HDART
|
||||
|
||||
|
||||
class PosterItem(TvItem):
|
||||
KEY = fanart.TYPE.TV.POSTER
|
||||
|
||||
|
||||
class BannerItem(TvItem):
|
||||
KEY = fanart.TYPE.TV.BANNER
|
||||
|
||||
|
||||
class TvShow(ResourceItem):
|
||||
WS = fanart.WS.TV
|
||||
|
||||
@Immutable.mutablemethod
|
||||
def __init__(self, name, tvdbid, backgrounds, characters, arts, logos, seasons, thumbs, hdlogos, hdarts, posters,
|
||||
banners):
|
||||
self.name = name
|
||||
self.tvdbid = tvdbid
|
||||
self.backgrounds = backgrounds
|
||||
self.characters = characters
|
||||
self.arts = arts
|
||||
self.logos = logos
|
||||
self.seasons = seasons
|
||||
self.thumbs = thumbs
|
||||
self.hdlogos = hdlogos
|
||||
self.hdarts = hdarts
|
||||
self.posters = posters
|
||||
self.banners = banners
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, resource):
|
||||
assert len(resource) == 1, 'Bad Format Map'
|
||||
name, resource = resource.items()[0]
|
||||
return cls(
|
||||
name=name,
|
||||
tvdbid=resource['thetvdb_id'],
|
||||
backgrounds=BackgroundItem.extract(resource),
|
||||
characters=CharacterItem.extract(resource),
|
||||
arts=ArtItem.extract(resource),
|
||||
logos=LogoItem.extract(resource),
|
||||
seasons=SeasonItem.extract(resource),
|
||||
thumbs=ThumbItem.extract(resource),
|
||||
hdlogos=HdLogoItem.extract(resource),
|
||||
hdarts=HdArtItem.extract(resource),
|
||||
posters=PosterItem.extract(resource),
|
||||
banners=BannerItem.extract(resource),
|
||||
)
|
||||
Reference in New Issue
Block a user