diff --git a/data/images/scn-no.gif b/data/images/scn-no.gif new file mode 100644 index 0000000000000000000000000000000000000000..d85c844f693dcc63e26e96a0fce8d1e22035b326 Binary files /dev/null and b/data/images/scn-no.gif differ diff --git a/data/images/scn.gif b/data/images/scn.gif new file mode 100644 index 0000000000000000000000000000000000000000..f345d2147a013cfdd542443447be220ac9ce3ebc Binary files /dev/null and b/data/images/scn.gif differ diff --git a/data/interfaces/default/displayShow.tmpl b/data/interfaces/default/displayShow.tmpl index 6d80153187262e90aa9ac8cd9b32974f2aad9f7b..d9461bfab80a9392fd28a407470b72a18219eaf7 100644 --- a/data/interfaces/default/displayShow.tmpl +++ b/data/interfaces/default/displayShow.tmpl @@ -293,13 +293,17 @@ #end if #if int($epResult["season"]) != $curSeason: - <tr><td colspan="9" style="height: 0px; padding:0; margin:0;"><a name="season-$epResult["season"]"></a></td></tr> + <tr><td colspan="#if $showSceneNumberColum then "10" else "9"#" style="height: 0px; padding:0; margin:0;"><a name="season-$epResult["season"]"></a></td></tr> <tr class="seasonheader" id="season-$epResult["season"]" > - <td colspan="9"> + <td colspan="#if $showSceneNumberColum then "10" else "9"#"> <h2>#if int($epResult["season"]) == 0 then "Specials" else "Season "+str($epResult["season"])#</h2> </td> </tr> - <tr id="season-$epResult["season"]-cols"><th width="1%"><input type="checkbox" class="seasonCheck" id="$epResult["season"]" /></th><th>Episode</th><th>Name</th><th class="nowrap">Airdate</th><th>Filename</th><th>Audio</th>#if $sickbeard.USE_SUBTITLES and $show.subtitles then "<th>Subs</th>" else ""#<th>Status</th><th>Search</th><th>Hist</th></tr> + <tr id="season-$epResult["season"]-cols"><th width="1%"><input type="checkbox" class="seasonCheck" id="$epResult["season"]" /> + #if $showSceneNumberColum + <th>XEM</th> + #end if + </th><th>Episode</th><th>Name</th><th class="nowrap">Airdate</th><th>Filename</th><th>Audio</th>#if $sickbeard.USE_SUBTITLES and $show.subtitles then "<th>Subs</th>" else ""#<th>Status</th><th>Search</th><th>Hist</th></tr> #set $curSeason = int($epResult["season"]) #end if @@ -311,6 +315,15 @@ <input type="checkbox" class="epCheck" id="<%=str(epResult["season"])+'x'+str(epResult["episode"])%>" name="<%=str(epResult["season"]) +"x"+str(epResult["episode"]) %>" /> #end if </td> + #if $showSceneNumberColum + <td align="center"> + #if isinstance($epResult["scene_season"], int) and isinstance($epResult["scene_episode"], int) + <img src="$sbRoot/images/scn.gif" alt="Y" width="16" height="16" title="Scene number $epResult["scene_season"] x $epResult["scene_episode"]"/> + #else + <img src="$sbRoot/images/scn-no.gif" alt="N" width="16" height="16" title="No scene number" /> + #end if + </td> + #end if <td align="center">$epResult["episode"]</td> <td class="title"> #if $epResult["description"] != "" and $epResult["description"] != None: diff --git a/lib/dateutil/zoneinfo/zoneinfo-2013g.tar.gz b/lib/dateutil/zoneinfo/zoneinfo-2013g.tar.gz deleted file mode 100644 index a3bce5b9d668a864ecc7d6299eae3ca83d596e63..0000000000000000000000000000000000000000 Binary files a/lib/dateutil/zoneinfo/zoneinfo-2013g.tar.gz and /dev/null differ diff --git a/lib/dateutil/zoneinfo/zoneinfo-2013h.tar.gz b/lib/dateutil/zoneinfo/zoneinfo-2013h.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..53303b1a83fdf2b72777d266cf953cdc4111438e Binary files /dev/null and b/lib/dateutil/zoneinfo/zoneinfo-2013h.tar.gz differ diff --git a/sickbeard/databases/cache_db.py b/sickbeard/databases/cache_db.py index 5675ab8b745db0f04689d8cd8f9c22cd03e96948..97a71c495e92dd3e756c45714dbd838fa2cc8f75 100644 --- a/sickbeard/databases/cache_db.py +++ b/sickbeard/databases/cache_db.py @@ -55,4 +55,10 @@ class AddNetworkTimezones(AddSceneNameCache): return self.hasTable("network_timezones") def execute(self): - self.connection.action("CREATE TABLE network_timezones (network_name TEXT PRIMARY KEY, timezone TEXT)") \ No newline at end of file + self.connection.action("CREATE TABLE network_timezones (network_name TEXT PRIMARY KEY, timezone TEXT)") + +class AddSceneExceptionsSeasons(AddNetworkTimezones): + def test(self): + return self.hasColumn("scene_exceptions", "season") + def execute(self): + self.addColumn("scene_exceptions", "season", "NUMERIC", -1) diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py index 83ce8c644dae5c06e0ec3ff2a6277f1a480345ee..7b5ab5bb16eb80ecd998fc60388ec1fca413f2e3 100644 --- a/sickbeard/databases/mainDB.py +++ b/sickbeard/databases/mainDB.py @@ -25,7 +25,7 @@ from sickbeard.providers.generic import GenericProvider from sickbeard import encodingKludge as ek from sickbeard.name_parser.parser import NameParser, InvalidNameException -MAX_DB_VERSION = 17 +MAX_DB_VERSION = 18 class MainSanityCheck(db.DBSanityCheck): @@ -744,4 +744,14 @@ class AddFrenchSearch (AddProcessedFilesTable): if self.hasColumn("tv_shows", "frenchsearch") != True: self.addColumn("tv_shows", "frenchsearch", "NUMERIC", 0) self.incDBVersion() - \ No newline at end of file +class AddSceneNumbers(FixAirByDateSetting): + + def test(self): + return self.checkDBVersion() >= 18 + + def execute(self): + + self.addColumn("tv_episodes", "scene_episode", "NUMERIC", "NULL") + self.addColumn("tv_episodes", "scene_season", "NUMERIC", "NULL") + + self.incDBVersion() diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py index e1fedefefe21b26f56b9e8dc7eb3eb772ad37274..96b49884b2caccd227d825eaf0dc7f7b1e95d47a 100755 --- a/sickbeard/postProcessor.py +++ b/sickbeard/postProcessor.py @@ -658,11 +658,22 @@ class PostProcessor(object): season = 1 if tvdb_id and season != None and episodes: + season, episodes = self._sceneToTVDBNumbers(tvdb_id, season, episodes) return (tvdb_id, season, episodes) - + season, episodes = self._sceneToTVDBNumbers(tvdb_id, season, episodes) return (tvdb_id, season, episodes) - - def _get_ep_obj(self, tvdb_id, season, episodes): + def _sceneToTVDBNumbers(self, tvdb_id, season, episodes): + + self._log(u"This looks like a scene release converting scene numbers to tvdb numbers", logger.DEBUG) + ep_obj = self._get_ep_obj(tvdb_id, season, episodes, scene=True) + if ep_obj: + newEpisodeNumbers = [] + for curEp in [ep_obj] + ep_obj.relatedEps: + newEpisodeNumbers.append(curEp.episode) + return (ep_obj.season, newEpisodeNumbers) + return (season, episodes) + + def _get_ep_obj(self, tvdb_id, season, episodes, scene=False): """ Retrieve the TVEpisode object requested. @@ -675,7 +686,9 @@ class PostProcessor(object): """ show_obj = None - + sceneMsg = "" + if scene: + sceneMsg = "(scene numbers) " self._log(u"Loading show object for tvdb_id "+str(tvdb_id), logger.DEBUG) # find the show in the showlist try: @@ -692,11 +705,11 @@ class PostProcessor(object): for cur_episode in episodes: episode = int(cur_episode) - self._log(u"Retrieving episode object for " + str(season) + "x" + str(episode), logger.DEBUG) + self._log(u"Retrieving episode object for " + sceneMsg + str(season) + "x" + str(episode), logger.DEBUG) # now that we've figured out which episode this file is just load it manually try: - curEp = show_obj.getEpisode(season, episode) + curEp = show_obj.getEpisode(season, episode, scene=scene) except exceptions.EpisodeNotFoundException, e: self._log(u"Unable to create episode: "+ex(e), logger.DEBUG) raise exceptions.PostProcessingFailed() @@ -704,8 +717,10 @@ class PostProcessor(object): # associate all the episodes together under a single root episode if root_ep == None: root_ep = curEp - root_ep.relatedEps = [] + if not scene: + root_ep.relatedEps = [] elif curEp not in root_ep.relatedEps: + self._log("Adding a related episode: " + str(curEp.season) + "x" + str(curEp.episode)) root_ep.relatedEps.append(curEp) return root_ep diff --git a/sickbeard/providers/binnewz/__init__.py b/sickbeard/providers/binnewz/__init__.py index af1f24267fcbadd0ceea373a9d785ee308a81a60..6058790701a9f5a861f9f479327d944e4ae1ba07 100644 --- a/sickbeard/providers/binnewz/__init__.py +++ b/sickbeard/providers/binnewz/__init__.py @@ -106,22 +106,22 @@ class BinNewzProvider(generic.NZBProvider): epidr = myDB.select("SELECT episode_id from tv_episodes where tvdbid=?", [ep_obj.tvdbid]) globepid = epidr[0][0] for showName in showNames: - strings.append("%s S%02dE%02d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%02dE%d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%dE%02d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s %dx%d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%02d E%02d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%02d E%d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%d E%02d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%02dEp%02d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%02dEp%d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%dEp%02d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%02d Ep%02d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%02d Ep%d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%d Ep%02d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%02d Ep %02d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%02d Ep %d" % (showName, ep_obj.season, ep_obj.episode)) - strings.append("%s S%d Ep %02d" % (showName, ep_obj.season, ep_obj.episode)) + strings.append("%s S%02dE%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%02dE%d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%dE%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s %dx%d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%02d E%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%02d E%d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%d E%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%02dEp%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%02dEp%d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%dEp%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%02d Ep%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%02d Ep%d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%d Ep%02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%02d Ep %02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%02d Ep %d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) + strings.append("%s S%d Ep %02d" % (showName, ep_obj.scene_season, ep_obj.scene_episode)) return strings def _get_title_and_url(self, item): @@ -144,7 +144,7 @@ class BinNewzProvider(generic.NZBProvider): if searchString is None: return [] logger.log("BinNewz : Searching for " + searchString, logger.DEBUG) - data = self.buildUrl(searchString, show.quality) + data = self.buildUrl(searchString.replace('!',''), show.quality) try: soup = BeautifulSoup(urllib2.urlopen("http://www.binnews.in/_bin/search2.php", urllib.urlencode(data, True))) diff --git a/sickbeard/providers/cpasbien.py b/sickbeard/providers/cpasbien.py index 483542e92aaf23de078f1ff4ea5719e7edd2ca55..cc1c38fe4e590afbe78a0084617b1c4a9bb302f0 100644 --- a/sickbeard/providers/cpasbien.py +++ b/sickbeard/providers/cpasbien.py @@ -60,8 +60,8 @@ class CpasbienProvider(generic.TorrentProvider): showNames = show_name_helpers.allPossibleShowNames(ep_obj.show) for showName in showNames: - strings.append("%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode) ) - strings.append("%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ) ) + strings.append("%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode) ) + strings.append("%s %dx%d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode ) ) return strings @@ -76,7 +76,7 @@ class CpasbienProvider(generic.TorrentProvider): results = [] searchUrl = self.url + '/recherche/' - data = urllib.urlencode({'champ_recherche': searchString}) + data = urllib.urlencode({'champ_recherche': searchString.replace('!','')}) req = urllib2.Request(searchUrl, data, headers={'User-Agent' : "Mozilla/5.0"}) try: soup = BeautifulSoup( urllib2.urlopen(req) ) diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py index 84d7dd19bd64486c924e1fffd2897befb86864eb..babcadba620a678b30d9c691287dd45ca82b0264 100644 --- a/sickbeard/providers/generic.py +++ b/sickbeard/providers/generic.py @@ -262,10 +262,11 @@ class GenericProvider: if parse_result.air_date != episode.airdate: logger.log("Episode "+title+" didn't air on "+str(episode.airdate)+", skipping it", logger.DEBUG) continue - elif parse_result.season_number != episode.season or episode.episode not in parse_result.episode_numbers: - logger.log("Episode "+title+" isn't "+str(episode.season)+"x"+str(episode.episode)+", skipping it", logger.DEBUG) + elif parse_result.season_number != episode.scene_season or episode.scene_episode not in parse_result.episode_numbers: + logger.log("Episode "+title+" isn't "+str(episode.scene_season)+"x"+str(episode.scene_episode)+", skipping it", logger.DEBUG) continue + quality = self.getQuality(item) if not episode.show.wantEpisode(episode.season, episode.episode, quality, manualSearch): diff --git a/sickbeard/providers/gks.py b/sickbeard/providers/gks.py index 45762f800dfbc43ccb4a871ba3a81f0617a0fbe8..adea259264a823c7d8dbc41b99f4c4a5248331f1 100644 --- a/sickbeard/providers/gks.py +++ b/sickbeard/providers/gks.py @@ -52,12 +52,15 @@ class GksProvider(generic.TorrentProvider): else: if audio_lang == "en": results.append( urllib.urlencode( {'q': searchString, 'category' : 22, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" ) + results.append( urllib.urlencode( {'q': searchString, 'category' : 21, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" ) if sickbeard.USE_SUBTITLES : results.append( urllib.urlencode( {'q': searchString, 'category' : 11, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" ) results.append( urllib.urlencode( {'q': searchString, 'category' : 13, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" ) + results.append( urllib.urlencode( {'q': searchString, 'category' : 13, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" ) elif audio_lang == "fr": results.append( urllib.urlencode( {'q': searchString, 'category' : 12, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" ) results.append( urllib.urlencode( {'q': searchString, 'category' : 14, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" ) + results.append( urllib.urlencode( {'q': searchString, 'category' : 21, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" ) else: results.append( urllib.urlencode( {'q': searchString, 'ak' : sickbeard.GKS_KEY} ) + "&order=desc&sort=normal&exact" ) return results @@ -84,13 +87,13 @@ class GksProvider(generic.TorrentProvider): lang='fr' else: lang=ep_obj.show.audio_lang - for result in self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), lang) : + for result in self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode), lang) : results.append(result) return results def _doSearch(self, searchString, show=None, season=None, french=None): results = [] - searchUrl = self.url+'rdirect.php?type=search&'+searchString + searchUrl = self.url+'rdirect.php?type=search&'+searchString.replace('!','') logger.log(u"Search URL: " + searchUrl, logger.DEBUG) data = self.getURL(searchUrl) diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py index f57d6f53890e6c80a90b90302febfa5b7cae1b20..8a40b10a11be0a6ba45ea6314ed1e8eaaf611a36 100644 --- a/sickbeard/providers/kat.py +++ b/sickbeard/providers/kat.py @@ -84,7 +84,7 @@ class KATProvider(generic.TorrentProvider): return params global lang lang = show.audio_lang - params['show_name'] = helpers.sanitizeSceneName(show.name).replace('.',' ').encode('utf-8') + params['show_name'] = helpers.sanitizeSceneName(show.name).replace('.',' ').replace('!','').encode('utf-8') if season != None: params['season'] = season @@ -100,13 +100,13 @@ class KATProvider(generic.TorrentProvider): if not ep_obj: return [params] - params['show_name'] = helpers.sanitizeSceneName(ep_obj.show.name).replace('.',' ').encode('utf-8') + params['show_name'] = helpers.sanitizeSceneName(ep_obj.show.name).replace('.',' ').replace('!','').encode('utf-8') if ep_obj.show.air_by_date: params['date'] = str(ep_obj.airdate) else: - params['season'] = ep_obj.season - params['episode'] = ep_obj.episode + params['season'] = ep_obj.scene_season + params['episode'] = ep_obj.scene_episode to_return = [params] diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py index 378266a1f1c0a3f8d105d8ac88a5c662857a61a8..bb80e5588956d90fc736b71231f1f974cb43b42f 100644 --- a/sickbeard/providers/newznab.py +++ b/sickbeard/providers/newznab.py @@ -140,8 +140,8 @@ class NewznabProvider(generic.NZBProvider): params['ep'] = date_str.partition('-')[2].replace('-', '/') else: - params['season'] = ep_obj.season - params['ep'] = ep_obj.episode + params['season'] = ep_obj.scene_season + params['ep'] = ep_obj.scene_episode to_return = [params] @@ -176,7 +176,7 @@ class NewznabProvider(generic.NZBProvider): return parse_result.audio_langs def _doGeneralSearch(self, search_string): - return self._doSearch({'q': search_string}) + return self._doSearch({'q': search_string.replace('!','')}) def _checkAuthFromData(self, data): diff --git a/sickbeard/providers/piratebay/__init__.py b/sickbeard/providers/piratebay/__init__.py index 35ffe0d9d1d5ad4b287ab1a578b6d2bb7eeb62da..288acd2fdc9bfb2ab8d5a979bb97734ff823b3fd 100644 --- a/sickbeard/providers/piratebay/__init__.py +++ b/sickbeard/providers/piratebay/__init__.py @@ -190,9 +190,9 @@ class ThePirateBayProvider(generic.TorrentProvider): else: for show_name in set(show_name_helpers.allPossibleShowNames(ep_obj.show)): ep_string = show_name_helpers.sanitizeSceneName(show_name) +' '+ \ - sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.season, 'episodenumber': ep_obj.episode} +'|'+\ - sickbeard.config.naming_ep_type[0] % {'seasonnumber': ep_obj.season, 'episodenumber': ep_obj.episode} +'|'+\ - sickbeard.config.naming_ep_type[3] % {'seasonnumber': ep_obj.season, 'episodenumber': ep_obj.episode} \ + sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season, 'episodenumber': ep_obj.scene_episode} +'|'+\ + sickbeard.config.naming_ep_type[0] % {'seasonnumber': ep_obj.scene_season, 'episodenumber': ep_obj.scene_episode} +'|'+\ + sickbeard.config.naming_ep_type[3] % {'seasonnumber': ep_obj.scene_season, 'episodenumber': ep_obj.scene_episode} \ search_string['Episode'].append(ep_string) @@ -206,7 +206,7 @@ class ThePirateBayProvider(generic.TorrentProvider): for mode in search_params.keys(): for search_string in search_params[mode]: - searchURL = self.proxy._buildURL(self.searchurl %(urllib.quote(search_string.encode("utf-8")))) + searchURL = self.proxy._buildURL(self.searchurl %(urllib.quote(search_string.replace('!','').encode("utf-8")))) logger.log(u"Search string: " + searchURL, logger.DEBUG) diff --git a/sickbeard/providers/t411.py b/sickbeard/providers/t411.py index b443c136828c35622fd71da58e50c10615e47c8f..d2c9c7f74d12598878c8f685ec2d50e66725e8f1 100644 --- a/sickbeard/providers/t411.py +++ b/sickbeard/providers/t411.py @@ -84,19 +84,19 @@ class T411Provider(generic.TorrentProvider): showNames = list(set(showNam)) results = [] for showName in showNames: - results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 433, french )) - if (int(ep_obj.season) < 31 and int(ep_obj.episode) < 61): - results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 433, french)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.episode), 'term[45][]': self.seasonValue(ep_obj.season)})) + results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode), ep_obj.show.audio_lang, 433, french )) + if (int(ep_obj.scene_season) < 31 and int(ep_obj.scene_episode) < 61): + results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 433, french)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.scene_episode), 'term[45][]': self.seasonValue(ep_obj.scene_season)})) #results.append( self.getSearchParams( "%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang , 433 )) MAY RETURN 1x12 WHEN SEARCHING 1x1 - results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 433, french )) - results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 637, french )) - if (int(ep_obj.season) < 31 and int(ep_obj.episode) < 61): - results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 637, french)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.episode), 'term[45][]': self.seasonValue(ep_obj.season)})) + results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode ), ep_obj.show.audio_lang, 433, french )) + results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode), ep_obj.show.audio_lang, 637, french )) + if (int(ep_obj.scene_season) < 31 and int(ep_obj.scene_episode) < 61): + results.append( self.getSearchParams( showName, ep_obj.show.audio_lang, 637, french)+ "&" + urllib.urlencode({'term[46][]': self.episodeValue(ep_obj.scene_episode), 'term[45][]': self.seasonValue(ep_obj.scene_season)})) #results.append( self.getSearchParams( "%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 637 )) - results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 637, french )) - results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.season, ep_obj.episode), ep_obj.show.audio_lang, 634, french)) + results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode ), ep_obj.show.audio_lang, 637, french )) + results.append( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode), ep_obj.show.audio_lang, 634, french)) #results.append( self.getSearchParams( "%s %dx%d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 634 )) - results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.season, ep_obj.episode ), ep_obj.show.audio_lang, 634, french )) + results.append( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode ), ep_obj.show.audio_lang, 634, french )) return results def _get_title_and_url(self, item): @@ -116,7 +116,7 @@ class T411Provider(generic.TorrentProvider): self._doLogin( sickbeard.T411_USERNAME, sickbeard.T411_PASSWORD ) results = [] - searchUrl = self.url + '/torrents/search/?' + searchString + searchUrl = self.url + '/torrents/search/?' + searchString.replace('!','') logger.log(u"Search string: " + searchUrl, logger.DEBUG) r = self.opener.open( searchUrl ) diff --git a/sickbeard/scene_exceptions.py b/sickbeard/scene_exceptions.py index e94d57772493b9df0ac37422d19937af0db5a20d..a6c48acb559c3a66ace3fbc9d9e756cd57eb39d0 100644 --- a/sickbeard/scene_exceptions.py +++ b/sickbeard/scene_exceptions.py @@ -18,19 +18,25 @@ import re import os +import urllib, urllib2, httplib import sickbeard from sickbeard import helpers from sickbeard import name_cache from sickbeard import logger from sickbeard import db +try: + import json +except ImportError: + from lib import simplejson as json +from sickbeard.exceptions import ex -def get_scene_exceptions(tvdb_id): +def get_scene_exceptions(tvdb_id, season=-1): """ Given a tvdb_id, return a list of all the scene exceptions. """ myDB = db.DBConnection("cache.db") - exceptions = myDB.select("SELECT show_name FROM scene_exceptions WHERE tvdb_id = ?", [tvdb_id]) + exceptions = myDB.select("SELECT show_name FROM scene_exceptions WHERE tvdb_id = ? and season= ?", [tvdb_id, season]) return [cur_exception["show_name"] for cur_exception in exceptions] @@ -94,34 +100,27 @@ def retrieve_exceptions(): tvdb_id = int(tvdb_id) # regex out the list of shows, taking \' into account - alias_list = [re.sub(r'\\(.)', r'\1', x) for x in re.findall(r"'(.*?)(?<!\\)',?", aliases)] + alias_list = [{re.sub(r'\\(.)', r'\1', x):-1} for x in re.findall(r"'(.*?)(?<!\\)',?", aliases)] exception_dict[tvdb_id] = alias_list - myDB = db.DBConnection("cache.db") + xem_exceptions = _xem_excpetions_fetcher() + exception_dict = dict(xem_exceptions.items() + exception_dict.items()) + + if not len(exception_dict): + logger.log("Retreived exception list is totally empty. Assuming remote server error not flushing local and stoping now") + return False - changed_exceptions = False + myDB = db.DBConnection("cache.db") + myDB.action("DELETE FROM scene_exceptions") # flush current list # write all the exceptions we got off the net into the database for cur_tvdb_id in exception_dict: - - # get a list of the existing exceptions for this ID - existing_exceptions = [x["show_name"] for x in myDB.select("SELECT * FROM scene_exceptions WHERE tvdb_id = ?", [cur_tvdb_id])] - - for cur_exception in exception_dict[cur_tvdb_id]: - # if this exception isn't already in the DB then add it - if cur_exception not in existing_exceptions: - myDB.action("INSERT INTO scene_exceptions (tvdb_id, show_name) VALUES (?,?)", [cur_tvdb_id, cur_exception]) - changed_exceptions = True - - # since this could invalidate the results of the cache we clear it out after updating - if changed_exceptions: - logger.log(u"Updated scene exceptions") - name_cache.clearCache() - f.close() - else: - logger.log(u"No scene exceptions update needed") - f.close() + for cur_exception_dict in exception_dict[cur_tvdb_id]: + cur_exception, curSeason = cur_exception_dict.items()[0] + myDB.action("INSERT INTO scene_exceptions (tvdb_id, show_name, season) VALUES (?,?,?)", [cur_tvdb_id, cur_exception, curSeason]) + name_cache.clearCache() + f.close() def update_scene_exceptions(tvdb_id, scene_exceptions): """ Given a tvdb_id, and a list of all show scene exceptions, update the db. @@ -134,4 +133,39 @@ def update_scene_exceptions(tvdb_id, scene_exceptions): for cur_exception in scene_exceptions: myDB.action("INSERT INTO scene_exceptions (tvdb_id, show_name) VALUES (?,?)", [tvdb_id, cur_exception]) - name_cache.clearCache() \ No newline at end of file + name_cache.clearCache() +def _xem_excpetions_fetcher(): + exception_dict = {} + opener = urllib2.build_opener() + + url = "http://thexem.de/map/allNames?origin=tvdb&seasonNumbers=1" + try: + f = opener.open(url) + except (EOFError, IOError), e: + logger.log(u"Unable to connect to XEM. Is thexem.de down ?" + ex(e), logger.ERROR) + return exception_dict + except httplib.InvalidURL, e: + logger.log(u"Invalid XEM host. Is thexem.de down ?: " + ex(e), logger.ERROR) + return exception_dict + if not f: + logger.log(u"Empty response from " + url + ": " + ex(e), logger.ERROR) + return exception_dict + try: + xemJson = json.loads(f.read()) + except ValueError, e: + pass + + if xemJson['result'] == 'failure': + return exception_dict + + for tvdbid, names in xemJson['data'].items(): + exception_dict[int(tvdbid)] = names + + logger.log(u"xem exception dict: " + str(exception_dict), logger.DEBUG) + return exception_dict +def getSceneSeasons(tvdb_id): + """get a list of season numbers that have scene excpetions + """ + myDB = db.DBConnection("cache.db") + seasons = myDB.select("SELECT DISTINCT season FROM scene_exceptions WHERE tvdb_id = ?", [tvdb_id]) + return [cur_exception["season"] for cur_exception in seasons] diff --git a/sickbeard/show_name_helpers.py b/sickbeard/show_name_helpers.py index 9bacc303a896f46a83ebd7644bcd39058125d690..a5f6133577a08b785f0a0c6e6034aab338a265af 100644 --- a/sickbeard/show_name_helpers.py +++ b/sickbeard/show_name_helpers.py @@ -115,9 +115,9 @@ def sceneToNormalShowNames(name): return list(set(results)) -def makeSceneShowSearchStrings(show): +def makeSceneShowSearchStrings(show, season=-1): - showNames = allPossibleShowNames(show) + showNames = allPossibleShowNames(show,season=season) # scenify the names return map(sanitizeSceneName, showNames) @@ -191,15 +191,17 @@ def makeSceneSearchString (episode): if episode.show.air_by_date and episode.airdate != datetime.date.fromordinal(1): epStrings = [str(episode.airdate)] else: - epStrings = ["S%02iE%02i" % (int(episode.season), int(episode.episode)), - "%ix%02i" % (int(episode.season), int(episode.episode))] + epStrings = ["S%02iE%02i" % (int(episode.scene_season), int(episode.scene_episode)), + "%ix%02i" % (int(episode.scene_season), int(episode.scene_episode))] + + # for single-season shows just search for the show name -- if total ep count (exclude s0) is less than 11 # due to the amount of qualities and releases, it is easy to go over the 50 result limit on rss feeds otherwise if numseasons == 1 and numepisodes < 11: epStrings = [''] - showNames = set(makeSceneShowSearchStrings(episode.show)) + showNames = set(makeSceneShowSearchStrings(episode.show, episode.scene_season)) toReturn = [] @@ -209,12 +211,12 @@ def makeSceneSearchString (episode): return toReturn -def isGoodResult(name, show, log=True): +def isGoodResult(name, show, log=True, season=-1): """ Use an automatically-created regex to make sure the result actually is the show it claims to be """ - all_show_names = allPossibleShowNames(show) + all_show_names = allPossibleShowNames(show,season=season) showNames = map(sanitizeSceneName, all_show_names) + all_show_names for curName in set(showNames): @@ -235,7 +237,7 @@ def isGoodResult(name, show, log=True): logger.log(u"Provider gave result "+name+" but that doesn't seem like a valid result for "+show.name+" so I'm ignoring it") return False -def allPossibleShowNames(show): +def allPossibleShowNames(show, season=-1): """ Figures out every possible variation of the name for a particular show. Includes TVDB name, TVRage name, country codes on the end, eg. "Show Name (AU)", and any scene exception names. @@ -245,7 +247,9 @@ def allPossibleShowNames(show): Returns: a list of all the possible show names """ - showNames = [show.name] + showNames = [] + if season is -1: + showNames = [show.name] for name in get_scene_exceptions(show.tvdbid): if not name in showNames: showNames.append( name ) diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py index eb2056d1c280189b33b5842d4f1c3462e10b357c..c1ef3c4fa4e9a32f1fc53af5dfe2785e0adcaa57 100644 --- a/sickbeard/show_queue.py +++ b/sickbeard/show_queue.py @@ -365,6 +365,11 @@ class QueueItemAdd(ShowQueueItem): 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.tvdbid]) + logger.log(u"Attempting to load scene numbers", logger.DEBUG) + if self.show.loadEpisodeSceneNumbers(): + logger.log(u"loading scene numbers successfull", logger.DEBUG) + else: + logger.log(u"loading scene numbers NOT successfull or no scene numbers available", logger.DEBUG) # if they started with WANTED eps then run the backlog if self.default_status == WANTED: @@ -557,6 +562,12 @@ class QueueItemUpdate(ShowQueueItem): curEp.deleteEpisode() except exceptions.EpisodeDeletedException: pass + logger.log(u"Attempting to load scene numbers", logger.DEBUG) + if self.show.loadEpisodeSceneNumbers(): + logger.log(u"loading scene numbers successfull", logger.DEBUG) + else: + logger.log(u"loading scene numbers NOT successfull or no scene numbers available", logger.DEBUG) + # now that we've updated the DB from TVDB see if there's anything we can add from TVRage with self.show.lock: diff --git a/sickbeard/tv.py b/sickbeard/tv.py index f3764db86b43d8f4f025b0f3594bb574cdb60802..faf1539001e7968d21914f98bdb16eb29a459313 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -23,6 +23,11 @@ import datetime import threading import re import glob +try: + import json +except ImportError: + from lib import simplejson as json +import urllib2, httplib import traceback import hashlib from sickbeard import common @@ -174,27 +179,31 @@ class TVShow(object): return ep_list - def getEpisode(self, season, episode, file=None, noCreate=False): + def getEpisode(self, season, episode, file=None, noCreate=False, scene=False): #return TVEpisode(self, season, episode) - - if not season in self.episodes: - self.episodes[season] = {} - + def createCurSeasonDict(): + if not season in self.episodes: + self.episodes[season] = {} + createCurSeasonDict() ep = None - if not episode in self.episodes[season] or self.episodes[season][episode] == None: + if (not episode in self.episodes[season] or self.episodes[season][episode] == None) or scene: if noCreate: return None logger.log(str(self.tvdbid) + ": An object for episode " + str(season) + "x" + str(episode) + " didn't exist in the cache, trying to create it", logger.DEBUG) if file != None: - ep = TVEpisode(self, season, episode, file) + ep = TVEpisode(self, season, episode, file, scene) else: - ep = TVEpisode(self, season, episode) + ep = TVEpisode(self, season, episode, scene=scene) if ep != None: + if scene: # if scene mode was active we need to use the new ep season episode numbers + season = ep.season + episode = ep.episode + createCurSeasonDict() # recheck current "real" season dict self.episodes[season][episode] = ep return self.episodes[season][episode] @@ -403,6 +412,49 @@ class TVShow(object): scannedEps[season][episode] = True return scannedEps + def loadEpisodeSceneNumbers(self): + url = "http://thexem.de/map/all?id=%s&origin=tvdb&destination=scene" % self.tvdbid + logger.log("xem url: " + url, logger.DEBUG) + opener = urllib2.build_opener() + try: + f = opener.open(url) + except (EOFError, IOError), e: + logger.log(u"Unable to connect to XEM. Is thexem.de down ?" + ex(e), logger.ERROR) + return False + except httplib.InvalidURL, e: + logger.log(u"Invalid XEM host. Is thexem.de down ?: " + ex(e), logger.ERROR) + return False + if not f: + logger.log(u"Empty response from " + url + ": " + ex(e), logger.ERROR) + return False + try: + xemJson = json.loads(f.read()) + except ValueError, e: + pass + + epList = self.loadEpisodesFromDB() + for curSeason in epList: + for curEp in epList[curSeason]: + epObj = self.getEpisode(curSeason, curEp) + epObj.scene_season = None + epObj.scene_episode = None + epObj.saveToDB() + + if xemJson['result'] == 'failure': + return False + + for epNumbers in xemJson['data']: + tvdb = epNumbers['tvdb'] + scene = epNumbers['scene'] + if not tvdb['season'] in epList or not tvdb['episode'] in epList[tvdb['season']]: + logger.log(str(self.tvdbid) + ": NOT adding scene number. tvdb: " + str(tvdb) + "| scene: " + str(scene) + " we dont have a ep with this (tvdb) sxxexx", logger.WARNING) + + logger.log(str(self.tvdbid) + ": adding scene number. tvdb: " + str(tvdb) + "| scene: " + str(scene), logger.DEBUG) + curEp = self.getEpisode(tvdb['season'], tvdb['episode']) + curEp.scene_season = scene['season'] + curEp.scene_episode = scene['episode'] + curEp.saveToDB() + return True def setTVRID(self, force=False): @@ -1106,7 +1158,7 @@ def dirty_setter(attr_name): class TVEpisode(object): - def __init__(self, show, season, episode, file=""): + def __init__(self, show, season, episode, file="", scene=False): self._name = "" self._season = season @@ -1123,6 +1175,12 @@ class TVEpisode(object): self._file_size = 0 self._audio_langs = '' self._release_name = '' + self.scene = scene + self._scene_season = None + self._scene_episode = None + if self.scene: + self._scene_season = self._season + self._scene_episode = self._episode # setting any of the above sets the dirty flag self.dirty = True @@ -1132,9 +1190,9 @@ class TVEpisode(object): self.lock = threading.Lock() - self.specifyEpisode(self.season, self.episode) - self.relatedEps = [] + + self.specifyEpisode(self.season, self.episode) self.checkForMetaFiles() @@ -1154,6 +1212,20 @@ class TVEpisode(object): file_size = property(lambda self: self._file_size, dirty_setter("_file_size")) audio_langs = property(lambda self: self._audio_langs, dirty_setter("_audio_langs")) release_name = property(lambda self: self._release_name, dirty_setter("_release_name")) + scene_season = property(lambda self: self._getSceneOrTVDBSeason(), dirty_setter("_scene_season")) + scene_episode = property(lambda self: self._getSceneOrTVDBEpisode(), dirty_setter("_scene_episode")) + + def _getSceneOrTVDBSeason(self): + if self._scene_season is None: + return self.season + else: + return self._scene_season + + def _getSceneOrTVDBEpisode(self): + if self._scene_episode is None: + return self.episode + else: + return self._scene_episode def _set_location(self, new_location): logger.log(u"Setter sets location to " + new_location, logger.DEBUG) @@ -1334,6 +1406,12 @@ class TVEpisode(object): def specifyEpisode(self, season, episode): sqlResult = self.loadFromDB(season, episode) + # we need this because if the db loading is done with scene we change the acctuay ep ans season number + + # and these numbers are not valid any more and have been replaced with tvdb numbers + if sqlResult: + season = self.season + episode = self.episode if not sqlResult: # only load from NFO if we didn't load from DB @@ -1361,22 +1439,43 @@ class TVEpisode(object): def loadFromDB(self, season, episode): - logger.log(str(self.show.tvdbid) + ": Loading episode details from DB for episode " + str(season) + "x" + str(episode), logger.DEBUG) + msg = '' + if self.scene: + msg = "(mode: scene numbers)" + logger.log(str(self.show.tvdbid) + ": Loading episode details from DB for episode " + msg + " " + str(season) + "x" + str(episode), logger.DEBUG) myDB = db.DBConnection() - sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?", [self.show.tvdbid, season, episode]) + if not self.scene: + sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?", [self.show.tvdbid, season, episode]) + else: + sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE showid = ? AND scene_season = ? AND scene_episode = ?", [self.show.tvdbid, season, episode]) + + if len(sqlResults) > 1 and not self.scene: + raise exceptions.MultipleDBEpisodesException("Your DB has two records for the same episode somehow."+msg) + elif len(sqlResults) > 1 and self.scene: + first = True + for relatedEP in sqlResults: + if first: # first shal be root ep + first = False + continue + logger.log(str(self.show.tvdbid) + ": Adding a related episode because of a scene mapping with tvdb numbers " + str(relatedEP["season"]) + "x" + str(relatedEP["episode"]), logger.DEBUG) - if len(sqlResults) > 1: - raise exceptions.MultipleDBEpisodesException("Your DB has two records for the same show somehow.") + rel_ep_obj = TVEpisode(self.show, int(relatedEP["season"]), int(relatedEP["episode"])) + self.relatedEps.append(rel_ep_obj) elif len(sqlResults) == 0: - logger.log(str(self.show.tvdbid) + ": Episode " + str(self.season) + "x" + str(self.episode) + " not found in the database", logger.DEBUG) + logger.log(str(self.show.tvdbid) + ": Episode " +msg+ str(self.season) + "x" + str(self.episode) + " not found in the database", logger.DEBUG) return False else: #NAMEIT logger.log(u"AAAAA from" + str(self.season)+"x"+str(self.episode) + " -" + self.name + " to " + str(sqlResults[0]["name"])) if sqlResults[0]["name"] != None: self.name = sqlResults[0]["name"] - self.season = season - self.episode = episode + + if not self.scene: + self.season = season + self.episode = episode + else: + self.season = int(sqlResults[0]["season"]) + self.episode = int(sqlResults[0]["episode"]) self.description = sqlResults[0]["description"] if self.description == None: self.description = "" @@ -1397,6 +1496,16 @@ class TVEpisode(object): self.file_size = 0 self.tvdbid = int(sqlResults[0]["tvdbid"]) + # does one now a better way to test for NULL in the db field ? + if isinstance(sqlResults[0]["scene_season"], int): + self.scene_season = int(sqlResults[0]["scene_season"]) + + if isinstance(sqlResults[0]["scene_episode"], int): + self.scene_episode = int(sqlResults[0]["scene_episode"]) + + logger.log("Episode loading done " + msg + str(self.season) + "x" + str(self.episode), logger.DEBUG) + + self.scene = False if sqlResults[0]["audio_langs"] != None: self.audio_langs = sqlResults[0]["audio_langs"] @@ -1691,6 +1800,8 @@ class TVEpisode(object): "hastbn": self.hastbn, "status": self.status, "location": self.location, + "scene_season": self._scene_season, + "scene_episode": self._scene_episode, "audio_langs": self.audio_langs, "file_size": self.file_size, "release_name": self.release_name} diff --git a/sickbeard/tvcache.py b/sickbeard/tvcache.py index 1d6a042d640997e088528291b49b5c62b31db026..1cc6cb3a49c47d038ca895255baffe08d238f27e 100644 --- a/sickbeard/tvcache.py +++ b/sickbeard/tvcache.py @@ -26,7 +26,7 @@ from sickbeard import db from sickbeard import logger from sickbeard.common import Quality -from sickbeard import helpers, exceptions, show_name_helpers +from sickbeard import helpers, exceptions, show_name_helpers, scene_exceptions from sickbeard import name_cache from sickbeard.exceptions import ex @@ -248,17 +248,27 @@ class TVCache(): if showResult: logger.log(parse_result.series_name+" was found to be show "+showResult[1]+" ("+str(showResult[0])+") in our DB.", logger.DEBUG) tvdb_id = showResult[0] - + def regexSearch(season=-1): + if show_name_helpers.isGoodResult(name, curShow, False, season=season): + logger.log(u"Successfully matched " + name + " to " + curShow.name + " with regex", logger.DEBUG) + tvdb_id = curShow.tvdbid + tvdb_lang = curShow.lang + return True + return False # if the DB lookup fails then do a comprehensive regex search if tvdb_id == None: logger.log(u"Couldn't figure out a show name straight from the DB, trying a regex search instead", logger.DEBUG) for curShow in sickbeard.showList: - if show_name_helpers.isGoodResult(name, curShow, False): - logger.log(u"Successfully matched "+name+" to "+curShow.name+" with regex", logger.DEBUG) - tvdb_id = curShow.tvdbid - tvdb_lang = curShow.lang + if regexSearch(): break - + # if the DB lookup fails then do a comprehensive regex search on saason exceptions + if tvdb_id == None: + logger.log(u"Couldn't figure out a show name straight from the DB, trying a regex search on season exceptions", logger.DEBUG) + for curShow in sickbeard.showList: + scene_seasons = scene_exceptions.getSceneSeasons(curShow.tvdbid) + for cur_scene_season in scene_seasons: + if regexSearch(cur_scene_season): + break # if tvdb_id was anything but None (0 or a number) then if not from_cache: name_cache.addNameToCache(parse_result.series_name, tvdb_id) @@ -340,7 +350,7 @@ class TVCache(): if not episode: sqlResults = myDB.select("SELECT * FROM "+self.providerID) else: - sqlResults = myDB.select("SELECT * FROM "+self.providerID+" WHERE tvdbid = ? AND season = ? AND episodes LIKE ?", [episode.show.tvdbid, episode.season, "%|"+str(episode.episode)+"|%"]) + sqlResults = myDB.select("SELECT * FROM "+self.providerID+" WHERE tvdbid = ? AND season = ? AND episodes LIKE ?", [episode.show.tvdbid, episode.scene_season, "%|"+str(episode.scene_episode)+"|%"]) # for each cache entry for curResult in sqlResults: diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 33a00de0467c3f99001cf95bd3f40c6f5d26926a..34465fe5115bc129ee3f1e51f87e1dfb54ed0485 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -2949,13 +2949,14 @@ class Home: epCounts[Overview.GOOD] = 0 epCounts[Overview.UNAIRED] = 0 epCounts[Overview.SNATCHED] = 0 - + showSceneNumberColum = False for curResult in sqlResults: - + if not showSceneNumberColum and (isinstance(curResult["scene_season"], int) and isinstance(curResult["scene_episode"], int)): + showSceneNumberColum = True curEpCat = showObj.getOverview(int(curResult["status"])) epCats[str(curResult["season"])+"x"+str(curResult["episode"])] = curEpCat epCounts[curEpCat] += 1 - + t.showSceneNumberColum = showSceneNumberColum def titler(x): if not x: return x