Esempio n. 1
0
    def _parse_string(self, name):
        if not name:
            return

        matches = []
        initial_best_result = None
        for reg_ex in self.compiled_regexes:
            for (cur_regex_num, cur_regex_name,
                 cur_regex) in self.compiled_regexes[reg_ex]:
                new_name = helpers.remove_non_release_groups(
                    name, 'anime' in cur_regex_name)
                match = cur_regex.match(new_name)

                if not match:
                    continue

                if 'garbage_name' == cur_regex_name:
                    return

                result = ParseResult(new_name)
                result.which_regex = [cur_regex_name]
                result.score = 0 - cur_regex_num

                named_groups = match.groupdict().keys()

                if 'series_name' in named_groups:
                    result.series_name = match.group('series_name')
                    if result.series_name:
                        result.series_name = self.clean_series_name(
                            result.series_name)
                        name_parts = re.match(
                            '(?i)(.*)[ -]((?:part|pt)[ -]?\w+)$',
                            result.series_name)
                        try:
                            result.series_name = name_parts.group(1)
                            result.extra_info = name_parts.group(2)
                        except (AttributeError, IndexError):
                            pass

                        result.score += 1

                if 'anime' in cur_regex_name and not (self.showObj and
                                                      self.showObj.is_anime):
                    p_show = helpers.get_show(result.series_name, True)
                    if p_show and self.showObj and p_show.indexerid != self.showObj.indexerid:
                        p_show = None
                    if not p_show and self.showObj:
                        p_show = self.showObj
                    if p_show and not p_show.is_anime:
                        continue

                if 'series_num' in named_groups and match.group('series_num'):
                    result.score += 1

                if 'season_num' in named_groups:
                    tmp_season = int(match.group('season_num'))
                    if 'bare' == cur_regex_name and tmp_season in (19, 20):
                        continue
                    result.season_number = tmp_season
                    result.score += 1

                def _process_epnum(captures, capture_names, grp_name,
                                   extra_grp_name, ep_numbers, parse_result):
                    ep_num = self._convert_number(captures.group(grp_name))
                    extra_grp_name = 'extra_%s' % extra_grp_name
                    ep_numbers = '%sepisode_numbers' % ep_numbers
                    if extra_grp_name in capture_names and captures.group(
                            extra_grp_name):
                        try:
                            if hasattr(self.showObj, 'getEpisode'):
                                ep = self.showObj.getEpisode(
                                    parse_result.season_number, ep_num)
                            else:
                                tmp_show = helpers.get_show(
                                    parse_result.series_name, True, False)
                                if tmp_show and hasattr(
                                        tmp_show, 'getEpisode'):
                                    ep = tmp_show.getEpisode(
                                        parse_result.season_number, ep_num)
                                else:
                                    ep = None
                        except (StandardError, Exception):
                            ep = None
                        en = ep and ep.name and re.match(
                            r'^\W*(\d+)', ep.name) or None
                        es = en and en.group(1) or None

                        extra_ep_num = self._convert_number(
                            captures.group(extra_grp_name))
                        parse_result.__dict__[ep_numbers] = range(
                            ep_num, extra_ep_num +
                            1) if not (ep and es
                                       and es != captures.group(extra_grp_name)
                                       ) and (0 < extra_ep_num -
                                              ep_num < 10) else [ep_num]
                        parse_result.score += 1
                    else:
                        parse_result.__dict__[ep_numbers] = [ep_num]
                    parse_result.score += 1
                    return parse_result

                if 'ep_num' in named_groups:
                    result = _process_epnum(match, named_groups, 'ep_num',
                                            'ep_num', '', result)

                if 'ep_ab_num' in named_groups:
                    result = _process_epnum(match, named_groups, 'ep_ab_num',
                                            'ab_ep_num', 'ab_', result)

                if 'air_year' in named_groups and 'air_month' in named_groups and 'air_day' in named_groups:
                    year = int(match.group('air_year'))
                    try:
                        month = int(match.group('air_month'))
                    except ValueError:
                        try:
                            month = time.strptime(
                                match.group('air_month')[0:3], '%b').tm_mon
                        except ValueError as e:
                            raise InvalidNameException(ex(e))
                    day = int(match.group('air_day'))
                    # make an attempt to detect YYYY-DD-MM formats
                    if 12 < month:
                        tmp_month = month
                        month = day
                        day = tmp_month
                    try:
                        result.air_date = datetime.date(
                            year +
                            ((1900, 2000)[0 < year < 28], 0)[1900 < year],
                            month, day)
                    except ValueError as e:
                        raise InvalidNameException(ex(e))

                if 'extra_info' in named_groups:
                    tmp_extra_info = match.group('extra_info')

                    # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
                    if tmp_extra_info and 'season_only' == cur_regex_name and re.search(
                            r'([. _-]|^)(special|extra)s?\w*([. _-]|$)',
                            tmp_extra_info, re.I):
                        continue
                    if tmp_extra_info:
                        if result.extra_info:
                            tmp_extra_info = '%s %s' % (result.extra_info,
                                                        tmp_extra_info)
                        result.extra_info = tmp_extra_info
                    result.score += 1

                if 'release_group' in named_groups:
                    result.release_group = match.group('release_group')
                    result.score += 1

                if 'version' in named_groups:
                    # assigns version to anime file if detected using anime regex. Non-anime regex receives -1
                    version = match.group('version')
                    if version:
                        result.version = helpers.tryInt(version)
                    else:
                        result.version = 1
                else:
                    result.version = -1

                if None is result.season_number and result.episode_numbers and not result.air_date and \
                        cur_regex_name in ['no_season', 'no_season_general', 'no_season_multi_ep'] and \
                        re.search(r'(?i)\bpart.?\d{1,2}\b', result.original_name):
                    result.season_number = 1

                matches.append(result)

            if len(matches):
                # pick best match with highest score based on placement
                best_result = max(sorted(matches,
                                         reverse=True,
                                         key=lambda x: x.which_regex),
                                  key=lambda x: x.score)

                show = None
                if not self.naming_pattern:
                    # try and create a show object for this result
                    show = helpers.get_show(best_result.series_name,
                                            self.try_scene_exceptions)

                # confirm passed in show object indexer id matches result show object indexer id
                if show and not self.testing:
                    if self.showObj and show.indexerid != self.showObj.indexerid:
                        show = None
                elif not show and self.showObj:
                    show = self.showObj
                best_result.show = show

                if show and show.is_anime and 1 < len(
                        self.compiled_regexes[1]) and 1 != reg_ex:
                    continue

                # if this is a naming pattern test then return best result
                if not show or self.naming_pattern:
                    if not show and not self.naming_pattern and not self.testing:
                        # ensure anime regex test but use initial best if show still not found
                        if 0 == reg_ex:
                            initial_best_result = best_result
                            matches = []  # clear non-anime match scores
                            continue
                        return initial_best_result
                    return best_result

                # get quality
                new_name = helpers.remove_non_release_groups(
                    name, show.is_anime)
                best_result.quality = common.Quality.nameQuality(
                    new_name, show.is_anime)

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

                # if we have an air-by-date show then get the real season/episode numbers
                if best_result.is_air_by_date:
                    season_number, episode_numbers = None, []

                    airdate = best_result.air_date.toordinal()
                    my_db = db.DBConnection()
                    sql_result = my_db.select(
                        'SELECT season, episode, name FROM tv_episodes ' +
                        'WHERE showid = ? and indexer = ? and airdate = ?',
                        [show.indexerid, show.indexer, airdate])

                    if sql_result:
                        season_number = int(sql_result[0]['season'])
                        episode_numbers = [int(sql_result[0]['episode'])]
                        if 1 < len(sql_result):
                            # multi-eps broadcast on this day
                            nums = {
                                '1': 'one',
                                '2': 'two',
                                '3': 'three',
                                '4': 'four',
                                '5': 'five',
                                '6': 'six',
                                '7': 'seven',
                                '8': 'eight',
                                '9': 'nine',
                                '10': 'ten'
                            }
                            patt = '(?i)(?:e(?:p(?:isode)?)?|part|pt)[. _-]?(%s)'
                            try:
                                src_num = str(
                                    re.findall(patt % '\w+',
                                               best_result.extra_info)[0])
                                alt_num = nums.get(src_num) or list(
                                    nums.keys())[list(
                                        nums.values()).index(src_num)]
                                re_partnum = re.compile(
                                    patt % ('%s|%s' % (src_num, alt_num)))
                                for ep_details in sql_result:
                                    if re_partnum.search(ep_details['name']):
                                        season_number = int(
                                            ep_details['season'])
                                        episode_numbers = [
                                            int(ep_details['episode'])
                                        ]
                                        break
                            except (StandardError, Exception):
                                pass

                    if self.indexer_lookup and not season_number or not len(
                            episode_numbers):
                        try:
                            lindexer_api_parms = sickbeard.indexerApi(
                                show.indexer).api_params.copy()

                            if show.lang:
                                lindexer_api_parms['language'] = show.lang

                            t = sickbeard.indexerApi(
                                show.indexer).indexer(**lindexer_api_parms)

                            ep_obj = t[show.indexerid].aired_on(
                                best_result.air_date)[0]

                            season_number = int(ep_obj['seasonnumber'])
                            episode_numbers = [int(ep_obj['episodenumber'])]
                        except sickbeard.indexer_episodenotfound:
                            logger.log(
                                u'Unable to find episode with date ' +
                                str(best_result.air_date) + ' for show ' +
                                show.name + ', skipping', logger.WARNING)
                            episode_numbers = []
                        except sickbeard.indexer_error as e:
                            logger.log(
                                u'Unable to contact ' +
                                sickbeard.indexerApi(show.indexer).name +
                                ': ' + ex(e), logger.WARNING)
                            episode_numbers = []

                    for epNo in episode_numbers:
                        s = season_number
                        e = epNo

                        if self.convert and show.is_scene:
                            (s, e) = scene_numbering.get_indexer_numbering(
                                show.indexerid, show.indexer, season_number,
                                epNo)
                        new_episode_numbers.append(e)
                        new_season_numbers.append(s)

                elif show.is_anime and len(
                        best_result.ab_episode_numbers) and not self.testing:
                    scene_season = scene_exceptions.get_scene_exception_by_name(
                        best_result.series_name)[1]
                    for epAbsNo in best_result.ab_episode_numbers:
                        a = epAbsNo

                        if self.convert and show.is_scene:
                            a = scene_numbering.get_indexer_absolute_numbering(
                                show.indexerid, show.indexer, epAbsNo, True,
                                scene_season)

                        (s, e) = helpers.get_all_episodes_from_absolute_number(
                            show, [a])

                        new_absolute_numbers.append(a)
                        new_episode_numbers.extend(e)
                        new_season_numbers.append(s)

                elif best_result.season_number and len(
                        best_result.episode_numbers) and not self.testing:
                    for epNo in best_result.episode_numbers:
                        s = best_result.season_number
                        e = epNo

                        if self.convert and show.is_scene:
                            (s, e) = scene_numbering.get_indexer_numbering(
                                show.indexerid, show.indexer,
                                best_result.season_number, epNo)
                        if show.is_anime:
                            a = helpers.get_absolute_number_from_season_and_episode(
                                show, s, e)
                            if a:
                                new_absolute_numbers.append(a)

                        new_episode_numbers.append(e)
                        new_season_numbers.append(s)

                # 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 sickbeard, so we'd need to flag it.
                new_season_numbers = list(
                    set(new_season_numbers))  # remove duplicates
                if 1 < len(new_season_numbers):
                    raise InvalidNameException(
                        'Scene numbering results episodes from '
                        'seasons %s, (i.e. more than one) and '
                        'SickGear does not support this.  '
                        'Sorry.' % (str(new_season_numbers)))

                # I guess it's possible that we'd have duplicate episodes too, so lets
                # eliminate them
                new_episode_numbers = list(set(new_episode_numbers))
                new_episode_numbers.sort()

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

                if len(new_absolute_numbers):
                    best_result.ab_episode_numbers = new_absolute_numbers

                if len(new_season_numbers) and len(new_episode_numbers):
                    best_result.episode_numbers = new_episode_numbers
                    best_result.season_number = new_season_numbers[0]

                if self.convert and show.is_scene:
                    logger.log(
                        u'Converted parsed result %s into %s' %
                        (best_result.original_name, str(best_result).decode(
                            'utf-8', 'xmlcharrefreplace')), logger.DEBUG)

                helpers.cpu_sleep()

                return best_result
Esempio n. 2
0
    def _parse_string(self, name, skip_scene_detection=False):  # pylint: disable=too-many-locals, too-many-branches, too-many-statements
        if not name:
            return

        matches = []
        bestResult = None

        for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes:
            match = cur_regex.match(name)

            if not match:
                continue

            result = ParseResult(name)
            result.which_regex = [cur_regex_name]
            result.score = 0 - cur_regex_num

            named_groups = match.groupdict().keys()

            if 'series_name' in named_groups:
                result.series_name = match.group('series_name')
                if result.series_name:
                    result.series_name = self.clean_series_name(result.series_name)
                    result.score += 1

            if 'series_num' in named_groups and match.group('series_num'):
                result.score += 1

            if 'season_num' in named_groups:
                tmp_season = int(match.group('season_num'))
                if cur_regex_name == 'bare' and tmp_season in (19, 20):
                    continue
                if cur_regex_name == 'fov' and tmp_season > 500:
                    continue

                result.season_number = tmp_season
                result.score += 1

            if 'ep_num' in named_groups:
                ep_num = self._convert_number(match.group('ep_num'))
                if 'extra_ep_num' in named_groups and match.group('extra_ep_num'):
                    tmp_episodes = range(ep_num, self._convert_number(match.group('extra_ep_num')) + 1)
                    if len(tmp_episodes) > 4:
                        matches = []
                        break
                else:
                    tmp_episodes = [ep_num]

                result.episode_numbers = tmp_episodes
                result.score += 3

            if 'ep_ab_num' in named_groups:
                ep_ab_num = self._convert_number(match.group('ep_ab_num'))
                if 'extra_ab_ep_num' in named_groups and match.group('extra_ab_ep_num'):
                    result.ab_episode_numbers = range(ep_ab_num,
                                                      self._convert_number(match.group('extra_ab_ep_num')) + 1)
                    result.score += 1
                else:
                    result.ab_episode_numbers = [ep_ab_num]
                result.score += 1

            if 'air_date' in named_groups:
                air_date = match.group('air_date')
                try:
                    assert re.sub(r'[^\d]*', '', air_date) != '112263'
                    result.air_date = dateutil.parser.parse(air_date, fuzzy_with_tokens=True)[0].date()
                    result.score += 1
                except Exception:
                    continue

            if 'extra_info' in named_groups:
                tmp_extra_info = match.group('extra_info')

                # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
                if tmp_extra_info and cur_regex_name == 'season_only' and re.search(
                        r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I):
                    continue
                result.extra_info = tmp_extra_info
                result.score += 1

            if 'release_group' in named_groups:
                result.release_group = match.group('release_group')
                result.score += 1

            if 'version' in named_groups:
                # assigns version to anime file if detected using anime regex. Non-anime regex receives -1
                version = match.group('version')
                if version:
                    result.version = version
                else:
                    result.version = 1
            else:
                result.version = -1

            matches.append(result)

        if matches:
            # pick best match with highest score based on placement
            bestResult = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score)

            show = None
            if not self.naming_pattern:
                # try and create a show object for this result
                show = helpers.get_show(bestResult.series_name, self.tryIndexers)

            # confirm passed in show object indexer id matches result show object indexer id
            if show:
                if self.showObj and show.indexerid != self.showObj.indexerid:
                    show = None
                bestResult.show = show
            elif not show and self.showObj:
                bestResult.show = self.showObj

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

            # get quality
            bestResult.quality = common.Quality.nameQuality(name, bestResult.show.is_anime)

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

            # if we have an air-by-date show then get the real season/episode numbers
            if bestResult.is_air_by_date:
                airdate = bestResult.air_date.toordinal()
                main_db_con = db.DBConnection()
                sql_result = main_db_con.select(
                    "SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?",
                    [bestResult.show.indexerid, bestResult.show.indexer, airdate])

                season_number = None
                episode_numbers = []

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

                if season_number is None or not episode_numbers:
                    try:
                        lINDEXER_API_PARMS = sickbeard.indexerApi(bestResult.show.indexer).api_params.copy()

                        lINDEXER_API_PARMS['language'] = bestResult.show.lang or sickbeard.INDEXER_DEFAULT_LANGUAGE

                        t = sickbeard.indexerApi(bestResult.show.indexer).indexer(**lINDEXER_API_PARMS)

                        epObj = t[bestResult.show.indexerid].airedOn(bestResult.air_date)[0]

                        season_number = int(epObj["seasonnumber"])
                        episode_numbers = [int(epObj["episodenumber"])]
                    except sickbeard.indexer_episodenotfound:
                        logger.log("Unable to find episode with date " + six.text_type(bestResult.air_date) + " for show " + bestResult.show.name + ", skipping", logger.WARNING)
                        episode_numbers = []
                    except sickbeard.indexer_error as e:
                        logger.log("Unable to contact " + sickbeard.indexerApi(bestResult.show.indexer).name + ": " + ex(e), logger.WARNING)
                        episode_numbers = []

                for epNo in episode_numbers:
                    s = season_number
                    e = epNo

                    if bestResult.show.is_scene:
                        (s, e) = scene_numbering.get_indexer_numbering(bestResult.show.indexerid,
                                                                       bestResult.show.indexer,
                                                                       season_number,
                                                                       epNo)
                    new_episode_numbers.append(e)
                    new_season_numbers.append(s)

            elif bestResult.show.is_anime and bestResult.ab_episode_numbers:
                bestResult.scene_season = scene_exceptions.get_scene_exception_by_name(bestResult.series_name)[1]
                for epAbsNo in bestResult.ab_episode_numbers:
                    a = epAbsNo

                    if bestResult.show.is_scene and not skip_scene_detection:
                        a = scene_numbering.get_indexer_absolute_numbering(bestResult.show.indexerid,
                                                                           bestResult.show.indexer, epAbsNo,
                                                                           True, bestResult.scene_season)

                    (s, e) = helpers.get_all_episodes_from_absolute_number(bestResult.show, [a])

                    new_absolute_numbers.append(a)
                    new_episode_numbers.extend(e)
                    new_season_numbers.append(s)

            elif bestResult.season_number and bestResult.episode_numbers:
                for epNo in bestResult.episode_numbers:
                    s = bestResult.season_number
                    e = epNo

                    if bestResult.show.is_scene and not skip_scene_detection:
                        (s, e) = scene_numbering.get_indexer_numbering(bestResult.show.indexerid,
                                                                       bestResult.show.indexer,
                                                                       bestResult.season_number,
                                                                       epNo)
                    if bestResult.show.is_anime:
                        a = helpers.get_absolute_number_from_season_and_episode(bestResult.show, s, e)
                        if a:
                            new_absolute_numbers.append(a)

                    new_episode_numbers.append(e)
                    new_season_numbers.append(s)

            # 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 sickbeard, so we'd need to flag it.
            new_season_numbers = list(set(new_season_numbers))  # remove duplicates
            if len(new_season_numbers) > 1:
                raise InvalidNameException(("Scene numbering results episodes from "
                                            "seasons %s, (i.e. more than one) and "
                                            "sickrage does not support this.  "
                                            "Sorry.").format(six.text_type(new_season_numbers)))

            # I guess it's possible that we'd have duplicate episodes too, so lets
            # eliminate them
            new_episode_numbers = list(set(new_episode_numbers))
            new_episode_numbers.sort()

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

            if new_absolute_numbers:
                bestResult.ab_episode_numbers = new_absolute_numbers

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

            if bestResult.show.is_scene and not skip_scene_detection:
                logger.log(
                    "Converted parsed result " + bestResult.original_name + " into " + six.text_type(bestResult), logger.DEBUG)

        # CPU sleep
        time.sleep(0.02)

        return bestResult
Esempio n. 3
0
    def convert(self):
        if not self.show:
            return self  # can't convert with out a show object

        if self.air_by_date or self.sports:  # scene numbering does not apply to air-by-date or sports shows
            return self

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

        if self.show.is_anime and len(self.ab_episode_numbers):
            for epAbsNo in self.ab_episode_numbers:
                a = scene_numbering.get_indexer_absolute_numbering(
                    self.show.indexerid, self.show.indexer, epAbsNo)
                if a:
                    (s, e) = helpers.get_all_episodes_from_absolute_number(
                        self.show, None, [a])

                    new_absolute_numbers.append(a)
                    new_episode_numbers.extend(e)
                    new_season_numbers.append(s)

        elif self.season_number and len(self.episode_numbers):
            for epNo in self.episode_numbers:
                (s, e) = scene_numbering.get_indexer_numbering(
                    self.show.indexerid, self.show.indexer, self.season_number,
                    epNo)
                if self.show.is_anime:
                    a = helpers.get_absolute_number_from_season_and_episode(
                        self.show, s, e)
                    if a:
                        new_absolute_numbers.append(a)

                new_episode_numbers.append(e)
                new_season_numbers.append(s)

        # 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 sickbeard, so we'd need to flag it.
        new_season_numbers = list(set(new_season_numbers))  # remove duplicates
        if len(new_season_numbers) > 1:
            raise InvalidNameException("Scene numbering results episodes from "
                                       "seasons %s, (i.e. more than one) and "
                                       "sickrage does not support this.  "
                                       "Sorry." % (str(new_season_numbers)))

        # I guess it's possible that we'd have duplicate episodes too, so lets
        # eliminate them
        new_episode_numbers = list(set(new_episode_numbers))
        new_episode_numbers.sort()

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

        if len(new_absolute_numbers):
            self.ab_episode_numbers = new_absolute_numbers

        if len(new_season_numbers) and len(new_episode_numbers):
            self.episode_numbers = new_episode_numbers
            self.season_number = new_season_numbers[0]

        return self
Esempio n. 4
0
    def _parse_string(self, name, skip_scene_detection=False):  # pylint: disable=too-many-locals, too-many-branches, too-many-statements
        if not name:
            return

        matches = []
        bestResult = None

        for (cur_regex_num, cur_regex_name,
             cur_regex) in self.compiled_regexes:
            match = cur_regex.match(name)

            if not match:
                continue

            result = ParseResult(name)
            result.which_regex = [cur_regex_name]
            result.score = 0 - cur_regex_num

            named_groups = match.groupdict().keys()

            if 'series_name' in named_groups:
                result.series_name = match.group('series_name')
                if result.series_name:
                    result.series_name = self.clean_series_name(
                        result.series_name)
                    result.score += 1

            if 'series_num' in named_groups and match.group('series_num'):
                result.score += 1

            if 'season_num' in named_groups:
                tmp_season = int(match.group('season_num'))
                if cur_regex_name == 'bare' and tmp_season in (19, 20):
                    continue
                if cur_regex_name == 'fov' and tmp_season > 500:
                    continue

                result.season_number = tmp_season
                result.score += 1

            if 'ep_num' in named_groups:
                ep_num = self._convert_number(match.group('ep_num'))
                if 'extra_ep_num' in named_groups and match.group(
                        'extra_ep_num'):
                    tmp_episodes = range(
                        ep_num,
                        self._convert_number(match.group('extra_ep_num')) + 1)
                    if len(tmp_episodes) > 4:
                        matches = []
                        break
                else:
                    tmp_episodes = [ep_num]

                result.episode_numbers = tmp_episodes
                result.score += 3

            if 'ep_ab_num' in named_groups:
                ep_ab_num = self._convert_number(match.group('ep_ab_num'))
                if 'extra_ab_ep_num' in named_groups and match.group(
                        'extra_ab_ep_num'):
                    result.ab_episode_numbers = range(
                        ep_ab_num,
                        self._convert_number(match.group('extra_ab_ep_num')) +
                        1)
                    result.score += 1
                else:
                    result.ab_episode_numbers = [ep_ab_num]
                result.score += 1

            if 'air_date' in named_groups:
                air_date = match.group('air_date')
                try:
                    assert re.sub(r'[^\d]*', '', air_date) != '112263'
                    result.air_date = dateutil.parser.parse(
                        air_date, fuzzy_with_tokens=True)[0].date()
                    result.score += 1
                except Exception:
                    continue

            if 'extra_info' in named_groups:
                tmp_extra_info = match.group('extra_info')

                # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
                if tmp_extra_info and cur_regex_name == 'season_only' and re.search(
                        r'([. _-]|^)(special|extra)s?\w*([. _-]|$)',
                        tmp_extra_info, re.I):
                    continue
                result.extra_info = tmp_extra_info
                result.score += 1

            if 'release_group' in named_groups:
                result.release_group = match.group('release_group')
                result.score += 1

            if 'version' in named_groups:
                # assigns version to anime file if detected using anime regex. Non-anime regex receives -1
                version = match.group('version')
                if version:
                    result.version = version
                else:
                    result.version = 1
            else:
                result.version = -1

            matches.append(result)

        if matches:
            # pick best match with highest score based on placement
            bestResult = max(sorted(matches,
                                    reverse=True,
                                    key=lambda x: x.which_regex),
                             key=lambda x: x.score)

            show = None
            if not self.naming_pattern:
                # try and create a show object for this result
                show = helpers.get_show(bestResult.series_name,
                                        self.tryIndexers)

            # confirm passed in show object indexer id matches result show object indexer id
            if show:
                if self.showObj and show.indexerid != self.showObj.indexerid:
                    show = None
                bestResult.show = show
            elif not show and self.showObj:
                bestResult.show = self.showObj

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

            # get quality
            bestResult.quality = common.Quality.nameQuality(
                name, bestResult.show.is_anime)

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

            # if we have an air-by-date show then get the real season/episode numbers
            if bestResult.is_air_by_date:
                airdate = bestResult.air_date.toordinal()
                main_db_con = db.DBConnection()
                sql_result = main_db_con.select(
                    "SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?",
                    [
                        bestResult.show.indexerid, bestResult.show.indexer,
                        airdate
                    ])

                season_number = None
                episode_numbers = []

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

                if season_number is None or not episode_numbers:
                    try:
                        lINDEXER_API_PARMS = sickbeard.indexerApi(
                            bestResult.show.indexer).api_params.copy()

                        lINDEXER_API_PARMS[
                            'language'] = bestResult.show.lang or sickbeard.INDEXER_DEFAULT_LANGUAGE

                        t = sickbeard.indexerApi(
                            bestResult.show.indexer).indexer(
                                **lINDEXER_API_PARMS)

                        epObj = t[bestResult.show.indexerid].airedOn(
                            bestResult.air_date)[0]

                        season_number = int(epObj["seasonnumber"])
                        episode_numbers = [int(epObj["episodenumber"])]
                    except sickbeard.indexer_episodenotfound:
                        logger.log(
                            u"Unable to find episode with date " +
                            str(bestResult.air_date) + " for show " +
                            bestResult.show.name + ", skipping",
                            logger.WARNING)
                        episode_numbers = []
                    except sickbeard.indexer_error as e:
                        logger.log(
                            u"Unable to contact " + sickbeard.indexerApi(
                                bestResult.show.indexer).name + ": " + ex(e),
                            logger.WARNING)
                        episode_numbers = []

                for epNo in episode_numbers:
                    s = season_number
                    e = epNo

                    if bestResult.show.is_scene:
                        (s, e) = scene_numbering.get_indexer_numbering(
                            bestResult.show.indexerid, bestResult.show.indexer,
                            season_number, epNo)
                    new_episode_numbers.append(e)
                    new_season_numbers.append(s)

            elif bestResult.show.is_anime and bestResult.ab_episode_numbers:
                bestResult.scene_season = scene_exceptions.get_scene_exception_by_name(
                    bestResult.series_name)[1]
                for epAbsNo in bestResult.ab_episode_numbers:
                    a = epAbsNo

                    if bestResult.show.is_scene and not skip_scene_detection:
                        a = scene_numbering.get_indexer_absolute_numbering(
                            bestResult.show.indexerid, bestResult.show.indexer,
                            epAbsNo, True, bestResult.scene_season)

                    (s, e) = helpers.get_all_episodes_from_absolute_number(
                        bestResult.show, [a])

                    new_absolute_numbers.append(a)
                    new_episode_numbers.extend(e)
                    new_season_numbers.append(s)

            elif bestResult.season_number and bestResult.episode_numbers:
                for epNo in bestResult.episode_numbers:
                    s = bestResult.season_number
                    e = epNo

                    if bestResult.show.is_scene and not skip_scene_detection:
                        (s, e) = scene_numbering.get_indexer_numbering(
                            bestResult.show.indexerid, bestResult.show.indexer,
                            bestResult.season_number, epNo)
                    if bestResult.show.is_anime:
                        a = helpers.get_absolute_number_from_season_and_episode(
                            bestResult.show, s, e)
                        if a:
                            new_absolute_numbers.append(a)

                    new_episode_numbers.append(e)
                    new_season_numbers.append(s)

            # 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 sickbeard, so we'd need to flag it.
            new_season_numbers = list(
                set(new_season_numbers))  # remove duplicates
            if len(new_season_numbers) > 1:
                raise InvalidNameException(
                    "Scene numbering results episodes from "
                    "seasons %s, (i.e. more than one) and "
                    "sickrage does not support this.  "
                    "Sorry." % (str(new_season_numbers)))

            # I guess it's possible that we'd have duplicate episodes too, so lets
            # eliminate them
            new_episode_numbers = list(set(new_episode_numbers))
            new_episode_numbers.sort()

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

            if new_absolute_numbers:
                bestResult.ab_episode_numbers = new_absolute_numbers

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

            if bestResult.show.is_scene and not skip_scene_detection:
                logger.log(
                    u"Converted parsed result " + bestResult.original_name +
                    " into " +
                    str(bestResult).decode('utf-8', 'xmlcharrefreplace'),
                    logger.DEBUG)

        # CPU sleep
        time.sleep(0.02)

        return bestResult
Esempio n. 5
0
    def convert(self):
        if not self.show:
            return self  # can't convert with out a show object

        if self.air_by_date or self.sports:  # scene numbering does not apply to air-by-date or sports shows
            return self

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

        if self.show.is_anime and len(self.ab_episode_numbers):
            for epAbsNo in self.ab_episode_numbers:
                ab = scene_numbering.get_indexer_absolute_numbering(self.show.indexerid, self.show.indexer, epAbsNo)
                if ab:
                    try:
                        (s, e) = helpers.get_all_episodes_from_absolute_number(self.show, None, [ab])
                    except exceptions.EpisodeNotFoundByAbsoluteNumberException:
                        logger.log(str(self.show.indexerid) + ": Indexer object absolute number " + str(
                            ab) + " is incomplete, skipping this episode")
                        return self
                    else:
                        new_absolute_numbers.append(ab)
                        new_episode_numbers.extend(e)
                        new_season_numbers.append(s)

        elif self.season_number and len(self.episode_numbers):
            for epNo in self.episode_numbers:
                (s, e) = scene_numbering.get_indexer_numbering(self.show.indexerid, self.show.indexer,
                                                               self.season_number,
                                                               epNo)
                if self.show.is_anime:
                    a = helpers.get_absolute_number_from_season_and_episode(self.show, s, e)
                    if a:
                        new_absolute_numbers.append(a)

                new_episode_numbers.append(e)
                new_season_numbers.append(s)

        # 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 sickbeard, so we'd need to flag it.
        new_season_numbers = list(set(new_season_numbers))  # remove duplicates
        if len(new_season_numbers) > 1:
            raise InvalidNameException("Scene numbering results episodes from "
                                       "seasons %s, (i.e. more than one) and "
                                       "sickrage does not support this.  "
                                       "Sorry." % (str(new_season_numbers)))

        # I guess it's possible that we'd have duplicate episodes too, so lets
        # eliminate them
        new_episode_numbers = list(set(new_episode_numbers))
        new_episode_numbers.sort()

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

        if len(new_absolute_numbers):
            self.ab_episode_numbers = new_absolute_numbers

        if len(new_season_numbers) and len(new_episode_numbers):
            self.episode_numbers = new_episode_numbers
            self.season_number = new_season_numbers[0]

        logger.log(u"Converted parsed result " + self.original_name + " into " + str(self).decode('utf-8',
                                                                                                  'xmlcharrefreplace'),
                   logger.DEBUG)

        return self
Esempio n. 6
0
    def _parse_string(self, name):
        if not name:
            return

        matches = []
        bestResult = None

        for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes:
            match = cur_regex.match(name)

            if not match:
                continue

            result = ParseResult(name)
            result.which_regex = [cur_regex_name]
            result.score = 0 - cur_regex_num

            named_groups = match.groupdict().keys()

            if 'series_name' in named_groups:
                result.series_name = match.group('series_name')
                if result.series_name:
                    result.series_name = self.clean_series_name(result.series_name)
                    result.score += 1

            if 'season_num' in named_groups:
                tmp_season = int(match.group('season_num'))
                if cur_regex_name == 'bare' and tmp_season in (19, 20):
                    continue
                result.season_number = tmp_season
                result.score += 1

            if 'ep_num' in named_groups:
                ep_num = self._convert_number(match.group('ep_num'))
                if 'extra_ep_num' in named_groups and match.group('extra_ep_num'):
                    result.episode_numbers = range(ep_num, self._convert_number(match.group('extra_ep_num')) + 1)
                    result.score += 1
                else:
                    result.episode_numbers = [ep_num]
                result.score += 1

            if 'ep_ab_num' in named_groups:
                ep_ab_num = self._convert_number(match.group('ep_ab_num'))
                if 'extra_ab_ep_num' in named_groups and match.group('extra_ab_ep_num'):
                    result.ab_episode_numbers = range(ep_ab_num,
                                                      self._convert_number(match.group('extra_ab_ep_num')) + 1)
                    result.score += 1
                else:
                    result.ab_episode_numbers = [ep_ab_num]
                result.score += 1

            if 'sports_event_id' in named_groups:
                sports_event_id = match.group('sports_event_id')
                if sports_event_id:
                    result.sports_event_id = int(match.group('sports_event_id'))
                    result.score += 1

            if 'sports_event_name' in named_groups:
                result.sports_event_name = match.group('sports_event_name')
                if result.sports_event_name:
                    result.sports_event_name = self.clean_series_name(result.sports_event_name)
                    result.score += 1

            if 'sports_air_date' in named_groups:
                sports_air_date = match.group('sports_air_date')
                if result.show and result.show.is_sports:
                    try:
                        result.sports_air_date = parser.parse(sports_air_date, fuzzy=True).date()
                        result.score += 1
                    except:
                        continue

            if 'air_year' in named_groups and 'air_month' in named_groups and 'air_day' in named_groups:
                if result.show and result.show.air_by_date:
                    year = int(match.group('air_year'))
                    month = int(match.group('air_month'))
                    day = int(match.group('air_day'))

                    try:
                        dtStr = '%s-%s-%s' % (year, month, day)
                        result.air_date = datetime.datetime.strptime(dtStr, "%Y-%m-%d").date()
                        result.score += 1
                    except:
                        continue

            if 'extra_info' in named_groups:
                tmp_extra_info = match.group('extra_info')

                # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
                if tmp_extra_info and cur_regex_name == 'season_only' and re.search(
                        r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I):
                    continue
                result.extra_info = tmp_extra_info
                result.score += 1

            if 'release_group' in named_groups:
                result.release_group = match.group('release_group')
                result.score += 1

            if 'version' in named_groups:
                # assigns version to anime file if detected using anime regex. Non-anime regex receives -1
                version = match.group('version')
                if version:
                    result.version = version
                else:
                    result.version = 1
            else:
                result.version = -1


            matches.append(result)

        if len(matches):
            # pick best match with highest score based on placement
            bestResult = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score)

            show = None
            if not self.naming_pattern:
                # try and create a show object for this result
                show = helpers.get_show(bestResult.series_name, self.tryIndexers)

            # confirm passed in show object indexer id matches result show object indexer id
            if show:
                if self.showObj and show.indexerid != self.showObj.indexerid:
                    show = None
                bestResult.show = show
            elif not show and self.showObj:
                bestResult.show = self.showObj

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

            # get quality
            bestResult.quality = common.Quality.nameQuality(name, bestResult.show.is_anime)

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

            # if we have an air-by-date show then get the real season/episode numbers
            if bestResult.is_air_by_date or bestResult.is_sports:
                airdate = bestResult.air_date.toordinal() if bestResult.air_date else bestResult.sports_air_date.toordinal()

                myDB = db.DBConnection()
                sql_result = myDB.select(
                    "SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?",
                    [bestResult.show.indexerid, bestResult.show.indexer, airdate])

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

                    for epNo in episode_numbers:
                        s = season_number
                        e = epNo

                        if self.convert:
                            (s, e) = scene_numbering.get_indexer_numbering(bestResult.show.indexerid,
                                                                           bestResult.show.indexer,
                                                                           season_number,
                                                                           epNo)
                        new_episode_numbers.append(e)
                        new_season_numbers.append(s)

            elif bestResult.show.is_anime and len(bestResult.ab_episode_numbers):
                scene_season = scene_exceptions.get_scene_exception_by_name(bestResult.series_name)[1]
                for epAbsNo in bestResult.ab_episode_numbers:
                    a = epAbsNo

                    if self.convert:
                        a = scene_numbering.get_indexer_absolute_numbering(bestResult.show.indexerid,
                                                                           bestResult.show.indexer, epAbsNo,
                                                                           True, scene_season)

                    (s, e) = helpers.get_all_episodes_from_absolute_number(bestResult.show, [a])

                    new_absolute_numbers.append(a)
                    new_episode_numbers.extend(e)
                    new_season_numbers.append(s)

            elif bestResult.season_number and len(bestResult.episode_numbers):
                for epNo in bestResult.episode_numbers:
                    s = bestResult.season_number
                    e = epNo

                    if self.convert:
                        (s, e) = scene_numbering.get_indexer_numbering(bestResult.show.indexerid,
                                                                       bestResult.show.indexer,
                                                                       bestResult.season_number,
                                                                       epNo)
                    if bestResult.show.is_anime:
                        a = helpers.get_absolute_number_from_season_and_episode(bestResult.show, s, e)
                        if a:
                            new_absolute_numbers.append(a)

                    new_episode_numbers.append(e)
                    new_season_numbers.append(s)

            # 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 sickbeard, so we'd need to flag it.
            new_season_numbers = list(set(new_season_numbers))  # remove duplicates
            if len(new_season_numbers) > 1:
                raise InvalidNameException("Scene numbering results episodes from "
                                           "seasons %s, (i.e. more than one) and "
                                           "sickrage does not support this.  "
                                           "Sorry." % (str(new_season_numbers)))

            # I guess it's possible that we'd have duplicate episodes too, so lets
            # eliminate them
            new_episode_numbers = list(set(new_episode_numbers))
            new_episode_numbers.sort()

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

            if len(new_absolute_numbers):
                bestResult.ab_episode_numbers = new_absolute_numbers

            if len(new_season_numbers) and len(new_episode_numbers):
                bestResult.episode_numbers = new_episode_numbers
                bestResult.season_number = new_season_numbers[0]

            if self.convert:
                logger.log(
                    u"Converted parsed result " + bestResult.original_name + " into " + str(bestResult).decode('utf-8',
                                                                                                               'xmlcharrefreplace'),
                    logger.DEBUG)

        # CPU sleep
        time.sleep(0.02)

        return bestResult
Esempio n. 7
0
    def _parse_string(self, name):
        if not name:
            return

        matches = []
        bestResult = None

        for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes:
            match = cur_regex.match(name)

            if not match:
                continue

            result = ParseResult(name)
            result.which_regex = [cur_regex_name]
            result.score = 0 - cur_regex_num

            named_groups = match.groupdict().keys()

            if "series_name" in named_groups:
                result.series_name = match.group("series_name")
                if result.series_name:
                    result.series_name = self.clean_series_name(result.series_name)
                    result.score += 1

            if "series_num" in named_groups and match.group("series_num"):
                result.score += 1

            if "season_num" in named_groups:
                tmp_season = int(match.group("season_num"))
                if cur_regex_name == "bare" and tmp_season in (19, 20):
                    continue
                result.season_number = tmp_season
                result.score += 1

            if "ep_num" in named_groups:
                ep_num = self._convert_number(match.group("ep_num"))
                if "extra_ep_num" in named_groups and match.group("extra_ep_num"):
                    result.episode_numbers = range(ep_num, self._convert_number(match.group("extra_ep_num")) + 1)
                    result.score += 1
                else:
                    result.episode_numbers = [ep_num]
                result.score += 1

            if "ep_ab_num" in named_groups:
                ep_ab_num = self._convert_number(match.group("ep_ab_num"))
                if "extra_ab_ep_num" in named_groups and match.group("extra_ab_ep_num"):
                    result.ab_episode_numbers = range(
                        ep_ab_num, self._convert_number(match.group("extra_ab_ep_num")) + 1
                    )
                    result.score += 1
                else:
                    result.ab_episode_numbers = [ep_ab_num]
                result.score += 1

            if "air_date" in named_groups:
                air_date = match.group("air_date")
                try:
                    result.air_date = parser.parse(air_date, fuzzy=True).date()
                    result.score += 1
                except Exception:
                    continue

            if "extra_info" in named_groups:
                tmp_extra_info = match.group("extra_info")

                # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
                if (
                    tmp_extra_info
                    and cur_regex_name == "season_only"
                    and re.search(r"([. _-]|^)(special|extra)s?\w*([. _-]|$)", tmp_extra_info, re.I)
                ):
                    continue
                result.extra_info = tmp_extra_info
                result.score += 1

            if "release_group" in named_groups:
                result.release_group = match.group("release_group")
                result.score += 1

            if "version" in named_groups:
                # assigns version to anime file if detected using anime regex. Non-anime regex receives -1
                version = match.group("version")
                if version:
                    result.version = version
                else:
                    result.version = 1
            else:
                result.version = -1

            matches.append(result)

        if len(matches):
            # pick best match with highest score based on placement
            bestResult = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score)

            show = None
            if not self.naming_pattern:
                # try and create a show object for this result
                show = helpers.get_show(bestResult.series_name, self.tryIndexers, self.trySceneExceptions)

            # confirm passed in show object indexer id matches result show object indexer id
            if show:
                if self.showObj and show.indexerid != self.showObj.indexerid:
                    show = None
                bestResult.show = show
            elif not show and self.showObj:
                bestResult.show = self.showObj

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

            # get quality
            bestResult.quality = common.Quality.nameQuality(name, bestResult.show.is_anime)

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

            # if we have an air-by-date show then get the real season/episode numbers
            if bestResult.is_air_by_date:
                airdate = bestResult.air_date.toordinal()
                myDB = db.DBConnection()
                sql_result = myDB.select(
                    "SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?",
                    [bestResult.show.indexerid, bestResult.show.indexer, airdate],
                )

                season_number = None
                episode_numbers = []

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

                if not season_number or not len(episode_numbers):
                    try:
                        lINDEXER_API_PARMS = sickbeard.indexerApi(bestResult.show.indexer).api_params.copy()

                        if bestResult.show.lang:
                            lINDEXER_API_PARMS["language"] = bestResult.show.lang

                        t = sickbeard.indexerApi(bestResult.show.indexer).indexer(**lINDEXER_API_PARMS)

                        epObj = t[bestResult.show.indexerid].airedOn(bestResult.air_date)[0]

                        season_number = int(epObj["seasonnumber"])
                        episode_numbers = [int(epObj["episodenumber"])]
                    except sickbeard.indexer_episodenotfound:
                        logger.log(
                            u"Unable to find episode with date "
                            + str(bestResult.air_date)
                            + " for show "
                            + bestResult.show.name
                            + ", skipping",
                            logger.WARNING,
                        )
                        episode_numbers = []
                    except sickbeard.indexer_error, e:
                        logger.log(
                            u"Unable to contact " + sickbeard.indexerApi(bestResult.show.indexer).name + ": " + ex(e),
                            logger.WARNING,
                        )
                        episode_numbers = []

                for epNo in episode_numbers:
                    s = season_number
                    e = epNo

                    if bestResult.show.is_scene:
                        (s, e) = scene_numbering.get_indexer_numbering(
                            bestResult.show.indexerid, bestResult.show.indexer, season_number, epNo
                        )
                    new_episode_numbers.append(e)
                    new_season_numbers.append(s)

            elif bestResult.show.is_anime and len(bestResult.ab_episode_numbers):
                scene_season = scene_exceptions.get_scene_exception_by_name(bestResult.series_name)[1]
                for epAbsNo in bestResult.ab_episode_numbers:
                    a = epAbsNo

                    if bestResult.show.is_scene:
                        a = scene_numbering.get_indexer_absolute_numbering(
                            bestResult.show.indexerid, bestResult.show.indexer, epAbsNo, True, scene_season
                        )

                    (s, e) = helpers.get_all_episodes_from_absolute_number(bestResult.show, [a])

                    new_absolute_numbers.append(a)
                    new_episode_numbers.extend(e)
                    new_season_numbers.append(s)

            elif bestResult.season_number and len(bestResult.episode_numbers):
                for epNo in bestResult.episode_numbers:
                    s = bestResult.season_number
                    e = epNo

                    if bestResult.show.is_scene:
                        (s, e) = scene_numbering.get_indexer_numbering(
                            bestResult.show.indexerid, bestResult.show.indexer, bestResult.season_number, epNo
                        )
                    if bestResult.show.is_anime:
                        a = helpers.get_absolute_number_from_season_and_episode(bestResult.show, s, e)
                        if a:
                            new_absolute_numbers.append(a)

                    new_episode_numbers.append(e)
                    new_season_numbers.append(s)

            # 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 sickbeard, so we'd need to flag it.
            new_season_numbers = list(set(new_season_numbers))  # remove duplicates
            if len(new_season_numbers) > 1:
                raise InvalidNameException(
                    "Scene numbering results episodes from "
                    "seasons %s, (i.e. more than one) and "
                    "sickrage does not support this.  "
                    "Sorry." % (str(new_season_numbers))
                )

            # I guess it's possible that we'd have duplicate episodes too, so lets
            # eliminate them
            new_episode_numbers = list(set(new_episode_numbers))
            new_episode_numbers.sort()

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

            if len(new_absolute_numbers):
                bestResult.ab_episode_numbers = new_absolute_numbers

            if len(new_season_numbers) and len(new_episode_numbers):
                bestResult.episode_numbers = new_episode_numbers
                bestResult.season_number = new_season_numbers[0]

            if bestResult.show.is_scene:
                logger.log(
                    u"Converted parsed result "
                    + bestResult.original_name
                    + " into "
                    + str(bestResult).decode("utf-8", "xmlcharrefreplace"),
                    logger.DEBUG,
                )
Esempio n. 8
0
    def convert(self):
        if not self.show:
            return self  # can't convert with out a show object

        if self.air_by_date or self.sports:  # scene numbering does not apply to air-by-date or sports shows
            return self

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

        if self.show.is_anime and len(self.ab_episode_numbers):
            for epAbsNo in self.ab_episode_numbers:
                a = scene_numbering.get_indexer_absolute_numbering(self.show.indexerid, self.show.indexer, epAbsNo)
                if a:
                    (s, e) = helpers.get_all_episodes_from_absolute_number(self.show, None, [a])

                    new_absolute_numbers.append(a)
                    new_episode_numbers.extend(e)
                    new_season_numbers.append(s)

        elif self.season_number and len(self.episode_numbers):
            for epNo in self.episode_numbers:
                (s, e) = scene_numbering.get_indexer_numbering(self.show.indexerid, self.show.indexer,
                                                               self.season_number,
                                                               epNo)
                if self.show.is_anime:
                    a = helpers.get_absolute_number_from_season_and_episode(self.show, s, e)
                    if a:
                        new_absolute_numbers.append(a)

                new_episode_numbers.append(e)
                new_season_numbers.append(s)

        # 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 sickbeard, so we'd need to flag it.
        new_season_numbers = list(set(new_season_numbers))  # remove duplicates
        if len(new_season_numbers) > 1:
            raise InvalidNameException("Scene numbering results episodes from "
                                       "seasons %s, (i.e. more than one) and "
                                       "sickrage does not support this.  "
                                       "Sorry." % (str(new_season_numbers)))

        # I guess it's possible that we'd have duplicate episodes too, so lets
        # eliminate them
        new_episode_numbers = list(set(new_episode_numbers))
        new_episode_numbers.sort()

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

        if len(new_absolute_numbers):
            self.ab_episode_numbers = new_absolute_numbers

        if len(new_season_numbers) and len(new_episode_numbers):
            self.episode_numbers = new_episode_numbers
            self.season_number = new_season_numbers[0]

        return self
Esempio n. 9
0
    def _parse_string(self, name):
        if not name:
            return

        matches = []
        initial_best_result = None
        for reg_ex in self.compiled_regexes:
            for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes[reg_ex]:
                new_name = helpers.remove_non_release_groups(name, 'anime' in cur_regex_name)
                match = cur_regex.match(new_name)

                if not match:
                    continue

                if 'garbage_name' == cur_regex_name:
                    return

                result = ParseResult(new_name)
                result.which_regex = [cur_regex_name]
                result.score = 0 - cur_regex_num

                named_groups = match.groupdict().keys()

                if 'series_name' in named_groups:
                    result.series_name = match.group('series_name')
                    if result.series_name:
                        result.series_name = self.clean_series_name(result.series_name)
                        name_parts = re.match('(?i)(.*)[ -]((?:part|pt)[ -]?\w+)$', result.series_name)
                        try:
                            result.series_name = name_parts.group(1)
                            result.extra_info = name_parts.group(2)
                        except (AttributeError, IndexError):
                            pass

                        result.score += 1

                if 'anime' in cur_regex_name and not (self.showObj and self.showObj.is_anime):
                    p_show = helpers.get_show(result.series_name, True)
                    if p_show and self.showObj and p_show.indexerid != self.showObj.indexerid:
                        p_show = None
                    if not p_show and self.showObj:
                        p_show = self.showObj
                    if p_show and not p_show.is_anime:
                        continue

                if 'series_num' in named_groups and match.group('series_num'):
                    result.score += 1

                if 'season_num' in named_groups:
                    tmp_season = int(match.group('season_num'))
                    if 'bare' == cur_regex_name and tmp_season in (19, 20):
                        continue
                    result.season_number = tmp_season
                    result.score += 1

                def _process_epnum(captures, capture_names, grp_name, extra_grp_name, ep_numbers, parse_result):
                    ep_num = self._convert_number(captures.group(grp_name))
                    extra_grp_name = 'extra_%s' % extra_grp_name
                    ep_numbers = '%sepisode_numbers' % ep_numbers
                    if extra_grp_name in capture_names and captures.group(extra_grp_name):
                        try:
                            if hasattr(self.showObj, 'getEpisode'):
                                ep = self.showObj.getEpisode(parse_result.season_number, ep_num)
                            else:
                                tmp_show = helpers.get_show(parse_result.series_name, True, False)
                                if tmp_show and hasattr(tmp_show, 'getEpisode'):
                                    ep = tmp_show.getEpisode(parse_result.season_number, ep_num)
                                else:
                                    ep = None
                        except (StandardError, Exception):
                            ep = None
                        en = ep and ep.name and re.match(r'^\W*(\d+)', ep.name) or None
                        es = en and en.group(1) or None

                        extra_ep_num = self._convert_number(captures.group(extra_grp_name))
                        parse_result.__dict__[ep_numbers] = range(ep_num, extra_ep_num + 1) if not (
                            ep and es and es != captures.group(extra_grp_name)) and (
                            0 < extra_ep_num - ep_num < 10) else [ep_num]
                        parse_result.score += 1
                    else:
                        parse_result.__dict__[ep_numbers] = [ep_num]
                    parse_result.score += 1
                    return parse_result

                if 'ep_num' in named_groups:
                    result = _process_epnum(match, named_groups, 'ep_num', 'ep_num', '', result)

                if 'ep_ab_num' in named_groups:
                    result = _process_epnum(match, named_groups, 'ep_ab_num', 'ab_ep_num', 'ab_', result)

                if 'air_year' in named_groups and 'air_month' in named_groups and 'air_day' in named_groups:
                    year = int(match.group('air_year'))
                    try:
                        month = int(match.group('air_month'))
                    except ValueError:
                        try:
                            month = time.strptime(match.group('air_month')[0:3], '%b').tm_mon
                        except ValueError as e:
                            raise InvalidNameException(ex(e))
                    day = int(match.group('air_day'))
                    # make an attempt to detect YYYY-DD-MM formats
                    if 12 < month:
                        tmp_month = month
                        month = day
                        day = tmp_month
                    try:
                        result.air_date = datetime.date(
                            year + ((1900, 2000)[0 < year < 28], 0)[1900 < year], month, day)
                    except ValueError as e:
                        raise InvalidNameException(ex(e))

                if 'extra_info' in named_groups:
                    tmp_extra_info = match.group('extra_info')

                    # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
                    if tmp_extra_info and 'season_only' == cur_regex_name and re.search(
                            r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I):
                        continue
                    if tmp_extra_info:
                        if result.extra_info:
                            tmp_extra_info = '%s %s' % (result.extra_info, tmp_extra_info)
                        result.extra_info = tmp_extra_info
                    result.score += 1

                if 'release_group' in named_groups:
                    result.release_group = match.group('release_group')
                    result.score += 1

                if 'version' in named_groups:
                    # assigns version to anime file if detected using anime regex. Non-anime regex receives -1
                    version = match.group('version')
                    if version:
                        result.version = helpers.tryInt(version)
                    else:
                        result.version = 1
                else:
                    result.version = -1

                if None is result.season_number and result.episode_numbers and not result.air_date and \
                        cur_regex_name in ['no_season', 'no_season_general', 'no_season_multi_ep'] and \
                        re.search(r'(?i)\bpart.?\d{1,2}\b', result.original_name):
                    result.season_number = 1

                matches.append(result)

            if len(matches):
                # pick best match with highest score based on placement
                best_result = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score)

                show = None
                if not self.naming_pattern:
                    # try and create a show object for this result
                    show = helpers.get_show(best_result.series_name, self.try_scene_exceptions)

                # confirm passed in show object indexer id matches result show object indexer id
                if show and not self.testing:
                    if self.showObj and show.indexerid != self.showObj.indexerid:
                        show = None
                elif not show and self.showObj:
                    show = self.showObj
                best_result.show = show
                if not best_result.series_name and getattr(show, 'name', None):
                    best_result.series_name = show.name

                if show and show.is_anime and 1 < len(self.compiled_regexes[1]) and 1 != reg_ex:
                    continue

                # if this is a naming pattern test then return best result
                if not show or self.naming_pattern:
                    if not show and not self.naming_pattern and not self.testing:
                        # ensure anime regex test but use initial best if show still not found
                        if 0 == reg_ex:
                            initial_best_result = best_result
                            matches = []  # clear non-anime match scores
                            continue
                        return initial_best_result
                    return best_result

                # get quality
                new_name = helpers.remove_non_release_groups(name, show.is_anime)
                best_result.quality = common.Quality.nameQuality(new_name, show.is_anime)

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

                # if we have an air-by-date show then get the real season/episode numbers
                if best_result.is_air_by_date:
                    season_number, episode_numbers = None, []

                    airdate = best_result.air_date.toordinal()
                    my_db = db.DBConnection()
                    sql_result = my_db.select(
                        'SELECT season, episode, name FROM tv_episodes ' +
                        'WHERE showid = ? and indexer = ? and airdate = ?', [show.indexerid, show.indexer, airdate])

                    if sql_result:
                        season_number = int(sql_result[0]['season'])
                        episode_numbers = [int(sql_result[0]['episode'])]
                        if 1 < len(sql_result):
                            # multi-eps broadcast on this day
                            nums = {'1': 'one', '2': 'two', '3': 'three', '4': 'four', '5': 'five',
                                    '6': 'six', '7': 'seven', '8': 'eight', '9': 'nine', '10': 'ten'}
                            patt = '(?i)(?:e(?:p(?:isode)?)?|part|pt)[. _-]?(%s)'
                            try:
                                src_num = str(re.findall(patt % '\w+', best_result.extra_info)[0])
                                alt_num = nums.get(src_num) or list(nums.keys())[list(nums.values()).index(src_num)]
                                re_partnum = re.compile(patt % ('%s|%s' % (src_num, alt_num)))
                                for ep_details in sql_result:
                                    if re_partnum.search(ep_details['name']):
                                        season_number = int(ep_details['season'])
                                        episode_numbers = [int(ep_details['episode'])]
                                        break
                            except (StandardError, Exception):
                                pass

                    if self.indexer_lookup and not season_number or not len(episode_numbers):
                        try:
                            lindexer_api_parms = sickbeard.indexerApi(show.indexer).api_params.copy()

                            if show.lang:
                                lindexer_api_parms['language'] = show.lang

                            t = sickbeard.indexerApi(show.indexer).indexer(**lindexer_api_parms)

                            ep_obj = t[show.indexerid].aired_on(best_result.air_date)[0]

                            season_number = int(ep_obj['seasonnumber'])
                            episode_numbers = [int(ep_obj['episodenumber'])]
                        except sickbeard.indexer_episodenotfound:
                            logger.log(u'Unable to find episode with date ' + str(best_result.air_date)
                                       + ' for show ' + show.name + ', skipping', logger.WARNING)
                            episode_numbers = []
                        except sickbeard.indexer_error as e:
                            logger.log(u'Unable to contact ' + sickbeard.indexerApi(show.indexer).name
                                       + ': ' + ex(e), logger.WARNING)
                            episode_numbers = []

                    for epNo in episode_numbers:
                        s = season_number
                        e = epNo

                        if self.convert and show.is_scene:
                            (s, e) = scene_numbering.get_indexer_numbering(show.indexerid,
                                                                           show.indexer,
                                                                           season_number,
                                                                           epNo)
                        new_episode_numbers.append(e)
                        new_season_numbers.append(s)

                elif show.is_anime and len(best_result.ab_episode_numbers) and not self.testing:
                    scene_season = scene_exceptions.get_scene_exception_by_name(best_result.series_name)[1]
                    for epAbsNo in best_result.ab_episode_numbers:
                        a = epAbsNo

                        if self.convert and show.is_scene:
                            a = scene_numbering.get_indexer_absolute_numbering(show.indexerid,
                                                                               show.indexer, epAbsNo,
                                                                               True, scene_season)

                        (s, e) = helpers.get_all_episodes_from_absolute_number(show, [a])

                        new_absolute_numbers.append(a)
                        new_episode_numbers.extend(e)
                        new_season_numbers.append(s)

                elif best_result.season_number and len(best_result.episode_numbers) and not self.testing:
                    for epNo in best_result.episode_numbers:
                        s = best_result.season_number
                        e = epNo

                        if self.convert and show.is_scene:
                            (s, e) = scene_numbering.get_indexer_numbering(show.indexerid,
                                                                           show.indexer,
                                                                           best_result.season_number,
                                                                           epNo)
                        if show.is_anime:
                            a = helpers.get_absolute_number_from_season_and_episode(show, s, e)
                            if a:
                                new_absolute_numbers.append(a)

                        new_episode_numbers.append(e)
                        new_season_numbers.append(s)

                # 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 sickbeard, so we'd need to flag it.
                new_season_numbers = list(set(new_season_numbers))  # remove duplicates
                if 1 < len(new_season_numbers):
                    raise InvalidNameException('Scene numbering results episodes from '
                                               'seasons %s, (i.e. more than one) and '
                                               'SickGear does not support this.  '
                                               'Sorry.' % (str(new_season_numbers)))

                # I guess it's possible that we'd have duplicate episodes too, so lets
                # eliminate them
                new_episode_numbers = list(set(new_episode_numbers))
                new_episode_numbers.sort()

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

                if len(new_absolute_numbers):
                    best_result.ab_episode_numbers = new_absolute_numbers

                if len(new_season_numbers) and len(new_episode_numbers):
                    best_result.episode_numbers = new_episode_numbers
                    best_result.season_number = new_season_numbers[0]

                if self.convert and show.is_scene:
                    logger.log(u'Converted parsed result %s into %s'
                               % (best_result.original_name, str(best_result).decode('utf-8', 'xmlcharrefreplace')),
                               logger.DEBUG)

                helpers.cpu_sleep()

                return best_result
Esempio n. 10
0
    def _parse_string(self, name):
        if not name:
            return

        matches = []

        for regex in self.compiled_regexes:
            for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes[regex]:
                match = cur_regex.match(name)

                if not match:
                    continue

                result = ParseResult(name)
                result.which_regex = [cur_regex_name]
                result.score = 0 - cur_regex_num

                named_groups = match.groupdict().keys()

                if 'series_name' in named_groups:
                    result.series_name = match.group('series_name')
                    if result.series_name:
                        result.series_name = self.clean_series_name(result.series_name)
                        result.score += 1

                if 'series_num' in named_groups and match.group('series_num'):
                    result.score += 1

                if 'season_num' in named_groups:
                    tmp_season = int(match.group('season_num'))
                    if 'bare' == cur_regex_name and tmp_season in (19, 20):
                        continue
                    result.season_number = tmp_season
                    result.score += 1

                if 'ep_num' in named_groups:
                    ep_num = self._convert_number(match.group('ep_num'))
                    if 'extra_ep_num' in named_groups and match.group('extra_ep_num'):
                        result.episode_numbers = range(ep_num, self._convert_number(match.group('extra_ep_num')) + 1)
                        result.score += 1
                    else:
                        result.episode_numbers = [ep_num]
                    result.score += 1

                if 'ep_ab_num' in named_groups:
                    ep_ab_num = self._convert_number(match.group('ep_ab_num'))
                    if 'extra_ab_ep_num' in named_groups and match.group('extra_ab_ep_num'):
                        result.ab_episode_numbers = range(ep_ab_num,
                                                          self._convert_number(match.group('extra_ab_ep_num')) + 1)
                        result.score += 1
                    else:
                        result.ab_episode_numbers = [ep_ab_num]
                    result.score += 1

                if 'air_year' in named_groups and 'air_month' in named_groups and 'air_day' in named_groups:
                    year = int(match.group('air_year'))
                    month = int(match.group('air_month'))
                    day = int(match.group('air_day'))
                    # make an attempt to detect YYYY-DD-MM formats
                    if 12 < month:
                        tmp_month = month
                        month = day
                        day = tmp_month
                    try:
                        result.air_date = datetime.date(year, month, day)
                    except ValueError as e:
                        raise InvalidNameException(ex(e))

                if 'extra_info' in named_groups:
                    tmp_extra_info = match.group('extra_info')

                    # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
                    if tmp_extra_info and 'season_only' == cur_regex_name and re.search(
                            r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I):
                        continue
                    result.extra_info = tmp_extra_info
                    result.score += 1

                if 'release_group' in named_groups:
                    result.release_group = helpers.remove_non_release_groups(match.group('release_group'))
                    result.score += 1

                if 'version' in named_groups:
                    # assigns version to anime file if detected using anime regex. Non-anime regex receives -1
                    version = match.group('version')
                    if version:
                        result.version = version
                    else:
                        result.version = 1
                else:
                    result.version = -1

                matches.append(result)

            if len(matches):
                # pick best match with highest score based on placement
                best_result = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score)

                show = None
                if not self.naming_pattern:
                    # try and create a show object for this result
                    show = helpers.get_show(best_result.series_name, self.try_scene_exceptions)

                # confirm passed in show object indexer id matches result show object indexer id
                if show and not self.testing:
                    if self.showObj and show.indexerid != self.showObj.indexerid:
                        show = None
                elif not show and self.showObj:
                    show = self.showObj
                best_result.show = show

                if show and show.is_anime and 1 < len(self.compiled_regexes[1]) and 1 != regex:
                    continue

                # if this is a naming pattern test then return best result
                if not show or self.naming_pattern:
                    return best_result

                # get quality
                best_result.quality = common.Quality.nameQuality(name, show.is_anime)

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

                # if we have an air-by-date show then get the real season/episode numbers
                if best_result.is_air_by_date:
                    airdate = best_result.air_date.toordinal()
                    my_db = db.DBConnection()
                    sql_result = my_db.select(
                        'SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?',
                        [show.indexerid, show.indexer, airdate])

                    season_number = None
                    episode_numbers = []

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

                    if not season_number or not len(episode_numbers):
                        try:
                            lindexer_api_parms = sickbeard.indexerApi(show.indexer).api_params.copy()

                            if show.lang:
                                lindexer_api_parms['language'] = show.lang

                            t = sickbeard.indexerApi(show.indexer).indexer(**lindexer_api_parms)

                            ep_obj = t[show.indexerid].airedOn(best_result.air_date)[0]

                            season_number = int(ep_obj['seasonnumber'])
                            episode_numbers = [int(ep_obj['episodenumber'])]
                        except sickbeard.indexer_episodenotfound:
                            logger.log(u'Unable to find episode with date ' + str(best_result.air_date) + ' for show ' + show.name + ', skipping', logger.WARNING)
                            episode_numbers = []
                        except sickbeard.indexer_error as e:
                            logger.log(u'Unable to contact ' + sickbeard.indexerApi(show.indexer).name + ': ' + ex(e), logger.WARNING)
                            episode_numbers = []

                    for epNo in episode_numbers:
                        s = season_number
                        e = epNo

                        if self.convert and show.is_scene:
                            (s, e) = scene_numbering.get_indexer_numbering(show.indexerid,
                                                                           show.indexer,
                                                                           season_number,
                                                                           epNo)
                        new_episode_numbers.append(e)
                        new_season_numbers.append(s)

                elif show.is_anime and len(best_result.ab_episode_numbers) and not self.testing:
                    scene_season = scene_exceptions.get_scene_exception_by_name(best_result.series_name)[1]
                    for epAbsNo in best_result.ab_episode_numbers:
                        a = epAbsNo

                        if self.convert and show.is_scene:
                            a = scene_numbering.get_indexer_absolute_numbering(show.indexerid,
                                                                               show.indexer, epAbsNo,
                                                                               True, scene_season)

                        (s, e) = helpers.get_all_episodes_from_absolute_number(show, [a])

                        new_absolute_numbers.append(a)
                        new_episode_numbers.extend(e)
                        new_season_numbers.append(s)

                elif best_result.season_number and len(best_result.episode_numbers) and not self.testing:
                    for epNo in best_result.episode_numbers:
                        s = best_result.season_number
                        e = epNo

                        if self.convert and show.is_scene:
                            (s, e) = scene_numbering.get_indexer_numbering(show.indexerid,
                                                                           show.indexer,
                                                                           best_result.season_number,
                                                                           epNo)
                        if show.is_anime:
                            a = helpers.get_absolute_number_from_season_and_episode(show, s, e)
                            if a:
                                new_absolute_numbers.append(a)

                        new_episode_numbers.append(e)
                        new_season_numbers.append(s)

                # 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 sickbeard, so we'd need to flag it.
                new_season_numbers = list(set(new_season_numbers))  # remove duplicates
                if 1 < len(new_season_numbers):
                    raise InvalidNameException('Scene numbering results episodes from '
                                               'seasons %s, (i.e. more than one) and '
                                               'SickGear does not support this.  '
                                               'Sorry.' % (str(new_season_numbers)))

                # I guess it's possible that we'd have duplicate episodes too, so lets
                # eliminate them
                new_episode_numbers = list(set(new_episode_numbers))
                new_episode_numbers.sort()

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

                if len(new_absolute_numbers):
                    best_result.ab_episode_numbers = new_absolute_numbers

                if len(new_season_numbers) and len(new_episode_numbers):
                    best_result.episode_numbers = new_episode_numbers
                    best_result.season_number = new_season_numbers[0]

                if self.convert and show.is_scene:
                    logger.log(u'Converted parsed result %s into %s'
                               % (best_result.original_name, str(best_result).decode('utf-8', 'xmlcharrefreplace')),
                               logger.DEBUG)

                # CPU sleep
                time.sleep(cpu_presets[sickbeard.CPU_PRESET])

                return best_result
Esempio n. 11
0
    def _parse_string(self, name):
        if not name:
            return

        matches = []

        for regex in self.compiled_regexes:
            for (cur_regex_num, cur_regex_name,
                 cur_regex) in self.compiled_regexes[regex]:
                match = cur_regex.match(name)

                if not match:
                    continue

                result = ParseResult(name)
                result.which_regex = [cur_regex_name]
                result.score = 0 - cur_regex_num

                named_groups = match.groupdict().keys()

                if 'series_name' in named_groups:
                    result.series_name = match.group('series_name')
                    if result.series_name:
                        result.series_name = self.clean_series_name(
                            result.series_name)
                        result.score += 1

                if 'series_num' in named_groups and match.group('series_num'):
                    result.score += 1

                if 'season_num' in named_groups:
                    tmp_season = int(match.group('season_num'))
                    if 'bare' == cur_regex_name and tmp_season in (19, 20):
                        continue
                    result.season_number = tmp_season
                    result.score += 1

                if 'ep_num' in named_groups:
                    ep_num = self._convert_number(match.group('ep_num'))
                    if 'extra_ep_num' in named_groups and match.group(
                            'extra_ep_num'):
                        result.episode_numbers = range(
                            ep_num,
                            self._convert_number(match.group('extra_ep_num')) +
                            1)
                        result.score += 1
                    else:
                        result.episode_numbers = [ep_num]
                    result.score += 1

                if 'ep_ab_num' in named_groups:
                    ep_ab_num = self._convert_number(match.group('ep_ab_num'))
                    if 'extra_ab_ep_num' in named_groups and match.group(
                            'extra_ab_ep_num'):
                        result.ab_episode_numbers = range(
                            ep_ab_num,
                            self._convert_number(
                                match.group('extra_ab_ep_num')) + 1)
                        result.score += 1
                    else:
                        result.ab_episode_numbers = [ep_ab_num]
                    result.score += 1

                if 'air_year' in named_groups and 'air_month' in named_groups and 'air_day' in named_groups:
                    year = int(match.group('air_year'))
                    month = int(match.group('air_month'))
                    day = int(match.group('air_day'))
                    # make an attempt to detect YYYY-DD-MM formats
                    if 12 < month:
                        tmp_month = month
                        month = day
                        day = tmp_month
                    try:
                        result.air_date = datetime.date(year, month, day)
                    except ValueError as e:
                        raise InvalidNameException(ex(e))

                if 'extra_info' in named_groups:
                    tmp_extra_info = match.group('extra_info')

                    # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
                    if tmp_extra_info and 'season_only' == cur_regex_name and re.search(
                            r'([. _-]|^)(special|extra)s?\w*([. _-]|$)',
                            tmp_extra_info, re.I):
                        continue
                    result.extra_info = tmp_extra_info
                    result.score += 1

                if 'release_group' in named_groups:
                    result.release_group = helpers.remove_non_release_groups(
                        match.group('release_group'))
                    result.score += 1

                if 'version' in named_groups:
                    # assigns version to anime file if detected using anime regex. Non-anime regex receives -1
                    version = match.group('version')
                    if version:
                        result.version = version
                    else:
                        result.version = 1
                else:
                    result.version = -1

                matches.append(result)

            if len(matches):
                # pick best match with highest score based on placement
                best_result = max(sorted(matches,
                                         reverse=True,
                                         key=lambda x: x.which_regex),
                                  key=lambda x: x.score)

                show = None
                if not self.naming_pattern:
                    # try and create a show object for this result
                    show = helpers.get_show(best_result.series_name,
                                            self.try_scene_exceptions)

                # confirm passed in show object indexer id matches result show object indexer id
                if show and not self.testing:
                    if self.showObj and show.indexerid != self.showObj.indexerid:
                        show = None
                elif not show and self.showObj:
                    show = self.showObj
                best_result.show = show

                if show and show.is_anime and 1 < len(
                        self.compiled_regexes[1]) and 1 != regex:
                    continue

                # if this is a naming pattern test then return best result
                if not show or self.naming_pattern:
                    return best_result

                # get quality
                best_result.quality = common.Quality.nameQuality(
                    name, show.is_anime)

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

                # if we have an air-by-date show then get the real season/episode numbers
                if best_result.is_air_by_date:
                    airdate = best_result.air_date.toordinal()
                    my_db = db.DBConnection()
                    sql_result = my_db.select(
                        'SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?',
                        [show.indexerid, show.indexer, airdate])

                    season_number = None
                    episode_numbers = []

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

                    if not season_number or not len(episode_numbers):
                        try:
                            lindexer_api_parms = sickbeard.indexerApi(
                                show.indexer).api_params.copy()

                            if show.lang:
                                lindexer_api_parms['language'] = show.lang

                            t = sickbeard.indexerApi(
                                show.indexer).indexer(**lindexer_api_parms)

                            ep_obj = t[show.indexerid].airedOn(
                                best_result.air_date)[0]

                            season_number = int(ep_obj['seasonnumber'])
                            episode_numbers = [int(ep_obj['episodenumber'])]
                        except sickbeard.indexer_episodenotfound:
                            logger.log(
                                u'Unable to find episode with date ' +
                                str(best_result.air_date) + ' for show ' +
                                show.name + ', skipping', logger.WARNING)
                            episode_numbers = []
                        except sickbeard.indexer_error as e:
                            logger.log(
                                u'Unable to contact ' +
                                sickbeard.indexerApi(show.indexer).name +
                                ': ' + ex(e), logger.WARNING)
                            episode_numbers = []

                    for epNo in episode_numbers:
                        s = season_number
                        e = epNo

                        if self.convert and show.is_scene:
                            (s, e) = scene_numbering.get_indexer_numbering(
                                show.indexerid, show.indexer, season_number,
                                epNo)
                        new_episode_numbers.append(e)
                        new_season_numbers.append(s)

                elif show.is_anime and len(
                        best_result.ab_episode_numbers) and not self.testing:
                    scene_season = scene_exceptions.get_scene_exception_by_name(
                        best_result.series_name)[1]
                    for epAbsNo in best_result.ab_episode_numbers:
                        a = epAbsNo

                        if self.convert and show.is_scene:
                            a = scene_numbering.get_indexer_absolute_numbering(
                                show.indexerid, show.indexer, epAbsNo, True,
                                scene_season)

                        (s, e) = helpers.get_all_episodes_from_absolute_number(
                            show, [a])

                        new_absolute_numbers.append(a)
                        new_episode_numbers.extend(e)
                        new_season_numbers.append(s)

                elif best_result.season_number and len(
                        best_result.episode_numbers) and not self.testing:
                    for epNo in best_result.episode_numbers:
                        s = best_result.season_number
                        e = epNo

                        if self.convert and show.is_scene:
                            (s, e) = scene_numbering.get_indexer_numbering(
                                show.indexerid, show.indexer,
                                best_result.season_number, epNo)
                        if show.is_anime:
                            a = helpers.get_absolute_number_from_season_and_episode(
                                show, s, e)
                            if a:
                                new_absolute_numbers.append(a)

                        new_episode_numbers.append(e)
                        new_season_numbers.append(s)

                # 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 sickbeard, so we'd need to flag it.
                new_season_numbers = list(
                    set(new_season_numbers))  # remove duplicates
                if 1 < len(new_season_numbers):
                    raise InvalidNameException(
                        'Scene numbering results episodes from '
                        'seasons %s, (i.e. more than one) and '
                        'SickGear does not support this.  '
                        'Sorry.' % (str(new_season_numbers)))

                # I guess it's possible that we'd have duplicate episodes too, so lets
                # eliminate them
                new_episode_numbers = list(set(new_episode_numbers))
                new_episode_numbers.sort()

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

                if len(new_absolute_numbers):
                    best_result.ab_episode_numbers = new_absolute_numbers

                if len(new_season_numbers) and len(new_episode_numbers):
                    best_result.episode_numbers = new_episode_numbers
                    best_result.season_number = new_season_numbers[0]

                if self.convert and show.is_scene:
                    logger.log(
                        u'Converted parsed result %s into %s' %
                        (best_result.original_name, str(best_result).decode(
                            'utf-8', 'xmlcharrefreplace')), logger.DEBUG)

                # CPU sleep
                time.sleep(cpu_presets[sickbeard.CPU_PRESET])

                return best_result
Esempio n. 12
0
    def _parse_string(self, name):
        if not name:
            return

        matches = []
        bestResult = None

        for (cur_regex_num, cur_regex_name,
             cur_regex) in self.compiled_regexes:
            match = cur_regex.match(name)

            if not match:
                continue

            result = ParseResult(name)
            result.which_regex = [cur_regex_name]
            result.score = 0 - cur_regex_num

            named_groups = match.groupdict().keys()

            if 'series_name' in named_groups:
                result.series_name = match.group('series_name')
                if result.series_name:
                    result.series_name = self.clean_series_name(
                        result.series_name)
                    result.score += 1

            if 'season_num' in named_groups:
                tmp_season = int(match.group('season_num'))
                if cur_regex_name == 'bare' and tmp_season in (19, 20):
                    continue
                result.season_number = tmp_season
                result.score += 1

            if 'ep_num' in named_groups:
                ep_num = self._convert_number(match.group('ep_num'))
                if 'extra_ep_num' in named_groups and match.group(
                        'extra_ep_num'):
                    result.episode_numbers = range(
                        ep_num,
                        self._convert_number(match.group('extra_ep_num')) + 1)
                    result.score += 1
                else:
                    result.episode_numbers = [ep_num]
                result.score += 1

            if 'ep_ab_num' in named_groups:
                ep_ab_num = self._convert_number(match.group('ep_ab_num'))
                if 'extra_ab_ep_num' in named_groups and match.group(
                        'extra_ab_ep_num'):
                    result.ab_episode_numbers = range(
                        ep_ab_num,
                        self._convert_number(match.group('extra_ab_ep_num')) +
                        1)
                    result.score += 1
                else:
                    result.ab_episode_numbers = [ep_ab_num]
                result.score += 1

            if 'sports_event_id' in named_groups:
                sports_event_id = match.group('sports_event_id')
                if sports_event_id:
                    result.sports_event_id = int(
                        match.group('sports_event_id'))
                    result.score += 1

            if 'sports_event_name' in named_groups:
                result.sports_event_name = match.group('sports_event_name')
                if result.sports_event_name:
                    result.sports_event_name = self.clean_series_name(
                        result.sports_event_name)
                    result.score += 1

            if 'sports_air_date' in named_groups:
                sports_air_date = match.group('sports_air_date')
                try:
                    result.sports_air_date = parser.parse(sports_air_date,
                                                          fuzzy=True).date()
                    result.score += 1
                except:
                    continue

            if 'air_year' in named_groups and 'air_month' in named_groups and 'air_day' in named_groups:
                year = int(match.group('air_year'))
                month = int(match.group('air_month'))
                day = int(match.group('air_day'))

                try:
                    dtStr = '%s-%s-%s' % (year, month, day)
                    result.air_date = datetime.datetime.strptime(
                        dtStr, "%Y-%m-%d").date()
                    result.score += 1
                except:
                    continue

            if 'extra_info' in named_groups:
                tmp_extra_info = match.group('extra_info')

                # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
                if tmp_extra_info and cur_regex_name == 'season_only' and re.search(
                        r'([. _-]|^)(special|extra)s?\w*([. _-]|$)',
                        tmp_extra_info, re.I):
                    continue
                result.extra_info = tmp_extra_info
                result.score += 1

            if 'release_group' in named_groups:
                result.release_group = match.group('release_group')
                result.score += 1

            if 'version' in named_groups:
                # assigns version to anime file if detected using anime regex. Non-anime regex receives -1
                version = match.group('version')
                if version:
                    result.version = version
                else:
                    result.version = 1
            else:
                result.version = -1

            matches.append(result)

        if len(matches):
            # pick best match with highest score based on placement
            bestResult = max(sorted(matches,
                                    reverse=True,
                                    key=lambda x: x.which_regex),
                             key=lambda x: x.score)

            show = None
            if not self.naming_pattern:
                # try and create a show object for this result
                show = helpers.get_show(bestResult.series_name,
                                        self.tryIndexers)

            # confirm passed in show object indexer id matches result show object indexer id
            if show:
                if self.showObj and show.indexerid != self.showObj.indexerid:
                    show = None
                bestResult.show = show
            elif not show and self.showObj:
                bestResult.show = self.showObj

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

            # get quality
            bestResult.quality = common.Quality.nameQuality(
                name, bestResult.show.is_anime)

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

            # if we have an air-by-date show then get the real season/episode numbers
            if bestResult.is_air_by_date or bestResult.is_sports:
                airdate = bestResult.air_date.toordinal(
                ) if bestResult.air_date else bestResult.sports_air_date.toordinal(
                )

                myDB = db.DBConnection()
                sql_result = myDB.select(
                    "SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?",
                    [
                        bestResult.show.indexerid, bestResult.show.indexer,
                        airdate
                    ])

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

                    for epNo in episode_numbers:
                        s = season_number
                        e = epNo

                        if self.convert:
                            (s, e) = scene_numbering.get_indexer_numbering(
                                bestResult.show.indexerid,
                                bestResult.show.indexer, season_number, epNo)
                        new_episode_numbers.append(e)
                        new_season_numbers.append(s)

            elif bestResult.show.is_anime and len(
                    bestResult.ab_episode_numbers):
                scene_season = scene_exceptions.get_scene_exception_by_name(
                    bestResult.series_name)[1]
                for epAbsNo in bestResult.ab_episode_numbers:
                    a = epAbsNo

                    if self.convert:
                        a = scene_numbering.get_indexer_absolute_numbering(
                            bestResult.show.indexerid, bestResult.show.indexer,
                            epAbsNo, True, scene_season)

                    (s, e) = helpers.get_all_episodes_from_absolute_number(
                        bestResult.show, [a])

                    new_absolute_numbers.append(a)
                    new_episode_numbers.extend(e)
                    new_season_numbers.append(s)

            elif bestResult.season_number and len(bestResult.episode_numbers):
                for epNo in bestResult.episode_numbers:
                    s = bestResult.season_number
                    e = epNo

                    if self.convert:
                        (s, e) = scene_numbering.get_indexer_numbering(
                            bestResult.show.indexerid, bestResult.show.indexer,
                            bestResult.season_number, epNo)
                    if bestResult.show.is_anime:
                        a = helpers.get_absolute_number_from_season_and_episode(
                            bestResult.show, s, e)
                        if a:
                            new_absolute_numbers.append(a)

                    new_episode_numbers.append(e)
                    new_season_numbers.append(s)

            # 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 sickbeard, so we'd need to flag it.
            new_season_numbers = list(
                set(new_season_numbers))  # remove duplicates
            if len(new_season_numbers) > 1:
                raise InvalidNameException(
                    "Scene numbering results episodes from "
                    "seasons %s, (i.e. more than one) and "
                    "sickrage does not support this.  "
                    "Sorry." % (str(new_season_numbers)))

            # I guess it's possible that we'd have duplicate episodes too, so lets
            # eliminate them
            new_episode_numbers = list(set(new_episode_numbers))
            new_episode_numbers.sort()

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

            if len(new_absolute_numbers):
                bestResult.ab_episode_numbers = new_absolute_numbers

            if len(new_season_numbers) and len(new_episode_numbers):
                bestResult.episode_numbers = new_episode_numbers
                bestResult.season_number = new_season_numbers[0]

            if self.convert:
                logger.log(
                    u"Converted parsed result " + bestResult.original_name +
                    " into " +
                    str(bestResult).decode('utf-8', 'xmlcharrefreplace'),
                    logger.DEBUG)

        # CPU sleep
        time.sleep(0.02)

        return bestResult