示例#1
0
    def run(self):
        generic_queue.QueueItem.run(self)

        is_error = False
        try:
            if not self.standard_backlog:
                ep_count, ep_count_scene = get_aired_in_season(self.show)
                for ep_obj in self.segment:
                    set_wanted_aired(ep_obj, True, ep_count, ep_count_scene)

            logger.log(u'Beginning backlog search for: [%s]' % self.show.name)
            search_result = search.search_providers(
                self.show, self.segment, False,
                try_other_searches=(not self.standard_backlog or not self.limited_backlog),
                scheduled=self.standard_backlog)

            if search_result:
                for result in search_result:
                    # just use the first result for now
                    logger.log(u'Downloading %s from %s' % (result.name, result.provider.name))
                    if search.snatch_episode(result):
                        for ep in result.episodes:
                            self.snatched_eps.add((ep.show.indexer, ep.show.indexerid, ep.season, ep.episode))

                    helpers.cpu_sleep()
            else:
                logger.log(u'No needed episodes found during backlog search for: [%s]' % self.show.name)
        except (StandardError, Exception):
            is_error = True
            logger.log(traceback.format_exc(), logger.ERROR)

        finally:
            logger.log('Completed backlog search %sfor: [%s]' % (('', 'with a debug error ')[is_error], self.show.name))
            self.finish()
示例#2
0
    def run(self):
        generic_queue.QueueItem.run(self)

        try:
            logger.log(u'Beginning manual search for: [%s]' % self.segment.prettyName())
            self.started = True

            search_result = search.search_providers(self.show, [self.segment], True, try_other_searches=True)

            if search_result:
                # just use the first result for now
                logger.log(u'Downloading %s from %s' % (search_result[0].name, search_result[0].provider.name))
                self.success = search.snatch_episode(search_result[0])

                helpers.cpu_sleep()

            else:
                ui.notifications.message('No downloads found',
                                         u'Could not find a download for <i>%s</i>' % self.segment.prettyName())

                logger.log(u'Unable to find a download for: [%s]' % self.segment.prettyName())

        except Exception:
            logger.log(traceback.format_exc(), logger.DEBUG)

        finally:
            # Keep a list with the 100 last executed searches
            fifo(MANUAL_SEARCH_HISTORY, self, MANUAL_SEARCH_HISTORY_SIZE)

            if self.success is None:
                self.success = False

            self.finish()
    def run(self):
        generic_queue.QueueItem.run(self)

        is_error = False
        try:
            logger.log(u'Beginning backlog search for: [%s]' % self.show.name)
            search_result = search.search_providers(
                self.show,
                self.segment,
                False,
                try_other_searches=(not self.standard_backlog
                                    or not self.limited_backlog))

            if search_result:
                for result in search_result:
                    # just use the first result for now
                    logger.log(u'Downloading %s from %s' %
                               (result.name, result.provider.name))
                    search.snatch_episode(result)

                    helpers.cpu_sleep()
            else:
                logger.log(
                    u'No needed episodes found during backlog search for: [%s]'
                    % self.show.name)
        except (StandardError, Exception):
            is_error = True
            logger.log(traceback.format_exc(), logger.DEBUG)

        finally:
            logger.log('Completed backlog search %sfor: [%s]' %
                       (('', 'with a debug error ')[is_error], self.show.name))
            self.finish()
示例#4
0
    def run(self):
        generic_queue.QueueItem.run(self)
        self.started = True

        try:
            ep_count, ep_count_scene = get_aired_in_season(self.show)
            for ep_obj in self.segment:

                logger.log(u'Marking episode as bad: [%s]' %
                           ep_obj.prettyName())

                failed_history.set_episode_failed(ep_obj)
                (release, provider) = failed_history.find_release(ep_obj)
                failed_history.revert_episode(ep_obj)
                if release:
                    failed_history.add_failed(release)
                    history.log_failed(ep_obj, release, provider)

                logger.log(u'Beginning failed download search for: [%s]' %
                           ep_obj.prettyName())

                set_wanted_aired(ep_obj,
                                 True,
                                 ep_count,
                                 ep_count_scene,
                                 manual=True)

            search_result = search.search_providers(self.show,
                                                    self.segment,
                                                    True,
                                                    try_other_searches=True)

            if search_result:
                for result in search_result:
                    # just use the first result for now
                    logger.log(u'Downloading %s from %s' %
                               (result.name, result.provider.name))
                    if search.snatch_episode(result):
                        for ep in result.episodes:
                            self.snatched_eps.add(
                                (ep.show.indexer, ep.show.indexerid, ep.season,
                                 ep.episode))

                    helpers.cpu_sleep()
            else:
                pass
                # logger.log(u'No valid episode found to retry for: [%s]' % self.segment.prettyName())
        except (StandardError, Exception):
            logger.log(traceback.format_exc(), logger.ERROR)

        finally:
            # Keep a list with the last executed searches
            fifo(MANUAL_SEARCH_HISTORY, self.base_info())

            if self.success is None:
                self.success = False

            self.finish()
示例#5
0
    def run(self):
        generic_queue.QueueItem.run(self)

        try:
            logger.log(u'Beginning manual search for: [%s]' %
                       self.segment.prettyName())
            self.started = True

            ep_count, ep_count_scene = get_aired_in_season(self.show)
            set_wanted_aired(self.segment,
                             True,
                             ep_count,
                             ep_count_scene,
                             manual=True)

            search_result = search.search_providers(self.show, [self.segment],
                                                    True,
                                                    try_other_searches=True)

            if search_result:
                # just use the first result for now
                logger.log(
                    u'Downloading %s from %s' %
                    (search_result[0].name, search_result[0].provider.name))
                self.success = search.snatch_episode(search_result[0])
                for ep in search_result[0].episodes:
                    self.snatched_eps.add((ep.show.indexer, ep.show.indexerid,
                                           ep.season, ep.episode))

                helpers.cpu_sleep()

            else:
                ui.notifications.message(
                    'No downloads found',
                    u'Could not find a download for <i>%s</i>' %
                    self.segment.prettyName())

                logger.log(u'Unable to find a download for: [%s]' %
                           self.segment.prettyName())

        except (StandardError, Exception):
            logger.log(traceback.format_exc(), logger.ERROR)

        finally:
            # Keep a list with the last executed searches
            fifo(MANUAL_SEARCH_HISTORY, self.base_info())

            if self.success is None:
                self.success = False

            self.finish()
    def run(self):
        generic_queue.QueueItem.run(self)
        self.started = True

        try:
            for ep_obj in self.segment:

                logger.log(u'Marking episode as bad: [%s]' %
                           ep_obj.prettyName())

                cur_status = ep_obj.status

                failed_history.set_episode_failed(ep_obj)
                (release, provider) = failed_history.find_release(ep_obj)
                failed_history.revert_episode(ep_obj)
                if release:
                    failed_history.add_failed(release)
                    history.logFailed(ep_obj, release, provider)

                logger.log(u'Beginning failed download search for: [%s]' %
                           ep_obj.prettyName())

            search_result = search.search_providers(self.show,
                                                    self.segment,
                                                    True,
                                                    try_other_searches=True,
                                                    old_status=cur_status)

            if search_result:
                for result in search_result:
                    # just use the first result for now
                    logger.log(u'Downloading %s from %s' %
                               (result.name, result.provider.name))
                    search.snatch_episode(result)

                    helpers.cpu_sleep()
            else:
                pass
                # logger.log(u'No valid episode found to retry for: [%s]' % self.segment.prettyName())
        except (StandardError, Exception):
            logger.log(traceback.format_exc(), logger.DEBUG)

        finally:
            # Keep a list with the 100 last executed searches
            fifo(MANUAL_SEARCH_HISTORY, self, MANUAL_SEARCH_HISTORY_SIZE)

            if self.success is None:
                self.success = False

            self.finish()
示例#7
0
    def run(self):
        generic_queue.QueueItem.run(self)
        self.started = True

        try:
            ep_count, ep_count_scene = get_aired_in_season(self.show)
            for ep_obj in self.segment:

                logger.log(u'Marking episode as bad: [%s]' % ep_obj.prettyName())

                failed_history.set_episode_failed(ep_obj)
                (release, provider) = failed_history.find_release(ep_obj)
                failed_history.revert_episode(ep_obj)
                if release:
                    failed_history.add_failed(release)
                    history.log_failed(ep_obj, release, provider)

                logger.log(u'Beginning failed download search for: [%s]' % ep_obj.prettyName())

                set_wanted_aired(ep_obj, True, ep_count, ep_count_scene, manual=True)

            search_result = search.search_providers(self.show, self.segment, True, try_other_searches=True)

            if search_result:
                for result in search_result:
                    # just use the first result for now
                    logger.log(u'Downloading %s from %s' % (result.name, result.provider.name))
                    if search.snatch_episode(result):
                        for ep in result.episodes:
                            self.snatched_eps.add((ep.show.indexer, ep.show.indexerid, ep.season, ep.episode))

                    helpers.cpu_sleep()
            else:
                pass
                # logger.log(u'No valid episode found to retry for: [%s]' % self.segment.prettyName())
        except (StandardError, Exception):
            logger.log(traceback.format_exc(), logger.ERROR)

        finally:
            # Keep a list with the last executed searches
            fifo(MANUAL_SEARCH_HISTORY, self.base_info())

            if self.success is None:
                self.success = False

            self.finish()
示例#8
0
    def run(self):
        generic_queue.QueueItem.run(self)

        is_error = False
        try:
            if not self.standard_backlog:
                ep_count, ep_count_scene = get_aired_in_season(self.show)
                for ep_obj in self.segment:
                    set_wanted_aired(ep_obj, True, ep_count, ep_count_scene)

            logger.log(u'Beginning backlog search for: [%s]' % self.show.name)
            search_result = search.search_providers(
                self.show,
                self.segment,
                False,
                try_other_searches=(not self.standard_backlog
                                    or not self.limited_backlog),
                scheduled=self.standard_backlog)

            if search_result:
                for result in search_result:
                    # just use the first result for now
                    logger.log(u'Downloading %s from %s' %
                               (result.name, result.provider.name))
                    if search.snatch_episode(result):
                        for ep in result.episodes:
                            self.snatched_eps.add(
                                (ep.show.indexer, ep.show.indexerid, ep.season,
                                 ep.episode))

                    helpers.cpu_sleep()
            else:
                logger.log(
                    u'No needed episodes found during backlog search for: [%s]'
                    % self.show.name)
        except (StandardError, Exception):
            is_error = True
            logger.log(traceback.format_exc(), logger.ERROR)

        finally:
            logger.log('Completed backlog search %sfor: [%s]' %
                       (('', 'with a debug error ')[is_error], self.show.name))
            self.finish()
示例#9
0
    def run(self):
        generic_queue.QueueItem.run(self)

        try:
            logger.log(u'Beginning manual search for: [%s]' % self.segment.prettyName())
            self.started = True

            ep_count, ep_count_scene = get_aired_in_season(self.show)
            set_wanted_aired(self.segment, True, ep_count, ep_count_scene, manual=True)

            search_result = search.search_providers(self.show, [self.segment], True, try_other_searches=True)

            if search_result:
                # just use the first result for now
                logger.log(u'Downloading %s from %s' % (search_result[0].name, search_result[0].provider.name))
                self.success = search.snatch_episode(search_result[0])
                for ep in search_result[0].episodes:
                    self.snatched_eps.add((ep.show.indexer, ep.show.indexerid, ep.season, ep.episode))

                helpers.cpu_sleep()

            else:
                ui.notifications.message('No downloads found',
                                         u'Could not find a download for <i>%s</i>' % self.segment.prettyName())

                logger.log(u'Unable to find a download for: [%s]' % self.segment.prettyName())

        except (StandardError, Exception):
            logger.log(traceback.format_exc(), logger.ERROR)

        finally:
            # Keep a list with the last executed searches
            fifo(MANUAL_SEARCH_HISTORY, self.base_info())

            if self.success is None:
                self.success = False

            self.finish()
示例#10
0
    def run(self):
        generic_queue.QueueItem.run(self)

        try:
            self._change_missing_episodes()

            show_list = sickbeard.showList
            from_date = datetime.date.fromordinal(1)
            needed = common.neededQualities()
            for curShow in show_list:
                if curShow.paused:
                    continue

                wanted_eps = wanted_episodes(curShow,
                                             from_date,
                                             unaired=sickbeard.SEARCH_UNAIRED)

                if wanted_eps:
                    if not needed.all_needed:
                        if not needed.all_types_needed:
                            needed.check_needed_types(curShow)
                        if not needed.all_qualities_needed:
                            for w in wanted_eps:
                                if needed.all_qualities_needed:
                                    break
                                if not w.show.is_anime and not w.show.is_sports:
                                    needed.check_needed_qualities(
                                        w.wantedQuality)

                    self.episodes.extend(wanted_eps)

            if sickbeard.DOWNLOAD_PROPERS:
                properFinder.get_needed_qualites(needed)

            self.update_providers(needed=needed)
            self._check_for_propers(needed)

            if not self.episodes:
                logger.log(u'No search of cache for episodes required')
                self.success = True
            else:
                num_shows = len(set([ep.show.name for ep in self.episodes]))
                logger.log(u'Found %d needed episode%s spanning %d show%s' %
                           (len(self.episodes),
                            helpers.maybe_plural(len(self.episodes)),
                            num_shows, helpers.maybe_plural(num_shows)))

                try:
                    logger.log(u'Beginning recent search for episodes')
                    found_results = search.search_for_needed_episodes(
                        self.episodes)

                    if not len(found_results):
                        logger.log(u'No needed episodes found')
                    else:
                        for result in found_results:
                            # just use the first result for now
                            logger.log(u'Downloading %s from %s' %
                                       (result.name, result.provider.name))
                            self.success = search.snatch_episode(result)

                            helpers.cpu_sleep()

                except (StandardError, Exception):
                    logger.log(traceback.format_exc(), logger.ERROR)

                if None is self.success:
                    self.success = False

        finally:
            self.finish()
示例#11
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
示例#12
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
示例#13
0
    def run(self):
        generic_queue.QueueItem.run(self)

        try:
            self._change_missing_episodes()

            show_list = sickbeard.showList
            from_date = datetime.date.fromordinal(1)
            need_anime = need_sports = need_sd = need_hd = need_uhd = False
            max_sd = Quality.SDDVD
            hd_qualities = [Quality.HDTV, Quality.FULLHDTV, Quality.HDWEBDL, Quality.FULLHDWEBDL,
                            Quality.HDBLURAY, Quality.FULLHDBLURAY]
            max_hd = Quality.FULLHDBLURAY
            for curShow in show_list:
                if curShow.paused:
                    continue

                wanted_eps = wanted_episodes(curShow, from_date, unaired=sickbeard.SEARCH_UNAIRED)
                if wanted_eps:
                    if not need_anime and curShow.is_anime:
                        need_anime = True
                    if not need_sports and curShow.is_sports:
                        need_sports = True
                    if not need_sd or not need_hd or not need_uhd:
                        for w in wanted_eps:
                            if need_sd and need_hd and need_uhd:
                                break
                            if not w.show.is_anime and not w.show.is_sports:
                                if Quality.UNKNOWN in w.wantedQuality:
                                    need_sd = need_hd = need_uhd = True
                                else:
                                    if not need_sd and max_sd >= min(w.wantedQuality):
                                        need_sd = True
                                    if not need_hd and any(i in hd_qualities for i in w.wantedQuality):
                                        need_hd = True
                                    if not need_uhd and max_hd < max(w.wantedQuality):
                                        need_uhd = True
                self.episodes.extend(wanted_eps)

            self.update_providers(need_anime=need_anime, need_sports=need_sports,
                                  need_sd=need_sd, need_hd=need_hd, need_uhd=need_uhd)

            if not self.episodes:
                logger.log(u'No search of cache for episodes required')
                self.success = True
            else:
                num_shows = len(set([ep.show.name for ep in self.episodes]))
                logger.log(u'Found %d needed episode%s spanning %d show%s'
                           % (len(self.episodes), helpers.maybe_plural(len(self.episodes)),
                              num_shows, helpers.maybe_plural(num_shows)))

                try:
                    logger.log(u'Beginning recent search for episodes')
                    found_results = search.search_for_needed_episodes(self.episodes)

                    if not len(found_results):
                        logger.log(u'No needed episodes found')
                    else:
                        for result in found_results:
                            # just use the first result for now
                            logger.log(u'Downloading %s from %s' % (result.name, result.provider.name))
                            self.success = search.snatch_episode(result)

                            helpers.cpu_sleep()

                except Exception:
                    logger.log(traceback.format_exc(), logger.DEBUG)

                if None is self.success:
                    self.success = False

        finally:
            self.finish()
示例#14
0
    def run(self):
        generic_queue.QueueItem.run(self)

        try:
            self._change_missing_episodes()

            show_list = sickbeard.showList
            from_date = datetime.date.fromordinal(1)
            needed = common.neededQualities()
            for curShow in show_list:
                if curShow.paused:
                    continue

                wanted_eps = wanted_episodes(curShow, from_date, unaired=sickbeard.SEARCH_UNAIRED)

                if wanted_eps:
                    if not needed.all_needed:
                        if not needed.all_types_needed:
                            needed.check_needed_types(curShow)
                        if not needed.all_qualities_needed:
                            for w in wanted_eps:
                                if needed.all_qualities_needed:
                                    break
                                if not w.show.is_anime and not w.show.is_sports:
                                    needed.check_needed_qualities(w.wantedQuality)

                    self.episodes.extend(wanted_eps)

            if sickbeard.DOWNLOAD_PROPERS:
                properFinder.get_needed_qualites(needed)

            self.update_providers(needed=needed)
            self._check_for_propers(needed)

            if not self.episodes:
                logger.log(u'No search of cache for episodes required')
                self.success = True
            else:
                num_shows = len(set([ep.show.name for ep in self.episodes]))
                logger.log(u'Found %d needed episode%s spanning %d show%s'
                           % (len(self.episodes), helpers.maybe_plural(len(self.episodes)),
                              num_shows, helpers.maybe_plural(num_shows)))

                try:
                    logger.log(u'Beginning recent search for episodes')
                    found_results = search.search_for_needed_episodes(self.episodes)

                    if not len(found_results):
                        logger.log(u'No needed episodes found')
                    else:
                        for result in found_results:
                            # just use the first result for now
                            logger.log(u'Downloading %s from %s' % (result.name, result.provider.name))
                            self.success = search.snatch_episode(result)
                            if self.success:
                                for ep in result.episodes:
                                    self.snatched_eps.add((ep.show.indexer, ep.show.indexerid, ep.season, ep.episode))

                            helpers.cpu_sleep()

                except (StandardError, Exception):
                    logger.log(traceback.format_exc(), logger.ERROR)

                if None is self.success:
                    self.success = False

        finally:
            self.finish()