Esempio n. 1
0
def pickBestResult(results, quality_list=None):

    logger.log(u"Picking the best result out of "+str([x.name for x in results]), logger.DEBUG)

    # find the best result for the current episode
    bestResult = None
    for cur_result in results:
        logger.log("Quality of "+cur_result.name+" is "+Quality.qualityStrings[cur_result.quality])
        
        if quality_list and cur_result.quality not in quality_list:
            logger.log(cur_result.name+" is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size, cur_result.provider.name):
            logger.log(cur_result.name + u" has previously failed, rejecting it")
            continue

        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
            bestResult = cur_result
        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked "+bestResult.name+" as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 2
0
def pickBestResult(results, quality_list=None):

    logger.log(u"Picking the best result out of "+str([x.name for x in results]), logger.DEBUG)

    # find the best result for the current episode
    bestResult = None
    for cur_result in results:
        logger.log("Quality of "+cur_result.name+" is "+Quality.qualityStrings[cur_result.quality])
        
        if quality_list and cur_result.quality not in quality_list:
            logger.log(cur_result.name+" is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size):
            logger.log(cur_result.name + u" has previously failed, rejecting it")
            continue

        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
            bestResult = cur_result
        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked "+bestResult.name+" as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 3
0
def pickBestResult(results, show, quality_list=None):
    logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    # build the black And white list
    bwl = None
    if show:
        if show.is_anime:
            bwl = BlackAndWhiteList(show.indexerid)
    else:
        logger.log("Could not create black and white list no show was given", logger.DEBUG)

    # find the best result for the current episode
    bestResult = None
    for cur_result in results:
            
        logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])

        if bwl:
            if not bwl.is_valid(cur_result):
                logger.log(cur_result.name+" does not match the blacklist or the whitelist, rejecting it. Result: " + bwl.get_last_result_msg(), logger.MESSAGE)
                continue

        if quality_list and cur_result.quality not in quality_list:
            logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if show.rls_ignore_words and filter_release_name(cur_result.name, show.rls_ignore_words):
            logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words,
                       logger.MESSAGE)
            continue

        if show.rls_require_words and not filter_release_name(cur_result.name, show.rls_require_words):
            logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words,
                       logger.MESSAGE)
            continue

        if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size,
                                                                       cur_result.provider.name):
            logger.log(cur_result.name + u" has previously failed, rejecting it")
            continue

        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
            bestResult = cur_result

        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 4
0
def pickBestResult(results, show, quality_list=None):
    logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    # build the black And white list
    bwl = None
    if show:
        if show.is_anime:
            bwl = BlackAndWhiteList(show.indexerid)
    else:
        logger.log("Could not create black and white list no show was given", logger.DEBUG)

    # find the best result for the current episode
    bestResult = None
    for cur_result in results:
            
        logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])

        if bwl:
            if not bwl.is_valid(cur_result):
                logger.log(cur_result.name+" does not match the blacklist or the whitelist, rejecting it. Result: " + bwl.get_last_result_msg(), logger.MESSAGE)
                continue

        if quality_list and cur_result.quality not in quality_list:
            logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if show.rls_ignore_words and filter_release_name(cur_result.name, show.rls_ignore_words):
            logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words,
                       logger.MESSAGE)
            continue

        if show.rls_require_words and not filter_release_name(cur_result.name, show.rls_require_words):
            logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words,
                       logger.MESSAGE)
            continue

        if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size,
                                                                       cur_result.provider.name):
            logger.log(cur_result.name + u" has previously failed, rejecting it")
            continue

        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
            bestResult = cur_result

        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 5
0
def pickBestResult(results, show, quality_list=None):
    logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    # find the best result for the current episode
    bestResult = None
    for cur_result in results:

        logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])

        if show.is_anime:
            if not show.release_groups.is_valid(cur_result):
                continue

        if quality_list and cur_result.quality not in quality_list:
            logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if show.rls_ignore_words and filter_release_name(cur_result.name, show.rls_ignore_words):
            logger.log(
                u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words,
                logger.MESSAGE,
            )
            continue

        if show.rls_require_words and not filter_release_name(cur_result.name, show.rls_require_words):
            logger.log(
                u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words,
                logger.MESSAGE,
            )
            continue

        cur_size = getattr(cur_result, "size", None)
        if (
            sickbeard.USE_FAILED_DOWNLOADS
            and None is not cur_size
            and failed_history.hasFailed(cur_result.name, cur_size, cur_result.provider.name)
        ):
            logger.log(cur_result.name + u" has previously failed, rejecting it")
            continue

        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
            bestResult = cur_result

        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 6
0
def pick_best_result(results, show, quality_list=None):
    logger.log(
        u'Picking the best result out of %s' % [x.name for x in results],
        logger.DEBUG)

    # find the best result for the current episode
    best_result = None
    for cur_result in results:

        logger.log(
            u'Quality is %s for %s' %
            (Quality.qualityStrings[cur_result.quality], cur_result.name))

        if show.is_anime and not show.release_groups.is_valid(cur_result):
            continue

        if quality_list and cur_result.quality not in quality_list:
            logger.log(
                u'%s is an unwanted quality, rejecting it' % cur_result.name,
                logger.DEBUG)
            continue

        if not pass_show_wordlist_checks(cur_result.name, show):
            continue

        cur_size = getattr(cur_result, 'size', None)
        if sickbeard.USE_FAILED_DOWNLOADS and None is not cur_size and failed_history.hasFailed(
                cur_result.name, cur_size, cur_result.provider.name):
            logger.log(u'%s has previously failed, rejecting it' %
                       cur_result.name)
            continue

        if not best_result or best_result.quality < cur_result.quality != Quality.UNKNOWN:
            best_result = cur_result

        elif best_result.quality == cur_result.quality:
            if re.search('(?i)(proper|repack)', cur_result.name) or \
                    show.is_anime and re.search('(?i)(v1|v2|v3|v4|v5)', cur_result.name):
                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():
                logger.log(u'Preferring %s (x264 over xvid)' % cur_result.name)
                best_result = cur_result

    if best_result:
        logger.log(u'Picked %s as the best' % best_result.name, logger.DEBUG)
    else:
        logger.log(u'No result picked.', logger.DEBUG)

    return best_result
Esempio n. 7
0
def pick_best_result(results, show, quality_list=None):
    logger.log(u'Picking the best result out of %s' % [x.name for x in results], logger.DEBUG)

    # find the best result for the current episode
    best_result = None
    for cur_result in results:

        logger.log(u'Quality is %s for %s' % (Quality.qualityStrings[cur_result.quality], cur_result.name))

        if show.is_anime and not show.release_groups.is_valid(cur_result):
            continue

        if quality_list and cur_result.quality not in quality_list:
            logger.log(u'%s is an unwanted quality, rejecting it' % cur_result.name, logger.DEBUG)
            continue

        re_extras = dict(re_prefix='.*', re_suffix='.*')
        result = show_name_helpers.contains_any(cur_result.name, show.rls_ignore_words, **re_extras)
        if None is not result and result:
            logger.log(u'Ignored: %s for containing ignore word' % cur_result.name)
            continue

        result = show_name_helpers.contains_any(cur_result.name, show.rls_require_words, **re_extras)
        if None is not result and not result:
            logger.log(u'Ignored: %s for not containing any required word match' % cur_result.name)
            continue

        cur_size = getattr(cur_result, 'size', None)
        if sickbeard.USE_FAILED_DOWNLOADS and None is not cur_size and failed_history.hasFailed(
                cur_result.name, cur_size, cur_result.provider.name):
            logger.log(u'%s has previously failed, rejecting it' % cur_result.name)
            continue

        if not best_result or best_result.quality < cur_result.quality != Quality.UNKNOWN:
            best_result = cur_result

        elif best_result.quality == cur_result.quality:
            if re.search('(?i)(proper|repack)', cur_result.name) or \
                    show.is_anime and re.search('(?i)(v1|v2|v3|v4|v5)', cur_result.name):
                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():
                logger.log(u'Preferring %s (x264 over xvid)' % cur_result.name)
                best_result = cur_result

    if best_result:
        logger.log(u'Picked %s as the best' % best_result.name, logger.DEBUG)
    else:
        logger.log(u'No result picked.', logger.DEBUG)

    return best_result
Esempio n. 8
0
def pickBestResult(results, show, quality_list=None):
    logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    # find the best result for the current episode
    bestResult = None
    for cur_result in results:
            
        logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])

        if show.is_anime:
            if not show.release_groups.is_valid(cur_result):
                continue

        if quality_list and cur_result.quality not in quality_list:
            logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if show.rls_ignore_words and filter_release_name(cur_result.name, show.rls_ignore_words):
            logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words,
                       logger.MESSAGE)
            continue

        if show.rls_require_words and not filter_release_name(cur_result.name, show.rls_require_words):
            logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words,
                       logger.MESSAGE)
            continue

        cur_size = getattr(cur_result, 'size', None)
        if sickbeard.USE_FAILED_DOWNLOADS and None is not cur_size and failed_history.hasFailed(
                cur_result.name, cur_size, cur_result.provider.name):
            logger.log(cur_result.name + u" has previously failed, rejecting it")
            continue

        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
            bestResult = cur_result

        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 9
0
def pickBestResult(results, show, quality_list=None):

    logger.log(u"Picking the best result out of "+str([x.name for x in results]), logger.DEBUG)

    # find the best result for the current episode
    bestResult = None
    for cur_result in results:
        logger.log(u"Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])
        
        if quality_list and cur_result.quality not in quality_list:
            logger.log(cur_result.name+" is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if failed_history.hasFailed(cur_result.name, cur_result.size):
            logger.log(cur_result.name + u" has previously failed, rejecting it")
            continue
        if show.rls_ignore_words and filter_release_name(cur_result.name, show.rls_ignore_words):
            logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words, logger.MESSAGE)
            continue
        if show.rls_require_words and not filter_release_name(cur_result.name, show.rls_require_words):
            logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words, logger.MESSAGE)
            continue
        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
            bestResult = cur_result
        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.MESSAGE)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 10
0
                    else:
                        foundResults[curProvider.name][epNum] = [
                            bestSeasonResult
                        ]

        # go through multi-ep results and see if we really want them or not, get rid of the rest
        multiResults = {}
        if MULTI_EP_RESULT in foundResults[curProvider.name]:
            for multiResult in foundResults[curProvider.name][MULTI_EP_RESULT]:

                logger.log(
                    u"Seeing if we want to bother with multi-episode result " +
                    multiResult.name, logger.DEBUG)

                if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(
                        multiResult.name, multiResult.size,
                        multiResult.provider.name):
                    logger.log(
                        multiResult.name +
                        u" has previously failed, rejecting this multi-ep result"
                    )
                    continue

                # see how many of the eps that this result covers aren't covered by single results
                neededEps = []
                notNeededEps = []
                for epObj in multiResult.episodes:
                    epNum = epObj.episode
                    # if we have results for the episode
                    if epNum in foundResults[curProvider.name] and len(
                            foundResults[curProvider.name][epNum]) > 0:
Esempio n. 11
0
def pickBestResult(results, show):  # pylint: disable=too-many-branches
    """
    Find the best result out of a list of search results for a show

    :param results: list of result objects
    :param show: Shows we check for
    :return: best result object
    """
    results = results if isinstance(results, list) else [results]

    logger.log(
        "Picking the best result out of " + str([x.name for x in results]),
        logger.DEBUG)

    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue

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

        logger.log("Quality of " + cur_result.name + " is " +
                   Quality.qualityStrings[cur_result.quality])

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        if cur_result.quality not in anyQualities + bestQualities:
            logger.log(
                cur_result.name +
                " is a quality we know we don't want, rejecting it",
                logger.DEBUG)
            continue

        if not show_name_helpers.filter_bad_releases(
                cur_result.name, parse=False, show=show):
            continue

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(
                    cur_result.name, cur_result.size,
                    cur_result.provider.name):
                logger.log(cur_result.name +
                           " has previously failed, rejecting it")
                continue

        if not bestResult:
            bestResult = cur_result
        elif cur_result.quality in bestQualities and (
                bestResult.quality < cur_result.quality
                or bestResult.quality not in bestQualities):
            bestResult = cur_result
        elif cur_result.quality in anyQualities and bestResult.quality not in bestQualities and bestResult.quality < cur_result.quality:
            bestResult = cur_result
        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower(
            ) or "real" in cur_result.name.lower(
            ) or "repack" in cur_result.name.lower():
                logger.log("Preferring " + cur_result.name +
                           " (repack/proper/real over nuked)")
                bestResult = cur_result
            elif "internal" in bestResult.name.lower(
            ) and "internal" not in cur_result.name.lower():
                logger.log("Preferring " + cur_result.name +
                           " (normal instead of internal)")
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower(
            ) and "x264" in cur_result.name.lower():
                logger.log("Preferring " + cur_result.name +
                           " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log("Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log("No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 12
0
def pickBestResult(results, show):
    """
    Find the best result out of a list of search results for a show

    :param results: list of result objects
    :param show: Shows we check for
    :return: best result object
    """
    results = results if isinstance(results, list) else [results]

    logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue

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

        logger.log(u"Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        if cur_result.quality not in anyQualities + bestQualities:
            logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if show.rls_ignore_words and show_name_helpers.containsAtLeastOneWord(cur_result.name, cur_result.show.rls_ignore_words):
            logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words,
                       logger.INFO)
            continue

        if show.rls_require_words and not show_name_helpers.containsAtLeastOneWord(cur_result.name, cur_result.show.rls_require_words):
            logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words,
                       logger.INFO)
            continue

        if not show_name_helpers.filterBadReleases(cur_result.name, parse=False):
            logger.log(u"Ignoring " + cur_result.name + " because its not a valid scene release that we want, ignoring it",
                       logger.INFO)
            continue

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size,
                                                                           cur_result.provider.name):
                logger.log(cur_result.name + u" has previously failed, rejecting it")
                continue

        if not bestResult:
            bestResult = cur_result
        elif cur_result.quality in bestQualities and (bestResult.quality < cur_result.quality or bestResult.quality not in bestQualities):
            bestResult = cur_result
        elif cur_result.quality in anyQualities and bestResult.quality not in bestQualities and bestResult.quality < cur_result.quality:
            bestResult = cur_result
        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 13
0
def pickBestResult(results, show):
    results = results if isinstance(results, list) else [results]

    logger.log(
        u"Picking the best result out of " + str([x.name for x in results]),
        logger.DEBUG)

    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue

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

        logger.log("Quality of " + cur_result.name + " is " +
                   Quality.qualityStrings[cur_result.quality])

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        if cur_result.quality not in anyQualities + bestQualities:
            logger.log(
                cur_result.name +
                " is a quality we know we don't want, rejecting it",
                logger.DEBUG)
            continue

        if show.rls_ignore_words and show_name_helpers.containsAtLeastOneWord(
                cur_result.name, cur_result.show.rls_ignore_words):
            logger.log(
                u"Ignoring " + cur_result.name +
                " based on ignored words filter: " + show.rls_ignore_words,
                logger.INFO)
            continue

        if show.rls_require_words and not show_name_helpers.containsAtLeastOneWord(
                cur_result.name, cur_result.show.rls_require_words):
            logger.log(
                u"Ignoring " + cur_result.name +
                " based on required words filter: " + show.rls_require_words,
                logger.INFO)
            continue

        if not show_name_helpers.filterBadReleases(cur_result.name,
                                                   parse=False):
            logger.log(
                u"Ignoring " + cur_result.name +
                " because its not a valid scene release that we want, ignoring it",
                logger.INFO)
            continue

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(
                    cur_result.name, cur_result.size,
                    cur_result.provider.name):
                logger.log(cur_result.name +
                           u" has previously failed, rejecting it")
                continue

        # Only request HEAD instead of downloading content here, and only after all other checks but before bestresult!
        # Otherwise we are spamming providers even when searching with cache only. We can validate now, and download later
        if len(cur_result.url) and cur_result.provider:
            cur_result.url = cur_result.provider.headURL(cur_result)
            if not len(cur_result.url):
                continue

        if cur_result.quality in bestQualities and (
                not bestResult or bestResult.quality < cur_result.quality
                or bestResult not in bestQualities):
            bestResult = cur_result
        elif cur_result.quality in anyQualities and (
                not bestResult or bestResult not in bestQualities) and (
                    not bestResult or bestResult.quality < cur_result.quality):
            bestResult = cur_result
        elif bestResult and bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower(
            ) or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower(
            ) and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower(
            ) and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name +
                           " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 14
0
                    bestSeasonResult.episodes = epObjs

                    epNum = MULTI_EP_RESULT
                    if epNum in foundResults[curProvider.name]:
                        foundResults[curProvider.name][epNum].append(bestSeasonResult)
                    else:
                        foundResults[curProvider.name][epNum] = [bestSeasonResult]

        # go through multi-ep results and see if we really want them or not, get rid of the rest
        multiResults = {}
        if MULTI_EP_RESULT in foundResults[curProvider.name]:
            for multiResult in foundResults[curProvider.name][MULTI_EP_RESULT]:

                logger.log(u"Seeing if we want to bother with multi-episode result " + multiResult.name, logger.DEBUG)

                if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(multiResult.name, multiResult.size,
                                                                               multiResult.provider.name):
                    logger.log(multiResult.name + u" has previously failed, rejecting this multi-ep result")
                    continue

                # see how many of the eps that this result covers aren't covered by single results
                neededEps = []
                notNeededEps = []
                for epObj in multiResult.episodes:
                    epNum = epObj.episode
                    # if we have results for the episode
                    if epNum in foundResults[curProvider.name] and len(foundResults[curProvider.name][epNum]) > 0:
                        neededEps.append(epNum)
                    else:
                        notNeededEps.append(epNum)

                logger.log(
Esempio n. 15
0
def pickBestResult(results, show=None, quality_list=None):
    results = results if isinstance(results, list) else [results]

    logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    bwl = None
    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue

        # build the black And white list
        if not bwl and cur_result.show.is_anime:
            bwl = BlackAndWhiteList(cur_result.show.indexerid)
            if not bwl.is_valid(cur_result):
                logger.log(cur_result.name+" does not match the blacklist or the whitelist, rejecting it. Result: " + bwl.get_last_result_msg(), logger.INFO)
                continue

        logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])

        if quality_list and cur_result.quality not in quality_list:
            logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if show.rls_ignore_words and filter_release_name(cur_result.name, cur_result.show.rls_ignore_words):
            logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words,
                       logger.INFO)
            continue

        if show.rls_require_words and not filter_release_name(cur_result.name, cur_result.show.rls_require_words):
            logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words,
                       logger.INFO)
            continue

        if not show_name_helpers.filterBadReleases(cur_result.name, parse=False):
            logger.log(u"Ignoring " + cur_result.name + " because its not a valid scene release that we want, ignoring it",
                       logger.INFO)
            continue

        if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size,
                                                                       cur_result.provider.name):
            logger.log(cur_result.name + u" has previously failed, rejecting it")
            continue

        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
            bestResult = cur_result

        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 16
0
def search_providers(show, episodes, manual_search=False):
    found_results = {}
    final_results = []

    search_done = False

    orig_thread_name = threading.currentThread().name

    provider_list = [x for x in sickbeard.providers.sortedProviderList() if x.is_active() and x.enable_backlog]
    for cur_provider in provider_list:
        if cur_provider.anime_only and not show.is_anime:
            logger.log(u'%s is not an anime, skipping' % show.name, logger.DEBUG)
            continue

        threading.currentThread().name = '%s :: [%s]' % (orig_thread_name, cur_provider.name)
        provider_id = cur_provider.get_id()

        found_results[provider_id] = {}

        search_count = 0
        search_mode = cur_provider.search_mode

        while True:
            search_count += 1

            if 'eponly' == search_mode:
                logger.log(u'Performing episode search for %s' % show.name)
            else:
                logger.log(u'Performing season pack search for %s' % show.name)

            try:
                cur_provider.cache._clearCache()
                search_results = cur_provider.find_search_results(show, episodes, search_mode, manual_search)
            except exceptions.AuthException as e:
                logger.log(u'Authentication error: %s' % ex(e), logger.ERROR)
                break
            except Exception as e:
                logger.log(u'Error while searching %s, skipping: %s' % (cur_provider.name, ex(e)), logger.ERROR)
                logger.log(traceback.format_exc(), logger.DEBUG)
                break
            finally:
                threading.currentThread().name = orig_thread_name

            search_done = True

            if len(search_results):
                # make a list of all the results for this provider
                for cur_ep in search_results:
                    # skip non-tv crap
                    search_results[cur_ep] = filter(
                        lambda item: show_name_helpers.pass_wordlist_checks(item.name, parse=False) and
                                     item.show == show, search_results[cur_ep])

                    if cur_ep in found_results:
                        found_results[provider_id][cur_ep] += search_results[cur_ep]
                    else:
                        found_results[provider_id][cur_ep] = search_results[cur_ep]

                break
            elif not cur_provider.search_fallback or search_count == 2:
                break

            search_mode = '%sonly' % ('ep', 'sp')['ep' in search_mode]
            logger.log(u'Falling back to %s search ...' % ('season pack', 'episode')['ep' in search_mode])

        # skip to next provider if we have no results to process
        if not len(found_results[provider_id]):
            continue

        any_qualities, best_qualities = Quality.splitQuality(show.quality)

        # pick the best season NZB
        best_season_result = None
        if SEASON_RESULT in found_results[provider_id]:
            best_season_result = pick_best_result(found_results[provider_id][SEASON_RESULT], show,
                                                  any_qualities + best_qualities)

        highest_quality_overall = 0
        for cur_episode in found_results[provider_id]:
            for cur_result in found_results[provider_id][cur_episode]:
                if Quality.UNKNOWN != cur_result.quality and highest_quality_overall < cur_result.quality:
                    highest_quality_overall = cur_result.quality
        logger.log(u'%s is the highest quality of any match' % Quality.qualityStrings[highest_quality_overall],
                   logger.DEBUG)

        # see if every episode is wanted
        if best_season_result:
            # get the quality of the season nzb
            season_qual = best_season_result.quality
            logger.log(u'%s is the quality of the season %s' % (Quality.qualityStrings[season_qual],
                                                                best_season_result.provider.providerType), logger.DEBUG)

            my_db = db.DBConnection()
            sql = 'SELECT episode FROM tv_episodes WHERE showid = %s AND (season IN (%s))' %\
                  (show.indexerid, ','.join([str(x.season) for x in episodes]))
            ep_nums = [int(x['episode']) for x in my_db.select(sql)]

            logger.log(u'Executed query: [%s]' % sql)
            logger.log(u'Episode list: %s' % ep_nums, logger.DEBUG)

            all_wanted = True
            any_wanted = False
            for ep_num in ep_nums:
                for season in set([x.season for x in episodes]):
                    if not show.wantEpisode(season, ep_num, season_qual):
                        all_wanted = False
                    else:
                        any_wanted = True

            # if we need every ep in the season and there's nothing better then just download this and be done with it (unless single episodes are preferred)
            if all_wanted and highest_quality_overall == best_season_result.quality:
                logger.log(u'Every episode in this season is needed, downloading the whole %s %s' %
                           (best_season_result.provider.providerType, best_season_result.name))
                ep_objs = []
                for ep_num in ep_nums:
                    for season in set([x.season for x in episodes]):
                        ep_objs.append(show.getEpisode(season, ep_num))
                best_season_result.episodes = ep_objs

                return [best_season_result]

            elif not any_wanted:
                logger.log(u'No episodes from this season are wanted at this quality, ignoring the result of ' +
                           best_season_result.name, logger.DEBUG)
            else:
                if GenericProvider.NZB == best_season_result.provider.providerType:
                    logger.log(u'Breaking apart the NZB and adding the individual ones to our results', logger.DEBUG)

                    # if not, break it apart and add them as the lowest priority results
                    individual_results = nzbSplitter.splitResult(best_season_result)

                    individual_results = filter(
                        lambda r: show_name_helpers.pass_wordlist_checks(r.name, parse=False) and r.show == show, individual_results)

                    for cur_result in individual_results:
                        if 1 == len(cur_result.episodes):
                            ep_num = cur_result.episodes[0].episode
                        elif 1 < len(cur_result.episodes):
                            ep_num = MULTI_EP_RESULT

                        if ep_num in found_results[provider_id]:
                            found_results[provider_id][ep_num].append(cur_result)
                        else:
                            found_results[provider_id][ep_num] = [cur_result]

                # If this is a torrent all we can do is leech the entire torrent, user will have to select which eps not do download in his torrent client
                else:

                    # Season result from Torrent Provider must be a full-season torrent, creating multi-ep result for it.
                    logger.log(u'Adding multi episode result for full season torrent. In your torrent client, set ' +
                               u'the episodes that you do not want to "don\'t download"')
                    ep_objs = []
                    for ep_num in ep_nums:
                        for season in set([x.season for x in episodes]):
                            ep_objs.append(show.getEpisode(season, ep_num))
                    best_season_result.episodes = ep_objs

                    ep_num = MULTI_EP_RESULT
                    if ep_num in found_results[provider_id]:
                        found_results[provider_id][ep_num].append(best_season_result)
                    else:
                        found_results[provider_id][ep_num] = [best_season_result]

        # go through multi-ep results and see if we really want them or not, get rid of the rest
        multi_results = {}
        if MULTI_EP_RESULT in found_results[provider_id]:
            for multi_result in found_results[provider_id][MULTI_EP_RESULT]:

                logger.log(u'Checking usefulness of multi episode result %s' % multi_result.name, logger.DEBUG)

                if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(multi_result.name, multi_result.size,
                                                                               multi_result.provider.name):
                    logger.log(u'%s has previously failed, rejecting this multi episode result' % multi_result.name)
                    continue

                # see how many of the eps that this result covers aren't covered by single results
                needed_eps = []
                not_needed_eps = []
                for ep_obj in multi_result.episodes:
                    ep_num = ep_obj.episode
                    # if we have results for the episode
                    if ep_num in found_results[provider_id] and 0 < len(found_results[provider_id][ep_num]):
                        needed_eps.append(ep_num)
                    else:
                        not_needed_eps.append(ep_num)

                logger.log(u'Single episode check result is... needed episodes: %s, not needed episodes: %s' %
                           (needed_eps, not_needed_eps), logger.DEBUG)

                if not not_needed_eps:
                    logger.log(u'All of these episodes were covered by single episode results, ignoring this multi episode result', logger.DEBUG)
                    continue

                # check if these eps are already covered by another multi-result
                multi_needed_eps = []
                multi_not_needed_eps = []
                for ep_obj in multi_result.episodes:
                    ep_num = ep_obj.episode
                    if ep_num in multi_results:
                        multi_not_needed_eps.append(ep_num)
                    else:
                        multi_needed_eps.append(ep_num)

                logger.log(u'Multi episode check result is... multi needed episodes: %s, multi not needed episodes: %s' %
                           (multi_needed_eps, multi_not_needed_eps), logger.DEBUG)

                if not multi_needed_eps:
                    logger.log(u'All of these episodes were covered by another multi episode nzb, ignoring this multi episode result',
                               logger.DEBUG)
                    continue

                # if we're keeping this multi-result then remember it
                for ep_obj in multi_result.episodes:
                    multi_results[ep_obj.episode] = multi_result

                # don't bother with the single result if we're going to get it with a multi result
                for ep_obj in multi_result.episodes:
                    ep_num = ep_obj.episode
                    if ep_num in found_results[provider_id]:
                        logger.log(u'A needed multi episode result overlaps with a single episode result for episode #%s, removing the single episode results from the list' %
                                   ep_num, logger.DEBUG)
                        del found_results[provider_id][ep_num]

        # of all the single ep results narrow it down to the best one for each episode
        final_results += set(multi_results.values())
        for cur_ep in found_results[provider_id]:
            if cur_ep in (MULTI_EP_RESULT, SEASON_RESULT):
                continue

            if 0 == len(found_results[provider_id][cur_ep]):
                continue

            best_result = pick_best_result(found_results[provider_id][cur_ep], show)

            # if all results were rejected move on to the next episode
            if not best_result:
                continue

            # filter out possible bad torrents from providers
            if 'torrent' == best_result.resultType and 'blackhole' != sickbeard.TORRENT_METHOD:
                best_result.content = None
                if not best_result.url.startswith('magnet'):
                    best_result.content = best_result.provider.get_url(best_result.url)
                    if not best_result.content:
                        continue

            # add result if its not a duplicate and
            found = False
            for i, result in enumerate(final_results):
                for best_result_ep in best_result.episodes:
                    if best_result_ep in result.episodes:
                        if best_result.quality > result.quality:
                            final_results.pop(i)
                        else:
                            found = True
            if not found:
                final_results += [best_result]

        # check that we got all the episodes we wanted first before doing a match and snatch
        wanted_ep_count = 0
        for wanted_ep in episodes:
            for result in final_results:
                if wanted_ep in result.episodes and is_final_result(result):
                    wanted_ep_count += 1

        # make sure we search every provider for results unless we found everything we wanted
        if len(episodes) == wanted_ep_count:
            break

    if not search_done:
        logger.log(u'No NZB/Torrent providers found or enabled in the SickGear config for backlog searches. Please check your settings.',
                   logger.ERROR)

    return final_results
                epNum = MULTI_EP_RESULT
                if epNum in foundResults:
                    foundResults[epNum].append(bestSeasonNZB)
                else:
                    foundResults[epNum] = [bestSeasonNZB]

    # go through multi-ep results and see if we really want them or not, get rid of the rest
    multiResults = {}
    if MULTI_EP_RESULT in foundResults:
        for multiResult in foundResults[MULTI_EP_RESULT]:

            logger.log(
                u"Seeing if we want to bother with multi-episode result " +
                multiResult.name, logger.DEBUG)
            if failed_history.hasFailed(multiResult.name, multiResult.size):
                logger.log(
                    multiResult.name +
                    u" has previously failed, rejecting this multi-ep result")
                continue

            # see how many of the eps that this result covers aren't covered by single results
            neededEps = []
            notNeededEps = []
            for epObj in multiResult.episodes:
                epNum = epObj.episode
                # if we have results for the episode
                if epNum in foundResults and len(foundResults[epNum]) > 0:
                    # but the multi-ep is worse quality, we don't want it
                    # TODO: wtf is this False for
                    #if False and multiResult.quality <= pickBestResult(foundResults[epNum]):
Esempio n. 18
0
def pickBestResult(results, show):
    results = results if isinstance(results, list) else [results]

    logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue


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

        logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        if cur_result.quality not in anyQualities + bestQualities:
            logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if show.rls_ignore_words and show_name_helpers.containsAtLeastOneWord(cur_result.name, cur_result.show.rls_ignore_words):
            logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words,
                       logger.INFO)
            continue

        if show.rls_require_words and not show_name_helpers.containsAtLeastOneWord(cur_result.name, cur_result.show.rls_require_words):
            logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words,
                       logger.INFO)
            continue

        if not show_name_helpers.filterBadReleases(cur_result.name, parse=False):
            logger.log(u"Ignoring " + cur_result.name + " because its not a valid scene release that we want, ignoring it",
                       logger.INFO)
            continue

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size,
                                                                           cur_result.provider.name):
                logger.log(cur_result.name + u" has previously failed, rejecting it")
                continue

        # Only request HEAD instead of downloading content here, and only after all other checks but before bestresult!
        # Otherwise we are spamming providers even when searching with cache only. We can validate now, and download later
        if len(cur_result.url) and cur_result.provider:
            cur_result.url = cur_result.provider.headURL(cur_result)
            if not len(cur_result.url):
                logger.log('Skipping %s, URL check failed. Bad result from provider.' % cur_result.name,logger.INFO) 
                continue

        if cur_result.quality in bestQualities and (not bestResult or bestResult.quality < cur_result.quality or bestResult not in bestQualities):
            bestResult = cur_result
        elif cur_result.quality in anyQualities and (not bestResult or bestResult not in bestQualities) and (not bestResult or bestResult.quality < cur_result.quality):
            bestResult = cur_result
        elif bestResult and bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 19
0
def pickBestResult(results, show):
    results = results if isinstance(results, list) else [results]

    logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue


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

        logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        if cur_result.quality not in anyQualities + bestQualities:
            logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if show.rls_ignore_words and show_name_helpers.containsAtLeastOneWord(cur_result.name, cur_result.show.rls_ignore_words):
            logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words,
                       logger.INFO)
            continue

        if show.rls_require_words and not show_name_helpers.containsAtLeastOneWord(cur_result.name, cur_result.show.rls_require_words):
            logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words,
                       logger.INFO)
            continue

        if not show_name_helpers.filterBadReleases(cur_result.name, parse=False):
            logger.log(u"Ignoring " + cur_result.name + " because its not a valid scene release that we want, ignoring it",
                       logger.INFO)
            continue

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size,
                                                                           cur_result.provider.name):
                logger.log(cur_result.name + u" has previously failed, rejecting it")
                continue

        # Download the torrent file contents only if it has passed all other checks!
        # Must be done before setting bestResult
        if cur_result.resultType == "torrent" and sickbeard.TORRENT_METHOD != "blackhole":
            if len(cur_result.url) and  not cur_result.url.startswith('magnet'):
                cur_result.content = cur_result.provider.getURL(cur_result.url)
                if not cur_result.content:
                    continue

        if cur_result.quality in bestQualities and (not bestResult or bestResult.quality < cur_result.quality or bestResult not in bestQualities):
            bestResult = cur_result
        elif cur_result.quality in anyQualities and (not bestResult or bestResult not in bestQualities) and (not bestResult or bestResult.quality < cur_result.quality):
            bestResult = cur_result
        elif bestResult and bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 20
0
                    epObjs.append(show.getEpisode(season, curEpNum))
                bestSeasonNZB.episodes = epObjs

                epNum = MULTI_EP_RESULT
                if epNum in foundResults:
                    foundResults[epNum].append(bestSeasonNZB)
                else:
                    foundResults[epNum] = [bestSeasonNZB]

    # go through multi-ep results and see if we really want them or not, get rid of the rest
    multiResults = {}
    if MULTI_EP_RESULT in foundResults:
        for multiResult in foundResults[MULTI_EP_RESULT]:

            logger.log(u"Seeing if we want to bother with multi-episode result "+multiResult.name, logger.DEBUG)
            if failed_history.hasFailed(multiResult.name, multiResult.size):
                logger.log(multiResult.name + u" has previously failed, rejecting this multi-ep result")
                continue

            # see how many of the eps that this result covers aren't covered by single results
            neededEps = []
            notNeededEps = []
            for epObj in multiResult.episodes:
                epNum = epObj.episode
                # if we have results for the episode
                if epNum in foundResults and len(foundResults[epNum]) > 0:
                    # but the multi-ep is worse quality, we don't want it
                    # TODO: wtf is this False for
                    #if False and multiResult.quality <= pickBestResult(foundResults[epNum]):
                    #    notNeededEps.append(epNum)
                    #else:
Esempio n. 21
0
def pickBestResult(results, show):
    """
    Find the best result out of a list of search results for a show

    :param results: list of result objects
    :param show: Shows we check for
    :return: best result object
    """
    results = results if isinstance(results, list) else [results]

    logger.log(
        u"Picking the best result out of " + str([x.name for x in results]),
        logger.DEBUG)

    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue

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

        logger.log(u"Quality of " + cur_result.name + " is " +
                   Quality.qualityStrings[cur_result.quality])

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        if cur_result.quality not in anyQualities + bestQualities:
            logger.log(
                cur_result.name +
                " is a quality we know we don't want, rejecting it",
                logger.DEBUG)
            continue

        if show.rls_ignore_words and show_name_helpers.containsAtLeastOneWord(
                cur_result.name, cur_result.show.rls_ignore_words):
            logger.log(
                u"Ignoring " + cur_result.name +
                " based on ignored words filter: " + show.rls_ignore_words,
                logger.INFO)
            continue

        if show.rls_require_words and not show_name_helpers.containsAtLeastOneWord(
                cur_result.name, cur_result.show.rls_require_words):
            logger.log(
                u"Ignoring " + cur_result.name +
                " based on required words filter: " + show.rls_require_words,
                logger.INFO)
            continue

        if not show_name_helpers.filterBadReleases(cur_result.name,
                                                   parse=False):
            logger.log(
                u"Ignoring " + cur_result.name +
                " because its not a valid scene release that we want, ignoring it",
                logger.INFO)
            continue

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(
                    cur_result.name, cur_result.size,
                    cur_result.provider.name):
                logger.log(cur_result.name +
                           u" has previously failed, rejecting it")
                continue

        if not bestResult:
            bestResult = cur_result
        elif cur_result.quality in bestQualities and (
                bestResult.quality < cur_result.quality
                or bestResult.quality not in bestQualities):
            bestResult = cur_result
        elif cur_result.quality in anyQualities and bestResult.quality not in bestQualities and bestResult.quality < cur_result.quality:
            bestResult = cur_result
        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower(
            ) or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower(
            ) and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower(
            ) and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name +
                           " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 22
0
def pickBestResult(results, show):  # pylint: disable=too-many-branches
    """
    Find the best result out of a list of search results for a show.

    :param results: list of result objects
    :param show: Shows we check for
    :return: best result object
    """
    results = results if isinstance(results, list) else [results]

    logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue

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

        logger.log(u"Quality of " + cur_result.name + u" is " + Quality.qualityStrings[cur_result.quality])

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        if cur_result.quality not in anyQualities + bestQualities:
            logger.log(cur_result.name + u" is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        # If doesnt have min seeders OR min leechers then discard it
        if cur_result.seeders not in (-1, None) and cur_result.leechers not in (-1, None) \
            and hasattr(cur_result.provider, 'minseed') and hasattr(cur_result.provider, 'minleech') \
            and (int(cur_result.seeders) < int(cur_result.provider.minseed) or
                 int(cur_result.leechers) < int(cur_result.provider.minleech)):
            logger.log(u"Discarding torrent because it doesn't meet the minimum provider setting "
                       u"S:{0} L:{1}. Result has S:{2} L:{3}".format
                       (cur_result.provider.minseed, cur_result.provider.minleech,
                        cur_result.seeders, cur_result.leechers))
            continue

        show_words = show_name_helpers.show_words(cur_result.show)
        ignore_words = show_words.ignore_words
        require_words = show_words.require_words
        found_ignore_word = show_name_helpers.containsAtLeastOneWord(cur_result.name, ignore_words)
        found_require_word = show_name_helpers.containsAtLeastOneWord(cur_result.name, require_words)

        if ignore_words and found_ignore_word:
            logger.log(u"Ignoring " + cur_result.name + u" based on ignored words filter: " + found_ignore_word,
                       logger.INFO)
            continue

        if require_words and not found_require_word:
            logger.log(u"Ignoring " + cur_result.name + u" based on required words filter: " + require_words,
                       logger.INFO)
            continue

        if not show_name_helpers.filterBadReleases(cur_result.name, parse=False):
            continue

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size,
                                                                           cur_result.provider.name):
                logger.log(cur_result.name + u" has previously failed, rejecting it")
                continue
        preferred_words = ''
        if sickbeard.PREFERRED_WORDS:
            preferred_words = sickbeard.PREFERRED_WORDS.lower().split(',')
        undesired_words = ''
        if sickbeard.UNDESIRED_WORDS:
            undesired_words = sickbeard.UNDESIRED_WORDS.lower().split(',')

        if not bestResult:
            bestResult = cur_result
        elif cur_result.quality in bestQualities and (bestResult.quality < cur_result.quality or
                                                      bestResult.quality not in bestQualities):
            bestResult = cur_result
        elif cur_result.quality in anyQualities and bestResult.quality not in bestQualities and \
                bestResult.quality < cur_result.quality:
            bestResult = cur_result
        elif bestResult.quality == cur_result.quality:
            if any(ext in cur_result.name.lower() for ext in preferred_words):
                logger.log(u"Preferring " + cur_result.name + u" (preferred words)")
                bestResult = cur_result
            if cur_result.proper_tags:
                logger.log(u"Preferring " + cur_result.name + u" (repack/proper/real/rerip over nuked)")
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + u" (normal instead of internal)")
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + u" (x264 over xvid)")
                bestResult = cur_result
            if any(ext in bestResult.name.lower() and ext not in cur_result.name.lower() for ext in undesired_words):
                logger.log(u"Dont want this release " + cur_result.name + u" (contains undesired word(s))")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + u" as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 23
0
def pickBestResult(results, show):  # pylint: disable=too-many-branches
    """
    Find the best result out of a list of search results for a show

    :param results: list of result objects
    :param show: Shows we check for
    :return: best result object
    """
    results = results if isinstance(results, list) else [results]

    logger.log("Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue

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

        logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        if cur_result.quality not in anyQualities + bestQualities:
            logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if not show_name_helpers.filter_bad_releases(cur_result.name, parse=False, show=show):
            continue

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size,
                                                                           cur_result.provider.name):
                logger.log(cur_result.name + " has previously failed, rejecting it")
                continue

        if not bestResult:
            bestResult = cur_result
        elif cur_result.quality in bestQualities and (bestResult.quality < cur_result.quality or bestResult.quality not in bestQualities):
            bestResult = cur_result
        elif cur_result.quality in anyQualities and bestResult.quality not in bestQualities and bestResult.quality < cur_result.quality:
            bestResult = cur_result
        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "real" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                logger.log("Preferring " + cur_result.name + " (repack/proper/real over nuked)")
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                logger.log("Preferring " + cur_result.name + " (normal instead of internal)")
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log("Preferring " + cur_result.name + " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log("Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log("No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 24
0
def pickBestResult(results, show, quality_list=None):
    results = results if isinstance(results, list) else [results]

    logger.log(
        u"Picking the best result out of " + str([x.name for x in results]),
        logger.DEBUG)

    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue

        # filter out possible bad torrents from providers such as ezrss
        if isinstance(cur_result, sickbeard.classes.SearchResult):
            if cur_result.resultType == "torrent" and sickbeard.TORRENT_METHOD != "blackhole":
                if not cur_result.url.startswith('magnet'):
                    cur_result.content = cur_result.provider.getURL(
                        cur_result.url)
                    if not cur_result.content:
                        continue
        else:
            if not cur_result.url.startswith('magnet'):
                cur_result.content = cur_result.provider.getURL(cur_result.url)
                if not cur_result.content:
                    continue

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

        logger.log("Quality of " + cur_result.name + " is " +
                   Quality.qualityStrings[cur_result.quality])

        if quality_list and cur_result.quality not in quality_list:
            logger.log(
                cur_result.name +
                " is a quality we know we don't want, rejecting it",
                logger.DEBUG)
            continue

        if show.rls_ignore_words and show_name_helpers.containsAtLeastOneWord(
                cur_result.name, cur_result.show.rls_ignore_words):
            logger.log(
                u"Ignoring " + cur_result.name +
                " based on ignored words filter: " + show.rls_ignore_words,
                logger.INFO)
            continue

        if show.rls_require_words and not show_name_helpers.containsAtLeastOneWord(
                cur_result.name, cur_result.show.rls_require_words):
            logger.log(
                u"Ignoring " + cur_result.name +
                " based on required words filter: " + show.rls_require_words,
                logger.INFO)
            continue

        if not show_name_helpers.filterBadReleases(cur_result.name,
                                                   parse=False):
            logger.log(
                u"Ignoring " + cur_result.name +
                " because its not a valid scene release that we want, ignoring it",
                logger.INFO)
            continue

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(
                    cur_result.name, cur_result.size,
                    cur_result.provider.name):
                logger.log(cur_result.name +
                           u" has previously failed, rejecting it")
                continue

        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
            bestResult = cur_result

        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower(
            ) or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower(
            ) and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower(
            ) and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name +
                           " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 25
0
def search_providers(show,
                     episodes,
                     manual_search=False,
                     torrent_only=False,
                     try_other_searches=False):
    found_results = {}
    final_results = []

    search_done = False

    orig_thread_name = threading.currentThread().name

    provider_list = [
        x for x in sickbeard.providers.sortedProviderList()
        if x.is_active() and x.enable_backlog and (
            not torrent_only or x.providerType == GenericProvider.TORRENT)
    ]
    for cur_provider in provider_list:
        if cur_provider.anime_only and not show.is_anime:
            logger.log(u'%s is not an anime, skipping' % show.name,
                       logger.DEBUG)
            continue

        threading.currentThread().name = '%s :: [%s]' % (orig_thread_name,
                                                         cur_provider.name)
        provider_id = cur_provider.get_id()

        found_results[provider_id] = {}

        search_count = 0
        search_mode = cur_provider.search_mode

        while True:
            search_count += 1

            if 'eponly' == search_mode:
                logger.log(u'Performing episode search for %s' % show.name)
            else:
                logger.log(u'Performing season pack search for %s' % show.name)

            try:
                cur_provider.cache._clearCache()
                search_results = cur_provider.find_search_results(
                    show,
                    episodes,
                    search_mode,
                    manual_search,
                    try_other_searches=try_other_searches)
                if any(search_results):
                    logger.log(', '.join([
                        '%s %s candidate%s' %
                        (len(v), (('multiep', 'season')[SEASON_RESULT == k],
                                  'episode')['ep' in search_mode],
                         helpers.maybe_plural(len(v)))
                        for (k, v) in search_results.iteritems()
                    ]))
            except exceptions.AuthException as e:
                logger.log(u'Authentication error: %s' % ex(e), logger.ERROR)
                break
            except Exception as e:
                logger.log(
                    u'Error while searching %s, skipping: %s' %
                    (cur_provider.name, ex(e)), logger.ERROR)
                logger.log(traceback.format_exc(), logger.DEBUG)
                break
            finally:
                threading.currentThread().name = orig_thread_name

            search_done = True

            if len(search_results):
                # make a list of all the results for this provider
                for cur_ep in search_results:
                    # skip non-tv crap
                    search_results[cur_ep] = filter(
                        lambda ep_item: show_name_helpers.pass_wordlist_checks(
                            ep_item.name, parse=False) and ep_item.show ==
                        show, search_results[cur_ep])

                    if cur_ep in found_results:
                        found_results[provider_id][cur_ep] += search_results[
                            cur_ep]
                    else:
                        found_results[provider_id][cur_ep] = search_results[
                            cur_ep]

                break
            elif not cur_provider.search_fallback or search_count == 2:
                break

            search_mode = '%sonly' % ('ep', 'sp')['ep' in search_mode]
            logger.log(u'Falling back to %s search ...' %
                       ('season pack', 'episode')['ep' in search_mode])

        # skip to next provider if we have no results to process
        if not len(found_results[provider_id]):
            continue

        any_qualities, best_qualities = Quality.splitQuality(show.quality)

        # pick the best season NZB
        best_season_result = None
        if SEASON_RESULT in found_results[provider_id]:
            best_season_result = pick_best_result(
                found_results[provider_id][SEASON_RESULT], show,
                any_qualities + best_qualities)

        highest_quality_overall = 0
        for cur_episode in found_results[provider_id]:
            for cur_result in found_results[provider_id][cur_episode]:
                if Quality.UNKNOWN != cur_result.quality and highest_quality_overall < cur_result.quality:
                    highest_quality_overall = cur_result.quality
        logger.log(
            u'%s is the highest quality of any match' %
            Quality.qualityStrings[highest_quality_overall], logger.DEBUG)

        # see if every episode is wanted
        if best_season_result:
            # get the quality of the season nzb
            season_qual = best_season_result.quality
            logger.log(
                u'%s is the quality of the season %s' %
                (Quality.qualityStrings[season_qual],
                 best_season_result.provider.providerType), logger.DEBUG)

            my_db = db.DBConnection()
            sql = 'SELECT episode FROM tv_episodes WHERE showid = %s AND (season IN (%s))' %\
                  (show.indexerid, ','.join([str(x.season) for x in episodes]))
            ep_nums = [int(x['episode']) for x in my_db.select(sql)]

            logger.log(u'Executed query: [%s]' % sql)
            logger.log(u'Episode list: %s' % ep_nums, logger.DEBUG)

            all_wanted = True
            any_wanted = False
            for ep_num in ep_nums:
                for season in set([x.season for x in episodes]):
                    if not show.wantEpisode(season, ep_num, season_qual):
                        all_wanted = False
                    else:
                        any_wanted = True

            # if we need every ep in the season and there's nothing better then just download this and
            # be done with it (unless single episodes are preferred)
            if all_wanted and highest_quality_overall == best_season_result.quality:
                logger.log(
                    u'Every episode in this season is needed, downloading the whole %s %s'
                    % (best_season_result.provider.providerType,
                       best_season_result.name))
                ep_objs = []
                for ep_num in ep_nums:
                    for season in set([x.season for x in episodes]):
                        ep_objs.append(show.getEpisode(season, ep_num))
                best_season_result.episodes = ep_objs

                return [best_season_result]

            elif not any_wanted:
                logger.log(
                    u'No episodes from this season are wanted at this quality, ignoring the result of '
                    + best_season_result.name, logger.DEBUG)
            else:
                if GenericProvider.NZB == best_season_result.provider.providerType:
                    logger.log(
                        u'Breaking apart the NZB and adding the individual ones to our results',
                        logger.DEBUG)

                    # if not, break it apart and add them as the lowest priority results
                    individual_results = nzbSplitter.splitResult(
                        best_season_result)

                    individual_results = filter(
                        lambda r: show_name_helpers.pass_wordlist_checks(
                            r.name, parse=False) and r.show == show,
                        individual_results)

                    for cur_result in individual_results:
                        if 1 == len(cur_result.episodes):
                            ep_num = cur_result.episodes[0].episode
                        elif 1 < len(cur_result.episodes):
                            ep_num = MULTI_EP_RESULT

                        if ep_num in found_results[provider_id]:
                            found_results[provider_id][ep_num].append(
                                cur_result)
                        else:
                            found_results[provider_id][ep_num] = [cur_result]

                # If this is a torrent all we can do is leech the entire torrent,
                # user will have to select which eps not do download in his torrent client
                else:

                    # Season result from Torrent Provider must be a full-season torrent, creating multi-ep result for it
                    logger.log(
                        u'Adding multi episode result for full season torrent. In your torrent client, set '
                        +
                        u'the episodes that you do not want to "don\'t download"'
                    )
                    ep_objs = []
                    for ep_num in ep_nums:
                        for season in set([x.season for x in episodes]):
                            ep_objs.append(show.getEpisode(season, ep_num))
                    best_season_result.episodes = ep_objs

                    ep_num = MULTI_EP_RESULT
                    if ep_num in found_results[provider_id]:
                        found_results[provider_id][ep_num].append(
                            best_season_result)
                    else:
                        found_results[provider_id][ep_num] = [
                            best_season_result
                        ]

        # go through multi-ep results and see if we really want them or not, get rid of the rest
        multi_results = {}
        if MULTI_EP_RESULT in found_results[provider_id]:
            for multi_result in found_results[provider_id][MULTI_EP_RESULT]:

                logger.log(
                    u'Checking usefulness of multi episode result %s' %
                    multi_result.name, logger.DEBUG)

                if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(
                        multi_result.name, multi_result.size,
                        multi_result.provider.name):
                    logger.log(
                        u'%s has previously failed, rejecting this multi episode result'
                        % multi_result.name)
                    continue

                # see how many of the eps that this result covers aren't covered by single results
                needed_eps = []
                not_needed_eps = []
                for ep_obj in multi_result.episodes:
                    ep_num = ep_obj.episode
                    # if we have results for the episode
                    if ep_num in found_results[provider_id] and 0 < len(
                            found_results[provider_id][ep_num]):
                        needed_eps.append(ep_num)
                    else:
                        not_needed_eps.append(ep_num)

                logger.log(
                    u'Single episode check result is... needed episodes: %s, not needed episodes: %s'
                    % (needed_eps, not_needed_eps), logger.DEBUG)

                if not not_needed_eps:
                    logger.log(
                        u'All of these episodes were covered by single episode results, '
                        + 'ignoring this multi episode result', logger.DEBUG)
                    continue

                # check if these eps are already covered by another multi-result
                multi_needed_eps = []
                multi_not_needed_eps = []
                for ep_obj in multi_result.episodes:
                    ep_num = ep_obj.episode
                    if ep_num in multi_results:
                        multi_not_needed_eps.append(ep_num)
                    else:
                        multi_needed_eps.append(ep_num)

                logger.log(
                    u'Multi episode check result is... multi needed episodes: '
                    + '%s, multi not needed episodes: %s' %
                    (multi_needed_eps, multi_not_needed_eps), logger.DEBUG)

                if not multi_needed_eps:
                    logger.log(
                        u'All of these episodes were covered by another multi episode nzb, '
                        + 'ignoring this multi episode result', logger.DEBUG)
                    continue

                # if we're keeping this multi-result then remember it
                for ep_obj in multi_result.episodes:
                    multi_results[ep_obj.episode] = multi_result

                # don't bother with the single result if we're going to get it with a multi result
                for ep_obj in multi_result.episodes:
                    ep_num = ep_obj.episode
                    if ep_num in found_results[provider_id]:
                        logger.log(
                            u'A needed multi episode result overlaps with a single episode result for episode '
                            +
                            '#%s, removing the single episode results from the list'
                            % ep_num, logger.DEBUG)
                        del found_results[provider_id][ep_num]

        # of all the single ep results narrow it down to the best one for each episode
        final_results += set(multi_results.values())
        for cur_ep in found_results[provider_id]:
            if cur_ep in (MULTI_EP_RESULT, SEASON_RESULT):
                continue

            if 0 == len(found_results[provider_id][cur_ep]):
                continue

            best_result = pick_best_result(found_results[provider_id][cur_ep],
                                           show)

            # if all results were rejected move on to the next episode
            if not best_result:
                continue

            # filter out possible bad torrents from providers
            if 'torrent' == best_result.resultType:
                if best_result.url.startswith('magnet'):
                    if 'blackhole' != sickbeard.TORRENT_METHOD:
                        best_result.content = None
                else:
                    td = best_result.provider.get_url(best_result.url)
                    if not td:
                        continue
                    if getattr(best_result.provider, 'chk_td', None):
                        name = None
                        try:
                            hdr = re.findall('(\w+(\d+):)', td[0:6])[0]
                            x, v = len(hdr[0]), int(hdr[1])
                            for item in range(0, 12):
                                y = x + v
                                name = 'name' == td[x:y]
                                w = re.findall('((?:i\d+e|d|l)?(\d+):)',
                                               td[y:y + 32])[0]
                                x, v = y + len(w[0]), int(w[1])
                                if name:
                                    name = td[x:x + v]
                                    break
                        except:
                            continue
                        if name:
                            if not pass_show_wordlist_checks(name, show):
                                continue
                            if not show_name_helpers.pass_wordlist_checks(
                                    name):
                                logger.log(
                                    u'Ignored: %s (debug log has detail)' %
                                    name)
                                continue
                            best_result.name = name

                    if 'blackhole' != sickbeard.TORRENT_METHOD:
                        best_result.content = td

            # add result if its not a duplicate and
            found = False
            for i, result in enumerate(final_results):
                for best_result_ep in best_result.episodes:
                    if best_result_ep in result.episodes:
                        if best_result.quality > result.quality:
                            final_results.pop(i)
                        else:
                            found = True
            if not found:
                final_results += [best_result]

        # check that we got all the episodes we wanted first before doing a match and snatch
        wanted_ep_count = 0
        for wanted_ep in episodes:
            for result in final_results:
                if wanted_ep in result.episodes and is_final_result(result):
                    wanted_ep_count += 1

        # make sure we search every provider for results unless we found everything we wanted
        if len(episodes) == wanted_ep_count:
            break

    if not len(provider_list):
        logger.log(
            'No NZB/Torrent sources enabled in Search Provider options to do backlog searches',
            logger.WARNING)
    elif not search_done:
        logger.log(
            'Failed backlog search of %s enabled provider%s. More info in debug log.'
            % (len(provider_list), helpers.maybe_plural(len(provider_list))),
            logger.ERROR)

    return final_results
Esempio n. 26
0
def searchProviders(show, episodes, manual_search=False):
    foundResults = {}
    finalResults = []

    didSearch = False

    origThreadName = threading.currentThread().name

    providers = [x for x in sickbeard.providers.sortedProviderList() if x.is_active() and x.enable_backlog]
    for providerNum, curProvider in enumerate(providers):
        if curProvider.anime_only and not show.is_anime:
            logger.log(u"" + str(show.name) + " is not an anime, skipping", logger.DEBUG)
            continue

        threading.currentThread().name = origThreadName + " :: [" + curProvider.name + "]"

        foundResults[curProvider.name] = {}

        searchCount = 0
        search_mode = curProvider.search_mode

        while(True):
            searchCount += 1

            if search_mode == 'eponly':
                logger.log(u"Performing episode search for " + show.name)
            else:
                logger.log(u"Performing season pack search for " + show.name)

            try:
                curProvider.cache._clearCache()
                searchResults = curProvider.find_search_results(show, episodes, search_mode, manual_search)
            except exceptions.AuthException as e:
                logger.log(u"Authentication error: " + ex(e), logger.ERROR)
                break
            except Exception as e:
                logger.log(u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR)
                logger.log(traceback.format_exc(), logger.DEBUG)
                break
            finally:
                threading.currentThread().name = origThreadName

            didSearch = True

            if len(searchResults):
                # make a list of all the results for this provider
                for curEp in searchResults:
                    # skip non-tv crap
                    searchResults[curEp] = filter(
                        lambda x: show_name_helpers.filterBadReleases(x.name, parse=False) and x.show == show, searchResults[curEp])

                    if curEp in foundResults:
                        foundResults[curProvider.name][curEp] += searchResults[curEp]
                    else:
                        foundResults[curProvider.name][curEp] = searchResults[curEp]

                break
            elif not curProvider.search_fallback or searchCount == 2:
                break

            if search_mode == 'sponly':
                logger.log(u"FALLBACK EPISODE SEARCH INITIATED ...")
                search_mode = 'eponly'
            else:
                logger.log(u"FALLBACK SEASON PACK SEARCH INITIATED ...")
                search_mode = 'sponly'

        # skip to next provider if we have no results to process
        if not len(foundResults[curProvider.name]):
            continue

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        # pick the best season NZB
        bestSeasonResult = None
        if SEASON_RESULT in foundResults[curProvider.name]:
            bestSeasonResult = pickBestResult(foundResults[curProvider.name][SEASON_RESULT], show,
                                           anyQualities + bestQualities)

        highest_quality_overall = 0
        for cur_episode in foundResults[curProvider.name]:
            for cur_result in foundResults[curProvider.name][cur_episode]:
                if cur_result.quality != Quality.UNKNOWN and cur_result.quality > highest_quality_overall:
                    highest_quality_overall = cur_result.quality
        logger.log(u"The highest quality of any match is " + Quality.qualityStrings[highest_quality_overall],
                   logger.DEBUG)

        # see if every episode is wanted
        if bestSeasonResult:
            searchedSeasons = []
            searchedSeasons = [str(x.season) for x in episodes]
            # get the quality of the season nzb
            seasonQual = bestSeasonResult.quality
            logger.log(
                u"The quality of the season " + bestSeasonResult.provider.providerType + " is " + Quality.qualityStrings[
                    seasonQual], logger.DEBUG)

            myDB = db.DBConnection()
            allEps = [int(x["episode"]) 
                      for x in myDB.select("SELECT episode FROM tv_episodes WHERE showid = ? AND ( season IN ( " + ','.join(searchedSeasons) + " ) )", 
                                           [show.indexerid])]
            
            logger.log(u"Executed query: [SELECT episode FROM tv_episodes WHERE showid = %s AND season in  %s]" % (show.indexerid, ','.join(searchedSeasons)))
            logger.log(u"Episode list: " + str(allEps), logger.DEBUG)

            allWanted = True
            anyWanted = False
            for curEpNum in allEps:
                for season in set([x.season for x in episodes]):
                    if not show.wantEpisode(season, curEpNum, seasonQual):
                        allWanted = False
                    else:
                        anyWanted = True

            # if we need every ep in the season and there's nothing better then just download this and be done with it (unless single episodes are preferred)
            if allWanted and bestSeasonResult.quality == highest_quality_overall:
                logger.log(
                    u"Every episode in this season is needed, downloading the whole " + bestSeasonResult.provider.providerType + " " + bestSeasonResult.name)
                epObjs = []
                for curEpNum in allEps:
                    epObjs.append(show.getEpisode(season, curEpNum))
                bestSeasonResult.episodes = epObjs

                return [bestSeasonResult]

            elif not anyWanted:
                logger.log(
                    u"No episodes from this season are wanted at this quality, ignoring the result of " + bestSeasonResult.name,
                    logger.DEBUG)

            else:

                if bestSeasonResult.provider.providerType == GenericProvider.NZB:
                    logger.log(u"Breaking apart the NZB and adding the individual ones to our results", logger.DEBUG)

                    # if not, break it apart and add them as the lowest priority results
                    individualResults = nzbSplitter.splitResult(bestSeasonResult)

                    individualResults = filter(
                        lambda x: show_name_helpers.filterBadReleases(x.name, parse=False) and x.show == show, individualResults)

                    for curResult in individualResults:
                        if len(curResult.episodes) == 1:
                            epNum = curResult.episodes[0].episode
                        elif len(curResult.episodes) > 1:
                            epNum = MULTI_EP_RESULT

                        if epNum in foundResults[curProvider.name]:
                            foundResults[curProvider.name][epNum].append(curResult)
                        else:
                            foundResults[curProvider.name][epNum] = [curResult]

                # If this is a torrent all we can do is leech the entire torrent, user will have to select which eps not do download in his torrent client
                else:

                    # Season result from Torrent Provider must be a full-season torrent, creating multi-ep result for it.
                    logger.log(
                        u"Adding multi episode result for full season torrent. Set the episodes you don't want to 'don't download' in your torrent client if desired!")
                    epObjs = []
                    for curEpNum in allEps:
                        epObjs.append(show.getEpisode(season, curEpNum))
                    bestSeasonResult.episodes = epObjs

                    epNum = MULTI_EP_RESULT
                    if epNum in foundResults[curProvider.name]:
                        foundResults[curProvider.name][epNum].append(bestSeasonResult)
                    else:
                        foundResults[curProvider.name][epNum] = [bestSeasonResult]

        # go through multi-ep results and see if we really want them or not, get rid of the rest
        multiResults = {}
        if MULTI_EP_RESULT in foundResults[curProvider.name]:
            for multiResult in foundResults[curProvider.name][MULTI_EP_RESULT]:

                logger.log(u"Seeing if we want to bother with multi episode result " + multiResult.name, logger.DEBUG)

                if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(multiResult.name, multiResult.size,
                                                                               multiResult.provider.name):
                    logger.log(multiResult.name + u" has previously failed, rejecting this multi episode result")
                    continue

                # see how many of the eps that this result covers aren't covered by single results
                neededEps = []
                notNeededEps = []
                for epObj in multiResult.episodes:
                    epNum = epObj.episode
                    # if we have results for the episode
                    if epNum in foundResults[curProvider.name] and len(foundResults[curProvider.name][epNum]) > 0:
                        neededEps.append(epNum)
                    else:
                        notNeededEps.append(epNum)

                logger.log(
                    u"Single episode check result is needed episodes: " + str(neededEps) + ", not needed episodes: " + str(notNeededEps),
                    logger.DEBUG)

                if not notNeededEps:
                    logger.log(u"All of these episodes were covered by single episode results, ignoring this multi episode result", logger.DEBUG)
                    continue

                # check if these eps are already covered by another multi-result
                multiNeededEps = []
                multiNotNeededEps = []
                for epObj in multiResult.episodes:
                    epNum = epObj.episode
                    if epNum in multiResults:
                        multiNotNeededEps.append(epNum)
                    else:
                        multiNeededEps.append(epNum)

                logger.log(
                    u"Multi episode check result is multi needed episodes: " + str(multiNeededEps) + ", multi not needed episodes: " + str(
                        multiNotNeededEps), logger.DEBUG)

                if not multiNeededEps:
                    logger.log(
                        u"All of these episodes were covered by another multi episode nzb, ignoring this multi episode result",
                        logger.DEBUG)
                    continue

                # if we're keeping this multi-result then remember it
                for epObj in multiResult.episodes:
                    multiResults[epObj.episode] = multiResult

                # don't bother with the single result if we're going to get it with a multi result
                for epObj in multiResult.episodes:
                    epNum = epObj.episode
                    if epNum in foundResults[curProvider.name]:
                        logger.log(
                            u"A needed multi episode result overlaps with a single episode result for episode #" + str(
                                epNum) + ", removing the single episode results from the list", logger.DEBUG)
                        del foundResults[curProvider.name][epNum]

        # of all the single ep results narrow it down to the best one for each episode
        finalResults += set(multiResults.values())
        for curEp in foundResults[curProvider.name]:
            if curEp in (MULTI_EP_RESULT, SEASON_RESULT):
                continue

            if len(foundResults[curProvider.name][curEp]) == 0:
                continue

            bestResult = pickBestResult(foundResults[curProvider.name][curEp], show)

            # if all results were rejected move on to the next episode
            if not bestResult:
                continue

            # filter out possible bad torrents from providers
            if bestResult.resultType == "torrent" and sickbeard.TORRENT_METHOD != "blackhole":
                bestResult.content = None
                if not bestResult.url.startswith('magnet'):
                    bestResult.content = bestResult.provider.get_url(bestResult.url)
                    if not bestResult.content:
                        continue
                    
            # add result if its not a duplicate and
            found = False
            for i, result in enumerate(finalResults):
                for bestResultEp in bestResult.episodes:
                    if bestResultEp in result.episodes:
                        if result.quality < bestResult.quality:
                            finalResults.pop(i)
                        else:
                            found = True
            if not found:
                finalResults += [bestResult]

        # check that we got all the episodes we wanted first before doing a match and snatch
        wantedEpCount = 0
        for wantedEp in episodes:
            for result in finalResults:
                if wantedEp in result.episodes and isFinalResult(result):
                    wantedEpCount += 1

        # make sure we search every provider for results unless we found everything we wanted
        if wantedEpCount == len(episodes):
            break

    if not didSearch:
        logger.log(u"No NZB/Torrent providers found or enabled in the SickGear config for backlog searches. Please check your settings.",
                   logger.ERROR)

    return finalResults
Esempio n. 27
0
def pickBestResult(results, show, quality_list=None):
    results = results if isinstance(results, list) else [results]

    logger.log(u"Picking the best result out of " + str([x.name for x in results]), logger.DEBUG)

    bwl = None
    bestResult = None

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue

        # filter out possible bad torrents from providers such as ezrss
        if isinstance(cur_result, sickbeard.classes.SearchResult):
            if cur_result.resultType == "torrent" and sickbeard.TORRENT_METHOD != "blackhole":
                if not cur_result.url.startswith('magnet'):
                    cur_result.content = cur_result.provider.getURL(cur_result.url)
                    if not cur_result.content:
                        continue
        else:
            if not cur_result.url.startswith('magnet'):
                cur_result.content = cur_result.provider.getURL(cur_result.url)
                if not cur_result.content:
                    continue

        # build the black And white list
        if cur_result.show.is_anime:
            if not bwl:
                bwl = BlackAndWhiteList(cur_result.show.indexerid)
            if not bwl.is_valid(cur_result):
                logger.log(cur_result.name+" does not match the blacklist or the whitelist, rejecting it. Result: " + bwl.get_last_result_msg(), logger.INFO)
                continue

        logger.log("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality])

        if quality_list and cur_result.quality not in quality_list:
            logger.log(cur_result.name + " is a quality we know we don't want, rejecting it", logger.DEBUG)
            continue

        if show.rls_ignore_words and show_name_helpers.containsAtLeastOneWord(cur_result.name, cur_result.show.rls_ignore_words):
            logger.log(u"Ignoring " + cur_result.name + " based on ignored words filter: " + show.rls_ignore_words,
                       logger.INFO)
            continue

        if show.rls_require_words and not show_name_helpers.containsAtLeastOneWord(cur_result.name, cur_result.show.rls_require_words):
            logger.log(u"Ignoring " + cur_result.name + " based on required words filter: " + show.rls_require_words,
                       logger.INFO)
            continue

        if not show_name_helpers.filterBadReleases(cur_result.name, parse=False):
            logger.log(u"Ignoring " + cur_result.name + " because its not a valid scene release that we want, ignoring it",
                       logger.INFO)
            continue

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(cur_result.name, cur_result.size,
                                                                           cur_result.provider.name):
                logger.log(cur_result.name + u" has previously failed, rejecting it")
                continue

        if not bestResult or bestResult.quality < cur_result.quality and cur_result.quality != Quality.UNKNOWN:
            bestResult = cur_result

        elif bestResult.quality == cur_result.quality:
            if "proper" in cur_result.name.lower() or "repack" in cur_result.name.lower():
                bestResult = cur_result
            elif "internal" in bestResult.name.lower() and "internal" not in cur_result.name.lower():
                bestResult = cur_result
            elif "xvid" in bestResult.name.lower() and "x264" in cur_result.name.lower():
                logger.log(u"Preferring " + cur_result.name + " (x264 over xvid)")
                bestResult = cur_result

    if bestResult:
        logger.log(u"Picked " + bestResult.name + " as the best", logger.DEBUG)
    else:
        logger.log(u"No result picked.", logger.DEBUG)

    return bestResult
Esempio n. 28
0
def pickBestResult(results, show):  # pylint: disable=too-many-branches
    """
    Find the best result out of a list of search results for a show

    :param results: list of result objects
    :param show: Shows we check for
    :return: best result object
    """
    results = results if isinstance(results, list) else [results]

    logger.log(
        "Picking the best result out of " + str([x.name for x in results]),
        logger.DEBUG)

    preferredWords = [i.strip() for i in sickbeard.PREFERRED_WORDS.split(',')]

    # find the best result for the current episode
    for cur_result in results:
        if show and cur_result.show is not show:
            continue

        cur_result.searcher_score = 0
        nameLower = cur_result.name.lower()

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

        logger.log("Quality of " + cur_result.name + " is " +
                   Quality.qualityStrings[cur_result.quality])

        anyQualities, bestQualities = Quality.splitQuality(show.quality)

        if cur_result.quality not in anyQualities + bestQualities:
            logger.log(
                cur_result.name +
                " is a quality we know we don't want, rejecting it",
                logger.DEBUG)
            continue

        if not show_name_helpers.filter_bad_releases(
                cur_result.name, parse=False, show=show):
            continue

        cur_result.searcher_score += (cur_result.quality * 100)

        if hasattr(cur_result, 'size'):
            if sickbeard.USE_FAILED_DOWNLOADS and failed_history.hasFailed(
                    cur_result.name, cur_result.size,
                    cur_result.provider.name):
                logger.log(cur_result.name +
                           " has previously failed, rejecting it")
                cur_result.searcher_score = -1
                continue

        for i in preferredWords:
            if i.lower() in nameLower:
                logger.log('Found preferred word {} in {}'.format(
                    i, cur_result.name))
                cur_result.searcher_score += 1

    results.sort(key=lambda x: x.searcher_score, reverse=True)

    if len(results) == 0 or results[0].searcher_score == -1:
        logger.log("No result picked.", logger.DEBUG)
        return None
    else:
        acceptableResults = list(
            i for i in results
            if i.searcher_score == results[0].searcher_score)

    if len(acceptableResults) == 1:
        logger.log("Picked " + acceptableResults[0].name + " as the best",
                   logger.DEBUG)
        return acceptableResults[0]
    else:
        logger.log('Found {} acceptable results.'.format(
            len(acceptableResults)))
        bestResult = None
        for result in acceptableResults:
            nameLower = result.name.lower()
            if any(i in nameLower for i in ('proper', 'real', 'repack')):
                logger.log("Preferring " + result.name +
                           " (repack/proper/real over nuked)")
                bestResult = result
                break
            elif 'internal' in nameLower:
                logger.log('Lowering preferece for {} (internal)'.format(
                    result.name))
                result.searcher_score -= 10
            elif "xvid" in nameLower:
                logger.log('Lowering preferece for {} (xvid)'.format(
                    result.name))
                result.searcher_score -= 1

        if not bestResult:
            bestResult = sorted(acceptableResults,
                                key=lambda x: x.searcher_score,
                                reverse=True)[0]

        logger.log("Picked " + bestResult.name + " as the best", logger.DEBUG)
        return bestResult