Exemple #1
0
    def _parse_series(result):
        new_episode_numbers = []
        new_season_numbers = []
        new_absolute_numbers = []

        ex_season = scene_exceptions.get_season_from_name(result.series, result.series_name) or result.season_number

        for episode_number in result.episode_numbers:
            season = ex_season
            episode = episode_number

            (idx_season, idx_episode) = scene_numbering.get_indexer_numbering(
                result.series,
                episode_number,
                ex_season
            )

            if idx_season is not None:
                season = idx_season
            if idx_episode is not None:
                episode = idx_episode

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

        return new_episode_numbers, new_season_numbers, new_absolute_numbers
Exemple #2
0
    def _parse_series(result):
        new_episode_numbers = []
        new_season_numbers = []
        new_absolute_numbers = []

        season = scene_exceptions.get_season_from_name(result.series, result.series_name) or result.season_number

        for episode_number in result.episode_numbers:
            episode = episode_number

            if result.series.is_scene:
                (season, episode) = scene_numbering.get_indexer_numbering(
                    result.series,
                    season,
                    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)

        return new_episode_numbers, new_season_numbers, new_absolute_numbers
Exemple #3
0
    def _parse_series(result):
        new_episode_numbers = []
        new_season_numbers = []
        new_absolute_numbers = []

        ex_season = scene_exceptions.get_season_from_name(
            result.series, result.series_name) or result.season_number
        if ex_season is None:
            ex_season = 1
            log.info(
                "For the show {name} we could not parse a season number. We did match the title, so we'll asume season 1",
                {'name': result.series.name})

        if result.episode_numbers:
            for episode_number in result.episode_numbers:
                season = ex_season
                episode = episode_number

                (idx_season,
                 idx_episode) = scene_numbering.get_indexer_numbering(
                     result.series, episode_number, ex_season)

                if idx_season is not None:
                    season = idx_season
                if idx_episode is not None:
                    episode = idx_episode

                new_season_numbers.append(season)
                new_episode_numbers.append(episode)
        else:
            # No episode numbers. Treat it like a season pack.
            new_season_numbers.append(ex_season)

        return new_episode_numbers, new_season_numbers, new_absolute_numbers
Exemple #4
0
    def _parse_series(result):
        new_episode_numbers = []
        new_season_numbers = []
        new_absolute_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)}
                )

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

        return new_episode_numbers, new_season_numbers, new_absolute_numbers
Exemple #5
0
    def _parse_air_by_date(self, result):
        """
        Parse anime season episode results.

        Translate scene episode and season numbering to indexer numbering,
        using an air date to indexer season/episode translation.

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

        new_episode_numbers = []
        new_season_numbers = []

        episode_by_air_date = self._get_episodes_by_air_date(result)

        season_number = None
        episode_numbers = []

        if episode_by_air_date:
            season_number = int(episode_by_air_date[0]['season'])
            episode_numbers = [int(episode_by_air_date[0]['episode'])]

            # 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(episode_by_air_date) > 1:
                season_number = int(episode_by_air_date[1]['season'])
                episode_numbers = [int(episode_by_air_date[1]['episode'])]

            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})

            indexer_api_params = indexerApi(result.series.indexer).api_params.copy()
            indexer_api = indexerApi(result.series.indexer).indexer(**indexer_api_params)
            try:
                if result.series.lang:
                    indexer_api_params['language'] = result.series.lang

                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!r}',
                    {'indexer_api': indexer_api, 'error': error}
                )
                episode_numbers = []
            except IndexerException as error:
                log.warning(
                    'Indexer exception: {indexer_api.name}: {error!r}',
                    {'indexer_api': indexer_api, 'error': error}
                )
                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)

        return new_episode_numbers, new_season_numbers
Exemple #6
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
Exemple #7
0
    def _parse_air_by_date(self, result):
        """
        Parse anime season episode results.

        Translate scene episode and season numbering to indexer numbering,
        using an air date to indexer season/episode translation.

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

        new_episode_numbers = []
        new_season_numbers = []

        episode_by_air_date = self._get_episodes_by_air_date(result)

        season_number = None
        episode_numbers = []

        if episode_by_air_date:
            season_number = int(episode_by_air_date[0]['season'])
            episode_numbers = [int(episode_by_air_date[0]['episode'])]

            # 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(episode_by_air_date) > 1:
                season_number = int(episode_by_air_date[1]['season'])
                episode_numbers = [int(episode_by_air_date[1]['episode'])]

            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})

            indexer_api_params = indexerApi(result.series.indexer).api_params.copy()
            indexer_api = indexerApi(result.series.indexer).indexer(**indexer_api_params)
            try:
                if result.series.lang:
                    indexer_api_params['language'] = result.series.lang

                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!r}',
                    {'indexer_api': indexer_api, 'error': error}
                )
                episode_numbers = []
            except IndexerException as error:
                log.warning(
                    'Indexer exception: {indexer_api.name}: {error!r}',
                    {'indexer_api': indexer_api, 'error': error}
                )
                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)

        return new_episode_numbers, new_season_numbers
Exemple #8
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