From cf35e9778c1362518a1362b293d3361b31bdad60 Mon Sep 17 00:00:00 2001 From: echel0n Date: Sun, 23 Nov 2014 01:17:37 -0800 Subject: [PATCH] Added per-show option that allows you to set the default status that gets applied to new and missing show episodes, default is SKIPPED Fixed issues for failed/manual snatches always failing to complete --- gui/slick/interfaces/default/displayShow.tmpl | 38 ++++--- gui/slick/interfaces/default/editShow.tmpl | 107 ++++++++++-------- sickbeard/databases/mainDB.py | 14 ++- sickbeard/show_queue.py | 29 +++-- sickbeard/tv.py | 17 +-- sickbeard/webserve.py | 12 +- 6 files changed, 126 insertions(+), 91 deletions(-) diff --git a/gui/slick/interfaces/default/displayShow.tmpl b/gui/slick/interfaces/default/displayShow.tmpl index 4de97971..e2715fa0 100644 --- a/gui/slick/interfaces/default/displayShow.tmpl +++ b/gui/slick/interfaces/default/displayShow.tmpl @@ -198,19 +198,6 @@
- #if $show.network and $show.airs: - - #else if $show.network: - - #else if $show.airs: - - #end if - - #if $showLoc[1]: - - #else: - - #end if #set $anyQualities, $bestQualities = $Quality.splitQuality(int($show.quality)) + #else if $show.network: + + #else if $show.airs: + + #end if + + + #if $showLoc[1]: + + #else: + #end if @@ -263,14 +265,13 @@ #end if
Originally Airs: $show.airs #if not $network_timezones.test_timeformat($show.airs) then " (invalid Timeformat) " else ""# on $show.network
Originally Airs: $show.network
Originally Airs: >$show.airs #if not $network_timezones.test_timeformat($show.airs) then " (invalid Timeformat) " else ""#
Status: $show.status
Location: $showLoc[0]
Location: $showLoc[0] (dir is missing)
Quality: #if $show.quality in $qualityPresets: @@ -222,6 +209,21 @@ #if $bestQualities: Replace with: <%=", ".join([Quality.qualityStrings[x] for x in sorted(bestQualities)])%> #end if + #end if + + #if $show.network and $show.airs: +
Originally Airs: $show.airs #if not $network_timezones.test_timeformat($show.airs) then " (invalid Timeformat) " else ""# on $show.network
Originally Airs: $show.network
Originally Airs: >$show.airs #if not $network_timezones.test_timeformat($show.airs) then " (invalid Timeformat) " else ""#
Show Status: $show.status
Default EP Status: $statusStrings[$show.default_ep_status]
Location: $showLoc[0]
Location: $showLoc[0] (dir is missing)
Scene Name:#if $show.exceptions then $exceptions_string else $show.name#
-
- -
- Change selected episodes to + +
+ Change selected episodes to:
+
+
@@ -298,7 +301,6 @@
-
diff --git a/gui/slick/interfaces/default/editShow.tmpl b/gui/slick/interfaces/default/editShow.tmpl index f87af3d4..f7f7fbc6 100644 --- a/gui/slick/interfaces/default/editShow.tmpl +++ b/gui/slick/interfaces/default/editShow.tmpl @@ -1,6 +1,7 @@ #import sickbeard #import lib.adba as adba #from sickbeard import common +#from sickbeard.common import * #from sickbeard import exceptions #from sickbeard import scene_exceptions #from sickbeard.blackandwhitelist import * @@ -63,35 +64,21 @@ -Location:
-
-Quality: -#set $qualities = $common.Quality.splitQuality(int($show.quality)) -#set global $anyQualities = $qualities[0] -#set global $bestQualities = $qualities[1] -#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_qualityChooser.tmpl") +Location:
+

-#if $anyQualities + $bestQualities -Archive on first match: -
-(check this to have the episode archived after the first best match is found from your archive quality list) -
-
-#end if - -Scene Exception: - +Scene Exception:
+
-

This will affect the episode show search on nzb and torrent provider.
This list overrides the original name, it doesn't append to it.

-
- +
+

Exceptions List

-
+
-
+

-
+

-Info Language:
-Note: This will only affect the language of the retrieved metadata file contents and episode filenames.
-This DOES NOT allow SickRage to download non-english TV episodes!
+Quality:
+#set $qualities = $common.Quality.splitQuality(int($show.quality)) +#set global $anyQualities = $qualities[0] +#set global $bestQualities = $qualities[1] +#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_qualityChooser.tmpl")
-Flatten files (no folders):

-Paused:

-Subtitles:

+Default Episode Status:
+(this will set a default status to be applied to any newly added episodes)
+
+
+ +Info Language:
+(this will only affect the language of the retrieved metadata file contents and episode filenames)
+
+
+ +Flatten files (no folders):
+Paused:
+Subtitles:
+
Scene Numbering:
-(check this if you wish to search by scene numbering, uncheck to search by indexer numbering) -

-Air by date: +(check this if you wish to search by scene numbering, uncheck to search by indexer numbering)
+
+ +Air by date:
-(check this if the show is released as Show.03.02.2010 rather than Show.S02E03) -

+(check this if the show is released as Show.03.02.2010 rather than Show.S02E03)
+
+ Sports:
-(check this if the show is a sporting or MMA event) -

+(check this if the show is a sporting or MMA event)
+
+ Anime:
-(check this if the show is released as Show.265 rather than Show.S02E03, this show is an anime) -

+(check this if the show is released as Show.265 rather than Show.S02E03, this show is an anime)
+
+ DVD Order:
(check this if you wish to use the DVD order instead of the Airing order)

-Ignored Words:
-Results with any of these words in the title will be filtered out
-Separate words with a comma, e.g. "word1,word2,word3" -

+#if $anyQualities + $bestQualities +Archive on first match: +
+(check this to have the episode archived after the first best match is found from your archive quality list)
+
+#end if -Required Words:
+Ignored Words:
+
+Results with any of these words in the title will be filtered out
+Separate words with a comma, e.g. "word1,word2,word3"
+
+ +Required Words:
+
Results without one of these words in the title will be filtered out
-Separate words with a comma, e.g. "word1,word2,word3" -

+Separate words with a comma, e.g. "word1,word2,word3"
+
#if $show.is_anime: #from sickbeard.blackandwhitelist import * diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py index 3ccf14a1..9f969c81 100644 --- a/sickbeard/databases/mainDB.py +++ b/sickbeard/databases/mainDB.py @@ -27,7 +27,7 @@ from sickbeard import encodingKludge as ek from sickbeard.name_parser.parser import NameParser, InvalidNameException, InvalidShowException MIN_DB_VERSION = 9 # oldest db version we support migrating from -MAX_DB_VERSION = 40 +MAX_DB_VERSION = 41 class MainSanityCheck(db.DBSanityCheck): def check(self): @@ -915,3 +915,15 @@ class AddVersionToTvEpisodes(AddIndexerMapping): self.addColumn("history", "version", "NUMERIC", "-1") self.incDBVersion() + +class AddDefaultEpStatusToTvShows(AddVersionToTvEpisodes): + def test(self): + return self.checkDBVersion() >= 41 + + def execute(self): + backupDatabase(41) + + logger.log(u"Adding column default_ep_status to tv_shows") + self.addColumn("tv_shows", "default_ep_status", "TEXT", "") + + self.incDBVersion() diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py index 975497d5..d0cb2be7 100644 --- a/sickbeard/show_queue.py +++ b/sickbeard/show_queue.py @@ -293,6 +293,10 @@ class QueueItemAdd(ShowQueueItem): self.show.scene = self.scene if self.scene != None else sickbeard.SCENE_DEFAULT self.show.paused = self.paused if self.paused != None else False + # set up default new/missing episode status + self.show.default_ep_status = self.default_status + logger.log(u"Setting all episodes to the specified default status: " + str(self.show.default_ep_status)) + # be smartish about this if self.show.genre and "talk show" in self.show.genre.lower(): self.show.air_by_date = 1 @@ -364,17 +368,10 @@ class QueueItemAdd(ShowQueueItem): logger.log(u"Error searching dir for episodes: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) - # if they gave a custom status then change all the eps to it - if self.default_status != SKIPPED: - logger.log(u"Setting all episodes to the specified default status: " + str(self.default_status)) - myDB = db.DBConnection() - myDB.action("UPDATE tv_episodes SET status = ? WHERE status = ? AND showid = ? AND season != 0", - [self.default_status, SKIPPED, self.show.indexerid]) - - # if they started with WANTED eps then run the backlog - if self.default_status == WANTED: + # if they set default ep status to WANTED then run the backlog to search for episodes + if self.show.default_ep_status == WANTED: logger.log(u"Launching backlog for this show since its episodes are WANTED") - sickbeard.backlogSearchScheduler.action.searchBacklog([self.show]) #@UndefinedVariable + sickbeard.backlogSearchScheduler.action.searchBacklog([self.show]) self.show.writeMetadata() self.show.updateMetadata() @@ -539,17 +536,21 @@ class QueueItemUpdate(ShowQueueItem): self.show.indexer).name + ", the show info will not be refreshed: " + ex(e), logger.ERROR) IndexerEpList = None + foundMissingEps = False if IndexerEpList == None: logger.log(u"No data returned from " + sickbeard.indexerApi( self.show.indexer).name + ", unable to update this show", logger.ERROR) else: - # for each ep we found on TVDB delete it from the DB list + # for each ep we found on the Indexer delete it from the DB list for curSeason in IndexerEpList: for curEpisode in IndexerEpList[curSeason]: logger.log(u"Removing " + str(curSeason) + "x" + str(curEpisode) + " from the DB list", logger.DEBUG) if curSeason in DBEpList and curEpisode in DBEpList[curSeason]: del DBEpList[curSeason][curEpisode] + else: + # found missing episodes + foundMissingEps = True # for the remaining episodes in the DB list just delete them from the DB for curSeason in DBEpList: @@ -562,8 +563,12 @@ class QueueItemUpdate(ShowQueueItem): except exceptions.EpisodeDeletedException: pass - sickbeard.showQueueScheduler.action.refreshShow(self.show, self.force) + # if they set default ep status to WANTED then run the backlog + if foundMissingEps and self.show.default_ep_status == WANTED: + logger.log(u"Launching backlog for this show since we found missing episodes") + sickbeard.backlogSearchScheduler.action.searchBacklog([self.show]) + sickbeard.showQueueScheduler.action.refreshShow(self.show, self.force) class QueueItemForceUpdate(QueueItemUpdate): def __init__(self, show=None): diff --git a/sickbeard/tv.py b/sickbeard/tv.py index 8076076d..032c3782 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -97,7 +97,7 @@ class TVShow(object): self._scene = 0 self._rls_ignore_words = "" self._rls_require_words = "" - + self._default_ep_status = "" self.dirty = True self._location = "" @@ -139,6 +139,7 @@ class TVShow(object): scene = property(lambda self: self._scene, dirty_setter("_scene")) rls_ignore_words = property(lambda self: self._rls_ignore_words, dirty_setter("_rls_ignore_words")) rls_require_words = property(lambda self: self._rls_require_words, dirty_setter("_rls_require_words")) + default_ep_status = property(lambda self: self._default_ep_status, dirty_setter("_default_ep_status")) @property def is_anime(self): @@ -577,7 +578,6 @@ class TVShow(object): myDB = db.DBConnection() myDB.mass_action(sql_l) - # Done updating save last update date self.last_update_indexer = datetime.date.today().toordinal() self.saveToDB() @@ -770,9 +770,11 @@ class TVShow(object): self.status = sqlResults[0]["status"] if not self.status: self.status = "" + self.airs = sqlResults[0]["airs"] if not self.airs: self.airs = "" + self.startyear = sqlResults[0]["startyear"] if not self.startyear: self.startyear = 0 @@ -825,6 +827,8 @@ class TVShow(object): self.rls_ignore_words = sqlResults[0]["rls_ignore_words"] self.rls_require_words = sqlResults[0]["rls_require_words"] + self.default_ep_status = int(sqlResults[0]["default_ep_status"]) + if not self.imdbid: self.imdbid = sqlResults[0]["imdb_id"] @@ -1156,7 +1160,8 @@ class TVShow(object): "imdb_id": self.imdbid, "last_update_indexer": self.last_update_indexer, "rls_ignore_words": self.rls_ignore_words, - "rls_require_words": self.rls_require_words + "rls_require_words": self.rls_require_words, + "default_ep_status": self.default_ep_status } myDB = db.DBConnection() @@ -1741,9 +1746,9 @@ class TVEpisode(object): if self.status == UNAIRED: self.status = WANTED - # if we somehow are still UNKNOWN then just skip it + # if we somehow are still UNKNOWN then just use the shows defined default status elif self.status == UNKNOWN: - self.status = SKIPPED + self.status = self.show.default_ep_status else: logger.log( @@ -2024,7 +2029,6 @@ class TVEpisode(object): '%SN S%0SE%E', '%SN S%SE%E', '%SN S%0SE%0E' - ] strings = [] @@ -2062,7 +2066,6 @@ class TVEpisode(object): if len(self.relatedEps) == 0: goodName = self.name - else: goodName = '' diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index d56d755e..efd29866 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -3833,7 +3833,7 @@ class Home(MainHandler): flatten_folders=None, paused=None, directCall=False, air_by_date=None, sports=None, dvdorder=None, indexerLang=None, subtitles=None, archive_firstmatch=None, rls_ignore_words=None, rls_require_words=None, anime=None, blackWords=None, whiteWords=None, blacklist=None, whitelist=None, - scene=None): + scene=None, defaultEpStatus=None): if show is None: errString = "Invalid show ID: " + str(show) @@ -4007,6 +4007,7 @@ class Home(MainHandler): showObj.dvdorder = dvdorder showObj.rls_ignore_words = rls_ignore_words.strip() showObj.rls_require_words = rls_require_words.strip() + showObj.default_ep_status = defaultEpStatus # if we change location clear the db of episodes, change it, write to db, and rescan if os.path.normpath(showObj._location) != os.path.normpath(location): @@ -4405,8 +4406,6 @@ class Home(MainHandler): sickbeard.searchQueueScheduler.action.add_item(ep_queue_item) # @UndefinedVariable - if ep_queue_item.success: - return returnManualSearchResult(ep_queue_item) if not ep_queue_item.started and ep_queue_item.success is None: return json.dumps({'result': 'success'}) #I Actually want to call it queued, because the search hasnt been started yet! if ep_queue_item.started and ep_queue_item.success is None: @@ -4422,10 +4421,11 @@ class Home(MainHandler): episodes = [] currentManualSearchThreadsQueued = [] currentManualSearchThreadActive = [] - finishedManualSearchThreadItems= [] + finishedManualSearchThreadItems = [] # Queued Searches currentManualSearchThreadsQueued = sickbeard.searchQueueScheduler.action.get_all_ep_from_queue(show) + # Running Searches if (sickbeard.searchQueueScheduler.action.is_manualsearch_in_progress()): currentManualSearchThreadActive = sickbeard.searchQueueScheduler.action.currentItem @@ -4492,8 +4492,6 @@ class Home(MainHandler): return json.dumps({'show': show, 'episodes' : episodes}) - #return json.dumps() - def getQualityClass(self, ep_obj): # return the correct json value @@ -4617,8 +4615,6 @@ class Home(MainHandler): ep_queue_item = search_queue.FailedQueueItem(ep_obj.show, [ep_obj]) sickbeard.searchQueueScheduler.action.add_item(ep_queue_item) # @UndefinedVariable - if ep_queue_item.success: - return returnManualSearchResult(ep_queue_item) if not ep_queue_item.started and ep_queue_item.success is None: return json.dumps({'result': 'success'}) #I Actually want to call it queued, because the search hasnt been started yet! if ep_queue_item.started and ep_queue_item.success is None: