Exemplo n.º 1
0
    def _get_characterart(self, mediaid):
        data = self.get_data(mediaid, 'characterart')
        if not data:
            return {}
        baseurl = data['base_url_character_art']
        result = []
        for characterart in data['character_art']:
            result.append({
                'url':
                baseurl + '/' + characterart['name'],
                'language':
                None,
                'rating':
                SortedDisplay(characterart['likes'],
                              '{0} likes'.format(characterart['likes'])),
                'size':
                SortedDisplay(characterart['height'],
                              characterart['resolution']),
                'provider':
                self.name,
                'preview':
                baseurl + '/' + characterart['name']
            })

        return result
Exemplo n.º 2
0
 def _get_rating(self, image):
     if image['vote_count']:
         # Reweigh ratings, increase difference from 5
         rating = image['vote_average']
         rating = 5 + (rating - 5) * 2
         return SortedDisplay(rating, '{0:.1f} stars'.format(image['vote_average']))
     else:
         return SortedDisplay(5, 'Not rated')
Exemplo n.º 3
0
 def buildimage(self, url, title, fromartistfolder=False):
     provider = ARTIST_INFOFOLDER_PROVIDER if fromartistfolder else self.name
     result = {'url': url, 'provider': provider, 'preview': url}
     result['title'] = title
     result['rating'] = SortedDisplay(0, '')
     result['size'] = SortedDisplay(0, '')
     result['language'] = 'xx'
     return result
Exemplo n.º 4
0
 def _get_rating(self, image):
     if image['ratingsInfo']['count']:
         info = image['ratingsInfo']
         rating = info['average']
         if info['count'] < 5:
             # Reweigh ratings, decrease difference from 5
             rating = 5 + (rating - 5) * sin(info['count'] / pi)
         return SortedDisplay(rating,
                              '{0:.1f} stars'.format(info['average']))
     else:
         return SortedDisplay(5, 'Not rated')
Exemplo n.º 5
0
 def build_resultimage(self, url, title):
     if isinstance(url, unicode):
         url = url.encode('utf-8')
     if url.startswith('http'):
         url = urllib.quote(url, safe="%/:=&?~#+!$,;'@()*[]")
     resultimage = {'url': url, 'provider': self.name, 'preview': url}
     resultimage['title'] = '<{0}>'.format(title)
     resultimage['rating'] = SortedDisplay(0, '')
     resultimage['size'] = SortedDisplay(0, '')
     resultimage['language'] = 'xx'
     return resultimage
Exemplo n.º 6
0
 def get_images(self, uniqueids, types=None):
     if not settings.get_apienabled('tvdb'):
         return {}
     if types is not None and not self.provides(types):
         return {}
     mediaid = get_mediaid(uniqueids)
     if not mediaid:
         return {}
     result = {}
     languages = base.languages
     # Useful fanart can be hidden by the language filter, try a few of the most frequently used
     flanguages = ['en', 'de', 'fr', 'es', 'ru']
     flanguages.extend(lang for lang in languages if lang not in flanguages)
     for arttype in self.artmap:
         if types and not typematches(self.artmap[arttype], types):
             continue
         for language in languages if arttype != 'fanart' else flanguages:
             generaltype = self.artmap[arttype]
             data = self.get_data(mediaid, arttype, language)
             if not data:
                 continue
             isseason = arttype.startswith('season')
             if not isseason:
                 if generaltype not in result:
                     result[generaltype] = []
             for image in data['data']:
                 if not image.get('fileName'
                                  ) or isseason and not image.get('subKey'):
                     continue
                 ntype = generaltype
                 if isseason:
                     ntype = ntype % image['subKey']
                     if ntype not in result:
                         result[ntype] = []
                 resultimage = {'provider': self.name}
                 resultimage['url'] = self.imageurl_base + image['fileName']
                 resultimage['preview'] = self.imageurl_base + (
                     image['thumbnail'] or '_cache/' + image['fileName'])
                 resultimage[
                     'language'] = language if shouldset_imagelanguage(
                         image) else None
                 resultimage['rating'] = self._get_rating(image)
                 if arttype in ('series', 'seasonwide'):
                     resultimage['size'] = SortedDisplay(758, '758x140')
                 elif arttype == 'season':
                     resultimage['size'] = SortedDisplay(1000, '680x1000')
                 else:
                     resultimage['size'] = parse_sortsize(image, arttype)
                 result[ntype].append(resultimage)
     return result
Exemplo n.º 7
0
    def _get_animated_images(self, mediaid):
        data = self.get_data(mediaid, 'animated')
        if not data:
            return {}
        baseposter = data['base_url_posters']
        basefanart = data['base_url_backgrounds']
        result = {}
        for poster in data['posters']:
            newposter = {
                'url':
                baseposter + '/' + poster['name'],
                'language':
                get_language(poster.get('language', None)),
                'rating':
                SortedDisplay(poster['likes'],
                              '{0} likes'.format(poster['likes'])),
                'size':
                SortedDisplay(poster['height'], poster['resolution']),
                'provider':
                self.name,
                'preview':
                baseposter + '/' + poster['name']
            }

            arttype = 'animatedposter' if newposter[
                'language'] else 'animatedkeyart'
            if arttype not in result:
                result[arttype] = []
            result[arttype].append(newposter)
        for fanart in data['backgrounds']:
            if 'animatedfanart' not in result:
                result['animatedfanart'] = []
            result['animatedfanart'].append({
                'url':
                basefanart + '/' + fanart['name'],
                'language':
                None,
                'rating':
                SortedDisplay(fanart['likes'],
                              '{0} likes'.format(fanart['likes'])),
                'size':
                SortedDisplay(fanart['height'], fanart['resolution']),
                'provider':
                self.name,
                'preview':
                basefanart + '/' + fanart['name']
            })

        return result
Exemplo n.º 8
0
def parse_sortsize(image, arttype):
    try:
        sortsize = int(
            image['resolution'].split('x')[0 if arttype != 'poster' else 1])
    except (ValueError, IndexError):
        sortsize = 0
    return SortedDisplay(sortsize, image['resolution'])
Exemplo n.º 9
0
 def build_image(self, url, arttype, image, likediv=5.0):
     result = {'url': url, 'provider': self.name}
     result['preview'] = url.replace('.fanart.tv/fanart/', '.fanart.tv/preview/')
     result['rating'] = SortedDisplay(5.25 + int(image['likes']) / float(likediv), '{0} likes'.format(image['likes']))
     result['size'] = _get_imagesize(arttype)
     result['language'] = _get_imagelanguage(arttype, image)
     return result
Exemplo n.º 10
0
class AbstractProvider(object):
    __metaclass__ = ABCMeta

    name = SortedDisplay(0, '')
    mediatype = None
    contenttype = None

    def __init__(self):
        self.getter = Getter(self.contenttype, self.login)
        self.getter.session.headers['User-Agent'] = settings.useragent

    def doget(self, url, **kwargs):
        try:
            return self.getter(url, **kwargs)
        except GetterError as ex:
            message = L(CANT_CONTACT_PROVIDER) if ex.connection_error else L(
                HTTP_ERROR).format(ex.message)
            raise ProviderError(message, ex.cause)

    def log(self, message, level=xbmc.LOGDEBUG):
        if self.mediatype:
            log(message, level, tag='%s:%s' % (self.name.sort, self.mediatype))
        else:
            log(message, level, tag='%s' % self.name.sort)

    def login(self):
        return False
Exemplo n.º 11
0
class ArtFilesAbstractProvider(object):
    __metaclass__ = ABCMeta
    # 13514 = Local art
    name = SortedDisplay('file:art', 13514)

    def buildimage(self, url, title, fromartistfolder=False):
        provider = ARTIST_INFOFOLDER_PROVIDER if fromartistfolder else self.name
        result = {'url': url, 'provider': provider, 'preview': url}
        result['title'] = title
        result['rating'] = SortedDisplay(0, '')
        result['size'] = SortedDisplay(0, '')
        result['language'] = 'xx'
        return result

    def getextra(self, path, exacttypes, thumbs=False):
        arttype = 'thumb' if thumbs else 'fanart'
        extradir = 'extrathumbs' if thumbs else 'extrafanart'
        sep = get_pathsep(path)
        missing, nextno = getopentypes(exacttypes, arttype)
        path += extradir + sep
        _, files = xbmcvfs.listdir(path)
        files.sort(key=natural_sort)
        result = {}
        for filename in files:
            check_filename = filename.lower()
            if not check_filename.endswith(ARTWORK_EXTS):
                continue
            popped = missing.pop(0) if missing else None
            nexttype = popped if popped else format_arttype(arttype, nextno)
            result[nexttype] = self.buildimage(path + filename,
                                               extradir + sep + filename)
            if not popped:
                nextno += 1
        return result
Exemplo n.º 12
0
class VideoFileAbstractProvider(object):
    __metaclass__ = ABCMeta
    name = SortedDisplay('video:thumb', VIDEO_FILE)

    def build_video_thumbnail(self, path):
        url = build_video_thumbnail_path(path)
        return {'url': url, 'rating': SortedDisplay(0, ''), 'language': 'xx', 'title': L(VIDEO_FILE_THUMB),
            'provider': self.name, 'size': SortedDisplay(0, ''), 'preview': url}
Exemplo n.º 13
0
def _get_imagesize(arttype):
    if arttype in ('hdtvlogo', 'hdclearart', 'hdmovielogo', 'hdmovieclearart', 'hdmusiclogo'):
        return SortedDisplay(800, 'HD')
    elif arttype in ('clearlogo', 'clearart', 'movielogo', 'movieart', 'musiclogo'):
        return SortedDisplay(400, 'SD')
    elif arttype in ('tvbanner', 'seasonbanner', 'moviebanner', 'musicbanner'):
        return SortedDisplay(1000, '1000x185')
    elif arttype in ('showbackground', 'moviebackground', 'artistbackground'):
        return SortedDisplay(1920, '1920x1080')
    elif arttype in ('tvposter', 'seasonposter', 'movieposter'):
        return SortedDisplay(1426, '1000x1426')
    elif arttype in ('tvthumb', 'seasonthumb'):
        return SortedDisplay(500, '500x281 or 1000x562')
    elif arttype == 'characterart':
        return SortedDisplay(512, '512x512')
    elif arttype == 'moviethumb':
        return SortedDisplay(1000, '1000x562')
    elif arttype in ('moviedisc', 'cdart', 'artistthumb', 'albumcover'):
        return SortedDisplay(1000, '1000x1000')
    return SortedDisplay(0, '')
Exemplo n.º 14
0
 def _build_image(self, url, size, title=None):
     result = {
         'provider': self.name,
         'url': url,
         'preview': url + '/preview',
         'size': size,
         'language': None,
         'rating': SortedDisplay(5.1 if title == 'track' else 5.0, '')
     }
     if title:
         result['title'] = title
     return result
Exemplo n.º 15
0
def _get_imagesize(arttype):
    if arttype in ('strTrackThumb', 'strAlbumThumb', 'strArtistThumb',
                   'strAlbumThumbBack'):
        return SortedDisplay(500, '500-800')
    if arttype in ('strAlbumCDart', ):
        return SortedDisplay(500, '500 or 1000')
    if arttype in ('strArtistLogo', ):
        return SortedDisplay(400, '400x155 or 800x310')
    if arttype in ('strArtistBanner', ):
        return SortedDisplay(1000, '1000x185')
    if arttype in ('strArtistClearart', 'strArtistWideThumb'):
        return SortedDisplay(1000, '1000x562')
    if arttype in ('strArtistFanart', 'strArtistFanart2', 'strArtistFanart3'):
        return SortedDisplay(1280, '1280x720 or 1920x1080')
    if arttype in ('strAlbumSpine', ):
        return (SortedDisplay(700, '700x35'))
    return SortedDisplay(0, '')
Exemplo n.º 16
0
def _sort_images(basearttype, imagelist, mediasource, mediatype):
    # 1. Language, preferring fanart with no language/title if configured
    # 2. Match discart to media source
    # 3. Preferred source
    # 4. Size (in 200px groups), up to preferredsize
    # 5. Rating
    imagelist.sort(key=lambda image: image['rating'].sort, reverse=True)
    imagelist.sort(key=_size_sort, reverse=True)
    if basearttype == 'discart':
        if mediasource != 'unknown':
            imagelist.sort(key=lambda image: 0 if image.get(
                'subtype', SortedDisplay(None, '')).sort == mediasource else 1)
    imagelist.sort(key=lambda image: _preferredsource_sort(image, mediatype),
                   reverse=True)
    imagelist.sort(key=lambda image: _imagelanguage_sort(image, basearttype))
Exemplo n.º 17
0
class NFOFileAbstractProvider(object):
    __metaclass__ = ABCMeta
    name = SortedDisplay('file:nfo', NFO_FILE)

    def build_resultimage(self, url, title):
        if isinstance(url, unicode):
            url = url.encode('utf-8')
        if url.startswith('http'):
            url = urllib.quote(url, safe="%/:=&?~#+!$,;'@()*[]")
        resultimage = {'url': url, 'provider': self.name, 'preview': url}
        resultimage['title'] = '<{0}>'.format(title)
        resultimage['rating'] = SortedDisplay(0, '')
        resultimage['size'] = SortedDisplay(0, '')
        resultimage['language'] = 'xx'
        return resultimage
Exemplo n.º 18
0
class TheAudioDBSearch(AbstractProvider):
    name = SortedDisplay('theaudiodb.com:search', 'TheAudioDB.com search')
    contenttype = 'application/json'

    def __init__(self):
        super(TheAudioDBSearch, self).__init__()
        # s=[artist], t=[track title]
        self.url_trackby_artistandtrack = 'https://www.theaudiodb.com/api/v1/json/{0}/searchtrack.php'

    def get_data(self, url, params=None):
        apikey = settings.get_apikey('tadb')
        if not apikey:
            raise build_key_error('tadb')
        result = cache.cacheFunction(self._get_data,
                                     url.format(settings.get_apikey('tadb')),
                                     params)
        return result if result != 'Empty' else None

    def _get_data(self, url, params=None):
        self.log('uncached', xbmc.LOGINFO)
        if params is None:
            params = {}
        response = self.doget(url, params=params)
        if response is None:
            raise build_key_error('tadb')
        return 'Empty' if response is None else response.json()

    def search(self, query, mediatype):
        if mediatype != mediatypes.MUSICVIDEO:
            return []
        query = query.split(' - ', 1)
        if len(query) != 2:
            return []
        data = self.get_data(self.url_trackby_artistandtrack, {
            's': query[0],
            't': query[1]
        })
        if not data or not data.get('track'):
            return []

        return [{
            'label': item['strArtist'] + ' - ' + item['strTrack'],
            'uniqueids': {
                'mbtrack': item['strMusicBrainzID'],
                'mbartist': item['strMusicBrainzArtistID'],
                'mbgroup': item['strMusicBrainzAlbumID']
            }
        } for item in data['track']]
Exemplo n.º 19
0
 def _get_images(self, data):
     result = {}
     for arttype, artlist in data.iteritems():
         if arttype not in self.artmap:
             continue
         for image in artlist:
             generaltype = self.artmap[arttype]
             if generaltype == 'poster' and not _get_imagelanguage(arttype, image):
                 generaltype = 'keyart'
             if artlist and generaltype not in result:
                 result[generaltype] = []
             url = urllib.quote(image['url'], safe="%/:=&?~#+!$,;'@()*[]")
             resultimage = self.build_image(url, arttype, image)
             if arttype == 'moviedisc':
                 display = self.disctitles.get(image['disc_type']) or image['disc_type']
                 resultimage['subtype'] = SortedDisplay(image['disc_type'], display)
             result[generaltype].append(resultimage)
     return result
Exemplo n.º 20
0
class TheMovieDBSearch(AbstractProvider):
    name = SortedDisplay('themoviedb.org:search', 'The Movie Database search')
    contenttype = 'application/json'

    searchurl = 'https://api.themoviedb.org/3/search/{0}'
    tvexternalidsurl = 'https://api.themoviedb.org/3/tv/{0}/external_ids'
    typemap = {mediatypes.MOVIESET: 'collection'}

    def get_data(self, url, params=None):
        result = cache.cacheFunction(self._get_data, url, params)
        return result if result != 'Empty' else None

    def _get_data(self, url, params=None):
        apikey = settings.get_apikey('tmdb')
        if not apikey:
            raise build_key_error('tmdb')
        self.log('uncached', xbmc.LOGINFO)
        if params is None:
            params = {'api_key': apikey}
        else:
            params = dict(params, api_key=apikey)
        response = self.doget(url, params=params)
        return 'Empty' if response is None else response.json()

    def login(self):
        raise build_key_error('tmdb')

    def search(self, query, mediatype):
        if mediatype not in self.typemap:
            return []
        url = self.searchurl.format(self.typemap[mediatype])
        data = self.get_data(url, {'query': query})
        if not data or 'results' not in data:
            return []

        return [{'label': item['name'], 'uniqueids': {'tmdb': item['id']}} for item in data['results']]

    def get_more_uniqueids(self, uniqueids, mediatype):
        if mediatype != mediatypes.TVSHOW or 'tvdb' in uniqueids:
            return {}
        mediaid = get_mediaid(uniqueids)
        url = self.tvexternalidsurl.format(mediaid)
        data = self.get_data(url)
        return {} if not data or not data.get('tvdb_id') else {'tvdb': data['tvdb_id']}
Exemplo n.º 21
0
 def process_data(self, data):
     result = {}
     for arttype, artlist in data.iteritems():
         if arttype not in self.artmap:
             continue
         previewbit = 'w300' if arttype in ('backdrops', 'stills') else 'w342'
         for image in artlist:
             resultimage = {'url': self.baseurl + 'original' + image['file_path'], 'provider': self.name}
             resultimage['preview'] = self.baseurl + previewbit + image['file_path']
             resultimage['language'] = image['iso_639_1'] if image['iso_639_1'] != 'xx' else None
             resultimage['rating'] = self._get_rating(image)
             sortsize = image['width' if arttype != 'posters' else 'height']
             resultimage['size'] = SortedDisplay(sortsize, '{0}x{1}'.format(image['width'], image['height']))
             generaltype = self.artmap[arttype]
             if settings.use_tmdb_keyart and generaltype == 'poster' and not resultimage['language']:
                 generaltype = 'keyart'
             if generaltype not in result:
                 result[generaltype] = []
             result[generaltype].append(resultimage)
     return result
Exemplo n.º 22
0
def tag_forcedandexisting_art(availableart, forcedart, existingart):
    typeinsert = {}
    for exacttype, artlist in sorted(
            forcedart.iteritems(),
            key=lambda arttype: natural_sort(arttype[0])):
        arttype = info.get_basetype(exacttype)
        if arttype not in availableart:
            availableart[arttype] = artlist
        else:
            for image in artlist:
                match = next((available for available in availableart[arttype]
                              if available['url'] == image['url']), None)
                if match:
                    if 'title' in image and 'title' not in match:
                        match['title'] = image['title']
                    match['second provider'] = image['provider'].display
                else:
                    typeinsert[arttype] = typeinsert[
                        arttype] + 1 if arttype in typeinsert else 0
                    availableart[arttype].insert(typeinsert[arttype], image)

    typeinsert = {}
    for exacttype, existingurl in existingart.iteritems():
        arttype = info.get_basetype(exacttype)
        if arttype in availableart:
            match = next((available for available in availableart[arttype]
                          if available['url'] == existingurl), None)
            if match:
                match['preview'] = existingurl
                match['existing'] = True
            else:
                typeinsert[arttype] = typeinsert[
                    arttype] + 1 if arttype in typeinsert else 0
                image = {
                    'url': existingurl,
                    'preview': existingurl,
                    'title': exacttype,
                    'existing': True,
                    'provider': SortedDisplay('current', L(CURRENT_ART))
                }
                availableart[arttype].insert(typeinsert[arttype], image)
Exemplo n.º 23
0
    def get_images(self, uniqueids, types=None):
        if not settings.get_apienabled('tvdb'):
            return {}
        if types is not None and not self.provides(types):
            return {}
        mediaid = get_mediaid(uniqueids)
        if not mediaid:
            return {}
        result = {}
        languages = base.languages
        # Useful fanart can be hidden by the language filter, try a few of the most frequently used
        flanguages = ['en', 'de', 'fr', 'es', 'ru']
        flanguages.extend(lang for lang in languages if lang not in flanguages)
        for arttype in self.artmap:
            if types and not typematches(self.artmap[arttype], types):
                continue
            arttype_error = False
            for language in languages if arttype != 'fanart' else flanguages:
                generaltype = self.artmap[arttype]
                data = self.get_data(mediaid, arttype, language)
                if not data:
                    continue
                isseason = arttype.startswith('season')
                if not isseason:
                    if generaltype not in result:
                        result[generaltype] = []
                for image in data['data']:
                    if not image.get('fileName'
                                     ) or isseason and not image.get('subKey'):
                        continue
                    ntype = generaltype
                    if isseason:
                        try:
                            int(image['subKey'])
                        except ValueError:
                            if arttype_error:
                                continue
                            arttype_error = True
                            self.log(
                                "Provider returned unexpected content and '{0}' "
                                .format(arttype) +
                                "artwork could not be processed:\n" +
                                "expected a season number but got '{0}'".
                                format(image['subKey']), xbmc.LOGWARNING)
                            continue
                        ntype = ntype % image['subKey']
                        if ntype not in result:
                            result[ntype] = []

                    # skip duplicates
                    if any(x for x in result[ntype]
                           if x['url'].endswith(image['fileName'])):
                        continue

                    resultimage = {'provider': self.name}
                    resultimage['url'] = self.imageurl_base + image['fileName']
                    resultimage['preview'] = self.imageurl_base + (
                        image['thumbnail'] or '_cache/' + image['fileName'])
                    resultimage[
                        'language'] = language if shouldset_imagelanguage(
                            image) else None
                    resultimage['rating'] = self._get_rating(image)
                    if arttype in ('series', 'seasonwide'):
                        resultimage['size'] = SortedDisplay(758, '758x140')
                    elif arttype == 'season':
                        resultimage['size'] = SortedDisplay(1000, '680x1000')
                    else:
                        resultimage['size'] = parse_sortsize(image, arttype)
                    result[ntype].append(resultimage)
        return result
Exemplo n.º 24
0
class TheAudioDBAbstractProvider(AbstractImageProvider):
    name = SortedDisplay('theaudiodb.com', 'TheAudioDB.com')
    contenttype = 'application/json'

    def __init__(self):
        super(TheAudioDBAbstractProvider, self).__init__()
        # url param i=MB track/album/artist ID
        self.artmap = {
            'mbtrack': {
                'datakey': 'track',
                'artmap': {
                    'strTrackThumb': 'thumb'
                },
                'url':
                'https://www.theaudiodb.com/api/v1/json/{0}/track-mb.php'
            },
            'mbgroup': {
                'datakey': 'album',
                'artmap': {
                    'strAlbumThumb': 'thumb',
                    'strAlbumCDart': 'discart',
                    'strAlbumThumbBack': 'back',
                    'strAlbumSpine': 'spine'
                },
                'url':
                'https://www.theaudiodb.com/api/v1/json/{0}/album-mb.php'
            },
            'mbartist': {
                'datakey': 'artists',
                'artmap': {
                    'strArtistThumb': 'thumb',
                    'strArtistLogo': 'clearlogo',
                    'strArtistBanner': 'banner',
                    'strArtistFanart': 'fanart',
                    'strArtistFanart2': 'fanart',
                    'strArtistFanart3': 'fanart',
                    'strArtistClearart': 'clearart',
                    'strArtistWideThumb': 'landscape'
                },
                'url':
                'https://www.theaudiodb.com/api/v1/json/{0}/artist-mb.php'
            }
        }
        self.provtypes = set(x for data in self.artmap.values()
                             for x in data['artmap'].values())

    def get_data(self, url, params):
        result = cache.cacheFunction(self._get_data,
                                     url.format(settings.get_apikey('tadb')),
                                     params)
        return result if result != 'Empty' else None

    def _get_data(self, url, params):
        apikey = settings.get_apikey('tadb')
        if not apikey:
            raise build_key_error('tadb')
        self.log('uncached', xbmc.LOGINFO)
        response = self.doget(url, params=params)
        if response is None:
            raise build_key_error('tadb')
        return 'Empty' if response is None else json.loads(response.text,
                                                           cls=UTF8JSONDecoder)

    def _build_image(self, url, size, title=None):
        result = {
            'provider': self.name,
            'url': url,
            'preview': url + '/preview',
            'size': size,
            'language': None,
            'rating': SortedDisplay(5.1 if title == 'track' else 5.0, '')
        }
        if title:
            result['title'] = title
        return result
Exemplo n.º 25
0
class KyraDBMovieProvider(AbstractImageProvider):
    name = SortedDisplay('kyradb.com', 'KyraDB.com')
    contenttype = 'application/json'
    mediatype = mediatypes.MOVIE

    apiurl = 'https://www.kyradb.com/api10/movie/{0}/images/{1}'
    animatedtypes = ('animatedposter', 'animatedkeyart', 'animatedfanart')
    provtypes = animatedtypes + ('characterart', )

    def provides(self, types):
        return any(x in self.provtypes for x in types)

    def get_images(self, uniqueids, types=None):
        if not settings.get_apienabled('kyradb'):
            return {}
        mediaid = get_mediaid(uniqueids)
        if not mediaid:
            return {}
        if types is None:
            types = self.provtypes

        result = {}
        if any(x in self.animatedtypes for x in types):
            result.update(self._get_animated_images(mediaid))
        if 'characterart' in types:
            characterart = self._get_characterart(mediaid)
            if characterart:
                result['characterart'] = characterart

        return result

    def _get_animated_images(self, mediaid):
        data = self.get_data(mediaid, 'animated')
        if not data:
            return {}
        baseposter = data['base_url_posters']
        basefanart = data['base_url_backgrounds']
        result = {}
        for poster in data['posters']:
            newposter = {
                'url':
                baseposter + '/' + poster['name'],
                'language':
                get_language(poster.get('language', None)),
                'rating':
                SortedDisplay(poster['likes'],
                              '{0} likes'.format(poster['likes'])),
                'size':
                SortedDisplay(poster['height'], poster['resolution']),
                'provider':
                self.name,
                'preview':
                baseposter + '/' + poster['name']
            }

            arttype = 'animatedposter' if newposter[
                'language'] else 'animatedkeyart'
            if arttype not in result:
                result[arttype] = []
            result[arttype].append(newposter)
        for fanart in data['backgrounds']:
            if 'animatedfanart' not in result:
                result['animatedfanart'] = []
            result['animatedfanart'].append({
                'url':
                basefanart + '/' + fanart['name'],
                'language':
                None,
                'rating':
                SortedDisplay(fanart['likes'],
                              '{0} likes'.format(fanart['likes'])),
                'size':
                SortedDisplay(fanart['height'], fanart['resolution']),
                'provider':
                self.name,
                'preview':
                basefanart + '/' + fanart['name']
            })

        return result

    def _get_characterart(self, mediaid):
        data = self.get_data(mediaid, 'characterart')
        if not data:
            return {}
        baseurl = data['base_url_character_art']
        result = []
        for characterart in data['character_art']:
            result.append({
                'url':
                baseurl + '/' + characterart['name'],
                'language':
                None,
                'rating':
                SortedDisplay(characterart['likes'],
                              '{0} likes'.format(characterart['likes'])),
                'size':
                SortedDisplay(characterart['height'],
                              characterart['resolution']),
                'provider':
                self.name,
                'preview':
                baseurl + '/' + characterart['name']
            })

        return result

    def get_data(self, mediaid, urltype):
        result = cache.cacheFunction(self._get_data, mediaid, urltype)
        return result if result != 'Empty' else None

    def _get_data(self, mediaid, urltype):
        if not settings.kyradb_user_apikey or not settings.kyradb_userkey:
            raise ProviderError(
                "KyraDB API key and User key is required for artwork from KyraDB: "
                + str(self.provtypes))
        headers = {
            'Apikey': settings.kyradb_user_apikey,
            'Userkey': settings.kyradb_userkey
        }
        self.log('uncached', xbmc.LOGINFO)
        response = self.doget(self.apiurl.format(mediaid, urltype),
                              headers=headers)
        result = json.loads(
            response.text,
            cls=UTF8JSONDecoder) if response is not None else None
        if result and result.get('error'):
            if result['error'] != 4:
                # 4: "No results"
                raise ProviderError(result['message'])
            result = None
        return 'Empty' if result is None else result
Exemplo n.º 26
0
class TheTVDBProvider(AbstractImageProvider):
    name = SortedDisplay('thetvdb.com', 'TheTVDB.com')
    mediatype = mediatypes.TVSHOW
    contenttype = 'application/vnd.thetvdb.v2.1.0'

    apiurl = 'https://api.thetvdb.com/series/%s/images/query'
    loginurl = 'https://api.thetvdb.com/login'
    imageurl_base = 'https://www.thetvdb.com/banners/'

    artmap = {
        'fanart': 'fanart',
        'poster': 'poster',
        'season': mediatypes.SEASON + '.%s.poster',
        'seasonwide': mediatypes.SEASON + '.%s.banner',
        'series': 'banner'
    }

    def get_data(self, mediaid, arttype, language):
        result = cache.cacheFunction(self._get_data, mediaid, arttype,
                                     language)
        return result if result != 'Empty' else None

    def _get_data(self, mediaid, arttype, language):
        if not settings.get_apikey('tvdb'):
            raise build_key_error('tvdb')
        self.log('uncached', xbmc.LOGINFO)
        getparams = {
            'params': {
                'keyType': arttype
            },
            'headers': {
                'Accept-Language': language
            }
        }
        response = self.doget(self.apiurl % mediaid, **getparams)
        return 'Empty' if response is None else json.loads(response.text,
                                                           cls=UTF8JSONDecoder)

    def _get_rating(self, image):
        if image['ratingsInfo']['count']:
            info = image['ratingsInfo']
            rating = info['average']
            if info['count'] < 5:
                # Reweigh ratings, decrease difference from 5
                rating = 5 + (rating - 5) * sin(info['count'] / pi)
            return SortedDisplay(rating,
                                 '{0:.1f} stars'.format(info['average']))
        else:
            return SortedDisplay(5, 'Not rated')

    def get_images(self, uniqueids, types=None):
        if not settings.get_apienabled('tvdb'):
            return {}
        if types is not None and not self.provides(types):
            return {}
        mediaid = get_mediaid(uniqueids)
        if not mediaid:
            return {}
        result = {}
        languages = base.languages
        # Useful fanart can be hidden by the language filter, try a few of the most frequently used
        flanguages = ['en', 'de', 'fr', 'es', 'ru']
        flanguages.extend(lang for lang in languages if lang not in flanguages)
        for arttype in self.artmap:
            if types and not typematches(self.artmap[arttype], types):
                continue
            arttype_error = False
            for language in languages if arttype != 'fanart' else flanguages:
                generaltype = self.artmap[arttype]
                data = self.get_data(mediaid, arttype, language)
                if not data:
                    continue
                isseason = arttype.startswith('season')
                if not isseason:
                    if generaltype not in result:
                        result[generaltype] = []
                for image in data['data']:
                    if not image.get('fileName'
                                     ) or isseason and not image.get('subKey'):
                        continue
                    ntype = generaltype
                    if isseason:
                        try:
                            int(image['subKey'])
                        except ValueError:
                            if arttype_error:
                                continue
                            arttype_error = True
                            self.log(
                                "Provider returned unexpected content and '{0}' "
                                .format(arttype) +
                                "artwork could not be processed:\n" +
                                "expected a season number but got '{0}'".
                                format(image['subKey']), xbmc.LOGWARNING)
                            continue
                        ntype = ntype % image['subKey']
                        if ntype not in result:
                            result[ntype] = []

                    # skip duplicates
                    if any(x for x in result[ntype]
                           if x['url'].endswith(image['fileName'])):
                        continue

                    resultimage = {'provider': self.name}
                    resultimage['url'] = self.imageurl_base + image['fileName']
                    resultimage['preview'] = self.imageurl_base + (
                        image['thumbnail'] or '_cache/' + image['fileName'])
                    resultimage[
                        'language'] = language if shouldset_imagelanguage(
                            image) else None
                    resultimage['rating'] = self._get_rating(image)
                    if arttype in ('series', 'seasonwide'):
                        resultimage['size'] = SortedDisplay(758, '758x140')
                    elif arttype == 'season':
                        resultimage['size'] = SortedDisplay(1000, '680x1000')
                    else:
                        resultimage['size'] = parse_sortsize(image, arttype)
                    result[ntype].append(resultimage)
        return result

    def login(self):
        response = self.getter.session.post(
            self.loginurl,
            json={'apikey': settings.get_apikey('tvdb')},
            headers={
                'Content-Type': 'application/json',
                'User-Agent': settings.useragent
            },
            timeout=15)
        if response is not None and response.status_code == 401:
            raise build_key_error('tvdb')
        response.raise_for_status()
        if not response or not response.headers['Content-Type'].startswith(
                'application/json'):
            raise ProviderError("Provider returned unexpected content")
        self.getter.session.headers[
            'authorization'] = 'Bearer %s' % response.json()['token']
        return True

    def provides(self, types):
        types = set(
            x if not x.startswith('season.') else re.sub(r'[\d]', '%s', x)
            for x in types)
        return any(x in types for x in self.artmap.values())
Exemplo n.º 27
0
class TheMovieDBAbstractProvider(AbstractImageProvider):
    __metaclass__ = ABCMeta
    contenttype = 'application/json'

    name = SortedDisplay('themoviedb.org', 'The Movie Database')
    _baseurl = None
    artmap = {}

    @property
    def baseurl(self):
        if not self._baseurl:
            apikey = settings.get_apikey('tmdb')
            if not apikey:
                raise build_key_error('tmdb')
            response = self.doget(cfgurl, params={'api_key': apikey})
            if response is None:
                return
            self._baseurl = response.json()['images']['secure_base_url']
        return self._baseurl

    def _get_rating(self, image):
        if image['vote_count']:
            # Reweigh ratings, increase difference from 5
            rating = image['vote_average']
            rating = 5 + (rating - 5) * 2
            return SortedDisplay(rating, '{0:.1f} stars'.format(image['vote_average']))
        else:
            return SortedDisplay(5, 'Not rated')

    def get_data(self, url):
        result = cache.cacheFunction(self._get_data, url)
        return result if result != 'Empty' else None

    def _get_data(self, url):
        apikey = settings.get_apikey('tmdb')
        if not apikey:
            raise build_key_error('tmdb')
        self.log('uncached', xbmc.LOGINFO)
        response = self.doget(url, params={'api_key': apikey})
        return 'Empty' if response is None else json.loads(response.text, cls=UTF8JSONDecoder)

    def login(self):
        raise build_key_error('tmdb')

    def process_data(self, data):
        result = {}
        for arttype, artlist in data.iteritems():
            if arttype not in self.artmap:
                continue
            previewbit = 'w300' if arttype in ('backdrops', 'stills') else 'w342'
            for image in artlist:
                resultimage = {'url': self.baseurl + 'original' + image['file_path'], 'provider': self.name}
                resultimage['preview'] = self.baseurl + previewbit + image['file_path']
                resultimage['language'] = image['iso_639_1'] if image['iso_639_1'] != 'xx' else None
                resultimage['rating'] = self._get_rating(image)
                sortsize = image['width' if arttype != 'posters' else 'height']
                resultimage['size'] = SortedDisplay(sortsize, '{0}x{1}'.format(image['width'], image['height']))
                generaltype = self.artmap[arttype]
                if settings.use_tmdb_keyart and generaltype == 'poster' and not resultimage['language']:
                    generaltype = 'keyart'
                if generaltype not in result:
                    result[generaltype] = []
                result[generaltype].append(resultimage)
        return result

    def provides(self, types):
        return any(x in types for x in self.artmap.values())
Exemplo n.º 28
0
 def build_video_thumbnail(self, path):
     url = build_video_thumbnail_path(path)
     return {'url': url, 'rating': SortedDisplay(0, ''), 'language': 'xx', 'title': L(VIDEO_FILE_THUMB),
         'provider': self.name, 'size': SortedDisplay(0, ''), 'preview': url}
Exemplo n.º 29
0
class FanartTVAbstractProvider(AbstractImageProvider):
    __metaclass__ = ABCMeta
    api_section = None
    mediatype = None
    contenttype = 'application/json'

    name = SortedDisplay('fanart.tv', 'fanart.tv')
    apiurl = 'https://webservice.fanart.tv/v3/%s/%s'

    def get_images(self, uniqueids, types=None):
        if not settings.get_apienabled('fanarttv'):
            return {}
        if types is not None and not self.provides(types):
            return {}
        mediaid = get_mediaid(uniqueids, self.mediatype)
        if not mediaid or isinstance(mediaid, tuple) and not mediaid[0]:
            return {}
        data = self.get_data(mediaid[0] if isinstance(mediaid, tuple) else mediaid)
        if not data:
            return {}
        if self.mediatype == mediatypes.MUSICVIDEO:
            return self._get_images(data, mediaid)
        elif self.mediatype == mediatypes.ALBUM:
            if not data.get('albums', {}).get(mediaid):
                return {}
            return self._get_images(data['albums'][mediaid])
        else:
            return self._get_images(data)

    def get_data(self, mediaid):
        result = cache.cacheFunction(self._get_data, mediaid)
        return result if result != 'Empty' else None

    def _get_data(self, mediaid):
        apikey = settings.get_apikey('fanarttv')
        if not apikey:
            raise build_key_error('fanarttv')
        self.log('uncached', xbmc.LOGINFO)
        headers = {'api-key': apikey}
        if settings.fanarttv_clientkey:
            headers['client-key'] = settings.fanarttv_clientkey
        response = self.doget(self.apiurl % (self.api_section, mediaid), headers=headers)
        return 'Empty' if response is None else json.loads(response.text, cls=UTF8JSONDecoder)

    def login(self):
        raise build_key_error('fanarttv')

    def build_image(self, url, arttype, image, likediv=5.0):
        result = {'url': url, 'provider': self.name}
        result['preview'] = url.replace('.fanart.tv/fanart/', '.fanart.tv/preview/')
        result['rating'] = SortedDisplay(5.25 + int(image['likes']) / float(likediv), '{0} likes'.format(image['likes']))
        result['size'] = _get_imagesize(arttype)
        result['language'] = _get_imagelanguage(arttype, image)
        return result

    @abstractmethod
    def _get_images(self, data, mediaid=None):
        pass

    @abstractmethod
    def provides(self, types):
        pass
Exemplo n.º 30
0
import os
import xbmcvfs
from abc import ABCMeta

from lib.libs import mediatypes
from lib.libs.addonsettings import settings
from lib.libs.mediainfo import arttype_matches_base, format_arttype, find_central_infodir
from lib.libs.utils import SortedDisplay, natural_sort, get_movie_path_list, get_pathsep, \
    iter_possible_cleannames, parent_dir

ARTWORK_EXTS = ('.jpg', '.png', '.gif')
ARTIST_INFOFOLDER_PROVIDER = SortedDisplay('file:art', 20223)

ARTTYPE_MAXLENGTH = 30


class ArtFilesAbstractProvider(object):
    __metaclass__ = ABCMeta
    # 13514 = Local art
    name = SortedDisplay('file:art', 13514)

    def buildimage(self, url, title, fromartistfolder=False):
        provider = ARTIST_INFOFOLDER_PROVIDER if fromartistfolder else self.name
        result = {'url': url, 'provider': provider, 'preview': url}
        result['title'] = title
        result['rating'] = SortedDisplay(0, '')
        result['size'] = SortedDisplay(0, '')
        result['language'] = 'xx'
        return result

    def getextra(self, path, exacttypes, thumbs=False):