def test_RAWHDTV(self): from sickrage.core.common import Quality self.assertEqual(Quality.RAWHDTV, Quality.nameQuality("Test.Show.S01E02.720p.HDTV.DD5.1.MPEG2-GROUP")) self.assertEqual(Quality.RAWHDTV, Quality.nameQuality("Test.Show.S01E02.1080i.HDTV.DD2.0.MPEG2-GROUP")) self.assertEqual(Quality.RAWHDTV, Quality.nameQuality("Test.Show.S01E02.1080i.HDTV.H.264.DD2.0-GROUP")) self.assertEqual(Quality.RAWHDTV, Quality.nameQuality("Test Show - S01E02 - 1080i HDTV MPA1.0 H.264 - GROUP")) self.assertEqual(Quality.RAWHDTV, Quality.nameQuality("Test.Show.S01E02.1080i.HDTV.DD.5.1.h264-GROUP"))
def test_HDWEBDL(self): from sickrage.core.common import Quality self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEB-DL-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEBRip-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.WEBRip.720p.H.264.AAC.2.0-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEB-DL.AAC2.0.H.264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test Show S01E02 720p WEB-DL AAC2 0 H 264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test_Show.S01E02_720p_WEB-DL_AAC2.0_H264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEB-DL.AAC2.0.H264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.iTunes.Rip.H264.AAC-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.AMZN.WEBRip.DDP5.1.x264-GROUP"))
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 generate_sample_ep(multi=None, abd=False, sports=False, anime_type=None): # make a fake episode object ep = Validator.FakeTVEpisode(2, 3, 3, "Ep Name") ep.status = Quality.compositeStatus(DOWNLOADED, Quality.HDTV) ep.airdate = datetime.date(2011, 3, 9) if abd: ep.release_name = 'Show.Name.2011.03.09.HDTV.XviD-RLSGROUP' ep.show.air_by_date = 1 elif sports: ep.release_name = 'Show.Name.2011.03.09.HDTV.XviD-RLSGROUP' ep.show.sports = 1 else: if anime_type != 3: ep.show.anime = 1 ep.release_name = 'Show.Name.003.HDTV.XviD-RLSGROUP' else: ep.release_name = 'Show.Name.S02E03.HDTV.XviD-RLSGROUP' if multi is not None: ep.name = "Ep Name (1)" if anime_type != 3: ep.show.anime = 1 ep.release_name = 'Show.Name.003-004.HDTV.XviD-RLSGROUP' secondEp = Validator.FakeTVEpisode(2, 4, 4, "Ep Name (2)") secondEp.status = Quality.compositeStatus(DOWNLOADED, Quality.HDTV) secondEp.release_name = ep.release_name ep.relatedEps.append(secondEp) else: ep.release_name = 'Show.Name.S02E03E04E05.HDTV.XviD-RLSGROUP' secondEp = Validator.FakeTVEpisode(2, 4, 4, "Ep Name (2)") secondEp.status = Quality.compositeStatus(DOWNLOADED, Quality.HDTV) secondEp.release_name = ep.release_name thirdEp = Validator.FakeTVEpisode(2, 5, 5, "Ep Name (3)") thirdEp.status = Quality.compositeStatus(DOWNLOADED, Quality.HDTV) thirdEp.release_name = ep.release_name ep.relatedEps.append(secondEp) ep.relatedEps.append(thirdEp) return ep
def isFinalResult(result): """ Checks if the given result is good enough quality that we can stop searching for other ones. If the result is the highest quality in both the any/best quality lists then this function returns True, if not then it's False """ sickrage.srCore.srLogger.debug("Checking if we should keep searching after we've found " + result.name) show_obj = result.episodes[0].show any_qualities, best_qualities = Quality.splitQuality(show_obj.quality) # if there is a redownload that's higher than this then we definitely need to keep looking if best_qualities and result.quality < max(best_qualities): return False # if it does not match the shows black and white list its no good elif show_obj.is_anime and show_obj.release_groups.is_valid(result): return False # if there's no redownload that's higher (above) and this is the highest initial download then we're good elif any_qualities and result.quality in any_qualities: return True elif best_qualities and result.quality == max(best_qualities): return True # if we got here than it's either not on the lists, they're empty, or it's lower than the highest required else: return False
def logSnatch(searchResult): """ Log history of snatch :param searchResult: search result object """ for curEpObj in searchResult.episodes: showid = int(curEpObj.show.indexerid) season = int(curEpObj.season) episode = int(curEpObj.episode) quality = searchResult.quality version = searchResult.version providerClass = searchResult.provider if providerClass is not None: provider = providerClass.name else: provider = "unknown" action = Quality.compositeStatus(SNATCHED, searchResult.quality) resource = searchResult.name History._logHistoryItem(action, showid, season, episode, quality, resource, provider, version)
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 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 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 sickrage.app.main_db.get_many('tv_episodes', show.indexerid): if dbData['season'] > 0 and dbData['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(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 _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 test_FULLHDWEBDL(self): from sickrage.core.common import Qualities from sickrage.core.common import Quality self.assertEqual( Qualities.FULLHDWEBDL, Quality.name_quality("Test.Show.S01E02.1080p.WEB-DL-GROUP")) self.assertEqual( Qualities.FULLHDWEBDL, Quality.name_quality("Test.Show.S01E02.1080p.WEBRip-GROUP")) self.assertEqual( Qualities.FULLHDWEBDL, Quality.name_quality( "Test.Show.S01E02.WEBRip.1080p.H.264.AAC.2.0-GROUP")) self.assertEqual( Qualities.FULLHDWEBDL, Quality.name_quality( "Test.Show.S01E02.WEBRip.1080p.H264.AAC.2.0-GROUP")) self.assertEqual( Qualities.FULLHDWEBDL, Quality.name_quality( "Test.Show.S01E02.1080p.iTunes.H.264.AAC-GROUP")) self.assertEqual( Qualities.FULLHDWEBDL, Quality.name_quality( "Test Show S01E02 1080p iTunes H 264 AAC-GROUP")) self.assertEqual( Qualities.FULLHDWEBDL, Quality.name_quality( "Test_Show_S01E02_1080p_iTunes_H_264_AAC-GROUP"))
def _get_wanted(show, from_date): any_qualities, best_qualities = Quality.split_quality(show.quality) sickrage.app.log.debug( "Seeing if we need anything that's older then today for {}".format( show.name)) # check through the list of statuses to see if we want any wanted = [] for episode_object in show.episodes: if not episode_object.season > 0 or not datetime.date.today( ) > episode_object.airdate > from_date: continue cur_status, cur_quality = Quality.split_composite_status( episode_object.status) # if we need a better one then say yes if cur_status not in { EpisodeStatus.WANTED, EpisodeStatus.DOWNLOADED, EpisodeStatus.SNATCHED, EpisodeStatus.SNATCHED_PROPER }: continue if cur_status != EpisodeStatus.WANTED: if best_qualities: if cur_quality in best_qualities: continue elif cur_quality != Qualities.UNKNOWN and cur_quality > max( best_qualities): continue elif any_qualities: if cur_quality in any_qualities: continue elif cur_quality != Qualities.UNKNOWN and cur_quality > max( any_qualities): continue # skip upgrading quality of downloaded episodes if enabled if cur_status == EpisodeStatus.DOWNLOADED and show.skip_downloaded: continue wanted += [(episode_object.season, episode_object.episode)] return wanted
def test_FULLHDWEBDL(self): self.assertEqual( Quality.FULLHDWEBDL, Quality.nameQuality("Test.Show.S01E02.1080p.WEB-DL-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.nameQuality("Test.Show.S01E02.1080p.WEBRip-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.nameQuality( "Test.Show.S01E02.WEBRip.1080p.H.264.AAC.2.0-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.nameQuality( "Test.Show.S01E02.WEBRip.1080p.H264.AAC.2.0-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.nameQuality( "Test.Show.S01E02.1080p.iTunes.H.264.AAC-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.nameQuality( "Test Show S01E02 1080p iTunes H 264 AAC-GROUP")) self.assertEqual( Quality.FULLHDWEBDL, Quality.nameQuality( "Test_Show_S01E02_1080p_iTunes_H_264_AAC-GROUP"))
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 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 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 _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 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 mark_failed(show_id, season, episode, session=None): """ Mark an episode as failed :param epObj: Episode object to mark as failed :return: empty string """ log_str = "" show_object = find_show(show_id, session=session) episode_object = show_object.get_episode(season, episode) try: quality = Quality.split_composite_status(episode_object.status)[1] episode_object.status = Quality.composite_status(FAILED, quality) except EpisodeNotFoundException as e: sickrage.app.log.warning("Unable to get episode, please set its status manually: {}".format(e)) return log_str
def log_failed(show_id, season, episode, release, provider=None): """ Log a failed download :param epObj: Episode object :param release: Release group :param provider: Provider used for snatch """ show_object = find_show(show_id) if not show_object: return episode_object = show_object.get_episode(season, episode) status, quality = Quality.split_composite_status(episode_object.status) action = Quality.composite_status(FAILED, quality) History._log_history_item(action, show_id, season, episode, quality, release, provider)
def log_subtitle(series_id, series_provider_id, season, episode, status, subtitle): """ Log download of subtitle :param series_id: Showid of download :param season: Show season :param episode: Show episode :param status: Status of download :param subtitle: Result object """ resource = subtitle.language.opensubtitles provider = subtitle.provider_name status, quality = Quality.split_composite_status(status) action = Quality.composite_status(EpisodeStatus.SUBTITLED, quality) History._log_history_item(action, series_id, series_provider_id, season, episode, quality, resource, provider)
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 test_FULLHDWEBDL(self): from sickrage.core.common import Quality self.assertEqual(Quality.FULLHDWEBDL, Quality.nameQuality("Test.Show.S01E02.1080p.WEB-DL-GROUP")) self.assertEqual(Quality.FULLHDWEBDL, Quality.nameQuality("Test.Show.S01E02.1080p.WEBRip-GROUP")) self.assertEqual(Quality.FULLHDWEBDL, Quality.nameQuality("Test.Show.S01E02.WEBRip.1080p.H.264.AAC.2.0-GROUP")) self.assertEqual(Quality.FULLHDWEBDL, Quality.nameQuality("Test.Show.S01E02.WEBRip.1080p.H264.AAC.2.0-GROUP")) self.assertEqual(Quality.FULLHDWEBDL, Quality.nameQuality("Test.Show.S01E02.1080p.iTunes.H.264.AAC-GROUP")) self.assertEqual(Quality.FULLHDWEBDL, Quality.nameQuality("Test Show S01E02 1080p iTunes H 264 AAC-GROUP")) self.assertEqual(Quality.FULLHDWEBDL, Quality.nameQuality("Test_Show_S01E02_1080p_iTunes_H_264_AAC-GROUP"))
def getQuality(self, item, anime=False): """ Figures out the quality of the given RSS item node item: An elementtree.ElementTree element representing the <item> tag of the RSS feed Returns a Quality value obtained from the node's data """ (title, url) = self._get_title_and_url(item) quality = Quality.sceneQuality(title, anime) return quality
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 task(self, force=False): """ Runs the failed searcher, queuing selected episodes for search that have failed to snatch :param force: Force search """ if self.running or not sickrage.app.config.failed_snatches.enable and not force: return try: self.running = True # set thread name threading.currentThread().setName(self.name) # trim failed download history FailedHistory.trim_history() sickrage.app.log.info("Searching for failed snatches") failed_snatches = False for snatched_episode_obj in [ x for x in self.snatched_episodes() if (x.series_id, x.season, x.episode) not in self.downloaded_releases() ]: show_object = find_show( snatched_episode_obj.series_id, snatched_episode_obj.series_provider_id) episode_object = show_object.get_episode( snatched_episode_obj.season, snatched_episode_obj.episode) if episode_object.show.paused: continue cur_status, cur_quality = Quality.split_composite_status( episode_object.status) if cur_status not in { EpisodeStatus.SNATCHED, EpisodeStatus.SNATCHED_BEST, EpisodeStatus.SNATCHED_PROPER }: continue sickrage.app.search_queue.put( FailedSearchTask(show_object.series_id, show_object.series_provider_id, episode_object.season, episode_object.episode, True)) failed_snatches = True if not failed_snatches: sickrage.app.log.info("No failed snatches found") finally: self.running = False
def getQuality(self, item, anime=False): """ Figures out the quality of the given RSS item node item: An elementtree.ElementTree element representing the <item> tag of the RSS feed Returns a Quality value obtained from the node's data """ (title, url) = self._get_title_and_url(item) quality = Quality.sceneQuality(title, anime) return quality
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 test_RAWHDTV(self): self.assertEqual( Quality.RAWHDTV, Quality.nameQuality( "Test.Show.S01E02.720p.HDTV.DD5.1.MPEG2-GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.nameQuality( "Test.Show.S01E02.1080i.HDTV.DD2.0.MPEG2-GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.nameQuality( "Test.Show.S01E02.1080i.HDTV.H.264.DD2.0-GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.nameQuality( "Test Show - S01E02 - 1080i HDTV MPA1.0 H.264 - GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.nameQuality( "Test.Show.S01E02.1080i.HDTV.DD.5.1.h264-GROUP"))
def test_RAWHDTV(self): from sickrage.core.common import Quality self.assertEqual( Quality.RAWHDTV, Quality.name_quality( "Test.Show.S01E02.720p.HDTV.DD5.1.MPEG2-GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.name_quality( "Test.Show.S01E02.1080i.HDTV.DD2.0.MPEG2-GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.name_quality( "Test.Show.S01E02.1080i.HDTV.H.264.DD2.0-GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.name_quality( "Test Show - S01E02 - 1080i HDTV MPA1.0 H.264 - GROUP")) self.assertEqual( Quality.RAWHDTV, Quality.name_quality( "Test.Show.S01E02.1080i.HDTV.DD.5.1.h264-GROUP"))
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 test_HDWEBDL(self): self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEB-DL-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEBRip-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.WEBRip.720p.H.264.AAC.2.0-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEB-DL.AAC2.0.H.264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test Show S01E02 720p WEB-DL AAC2 0 H 264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test_Show.S01E02_720p_WEB-DL_AAC2.0_H264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEB-DL.AAC2.0.H264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.iTunes.Rip.H264.AAC-GROUP"))
def test_HDWEBDL(self): self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEB-DL-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEBRip-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.WEBRip.720p.H.264.AAC.2.0-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEB-DL.AAC2.0.H.264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test Show S01E02 720p WEB-DL AAC2 0 H 264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test_Show.S01E02_720p_WEB-DL_AAC2.0_H264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.WEB-DL.AAC2.0.H264-GROUP")) self.assertEqual(Quality.HDWEBDL, Quality.nameQuality("Test.Show.S01E02.720p.iTunes.Rip.H264.AAC-GROUP"))
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 __init__(self, season, episode, absolute_number, name): self.relatedEps = [] self.name = name self.season = season self.episode = episode self.absolute_number = absolute_number self.scene_season = season self.scene_episode = episode self.scene_absolute_number = absolute_number self.airdate = datetime.date(2010, 3, 9) self.show = Validator.FakeTVShow() self.status = Quality.compositeStatus(DOWNLOADED, Quality.SDTV) self.release_name = 'Show.Name.S02E03.HDTV.XviD-RLSGROUP' self.is_proper = True
def __init__(self, season, episode, absolute_number, name): self.relatedEps = [] self.name = name self.season = season self.episode = episode self.absolute_number = absolute_number self.scene_season = season self.scene_episode = episode self.scene_absolute_number = absolute_number self.airdate = datetime.date(2010, 3, 9) self.show = Validator.FakeTVShow() self.status = Quality.compositeStatus(DOWNLOADED, Quality.SDTV) self.release_name = 'Show.Name.S02E03.HDTV.XviD-RLSGROUP' self.is_proper = True
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 run(self, force=False, session=None): """ 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 and not force: return self.amActive = True # set thread name threading.currentThread().setName(self.name) # trim failed download history FailedHistory.trim_history() sickrage.app.log.info("Searching for failed snatches") failed_snatches = False for snatched_episode_obj in [ x for x in self.snatched_episodes() if (x.showid, x.season, x.episode) not in self.downloaded_releases() ]: show_object = find_show(snatched_episode_obj.showid, session=session) episode_object = show_object.get_episode( snatched_episode_obj.season, snatched_episode_obj.episode) if episode_object.show.paused: continue cur_status, cur_quality = Quality.split_composite_status( episode_object.status) if cur_status not in {SNATCHED, SNATCHED_BEST, SNATCHED_PROPER}: continue sickrage.app.io_loop.add_callback( sickrage.app.search_queue.put, FailedQueueItem(episode_object.showid, episode_object.season, episode_object.episode, True)) failed_snatches = True if not failed_snatches: sickrage.app.log.info("No failed snatches found") self.amActive = False
def isFirstBestMatch(result): """ Checks if the given result is a best quality match and if we want to archive the episode on first match. """ sickrage.LOGGER.debug("Checking if we should archive our first best quality match for for episode " + result.name) show_obj = result.episodes[0].show any_qualities, best_qualities = Quality.splitQuality(show_obj.quality) # if there is a redownload that's a match to one of our best qualities and we want to archive the episode then we are done if best_qualities and show_obj.archive_firstmatch and result.quality in best_qualities: return True return False
def get(self, *args, **kwargs): default_status = self.get_argument('defaultStatus', '5') quality_preset = self.get_argument('qualityPreset', '') any_qualities = self.get_argument('anyQualities', '') best_qualities = self.get_argument('bestQualities', '') default_flatten_folders = self.get_argument('defaultFlattenFolders', None) subtitles = self.get_argument('subtitles', None) anime = self.get_argument('anime', None) search_format = self.get_argument('search_format', None) default_status_after = self.get_argument('defaultStatusAfter', None) or EpisodeStatus.WANTED scene = self.get_argument('scene', None) skip_downloaded = self.get_argument('skip_downloaded', None) add_show_year = self.get_argument('add_show_year', None) any_qualities = any_qualities.split(',') if len(any_qualities) else [] best_qualities = best_qualities.split(',') if len( best_qualities) else [] try: new_quality = Qualities[quality_preset] except KeyError: new_quality = Quality.combine_qualities( [Qualities[x] for x in any_qualities], [Qualities[x] for x in best_qualities]) sickrage.app.config.general.status_default = EpisodeStatus[ default_status] sickrage.app.config.general.status_default_after = EpisodeStatus[ default_status_after] sickrage.app.config.general.quality_default = new_quality sickrage.app.config.general.flatten_folders_default = not checkbox_to_value( default_flatten_folders) sickrage.app.config.subtitles.default = checkbox_to_value(subtitles) sickrage.app.config.general.anime_default = checkbox_to_value(anime) sickrage.app.config.general.search_format_default = SearchFormat[ search_format] sickrage.app.config.general.scene_default = checkbox_to_value(scene) sickrage.app.config.general.skip_downloaded_default = checkbox_to_value( skip_downloaded) sickrage.app.config.general.add_show_year_default = checkbox_to_value( add_show_year) sickrage.app.config.save()
def is_first_best_match(result): """ Checks if the given result is a best quality match and if we want to archive the episode on first match. """ sickrage.app.log.debug("Checking if we should archive our first best quality match for episode " + result.name) show_obj = find_show(result.series_id, result.series_provider_id) any_qualities, best_qualities = Quality.split_quality(show_obj.quality) # if there is a re-download that's a match to one of our best qualities and we want to skip downloaded then we # are done if best_qualities and show_obj.skip_downloaded and result.quality in best_qualities: return True return False
def isFirstBestMatch(result): """ Checks if the given result is a best quality match and if we want to archive the episode on first match. """ sickrage.srCore.srLogger.debug( "Checking if we should archive our first best quality match for episode " + result.name) show_obj = result.episodes[0].show any_qualities, best_qualities = Quality.splitQuality(show_obj.quality) # if there is a redownload that's a match to one of our best qualities and we want to archive the episode then we are done if best_qualities and show_obj.archive_firstmatch and result.quality in best_qualities: return True return False
def __init__(self, season, episode, absolute_number, name): self.name = name self.season = season self.episode = episode self.absolute_number = absolute_number self.airdate = datetime.date(2010, 3, 9) self.status = Quality.composite_status(DOWNLOADED, Quality.SDTV) self.release_name = 'Show.Name.S02E03.HDTV.XviD-RLSGROUP' self.release_group = 'RLSGROUP' self.is_proper = True self.show = FakeShow() self.scene_season = season self.scene_episode = episode self.scene_absolute_number = absolute_number self.related_episodes = [] self.session = sickrage.app.main_db.session()
def test_HDWEBDL(self): from sickrage.core.common import Qualities from sickrage.core.common import Quality self.assertEqual( Qualities.HDWEBDL, Quality.name_quality("Test.Show.S01E02.720p.WEB-DL-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality("Test.Show.S01E02.720p.WEBRip-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test.Show.S01E02.WEBRip.720p.H.264.AAC.2.0-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test.Show.S01E02.720p.WEB-DL.AAC2.0.H.264-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test Show S01E02 720p WEB-DL AAC2 0 H 264-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test_Show.S01E02_720p_WEB-DL_AAC2.0_H264-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test.Show.S01E02.720p.WEB-DL.AAC2.0.H264-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test.Show.S01E02.720p.iTunes.Rip.H264.AAC-GROUP")) self.assertEqual( Qualities.HDWEBDL, Quality.name_quality( "Test.Show.S01E02.720p.AMZN.WEBRip.DDP5.1.x264-GROUP"))
def test_UNKNOWN(self): self.assertEqual(Quality.UNKNOWN, Quality.nameQuality("Test.Show.S01E02-SiCKBEARD"))
def test_FULLHDBLURAY(self): self.assertEqual(Quality.FULLHDBLURAY, Quality.nameQuality("Test.Show.S01E02.1080p.BluRay.x264-GROUP")) self.assertEqual(Quality.FULLHDBLURAY, Quality.nameQuality("Test.Show.S01E02.1080p.HDDVD.x264-GROUP"))
def parse(self, data, mode): """ Parse search results for items. :param data: The raw response from a search :param mode: The current mode used to search, e.g. RSS :return: A list of items found """ results = [] hdtext = [' Versione 720p', ' V 720p', ' V 720', ' V HEVC', ' V HEVC', ' V 1080', ' Versione 1080p', ' 720p HEVC', ' Ver 720', ' 720p HEVC', ' 720p'] with bs4_parser(data) as html: torrent_table = html.find(class_='showrelease_tb') torrent_rows = torrent_table('tr') if torrent_table else [] # Continue only if at least one release is found if len(torrent_rows) < 3: sickrage.app.log.debug('Data returned from provider does not contain any torrents') return results # Skip column headers for row in torrent_table('tr')[1:]: cells = row('td') if not cells: continue try: title = unidecode(cells[6].text) title = title.replace('·', '').replace(',', '') title = title.replace('by', '-').strip() title = title.strip('-').strip() download_url = cells[1].find('a')['href'] if not all([title, download_url]): continue leechers = try_int(cells[3].text) seeders = try_int(cells[4].text, 1) filename_qt = self._reverse_quality(self._episode_quality(title)) for text in hdtext: title1 = title title = title.replace(text, filename_qt) if title != title1: break if Quality.nameQuality(title) == Quality.UNKNOWN: title += filename_qt if self._has_only_subs(title) and not self.subtitle: sickrage.app.log.debug('Torrent is only subtitled, skipping: {}'.format(title)) continue if self.engrelease and not self._is_english(title): sickrage.app.log.debug("Torrent isn't english audio/subtitled, skipping: {} ".format(title)) continue size = -1 item = { 'title': title, 'link': download_url, 'size': size, 'seeders': seeders, 'leechers': leechers, } if mode != 'RSS': sickrage.app.log.debug('Found result: {}'.format(title)) results.append(item) except Exception: sickrage.app.log.error('Failed parsing provider') return results
def test_SDDVD(self): self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.DVDRiP.XViD-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.DVDRiP.DiVX-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.DVDRiP.x264-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.DVDRip.WS.XViD-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.DVDRip.WS.DiVX-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.DVDRip.WS.x264-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.BDRIP.XViD-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.BDRIP.DiVX-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.BDRIP.x264-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.BDRIP.WS.XViD-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.BDRIP.WS.DiVX-GROUP")) self.assertEqual(Quality.SDDVD, Quality.nameQuality("Test.Show.S01E02.BDRIP.WS.x264-GROUP"))
def test_HDTV(self): self.assertEqual(Quality.HDTV, Quality.nameQuality("Test.Show.S01E02.720p.HDTV.x264-GROUP")) self.assertEqual(Quality.HDTV, Quality.nameQuality("Test.Show.S01E02.HR.WS.PDTV.x264-GROUP"))
def test_FULLHDTV(self): self.assertEqual(Quality.FULLHDTV, Quality.nameQuality("Test.Show.S01E02.1080p.HDTV.x264-GROUP"))
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 _parse_string(self, name): if not name: return matches = [] bestResult = None for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes: match = cur_regex.match(name) if not match: continue result = ParseResult(name) result.which_regex = [cur_regex_name] result.score = 0 - cur_regex_num named_groups = match.groupdict().keys() if 'series_name' in named_groups: result.series_name = match.group('series_name') if result.series_name: result.series_name = self.clean_series_name(result.series_name) result.score += 1 if 'series_num' in named_groups and match.group('series_num'): result.score += 1 if 'season_num' in named_groups: tmp_season = int(match.group('season_num')) if cur_regex_name == 'bare' and tmp_season in (19, 20): continue result.season_number = tmp_season result.score += 1 if 'ep_num' in named_groups: ep_num = self._convert_number(match.group('ep_num')) result.score += 1 if 'extra_ep_num' in named_groups and match.group('extra_ep_num'): result.episode_numbers = range(ep_num, self._convert_number(match.group('extra_ep_num')) + 1) result.score += 1 else: result.episode_numbers = [ep_num] if 'ep_ab_num' in named_groups: ep_ab_num = self._convert_number(match.group('ep_ab_num')) result.score += 1 if 'extra_ab_ep_num' in named_groups and match.group('extra_ab_ep_num'): result.ab_episode_numbers = range(ep_ab_num, self._convert_number(match.group('extra_ab_ep_num')) + 1) result.score += 1 else: result.ab_episode_numbers = [ep_ab_num] if 'air_date' in named_groups: air_date = match.group('air_date') try: result.air_date = parser.parse(air_date, fuzzy=True).date() result.score += 1 except Exception: continue if 'extra_info' in named_groups: tmp_extra_info = match.group('extra_info') # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season if tmp_extra_info and cur_regex_name == 'season_only' and re.search( r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I): continue result.extra_info = tmp_extra_info result.score += 1 if 'release_group' in named_groups: result.release_group = match.group('release_group') result.score += 1 if 'version' in named_groups: # assigns version to anime file if detected using anime regex. Non-anime regex receives -1 version = match.group('version') if version: result.version = version else: result.version = 1 else: result.version = -1 matches.append(result) if len(matches): # pick best match with highest score based on placement bestResult = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score) show = None if not self.naming_pattern: # try and create a show object for this result show = self.get_show(bestResult.series_name, self.tryIndexers) # confirm passed in show object indexer id matches result show object indexer id if show: if self.showObj and show.indexerid != self.showObj.indexerid: show = None bestResult.show = show elif not show and self.showObj: bestResult.show = self.showObj # if this is a naming pattern test or result doesn't have a show object then return best result if not bestResult.show or self.naming_pattern: return bestResult # get quality bestResult.quality = Quality.nameQuality(name, bestResult.show.is_anime) new_episode_numbers = [] new_season_numbers = [] new_absolute_numbers = [] # if we have an air-by-date show then get the real season/episode numbers if bestResult.is_air_by_date: from sickrage.core.databases import main_db airdate = bestResult.air_date.toordinal() sql_result = main_db.MainDB().select( "SELECT season, episode FROM tv_episodes WHERE showid = ? AND indexer = ? AND airdate = ?", [bestResult.show.indexerid, bestResult.show.indexer, airdate]) season_number = None episode_numbers = [] if sql_result: season_number = int(sql_result[0][0]) episode_numbers = [int(sql_result[0][1])] if not season_number or not len(episode_numbers): try: lINDEXER_API_PARMS = srIndexerApi(bestResult.show.indexer).api_params.copy() if bestResult.show.lang: lINDEXER_API_PARMS['language'] = bestResult.show.lang t = srIndexerApi(bestResult.show.indexer).indexer(**lINDEXER_API_PARMS) epObj = t[bestResult.show.indexerid].airedOn(bestResult.air_date)[0] season_number = int(epObj["seasonnumber"]) episode_numbers = [int(epObj["episodenumber"])] except indexer_episodenotfound: sickrage.srCore.srLogger.warning( "Unable to find episode with date " + bestResult.air_date + " for show " + bestResult.show.name + ", skipping") episode_numbers = [] except indexer_error as e: sickrage.srCore.srLogger.warning( "Unable to contact " + srIndexerApi(bestResult.show.indexer).name + ": {}".format( e)) episode_numbers = [] for epNo in episode_numbers: s = season_number e = epNo if bestResult.show.is_scene: (s, e) = get_indexer_numbering(bestResult.show.indexerid, bestResult.show.indexer, season_number, epNo) new_episode_numbers.append(e) new_season_numbers.append(s) elif bestResult.show.is_anime and len(bestResult.ab_episode_numbers): scene_season = get_scene_exception_by_name(bestResult.series_name)[1] for epAbsNo in bestResult.ab_episode_numbers: a = epAbsNo if bestResult.show.is_scene: a = get_indexer_absolute_numbering(bestResult.show.indexerid, bestResult.show.indexer, epAbsNo, True, scene_season) (s, e) = get_all_episodes_from_absolute_number(bestResult.show, [a]) new_absolute_numbers.append(a) new_episode_numbers.extend(e) new_season_numbers.append(s) elif bestResult.season_number and len(bestResult.episode_numbers): for epNo in bestResult.episode_numbers: s = bestResult.season_number e = epNo if bestResult.show.is_scene: (s, e) = get_indexer_numbering(bestResult.show.indexerid, bestResult.show.indexer, bestResult.season_number, epNo) if bestResult.show.is_anime: a = get_absolute_number_from_season_and_episode(bestResult.show, s, e) if a: new_absolute_numbers.append(a) new_episode_numbers.append(e) new_season_numbers.append(s) # need to do a quick sanity check heregex. It's possible that we now have episodes # from more than one season (by tvdb numbering), and this is just too much # for sickrage, so we'd need to flag it. new_season_numbers = list(set(new_season_numbers)) # remove duplicates if len(new_season_numbers) > 1: raise InvalidNameException("Scene numbering results episodes from " "seasons %s, (i.e. more than one) and " "sickrage does not support this. " "Sorry." % new_season_numbers) # I guess it's possible that we'd have duplicate episodes too, so lets # eliminate them new_episode_numbers = list(set(new_episode_numbers)) new_episode_numbers.sort() # maybe even duplicate absolute numbers so why not do them as well new_absolute_numbers = list(set(new_absolute_numbers)) new_absolute_numbers.sort() if len(new_absolute_numbers): bestResult.ab_episode_numbers = new_absolute_numbers if len(new_season_numbers) and len(new_episode_numbers): bestResult.episode_numbers = new_episode_numbers bestResult.season_number = new_season_numbers[0] if bestResult.show.is_scene: sickrage.srCore.srLogger.debug( "Converted parsed result {} into {}".format(bestResult.original_name, bestResult)) # CPU sleep time.sleep(1) return bestResult
def _doSearch(self, search_params, search_mode="eponly", epcount=0, age=0, epObj=None): results = [] items = {"Season": [], "Episode": [], "RSS": []} self.categories = "cat=" + str(self.cat) if not self._doLogin(): return results for mode in search_params.keys(): sickrage.LOGGER.debug("Search Mode: %s" % mode) for search_string in search_params[mode]: if mode is "RSS": self.page = 2 last_page = 0 y = int(self.page) if search_string == "": continue search_string = str(search_string).replace(".", " ") for x in range(0, y): z = x * 20 if last_page: break if mode is not "RSS": searchURL = (self.urls["search_page"] + "&filter={2}").format(z, self.categories, search_string) else: searchURL = self.urls["search_page"].format(z, self.categories) if mode is not "RSS": sickrage.LOGGER.debug("Search string: %s " % search_string) sickrage.LOGGER.debug("Search URL: %s" % searchURL) data = self.getURL(searchURL) if not data: sickrage.LOGGER.debug("No data returned from provider") continue try: with BS4Parser(data, markup_type="HTML", features=["html5lib", "permissive"]) as html: torrent_table = html.find("table", attrs={"class": "copyright"}) torrent_rows = torrent_table.find_all("tr") if torrent_table else [] # Continue only if one Release is found if len(torrent_rows) < 3: sickrage.LOGGER.debug("Data returned from provider does not contain any torrents") last_page = 1 continue if len(torrent_rows) < 42: last_page = 1 for result in torrent_table.find_all("tr")[2:]: try: link = result.find("td").find("a") title = link.string download_url = ( self.urls["download"] % result.find_all("td")[8].find("a")["href"][-8:] ) leechers = result.find_all("td")[3].find_all("td")[1].text leechers = int(leechers.strip("[]")) seeders = result.find_all("td")[3].find_all("td")[2].text seeders = int(seeders.strip("[]")) # FIXME size = -1 except (AttributeError, TypeError): continue filename_qt = self._reverseQuality(self._episodeQuality(result)) for text in self.hdtext: title1 = title title = title.replace(text, filename_qt) if title != title1: break if Quality.nameQuality(title) == Quality.UNKNOWN: title += filename_qt if not self._is_italian(result) and not self.subtitle: sickrage.LOGGER.debug("Torrent is subtitled, skipping: %s " % title) continue if self.engrelease and not self._is_english(result): sickrage.LOGGER.debug( "Torrent isnt english audio/subtitled , skipping: %s " % title ) continue search_show = re.split(r"([Ss][\d{1,2}]+)", search_string)[0] show_title = search_show rindex = re.search(r"([Ss][\d{1,2}]+)", title) if rindex: show_title = title[: rindex.start()] ep_params = title[rindex.start() :] if ( show_title.lower() != search_show.lower() and search_show.lower() in show_title.lower() and ep_params ): title = search_show + ep_params if not all([title, download_url]): continue if self._is_season_pack(title): title = re.sub(r"([Ee][\d{1,2}\-?]+)", "", title) # Filter unseeded torrent if seeders < self.minseed or leechers < self.minleech: if mode is not "RSS": sickrage.LOGGER.debug( "Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format( title, seeders, leechers ) ) continue item = title, download_url, size, seeders, leechers if mode is not "RSS": sickrage.LOGGER.debug("Found result: %s " % title) items[mode].append(item) except Exception: sickrage.LOGGER.error("Failed parsing provider. Traceback: %s" % traceback.format_exc()) # For each search mode sort all the items by seeders if available if available items[mode].sort(key=lambda tup: tup[3], reverse=True) results += items[mode] return results
def test_SDTV(self): self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.PDTV.XViD-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.PDTV.x264-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.HDTV.XViD-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.HDTV.x264-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.DSR.XViD-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.DSR.x264-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.TVRip.XViD-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.TVRip.x264-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.WEBRip.XViD-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.WEBRip.x264-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.WEB-DL.x264-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.WEB-DL.AAC2.0.H.264-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02 WEB-DL H 264-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02_WEB-DL_H_264-GROUP")) self.assertEqual(Quality.SDTV, Quality.nameQuality("Test.Show.S01E02.WEB-DL.AAC2.0.H264-GROUP"))