mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 00:43:37 +00:00
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:
parent
748ba6be71
commit
f4a9987933
6 changed files with 50 additions and 19 deletions
|
@ -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>
|
<b>Archive on first match: </b>
|
||||||
#if $bestQualities
|
#if $bestQualities
|
||||||
<input type="checkbox" name="archive_firstmatch" #if $show.archive_firstmatch == 1 then "checked=\"checked\"" else ""# /><br />
|
<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 />
|
<br />
|
||||||
#end if
|
#end if
|
||||||
<input type="submit" id="submit" value="Submit" class="btn btn-primary" />
|
<input type="submit" id="submit" value="Submit" class="btn btn-primary" />
|
||||||
|
|
|
@ -63,6 +63,7 @@ IGNORED = 7 # episodes that you don't want included in your download stats
|
||||||
SNATCHED_PROPER = 9 # qualified with quality
|
SNATCHED_PROPER = 9 # qualified with quality
|
||||||
SUBTITLED = 10 # qualified with quality
|
SUBTITLED = 10 # qualified with quality
|
||||||
FAILED = 11 #episode downloaded or snatched we don't want
|
FAILED = 11 #episode downloaded or snatched we don't want
|
||||||
|
SNATCHED_BEST = 12 # episode redownloaded using best quality
|
||||||
|
|
||||||
NAMING_REPEAT = 1
|
NAMING_REPEAT = 1
|
||||||
NAMING_EXTEND = 2
|
NAMING_EXTEND = 2
|
||||||
|
@ -117,7 +118,8 @@ class Quality:
|
||||||
statusPrefixes = {DOWNLOADED: "Downloaded",
|
statusPrefixes = {DOWNLOADED: "Downloaded",
|
||||||
SNATCHED: "Snatched",
|
SNATCHED: "Snatched",
|
||||||
SNATCHED_PROPER: "Snatched (Proper)",
|
SNATCHED_PROPER: "Snatched (Proper)",
|
||||||
FAILED: "Failed"}
|
FAILED: "Failed",
|
||||||
|
SNATCHED_BEST: "Snatched (Best)"}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _getStatusStrings(status):
|
def _getStatusStrings(status):
|
||||||
|
@ -248,11 +250,13 @@ class Quality:
|
||||||
SNATCHED = None
|
SNATCHED = None
|
||||||
SNATCHED_PROPER = None
|
SNATCHED_PROPER = None
|
||||||
FAILED = None
|
FAILED = None
|
||||||
|
SNATCHED_BEST = None
|
||||||
|
|
||||||
Quality.DOWNLOADED = [Quality.compositeStatus(DOWNLOADED, x) for x in Quality.qualityStrings.keys()]
|
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 = [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.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.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], [])
|
SD = Quality.combineQualities([Quality.SDTV, Quality.SDDVD], [])
|
||||||
HD = Quality.combineQualities([Quality.HDTV, Quality.FULLHDTV, Quality.HDWEBDL, Quality.FULLHDWEBDL, Quality.HDBLURAY, Quality.FULLHDBLURAY], []) # HD720p + HD1080p
|
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",
|
ARCHIVED: "Archived",
|
||||||
IGNORED: "Ignored",
|
IGNORED: "Ignored",
|
||||||
SUBTITLED: "Subtitled",
|
SUBTITLED: "Subtitled",
|
||||||
FAILED: "Failed"}
|
FAILED: "Failed",
|
||||||
|
SNATCHED_BEST: "Snatched (Best)"}
|
||||||
|
|
||||||
def __getitem__(self, name):
|
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)
|
status, quality = Quality.splitCompositeStatus(name)
|
||||||
if quality == Quality.NONE:
|
if quality == Quality.NONE:
|
||||||
return self.statusStrings[status]
|
return self.statusStrings[status]
|
||||||
|
@ -295,7 +300,7 @@ class StatusStrings:
|
||||||
return self.statusStrings[name]
|
return self.statusStrings[name]
|
||||||
|
|
||||||
def has_key(self, 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()
|
statusStrings = StatusStrings()
|
||||||
|
|
||||||
|
@ -307,7 +312,7 @@ class Overview:
|
||||||
SKIPPED = SKIPPED # 5
|
SKIPPED = SKIPPED # 5
|
||||||
|
|
||||||
# For both snatched statuses. Note: SNATCHED/QUAL have same value and break dict.
|
# 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",
|
overviewStrings = {SKIPPED: "skipped",
|
||||||
WANTED: "wanted",
|
WANTED: "wanted",
|
||||||
|
|
|
@ -710,7 +710,7 @@ class PostProcessor(object):
|
||||||
ep_quality = common.Quality.UNKNOWN
|
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 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
|
oldStatus, ep_quality = common.Quality.splitCompositeStatus(ep_obj.status) #@UnusedVariable
|
||||||
if ep_quality != common.Quality.UNKNOWN:
|
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)
|
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
|
return True
|
||||||
|
|
||||||
# if SB downloaded this on purpose then this is a priority download
|
# 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)
|
self._log(u"SB snatched this episode so I'm marking it as priority", logger.DEBUG)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -846,10 +846,10 @@ class PostProcessor(object):
|
||||||
|
|
||||||
# get the quality of the episode we're processing
|
# get the quality of the episode we're processing
|
||||||
new_ep_quality = self._get_quality(ep_obj)
|
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)
|
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)
|
priority_download = self._is_priority(ep_obj, new_ep_quality)
|
||||||
self._log(u"Is ep a priority download: " + str(priority_download), logger.DEBUG)
|
self._log(u"Is ep a priority download: " + str(priority_download), logger.DEBUG)
|
||||||
|
|
||||||
|
@ -924,7 +924,10 @@ class PostProcessor(object):
|
||||||
else:
|
else:
|
||||||
logger.log("good results: " + repr(self.good_results), logger.DEBUG)
|
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 = []
|
cur_ep.subtitles = []
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ import datetime
|
||||||
|
|
||||||
import sickbeard
|
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 logger, db, show_name_helpers, exceptions, helpers
|
||||||
from sickbeard import sab
|
from sickbeard import sab
|
||||||
|
@ -104,6 +104,9 @@ def snatchEpisode(result, endStatus=SNATCHED):
|
||||||
result: SearchResult instance to be snatched.
|
result: SearchResult instance to be snatched.
|
||||||
endStatus: the episode status that should be used for the episode object once it's 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
|
result.priority = 0 # -1 = low, 0 = normal, 1 = high
|
||||||
if sickbeard.ALLOW_HIGH_PRIORITY:
|
if sickbeard.ALLOW_HIGH_PRIORITY:
|
||||||
# if it aired recently make it 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
|
# don't notify when we re-download an episode
|
||||||
for curEpObj in result.episodes:
|
for curEpObj in result.episodes:
|
||||||
with curEpObj.lock:
|
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()
|
curEpObj.saveToDB()
|
||||||
|
|
||||||
if curEpObj.status not in Quality.DOWNLOADED:
|
if curEpObj.status not in Quality.DOWNLOADED:
|
||||||
|
@ -290,6 +296,22 @@ def isFinalResult(result):
|
||||||
else:
|
else:
|
||||||
return False
|
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):
|
def findEpisode(episode, manualSearch=False):
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ from sickbeard import db, logger, common, exceptions, helpers
|
||||||
from sickbeard import generic_queue
|
from sickbeard import generic_queue
|
||||||
from sickbeard import search, failed_history, history
|
from sickbeard import search, failed_history, history
|
||||||
from sickbeard import ui
|
from sickbeard import ui
|
||||||
from sickbeard.common import Quality
|
|
||||||
|
|
||||||
BACKLOG_SEARCH = 10
|
BACKLOG_SEARCH = 10
|
||||||
RSS_SEARCH = 20
|
RSS_SEARCH = 20
|
||||||
|
@ -105,7 +104,9 @@ class ManualSearchQueueItem(generic_queue.QueueItem):
|
||||||
|
|
||||||
# just use the first result for now
|
# just use the first result for now
|
||||||
logger.log(u"Downloading episode from " + foundEpisode.url)
|
logger.log(u"Downloading episode from " + foundEpisode.url)
|
||||||
|
|
||||||
result = search.snatchEpisode(foundEpisode)
|
result = search.snatchEpisode(foundEpisode)
|
||||||
|
|
||||||
providerModule = foundEpisode.provider
|
providerModule = foundEpisode.provider
|
||||||
if not result:
|
if not result:
|
||||||
ui.notifications.error('Error while attempting to snatch ' + foundEpisode.name+', check your logs')
|
ui.notifications.error('Error while attempting to snatch ' + foundEpisode.name+', check your logs')
|
||||||
|
@ -231,7 +232,7 @@ class BacklogQueueItem(generic_queue.QueueItem):
|
||||||
highestBestQuality = 0
|
highestBestQuality = 0
|
||||||
|
|
||||||
# if we need a better one then say yes
|
# 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
|
wantSeason = True
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ from sickbeard import history
|
||||||
from sickbeard import encodingKludge as ek
|
from sickbeard import encodingKludge as ek
|
||||||
|
|
||||||
from common import Quality, Overview
|
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
|
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
|
return Overview.SKIPPED
|
||||||
elif epStatus == ARCHIVED:
|
elif epStatus == ARCHIVED:
|
||||||
return Overview.GOOD
|
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
|
anyQualities, bestQualities = Quality.splitQuality(self.quality) # @UnusedVariable
|
||||||
if bestQualities:
|
if bestQualities:
|
||||||
|
@ -1034,7 +1034,7 @@ class TVShow(object):
|
||||||
|
|
||||||
if epStatus == FAILED:
|
if epStatus == FAILED:
|
||||||
return Overview.WANTED
|
return Overview.WANTED
|
||||||
elif epStatus in (SNATCHED, SNATCHED_PROPER):
|
elif epStatus in (SNATCHED, SNATCHED_PROPER, SNATCHED_BEST):
|
||||||
return Overview.SNATCHED
|
return Overview.SNATCHED
|
||||||
# if they don't want re-downloads then we call it good if they have anything
|
# if they don't want re-downloads then we call it good if they have anything
|
||||||
elif maxBestQuality == None:
|
elif maxBestQuality == None:
|
||||||
|
@ -1385,7 +1385,7 @@ class TVEpisode(object):
|
||||||
if not ek.ek(os.path.isfile, self.location):
|
if not ek.ek(os.path.isfile, self.location):
|
||||||
|
|
||||||
# if we don't have the file
|
# 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
|
# 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)
|
logger.log(u"Episode airs in the future, changing status from " + str(self.status) + " to " + str(UNAIRED), logger.DEBUG)
|
||||||
self.status = UNAIRED
|
self.status = UNAIRED
|
||||||
|
|
Loading…
Reference in a new issue