From 681d8b1ddc736ccc90e118cc10a91c95dfa41bac Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 2 Jun 2014 22:23:26 +0200 Subject: [PATCH] Simplify fanart provider --- .../media/movie/providers/info/fanarttv.py | 95 +++++++-------- libs/fanarttv/__init__.py | 110 ------------------ libs/fanarttv/core.py | 44 ------- libs/fanarttv/errors.py | 15 --- libs/fanarttv/immutable.py | 46 -------- libs/fanarttv/items.py | 68 ----------- libs/fanarttv/movie.py | 103 ---------------- libs/fanarttv/music.py | 80 ------------- libs/fanarttv/tv.py | 108 ----------------- 9 files changed, 40 insertions(+), 629 deletions(-) delete mode 100644 libs/fanarttv/__init__.py delete mode 100644 libs/fanarttv/core.py delete mode 100644 libs/fanarttv/errors.py delete mode 100644 libs/fanarttv/immutable.py delete mode 100644 libs/fanarttv/items.py delete mode 100644 libs/fanarttv/movie.py delete mode 100644 libs/fanarttv/music.py delete mode 100644 libs/fanarttv/tv.py diff --git a/couchpotato/core/media/movie/providers/info/fanarttv.py b/couchpotato/core/media/movie/providers/info/fanarttv.py index fe4bb93a..1d7fbce3 100644 --- a/couchpotato/core/media/movie/providers/info/fanarttv.py +++ b/couchpotato/core/media/movie/providers/info/fanarttv.py @@ -1,12 +1,9 @@ -import os import traceback +from couchpotato import tryInt 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 -import libs.fanarttv.errors as fanarttv_errors -from libs.fanarttv.movie import Movie log = CPLog(__name__) @@ -16,16 +13,17 @@ autoload = 'FanartTV' class FanartTV(MovieProvider): + urls = { + 'api': 'http://api.fanart.tv/webservice/movie/%s/%s/JSON/all/1/2' + } + MAX_EXTRAFANART = 20 def __init__(self): - addEvent('movie.extra_art', self.getArt, priority=2) + addEvent('movie.info', self.getArt, priority = 1) - # Configure fanarttv API settings - os.environ.setdefault('FANART_APIKEY', self.conf('api_key')) + def getArt(self, identifier = None, **kwargs): - 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 {} @@ -33,23 +31,24 @@ class FanartTV(MovieProvider): images = {} try: - try: - exists = True - movie = Movie.get(id = identifier) - except (fanarttv_errors.FanartError, IOError): - exists = False + url = self.urls['api'] % (self.conf('api_key'), identifier) + fanart_data = self.getJsonData(url) - if exists: - images = self._parseMovie(movie, True) + if fanart_data: + name, resource = fanart_data.items()[0] + log.debug('Found images for %s', name) + images = self._parseMovie(resource) except: log.error('Failed getting extra art for %s: %s', (identifier, traceback.format_exc())) return {} - return images + return { + 'images': images + } - def _parseMovie(self, movie, is_hd): + def _parseMovie(self, movie): images = { 'landscape': [], 'logo': [], @@ -59,56 +58,48 @@ class FanartTV(MovieProvider): 'extra_fanart': [], } - images['landscape'] = self._getMultImages(movie.thumbs, 1) - images['banner'] = self._getMultImages(movie.banners, 1) - images['disc_art'] = self._getMultImages(self._trimDiscs(movie.discs, is_hd), 1) + images['landscape'] = self._getMultImages(movie.get('moviethumb', []), 1) + images['banner'] = self._getMultImages(movie.get('moviebanner', []), 1) + images['disc_art'] = self._getMultImages(self._trimDiscs(movie.get('moviedisc', [])), 1) - images['clear_art'] = self._getMultImages(movie.hdarts, 1) - if len(images['clear_art']) is 0: - images['clear_art'] = self._getMultImages(movie.arts, 1) + images['clear_art'] = self._getMultImages(movie.get('hdmovieart', []), 1) + if len(images['clear_art']) == 0: + images['clear_art'] = self._getMultImages(movie.get('movieart', []), 1) - images['logo'] = self._getMultImages(movie.hdlogos, 1) - if len(images['logo']) is 0: - images['logo'] = self._getMultImages(movie.logos, 1) + images['logo'] = self._getMultImages(movie.get('hdmovielogo', []), 1) + if len(images['logo']) == 0: + images['logo'] = self._getMultImages(movie.get('movielogo', []), 1) - fanarts = self._getMultImages(movie.backgrounds, self.MAX_EXTRAFANART + 1) + fanarts = self._getMultImages(movie.get('moviebackground', []), self.MAX_EXTRAFANART + 1) if fanarts: images['backdrop_original'] = fanarts[0] images['extra_fanart'] = fanarts[1:] - # TODO: Add support for extra backgrounds - #extra_fanart = self._getMultImages(movie.backgrounds, -1) - return images - def _trimDiscs(self, disc_images, is_hd): + def _trimDiscs(self, disc_images): """ - 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. + Return a subset of discImages. Only bluray disc images will be returned. """ trimmed = [] for disc in disc_images: - if is_hd and disc.disc_type == u'bluray': - trimmed.append(disc) - elif not is_hd and disc.disc_type == u'dvd': + if disc.get('disc_type') == 'bluray': trimmed.append(disc) - if len(trimmed) is 0: + if len(trimmed) == 0: return disc_images - else: - return trimmed + + 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 + if tryInt(image.get('likes')) > highscore: + highscore = tryInt(image.get('likes')) + image_url = image.get('url') return image_url @@ -120,7 +111,7 @@ class FanartTV(MovieProvider): image_urls = [] pool = [] for image in images: - if image.lang == u'en': + if image.get('lang') == 'en': pool.append(image) orig_pool_size = len(pool) @@ -128,10 +119,10 @@ class FanartTV(MovieProvider): best = None highscore = -1 for image in pool: - if image.likes > highscore: - highscore = image.likes + if tryInt(image.get('likes')) > highscore: + highscore = tryInt(image.get('likes')) best = image - image_urls.append(best.url) + image_urls.append(best.get('url')) pool.remove(best) return image_urls @@ -142,12 +133,6 @@ class FanartTV(MovieProvider): 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', diff --git a/libs/fanarttv/__init__.py b/libs/fanarttv/__init__.py deleted file mode 100644 index 773703ca..00000000 --- a/libs/fanarttv/__init__.py +++ /dev/null @@ -1,110 +0,0 @@ -__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) diff --git a/libs/fanarttv/core.py b/libs/fanarttv/core.py deleted file mode 100644 index 9cd1cad7..00000000 --- a/libs/fanarttv/core.py +++ /dev/null @@ -1,44 +0,0 @@ -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)) diff --git a/libs/fanarttv/errors.py b/libs/fanarttv/errors.py deleted file mode 100644 index 95a71e35..00000000 --- a/libs/fanarttv/errors.py +++ /dev/null @@ -1,15 +0,0 @@ -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 diff --git a/libs/fanarttv/immutable.py b/libs/fanarttv/immutable.py deleted file mode 100644 index 170de370..00000000 --- a/libs/fanarttv/immutable.py +++ /dev/null @@ -1,46 +0,0 @@ -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 diff --git a/libs/fanarttv/items.py b/libs/fanarttv/items.py deleted file mode 100644 index 64848076..00000000 --- a/libs/fanarttv/items.py +++ /dev/null @@ -1,68 +0,0 @@ -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()] diff --git a/libs/fanarttv/movie.py b/libs/fanarttv/movie.py deleted file mode 100644 index fe473d4d..00000000 --- a/libs/fanarttv/movie.py +++ /dev/null @@ -1,103 +0,0 @@ -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), - ) diff --git a/libs/fanarttv/music.py b/libs/fanarttv/music.py deleted file mode 100644 index df634c67..00000000 --- a/libs/fanarttv/music.py +++ /dev/null @@ -1,80 +0,0 @@ -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), - ) diff --git a/libs/fanarttv/tv.py b/libs/fanarttv/tv.py deleted file mode 100644 index 9b1b08a7..00000000 --- a/libs/fanarttv/tv.py +++ /dev/null @@ -1,108 +0,0 @@ -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), - )