From f4a9987933fefd10dea6b233b04f175565aab329 Mon Sep 17 00:00:00 2001 From: echel0n Date: Wed, 19 Mar 2014 16:33:49 -0700 Subject: [PATCH] Added in a new feature called "Archive First Match", you can enable this feature from displayShow->editShow by using custom qualities and checking off "archive first match" This feature will snatch and your episode based on matching ANY one of your archive quality choices on a first match basis then set its status to archived to prevent further snatch attempts. --- gui/slick/interfaces/default/editShow.tmpl | 2 +- sickbeard/common.py | 15 ++++++++----- sickbeard/postProcessor.py | 13 ++++++----- sickbeard/search.py | 26 ++++++++++++++++++++-- sickbeard/search_queue.py | 5 +++-- sickbeard/tv.py | 8 +++---- 6 files changed, 50 insertions(+), 19 deletions(-) diff --git a/gui/slick/interfaces/default/editShow.tmpl b/gui/slick/interfaces/default/editShow.tmpl index a21f594b..1acba0f7 100644 --- a/gui/slick/interfaces/default/editShow.tmpl +++ b/gui/slick/interfaces/default/editShow.tmpl @@ -115,7 +115,7 @@ This DOES NOT allow Sick Beard to download non-english TV episodes!
Archive on first match: #if $bestQualities
-(check this to have the show archived after first match and download from your archive quality choices) +(check this to have the episode archived after the first best match is found from your archive quality list)
#end if diff --git a/sickbeard/common.py b/sickbeard/common.py index e447e137..440475ec 100644 --- a/sickbeard/common.py +++ b/sickbeard/common.py @@ -63,6 +63,7 @@ IGNORED = 7 # episodes that you don't want included in your download stats SNATCHED_PROPER = 9 # qualified with quality SUBTITLED = 10 # qualified with quality FAILED = 11 #episode downloaded or snatched we don't want +SNATCHED_BEST = 12 # episode redownloaded using best quality NAMING_REPEAT = 1 NAMING_EXTEND = 2 @@ -117,7 +118,8 @@ class Quality: statusPrefixes = {DOWNLOADED: "Downloaded", SNATCHED: "Snatched", SNATCHED_PROPER: "Snatched (Proper)", - FAILED: "Failed"} + FAILED: "Failed", + SNATCHED_BEST: "Snatched (Best)"} @staticmethod def _getStatusStrings(status): @@ -248,11 +250,13 @@ class Quality: SNATCHED = None SNATCHED_PROPER = None FAILED = None + SNATCHED_BEST = None Quality.DOWNLOADED = [Quality.compositeStatus(DOWNLOADED, x) for x in Quality.qualityStrings.keys()] Quality.SNATCHED = [Quality.compositeStatus(SNATCHED, x) for x in Quality.qualityStrings.keys()] Quality.SNATCHED_PROPER = [Quality.compositeStatus(SNATCHED_PROPER, x) for x in Quality.qualityStrings.keys()] Quality.FAILED = [Quality.compositeStatus(FAILED, x) for x in Quality.qualityStrings.keys()] +Quality.SNATCHED_BEST = [Quality.compositeStatus(SNATCHED_BEST, x) for x in Quality.qualityStrings.keys()] SD = Quality.combineQualities([Quality.SDTV, Quality.SDDVD], []) HD = Quality.combineQualities([Quality.HDTV, Quality.FULLHDTV, Quality.HDWEBDL, Quality.FULLHDWEBDL, Quality.HDBLURAY, Quality.FULLHDBLURAY], []) # HD720p + HD1080p @@ -282,10 +286,11 @@ class StatusStrings: ARCHIVED: "Archived", IGNORED: "Ignored", SUBTITLED: "Subtitled", - FAILED: "Failed"} + FAILED: "Failed", + SNATCHED_BEST: "Snatched (Best)"} def __getitem__(self, name): - if name in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER: + if name in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_BEST: status, quality = Quality.splitCompositeStatus(name) if quality == Quality.NONE: return self.statusStrings[status] @@ -295,7 +300,7 @@ class StatusStrings: return self.statusStrings[name] def has_key(self, name): - return name in self.statusStrings or name in Quality.DOWNLOADED or name in Quality.SNATCHED or name in Quality.SNATCHED_PROPER + return name in self.statusStrings or name in Quality.DOWNLOADED or name in Quality.SNATCHED or name in Quality.SNATCHED_PROPER or name in Quality.SNATCHED_BEST statusStrings = StatusStrings() @@ -307,7 +312,7 @@ class Overview: SKIPPED = SKIPPED # 5 # For both snatched statuses. Note: SNATCHED/QUAL have same value and break dict. - SNATCHED = SNATCHED_PROPER # 9 + SNATCHED = SNATCHED_PROPER = SNATCHED_BEST # 9 overviewStrings = {SKIPPED: "skipped", WANTED: "wanted", diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py index 8eb6721f..01590320 100644 --- a/sickbeard/postProcessor.py +++ b/sickbeard/postProcessor.py @@ -710,7 +710,7 @@ class PostProcessor(object): ep_quality = common.Quality.UNKNOWN # if there is a quality available in the status then we don't need to bother guessing from the filename - if ep_obj.status in common.Quality.SNATCHED + common.Quality.SNATCHED_PROPER: + if ep_obj.status in common.Quality.SNATCHED + common.Quality.SNATCHED_PROPER + common.Quality.SNATCHED_BEST: oldStatus, ep_quality = common.Quality.splitCompositeStatus(ep_obj.status) #@UnusedVariable if ep_quality != common.Quality.UNKNOWN: self._log(u"The old status had a quality in it, using that: " + common.Quality.qualityStrings[ep_quality], logger.DEBUG) @@ -787,7 +787,7 @@ class PostProcessor(object): return True # if SB downloaded this on purpose then this is a priority download - if self.in_history or ep_obj.status in common.Quality.SNATCHED + common.Quality.SNATCHED_PROPER: + if self.in_history or ep_obj.status in common.Quality.SNATCHED + common.Quality.SNATCHED_PROPER + common.Quality.SNATCHED_BEST: self._log(u"SB snatched this episode so I'm marking it as priority", logger.DEBUG) return True @@ -846,10 +846,10 @@ class PostProcessor(object): # get the quality of the episode we're processing new_ep_quality = self._get_quality(ep_obj) - test = str(new_ep_quality) + logger.log(u"Quality of the episode we're processing: " + str(new_ep_quality), logger.DEBUG) - # see if this is a priority download (is it snatched, in history, or PROPER) + # see if this is a priority download (is it snatched, in history, PROPER, or BEST) priority_download = self._is_priority(ep_obj, new_ep_quality) self._log(u"Is ep a priority download: " + str(priority_download), logger.DEBUG) @@ -924,7 +924,10 @@ class PostProcessor(object): else: logger.log("good results: " + repr(self.good_results), logger.DEBUG) - cur_ep.status = common.Quality.compositeStatus(common.DOWNLOADED, new_ep_quality) + if ep_obj.status in common.Quality.SNATCHED_BEST: + cur_ep.status = common.Quality.compositeStatus(common.ARCHIVED, new_ep_quality) + else: + cur_ep.status = common.Quality.compositeStatus(common.DOWNLOADED, new_ep_quality) cur_ep.subtitles = [] diff --git a/sickbeard/search.py b/sickbeard/search.py index 00b73d1a..b48a1bce 100644 --- a/sickbeard/search.py +++ b/sickbeard/search.py @@ -24,7 +24,7 @@ import datetime import sickbeard -from common import SNATCHED, SNATCHED_PROPER, Quality, SEASON_RESULT, MULTI_EP_RESULT +from common import SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, Quality, SEASON_RESULT, MULTI_EP_RESULT from sickbeard import logger, db, show_name_helpers, exceptions, helpers from sickbeard import sab @@ -104,6 +104,9 @@ def snatchEpisode(result, endStatus=SNATCHED): result: SearchResult instance to be snatched. endStatus: the episode status that should be used for the episode object once it's snatched. """ + + if result is None: return False + result.priority = 0 # -1 = low, 0 = normal, 1 = high if sickbeard.ALLOW_HIGH_PRIORITY: # if it aired recently make it high priority @@ -153,7 +156,10 @@ def snatchEpisode(result, endStatus=SNATCHED): # don't notify when we re-download an episode for curEpObj in result.episodes: with curEpObj.lock: - curEpObj.status = Quality.compositeStatus(endStatus, result.quality) + if isFirstBestMatch(result): + curEpObj.status = Quality.compositeStatus(SNATCHED_BEST, result.quality) + else: + curEpObj.status = Quality.compositeStatus(endStatus, result.quality) curEpObj.saveToDB() if curEpObj.status not in Quality.DOWNLOADED: @@ -290,6 +296,22 @@ def isFinalResult(result): else: 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. + """ + + logger.log(u"Checking if we should archive our first best quality match for for episode " + result.name, logger.DEBUG) + + 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 findEpisode(episode, manualSearch=False): diff --git a/sickbeard/search_queue.py b/sickbeard/search_queue.py index 1c66fc69..eede681d 100644 --- a/sickbeard/search_queue.py +++ b/sickbeard/search_queue.py @@ -26,7 +26,6 @@ from sickbeard import db, logger, common, exceptions, helpers from sickbeard import generic_queue from sickbeard import search, failed_history, history from sickbeard import ui -from sickbeard.common import Quality BACKLOG_SEARCH = 10 RSS_SEARCH = 20 @@ -105,7 +104,9 @@ class ManualSearchQueueItem(generic_queue.QueueItem): # just use the first result for now logger.log(u"Downloading episode from " + foundEpisode.url) + result = search.snatchEpisode(foundEpisode) + providerModule = foundEpisode.provider if not result: ui.notifications.error('Error while attempting to snatch ' + foundEpisode.name+', check your logs') @@ -231,7 +232,7 @@ class BacklogQueueItem(generic_queue.QueueItem): highestBestQuality = 0 # if we need a better one then say yes - if (curStatus in (common.DOWNLOADED, common.SNATCHED, common.SNATCHED_PROPER) and curQuality < highestBestQuality) or curStatus == common.WANTED: + if (curStatus in (common.DOWNLOADED, common.SNATCHED, common.SNATCHED_PROPER, common.SNATCHED_BEST) and curQuality < highestBestQuality) or curStatus == common.WANTED: wantSeason = True break diff --git a/sickbeard/tv.py b/sickbeard/tv.py index 76164d13..b75f7340 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -50,7 +50,7 @@ from sickbeard import history from sickbeard import encodingKludge as ek from common import Quality, Overview -from common import DOWNLOADED, SNATCHED, SNATCHED_PROPER, ARCHIVED, IGNORED, UNAIRED, WANTED, SKIPPED, UNKNOWN, FAILED +from common import DOWNLOADED, SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, ARCHIVED, IGNORED, UNAIRED, WANTED, SKIPPED, UNKNOWN, FAILED from common import NAMING_DUPLICATE, NAMING_EXTEND, NAMING_LIMITED_EXTEND, NAMING_SEPARATED_REPEAT, NAMING_LIMITED_EXTEND_E_PREFIXED @@ -1022,7 +1022,7 @@ class TVShow(object): return Overview.SKIPPED elif epStatus == ARCHIVED: return Overview.GOOD - elif epStatus in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.FAILED: + elif epStatus in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.FAILED + Quality.SNATCHED_BEST: anyQualities, bestQualities = Quality.splitQuality(self.quality) # @UnusedVariable if bestQualities: @@ -1034,7 +1034,7 @@ class TVShow(object): if epStatus == FAILED: return Overview.WANTED - elif epStatus in (SNATCHED, SNATCHED_PROPER): + elif epStatus in (SNATCHED, SNATCHED_PROPER, SNATCHED_BEST): return Overview.SNATCHED # if they don't want re-downloads then we call it good if they have anything elif maxBestQuality == None: @@ -1385,7 +1385,7 @@ class TVEpisode(object): if not ek.ek(os.path.isfile, self.location): # if we don't have the file - if self.airdate >= datetime.date.today() and self.status not in Quality.SNATCHED + Quality.SNATCHED_PROPER: + if self.airdate >= datetime.date.today() and self.status not in Quality.SNATCHED + Quality.SNATCHED_PROPER : # and it hasn't aired yet set the status to UNAIRED logger.log(u"Episode airs in the future, changing status from " + str(self.status) + " to " + str(UNAIRED), logger.DEBUG) self.status = UNAIRED