mirror of
https://github.com/SickGear/SickGear.git
synced 2025-01-05 17:43:37 +00:00
Merge pull request #321 from Prinz23/feature/AddSearchUnaired
Add Option to search for Unaired Episodes
This commit is contained in:
commit
ebdbf43d8b
11 changed files with 146 additions and 108 deletions
|
@ -1,4 +1,4 @@
|
|||
### 0.x.x (2015-xx-xx xx:xx:xx UTC)
|
||||
### 0.x.x (2015-xx-xx xx:xx:xx UTC)
|
||||
|
||||
* Change network names to only display on top line of Day by Day layout on Episode View
|
||||
* Reposition country part of network name into the hover over in Day by Day layout
|
||||
|
@ -6,6 +6,7 @@
|
|||
* Fix Backlog scheduler initialization and change backlog frequency from minutes to days
|
||||
* Change to consolidate and tidy some provider code
|
||||
* Fix restore table row colours on the Manage/Episode Status Management page
|
||||
* Add option "Search for unaired episodes" to config/Search Settings
|
||||
|
||||
|
||||
### 0.8.3 (2015-04-25 08:48:00 UTC)
|
||||
|
|
|
@ -100,6 +100,15 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-pair">
|
||||
<label for="search_unaired">
|
||||
<span class="component-title">Search for unaired episodes</span>
|
||||
<span class="component-desc">
|
||||
<input type="checkbox" name="search_unaired" id="search_unaired" class="enabler"<%= html_checked if sickbeard.SEARCH_UNAIRED == True else '' %>>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-pair">
|
||||
<label>
|
||||
<span class="component-title">Usenet retention</span>
|
||||
|
|
|
@ -31,6 +31,7 @@ import sys
|
|||
import os.path
|
||||
import uuid
|
||||
import base64
|
||||
import sickbeard
|
||||
sys.path.append(os.path.abspath('../lib'))
|
||||
from sickbeard import providers, metadata, config, webserveInit
|
||||
from sickbeard.providers.generic import GenericProvider
|
||||
|
@ -225,6 +226,7 @@ MAX_BACKLOG_FREQUENCY = 35
|
|||
MIN_UPDATE_FREQUENCY = 1
|
||||
|
||||
BACKLOG_DAYS = 7
|
||||
SEARCH_UNAIRED = False
|
||||
|
||||
ADD_SHOWS_WO_DIR = False
|
||||
CREATE_MISSING_SHOW_DIRS = False
|
||||
|
@ -528,7 +530,7 @@ def initialize(consoleLogging=True):
|
|||
USE_FAILED_DOWNLOADS, DELETE_FAILED, ANON_REDIRECT, LOCALHOST_IP, TMDB_API_KEY, DEBUG, PROXY_SETTING, PROXY_INDEXERS, \
|
||||
AUTOPOSTPROCESSER_FREQUENCY, DEFAULT_AUTOPOSTPROCESSER_FREQUENCY, MIN_AUTOPOSTPROCESSER_FREQUENCY, \
|
||||
ANIME_DEFAULT, NAMING_ANIME, USE_ANIDB, ANIDB_USERNAME, ANIDB_PASSWORD, ANIDB_USE_MYLIST, \
|
||||
ANIME_SPLIT_HOME, SCENE_DEFAULT, BACKLOG_DAYS, ANIME_TREAT_AS_HDTV, \
|
||||
ANIME_SPLIT_HOME, SCENE_DEFAULT, BACKLOG_DAYS, SEARCH_UNAIRED, ANIME_TREAT_AS_HDTV, \
|
||||
COOKIE_SECRET, USE_IMDB_INFO, DISPLAY_BACKGROUND, DISPLAY_BACKGROUND_TRANSPARENT, DISPLAY_ALL_SEASONS
|
||||
|
||||
if __INITIALIZED__:
|
||||
|
@ -736,6 +738,7 @@ def initialize(consoleLogging=True):
|
|||
UPDATE_FREQUENCY = MIN_UPDATE_FREQUENCY
|
||||
|
||||
BACKLOG_DAYS = check_setting_int(CFG, 'General', 'backlog_days', 7)
|
||||
SEARCH_UNAIRED = bool(check_setting_int(CFG, 'General', 'search_unaired', 0))
|
||||
|
||||
NZB_DIR = check_setting_str(CFG, 'Blackhole', 'nzb_dir', '')
|
||||
TORRENT_DIR = check_setting_str(CFG, 'Blackhole', 'torrent_dir', '')
|
||||
|
@ -1170,13 +1173,15 @@ def initialize(consoleLogging=True):
|
|||
cycleTime=update_interval,
|
||||
threadName="RECENTSEARCHER",
|
||||
run_delay=update_now if RECENTSEARCH_STARTUP
|
||||
else datetime.timedelta(minutes=5))
|
||||
else datetime.timedelta(minutes=5),
|
||||
prevent_cycle_run=sickbeard.searchQueueScheduler.action.is_recentsearch_in_progress)
|
||||
|
||||
backlogSearchScheduler = searchBacklog.BacklogSearchScheduler(searchBacklog.BacklogSearcher(),
|
||||
cycleTime=datetime.timedelta(minutes=get_backlog_cycle_time()),
|
||||
threadName="BACKLOG",
|
||||
run_delay=update_now if BACKLOG_STARTUP
|
||||
else datetime.timedelta(minutes=10))
|
||||
else datetime.timedelta(minutes=10),
|
||||
prevent_cycle_run=sickbeard.searchQueueScheduler.action.is_standard_backlog_in_progress)
|
||||
|
||||
search_intervals = {'15m': 15, '45m': 45, '90m': 90, '4h': 4 * 60, 'daily': 24 * 60}
|
||||
if CHECK_PROPERS_INTERVAL in search_intervals:
|
||||
|
@ -1495,6 +1500,7 @@ def save_config():
|
|||
new_config['General']['metadata_kodi'] = METADATA_KODI
|
||||
|
||||
new_config['General']['backlog_days'] = int(BACKLOG_DAYS)
|
||||
new_config['General']['search_unaired'] = int(SEARCH_UNAIRED)
|
||||
|
||||
new_config['General']['cache_dir'] = ACTUAL_CACHE_DIR if ACTUAL_CACHE_DIR else 'cache'
|
||||
new_config['General']['root_dirs'] = ROOT_DIRS if ROOT_DIRS else ''
|
||||
|
|
|
@ -206,26 +206,26 @@ class Quality:
|
|||
return Quality.UNKNOWN
|
||||
|
||||
if checkName(['(pdtv|hdtv|dsr|tvrip).(xvid|x264|h.?264)'], all) and not checkName(['(720|1080)[pi]'], all) \
|
||||
and not checkName(['hr.ws.pdtv.x264'], any):
|
||||
and not checkName(['hr.ws.pdtv.(x264|h.?264)'], any):
|
||||
return Quality.SDTV
|
||||
elif checkName(['web.dl|webrip', 'xvid|x264|h.?264'], all) and not checkName(['(720|1080)[pi]'], all):
|
||||
elif checkName(['web.?dl|web.?rip', 'xvid|x264|h.?264'], all) and not checkName(['(720|1080)[pi]'], all):
|
||||
return Quality.SDTV
|
||||
elif checkName(['(dvdrip|b[r|d]rip)(.ws)?.(xvid|divx|x264)'], any) and not checkName(['(720|1080)[pi]'], all):
|
||||
elif checkName(['(dvd.?rip|b[r|d]rip)(.ws)?(.(xvid|divx|x264|h.?264))?'], any) and not checkName(['(720|1080)[pi]'], all):
|
||||
return Quality.SDDVD
|
||||
elif checkName(['720p', 'hdtv', 'x264'], all) or checkName(['hr.ws.pdtv.x264'], any) \
|
||||
elif checkName(['720p', 'hdtv', 'x264|h.?264'], all) or checkName(['hr.ws.pdtv.(x264|h.?264)'], any) \
|
||||
and not checkName(['(1080)[pi]'], all):
|
||||
return Quality.HDTV
|
||||
elif checkName(['720p|1080i', 'hdtv', 'mpeg-?2'], all) or checkName(['1080[pi].hdtv', 'h.?264'], all):
|
||||
return Quality.RAWHDTV
|
||||
elif checkName(['1080p', 'hdtv', 'x264'], all):
|
||||
return Quality.FULLHDTV
|
||||
elif checkName(['720p', 'web.dl|webrip'], all) or checkName(['720p', 'itunes', 'h.?264'], all):
|
||||
elif checkName(['720p', 'web.?dl|web.?rip'], all) or checkName(['720p', 'itunes', 'x264|h.?264'], all):
|
||||
return Quality.HDWEBDL
|
||||
elif checkName(['1080p', 'web.dl|webrip'], all) or checkName(['1080p', 'itunes', 'h.?264'], all):
|
||||
elif checkName(['1080p', 'web.?dl|web.?rip'], all) or checkName(['1080p', 'itunes', 'x264|h.?264'], all):
|
||||
return Quality.FULLHDWEBDL
|
||||
elif checkName(['720p', 'bluray|hddvd|b[r|d]rip', 'x264'], all):
|
||||
elif checkName(['720p', 'blu.?ray|hddvd|b[r|d]rip', 'x264|h.?264'], all):
|
||||
return Quality.HDBLURAY
|
||||
elif checkName(['1080p', 'bluray|hddvd|b[r|d]rip', 'x264'], all):
|
||||
elif checkName(['1080p', 'blu.?ray|hddvd|b[r|d]rip', 'x264|h.?264'], all):
|
||||
return Quality.FULLHDBLURAY
|
||||
else:
|
||||
return Quality.UNKNOWN
|
||||
|
|
|
@ -27,13 +27,14 @@ from sickbeard.exceptions import ex
|
|||
|
||||
class Scheduler(threading.Thread):
|
||||
def __init__(self, action, cycleTime=datetime.timedelta(minutes=10), run_delay=datetime.timedelta(minutes=0),
|
||||
start_time=None, threadName="ScheduledThread", silent=True):
|
||||
start_time=None, threadName="ScheduledThread", silent=True, prevent_cycle_run=None):
|
||||
super(Scheduler, self).__init__()
|
||||
|
||||
self.lastRun = datetime.datetime.now() + run_delay - cycleTime
|
||||
self.action = action
|
||||
self.cycleTime = cycleTime
|
||||
self.start_time = start_time
|
||||
self.prevent_cycle_run = prevent_cycle_run
|
||||
|
||||
self.name = threadName
|
||||
self.silent = silent
|
||||
|
@ -70,6 +71,12 @@ class Scheduler(threading.Thread):
|
|||
else:
|
||||
should_run = True
|
||||
|
||||
if should_run and self.prevent_cycle_run is not None and self.prevent_cycle_run():
|
||||
logger.log(u'%s skipping this cycleTime' % self.name, logger.WARNING)
|
||||
# set lastRun to only check start_time after another cycleTime
|
||||
self.lastRun = current_time
|
||||
should_run = False
|
||||
|
||||
if should_run:
|
||||
self.lastRun = current_time
|
||||
|
||||
|
|
|
@ -317,49 +317,78 @@ def isFirstBestMatch(result):
|
|||
return False
|
||||
|
||||
|
||||
def wantedEpisodes(show, fromDate):
|
||||
anyQualities, bestQualities = common.Quality.splitQuality(show.quality) # @UnusedVariable
|
||||
allQualities = list(set(anyQualities + bestQualities))
|
||||
def wantedEpisodes(show, fromDate, make_dict=False):
|
||||
initialQualities, archiveQualities = common.Quality.splitQuality(show.quality)
|
||||
allQualities = list(set(initialQualities + archiveQualities))
|
||||
|
||||
myDB = db.DBConnection()
|
||||
|
||||
if show.air_by_date:
|
||||
sqlResults = myDB.select(
|
||||
"SELECT ep.status, ep.season, ep.episode FROM tv_episodes ep, tv_shows show WHERE season != 0 AND ep.showid = show.indexer_id AND show.paused = 0 AND ep.airdate > ? AND ep.showid = ? AND show.air_by_date = 1",
|
||||
[fromDate.toordinal(), show.indexerid])
|
||||
sqlString = 'SELECT ep.status, ep.season, ep.episode, ep.airdate FROM [tv_episodes] AS ep, [tv_shows] AS show WHERE season != 0 AND ep.showid = show.indexer_id AND show.paused = 0 AND ep.showid = ? AND show.air_by_date = 1'
|
||||
else:
|
||||
sqlResults = myDB.select(
|
||||
"SELECT status, season, episode FROM tv_episodes WHERE showid = ? AND season > 0 and airdate > ?",
|
||||
[show.indexerid, fromDate.toordinal()])
|
||||
sqlString = 'SELECT status, season, episode, airdate FROM [tv_episodes] WHERE showid = ? AND season > 0'
|
||||
|
||||
if sickbeard.SEARCH_UNAIRED:
|
||||
statusList = [common.WANTED, common.FAILED, common.UNAIRED]
|
||||
sqlString += ' AND ( airdate > ? OR airdate = 1 )'
|
||||
else:
|
||||
statusList = [common.WANTED, common.FAILED]
|
||||
sqlString += ' AND airdate > ?'
|
||||
|
||||
sqlResults = myDB.select(sqlString, [show.indexerid, fromDate.toordinal()])
|
||||
|
||||
# check through the list of statuses to see if we want any
|
||||
wanted = []
|
||||
total_wanted = total_replacing = 0
|
||||
if make_dict:
|
||||
wanted = {}
|
||||
else:
|
||||
wanted = []
|
||||
total_wanted = total_replacing = total_unaired = 0
|
||||
downloadedStatusList = (common.DOWNLOADED, common.SNATCHED, common.SNATCHED_PROPER, common.SNATCHED_BEST)
|
||||
for result in sqlResults:
|
||||
not_downloaded = True
|
||||
curCompositeStatus = int(result["status"])
|
||||
curStatus, curQuality = common.Quality.splitCompositeStatus(curCompositeStatus)
|
||||
|
||||
if bestQualities:
|
||||
highestBestQuality = max(allQualities)
|
||||
if show.archive_firstmatch and curStatus in downloadedStatusList and curQuality in archiveQualities:
|
||||
continue
|
||||
|
||||
# special case: already downloaded quality is not in any of the wanted Qualities
|
||||
other_quality_downloaded = False
|
||||
if curStatus in downloadedStatusList and curQuality not in allQualities:
|
||||
other_quality_downloaded = True
|
||||
wantedQualities = allQualities
|
||||
else:
|
||||
highestBestQuality = 0
|
||||
wantedQualities = archiveQualities
|
||||
|
||||
if archiveQualities:
|
||||
highestWantedQuality = max(wantedQualities)
|
||||
else:
|
||||
if other_quality_downloaded:
|
||||
highestWantedQuality = max(initialQualities)
|
||||
else:
|
||||
highestWantedQuality = 0
|
||||
|
||||
# if we need a better one then say yes
|
||||
if (curStatus in (common.DOWNLOADED, common.SNATCHED, common.SNATCHED_PROPER,
|
||||
common.SNATCHED_BEST) and curQuality < highestBestQuality) or curStatus == common.WANTED:
|
||||
if (curStatus in downloadedStatusList and curQuality < highestWantedQuality) or curStatus in statusList or (sickbeard.SEARCH_UNAIRED and result['airdate'] == 1 and curStatus in (common.SKIPPED, common.IGNORED, common.UNAIRED, common.UNKNOWN, common.FAILED)):
|
||||
|
||||
if curStatus == common.WANTED:
|
||||
if curStatus in (common.WANTED, common.FAILED):
|
||||
total_wanted += 1
|
||||
elif curStatus in (common.UNAIRED, common.SKIPPED, common.IGNORED, common.UNKNOWN):
|
||||
total_unaired += 1
|
||||
else:
|
||||
total_replacing += 1
|
||||
not_downloaded = False
|
||||
|
||||
epObj = show.getEpisode(int(result["season"]), int(result["episode"]))
|
||||
epObj.wantedQuality = [i for i in allQualities if (i > curQuality and i != common.Quality.UNKNOWN)]
|
||||
wanted.append(epObj)
|
||||
if make_dict:
|
||||
wanted.setdefault(epObj.season, []).append(epObj)
|
||||
else:
|
||||
epObj.wantedQuality = [i for i in (initialQualities if not_downloaded else wantedQualities) if (i > curQuality and i != common.Quality.UNKNOWN)]
|
||||
wanted.append(epObj)
|
||||
|
||||
if 0 < total_wanted + total_replacing:
|
||||
if 0 < total_wanted + total_replacing + total_unaired:
|
||||
actions = []
|
||||
for msg, total in ['%d episode%s', total_wanted], ['to upgrade %d episode%s', total_replacing]:
|
||||
for msg, total in ['%d episode%s', total_wanted], ['to upgrade %d episode%s', total_replacing], ['%d unaired episode%s', total_unaired]:
|
||||
if 0 < total:
|
||||
actions.append(msg % (total, helpers.maybe_plural(total)))
|
||||
logger.log(u'We want %s for %s' % (' and '.join(actions), show.name))
|
||||
|
@ -393,11 +422,6 @@ def searchForNeededEpisodes(episodes):
|
|||
continue
|
||||
|
||||
# find the best result for the current episode
|
||||
bestResult = None
|
||||
for curResult in curFoundResults[curEp]:
|
||||
if not bestResult or bestResult.quality < curResult.quality:
|
||||
bestResult = curResult
|
||||
|
||||
bestResult = pickBestResult(curFoundResults[curEp], curEp.show)
|
||||
|
||||
# if all results were rejected move on to the next episode
|
||||
|
|
|
@ -28,6 +28,7 @@ from sickbeard import search_queue
|
|||
from sickbeard import logger
|
||||
from sickbeard import ui
|
||||
from sickbeard import common
|
||||
from sickbeard.search import wantedEpisodes
|
||||
|
||||
|
||||
class BacklogSearchScheduler(scheduler.Scheduler):
|
||||
|
@ -78,8 +79,10 @@ class BacklogSearcher:
|
|||
|
||||
if which_shows:
|
||||
show_list = which_shows
|
||||
standard_backlog = False
|
||||
else:
|
||||
show_list = sickbeard.showList
|
||||
standard_backlog = True
|
||||
|
||||
self._get_lastBacklog()
|
||||
|
||||
|
@ -99,12 +102,12 @@ class BacklogSearcher:
|
|||
if curShow.paused:
|
||||
continue
|
||||
|
||||
segments = self._get_segments(curShow, fromDate)
|
||||
segments = wantedEpisodes(curShow, fromDate, make_dict=True)
|
||||
|
||||
for season, segment in segments.items():
|
||||
self.currentSearchInfo = {'title': curShow.name + " Season " + str(season)}
|
||||
|
||||
backlog_queue_item = search_queue.BacklogQueueItem(curShow, segment)
|
||||
backlog_queue_item = search_queue.BacklogQueueItem(curShow, segment, standard_backlog=standard_backlog)
|
||||
sickbeard.searchQueueScheduler.action.add_item(backlog_queue_item) # @UndefinedVariable
|
||||
else:
|
||||
logger.log(u'Nothing needs to be downloaded for %s, skipping' % str(curShow.name), logger.DEBUG)
|
||||
|
@ -136,55 +139,6 @@ class BacklogSearcher:
|
|||
self._lastBacklog = lastBacklog
|
||||
return self._lastBacklog
|
||||
|
||||
def _get_segments(self, show, fromDate):
|
||||
anyQualities, bestQualities = common.Quality.splitQuality(show.quality) # @UnusedVariable
|
||||
|
||||
myDB = db.DBConnection()
|
||||
if show.air_by_date:
|
||||
sqlResults = myDB.select(
|
||||
"SELECT ep.status, ep.season, ep.episode FROM tv_episodes ep, tv_shows show WHERE season != 0 AND ep.showid = show.indexer_id AND show.paused = 0 AND ep.airdate > ? AND ep.showid = ? AND show.air_by_date = 1",
|
||||
[fromDate.toordinal(), show.indexerid])
|
||||
else:
|
||||
sqlResults = myDB.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 = {}
|
||||
total_wanted = total_replacing = 0
|
||||
for result in sqlResults:
|
||||
curCompositeStatus = int(result["status"])
|
||||
curStatus, curQuality = common.Quality.splitCompositeStatus(curCompositeStatus)
|
||||
|
||||
if bestQualities:
|
||||
highestBestQuality = max(bestQualities)
|
||||
else:
|
||||
highestBestQuality = 0
|
||||
|
||||
# if we need a better one then say yes
|
||||
if (curStatus in (common.DOWNLOADED, common.SNATCHED, common.SNATCHED_PROPER,
|
||||
common.SNATCHED_BEST) and curQuality < highestBestQuality) or curStatus == common.WANTED:
|
||||
|
||||
if curStatus == common.WANTED:
|
||||
total_wanted += 1
|
||||
else:
|
||||
total_replacing += 1
|
||||
|
||||
epObj = show.getEpisode(int(result["season"]), int(result["episode"]))
|
||||
if epObj.season not in wanted:
|
||||
wanted[epObj.season] = [epObj]
|
||||
else:
|
||||
wanted[epObj.season].append(epObj)
|
||||
|
||||
if 0 < total_wanted + total_replacing:
|
||||
actions = []
|
||||
for msg, total in ['%d episode%s', total_wanted], ['to upgrade %d episode%s', total_replacing]:
|
||||
if 0 < total:
|
||||
actions.append(msg % (total, helpers.maybe_plural(total)))
|
||||
logger.log(u'We want %s for %s' % (' and '.join(actions), show.name))
|
||||
|
||||
return wanted
|
||||
|
||||
def _set_lastBacklog(self, when):
|
||||
|
||||
logger.log(u"Setting the last backlog in the DB to " + str(when), logger.DEBUG)
|
||||
|
|
|
@ -94,6 +94,12 @@ class SearchQueue(generic_queue.GenericQueue):
|
|||
return True
|
||||
return False
|
||||
|
||||
def is_standard_backlog_in_progress(self):
|
||||
for cur_item in self.queue + [self.currentItem]:
|
||||
if isinstance(cur_item, BacklogQueueItem) and cur_item.standard_backlog:
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_recentsearch_in_progress(self):
|
||||
for cur_item in self.queue + [self.currentItem]:
|
||||
if isinstance(cur_item, RecentSearchQueueItem):
|
||||
|
@ -308,13 +314,14 @@ class ManualSearchQueueItem(generic_queue.QueueItem):
|
|||
|
||||
|
||||
class BacklogQueueItem(generic_queue.QueueItem):
|
||||
def __init__(self, show, segment):
|
||||
def __init__(self, show, segment, standard_backlog=False):
|
||||
generic_queue.QueueItem.__init__(self, 'Backlog', BACKLOG_SEARCH)
|
||||
self.priority = generic_queue.QueuePriorities.LOW
|
||||
self.name = 'BACKLOG-' + str(show.indexerid)
|
||||
self.success = None
|
||||
self.show = show
|
||||
self.segment = segment
|
||||
self.standard_backlog = standard_backlog
|
||||
|
||||
def run(self):
|
||||
generic_queue.QueueItem.run(self)
|
||||
|
|
|
@ -1243,11 +1243,12 @@ class TVShow(object):
|
|||
Quality.qualityStrings[quality], logger.DEBUG)
|
||||
|
||||
# if the quality isn't one we want under any circumstances then just say no
|
||||
anyQualities, bestQualities = Quality.splitQuality(self.quality)
|
||||
logger.log(u"any,best = " + str(anyQualities) + " " + str(bestQualities) + " and found " + str(quality),
|
||||
initialQualities, archiveQualities = Quality.splitQuality(self.quality)
|
||||
allQualities = list(set(initialQualities + archiveQualities))
|
||||
logger.log(u"initial + archive = (" + ",".join([Quality.qualityStrings[qual] for qual in initialQualities]) + ") + (" + ",".join([Quality.qualityStrings[qual] for qual in archiveQualities]) + ") and found " + Quality.qualityStrings[quality],
|
||||
logger.DEBUG)
|
||||
|
||||
if quality not in anyQualities + bestQualities:
|
||||
if quality not in allQualities:
|
||||
logger.log(u"Don't want this quality, ignoring found episode", logger.DEBUG)
|
||||
return False
|
||||
|
||||
|
@ -1270,9 +1271,9 @@ class TVShow(object):
|
|||
return False
|
||||
|
||||
# if it's one of these then we want it as long as it's in our allowed initial qualities
|
||||
if quality in anyQualities + bestQualities:
|
||||
if epStatus in (WANTED, UNAIRED, SKIPPED):
|
||||
logger.log(u"Existing episode status is wanted/unaired/skipped, getting found episode", logger.DEBUG)
|
||||
if quality in allQualities:
|
||||
if epStatus in (WANTED, UNAIRED, SKIPPED, FAILED):
|
||||
logger.log(u"Existing episode status is wanted/unaired/skipped/failed, getting found episode", logger.DEBUG)
|
||||
return True
|
||||
elif manualSearch:
|
||||
logger.log(
|
||||
|
@ -1284,9 +1285,15 @@ class TVShow(object):
|
|||
logger.DEBUG)
|
||||
|
||||
curStatus, curQuality = Quality.splitCompositeStatus(epStatus)
|
||||
downloadedStatusList = (DOWNLOADED, SNATCHED, SNATCHED_PROPER, SNATCHED_BEST)
|
||||
# special case: already downloaded quality is not in any of the wanted Qualities
|
||||
if curStatus in downloadedStatusList and curQuality not in allQualities:
|
||||
wantedQualities = allQualities
|
||||
else:
|
||||
wantedQualities = archiveQualities
|
||||
|
||||
# if we are re-downloading then we only want it if it's in our bestQualities list and better than what we have
|
||||
if curStatus in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.SNATCHED_BEST and quality in bestQualities and quality > curQuality:
|
||||
# if we are re-downloading then we only want it if it's in our archiveQualities list and better than what we have
|
||||
if curStatus in downloadedStatusList and quality in wantedQualities and quality > curQuality:
|
||||
logger.log(u"Episode already exists but the found episode has better quality, getting found episode",
|
||||
logger.DEBUG)
|
||||
return True
|
||||
|
@ -1767,7 +1774,7 @@ class TVEpisode(object):
|
|||
|
||||
# if it hasn't aired yet set the status to UNAIRED
|
||||
if self.airdate >= datetime.date.today() and self.status in [SKIPPED, UNAIRED, UNKNOWN, WANTED]:
|
||||
logger.log(u"Episode airs in the future, marking it " + str(UNAIRED), logger.DEBUG)
|
||||
logger.log(u"Episode airs in the future, marking it " + statusStrings[UNAIRED], logger.DEBUG)
|
||||
self.status = UNAIRED
|
||||
|
||||
# if there's no airdate then set it to skipped (and respect ignored)
|
||||
|
|
|
@ -1618,7 +1618,7 @@ class Home(MainHandler):
|
|||
msg += '<ul>'
|
||||
|
||||
for season, segment in segments.items():
|
||||
cur_failed_queue_item = search_queue.FailedQueueItem(showObj, [segment])
|
||||
cur_failed_queue_item = search_queue.FailedQueueItem(showObj, segment)
|
||||
sickbeard.searchQueueScheduler.action.add_item(cur_failed_queue_item) # @UndefinedVariable
|
||||
|
||||
msg += '<li>Season ' + str(season) + '</li>'
|
||||
|
@ -1793,12 +1793,21 @@ class Home(MainHandler):
|
|||
searchstatus = 'finished'
|
||||
else:
|
||||
searchstatus = 'searching'
|
||||
episodes.append({'episode': searchThread.segment.episode,
|
||||
'episodeindexid': searchThread.segment.indexerid,
|
||||
'season' : searchThread.segment.season,
|
||||
'searchstatus' : searchstatus,
|
||||
'status' : statusStrings[searchThread.segment.status],
|
||||
'quality': self.getQualityClass(searchThread.segment)})
|
||||
if isinstance(searchThread, sickbeard.search_queue.ManualSearchQueueItem):
|
||||
episodes.append({'episode': searchThread.segment.episode,
|
||||
'episodeindexid': searchThread.segment.indexerid,
|
||||
'season' : searchThread.segment.season,
|
||||
'searchstatus' : searchstatus,
|
||||
'status' : statusStrings[searchThread.segment.status],
|
||||
'quality': self.getQualityClass(searchThread.segment)})
|
||||
else:
|
||||
for epObj in searchThread.segment:
|
||||
episodes.append({'episode': epObj.episode,
|
||||
'episodeindexid': epObj.indexerid,
|
||||
'season' : epObj.season,
|
||||
'searchstatus' : searchstatus,
|
||||
'status' : statusStrings[epObj.status],
|
||||
'quality': self.getQualityClass(epObj)})
|
||||
|
||||
if finishedManualSearchThreadItems:
|
||||
for searchThread in finishedManualSearchThreadItems:
|
||||
|
@ -3558,7 +3567,7 @@ class ConfigSearch(Config):
|
|||
def saveSearch(self, use_nzbs=None, use_torrents=None, nzb_dir=None, sab_username=None, sab_password=None,
|
||||
sab_apikey=None, sab_category=None, sab_host=None, nzbget_username=None, nzbget_password=None,
|
||||
nzbget_category=None, nzbget_priority=None, nzbget_host=None, nzbget_use_https=None,
|
||||
backlog_days=None, backlog_frequency=None, recentsearch_frequency=None,
|
||||
backlog_days=None, backlog_frequency=None, search_unaired=None, recentsearch_frequency=None,
|
||||
nzb_method=None, torrent_method=None, usenet_retention=None,
|
||||
download_propers=None, check_propers_interval=None, allow_high_priority=None,
|
||||
torrent_dir=None, torrent_username=None, torrent_password=None, torrent_host=None,
|
||||
|
@ -3591,6 +3600,8 @@ class ConfigSearch(Config):
|
|||
sickbeard.DOWNLOAD_PROPERS = config.checkbox_to_value(download_propers)
|
||||
sickbeard.CHECK_PROPERS_INTERVAL = check_propers_interval
|
||||
|
||||
sickbeard.SEARCH_UNAIRED = config.checkbox_to_value(search_unaired)
|
||||
|
||||
sickbeard.ALLOW_HIGH_PRIORITY = config.checkbox_to_value(allow_high_priority)
|
||||
|
||||
sickbeard.SAB_USERNAME = sab_username
|
||||
|
|
|
@ -22,6 +22,7 @@ class QualityTests(unittest.TestCase):
|
|||
self.assertEqual(common.Quality.SDTV, common.Quality.nameQuality("Test.Show.S01E02.TVRip.x264-GROUP"))
|
||||
self.assertEqual(common.Quality.SDTV, common.Quality.nameQuality("Test.Show.S01E02.WEBRip.XViD-GROUP"))
|
||||
self.assertEqual(common.Quality.SDTV, common.Quality.nameQuality("Test.Show.S01E02.WEBRip.x264-GROUP"))
|
||||
self.assertEqual(common.Quality.SDTV, common.Quality.nameQuality("Test.Show.S01E02.Web-Rip.x264.GROUP"))
|
||||
self.assertEqual(common.Quality.SDTV, common.Quality.nameQuality("Test.Show.S01E02.WEB-DL.x264-GROUP"))
|
||||
self.assertEqual(common.Quality.SDTV, common.Quality.nameQuality("Test.Show.S01E02.WEB-DL.AAC2.0.H.264-GROUP"))
|
||||
self.assertEqual(common.Quality.SDTV, common.Quality.nameQuality("Test.Show.S01E02 WEB-DL H 264-GROUP"))
|
||||
|
@ -35,6 +36,7 @@ class QualityTests(unittest.TestCase):
|
|||
self.assertEqual(common.Quality.SDDVD, common.Quality.nameQuality("Test.Show.S01E02.DVDRip.WS.XViD-GROUP"))
|
||||
self.assertEqual(common.Quality.SDDVD, common.Quality.nameQuality("Test.Show.S01E02.DVDRip.WS.DiVX-GROUP"))
|
||||
self.assertEqual(common.Quality.SDDVD, common.Quality.nameQuality("Test.Show.S01E02.DVDRip.WS.x264-GROUP"))
|
||||
self.assertEqual(common.Quality.SDDVD, common.Quality.nameQuality("Test.Show-S01E02-Test.Dvd Rip"))
|
||||
self.assertEqual(common.Quality.SDDVD, common.Quality.nameQuality("Test.Show.S01E02.BDRIP.XViD-GROUP"))
|
||||
self.assertEqual(common.Quality.SDDVD, common.Quality.nameQuality("Test.Show.S01E02.BDRIP.DiVX-GROUP"))
|
||||
self.assertEqual(common.Quality.SDDVD, common.Quality.nameQuality("Test.Show.S01E02.BDRIP.x264-GROUP"))
|
||||
|
@ -65,6 +67,10 @@ class QualityTests(unittest.TestCase):
|
|||
self.assertEqual(common.Quality.HDWEBDL, common.Quality.nameQuality("Test_Show.S01E02_720p_WEB-DL_AAC2.0_H264-GROUP"))
|
||||
self.assertEqual(common.Quality.HDWEBDL, common.Quality.nameQuality("Test.Show.S01E02.720p.WEB-DL.AAC2.0.H264-GROUP"))
|
||||
self.assertEqual(common.Quality.HDWEBDL, common.Quality.nameQuality("Test.Show.S01E02.720p.iTunes.Rip.H264.AAC-GROUP"))
|
||||
self.assertEqual(common.Quality.HDWEBDL, common.Quality.nameQuality("Test.Show.s01e02.WEBDL.720p.GROUP"))
|
||||
self.assertEqual(common.Quality.HDWEBDL, common.Quality.nameQuality("Test Show s01e02 WEBDL 720p GROUP"))
|
||||
self.assertEqual(common.Quality.HDWEBDL, common.Quality.nameQuality("Test Show S01E02 720p WEB-DL AVC-GROUP"))
|
||||
self.assertEqual(common.Quality.HDWEBDL, common.Quality.nameQuality("Test.Show.S01E02.WEB-RIP.720p.GROUP"))
|
||||
|
||||
def test_FULLHDWEBDL(self):
|
||||
self.assertEqual(common.Quality.FULLHDWEBDL, common.Quality.nameQuality("Test.Show.S01E02.1080p.WEB-DL-GROUP"))
|
||||
|
@ -74,14 +80,20 @@ class QualityTests(unittest.TestCase):
|
|||
self.assertEqual(common.Quality.FULLHDWEBDL, common.Quality.nameQuality("Test.Show.S01E02.1080p.iTunes.H.264.AAC-GROUP"))
|
||||
self.assertEqual(common.Quality.FULLHDWEBDL, common.Quality.nameQuality("Test Show S01E02 1080p iTunes H 264 AAC-GROUP"))
|
||||
self.assertEqual(common.Quality.FULLHDWEBDL, common.Quality.nameQuality("Test_Show_S01E02_1080p_iTunes_H_264_AAC-GROUP"))
|
||||
self.assertEqual(common.Quality.FULLHDWEBDL, common.Quality.nameQuality("Test.Show.s01e02.WEBDL.1080p.GROUP"))
|
||||
self.assertEqual(common.Quality.FULLHDWEBDL, common.Quality.nameQuality("Test Show s01e02 WEBDL 1080p GROUP"))
|
||||
self.assertEqual(common.Quality.FULLHDWEBDL, common.Quality.nameQuality("Test Show S01E02 1080p WEB-DL AVC-GROUP"))
|
||||
self.assertEqual(common.Quality.FULLHDWEBDL, common.Quality.nameQuality("Test.Show.S01E02.WEB-RIP.1080p.GROUP"))
|
||||
|
||||
def test_HDBLURAY(self):
|
||||
self.assertEqual(common.Quality.HDBLURAY, common.Quality.nameQuality("Test.Show.S01E02.720p.BluRay.x264-GROUP"))
|
||||
self.assertEqual(common.Quality.HDBLURAY, common.Quality.nameQuality("Test.Show.S01E02.720p.HDDVD.x264-GROUP"))
|
||||
self.assertEqual(common.Quality.HDBLURAY, common.Quality.nameQuality("Test.Show.S01E02.720p.Blu-ray.x264-GROUP"))
|
||||
|
||||
def test_FULLHDBLURAY(self):
|
||||
self.assertEqual(common.Quality.FULLHDBLURAY, common.Quality.nameQuality("Test.Show.S01E02.1080p.BluRay.x264-GROUP"))
|
||||
self.assertEqual(common.Quality.FULLHDBLURAY, common.Quality.nameQuality("Test.Show.S01E02.1080p.HDDVD.x264-GROUP"))
|
||||
self.assertEqual(common.Quality.FULLHDBLURAY, common.Quality.nameQuality("Test.Show.S01E02.1080p.Blu-ray.x264-GROUP"))
|
||||
|
||||
def test_UNKNOWN(self):
|
||||
self.assertEqual(common.Quality.UNKNOWN, common.Quality.nameQuality("Test.Show.S01E02-SiCKBEARD"))
|
||||
|
|
Loading…
Reference in a new issue