Add option "Search for unaired episodes" to config/Search Settings

* Change reduce time to search recent result list by searching only once for a best result
* Fix replacing episodes that have a lower quality than what is selected in the initial and archive quality list
* Fix to include episodes marked Failed in the recent and backlog search processes
* Fix display of search status for an alternative release after episode is manually set to "Failed" on the Display Show page
* Change handle more varieties of media quality
* Change to prevent another scheduled search when one of the same type is already running
This commit is contained in:
Prinz23 2015-04-05 20:12:15 +02:00
parent 7cdcbaf241
commit 4ae30ab6ad
11 changed files with 146 additions and 108 deletions

View file

@ -1,9 +1,10 @@
### 0.x.x (2015-xx-xx xx:xx:xx UTC)
### 0.x.x (2015-xx-xx xx:xx:xx UTC)
* Add ToTV provider
* 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.2 (2015-04-19 06:45:00 UTC)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1614,7 +1614,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>'
@ -1789,12 +1789,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:
@ -3554,7 +3563,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,
@ -3587,6 +3596,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

View file

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