예제 #1
0
    def _show_search(self, show, request_language='en'):
        """Use TMDB API to search for a show.

        :param show: The show name that's searched for as a string
        :param request_language: Language in two letter code. TMDB fallsback to en itself.
        :return: A list of Show objects.
        """
        try:
            # get paginated pages
            page = 1
            last = 1
            results = []
            while page <= last:
                search_result = self.tmdb.Search().tv(
                    query=show, language=request_language, page=page)
                last = search_result.get('total_pages', 0)
                results += search_result.get('results')
                page += 1
        except RequestException as error:
            raise IndexerUnavailable(
                'Show search failed using indexer TMDB. Cause: {cause}'.format(
                    cause=error))

        if not results:
            raise IndexerShowNotFound(
                'Show search failed in getting a result with reason: Not found'
            )

        return results
예제 #2
0
    def _get_show_by_id(self, tmdb_id, request_language='en', extra_info=None):
        """Retrieve tmdb show information by tmdb id.

        :param tmdb_id: The show's tmdb id
        :param request_language: Language to get the show in
        :type request_language: string or unicode
        :extra_info: Extra details of the show to get (e.g. ['content_ratings', 'external_ids'])
        :type extra_info: list, tuple or None
        :return: An ordered dict with the show searched for.
        """
        if extra_info and isinstance(extra_info, (list, tuple)):
            extra_info = ','.join(extra_info)

        log.debug('Getting all show data for {0}', tmdb_id)
        try:
            results = self.tmdb.TV(tmdb_id).info(
                language='{0}'.format(request_language),
                append_to_response=extra_info)
        except RequestException as error:
            raise IndexerUnavailable(
                'Show info retrieval failed using indexer TMDB. Cause: {cause!r}'
                .format(cause=error))

        if not results:
            return

        mapped_results = self._map_results(results, self.series_map, '|')
        return OrderedDict({'series': mapped_results})
예제 #3
0
    def _get_show_by_id(self, tvdb_id, request_language='de'):  # pylint: disable=unused-argument
        """Retrieve Glotz show information by tvdb id.

        :param tvdb_id: The shows tvdb id
        :return: An ordered dict with the show searched for.
        """
        results = None
        if tvdb_id:
            log.debug('Getting all show data for {0}', tvdb_id)

            try:
                results = self.glotz_api.get_show(tvdb_id=tvdb_id, language=request_language)
            except IDNotFound as error:
                raise IndexerShowNotFound(
                    'Show search failed in getting a result with reason: {0}'.format(error.value)
                )

            except BaseError as error:
                raise IndexerUnavailable('Show search failed in getting a result with error: {0!r}'.format(error))

        if results:
            log.debug('Getting aliases for show {0}', tvdb_id)
            results.aliases = self.glotz_api.get_show_aliases(tvdb_id)

        if not results:
            log.debug('Getting show data for {0} on Glotz failed', tvdb_id)
            return

        mapped_results = self._map_results(results, self.series_map)

        return OrderedDict({'series': mapped_results})
예제 #4
0
    def _get_show_by_id(self, tvdbv2_id, request_language='en'):  # pylint: disable=unused-argument
        """Retrieve tvdbv2 show information by tvdbv2 id, or if no tvdbv2 id provided by passed external id.

        :param tvdbv2_id: The shows tvdbv2 id
        :return: An ordered dict with the show searched for.
        """
        results = None
        if tvdbv2_id:
            log.debug('Getting all show data for {0}', tvdbv2_id)
            try:
                results = self.config['session'].series_api.series_id_get(
                    tvdbv2_id, accept_language=request_language)
            except ApiException as error:
                if error.status == 401:
                    raise IndexerAuthFailed(
                        'Authentication failed, possible bad API key. Reason: {reason} ({status})'
                        .format(reason=error.reason, status=error.status))
                if error.status == 404:
                    raise IndexerShowNotFound(
                        'Show search failed in getting a result with reason: {reason} ({status})'
                        .format(reason=error.reason, status=error.status))
                raise IndexerUnavailable(error.reason)

        if not results:
            return

        if not getattr(results.data, 'series_name', None):
            raise IndexerShowNotFoundInLanguage(
                'Missing attribute series_name, cant index in language: {0}'.
                format(request_language), request_language)

        mapped_results = self._map_results(results, self.series_map, '|')
        return OrderedDict({'series': mapped_results})
예제 #5
0
    def _get_show_by_id(self, tvmaze_id, request_language='en'):  # pylint: disable=unused-argument
        """
        Retrieve tvmaze show information by tvmaze id, or if no tvmaze id provided by passed external id.

        :param tvmaze_id: The shows tvmaze id
        :return: An ordered dict with the show searched for.
        """
        results = None
        if tvmaze_id:
            log.debug('Getting all show data for {0}', tvmaze_id)

            try:
                results = self.tvmaze_api.get_show(maze_id=tvmaze_id)
            except ShowNotFound as error:
                # Use error.value because TVMaze API exceptions may be utf-8 encoded when using __str__
                raise IndexerShowNotFound(
                    'Show search failed in getting a result with reason: {0}'.format(error.value)
                )
            except BaseError as error:
                raise IndexerUnavailable('Show search failed in getting a result with error: {0!r}'.format(error))

        if not results:
            return

        mapped_results = self._map_results(results, self.series_map)
        return OrderedDict({'series': mapped_results})
예제 #6
0
파일: api.py 프로젝트: reconman/Medusa
    def __init__(self, *args, **kwargs):  # pylint: disable=too-many-locals,too-many-arguments
        """Tmdb api constructor."""
        super(Tmdb, self).__init__(*args, **kwargs)

        self.tmdb = tmdb
        self.tmdb.API_KEY = TMDB_API_KEY
        self.tmdb.REQUESTS_SESSION = self.config['session']
        self.tmdb_configuration = self.tmdb.Configuration()
        try:
            self.response = self.tmdb_configuration.info()
        except (AttributeError, RequestException) as e:
            raise IndexerUnavailable('Indexer TMDB is unavailable at this time. Cause: {cause}'.format(cause=e))

        self.config['artwork_prefix'] = '{base_url}{image_size}{file_path}'

        # An api to indexer series/episode object mapping
        self.series_map = [
            ('id', 'id'),
            ('status', 'status'),
            ('seriesname', 'name'),
            ('aliasnames', 'original_name'),
            ('overview', 'overview'),
            ('firstaired', 'air_date'),
            ('firstaired', 'first_air_date'),
            ('show_url', 'url'),
            ('episodenumber', 'episode_number'),
            ('seasonnumber', 'season_number'),
            ('dvd_episodenumber', 'dvd_episode_number'),
            ('airs_dayofweek', 'last_air_date'),
            ('lastupdated', 'last_updated'),
            ('networkid', 'network_id'),
            ('rating', 'vote_average'),
            ('genre', 'genres'),
            ('classification', 'type'),
            ('network', 'networks[0].name'),
            ('runtime', 'episode_run_time'),
            ('seasons', 'seasons'),
            ('poster_thumb', 'poster_path'),
            ('fanart', 'backdrop_path'),
            ('origin_country', 'origin_country'),
            ('external_ids', 'external_ids'),
        ]

        self.episodes_map = [
            ('id', 'id'),
            ('episodename', 'name'),
            ('overview', 'overview'),
            ('firstaired', 'air_date'),
            ('runtime', 'episode_run_time'),
            ('episodenumber', 'episode_number'),
            ('seasonnumber', 'season_number'),
            ('rating', 'vote_average'),
            ('filename', 'still_path'),
        ]
예제 #7
0
    def get_last_updated_series(self,
                                from_time,
                                weeks=1,
                                filter_show_list=None):
        """Retrieve a list with updated shows.

        :param from_time: epoch timestamp, with the start date/time as int
        :param weeks: number of weeks to get updates for.
        :param filter_show_list: Optional list of show objects, to use for filtering the returned list.
        :returns: A list of show_id's.
        """
        total_updates = []
        updates = True

        count = 0
        try:
            while updates and count < weeks:
                updates = self.config['session'].updates_api.updated_query_get(
                    from_time).data
                if updates:
                    last_update_ts = max(x.last_updated for x in updates)
                    if last_update_ts == from_time:
                        break

                    from_time = last_update_ts
                    total_updates += [int(_.id) for _ in updates]
                count += 1
        except ApiException as error:
            if error.status == 401:
                raise IndexerAuthFailed(
                    'Authentication failed, possible bad API key. Reason: {reason} ({status})'
                    .format(reason=error.reason, status=error.status))
            raise IndexerUnavailable(
                'Error connecting to TVDB API. Reason: {0}'.format(
                    error.reason))

        if total_updates and filter_show_list:
            new_list = []
            for show in filter_show_list:
                if show.indexerid in total_updates:
                    new_list.append(show.indexerid)
            total_updates = new_list

        return total_updates
예제 #8
0
    def _show_search(self, show, request_language='en'):
        """
        Use the TVMaze API to search for a show.

        :param show: The show name that's searched for as a string
        :param request_language: Language in two letter code. TVMaze fallsback to en itself.
        :return: A list of Show objects.
        """
        try:
            results = self.tvmaze_api.get_show_list(show)
        except ShowNotFound as error:
            # Use error.value because TVMaze API exceptions may be utf-8 encoded when using __str__
            raise IndexerShowNotFound(
                'Show search failed in getting a result with reason: {0}'.format(error.value)
            )
        except BaseError as error:
            raise IndexerUnavailable('Show search failed in getting a result with error: {0!r}'.format(error))

        return results
예제 #9
0
    def _show_search(self, show, request_language='de'):
        """
        Use the Glotz API to search for a show.

        :param show: The show name that's searched for as a string.
        :param request_language: Language in two letter code. As Glotz is primarily a German indexer, default is German
        :return: A list of Show objects.
        """
        try:
            results = self.glotz_api.get_show_list(show, request_language)
        except ShowNotFound as error:
            # Use error.value because Glotz API exceptions may be utf-8 encoded when using __str__
            raise IndexerShowNotFound(
                'Show search failed in getting a result with reason: {0}'.format(error.value)
            )
        except BaseError as error:
            raise IndexerUnavailable('Show search failed in getting a result with error: {0!r}'.format(error))

        return results
예제 #10
0
    def _show_search(self, show, request_language='en'):
        """Use the pytvdbv2 API to search for a show.

        @param show: The show name that's searched for as a string
        @return: A list of Show objects.
        """
        try:
            results = self.config['session'].search_api.search_series_get(
                name=show, accept_language=request_language)
        except ApiException as error:
            if error.status == 401:
                raise IndexerAuthFailed(
                    'Authentication failed, possible bad API key. Reason: {reason} ({status})'
                    .format(reason=error.reason, status=error.status))
            if error.status == 404:
                raise IndexerShowNotFound(
                    'Show search failed in getting a result with reason: {reason} ({status})'
                    .format(reason=error.reason, status=error.status))
            raise IndexerUnavailable(error.reason)

        return results
예제 #11
0
파일: api.py 프로젝트: reconman/Medusa
    def _show_search(self, series):
        """
        Use the Imdb API to search for a show.

        :param series: The series name that's searched for as a string
        :return: A list of Show objects.series_map
        """
        try:
            results = self.imdb_api.search_for_title(series)
        except LookupError as error:
            raise IndexerShowNotFound(
                'Could not get any results searching for {series} using indexer Imdb. Cause: {cause!r}'
                .format(series=series, cause=error))
        except (AttributeError, RequestException) as error:
            raise IndexerUnavailable(
                'Could not get any results searching for {series} using indexer Imdb. Cause: {cause!r}'
                .format(series=series, cause=error))

        if results:
            return results
        else:
            return None
예제 #12
0
파일: api.py 프로젝트: reconman/Medusa
    def _parse_actors(self, imdb_id):
        """Get and parse actors using the get_title_credits route.

        Actors are retrieved using t['show name]['_actors'].

        Any key starting with an underscore has been processed (not the raw
        data from the indexer)
        """
        log.debug('Getting actors for {0}', imdb_id)

        try:
            actors = self.imdb_api.get_title_credits(
                ImdbIdentifier(imdb_id).imdb_id)
        except LookupError as error:
            raise IndexerShowNotFound(
                'Could not find show {imdb_id} using indexer Imdb. Cause: {cause!r}'
                .format(imdb_id=imdb_id, cause=error))
        except (AttributeError, RequestException) as error:
            raise IndexerUnavailable(
                'Could not get actors for show {imdb_id} using indexer Imdb. Cause: {cause!r}'
                .format(imdb_id=imdb_id, cause=error))

        if not actors.get('credits') or not actors['credits'].get('cast'):
            return

        cur_actors = Actors()
        for order, cur_actor in enumerate(actors['credits']['cast'][:25]):
            save_actor = Actor()
            save_actor['id'] = cur_actor['id'].split('/')[-2]
            save_actor['image'] = cur_actor.get('image', {}).get('url', None)
            save_actor['name'] = cur_actor['name']
            save_actor['role'] = cur_actor['characters'][0] if cur_actor.get(
                'characters') else ''
            save_actor['sortorder'] = order
            cur_actors.append(save_actor)
        self._set_show_data(imdb_id, '_actors', cur_actors)
예제 #13
0
파일: api.py 프로젝트: reconman/Medusa
    def _get_episodes(self,
                      imdb_id,
                      detailed=True,
                      aired_season=None,
                      *args,
                      **kwargs):  # pylint: disable=unused-argument
        """Get all the episodes for a show by imdb id.

        :param imdb_id: Series imdb id.
        :return: An ordered dict with the show searched for. In the format of OrderedDict{"episode": [list of episodes]}
        """
        # Parse episode data
        log.debug('Getting all episodes of {0}', imdb_id)

        if aired_season:
            aired_season = [
                aired_season
            ] if not isinstance(aired_season, list) else aired_season

        series_id = imdb_id
        imdb_id = ImdbIdentifier(imdb_id).imdb_id

        try:
            # results = self.imdb_api.get_title_episodes(imdb_id)
            results = self.imdb_api.get_title_episodes(
                ImdbIdentifier(imdb_id).imdb_id)
        except LookupError as error:
            raise IndexerShowIncomplete(
                'Show episode search exception, '
                'could not get any episodes. Exception: {e!r}'.format(e=error))
        except (AttributeError, RequestException) as error:
            raise IndexerUnavailable(
                'Error connecting to Imdb api. Caused by: {0!r}'.format(error))

        if not results or not results.get('seasons'):
            return False

        absolute_number_counter = 1
        for season in results.get('seasons'):
            if aired_season and season.get('season') not in aired_season:
                continue

            for episode in season['episodes']:
                season_no, episode_no = episode.get('season'), episode.get(
                    'episode')

                if season_no is None or episode_no is None:
                    log.debug(
                        '{0}: Found incomplete episode with season: {1!r} and episode: {2!r})',
                        imdb_id, season_no, episode_no)
                    continue  # Skip to next episode

                if season_no > 0:
                    episode['absolute_number'] = absolute_number_counter
                    absolute_number_counter += 1

                for k, config in self.episode_map:
                    v = self.get_nested_value(episode, config)
                    if v is not None:
                        if k == 'id':
                            v = ImdbIdentifier(v).series_id
                        if k == 'firstaired':
                            v = '{year}-01-01'.format(year=v)

                        self._set_item(series_id, season_no, episode_no, k, v)

            if detailed and season.get('season'):
                # Enrich episode for the current season.
                self._get_episodes_detailed(imdb_id, season['season'])

                # Scrape the synopsys and the episode thumbnail.
                self._enrich_episodes(imdb_id, season['season'])

        # Try to calculate the airs day of week
        self._calc_airs_day_of_week(imdb_id)
예제 #14
0
    def _parse_images(self, tmdb_id):
        """Parse images.

        This interface will be improved in future versions.
        """
        key_mapping = {
            'file_path': 'bannerpath',
            'vote_count': 'ratingcount',
            'vote_average': 'rating',
            'id': 'id'
        }
        image_sizes = {'fanart': 'backdrop_sizes', 'poster': 'poster_sizes'}
        typecasts = {'rating': float, 'ratingcount': int}

        log.debug('Getting show banners for {series}', series=tmdb_id)
        _images = {}

        # Let's get the different type of images available for this series
        params = {
            'include_image_language':
            '{search_language}'.format(search_language=self.config['language'])
        }

        try:
            images = self.tmdb.TV(tmdb_id).images(params=params)
        except RequestException as error:
            raise IndexerUnavailable(
                'Error trying to get images. Cause: {cause}'.format(
                    cause=error))

        bid = images['id']
        for image_type, images in viewitems({
                'poster': images['posters'],
                'fanart': images['backdrops']
        }):
            try:
                if images and image_type not in _images:
                    _images[image_type] = {}

                for image in images:
                    bid += 1
                    image_mapped = self._map_results(image,
                                                     key_mappings=key_mapping)

                    for size in self.tmdb_configuration.images.get(
                            image_sizes[image_type]):
                        if size == 'original':
                            width = image_mapped['width']
                            height = image_mapped['height']
                        else:
                            width = int(size[1:])
                            height = int(
                                round(width /
                                      float(image_mapped['aspect_ratio'])))
                        resolution = '{0}x{1}'.format(width, height)

                        if resolution not in _images[image_type]:
                            _images[image_type][resolution] = {}

                        if bid not in _images[image_type][resolution]:
                            _images[image_type][resolution][bid] = {}

                        for k, v in viewitems(image_mapped):
                            if k is None or v is None:
                                continue

                            try:
                                typecast = typecasts[k]
                            except KeyError:
                                pass
                            else:
                                v = typecast(v)

                            _images[image_type][resolution][bid][k] = v
                            if k.endswith('path'):
                                new_key = '_{0}'.format(k)
                                log.debug('Adding base url for image: {0}', v)
                                _images[image_type][resolution][bid][
                                    new_key] = self.config[
                                        'artwork_prefix'].format(
                                            base_url=self.tmdb_configuration.
                                            images['base_url'],
                                            image_size=size,
                                            file_path=v)

                        if size != 'original':
                            _images[image_type][resolution][bid]['rating'] = 0

            except Exception as error:
                log.warning(
                    'Could not parse Poster for show id: {0}, with exception: {1!r}',
                    tmdb_id, error)
                return False

        season_images = self._parse_season_images(tmdb_id)
        if season_images:
            _images.update(season_images)

        self._save_images(tmdb_id, _images)
        self._set_show_data(tmdb_id, '_banners', _images)
예제 #15
0
    def _query_series(self,
                      tvdb_id,
                      specials=False,
                      aired_season=None,
                      full_info=False):
        """Query against episodes for the given series.

        :param tvdb_id: tvdb series id.
        :param specials: enable/disable download of specials. Currently not used.
        :param aired_season: the episodes returned for a specific aired season.
        :param full_info: add full information to the episodes
        :return: An ordered dict of {'episode': [list of episode dicts]}
        """
        results = []
        if aired_season:
            aired_season = [
                aired_season
            ] if not isinstance(aired_season, list) else aired_season

        # Parse episode data
        log.debug('Getting all episodes of {0}', tvdb_id)

        # get paginated pages
        page = 1
        last = 1
        try:
            if aired_season:
                for season in aired_season:
                    page = 1
                    last = 1
                    while page <= last:
                        paged_episodes = self.config[
                            'session'].series_api.series_id_episodes_query_get(
                                tvdb_id,
                                page=page,
                                aired_season=season,
                                accept_language=self.config['language'])
                        if paged_episodes.data:
                            results += paged_episodes.data
                            last = paged_episodes.links.last
                            page += 1
            else:
                while page <= last:
                    paged_episodes = self.config[
                        'session'].series_api.series_id_episodes_query_get(
                            tvdb_id,
                            page=page,
                            accept_language=self.config['language'])
                    if paged_episodes.data:
                        results += paged_episodes.data
                        last = paged_episodes.links.last
                        page += 1

            if results and full_info:
                results = self._get_episodes_info(tvdb_id,
                                                  results,
                                                  season=aired_season)

        except ApiException as error:
            log.debug('Error trying to index the episodes')
            if error.status == 401:
                raise IndexerAuthFailed(
                    'Authentication failed, possible bad API key. Reason: {reason} ({status})'
                    .format(reason=error.reason, status=error.status))

            if error.status == 404:
                show_data = self.shows.get(tvdb_id)
                if show_data and not show_data['firstaired']:
                    log.info('Show {name} does not have any episodes yet.',
                             {'name': self.shows[tvdb_id]['seriesname']})

            else:
                raise IndexerUnavailable(
                    'Error connecting to TVDB API. Reason: {reason}'.format(
                        reason=error.reason))

        mapped_episodes = self._map_results(results, self.series_map, '|')
        return OrderedDict({
            'episode':
            mapped_episodes
            if isinstance(mapped_episodes, list) else [mapped_episodes]
        })
예제 #16
0
파일: api.py 프로젝트: reconman/Medusa
    def get_last_updated_seasons(self,
                                 show_list=None,
                                 cache=None,
                                 *args,
                                 **kwargs):
        """Return updated seasons for shows passed, using the from_time.

        :param show_list[int]: The list of shows, where seasons updates are retrieved for.
        :param from_time[int]: epoch timestamp, with the start date/time
        :param weeks: number of weeks to get updates for.
        """
        show_season_updates = {}

        # we don't have a single api call tha we can run to check if an update is required.
        # So we'll have to check what's there in the library, and decide based on the last episode's date, if a
        # season update is needed.

        for series_id in show_list:
            series_obj = Show.find_by_id(app.showList, self.indexer, series_id)
            all_episodes_local = series_obj.get_all_episodes()

            total_updates = []
            results = None
            # A small api call to get the amount of known seasons
            try:
                results = self.imdb_api.get_title_episodes(
                    ImdbIdentifier(series_id).imdb_id)
            except LookupError as error:
                raise IndexerShowIncomplete(
                    'Show episode search exception, '
                    'could not get any episodes. Exception: {error!r}'.format(
                        error=error))
            except (AttributeError, RequestException) as error:
                raise IndexerUnavailable(
                    'Error connecting to Imdb api. Caused by: {0!r}'.format(
                        error))

            if not results or not results.get('seasons'):
                continue

            # Get all the seasons

            # Loop through seasons
            for season in results['seasons']:
                season_number = season.get('season')

                # Imdb api gives back a season without the 'season' key. This season has special episodes.
                # Dont know what this is, but skipping it.
                if not season_number:
                    continue

                # Check if the season is already known in our local db.
                local_season_episodes = [
                    ep for ep in all_episodes_local
                    if ep.season == season_number
                ]
                remote_season_episodes = season['episodes']
                if not local_season_episodes or len(
                        remote_season_episodes) != len(local_season_episodes):
                    total_updates.append(season_number)
                    log.debug(
                        '{series}: Season {season} seems to be a new season. Adding it.',
                        {
                            'series': series_obj.name,
                            'season': season_number
                        })
                    continue

                # Per season, get latest episode airdate
                sorted_episodes = sorted(local_season_episodes,
                                         key=lambda x: x.airdate)
                # date_season_start = sorted_episodes[0].airdate
                date_season_last = sorted_episodes[-1].airdate

                # Get date for last updated, from the cache object.

                # Calculate update interval for the season
                update_interval = self._calc_update_interval(
                    # date_season_start,
                    date_season_last,
                    season_finished=bool([
                        s for s in results['seasons']
                        if s.get('season') == season_number + 1
                    ]))

                last_update = cache.get_last_update_season(
                    self.indexer, series_id, season_number)
                if last_update < time() - update_interval:
                    # This season should be updated.
                    total_updates.append(season_number)

                    # Update last_update for this season.
                    cache.set_last_update_season(self.indexer, series_id,
                                                 season_number)
                else:
                    log.debug(
                        '{series}: Season {season} seems to have been recently updated. Not scheduling a new refresh',
                        {
                            'series': series_obj.name,
                            'season': season_number
                        })

            show_season_updates[series_id] = list(set(total_updates))

        return show_season_updates
예제 #17
0
파일: api.py 프로젝트: reconman/Medusa
    def _parse_images(self, imdb_id, language='en'):
        """Parse Show and Season posters.

        Any key starting with an underscore has been processed (not the raw
        data from the XML)

        This interface will be improved in future versions.
        Available sources: amazon, custom, getty, paidcustomer, presskit, userupload.
        Available types: behind_the_scenes, event, poster, product, production_art, publicity, still_frame
        """
        log.debug('Getting show banners for {0}', imdb_id)

        try:
            images = self.imdb_api.get_title_images(
                ImdbIdentifier(imdb_id).imdb_id)
        except LookupError as error:
            raise IndexerShowNotFound(
                'Could not find show {imdb_id} using indexer Imdb. Cause: {cause!r}'
                .format(imdb_id=imdb_id, cause=error))
        except (AttributeError, RequestException) as error:
            raise IndexerUnavailable(
                'Could not get images for show {imdb_id} using indexer Imdb. Cause: {cause!r}'
                .format(imdb_id=imdb_id, cause=error))

        image_mapping = {
            'poster': 'poster',
            'production_art': 'fanart'
        }  # Removed 'still_frame': 'fanart',
        thumb_height = 640

        _images = {}
        try:
            for image in images.get('images', []):
                image_type = image_mapping.get(image.get('type'))
                if image_type not in ('poster', 'fanart'):
                    continue
                image_type_thumb = image_type + '_thumb'
                if image_type not in _images:
                    _images[image_type] = {}
                    _images[image_type + '_thumb'] = {}

                # Store the images for each resolution available
                # Always provide a resolution or 'original'.
                resolution = '{0}x{1}'.format(image['width'], image['height'])
                thumb_width = int(
                    (float(image['width']) / image['height']) * thumb_height)
                resolution_thumb = '{0}x{1}'.format(thumb_width, thumb_height)

                if resolution not in _images[image_type]:
                    _images[image_type][resolution] = {}
                    _images[image_type_thumb][resolution_thumb] = {}

                bid = image['id'].split('/')[-1]

                if image_type in ['season', 'seasonwide']:
                    if int(image.sub_key
                           ) not in _images[image_type][resolution]:
                        _images[image_type][resolution][int(
                            image.sub_key)] = {}
                    if bid not in _images[image_type][resolution][int(
                            image.sub_key)]:
                        _images[image_type][resolution][int(
                            image.sub_key)][bid] = {}
                    base_path = _images[image_type_thumb][resolution][int(
                        image.sub_key)][bid]
                else:
                    if bid not in _images[image_type][resolution]:
                        _images[image_type][resolution][bid] = {}
                        _images[image_type_thumb][resolution_thumb][bid] = {}
                    base_path = _images[image_type][resolution][bid]
                    base_path_thumb = _images[image_type_thumb][
                        resolution_thumb][bid]

                base_path['bannertype'] = image_type
                base_path['bannertype2'] = resolution
                base_path['_bannerpath'] = image.get('url')
                base_path['bannerpath'] = image.get('url').split('/')[-1]
                base_path['languages'] = image.get('languages')
                base_path['source'] = image.get('source')
                base_path['id'] = bid

                base_path_thumb['bannertype'] = image_type_thumb
                base_path_thumb['bannertype2'] = resolution_thumb
                base_path_thumb['_bannerpath'] = image['url'].split(
                    'V1')[0] + 'V1_SY{0}_AL_.jpg'.format(thumb_height)
                base_path_thumb['bannerpath'] = image['url'].split('V1')[
                    0] + 'V1_SY{0}_AL_.jpg'.format(thumb_height).split('/')[-1]
                base_path_thumb['id'] = bid

        except Exception as error:
            log.warning(
                'Could not parse Poster for show id: {0}, with exception: {1!r}',
                imdb_id, error)
            return

        def _get_poster_thumb(thumbs):
            for bid in thumbs.values():
                for image in bid.values():
                    return image.get('bannerpath')

        if _images.get('poster_thumb'):
            self._set_show_data(imdb_id, 'poster_thumb',
                                _get_poster_thumb(_images.get('poster_thumb')))

        self._save_images(imdb_id, _images, language=language)
        self._set_show_data(imdb_id, '_banners', _images)
예제 #18
0
파일: api.py 프로젝트: reconman/Medusa
    def _get_show_by_id(self, imdb_id):  # pylint: disable=unused-argument
        """Retrieve imdb show information by imdb id, or if no imdb id provided by passed external id.

        :param imdb_id: The shows imdb id
        :return: An ordered dict with the show searched for.
        """
        results = None
        log.debug('Getting all show data for {0}', imdb_id)
        try:
            results = self.imdb_api.get_title(ImdbIdentifier(imdb_id).imdb_id)
        except LookupError as error:
            raise IndexerShowNotFound(
                'Could not find show {imdb_id} using indexer Imdb. Cause: {cause!r}'
                .format(imdb_id=imdb_id, cause=error))
        except (AttributeError, RequestException) as error:
            raise IndexerUnavailable(
                'Could not find show {imdb_id} using indexer Imdb. Cause: {cause!r}'
                .format(imdb_id=imdb_id, cause=error))

        if not results:
            return

        mapped_results = self._map_results(results, self.series_map)

        if not mapped_results:
            return

        try:
            # Get firstaired
            releases = self.imdb_api.get_title_releases(
                ImdbIdentifier(imdb_id).imdb_id)
        except LookupError as error:
            raise IndexerShowNotFound(
                'Could not find show {imdb_id} using indexer Imdb. Cause: {cause!r}'
                .format(imdb_id=imdb_id, cause=error))
        except (AttributeError, RequestException) as error:
            raise IndexerUnavailable(
                'Could not get title releases for show {imdb_id} using indexer Imdb. Cause: {cause!r}'
                .format(imdb_id=imdb_id, cause=error))

        if releases.get('releases'):
            first_released = sorted([r['date']
                                     for r in releases['releases']])[0]
            mapped_results['firstaired'] = first_released

        try:
            companies = self.imdb_api.get_title_companies(
                ImdbIdentifier(imdb_id).imdb_id)
            # If there was a release check if it was distributed.
            if companies.get('distribution'):
                origins = self.imdb_api.get_title_versions(
                    ImdbIdentifier(imdb_id).imdb_id)['origins'][0]
                released_in_regions = [
                    dist for dist in companies['distribution']
                    if dist.get('regions') and origins in dist['regions']
                ]
                # Used item.get('startYear') because a startYear is not always available.
                first_release = sorted(released_in_regions,
                                       key=lambda x: x.get('startYear'))

                if first_release:
                    mapped_results['network'] = first_release[0]['company'][
                        'name']
        except (AttributeError, LookupError, RequestException):
            log.info('No company data available for {0}, cant get a network',
                     imdb_id)

        return OrderedDict({'series': mapped_results})