def search_cache(self, show_id, season, episode, manualSearch=False, downCurQuality=False): cache_results = {} dbData = [] # get data from external database if sickrage.app.config.enable_api_providers_cache and not self.provider.private: try: dbData += sickrage.app.api.provider_cache.get(self.providerID, show_id, season, episode)['data'] except Exception: pass # get data from internal database session = sickrage.app.cache_db.session() dbData += [x.as_dict() for x in session.query(CacheDB.Provider).filter_by(provider=self.providerID, series_id=show_id, season=season).filter( CacheDB.Provider.episodes.contains("|{}|".format(episode)))] for curResult in dbData: show_object = find_show(int(curResult["series_id"])) if not show_object: continue result = self.provider.get_result() # ignore invalid and private IP address urls if not validate_url(curResult["url"]): if not curResult["url"].startswith('magnet'): continue elif is_ip_private(curResult["url"].split(r'//')[-1].split(r'/')[0]): continue # ignored/required words, and non-tv junk if not show_names.filter_bad_releases(curResult["name"]): continue # get the show object, or if it's not one of our shows then ignore it result.show_id = int(curResult["series_id"]) # skip if provider is anime only and show is not anime if self.provider.anime_only and not show_object.is_anime: sickrage.app.log.debug("" + str(show_object.name) + " is not an anime, skiping") continue # get season and ep data (ignoring multi-eps for now) curSeason = int(curResult["season"]) if curSeason == -1: continue result.season = curSeason result.episodes = [int(curEp) for curEp in filter(None, curResult["episodes"].split("|"))] result.quality = int(curResult["quality"]) result.release_group = curResult["release_group"] result.version = curResult["version"] # make sure we want the episode wantEp = False for result_episode in result.episodes: if show_object.want_episode(result.season, result_episode, result.quality, manualSearch, downCurQuality): wantEp = True if not wantEp: sickrage.app.log.info("Skipping " + curResult["name"] + " because we don't want an episode that's " + Quality.qualityStrings[result.quality]) continue # build a result object result.name = curResult["name"] result.url = curResult["url"] sickrage.app.log.info("Found cached {} result {}".format(result.type, result.name)) result.seeders = curResult.get("seeders", -1) result.leechers = curResult.get("leechers", -1) result.size = curResult.get("size", -1) result.content = None # add it to the list if episode not in cache_results: cache_results[int(episode)] = [result] else: cache_results[int(episode)] += [result] # datetime stamp this search so cache gets cleared self.last_search = datetime.datetime.today() return cache_results
def pick_best_result(results, season_pack=False): """ Find the best result out of a list of search results for a show :param results: list of result objects :param show_id: Show ID we check for :return: best result object """ results = results if isinstance(results, list) else [results] sickrage.app.log.debug("Picking the best result out of " + str([x.name for x in results])) best_result = None # find the best result for the current episode for cur_result in results: show_obj = find_show(cur_result.show_id) # build the black And white list if show_obj.is_anime: if not show_obj.release_groups.is_valid(cur_result): continue sickrage.app.log.info("Quality of " + cur_result.name + " is " + Quality.qualityStrings[cur_result.quality]) any_qualities, best_qualities = Quality.split_quality(show_obj.quality) if cur_result.quality not in any_qualities + best_qualities: sickrage.app.log.debug( cur_result.name + " is a quality we know we don't want, rejecting it") continue # check if seeders meet out minimum requirements, disgard result if it does not if hasattr(cur_result.provider, 'minseed') and cur_result.seeders not in (-1, None): if int(cur_result.seeders) < min(cur_result.provider.minseed, 1): sickrage.app.log.info( "Discarding torrent because it doesn't meet the minimum seeders: {}. Seeders: " "{}".format(cur_result.name, cur_result.seeders)) continue # check if leechers meet out minimum requirements, disgard result if it does not if hasattr(cur_result.provider, 'minleech') and cur_result.leechers not in (-1, None): if int(cur_result.leechers) < min(cur_result.provider.minleech, 0): sickrage.app.log.info( "Discarding torrent because it doesn't meet the minimum leechers: {}. Leechers: " "{}".format(cur_result.name, cur_result.leechers)) continue if show_obj.rls_ignore_words and show_names.contains_at_least_one_word( cur_result.name, show_obj.rls_ignore_words): sickrage.app.log.info("Ignoring " + cur_result.name + " based on ignored words filter: " + show_obj.rls_ignore_words) continue if show_obj.rls_require_words and not show_names.contains_at_least_one_word( cur_result.name, show_obj.rls_require_words): sickrage.app.log.info("Ignoring " + cur_result.name + " based on required words filter: " + show_obj.rls_require_words) continue if not show_names.filter_bad_releases(cur_result.name, parse=False): sickrage.app.log.info( "Ignoring " + cur_result.name + " because its not a valid scene release that we want") continue if hasattr(cur_result, 'size'): if FailedHistory.has_failed(cur_result.name, cur_result.size, cur_result.provider.name): sickrage.app.log.info(cur_result.name + " has previously failed, rejecting it") continue # quality definition video file size constraints check try: if cur_result.size: quality_size = sickrage.app.config.quality_sizes[ cur_result.quality] if season_pack and not len(cur_result.episodes): episode_count = len([ x for x in show_obj.episodes if x.season == cur_result.season ]) file_size = float(cur_result.size / episode_count / 1000000) else: file_size = float(cur_result.size / len(cur_result.episodes) / 1000000) if file_size > quality_size: raise Exception( "Ignoring " + cur_result.name + " with size: {} based on quality size filter: {}". format(file_size, quality_size)) except Exception as e: sickrage.app.log.info(e) continue # verify result content # if not cur_result.provider.private: # if cur_result.type in ["nzb", "torrent"] and not cur_result.provider.get_content(cur_result.url): # if not sickrage.app.config.download_unverified_magnet_link and cur_result.url.startswith('magnet'): # sickrage.app.log.info("Ignoring {} because we are unable to verify the download url".format(cur_result.name)) # continue if not best_result: best_result = cur_result elif cur_result.quality in best_qualities and ( best_result.quality < cur_result.quality or best_result.quality not in best_qualities): best_result = cur_result elif cur_result.quality in any_qualities and best_result.quality not in best_qualities and best_result.quality < cur_result.quality: best_result = cur_result elif best_result.quality == cur_result.quality: if "proper" in cur_result.name.lower( ) or "repack" in cur_result.name.lower(): best_result = cur_result elif "internal" in best_result.name.lower( ) and "internal" not in cur_result.name.lower(): best_result = cur_result elif "xvid" in best_result.name.lower( ) and "x264" in cur_result.name.lower(): sickrage.app.log.info("Preferring " + cur_result.name + " (x264 over xvid)") best_result = cur_result if best_result: sickrage.app.log.debug("Picked " + best_result.name + " as the best") else: sickrage.app.log.debug("No result picked.") return best_result
def _test_filterBadReleases(self, name, expected): result = show_names.filter_bad_releases(name) self.assertEqual(result, expected)
def search_cache(self, series_id, series_provider_id, season, episode, manualSearch=False, downCurQuality=False): cache_results = {} dbData = [] # get data from external database if sickrage.app.config.general.enable_sickrage_api and not self.provider.private: resp = sickrage.app.api.provider.get_search_result( self.providerID, series_id, season, episode) if resp and 'data' in resp: dbData += resp['data'] # get data from internal database session = sickrage.app.cache_db.session() dbData += [ x.as_dict() for x in session.query(CacheDB.Provider).filter_by( provider=self.providerID, series_id=series_id, season=season). filter(CacheDB.Provider.episodes.contains("|{}|".format(episode))) ] for curResult in dbData: result = self.provider.get_result() result.series_id = int(curResult["series_id"]) result.series_provider_id = curResult["series_provider_id"] # convert to series provider id enum if not isinstance(result.series_provider_id, SeriesProviderID): result.series_provider_id = SeriesProviderID[ curResult["series_provider_id"]] # get series, if it's not one of our shows then ignore it series = find_show(result.series_id, result.series_provider_id) if not series or series.series_provider_id != series_provider_id: continue # ignored/required words, and non-tv junk if not show_names.filter_bad_releases(curResult["name"]): continue # skip if provider is anime only and show is not anime if self.provider.anime_only and not series.is_anime: sickrage.app.log.debug("" + str(series.name) + " is not an anime, skiping") continue # get season and ep data (ignoring multi-eps for now) curSeason = int(curResult["season"]) if curSeason == -1: continue result.season = curSeason result.episodes = [ int(curEp) for curEp in filter(None, curResult["episodes"].split("|")) ] result.quality = Qualities(curResult["quality"]) result.release_group = curResult["release_group"] result.version = curResult["version"] # make sure we want the episode wantEp = False for result_episode in result.episodes: if series.want_episode(result.season, result_episode, result.quality, manualSearch, downCurQuality): wantEp = True if not wantEp: sickrage.app.log.info( "Skipping " + curResult["name"] + " because we don't want an episode that's " + result.quality.display_name) continue # build a result object result.name = curResult["name"] result.url = curResult["url"] sickrage.app.log.info("Found cached {} result {}".format( result.provider_type, result.name)) result.seeders = curResult.get("seeders", -1) result.leechers = curResult.get("leechers", -1) result.size = curResult.get("size", -1) result.content = None # add it to the list if episode not in cache_results: cache_results[int(episode)] = [result] else: cache_results[int(episode)] += [result] # datetime stamp this search so cache gets cleared self.last_search = datetime.datetime.today() return cache_results