Ejemplo n.º 1
0
    def _parse_anime(result):
        """
        Parse anime season episode results.

        Translate scene episode and season numbering to indexer numbering,
        using anime scen episode/season translation tables to indexer episode/season.

        :param result: Guessit parse result object.
        :return: tuple of found indexer episode numbers and indexer season numbers
        """
        log.debug('Series {name} is anime', {'name': result.series.name})

        new_episode_numbers = []
        new_season_numbers = []
        new_absolute_numbers = []

        # Try to translate the scene series name to a scene number.
        # For example Jojo's bizarre Adventure - Diamond is unbreakable, will use xem, to translate the
        # "diamond is unbreakable" exception back to season 4 of it's "master" table. This will be used later
        # to translate it to an absolute number, which in turn can be translated to an indexer SxEx.
        # For example Diamond is unbreakable - 26 -> Season 4 -> Absolute number 100 -> tvdb S03E26
        season_exception = None
        if result.season_number is None:
            season_exception = scene_exceptions.get_season_from_name(result.series, result.series_name)

        if result.ab_episode_numbers:
            for absolute_episode in result.ab_episode_numbers:
                a = absolute_episode

                # Don't assume that scene_exceptions season is the same as indexer season.
                # E.g.: [HorribleSubs] Cardcaptor Sakura Clear Card - 08 [720p].mkv thetvdb s04, thexem s02
                if season_exception is not None or result.series.is_scene:
                    # Get absolute number from custom numbering (1), XEM (2) or indexer (3)
                    a = scene_numbering.get_indexer_absolute_numbering(
                        result.series, a, fallback_to_xem=True, scene_season=season_exception
                    )

                new_absolute_numbers.append(a)

                # Translate the absolute episode number, back to the indexers season and episode.
                (season, episodes) = helpers.get_all_episodes_from_absolute_number(result.series, [a])
                if season and episodes:

                    new_episode_numbers.extend(episodes)
                    new_season_numbers.append(season)

                    if season_exception is not None:
                        log.debug(
                            'Detected a season scene exception [{series_name} -> {scene_season}] without a '
                            'season number in the title, '
                            'translating the episode #{abs} to indexer #{indexer_absolute}: {ep}',
                            {'series_name': result.series_name, 'scene_season': season_exception,
                             'abs': absolute_episode, 'indexer_absolute': a, 'ep': episode_num(season, episodes[0])}
                        )
                    elif result.series.is_scene:
                        log.debug(
                            'Scene numbering enabled anime series {name} using indexer numbering #{absolute}: {ep}',
                            {'name': result.series.name, 'season': season, 'absolute': a,
                             'ep': episode_num(season, episodes[0])}
                        )
                    else:
                        log.debug(
                            'Anime series {name} using indexer numbering #{absolute}: {ep}',
                            {'name': result.series.name, 'season': season, 'absolute': a,
                             'ep': episode_num(season, episodes[0])}
                        )

        # It's possible that we map a parsed result to an anime series,
        # but the result is not detected/parsed as an anime. In that case, we're using the result.episode_numbers.
        else:
            for episode_number in result.episode_numbers:
                season = result.season_number
                episode = episode_number

                if result.series.is_scene:
                    (season, episode) = scene_numbering.get_indexer_numbering(
                        result.series,
                        result.season_number,
                        episode_number
                    )
                    log.debug(
                        'Scene numbering enabled anime {name} using indexer numbering: {ep}',
                        {'name': result.series.name, 'ep': episode_num(season, episode)}
                    )

                a = helpers.get_absolute_number_from_season_and_episode(result.series, season, episode)
                if a:
                    new_absolute_numbers.append(a)
                    log.debug(
                        'Anime series {name} using using indexer numbering #{absolute}: {ep}',
                        {'name': result.series.name, 'absolute': a, 'ep': episode_num(season, episode)}
                    )

                new_episode_numbers.append(episode)
                new_season_numbers.append(season)

        return new_episode_numbers, new_season_numbers, new_absolute_numbers
Ejemplo n.º 2
0
    def _parse_anime(result):
        """
        Parse anime season episode results.

        Translate scene episode and season numbering to indexer numbering,
        using anime scen episode/season translation tables to indexer episode/season.

        :param result: Guessit parse result object.
        :return: tuple of found indexer episode numbers and indexer season numbers
        """
        log.debug('Scene numbering enabled series {name} is anime',
                  {'name': result.series.name})

        new_episode_numbers = []
        new_season_numbers = []
        new_absolute_numbers = []

        # Try to translate the scene series name to a scene number.
        # For example Jojo's bizarre Adventure - Diamond is unbreakable, will use xem, to translate the
        # "diamond is unbreakable" exception back to season 4 of it's "master" table. This will be used later
        # to translate it to an absolute number, which in turn can be translated to an indexer SxEx.
        # For example Diamond is unbreakable - 26 -> Season 4 -> Absolute number 100 -> tvdb S03E26
        scene_season = scene_exceptions.get_scene_exceptions_by_name(
            result.series_name or result.series.name)[0][1]

        if result.ab_episode_numbers:
            for absolute_episode in result.ab_episode_numbers:
                a = absolute_episode

                # Apparently we got a scene_season using the season scene exceptions. If we also do not have a season
                # parsed, guessit made a 'mistake' and it should have set the season with the value.
                # This is required for titles like: '[HorribleSubs].Kekkai.Sensen.&.Beyond.-.01.[1080p].mkv'
                #
                # Don't assume that scene_exceptions season is the same as indexer season.
                # E.g.: [HorribleSubs] Cardcaptor Sakura Clear Card - 08 [720p].mkv thetvdb s04, thexem s02
                if result.series.is_scene or (result.season_number is None
                                              and scene_season is not None
                                              and scene_season > 0):
                    a = scene_numbering.get_indexer_absolute_numbering(
                        result.series, absolute_episode, True, scene_season)

                # Translate the absolute episode number, back to the indexers season and episode.
                (season,
                 episode) = helpers.get_all_episodes_from_absolute_number(
                     result.series, [a])

                if result.season_number is None and scene_season is not None and scene_season > 0:
                    log.debug(
                        'Detected a season scene exception [{series_name} -> {scene_season}] without a '
                        'season number in the title, '
                        'translating the episode absolute # [{scene_absolute}] to season #[{absolute_season}] and '
                        'episode #[{absolute_episode}].', {
                            'series_name': result.series_name,
                            'scene_season': scene_season,
                            'scene_absolute': a,
                            'absolute_season': season,
                            'absolute_episode': episode
                        })
                else:
                    log.debug(
                        'Scene numbering enabled series {name} with season {season} using indexer for absolute {absolute}: {ep}',
                        {
                            'name': result.series.name,
                            'season': season,
                            'absolute': a,
                            'ep': episode_num(season, episode, 'absolute')
                        })

                new_absolute_numbers.append(a)
                new_episode_numbers.extend(episode)
                new_season_numbers.append(season)

        # It's possible that we map a parsed result to an anime series,
        # but the result is not detected/parsed as an anime. In that case, we're using the result.episode_numbers.
        else:
            for episode_number in result.episode_numbers:
                season = result.season_number
                episode = episode_number
                a = helpers.get_absolute_number_from_season_and_episode(
                    result.series, season, episode)
                if a:
                    new_absolute_numbers.append(a)
                    log.debug(
                        'Scene numbering enabled anime {name} using indexer with absolute {absolute}: {ep}',
                        {
                            'name': result.series.name,
                            'absolute': a,
                            'ep': episode_num(season, episode, 'absolute')
                        })

                new_episode_numbers.append(episode)
                new_season_numbers.append(season)

        return new_episode_numbers, new_season_numbers, new_absolute_numbers
Ejemplo n.º 3
0
    def _parse_anime(result):
        """
        Parse anime season episode results.

        Translate scene episode and season numbering to indexer numbering,
        using anime scen episode/season translation tables to indexer episode/season.

        :param result: Guessit parse result object.
        :return: tuple of found indexer episode numbers and indexer season numbers
        """
        log.debug('Scene numbering enabled series {name} is anime',
                  {'name': result.series.name})

        new_episode_numbers = []
        new_season_numbers = []
        new_absolute_numbers = []

        # Try to translate the scene series name to a scene number.
        # For example Jojo's bizarre Adventure - Diamond is unbreakable, will use xem, to translate the
        # "diamond is unbreakable" exception back to season 4 of it's "master" table. This will be used later
        # to translate it to an absolute number, which in turn can be translated to an indexer SxEx.
        # For example Diamond is unbreakable - 26 -> Season 4 -> Absolute number 100 -> tvdb S03E26
        scene_season = scene_exceptions.get_scene_exceptions_by_name(
            result.series_name or result.series.name)[0][1]

        if result.ab_episode_numbers:
            for absolute_episode in result.ab_episode_numbers:
                a = absolute_episode

                # Apparently we got a scene_season using the season scene exceptions. If we also do not have a season
                # parsed, guessit made a 'mistake' and it should have set the season with the value.
                # This is required for titles like: '[HorribleSubs].Kekkai.Sensen.&.Beyond.-.01.[1080p].mkv'
                #
                # Don't assume that scene_exceptions season is the same as indexer season.
                # E.g.: [HorribleSubs] Cardcaptor Sakura Clear Card - 08 [720p].mkv thetvdb s04, thexem s02
                if result.series.is_scene or (result.season_number is None
                                              and scene_season is not None and scene_season > 0):
                    a = scene_numbering.get_indexer_absolute_numbering(
                        result.series, absolute_episode, True, scene_season
                    )

                # Translate the absolute episode number, back to the indexers season and episode.
                (season, episode) = helpers.get_all_episodes_from_absolute_number(result.series, [a])

                if result.season_number is None and scene_season is not None and scene_season > 0:
                    log.debug(
                        'Detected a season scene exception [{series_name} -> {scene_season}] without a '
                        'season number in the title, '
                        'translating the episode absolute # [{scene_absolute}] to season #[{absolute_season}] and '
                        'episode #[{absolute_episode}].',
                        {'series_name': result.series_name, 'scene_season': scene_season, 'scene_absolute': a,
                         'absolute_season': season, 'absolute_episode': episode}
                    )
                else:
                    log.debug(
                        'Scene numbering enabled series {name} with season {season} using indexer for absolute {absolute}: {ep}',
                        {'name': result.series.name, 'season': season, 'absolute': a,
                         'ep': episode_num(season, episode, 'absolute')}
                    )

                new_absolute_numbers.append(a)
                new_episode_numbers.extend(episode)
                new_season_numbers.append(season)

        # It's possible that we map a parsed result to an anime series,
        # but the result is not detected/parsed as an anime. In that case, we're using the result.episode_numbers.
        else:
            for episode_number in result.episode_numbers:
                season = result.season_number
                episode = episode_number
                a = helpers.get_absolute_number_from_season_and_episode(result.series, season, episode)
                if a:
                    new_absolute_numbers.append(a)
                    log.debug(
                        'Scene numbering enabled anime {name} using indexer with absolute {absolute}: {ep}',
                        {'name': result.series.name, 'absolute': a, 'ep': episode_num(season, episode, 'absolute')}
                    )

                new_episode_numbers.append(episode)
                new_season_numbers.append(season)

        return new_episode_numbers, new_season_numbers, new_absolute_numbers
Ejemplo n.º 4
0
    def _parse_string(self, name):
        guess = guessit.guessit(name, dict(show_type=self.show_type))
        result = self.to_parse_result(name, guess)

        search_series = helpers.get_show(result.series_name, self.try_indexers) if not self.naming_pattern else None

        # confirm passed in show object indexer id matches result show object indexer id
        series_obj = None if search_series and self.series and search_series.indexerid != self.series.indexerid else search_series
        result.series = series_obj or self.series

        # if this is a naming pattern test or result doesn't have a show object then return best result
        if not result.series or self.naming_pattern:
            return result

        new_episode_numbers = []
        new_season_numbers = []
        new_absolute_numbers = []

        # if we have an air-by-date show and the result is air-by-date,
        # then get the real season/episode numbers
        if result.series.air_by_date and result.is_air_by_date:
            log.debug('Series {name} is air by date', {'name': result.series.name})
            airdate = result.air_date.toordinal()
            main_db_con = db.DBConnection()
            sql_result = main_db_con.select(
                b'SELECT season, episode FROM tv_episodes WHERE indexer = ? AND showid = ? AND airdate = ?',
                [result.series.indexer, result.series.series_id, airdate])

            season_number = None
            episode_numbers = []

            if sql_result:
                season_number = int(sql_result[0][0])
                episode_numbers = [int(sql_result[0][1])]

                # Use the next query item if we have multiple results
                # and the current one is a special episode (season 0)
                if season_number == 0 and len(sql_result) > 1:
                    season_number = int(sql_result[1][0])
                    episode_numbers = [int(sql_result[1][1])]

                log.debug(
                    'Database info for series {name}: Season: {season} Episode(s): {episodes}', {
                        'name': result.series.name,
                        'season': season_number,
                        'episodes': episode_numbers
                    }
                )

            if season_number is None or not episode_numbers:
                log.debug('Series {name} has no season or episodes, using indexer',
                          {'name': result.series.name})
                try:
                    indexer_api_params = indexerApi(result.series.indexer).api_params.copy()

                    if result.series.lang:
                        indexer_api_params['language'] = result.series.lang

                    indexer_api = indexerApi(result.series.indexer).indexer(**indexer_api_params)
                    tv_episode = indexer_api[result.series.indexerid].aired_on(result.air_date)[0]

                    season_number = int(tv_episode['seasonnumber'])
                    episode_numbers = [int(tv_episode['episodenumber'])]
                    log.debug(
                        'Indexer info for series {name}: {ep}', {
                            'name': result.series.name,
                            'ep': episode_num(season_number, episode_numbers[0]),
                        }
                    )
                except IndexerEpisodeNotFound:
                    log.warning(
                        'Unable to find episode with date {date} for series {name}. Skipping',
                        {'date': result.air_date, 'name': result.series.name}
                    )
                    episode_numbers = []
                except IndexerError as error:
                    log.warning(
                        'Unable to contact {indexer_api.name}: {error}',
                        {'indexer_api': indexer_api, 'error': error.message}
                    )
                    episode_numbers = []
                except IndexerException as error:
                    log.warning(
                        'Indexer exception: {indexer_api.name}: {error}',
                        {'indexer_api': indexer_api, 'error': error.message}
                    )
                    episode_numbers = []

            for episode_number in episode_numbers:
                season = season_number
                episode = episode_number

                if result.series.is_scene:
                    (season, episode) = scene_numbering.get_indexer_numbering(
                        result.series,
                        season_number,
                        episode_number,
                    )
                    log.debug(
                        'Scene numbering enabled series {name}, using indexer numbering: {ep}',
                        {'name': result.series.name, 'ep': episode_num(season, episode)}
                    )
                new_episode_numbers.append(episode)
                new_season_numbers.append(season)

        elif result.series.is_anime and result.is_anime:
            log.debug('Scene numbering enabled series {name} is anime',
                      {'name': result.series.name})
            scene_season = scene_exceptions.get_scene_exceptions_by_name(result.series_name)[0][1]

            for absolute_episode in result.ab_episode_numbers:
                a = absolute_episode

                # Apparently we got a scene_season using the season scene exceptions. If we also do not have a season
                # parsed, guessit made a 'mistake' and it should have set the season with the value.
                # This is required for titles like: '[HorribleSubs].Kekkai.Sensen.&.Beyond.-.01.[1080p].mkv'
                if result.season_number is None and scene_season > 0:
                    season = scene_season
                    episode = [a]
                    log.debug(
                        'Detected a season scene exception [{series_name} -> {scene_season}] without a '
                        'season number in the title, '
                        'assuming the episode # [{scene_absolute}] is the scene_absolute #.',
                        {'series_name': result.series_name, 'scene_season': scene_season, 'scene_absolute': a}
                    )
                else:
                    if result.series.is_scene:
                        a = scene_numbering.get_indexer_absolute_numbering(result.series, absolute_episode,
                                                                           True, scene_season)

                    # Translate the absolute episode number, back to the indexers season and episode.
                    (season, episode) = helpers.get_all_episodes_from_absolute_number(result.series, [a])
                    log.debug(
                        'Scene numbering enabled series {name} using indexer for absolute {absolute}: {ep}',
                        {'name': result.series.name, 'absolute': a, 'ep': episode_num(season, episode, 'absolute')}
                    )

                new_absolute_numbers.append(a)
                new_episode_numbers.extend(episode)
                new_season_numbers.append(season)

        elif result.season_number and result.episode_numbers:
            for episode_number in result.episode_numbers:
                season = result.season_number
                episode = episode_number

                if result.series.is_scene:
                    (season, episode) = scene_numbering.get_indexer_numbering(
                        result.series,
                        result.season_number,
                        episode_number
                    )
                    log.debug(
                        'Scene numbering enabled series {name} using indexer numbering: {ep}',
                        {'name': result.series.name, 'ep': episode_num(season, episode)}
                    )

                if result.series.is_anime:
                    a = helpers.get_absolute_number_from_season_and_episode(result.series, season, episode)
                    if a:
                        new_absolute_numbers.append(a)
                        log.debug(
                            'Scene numbering enabled anime {name} using indexer with absolute {absolute}: {ep}',
                            {'name': result.series.name, 'absolute': a, 'ep': episode_num(season, episode, 'absolute')}
                        )

                new_episode_numbers.append(episode)
                new_season_numbers.append(season)

        # need to do a quick sanity check heregex.  It's possible that we now have episodes
        # from more than one season (by tvdb numbering), and this is just too much
        # for the application, so we'd need to flag it.
        new_season_numbers = sorted(set(new_season_numbers))  # remove duplicates
        if len(new_season_numbers) > 1:
            raise InvalidNameException('Scene numbering results episodes from seasons {seasons}, (i.e. more than one) '
                                       'and Medusa does not support this. Sorry.'.format(seasons=new_season_numbers))

        # If guess it's possible that we'd have duplicate episodes too,
        # so lets eliminate them
        new_episode_numbers = sorted(set(new_episode_numbers))

        # maybe even duplicate absolute numbers so why not do them as well
        new_absolute_numbers = sorted(set(new_absolute_numbers))

        if new_absolute_numbers:
            result.ab_episode_numbers = new_absolute_numbers

        if new_season_numbers and new_episode_numbers:
            result.episode_numbers = new_episode_numbers
            result.season_number = new_season_numbers[0]

        # For anime that we still couldn't get a season, let's assume we should use 1.
        if result.series.is_anime and result.season_number is None and result.episode_numbers:
            result.season_number = 1
            log.warning(
                'Unable to parse season number for anime {name}, '
                'assuming absolute numbered anime with season 1',
                {'name': result.series.name}
            )

        if result.series.is_scene:
            log.debug(
                'Converted parsed result {original} into {result}',
                {'original': result.original_name, 'result': result}
            )

        return result