Example #1
0
def is_final_result(result):
    """
    Checks if the given result is good enough quality that we can stop searching for other ones.

    If the result is the highest quality in both the any/best quality lists then this function
    returns True, if not then it's False
    """

    sickrage.app.log.debug(
        "Checking if we should keep searching after we've found " +
        result.name)

    show_obj = find_show(result.show_id)

    any_qualities, best_qualities = Quality.split_quality(show_obj.quality)

    # if there is a download that's higher than this then we definitely need to keep looking
    if best_qualities and result.quality < max(best_qualities):
        return False

    # if it does not match the shows black and white list its no good
    elif show_obj.is_anime and show_obj.release_groups.is_valid(result):
        return False

    # if there's no redownload that's higher (above) and this is the highest initial download then we're good
    elif any_qualities and result.quality in any_qualities:
        return True

    elif best_qualities and result.quality == max(best_qualities):
        return True

    # if we got here than it's either not on the lists, they're empty, or it's lower than the highest required
    else:
        return False
Example #2
0
    def _get_wanted(show, from_date):
        """
        Get a list of episodes that we want to download
        :param show: Show these episodes are from
        :param fromDate: Search from a certain date
        :return: list of wanted episodes
        """

        wanted = []

        any_qualities, best_qualities = Quality.split_quality(show.quality)
        all_qualities = list(set(any_qualities + best_qualities))

        sickrage.app.log.debug(
            "Seeing if we need anything for today from {}".format(show.name))

        # check through the list of statuses to see if we want any
        for episode_object in show.episodes:
            if not episode_object.season > 0 or not episode_object.airdate >= from_date:
                continue

            cur_status, cur_quality = Quality.split_composite_status(
                episode_object.status)

            # if we need a better one then say yes
            if cur_status not in (EpisodeStatus.WANTED,
                                  EpisodeStatus.DOWNLOADED,
                                  EpisodeStatus.SNATCHED,
                                  EpisodeStatus.SNATCHED_PROPER):
                continue

            if cur_status != EpisodeStatus.WANTED:
                if best_qualities:
                    if cur_quality in best_qualities:
                        continue
                    elif cur_quality != Qualities.UNKNOWN and cur_quality > max(
                            best_qualities):
                        continue
                else:
                    if cur_quality in any_qualities:
                        continue
                    elif cur_quality != Qualities.UNKNOWN and cur_quality > max(
                            any_qualities):
                        continue

            # skip upgrading quality of downloaded episodes if enabled
            if cur_status == EpisodeStatus.DOWNLOADED and show.skip_downloaded:
                continue

            wanted += [(episode_object.season, episode_object.episode)]

        return wanted
Example #3
0
    def get_overview(self, epStatus):
        epStatus = try_int(epStatus) or UNKNOWN

        if epStatus == WANTED:
            return Overview.WANTED
        elif epStatus in (UNAIRED, UNKNOWN):
            return Overview.UNAIRED
        elif epStatus in (SKIPPED, IGNORED):
            return Overview.SKIPPED
        elif epStatus in Quality.ARCHIVED:
            return Overview.GOOD
        elif epStatus in Quality.FAILED:
            return Overview.WANTED
        elif epStatus in Quality.SNATCHED:
            return Overview.SNATCHED
        elif epStatus in Quality.SNATCHED_PROPER:
            return Overview.SNATCHED_PROPER
        elif epStatus in Quality.SNATCHED_BEST:
            return Overview.SNATCHED_BEST
        elif epStatus in Quality.DOWNLOADED:
            anyQualities, bestQualities = Quality.split_quality(self.quality)
            epStatus, curQuality = Quality.split_composite_status(epStatus)

            if bestQualities:
                maxBestQuality = max(bestQualities)
                minBestQuality = min(bestQualities)
            else:
                maxBestQuality = None
                minBestQuality = None

            # elif epStatus == DOWNLOADED and curQuality == Quality.UNKNOWN:
            #    return Overview.QUAL
            # if they don't want re-downloads then we call it good if they have anything
            if maxBestQuality is None:
                return Overview.GOOD
            # if the want only first match and already have one call it good
            elif self.skip_downloaded and curQuality in bestQualities:
                return Overview.GOOD
            # if they want only first match and current quality is higher than minimal best quality call it good
            elif self.skip_downloaded and minBestQuality is not None and curQuality > minBestQuality:
                return Overview.GOOD
            # if they have one but it's not the best they want then mark it as qual
            elif curQuality < maxBestQuality:
                return Overview.QUAL
            # if it's >= maxBestQuality then it's good
            else:
                return Overview.GOOD
        else:
            sickrage.app.log.error(
                'Could not parse episode status into a valid overview status: {}'
                .format(epStatus))
Example #4
0
def is_first_best_match(result):
    """
    Checks if the given result is a best quality match and if we want to archive the episode on first match.
    """

    sickrage.app.log.debug("Checking if we should archive our first best quality match for episode " + result.name)

    show_obj = find_show(result.series_id, result.series_provider_id)

    any_qualities, best_qualities = Quality.split_quality(show_obj.quality)

    # if there is a re-download that's a match to one of our best qualities and we want to skip downloaded then we
    # are done
    if best_qualities and show_obj.skip_downloaded and result.quality in best_qualities:
        return True

    return False
Example #5
0
    def _get_wanted(show, from_date):
        any_qualities, best_qualities = Quality.split_quality(show.quality)

        sickrage.app.log.debug(
            "Seeing if we need anything that's older then today for {}".format(
                show.name))

        # check through the list of statuses to see if we want any
        wanted = []
        for episode_object in show.episodes:
            if not episode_object.season > 0 or not datetime.date.today(
            ) > episode_object.airdate > from_date:
                continue

            cur_status, cur_quality = Quality.split_composite_status(
                episode_object.status)

            # if we need a better one then say yes
            if cur_status not in {
                    EpisodeStatus.WANTED, EpisodeStatus.DOWNLOADED,
                    EpisodeStatus.SNATCHED, EpisodeStatus.SNATCHED_PROPER
            }:
                continue

            if cur_status != EpisodeStatus.WANTED:
                if best_qualities:
                    if cur_quality in best_qualities:
                        continue
                    elif cur_quality != Qualities.UNKNOWN and cur_quality > max(
                            best_qualities):
                        continue
                elif any_qualities:
                    if cur_quality in any_qualities:
                        continue
                    elif cur_quality != Qualities.UNKNOWN and cur_quality > max(
                            any_qualities):
                        continue

            # skip upgrading quality of downloaded episodes if enabled
            if cur_status == EpisodeStatus.DOWNLOADED and show.skip_downloaded:
                continue

            wanted += [(episode_object.season, episode_object.episode)]

        return wanted
Example #6
0
    def want_episode(self,
                     season,
                     episode,
                     quality,
                     manualSearch=False,
                     downCurQuality=False):
        try:
            episode_object = self.get_episode(season, episode)
        except EpisodeNotFoundException:
            sickrage.app.log.debug(
                "Unable to find a matching episode in database, ignoring found episode"
            )
            return False

        sickrage.app.log.debug(
            "Checking if found episode %s S%02dE%02d is wanted at quality %s" %
            (self.name, episode_object.season or 0, episode_object.episode
             or 0, Quality.qualityStrings[quality]))

        # if the quality isn't one we want under any circumstances then just say no
        any_qualities, best_qualities = Quality.split_quality(self.quality)
        sickrage.app.log.debug("Any, Best = [{}] [{}] Found = [{}]".format(
            self.qualitiesToString(any_qualities),
            self.qualitiesToString(best_qualities),
            self.qualitiesToString([quality])))

        if quality not in any_qualities + best_qualities or quality is UNKNOWN:
            sickrage.app.log.debug(
                "Don't want this quality, ignoring found episode")
            return False

        ep_status = int(episode_object.status)
        ep_status_text = statusStrings[ep_status]

        sickrage.app.log.debug("Existing episode status: " + str(ep_status) +
                               " (" + ep_status_text + ")")

        # if we know we don't want it then just say no
        if ep_status in Quality.ARCHIVED + [UNAIRED, SKIPPED, IGNORED
                                            ] and not manualSearch:
            sickrage.app.log.debug(
                "Existing episode status is unaired/skipped/ignored/archived, ignoring found episode"
            )
            return False

        cur_status, cur_quality = Quality.split_composite_status(ep_status)

        # if it's one of these then we want it as long as it's in our allowed initial qualities
        if ep_status == WANTED:
            sickrage.app.log.debug(
                "Existing episode status is WANTED, getting found episode")
            return True
        elif manualSearch:
            if (downCurQuality
                    and quality >= cur_quality) or (not downCurQuality
                                                    and quality > cur_quality):
                sickrage.app.log.debug(
                    "Usually ignoring found episode, but forced search allows the quality, getting found episode"
                )
                return True

        # if we are re-downloading then we only want it if it's in our bestQualities list and better than what we
        # have, or we only have one bestQuality and we do not have that quality yet
        if ep_status in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER and quality in best_qualities and (
                quality > cur_quality or cur_quality not in best_qualities):
            sickrage.app.log.debug(
                "Episode already exists but the found episode quality is wanted more, getting found episode"
            )
            return True
        elif cur_quality == UNKNOWN and manualSearch:
            sickrage.app.log.debug(
                "Episode already exists but quality is Unknown, getting found episode"
            )
            return True
        else:
            sickrage.app.log.debug(
                "Episode already exists and the found episode has same/lower quality, ignoring found episode"
            )

        sickrage.app.log.debug(
            "None of the conditions were met, ignoring found episode")
        return False
Example #7
0
def pick_best_result(results, season_pack=False):
    """
    Find the best result out of a list of search results for a show

    :param results: list of result objects
    :param show_id: Show ID we check for
    :return: best result object
    """

    results = results if isinstance(results, list) else [results]

    sickrage.app.log.debug("Picking the best result out of " +
                           str([x.name for x in results]))

    best_result = None

    # find the best result for the current episode
    for cur_result in results:
        show_obj = find_show(cur_result.show_id)

        # build the black And white list
        if show_obj.is_anime:
            if not show_obj.release_groups.is_valid(cur_result):
                continue

        sickrage.app.log.info("Quality of " + cur_result.name + " is " +
                              Quality.qualityStrings[cur_result.quality])

        any_qualities, best_qualities = Quality.split_quality(show_obj.quality)
        if cur_result.quality not in any_qualities + best_qualities:
            sickrage.app.log.debug(
                cur_result.name +
                " is a quality we know we don't want, rejecting it")
            continue

        # check if seeders meet out minimum requirements, disgard result if it does not
        if hasattr(cur_result.provider,
                   'minseed') and cur_result.seeders not in (-1, None):
            if int(cur_result.seeders) < min(cur_result.provider.minseed, 1):
                sickrage.app.log.info(
                    "Discarding torrent because it doesn't meet the minimum seeders: {}. Seeders:  "
                    "{}".format(cur_result.name, cur_result.seeders))
                continue

        # check if leechers meet out minimum requirements, disgard result if it does not
        if hasattr(cur_result.provider,
                   'minleech') and cur_result.leechers not in (-1, None):
            if int(cur_result.leechers) < min(cur_result.provider.minleech, 0):
                sickrage.app.log.info(
                    "Discarding torrent because it doesn't meet the minimum leechers: {}. Leechers:  "
                    "{}".format(cur_result.name, cur_result.leechers))
                continue

        if show_obj.rls_ignore_words and show_names.contains_at_least_one_word(
                cur_result.name, show_obj.rls_ignore_words):
            sickrage.app.log.info("Ignoring " + cur_result.name +
                                  " based on ignored words filter: " +
                                  show_obj.rls_ignore_words)
            continue

        if show_obj.rls_require_words and not show_names.contains_at_least_one_word(
                cur_result.name, show_obj.rls_require_words):
            sickrage.app.log.info("Ignoring " + cur_result.name +
                                  " based on required words filter: " +
                                  show_obj.rls_require_words)
            continue

        if not show_names.filter_bad_releases(cur_result.name, parse=False):
            sickrage.app.log.info(
                "Ignoring " + cur_result.name +
                " because its not a valid scene release that we want")
            continue

        if hasattr(cur_result, 'size'):
            if FailedHistory.has_failed(cur_result.name, cur_result.size,
                                        cur_result.provider.name):
                sickrage.app.log.info(cur_result.name +
                                      " has previously failed, rejecting it")
                continue

            # quality definition video file size constraints check
            try:
                if cur_result.size:
                    quality_size = sickrage.app.config.quality_sizes[
                        cur_result.quality]

                    if season_pack and not len(cur_result.episodes):
                        episode_count = len([
                            x for x in show_obj.episodes
                            if x.season == cur_result.season
                        ])
                        file_size = float(cur_result.size / episode_count /
                                          1000000)
                    else:
                        file_size = float(cur_result.size /
                                          len(cur_result.episodes) / 1000000)

                    if file_size > quality_size:
                        raise Exception(
                            "Ignoring " + cur_result.name +
                            " with size: {} based on quality size filter: {}".
                            format(file_size, quality_size))
            except Exception as e:
                sickrage.app.log.info(e)
                continue

        # verify result content
        # if not cur_result.provider.private:
        #     if cur_result.type in ["nzb", "torrent"] and not cur_result.provider.get_content(cur_result.url):
        #         if not sickrage.app.config.download_unverified_magnet_link and cur_result.url.startswith('magnet'):
        #             sickrage.app.log.info("Ignoring {} because we are unable to verify the download url".format(cur_result.name))
        #             continue

        if not best_result:
            best_result = cur_result
        elif cur_result.quality in best_qualities and (
                best_result.quality < cur_result.quality
                or best_result.quality not in best_qualities):
            best_result = cur_result
        elif cur_result.quality in any_qualities and best_result.quality not in best_qualities and best_result.quality < cur_result.quality:
            best_result = cur_result
        elif best_result.quality == cur_result.quality:
            if "proper" in cur_result.name.lower(
            ) or "repack" in cur_result.name.lower():
                best_result = cur_result
            elif "internal" in best_result.name.lower(
            ) and "internal" not in cur_result.name.lower():
                best_result = cur_result
            elif "xvid" in best_result.name.lower(
            ) and "x264" in cur_result.name.lower():
                sickrage.app.log.info("Preferring " + cur_result.name +
                                      " (x264 over xvid)")
                best_result = cur_result

    if best_result:
        sickrage.app.log.debug("Picked " + best_result.name + " as the best")
    else:
        sickrage.app.log.debug("No result picked.")

    return best_result
Example #8
0
    async def post(self, *args, **kwargs):
        skip_downloaded = self.get_argument('skip_downloaded', None)
        paused = self.get_argument('paused', None)
        default_ep_status = self.get_argument('default_ep_status', None)
        anime = self.get_argument('anime', None)
        sports = self.get_argument('sports', None)
        scene = self.get_argument('scene', None)
        flatten_folders = self.get_argument('flatten_folders', None)
        quality_preset = self.get_argument('quality_preset', None)
        subtitles = self.get_argument('subtitles', None)
        air_by_date = self.get_argument('air_by_date', None)
        any_qualities = self.get_arguments('anyQualities')
        best_qualities = self.get_arguments('bestQualities')
        to_edit = self.get_argument('toEdit', None)

        i = 0
        dir_map = {}
        while True:
            cur_arg = self.get_argument('orig_root_dir_{}'.format(i), None)
            if not cur_arg:
                break

            end_dir = self.get_argument('new_root_dir_{}'.format(i))
            dir_map[cur_arg] = end_dir

            i += 1

        show_ids = to_edit.split("|")
        warnings, errors = [], []
        for curShow in show_ids:
            cur_warnings = []
            cur_errors = []

            show_obj = find_show(int(curShow), session=self.db_session)
            if not show_obj:
                continue

            cur_root_dir = os.path.dirname(show_obj.location)
            cur_show_dir = os.path.basename(show_obj.location)
            if cur_root_dir in dir_map and cur_root_dir != dir_map[
                    cur_root_dir]:
                new_show_dir = os.path.join(dir_map[cur_root_dir],
                                            cur_show_dir)
                sickrage.app.log.info("For show " + show_obj.name +
                                      " changing dir from " +
                                      show_obj.location + " to " +
                                      new_show_dir)
            else:
                new_show_dir = show_obj.location

            if skip_downloaded == 'keep':
                new_skip_downloaded = show_obj.skip_downloaded
            else:
                new_skip_downloaded = True if skip_downloaded == 'enable' else False
            new_skip_downloaded = 'on' if new_skip_downloaded else 'off'

            if paused == 'keep':
                new_paused = show_obj.paused
            else:
                new_paused = True if paused == 'enable' else False
            new_paused = 'on' if new_paused else 'off'

            if default_ep_status == 'keep':
                new_default_ep_status = show_obj.default_ep_status
            else:
                new_default_ep_status = default_ep_status

            if anime == 'keep':
                new_anime = show_obj.anime
            else:
                new_anime = True if anime == 'enable' else False
            new_anime = 'on' if new_anime else 'off'

            if sports == 'keep':
                new_sports = show_obj.sports
            else:
                new_sports = True if sports == 'enable' else False
            new_sports = 'on' if new_sports else 'off'

            if scene == 'keep':
                new_scene = show_obj.is_scene
            else:
                new_scene = True if scene == 'enable' else False
            new_scene = 'on' if new_scene else 'off'

            if air_by_date == 'keep':
                new_air_by_date = show_obj.air_by_date
            else:
                new_air_by_date = True if air_by_date == 'enable' else False
            new_air_by_date = 'on' if new_air_by_date else 'off'

            if flatten_folders == 'keep':
                new_flatten_folders = show_obj.flatten_folders
            else:
                new_flatten_folders = True if flatten_folders == 'enable' else False
            new_flatten_folders = 'on' if new_flatten_folders else 'off'

            if subtitles == 'keep':
                new_subtitles = show_obj.subtitles
            else:
                new_subtitles = True if subtitles == 'enable' else False

            new_subtitles = 'on' if new_subtitles else 'off'

            if quality_preset == 'keep':
                any_qualities, best_qualities = Quality.split_quality(
                    show_obj.quality)
            elif try_int(quality_preset, None):
                best_qualities = []

            post_data = {
                'show': curShow,
                'location': new_show_dir,
                'anyQualities': any_qualities,
                'bestQualities': best_qualities,
                'exceptions_list': [],
                'defaultEpStatus': new_default_ep_status,
                'skip_downloaded': new_skip_downloaded,
                'flatten_folders': new_flatten_folders,
                'paused': new_paused,
                'sports': new_sports,
                'subtitles': new_subtitles,
                'anime': new_anime,
                'scene': new_scene,
                'air_by_date': new_air_by_date,
                'directCall': 'true'
            }

            response = await TornadoHTTP().post(self.get_url("/home/editShow"),
                                                body=urlencode(
                                                    post_data, True))

            if response.body:
                cur_warnings += json_decode(response.body)['warnings']
                cur_errors += json_decode(response.body)['errors']

            if cur_warnings:
                sickrage.app.log.warning("Warnings: " + str(cur_warnings))
                warnings.append('<b>%s:</b>\n<ul>' % show_obj.name + ' '.join(
                    ['<li>%s</li>' % warning
                     for warning in cur_warnings]) + "</ul>")

            if cur_errors:
                sickrage.app.log.error("Errors: " + str(cur_errors))
                errors.append(
                    '<b>%s:</b>\n<ul>' % show_obj.name +
                    ' '.join(['<li>%s</li>' % error
                              for error in cur_errors]) + "</ul>")

        if len(warnings) > 0:
            sickrage.app.alerts.message(
                _('{num_warnings:d} warning{plural} while saving changes:'
                  ).format(num_warnings=len(warnings),
                           plural="" if len(warnings) == 1 else "s"),
                " ".join(warnings))

        if len(errors) > 0:
            sickrage.app.alerts.error(
                _('{num_errors:d} error{plural} while saving changes:').format(
                    num_errors=len(errors),
                    plural="" if len(errors) == 1 else "s"), " ".join(errors))

        return self.redirect("/manage/")
Example #9
0
    async def post(self, *args, **kwargs):
        skip_downloaded = self.get_argument('skip_downloaded', None)
        scene = self.get_argument('scene', None)
        paused = self.get_argument('paused', None)
        default_ep_status = self.get_argument('default_ep_status', None)
        anime = self.get_argument('anime', None)
        flatten_folders = self.get_argument('flatten_folders', None)
        quality_preset = self.get_argument('quality_preset', None)
        subtitles = self.get_argument('subtitles', None)
        search_format = self.get_argument('search_format', None)
        any_qualities = self.get_arguments('anyQualities')
        best_qualities = self.get_arguments('bestQualities')
        to_edit = self.get_argument('toEdit', None)

        i = 0
        dir_map = {}
        while True:
            cur_arg = self.get_argument('orig_root_dir_{}'.format(i), None)
            if not cur_arg:
                break

            end_dir = self.get_argument('new_root_dir_{}'.format(i))
            dir_map[cur_arg] = end_dir

            i += 1

        show_ids = to_edit.split("|")
        warnings, errors = [], []
        for curShow in show_ids:
            cur_warnings = []
            cur_errors = []

            show_obj = find_show(int(curShow))
            if not show_obj:
                continue

            cur_root_dir = os.path.dirname(show_obj.location)
            cur_show_dir = os.path.basename(show_obj.location)
            if cur_root_dir in dir_map and cur_root_dir != dir_map[cur_root_dir]:
                new_show_dir = os.path.join(dir_map[cur_root_dir], cur_show_dir)
                sickrage.app.log.info(
                    "For show " + show_obj.name + " changing dir from " + show_obj.location + " to " + new_show_dir)
            else:
                new_show_dir = show_obj.location

            if skip_downloaded == 'keep':
                new_skip_downloaded = show_obj.skip_downloaded
            else:
                new_skip_downloaded = True if skip_downloaded == 'enable' else False
            new_skip_downloaded = 'on' if new_skip_downloaded else 'off'

            if scene == 'keep':
                new_scene = show_obj.scene
            else:
                new_scene = True if scene == 'enable' else False
            new_scene = 'on' if new_scene else 'off'

            if paused == 'keep':
                new_paused = show_obj.paused
            else:
                new_paused = True if paused == 'enable' else False
            new_paused = 'on' if new_paused else 'off'

            if default_ep_status == 'keep':
                new_default_ep_status = show_obj.default_ep_status
            else:
                new_default_ep_status = int(default_ep_status)

            if anime == 'keep':
                new_anime = show_obj.anime
            else:
                new_anime = True if anime == 'enable' else False
            new_anime = 'on' if new_anime else 'off'

            if search_format == 'keep':
                new_search_format = show_obj.search_format
            else:
                new_search_format = int(search_format)

            if flatten_folders == 'keep':
                new_flatten_folders = show_obj.flatten_folders
            else:
                new_flatten_folders = True if flatten_folders == 'enable' else False
            new_flatten_folders = 'on' if new_flatten_folders else 'off'

            if subtitles == 'keep':
                new_subtitles = show_obj.subtitles
            else:
                new_subtitles = True if subtitles == 'enable' else False

            new_subtitles = 'on' if new_subtitles else 'off'

            if quality_preset == 'keep':
                any_qualities, best_qualities = Quality.split_quality(show_obj.quality)
            elif try_int(quality_preset, None):
                best_qualities = []

            status, message = edit_show(show=curShow, location=new_show_dir, any_qualities=any_qualities, best_qualities=best_qualities, exceptions_list=[],
                                        default_ep_status=new_default_ep_status, skip_downloaded=new_skip_downloaded, flatten_folders=new_flatten_folders,
                                        paused=new_paused, search_format=new_search_format, subtitles=new_subtitles, anime=new_anime,
                                        scene=new_scene, direct_call=True)

            if status is False:
                cur_warnings += json_decode(message)['warnings']
                cur_errors += json_decode(message)['errors']

            if cur_warnings:
                sickrage.app.log.warning("Warnings: " + str(cur_warnings))
                warnings.append('<b>%s:</b>\n<ul>' % show_obj.name + ' '.join(
                    ['<li>%s</li>' % warning for warning in cur_warnings]) + "</ul>")

            if cur_errors:
                sickrage.app.log.error("Errors: " + str(cur_errors))
                errors.append('<b>%s:</b>\n<ul>' % show_obj.name + ' '.join(
                    ['<li>%s</li>' % error for error in cur_errors]) + "</ul>")

        if len(warnings) > 0:
            sickrage.app.alerts.message(
                _('{num_warnings:d} warning{plural} while saving changes:').format(num_warnings=len(warnings),
                                                                                   plural="" if len(warnings) == 1 else "s"), " ".join(warnings))

        if len(errors) > 0:
            sickrage.app.alerts.error(
                _('{num_errors:d} error{plural} while saving changes:').format(num_errors=len(errors),
                                                                               plural="" if len(errors) == 1 else "s"), " ".join(errors))

        return self.redirect("/manage/")