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
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
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
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
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
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
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
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
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:
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
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
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
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(
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
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]):
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
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
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:
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
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
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
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
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
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
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
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