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.
This commit is contained in:
echel0n 2014-03-19 16:33:49 -07:00
parent 748ba6be71
commit f4a9987933
6 changed files with 50 additions and 19 deletions

View file

@ -115,7 +115,7 @@ This <b>DOES NOT</b> allow Sick Beard to download non-english TV episodes!<br />
<b>Archive on first match: </b>
#if $bestQualities
<input type="checkbox" name="archive_firstmatch" #if $show.archive_firstmatch == 1 then "checked=\"checked\"" else ""# /><br />
(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)
<br />
#end if
<input type="submit" id="submit" value="Submit" class="btn btn-primary" />

View file

@ -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",

View file

@ -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 = []

View file

@ -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):

View file

@ -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

View file

@ -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