def wantedEpisodes(show, fromDate): """ Get a list of episodes that we want to download :param show: Show these episodes are from :param fromDate: Search from a certain date :return: list of wanted episodes """ wanted = [] anyQualities, bestQualities = Quality.splitQuality(show.quality) # @UnusedVariable allQualities = list(set(anyQualities + bestQualities)) sickrage.srCore.srLogger.debug("Seeing if we need anything from {}".format(show.name)) # check through the list of statuses to see if we want any for dbData in [x['doc'] for x in sickrage.srCore.mainDB.db.get_many('tv_episodes', show.indexerid, with_doc=True) if x['doc']['season'] > 0 and x['doc']['airdate'] > fromDate.toordinal()]: curCompositeStatus = int(dbData["status"] or -1) curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus) if bestQualities: highestBestQuality = max(allQualities) else: highestBestQuality = 0 # if we need a better one then say yes if (curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED: epObj = show.getEpisode(int(dbData["season"]), int(dbData["episode"])) epObj.wantedQuality = [i for i in allQualities if (i > curQuality and i != Quality.UNKNOWN)] wanted.append(epObj) return wanted
def refine_video(video, episode): # try to enrich video object using information in original filename if episode.release_name: guess_ep = subliminal.Episode.fromguess(None, guessit(episode.release_name)) for name in vars(guess_ep): if getattr(guess_ep, name) and not getattr(video, name): setattr(video, name, getattr(guess_ep, name)) # Use sickrage metadata metadata_mapping = { 'episode': 'episode', 'release_group': 'release_group', 'season': 'season', 'series': 'show.name', 'series_imdb_id': 'show.imdbid', 'size': 'file_size', 'title': 'name', 'year': 'show.startyear' } def get_attr_value(obj, name): value = None for attr in name.split('.'): if not value: value = getattr(obj, attr, None) else: value = getattr(value, attr, None) return value for name in metadata_mapping: if not getattr(video, name) and get_attr_value(episode, metadata_mapping[name]): setattr(video, name, get_attr_value(episode, metadata_mapping[name])) elif episode.show.subtitles_sr_metadata and get_attr_value(episode, metadata_mapping[name]): setattr(video, name, get_attr_value(episode, metadata_mapping[name])) # Set quality from metadata _, quality = Quality.splitCompositeStatus(episode.status) if not video.format or episode.show.subtitles_sr_metadata: if quality & Quality.ANYHDTV: video.format = Quality.combinedQualityStrings.get(Quality.ANYHDTV) elif quality & Quality.ANYWEBDL: video.format = Quality.combinedQualityStrings.get(Quality.ANYWEBDL) elif quality & Quality.ANYBLURAY: video.format = Quality.combinedQualityStrings.get(Quality.ANYBLURAY) if not video.resolution or episode.show.subtitles_sr_metadata: if quality & (Quality.HDTV | Quality.HDWEBDL | Quality.HDBLURAY): video.resolution = '720p' elif quality & Quality.RAWHDTV: video.resolution = '1080i' elif quality & (Quality.FULLHDTV | Quality.FULLHDWEBDL | Quality.FULLHDBLURAY): video.resolution = '1080p' elif quality & (Quality.UHD_4K_TV | Quality.UHD_4K_WEBDL | Quality.UHD_4K_BLURAY): video.resolution = '4K' elif quality & (Quality.UHD_8K_TV | Quality.UHD_8K_WEBDL | Quality.UHD_8K_BLURAY): video.resolution = '8K'
def _get_segments(show, fromDate): """ Get a list of episodes that we want to download :param show: Show these episodes are from :param fromDate: Search from a certain date :return: list of wanted episodes """ wanted = [] anyQualities, bestQualities = Quality.splitQuality(show.quality) allQualities = list(set(anyQualities + bestQualities)) sickrage.app.log.debug("Seeing if we need anything from {}".format( show.name)) # check through the list of statuses to see if we want any for dbData in sickrage.app.main_db.get_many('tv_episodes', show.indexerid): if dbData['season'] > 0 and dbData[ 'airdate'] >= fromDate.toordinal(): curStatus, curQuality = Quality.splitCompositeStatus( int(dbData["status"] or -1)) # if we need a better one then say yes if curStatus not in (WANTED, DOWNLOADED, SNATCHED, SNATCHED_PROPER): continue if curStatus != WANTED: if bestQualities: if curQuality in bestQualities: continue elif curQuality != Quality.UNKNOWN and curQuality > max( bestQualities): continue else: if curQuality in anyQualities: continue elif curQuality != Quality.UNKNOWN and curQuality > max( anyQualities): continue # skip upgrading quality of downloaded episodes if enabled if curStatus == DOWNLOADED and show.skip_downloaded: continue epObj = show.getEpisode(int(dbData["season"]), int(dbData["episode"])) epObj.wantedQuality = [ i for i in allQualities if (i > curQuality and i != Quality.UNKNOWN) ] wanted.append(epObj) return wanted
def process(self): """ Do the actual work :return: True """ self._log("Failed download detected: (" + str(self.nzb_name) + ", " + str(self.dir_name) + ")") release_name = show_names.determineReleaseName(self.dir_name, self.nzb_name) if release_name is None: self._log("Warning: unable to find a valid release name.", sickrage.app.log.WARNING) raise FailedPostProcessingFailedException() try: parsed = NameParser(False).parse(release_name) except InvalidNameException: self._log("Error: release name is invalid: " + release_name, sickrage.app.log.DEBUG) raise FailedPostProcessingFailedException() except InvalidShowException: self._log( "Error: unable to parse release name " + release_name + " into a valid show", sickrage.app.log.DEBUG) raise FailedPostProcessingFailedException() if parsed.show.paused: self._log( "Warning: skipping failed processing for {} because the show is paused" .format(release_name), sickrage.app.log.DEBUG) raise FailedPostProcessingFailedException() sickrage.app.log.debug("name_parser info: ") sickrage.app.log.debug(" - " + str(parsed.series_name)) sickrage.app.log.debug(" - " + str(parsed.season_number)) sickrage.app.log.debug(" - " + str(parsed.episode_numbers)) sickrage.app.log.debug(" - " + str(parsed.extra_info)) sickrage.app.log.debug(" - " + str(parsed.release_group)) sickrage.app.log.debug(" - " + str(parsed.air_date)) for episode in parsed.episode_numbers: segment = parsed.show.getEpisode(parsed.season_number, episode) curStatus, curQuality = Quality.splitCompositeStatus( segment.status) if curStatus not in {SNATCHED, SNATCHED_BEST, SNATCHED_PROPER}: continue sickrage.app.search_queue.put( FailedQueueItem(parsed.show, [segment])) return True
def run(self, force=False): """ Runs the failed searcher, queuing selected episodes for search that have failed to snatch :param force: Force search """ if self.amActive or (not sickrage.app.config.use_failed_snatcher or sickrage.app.developer) and not force: return self.amActive = True # set thread name threading.currentThread().setName(self.name) # trim failed download history FailedHistory.trimHistory() sickrage.app.log.info("Searching for failed snatches") show = None failed_snatches = False snatched_episodes = (x for x in sickrage.app.main_db.all('history') if x['action'] in Quality.SNATCHED + Quality.SNATCHED_BEST + Quality.SNATCHED_PROPER and 24 >= int((datetime.datetime.now() - datetime.datetime.strptime(x['date'], History.date_format)).total_seconds() / 3600) >= sickrage.app.config.failed_snatch_age) downloaded_releases = ((x['showid'], x['season'], x['episode']) for x in sickrage.app.main_db.all('history') if x['action'] in Quality.DOWNLOADED) episodes = [x for x in snatched_episodes if (x['showid'], x['season'], x['episode']) not in downloaded_releases] for episode in episodes: failed_snatches = True if not show or int(episode["showid"]) != show.indexerid: show = findCertainShow(int(episode["showid"])) # for when there is orphaned series in the database but not loaded into our showlist if not show or show.paused: continue ep_obj = show.get_episode(int(episode['season']), int(episode['episode'])) if isinstance(ep_obj, TVEpisode): curStatus, curQuality = Quality.splitCompositeStatus(ep_obj.status) if curStatus not in {SNATCHED, SNATCHED_BEST, SNATCHED_PROPER}: continue # put it on the queue sickrage.app.search_queue.put(FailedQueueItem(show, [ep_obj], True)) if not failed_snatches: sickrage.app.log.info("No failed snatches found") self.amActive = False
def logFailed(epObj, release, provider=None): """ Log a failed download :param epObj: Episode object :param release: Release group :param provider: Provider used for snatch """ showid = int(epObj.show.indexerid) season = int(epObj.season) epNum = int(epObj.episode) status, quality = Quality.splitCompositeStatus(epObj.status) action = Quality.compositeStatus(FAILED, quality) History._logHistoryItem(action, showid, season, epNum, quality, release, provider)
def _get_segments(self, show, fromDate): if show.paused: sickrage.srCore.srLogger.debug( "Skipping backlog for {show_name} because the show is paused". format(show_name=show.name)) return {} anyQualities, bestQualities = Quality.splitQuality( show.quality) # @UnusedVariable sickrage.srCore.srLogger.debug( "Seeing if we need anything from {}".format(show.name)) # check through the list of statuses to see if we want any wanted = {} for result in [ x['doc'] for x in sickrage.srCore.mainDB.db.get_many( 'tv_episodes', show.indexerid, with_doc=True) if x['doc']['season'] > 0 and x['doc']['airdate'] > fromDate.toordinal() ]: curCompositeStatus = int(result["status"] or -1) curStatus, curQuality = Quality.splitCompositeStatus( curCompositeStatus) if bestQualities: highestBestQuality = max(bestQualities) lowestBestQuality = min(bestQualities) else: highestBestQuality = 0 lowestBestQuality = 0 # if we need a better one then say yes if (curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED: epObj = show.getEpisode(int(result["season"]), int(result["episode"])) # only fetch if not archive on first match, or if show is lowest than the lower expected quality if (epObj.show.archive_firstmatch == 0 or curQuality < lowestBestQuality): if epObj.season not in wanted: wanted[epObj.season] = [epObj] else: wanted[epObj.season].append(epObj) return wanted
def wantedEpisodes(show, fromDate): """ Get a list of episodes that we want to download :param show: Show these episodes are from :param fromDate: Search from a certain date :return: list of wanted episodes """ wanted = [] anyQualities, bestQualities = Quality.splitQuality( show.quality) # @UnusedVariable allQualities = list(set(anyQualities + bestQualities)) sickrage.srCore.srLogger.debug("Seeing if we need anything from {}".format( show.name)) sqlResults = main_db.MainDB().select( "SELECT status, season, episode FROM tv_episodes WHERE showid = ? AND season > 0 AND airdate > ?", [show.indexerid, fromDate.toordinal()]) sickrage.srCore.srLogger.debug("Found {} episode(s) needed for {}".format( len(sqlResults), show.name)) # check through the list of statuses to see if we want any for result in sqlResults: curCompositeStatus = int(result["status"] or -1) curStatus, curQuality = Quality.splitCompositeStatus( curCompositeStatus) if bestQualities: highestBestQuality = max(allQualities) else: highestBestQuality = 0 # if we need a better one then say yes if (curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED: epObj = show.getEpisode(int(result["season"]), int(result["episode"])) epObj.wantedQuality = [ i for i in allQualities if (i > curQuality and i != Quality.UNKNOWN) ] wanted.append(epObj) return wanted
def logSubtitle(showid, season, episode, status, subtitleResult): """ Log download of subtitle :param showid: Showid of download :param season: Show season :param episode: Show episode :param status: Status of download :param subtitleResult: Result object """ resource = subtitleResult.language.opensubtitles provider = subtitleResult.provider_name status, quality = Quality.splitCompositeStatus(status) action = Quality.compositeStatus(SUBTITLED, quality) History._logHistoryItem(action, showid, season, episode, quality, resource, provider)
def _get_segments(self, show, from_date): anyQualities, bestQualities = Quality.splitQuality(show.quality) sickrage.app.log.debug("Seeing if we need anything from {}".format( show.name)) # check through the list of statuses to see if we want any wanted = [] for result in (x for x in sickrage.app.main_db.get_many( 'tv_episodes', show.indexerid) if x['season'] > 0 and datetime.date.today().toordinal( ) > x['airdate'] >= from_date.toordinal()): curStatus, curQuality = Quality.splitCompositeStatus( int(result["status"] or -1)) # if we need a better one then say yes if curStatus not in { WANTED, DOWNLOADED, SNATCHED, SNATCHED_PROPER }: continue if curStatus != WANTED: if bestQualities: if curQuality in bestQualities: continue elif curQuality != Quality.UNKNOWN and curQuality > max( bestQualities): continue else: if curQuality in anyQualities: continue elif curQuality != Quality.UNKNOWN and curQuality > max( anyQualities): continue # skip upgrading quality of downloaded episodes if enabled if curStatus == DOWNLOADED and show.skip_downloaded: continue epObj = show.getEpisode(int(result["season"]), int(result["episode"])) wanted.append(epObj) return wanted
def _get_segments(show, fromDate): """ Get a list of episodes that we want to download :param show: Show these episodes are from :param fromDate: Search from a certain date :return: list of wanted episodes """ wanted = [] anyQualities, bestQualities = Quality.splitQuality(show.quality) allQualities = list(set(anyQualities + bestQualities)) sickrage.app.log.debug("Seeing if we need anything from {}".format(show.name)) # check through the list of statuses to see if we want any for dbData in sickrage.app.main_db.get_many('tv_episodes', show.indexerid): if dbData['season'] > 0 and dbData['airdate'] >= fromDate.toordinal(): curStatus, curQuality = Quality.splitCompositeStatus(int(dbData["status"] or -1)) # if we need a better one then say yes if curStatus not in (WANTED, DOWNLOADED, SNATCHED, SNATCHED_PROPER): continue if curStatus != WANTED: if bestQualities: if curQuality in bestQualities: continue elif curQuality != Quality.UNKNOWN and curQuality > max(bestQualities): continue else: if curQuality in anyQualities: continue elif curQuality != Quality.UNKNOWN and curQuality > max(anyQualities): continue # skip upgrading quality of downloaded episodes if enabled if curStatus == DOWNLOADED and show.skip_downloaded: continue epObj = show.get_episode(int(dbData["season"]), int(dbData["episode"])) epObj.wantedQuality = [i for i in allQualities if (i > curQuality and i != Quality.UNKNOWN)] wanted.append(epObj) return wanted
def markFailed(epObj): """ Mark an episode as failed :param epObj: Episode object to mark as failed :return: empty string """ log_str = "" try: with epObj.lock: quality = Quality.splitCompositeStatus(epObj.status)[1] epObj.status = Quality.compositeStatus(FAILED, quality) epObj.saveToDB() except EpisodeNotFoundException as e: sickrage.srCore.srLogger.warning("Unable to get episode, please set its status manually: {}".format(e.message)) return log_str
def _get_segments(self, show, fromDate): if show.paused: sickrage.srCore.srLogger.debug("Skipping backlog for {show_name} because the show is paused".format(show_name=show.name)) return {} anyQualities, bestQualities = Quality.splitQuality(show.quality) # @UnusedVariable sickrage.srCore.srLogger.debug("Seeing if we need anything from {}".format(show.name)) sqlResults = main_db.MainDB().select( "SELECT status, season, episode FROM tv_episodes WHERE season > 0 AND airdate > ? AND showid = ?", [fromDate.toordinal(), show.indexerid]) # check through the list of statuses to see if we want any wanted = {} for result in sqlResults: curCompositeStatus = int(result["status"] or -1) curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus) if bestQualities: highestBestQuality = max(bestQualities) lowestBestQuality = min(bestQualities) else: highestBestQuality = 0 lowestBestQuality = 0 # if we need a better one then say yes if (curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED: epObj = show.getEpisode(int(result["season"]), int(result["episode"])) # only fetch if not archive on first match, or if show is lowest than the lower expected quality if (epObj.show.archive_firstmatch == 0 or curQuality < lowestBestQuality): if epObj.season not in wanted: wanted[epObj.season] = [epObj] else: wanted[epObj.season].append(epObj) return wanted
def _get_segments(self, show, fromDate): if show.paused: sickrage.LOGGER.debug("Skipping backlog for {show_name} because the show is paused".format(show_name=show.name)) return {} anyQualities, bestQualities = Quality.splitQuality(show.quality) # @UnusedVariable sickrage.LOGGER.debug("Seeing if we need anything from {show_name}".format(show_name=show.name)) sqlResults = main_db.MainDB().select( "SELECT status, season, episode FROM tv_episodes WHERE season > 0 AND airdate > ? AND showid = ?", [fromDate.toordinal(), show.indexerid]) # check through the list of statuses to see if we want any wanted = {} for result in sqlResults: curCompositeStatus = int(result[b"status"] or -1) curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus) if bestQualities: highestBestQuality = max(bestQualities) lowestBestQuality = min(bestQualities) else: highestBestQuality = 0 lowestBestQuality = 0 # if we need a better one then say yes if (curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED: epObj = show.getEpisode(int(result[b"season"]), int(result[b"episode"])) # only fetch if not archive on first match, or if show is lowest than the lower expected quality if (epObj.show.archive_firstmatch == 0 or curQuality < lowestBestQuality): if epObj.season not in wanted: wanted[epObj.season] = [epObj] else: wanted[epObj.season].append(epObj) return wanted
def wantedEpisodes(show, fromDate): """ Get a list of episodes that we want to download :param show: Show these episodes are from :param fromDate: Search from a certain date :return: list of wanted episodes """ anyQualities, bestQualities = Quality.splitQuality(show.quality) # @UnusedVariable allQualities = list(set(anyQualities + bestQualities)) sickrage.LOGGER.debug("Seeing if we need anything from " + show.name) sqlResults = main_db.MainDB().select( "SELECT status, season, episode FROM tv_episodes WHERE showid = ? AND season > 0 AND airdate > ?", [show.indexerid, fromDate.toordinal()], ) # check through the list of statuses to see if we want any wanted = [] for result in sqlResults: curCompositeStatus = int(result[b"status"] or -1) curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus) if bestQualities: highestBestQuality = max(allQualities) else: highestBestQuality = 0 # if we need a better one then say yes if ( curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER) and curQuality < highestBestQuality ) or curStatus == WANTED: epObj = show.getEpisode(int(result[b"season"]), int(result[b"episode"])) epObj.wantedQuality = [i for i in allQualities if (i > curQuality and i != Quality.UNKNOWN)] wanted.append(epObj) return wanted
def wantedEpisodes(show, fromDate): """ Get a list of episodes that we want to download :param show: Show these episodes are from :param fromDate: Search from a certain date :return: list of wanted episodes """ wanted = [] if show.paused: sickrage.app.log.debug("Not checking for episodes of {} because the show is paused".format(show.name)) return wanted anyQualities, bestQualities = Quality.splitQuality(show.quality) allQualities = list(set(anyQualities + bestQualities)) sickrage.app.log.debug("Seeing if we need anything from {}".format(show.name)) # check through the list of statuses to see if we want any for dbData in [x['doc'] for x in sickrage.app.main_db.db.get_many('tv_episodes', show.indexerid, with_doc=True) if x['doc']['season'] > 0 and x['doc']['airdate'] > fromDate.toordinal()]: curCompositeStatus = int(dbData["status"] or -1) curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus) if bestQualities: highestBestQuality = max(allQualities) else: highestBestQuality = 0 # if we need a better one then say yes if (curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED: epObj = show.getEpisode(int(dbData["season"]), int(dbData["episode"])) epObj.wantedQuality = [i for i in allQualities if (i > curQuality and i != Quality.UNKNOWN)] wanted.append(epObj) return wanted
def _get_segments(self, show, fromDate): if show.paused: sickrage.app.log.debug( "Skipping backlog for {show_name} because the show is paused".format(show_name=show.name)) return {} anyQualities, bestQualities = Quality.splitQuality(show.quality) sickrage.app.log.debug("Seeing if we need anything from {}".format(show.name)) # check through the list of statuses to see if we want any wanted = {} for result in [x['doc'] for x in sickrage.app.main_db.db.get_many('tv_episodes', show.indexerid, with_doc=True) if x['doc']['season'] > 0 and x['doc']['airdate'] > fromDate.toordinal()]: curCompositeStatus = int(result["status"] or -1) curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus) if bestQualities: highestBestQuality = max(bestQualities) lowestBestQuality = min(bestQualities) else: highestBestQuality = 0 lowestBestQuality = 0 # if we need a better one then say yes if (curStatus in (DOWNLOADED, SNATCHED, SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == WANTED: epObj = show.getEpisode(int(result["season"]), int(result["episode"])) # only fetch if not archive on first match, or if show is lowest than the lower expected quality if epObj.show.archive_firstmatch == 0 or curQuality < lowestBestQuality: if epObj.season not in wanted: wanted[epObj.season] = [epObj] else: wanted[epObj.season].append(epObj) return wanted
def _get_segments(show, from_date): anyQualities, bestQualities = Quality.splitQuality(show.quality) sickrage.app.log.debug("Seeing if we need anything from {}".format(show.name)) # check through the list of statuses to see if we want any wanted = [] for result in (x for x in sickrage.app.main_db.get_many('tv_episodes', show.indexerid) if x['season'] > 0 and datetime.date.today().toordinal() > x['airdate'] >= from_date.toordinal()): curStatus, curQuality = Quality.splitCompositeStatus(int(result["status"] or -1)) # if we need a better one then say yes if curStatus not in {WANTED, DOWNLOADED, SNATCHED, SNATCHED_PROPER}: continue if curStatus != WANTED: if bestQualities: if curQuality in bestQualities: continue elif curQuality != Quality.UNKNOWN and curQuality > max(bestQualities): continue else: if curQuality in anyQualities: continue elif curQuality != Quality.UNKNOWN and curQuality > max(anyQualities): continue # skip upgrading quality of downloaded episodes if enabled if curStatus == DOWNLOADED and show.skip_downloaded: continue epObj = show.get_episode(int(result["season"]), int(result["episode"])) wanted.append(epObj) return wanted
def _getProperList(self): """ Walk providers for propers """ propers = {} search_date = datetime.datetime.today() - datetime.timedelta(days=2) origThreadName = threading.currentThread().getName() # for each provider get a list of the for providerID, providerObj in sickrage.srCore.providersDict.sort( randomize=sickrage.srCore.srConfig.RANDOMIZE_PROVIDERS).items(): # check provider type and provider is enabled if not sickrage.srCore.srConfig.USE_NZBS and providerObj.type in [NZBProvider.type, NewznabProvider.type]: continue elif not sickrage.srCore.srConfig.USE_TORRENTS and providerObj.type in [TorrentProvider.type, TorrentRssProvider.type]: continue elif not providerObj.isEnabled: continue threading.currentThread().setName(origThreadName + " :: [" + providerObj.name + "]") sickrage.srCore.srLogger.info("Searching for any new PROPER releases from " + providerObj.name) try: curPropers = providerObj.findPropers(search_date) except AuthException as e: sickrage.srCore.srLogger.debug("Authentication error: {}".format(e.message)) continue except Exception as e: sickrage.srCore.srLogger.debug( "Error while searching " + providerObj.name + ", skipping: {}".format(e.message)) sickrage.srCore.srLogger.debug(traceback.format_exc()) continue # if they haven't been added by a different provider than add the proper to the list for x in curPropers: if not re.search(r'(^|[\. _-])(proper|repack)([\. _-]|$)', x.name, re.I): sickrage.srCore.srLogger.debug('findPropers returned a non-proper, we have caught and skipped it.') continue name = self._genericName(x.name) if not name in propers: sickrage.srCore.srLogger.debug("Found new proper: " + x.name) x.provider = providerObj propers[name] = x threading.currentThread().setName(origThreadName) # take the list of unique propers and get it sorted by sortedPropers = sorted(propers.values(), key=operator.attrgetter('date'), reverse=True) finalPropers = [] for curProper in sortedPropers: try: myParser = NameParser(False) parse_result = myParser.parse(curProper.name) except InvalidNameException: sickrage.srCore.srLogger.debug( "Unable to parse the filename " + curProper.name + " into a valid episode") continue except InvalidShowException: sickrage.srCore.srLogger.debug("Unable to parse the filename " + curProper.name + " into a valid show") continue if not parse_result.series_name: continue if not parse_result.episode_numbers: sickrage.srCore.srLogger.debug( "Ignoring " + curProper.name + " because it's for a full season rather than specific episode") continue sickrage.srCore.srLogger.debug( "Successful match! Result " + parse_result.original_name + " matched to show " + parse_result.show.name) # set the indexerid in the db to the show's indexerid curProper.indexerid = parse_result.show.indexerid # set the indexer in the db to the show's indexer curProper.indexer = parse_result.show.indexer # populate our Proper instance curProper.show = parse_result.show curProper.season = parse_result.season_number if parse_result.season_number is not None else 1 curProper.episode = parse_result.episode_numbers[0] curProper.release_group = parse_result.release_group curProper.version = parse_result.version curProper.quality = Quality.nameQuality(curProper.name, parse_result.is_anime) curProper.content = None # filter release bestResult = pickBestResult(curProper, parse_result.show) if not bestResult: sickrage.srCore.srLogger.debug("Proper " + curProper.name + " were rejected by our release filters.") continue # only get anime proper if it has release group and version if bestResult.show.is_anime: if not bestResult.release_group and bestResult.version == -1: sickrage.srCore.srLogger.debug( "Proper " + bestResult.name + " doesn't have a release group and version, ignoring it") continue # check if we actually want this proper (if it's the right quality) sqlResults = main_db.MainDB().select( "SELECT status FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?", [bestResult.indexerid, bestResult.season, bestResult.episode]) if not sqlResults: continue # only keep the proper if we have already retrieved the same quality ep (don't get better/worse ones) oldStatus, oldQuality = Quality.splitCompositeStatus(int(sqlResults[0]["status"])) if oldStatus not in (DOWNLOADED, SNATCHED) or oldQuality != bestResult.quality: continue # check if we actually want this proper (if it's the right release group and a higher version) if bestResult.show.is_anime: sqlResults = main_db.MainDB().select( "SELECT release_group, version FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?", [bestResult.indexerid, bestResult.season, bestResult.episode]) oldVersion = int(sqlResults[0]["version"]) oldRelease_group = (sqlResults[0]["release_group"]) if oldVersion > -1 and oldVersion < bestResult.version: sickrage.srCore.srLogger.info( "Found new anime v" + str(bestResult.version) + " to replace existing v" + str(oldVersion)) else: continue if oldRelease_group != bestResult.release_group: sickrage.srCore.srLogger.info( "Skipping proper from release group: " + bestResult.release_group + ", does not match existing release group: " + oldRelease_group) continue # if the show is in our list and there hasn't been a proper already added for that particular episode then add it to our list of propers if bestResult.indexerid != -1 and (bestResult.indexerid, bestResult.season, bestResult.episode) not in map( operator.attrgetter('indexerid', 'season', 'episode'), finalPropers): sickrage.srCore.srLogger.info("Found a proper that we need: " + str(bestResult.name)) finalPropers.append(bestResult) return finalPropers
def _replace_map(episode): """ Generates a replacement map for this episode which maps all possible custom naming patterns to the correct value for this episode. Returns: A dict with patterns as the keys and their replacement values as the values. """ ep_name = _ep_name(episode) def dot(name): return sanitizeSceneName(name) def us(name): return re.sub('[ -]', '_', name) def release_name(name): if name: name = remove_non_release_groups(remove_extension(name)) return name def release_group(show, name): if name: name = remove_non_release_groups(remove_extension(name)) else: return "" try: np = NameParser(name, showObj=show, naming_pattern=True) parse_result = np.parse(name) except (InvalidNameException, InvalidShowException) as e: sickrage.LOGGER.debug( "Unable to get parse release_group: {}".format(e)) return '' if not parse_result.release_group: return '' return parse_result.release_group _, epQual = Quality.splitCompositeStatus(episode.status) # @UnusedVariable if sickrage.NAMING_STRIP_YEAR: show_name = re.sub(r"\(\d+\)$", "", episode.show.name).rstrip() else: show_name = episode.show.name # try to get the release group rel_grp = {} rel_grp[b"SiCKRAGE"] = 'SiCKRAGE' if hasattr(episode, 'location'): # from the location name rel_grp[b'location'] = release_group(episode.show, episode.location) if not rel_grp[b'location']: del rel_grp[b'location'] if hasattr(episode, '_release_group'): # from the release group field in db rel_grp[b'database'] = episode._release_group if not rel_grp[b'database']: del rel_grp[b'database'] if hasattr(episode, 'release_name'): # from the release name field in db rel_grp[b'release_name'] = release_group(episode.show, episode.release_name) if not rel_grp[b'release_name']: del rel_grp[b'release_name'] # use release_group, release_name, location in that order if 'database' in rel_grp: relgrp = 'database' elif 'release_name' in rel_grp: relgrp = 'release_name' elif 'location' in rel_grp: relgrp = 'location' else: relgrp = 'SiCKRAGE' # try to get the release encoder to comply with scene naming standards encoder = Quality.sceneQualityFromName( episode.release_name.replace(rel_grp[relgrp], ""), epQual) if encoder: sickrage.LOGGER.debug("Found codec for '" + show_name + ": " + ep_name + "'.") return { '%SN': show_name, '%S.N': dot(show_name), '%S_N': us(show_name), '%EN': ep_name, '%E.N': dot(ep_name), '%E_N': us(ep_name), '%QN': Quality.qualityStrings[epQual], '%Q.N': dot(Quality.qualityStrings[epQual]), '%Q_N': us(Quality.qualityStrings[epQual]), '%SQN': Quality.sceneQualityStrings[epQual] + encoder, '%SQ.N': dot(Quality.sceneQualityStrings[epQual] + encoder), '%SQ_N': us(Quality.sceneQualityStrings[epQual] + encoder), '%S': str(episode.season), '%0S': '%02d' % episode.season, '%E': str(episode.episode), '%0E': '%02d' % episode.episode, '%XS': str(episode.scene_season), '%0XS': '%02d' % episode.scene_season, '%XE': str(episode.scene_episode), '%0XE': '%02d' % episode.scene_episode, '%AB': '%(#)03d' % { '#': episode.absolute_number }, '%XAB': '%(#)03d' % { '#': episode.scene_absolute_number }, '%RN': release_name(episode.release_name), '%RG': rel_grp[relgrp], '%CRG': rel_grp[relgrp].upper(), '%AD': str(episode.airdate).replace('-', ' '), '%A.D': str(episode.airdate).replace('-', '.'), '%A_D': us(str(episode.airdate)), '%A-D': str(episode.airdate), '%Y': str(episode.airdate.year), '%M': str(episode.airdate.month), '%D': str(episode.airdate.day), '%0M': '%02d' % episode.airdate.month, '%0D': '%02d' % episode.airdate.day, '%RT': "PROPER" if episode.is_proper else "", }
def makeSceneSeasonSearchString(show, ep_obj, extraSearchType=None): numseasons = 0 if show.air_by_date or show.sports: # the search string for air by date shows is just seasonStrings = [str(ep_obj.airdate).split('-')[0]] elif show.is_anime: seasonEps = show.getAllEpisodes(ep_obj.season) # get show qualities anyQualities, bestQualities = Quality.splitQuality(show.quality) # compile a list of all the episode numbers we need in this 'season' seasonStrings = [] for episode in seasonEps: # get quality of the episode curCompositeStatus = episode.status curStatus, curQuality = Quality.splitCompositeStatus( curCompositeStatus) if bestQualities: highestBestQuality = max(bestQualities) else: highestBestQuality = 0 # if we need a better one then add it to the list of episodes to fetch if (curStatus in (DOWNLOADED, SNATCHED) and curQuality < highestBestQuality) or curStatus == WANTED: ab_number = episode.scene_absolute_number if ab_number > 0: seasonStrings.append("%02d" % ab_number) else: numseasonsSQlResult = main_db.MainDB().select( "SELECT COUNT(DISTINCT season) as numseasons FROM tv_episodes WHERE showid = ? and season != 0", [show.indexerid]) if numseasonsSQlResult: numseasons = int(numseasonsSQlResult[0][0]) seasonStrings = ["S%02d" % int(ep_obj.scene_season)] showNames = set(makeSceneShowSearchStrings(show, ep_obj.scene_season)) toReturn = [] # search each show name for curShow in showNames: # most providers all work the same way if not extraSearchType: # if there's only one season then we can just use the show name straight up if numseasons == 1: toReturn.append(curShow) # for providers that don't allow multiple searches in one request we only search for Sxx style stuff else: for cur_season in seasonStrings: if ep_obj.show.is_anime: if ep_obj.show.release_groups is not None: if len(show.release_groups.whitelist) > 0: for keyword in show.release_groups.whitelist: toReturn.append(keyword + '.' + curShow + "." + cur_season) else: toReturn.append(curShow + "." + cur_season) return toReturn
def _replace_map(episode): """ Generates a replacement map for this episode which maps all possible custom naming patterns to the correct value for this episode. Returns: A dict with patterns as the keys and their replacement values as the values. """ ep_name = _ep_name(episode) def dot(name): return sanitizeSceneName(name) def us(name): return re.sub('[ -]', '_', name) def release_name(name): if name: name = remove_non_release_groups(remove_extension(name)) return name def release_group(show, name): if name: name = remove_non_release_groups(remove_extension(name)) else: return "" try: np = NameParser(name, showObj=show, naming_pattern=True) parse_result = np.parse(name) except (InvalidNameException, InvalidShowException) as e: sickrage.LOGGER.debug("Unable to get parse release_group: {}".format(e)) return '' if not parse_result.release_group: return '' return parse_result.release_group _, epQual = Quality.splitCompositeStatus(episode.status) # @UnusedVariable if sickrage.NAMING_STRIP_YEAR: show_name = re.sub(r"\(\d+\)$", "", episode.show.name).rstrip() else: show_name = episode.show.name # try to get the release group rel_grp = {} rel_grp[b"SiCKRAGE"] = 'SiCKRAGE' if hasattr(episode, 'location'): # from the location name rel_grp[b'location'] = release_group(episode.show, episode.location) if not rel_grp[b'location']: del rel_grp[b'location'] if hasattr(episode, '_release_group'): # from the release group field in db rel_grp[b'database'] = episode._release_group if not rel_grp[b'database']: del rel_grp[b'database'] if hasattr(episode, 'release_name'): # from the release name field in db rel_grp[b'release_name'] = release_group(episode.show, episode.release_name) if not rel_grp[b'release_name']: del rel_grp[b'release_name'] # use release_group, release_name, location in that order if 'database' in rel_grp: relgrp = 'database' elif 'release_name' in rel_grp: relgrp = 'release_name' elif 'location' in rel_grp: relgrp = 'location' else: relgrp = 'SiCKRAGE' # try to get the release encoder to comply with scene naming standards encoder = Quality.sceneQualityFromName(episode.release_name.replace(rel_grp[relgrp], ""), epQual) if encoder: sickrage.LOGGER.debug("Found codec for '" + show_name + ": " + ep_name + "'.") return { '%SN': show_name, '%S.N': dot(show_name), '%S_N': us(show_name), '%EN': ep_name, '%E.N': dot(ep_name), '%E_N': us(ep_name), '%QN': Quality.qualityStrings[epQual], '%Q.N': dot(Quality.qualityStrings[epQual]), '%Q_N': us(Quality.qualityStrings[epQual]), '%SQN': Quality.sceneQualityStrings[epQual] + encoder, '%SQ.N': dot(Quality.sceneQualityStrings[epQual] + encoder), '%SQ_N': us(Quality.sceneQualityStrings[epQual] + encoder), '%S': str(episode.season), '%0S': '%02d' % episode.season, '%E': str(episode.episode), '%0E': '%02d' % episode.episode, '%XS': str(episode.scene_season), '%0XS': '%02d' % episode.scene_season, '%XE': str(episode.scene_episode), '%0XE': '%02d' % episode.scene_episode, '%AB': '%(#)03d' % {'#': episode.absolute_number}, '%XAB': '%(#)03d' % {'#': episode.scene_absolute_number}, '%RN': release_name(episode.release_name), '%RG': rel_grp[relgrp], '%CRG': rel_grp[relgrp].upper(), '%AD': str(episode.airdate).replace('-', ' '), '%A.D': str(episode.airdate).replace('-', '.'), '%A_D': us(str(episode.airdate)), '%A-D': str(episode.airdate), '%Y': str(episode.airdate.year), '%M': str(episode.airdate.month), '%D': str(episode.airdate.day), '%0M': '%02d' % episode.airdate.month, '%0D': '%02d' % episode.airdate.day, '%RT': "PROPER" if episode.is_proper else "", }
def _getProperList(self): """ Walk providers for propers """ propers = {} search_date = datetime.datetime.today() - datetime.timedelta(days=2) origThreadName = threading.currentThread().getName() # for each provider get a list of the for providerID, providerObj in sickrage.srCore.providersDict.sort( randomize=sickrage.srCore.srConfig.RANDOMIZE_PROVIDERS).items( ): # check provider type and provider is enabled if not sickrage.srCore.srConfig.USE_NZBS and providerObj.type in [ NZBProvider.type, NewznabProvider.type ]: continue elif not sickrage.srCore.srConfig.USE_TORRENTS and providerObj.type in [ TorrentProvider.type, TorrentRssProvider.type ]: continue elif not providerObj.isEnabled: continue threading.currentThread().setName(origThreadName + " :: [" + providerObj.name + "]") sickrage.srCore.srLogger.info( "Searching for any new PROPER releases from " + providerObj.name) try: curPropers = providerObj.find_propers(search_date) except AuthException as e: sickrage.srCore.srLogger.warning( "Authentication error: {}".format(e.message)) continue except Exception as e: sickrage.srCore.srLogger.debug( "Error while searching " + providerObj.name + ", skipping: {}".format(e.message)) sickrage.srCore.srLogger.debug(traceback.format_exc()) continue # if they haven't been added by a different provider than add the proper to the list for x in curPropers: if not re.search(r'(^|[\. _-])(proper|repack)([\. _-]|$)', x.name, re.I): sickrage.srCore.srLogger.debug( 'findPropers returned a non-proper, we have caught and skipped it.' ) continue name = self._genericName(x.name) if not name in propers: sickrage.srCore.srLogger.debug("Found new proper: " + x.name) x.provider = providerObj propers[name] = x threading.currentThread().setName(origThreadName) # take the list of unique propers and get it sorted by sortedPropers = sorted(propers.values(), key=operator.attrgetter('date'), reverse=True) finalPropers = [] for curProper in sortedPropers: try: myParser = NameParser(False) parse_result = myParser.parse(curProper.name) except InvalidNameException: sickrage.srCore.srLogger.debug( "Unable to parse the filename " + curProper.name + " into a valid episode") continue except InvalidShowException: sickrage.srCore.srLogger.debug( "Unable to parse the filename " + curProper.name + " into a valid show") continue if not parse_result.series_name: continue if not parse_result.episode_numbers: sickrage.srCore.srLogger.debug( "Ignoring " + curProper.name + " because it's for a full season rather than specific episode" ) continue sickrage.srCore.srLogger.debug("Successful match! Result " + parse_result.original_name + " matched to show " + parse_result.show.name) # set the indexerid in the db to the show's indexerid curProper.indexerid = parse_result.show.indexerid # set the indexer in the db to the show's indexer curProper.indexer = parse_result.show.indexer # populate our Proper instance curProper.show = parse_result.show curProper.season = parse_result.season_number if parse_result.season_number is not None else 1 curProper.episode = parse_result.episode_numbers[0] curProper.release_group = parse_result.release_group curProper.version = parse_result.version curProper.quality = Quality.nameQuality(curProper.name, parse_result.is_anime) curProper.content = None # filter release bestResult = pickBestResult(curProper, parse_result.show) if not bestResult: sickrage.srCore.srLogger.debug( "Proper " + curProper.name + " were rejected by our release filters.") continue # only get anime proper if it has release group and version if bestResult.show.is_anime: if not bestResult.release_group and bestResult.version == -1: sickrage.srCore.srLogger.debug( "Proper " + bestResult.name + " doesn't have a release group and version, ignoring it" ) continue # check if we actually want this proper (if it's the right quality) dbData = [ x['doc'] for x in sickrage.srCore.mainDB().db.get_many( 'tv_episodes', bestResult.indexerid, with_doc=True) if x['doc']['season'] == bestResult.season and x['doc']['episode'] == bestResult.episode ] if not dbData: continue # only keep the proper if we have already retrieved the same quality ep (don't get better/worse ones) oldStatus, oldQuality = Quality.splitCompositeStatus( int(dbData[0]["status"])) if oldStatus not in (DOWNLOADED, SNATCHED) or oldQuality != bestResult.quality: continue # check if we actually want this proper (if it's the right release group and a higher version) if bestResult.show.is_anime: dbData = [ x['doc'] for x in sickrage.srCore.mainDB.db.get_many( 'tv_episodes', bestResult.indexerid, with_doc=True) if x['doc']['season'] == bestResult.season and x['doc']['episode'] == bestResult.episode ] oldVersion = int(dbData[0]["version"]) oldRelease_group = (dbData[0]["release_group"]) if -1 < oldVersion < bestResult.version: sickrage.srCore.srLogger.info("Found new anime v" + str(bestResult.version) + " to replace existing v" + str(oldVersion)) else: continue if oldRelease_group != bestResult.release_group: sickrage.srCore.srLogger.info( "Skipping proper from release group: " + bestResult.release_group + ", does not match existing release group: " + oldRelease_group) continue # if the show is in our list and there hasn't been a proper already added for that particular episode then add it to our list of propers if bestResult.indexerid != -1 and ( bestResult.indexerid, bestResult.season, bestResult.episode) not in map( operator.attrgetter('indexerid', 'season', 'episode'), finalPropers): sickrage.srCore.srLogger.info("Found a proper that we need: " + str(bestResult.name)) finalPropers.append(bestResult) return finalPropers
def makeSceneSeasonSearchString(show, ep_obj, extraSearchType=None): numseasons = 0 if show.air_by_date or show.sports: # the search string for air by date shows is just seasonStrings = [str(ep_obj.airdate).split('-')[0]] elif show.is_anime: seasonEps = show.get_all_episodes(ep_obj.season) # get show qualities anyQualities, bestQualities = Quality.splitQuality(show.quality) # compile a list of all the episode numbers we need in this 'season' seasonStrings = [] for episode in seasonEps: # get quality of the episode curCompositeStatus = episode.status curStatus, curQuality = Quality.splitCompositeStatus(curCompositeStatus) if bestQualities: highestBestQuality = max(bestQualities) else: highestBestQuality = 0 # if we need a better one then add it to the list of episodes to fetch if (curStatus in ( DOWNLOADED, SNATCHED) and curQuality < highestBestQuality) or curStatus == WANTED: ab_number = episode.scene_absolute_number if ab_number > 0: seasonStrings.append("%02d" % ab_number) else: numseasons = len({x['season'] for x in sickrage.app.main_db.get_many('tv_episodes', show.indexerid) if x['season'] != 0}) seasonStrings = ["S%02d" % int(ep_obj.scene_season)] showNames = set(makeSceneShowSearchStrings(show, ep_obj.scene_season)) toReturn = [] # search each show name for curShow in showNames: # most providers all work the same way if not extraSearchType: # if there's only one season then we can just use the show name straight up if numseasons == 1: toReturn.append(curShow) # for providers that don't allow multiple searches in one request we only search for Sxx style stuff else: for cur_season in seasonStrings: if ep_obj.show.is_anime: if ep_obj.show.release_groups is not None: if len(show.release_groups.whitelist) > 0: for keyword in show.release_groups.whitelist: toReturn.append(keyword + '.' + curShow + "." + cur_season) else: toReturn.append(curShow + "." + cur_season) return toReturn
def _getProperList(self): """ Walk providers for propers """ propers = {} search_date = datetime.datetime.today() - datetime.timedelta(days=2) origThreadName = threading.currentThread().getName() recently_aired = [] for show in sickrage.app.showlist: self._lastProperSearch = self._get_lastProperSearch(show.indexerid) for episode in sickrage.app.main_db.get_many('tv_episodes', show.indexerid): if episode['airdate'] >= str(search_date.toordinal()): if episode['status'] in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_BEST: recently_aired += [episode] self._set_lastProperSearch(show.indexerid, datetime.datetime.today().toordinal()) if not recently_aired: sickrage.app.log.info('No recently aired episodes, nothing to search for') return [] # for each provider get a list of the for providerID, providerObj in sickrage.app.search_providers.sort( randomize=sickrage.app.config.randomize_providers).items(): # check provider type and provider is enabled if not sickrage.app.config.use_nzbs and providerObj.type in [NZBProvider.type, NewznabProvider.type]: continue elif not sickrage.app.config.use_torrents and providerObj.type in [TorrentProvider.type, TorrentRssProvider.type]: continue elif not providerObj.isEnabled: continue threading.currentThread().setName(origThreadName + " :: [" + providerObj.name + "]") sickrage.app.log.info("Searching for any new PROPER releases from " + providerObj.name) try: curPropers = providerObj.find_propers(recently_aired) except AuthException as e: sickrage.app.log.warning("Authentication error: {}".format(e)) continue except Exception as e: sickrage.app.log.debug( "Error while searching " + providerObj.name + ", skipping: {}".format(e)) sickrage.app.log.debug(traceback.format_exc()) continue # if they haven't been added by a different provider than add the proper to the list for x in curPropers: if not re.search(r'(^|[. _-])(proper|repack)([. _-]|$)', x.name, re.I): sickrage.app.log.debug('findPropers returned a non-proper, we have caught and skipped it.') continue name = self._genericName(x.name) if name not in propers: sickrage.app.log.debug("Found new proper: " + x.name) x.provider = providerObj propers[name] = x threading.currentThread().setName(origThreadName) # take the list of unique propers and get it sorted by sortedPropers = sorted(propers.values(), key=operator.attrgetter('date'), reverse=True) finalPropers = [] for curProper in sortedPropers: try: myParser = NameParser(False) parse_result = myParser.parse(curProper.name) except InvalidNameException: sickrage.app.log.debug( "Unable to parse the filename " + curProper.name + " into a valid episode") continue except InvalidShowException: sickrage.app.log.debug("Unable to parse the filename " + curProper.name + " into a valid show") continue if not parse_result.series_name: continue if not parse_result.episode_numbers: sickrage.app.log.debug( "Ignoring " + curProper.name + " because it's for a full season rather than specific episode") continue sickrage.app.log.debug( "Successful match! Result " + parse_result.original_name + " matched to show " + parse_result.show.name) # set the indexerid in the db to the show's indexerid curProper.indexerid = parse_result.indexerid # set the indexer in the db to the show's indexer curProper.indexer = parse_result.show.indexer # populate our Proper instance curProper.show = parse_result.show curProper.season = parse_result.season_number if parse_result.season_number is not None else 1 curProper.episode = parse_result.episode_numbers[0] curProper.release_group = parse_result.release_group curProper.version = parse_result.version curProper.quality = Quality.nameQuality(curProper.name, parse_result.is_anime) curProper.content = None # filter release bestResult = pickBestResult(curProper, parse_result.show) if not bestResult: sickrage.app.log.debug("Proper " + curProper.name + " were rejected by our release filters.") continue # only get anime proper if it has release group and version if bestResult.show.is_anime: if not bestResult.release_group and bestResult.version == -1: sickrage.app.log.debug( "Proper " + bestResult.name + " doesn't have a release group and version, ignoring it") continue # check if we actually want this proper (if it's the right quality) dbData = [x for x in sickrage.app.main_db().get_many('tv_episodes', bestResult.indexerid) if x['season'] == bestResult.season and x['episode'] == bestResult.episode] if not dbData: continue # only keep the proper if we have already retrieved the same quality ep (don't get better/worse ones) oldStatus, oldQuality = Quality.splitCompositeStatus(int(dbData[0]["status"])) if oldStatus not in (DOWNLOADED, SNATCHED) or oldQuality != bestResult.quality: continue # check if we actually want this proper (if it's the right release group and a higher version) if bestResult.show.is_anime: dbData = [x for x in sickrage.app.main_db.get_many('tv_episodes', bestResult.indexerid) if x['season'] == bestResult.season and x['episode'] == bestResult.episode] oldVersion = int(dbData[0]["version"]) oldRelease_group = (dbData[0]["release_group"]) if -1 < oldVersion < bestResult.version: sickrage.app.log.info( "Found new anime v" + str(bestResult.version) + " to replace existing v" + str(oldVersion)) else: continue if oldRelease_group != bestResult.release_group: sickrage.app.log.info( "Skipping proper from release group: " + bestResult.release_group + ", does not match existing release group: " + oldRelease_group) continue # if the show is in our list and there hasn't been a proper already added for that particular episode then add it to our list of propers if bestResult.indexerid != -1 and (bestResult.indexerid, bestResult.season, bestResult.episode) not in map( operator.attrgetter('indexerid', 'season', 'episode'), finalPropers): sickrage.app.log.info("Found a proper that we need: " + str(bestResult.name)) finalPropers.append(bestResult) return finalPropers