mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 00:43:37 +00:00
Change only show unaired episodes on Manage/Backlog Overview and Manage/Episode Status Management where relevant.
Change display show page, can mark unaired items with a date to "Wanted" to trigger a manual active backlog search provided search setting "Unaired episodes" is enabled.
This commit is contained in:
parent
4a4afdaa01
commit
145301e275
8 changed files with 130 additions and 104 deletions
|
@ -166,6 +166,9 @@
|
|||
* Remove redundant config/general/"Allow incomplete show data"
|
||||
* Fix status reset of a snatched, downloaded, or archived episode when its date is set to never (no date) on the info
|
||||
source and there is no media file
|
||||
* Change only show unaired episodes on Manage/Backlog Overview and Manage/Episode Status Management where relevant
|
||||
* Change display show page, can mark unaired items with a date to "Wanted" to trigger a manual active backlog search
|
||||
provided search setting "Unaired episodes" is enabled
|
||||
|
||||
[develop changelog]
|
||||
* Change send nzb data to NZBGet for Anizb instead of url
|
||||
|
|
|
@ -483,7 +483,7 @@
|
|||
<tr class="#echo ($Overview.overviewStrings[$epCats[$epStr]], 'airdate-never')[$never_aired]##echo ('', ' archived')[ARCHIVED == int($epResult['status'])]# season-$curSeason seasonstyle">
|
||||
|
||||
<td class="col-checkbox">
|
||||
#if $UNAIRED != int($epResult['status']) and not $never_aired
|
||||
#if ($UNAIRED != int($epResult['status']) or $sickbeard.SEARCH_UNAIRED) and not $never_aired
|
||||
<input type="checkbox" class="epCheck" id="#echo $epStr#" name="#echo $epStr#">
|
||||
#end if
|
||||
</td>
|
||||
|
|
|
@ -175,7 +175,7 @@
|
|||
<span class="component-desc">
|
||||
<input type="checkbox" name="dvdorder" id="dvdorder"#echo ('', $html_checked)[$show.dvdorder]#>
|
||||
<p>#echo ('enable to use DVD title and episode ordering', 'disable to use TV network title, number and aired order')[$show.dvdorder]#.
|
||||
After changing this setting, a "force full update" is essential, and existing episodes must be manually renamed</p>
|
||||
After changing this setting, a "force full update" is essential, and existing episodes should be manually renamed or replaced with #echo ('DVD', 'network')[$show.dvdorder]# numbered releases</p>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -52,25 +52,29 @@
|
|||
#set $totalQual += $showCounts[$curShow.indexerid][$Overview.QUAL]
|
||||
#end for
|
||||
##
|
||||
<div class="h2footer pull-right">
|
||||
<div class="h2footer pull-right">
|
||||
<span class="listing-key wanted">Wanted: <b>$totalWanted</b></span>
|
||||
<span class="listing-key qual">Low Quality: <b>$totalQual</b></span>
|
||||
</div>
|
||||
<br/>
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
<div class="pull-left">
|
||||
Jump to Show
|
||||
#if not $totalWanted
|
||||
<h3>no shows require a <span class="grey-text">backlog search</span></h3>
|
||||
#else
|
||||
<div class="pull-left">
|
||||
Jump to Show
|
||||
<select id="pickShow" class="form-control form-control-inline input-sm">
|
||||
#for $curShow in sorted($sickbeard.showList, key = operator.attrgetter('name')):
|
||||
#for $curShow in sorted($sickbeard.showList, key = operator.attrgetter('name')):
|
||||
#if 0 != $showCounts[$curShow.indexerid][$Overview.QUAL] + $showCounts[$curShow.indexerid][$Overview.WANTED]:
|
||||
<option value="$curShow.indexerid">$curShow.name</option>
|
||||
#end if
|
||||
#end for
|
||||
#end for
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
#end if
|
||||
|
||||
<table class="sickbeardTable" border="0">
|
||||
#for $curShow in sorted($sickbeard.showList, key = operator.attrgetter('name')):
|
||||
<table class="sickbeardTable" border="0">
|
||||
#for $curShow in sorted($sickbeard.showList, key = operator.attrgetter('name')):
|
||||
##
|
||||
#if 0 == $showCounts[$curShow.indexerid][$Overview.QUAL] + $showCounts[$curShow.indexerid][$Overview.WANTED]:
|
||||
#continue
|
||||
|
@ -92,29 +96,29 @@ Jump to Show
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="seasoncols"><th>Episode</th><th class="text-left">Name</th><th class="text-nowrap">Airdate</th></tr>
|
||||
<tr class="seasoncols"><th style="width:10%">Episode</th><th class="text-left">Name</th><th class="text-nowrap">Airdate</th></tr>
|
||||
##
|
||||
#for $curResult in $showSQLResults[$curShow.indexerid]:
|
||||
#set $whichStr = $str($curResult['season']) + 'x' + $str($curResult['episode'])
|
||||
#set $whichStr = '%sx%s' % ($str($curResult['season']), $str($curResult['episode']))
|
||||
#try:
|
||||
#set $overview = $showCats[$curShow.indexerid][$whichStr]
|
||||
#except Exception
|
||||
#continue
|
||||
#end try
|
||||
##
|
||||
#if $overview not in ($Overview.QUAL, $Overview.WANTED):
|
||||
#continue
|
||||
#end if
|
||||
|
||||
#if $overview in ($Overview.QUAL, $Overview.WANTED) or ($sickbeard.SEARCH_UNAIRED and $Overview.UNAIRED == $overview and 0 < $curResult['season'])
|
||||
#
|
||||
<tr class="seasonstyle $Overview.overviewStrings[$showCats[$curShow.indexerid][$whichStr]]">
|
||||
<td>$whichStr</td>
|
||||
<td class="text-left">$curResult["name"]</td>
|
||||
<td class="text-nowrap"><div class="${fuzzydate}">#if int($curResult['airdate']) == 1 then 'never' else $sbdatetime.sbdatetime.sbfdate($sbdatetime.sbdatetime.convert_to_setting($network_timezones.parse_date_time($curResult['airdate'],$curShow.airs,$curShow.network)))#</div></td>
|
||||
<td class="text-left">$curResult['name']</td>
|
||||
<td class="text-nowrap"><div class="${fuzzydate}">#if 1 == int($curResult['airdate']) then 'never' else $sbdatetime.sbdatetime.sbfdate($sbdatetime.sbdatetime.convert_to_setting($network_timezones.parse_date_time($curResult['airdate'], $curShow.airs,$curShow.network)))#</div></td>
|
||||
</tr>
|
||||
#
|
||||
#end if
|
||||
#end for
|
||||
#end for
|
||||
#end for
|
||||
|
||||
</table>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl')
|
|
@ -35,12 +35,10 @@ from tvdb_ui import BaseUI, ConsoleUI
|
|||
from tvdb_exceptions import (tvdb_error, tvdb_shownotfound,
|
||||
tvdb_seasonnotfound, tvdb_episodenotfound, tvdb_attributenotfound)
|
||||
|
||||
|
||||
def log():
|
||||
return logging.getLogger('tvdb_api')
|
||||
from sickbeard import logger
|
||||
|
||||
|
||||
def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
|
||||
def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logr=None):
|
||||
"""Retry calling the decorated function using an exponential backoff.
|
||||
|
||||
http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/
|
||||
|
@ -56,8 +54,8 @@ def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
|
|||
:param backoff: backoff multiplier e.g. value of 2 will double the delay
|
||||
each retry
|
||||
:type backoff: int
|
||||
:param logger: logger to use. If None, print
|
||||
:type logger: logging.Logger instance
|
||||
:param logr: logger to use. If None, print
|
||||
:type logr: logging.Logger instance
|
||||
"""
|
||||
|
||||
def deco_retry(f):
|
||||
|
@ -69,9 +67,9 @@ def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
|
|||
try:
|
||||
return f(*args, **kwargs)
|
||||
except ExceptionToCheck, e:
|
||||
msg = '%s, Retrying in %d seconds...' % (str(e), mdelay)
|
||||
if logger:
|
||||
logger.warning(msg)
|
||||
msg = 'TVDB_API :: %s, Retrying in %d seconds...' % (str(e), mdelay)
|
||||
if logr:
|
||||
logger.log(msg, logger.WARNING)
|
||||
else:
|
||||
print msg
|
||||
time.sleep(mdelay)
|
||||
|
@ -518,6 +516,9 @@ class Tvdb:
|
|||
self.config['url_seriesBanner'] = u'%(base_url)s/api/%(apikey)s/series/%%s/banners.xml' % self.config
|
||||
self.config['url_artworkPrefix'] = u'%(base_url)s/banners/%%s' % self.config
|
||||
|
||||
def log(self, msg, log_level=logger.DEBUG):
|
||||
logger.log('TVDB_API :: %s' % (msg.replace(self.config['apikey'], '<apikey>')), logLevel=log_level)
|
||||
|
||||
@staticmethod
|
||||
def _get_temp_dir():
|
||||
"""Returns the [system temp dir]/tvdb_api-u501 (or
|
||||
|
@ -536,7 +537,7 @@ class Tvdb:
|
|||
|
||||
@retry(tvdb_error)
|
||||
def _load_url(self, url, params=None, language=None):
|
||||
log().debug('Retrieving URL %s' % url)
|
||||
self.log('Retrieving URL %s' % url)
|
||||
|
||||
session = requests.session()
|
||||
|
||||
|
@ -544,7 +545,7 @@ class Tvdb:
|
|||
session = CacheControl(session, cache=caches.FileCache(self.config['cache_location']))
|
||||
|
||||
if self.config['proxy']:
|
||||
log().debug('Using proxy for URL: %s' % url)
|
||||
self.log('Using proxy for URL: %s' % url)
|
||||
session.proxies = {'http': self.config['proxy'], 'https': self.config['proxy']}
|
||||
|
||||
session.headers.update({'Accept-Encoding': 'gzip,deflate'})
|
||||
|
@ -576,7 +577,7 @@ class Tvdb:
|
|||
if 'application/zip' in resp.headers.get('Content-Type', ''):
|
||||
try:
|
||||
# TODO: The zip contains actors.xml and banners.xml, which are currently ignored [GH-20]
|
||||
log().debug('We recived a zip file unpacking now ...')
|
||||
self.log('We received a zip file unpacking now ...')
|
||||
zipdata = StringIO.StringIO()
|
||||
zipdata.write(resp.content)
|
||||
myzipfile = zipfile.ZipFile(zipdata)
|
||||
|
@ -642,7 +643,7 @@ class Tvdb:
|
|||
and returns the result list
|
||||
"""
|
||||
series = series.encode('utf-8')
|
||||
log().debug('Searching for show %s' % series)
|
||||
self.log('Searching for show %s' % series)
|
||||
self.config['params_get_series']['seriesname'] = series
|
||||
|
||||
try:
|
||||
|
@ -666,19 +667,19 @@ class Tvdb:
|
|||
all_series = [all_series]
|
||||
|
||||
if 0 == len(all_series):
|
||||
log().debug('Series result returned zero')
|
||||
self.log('Series result returned zero')
|
||||
raise tvdb_shownotfound('Show-name search returned zero results (cannot find show on TVDB)')
|
||||
|
||||
if None is not self.config['custom_ui']:
|
||||
log().debug('Using custom UI %s' % (repr(self.config['custom_ui'])))
|
||||
self.log('Using custom UI %s' % (repr(self.config['custom_ui'])))
|
||||
custom_ui = self.config['custom_ui']
|
||||
ui = custom_ui(config=self.config)
|
||||
else:
|
||||
if not self.config['interactive']:
|
||||
log().debug('Auto-selecting first search result using BaseUI')
|
||||
self.log('Auto-selecting first search result using BaseUI')
|
||||
ui = BaseUI(config=self.config)
|
||||
else:
|
||||
log().debug('Interactively selecting show using ConsoleUI')
|
||||
self.log('Interactively selecting show using ConsoleUI')
|
||||
ui = ConsoleUI(config=self.config)
|
||||
|
||||
return ui.selectSeries(all_series)
|
||||
|
@ -701,7 +702,7 @@ class Tvdb:
|
|||
|
||||
This interface will be improved in future versions.
|
||||
"""
|
||||
log().debug('Getting season banners for %s' % sid)
|
||||
self.log('Getting season banners for %s' % sid)
|
||||
banners_et = self._getetsrc(self.config['url_seriesBanner'] % sid)
|
||||
banners = {}
|
||||
|
||||
|
@ -729,7 +730,7 @@ class Tvdb:
|
|||
for k, v in banners[btype][btype2][bid].items():
|
||||
if k.endswith('path'):
|
||||
new_key = '_%s' % k
|
||||
log().debug('Transforming %s to %s' % (k, new_key))
|
||||
self.log('Transforming %s to %s' % (k, new_key))
|
||||
new_url = self.config['url_artworkPrefix'] % v
|
||||
banners[btype][btype2][bid][new_key] = new_url
|
||||
except:
|
||||
|
@ -761,7 +762,7 @@ class Tvdb:
|
|||
Any key starting with an underscore has been processed (not the raw
|
||||
data from the XML)
|
||||
"""
|
||||
log().debug('Getting actors for %s' % sid)
|
||||
self.log('Getting actors for %s' % sid)
|
||||
actors_et = self._getetsrc(self.config['url_actorsInfo'] % sid)
|
||||
|
||||
cur_actors = Actors()
|
||||
|
@ -789,16 +790,16 @@ class Tvdb:
|
|||
"""
|
||||
|
||||
if None is self.config['language']:
|
||||
log().debug('Config language is none, using show language')
|
||||
self.log('Config language is none, using show language')
|
||||
if None is language:
|
||||
raise tvdb_error('config[\'language\'] was None, this should not happen')
|
||||
get_show_in_language = language
|
||||
else:
|
||||
log().debug('Configured language %s override show language of %s' % (self.config['language'], language))
|
||||
self.log('Configured language %s override show language of %s' % (self.config['language'], language))
|
||||
get_show_in_language = self.config['language']
|
||||
|
||||
# Parse show information
|
||||
log().debug('Getting all series data for %s' % sid)
|
||||
self.log('Getting all series data for %s' % sid)
|
||||
url = (self.config['url_seriesInfo'] % (sid, language), self.config['url_epInfo%s' % ('', '_zip')[self.config['useZip']]] % (sid, language))[get_ep_info]
|
||||
show_data = self._getetsrc(url, language=get_show_in_language)
|
||||
|
||||
|
@ -825,7 +826,7 @@ class Tvdb:
|
|||
self._parse_actors(sid)
|
||||
|
||||
# Parse episode data
|
||||
log().debug('Getting all episodes of %s' % sid)
|
||||
self.log('Getting all episodes of %s' % sid)
|
||||
|
||||
if 'Episode' not in show_data:
|
||||
return False
|
||||
|
@ -834,10 +835,10 @@ class Tvdb:
|
|||
if not isinstance(episodes, list):
|
||||
episodes = [episodes]
|
||||
|
||||
dvd_order = {'dvd': [], 'network': []}
|
||||
for cur_ep in episodes:
|
||||
if self.config['dvdorder']:
|
||||
log().debug('Using DVD ordering.')
|
||||
use_dvd = None is not cur_ep['DVD_season'] and None is not cur_ep['DVD_episodenumber']
|
||||
use_dvd = cur_ep['DVD_season'] not in (None, '') and cur_ep['DVD_episodenumber'] not in (None, '')
|
||||
else:
|
||||
use_dvd = False
|
||||
|
||||
|
@ -847,14 +848,17 @@ class Tvdb:
|
|||
elem_seasnum, elem_epno = cur_ep['SeasonNumber'], cur_ep['EpisodeNumber']
|
||||
|
||||
if None is elem_seasnum or None is elem_epno:
|
||||
log().warning('An episode has incomplete season/episode number (season: %r, episode: %r)' % (
|
||||
elem_seasnum, elem_epno))
|
||||
self.log('An episode has incomplete season/episode number (season: %r, episode: %r)' % (
|
||||
elem_seasnum, elem_epno), logger.WARNING)
|
||||
continue # Skip to next episode
|
||||
|
||||
# float() is because https://github.com/dbr/tvnamer/issues/95 - should probably be fixed in TVDB data
|
||||
seas_no = int(float(elem_seasnum))
|
||||
ep_no = int(float(elem_epno))
|
||||
|
||||
if self.config['dvdorder']:
|
||||
dvd_order[('network', 'dvd')[use_dvd]] += ['S%02dE%02d' % (seas_no, ep_no)]
|
||||
|
||||
for k, v in cur_ep.items():
|
||||
k = k.lower()
|
||||
|
||||
|
@ -866,6 +870,15 @@ class Tvdb:
|
|||
|
||||
self._set_item(sid, seas_no, ep_no, k, v)
|
||||
|
||||
if self.config['dvdorder']:
|
||||
num_dvd, num_network = [len(dvd_order[x]) for x in 'dvd', 'network']
|
||||
num_all = num_dvd + num_network
|
||||
if num_all:
|
||||
self.log('Of %s episodes, %s use the DVD order, and %s use the network aired order' % (
|
||||
num_all, num_dvd, num_network))
|
||||
for ep_numbers in [', '.join(dvd_order['dvd'][i:i + 5]) for i in xrange(0, num_dvd, 5)]:
|
||||
self.log('Using DVD order: %s' % ep_numbers)
|
||||
|
||||
return True
|
||||
|
||||
def _name_to_sid(self, name):
|
||||
|
@ -874,10 +887,10 @@ class Tvdb:
|
|||
the correct SID.
|
||||
"""
|
||||
if name in self.corrections:
|
||||
log().debug('Correcting %s to %s' % (name, self.corrections[name]))
|
||||
self.log('Correcting %s to %s' % (name, self.corrections[name]))
|
||||
return self.corrections[name]
|
||||
else:
|
||||
log().debug('Getting show %s' % name)
|
||||
self.log('Getting show %s' % name)
|
||||
selected_series = self._get_series(name)
|
||||
if isinstance(selected_series, dict):
|
||||
selected_series = [selected_series]
|
||||
|
|
|
@ -743,7 +743,7 @@ class TorrentProvider(object, GenericProvider):
|
|||
@property
|
||||
def url(self):
|
||||
if None is self._url or (hasattr(self, 'url_tmpl') and not self.urls):
|
||||
self._url = self._valid_home()
|
||||
self._url = self._valid_home(False)
|
||||
self._valid_url()
|
||||
return self._url
|
||||
|
||||
|
@ -873,7 +873,7 @@ class TorrentProvider(object, GenericProvider):
|
|||
return data and re.search(r'(?sim)<input[^<]+name="password"', data) and \
|
||||
re.search(r'(?sim)<input[^<]+name="username"', data)
|
||||
|
||||
def _valid_home(self):
|
||||
def _valid_home(self, attempt_fetch=True):
|
||||
"""
|
||||
:return: signature verified home url else None if validation fail
|
||||
"""
|
||||
|
@ -910,7 +910,7 @@ class TorrentProvider(object, GenericProvider):
|
|||
|
||||
logger.log('Failed to identify a "%s" page with %s %s (local network issue, site down, or ISP blocked) ' %
|
||||
(self.name, len(url_list), ('URL', 'different URLs')[1 < len(url_list)]) +
|
||||
'Suggest; 1) Disable "%s" 2) Use a proxy/VPN' % self.get_id(),
|
||||
(attempt_fetch and ('Suggest; 1) Disable "%s" 2) Use a proxy/VPN' % self.get_id()) or ''),
|
||||
(logger.WARNING, logger.ERROR)[self.enabled])
|
||||
self.urls = {}
|
||||
sickbeard.PROVIDER_HOMES[self.get_id()] = ('site down', int(time.time()) + (5 * 60))
|
||||
|
|
|
@ -1871,7 +1871,7 @@ class Home(MainHandler):
|
|||
|
||||
with epObj.lock:
|
||||
# don't let them mess up UNAIRED episodes
|
||||
if epObj.status == UNAIRED:
|
||||
if epObj.status == UNAIRED and not sickbeard.SEARCH_UNAIRED:
|
||||
logger.log(u'Refusing to change status of ' + curEp + ' because it is UNAIRED', logger.ERROR)
|
||||
continue
|
||||
|
||||
|
@ -3392,13 +3392,15 @@ class Manage(MainHandler):
|
|||
|
||||
result = {}
|
||||
for cur_result in cur_show_results:
|
||||
if not sickbeard.SEARCH_UNAIRED and 1000 > cur_result['airdate']:
|
||||
continue
|
||||
cur_season = int(cur_result['season'])
|
||||
cur_episode = int(cur_result['episode'])
|
||||
|
||||
if cur_season not in result:
|
||||
result[cur_season] = {}
|
||||
|
||||
result[cur_season][cur_episode] = {'name': cur_result['name'], 'airdate_never': (True, False)[1000 < int(cur_result['airdate'])]}
|
||||
result[cur_season][cur_episode] = {'name': cur_result['name'], 'airdate_never': 1000 > int(cur_result['airdate'])}
|
||||
|
||||
return json.dumps(result)
|
||||
|
||||
|
@ -3438,6 +3440,8 @@ class Manage(MainHandler):
|
|||
show_names = {}
|
||||
sorted_show_ids = []
|
||||
for cur_status_result in status_results:
|
||||
if not sickbeard.SEARCH_UNAIRED and 1000 > cur_status_result['airdate']:
|
||||
continue
|
||||
cur_indexer_id = int(cur_status_result['indexer_id'])
|
||||
if cur_indexer_id not in ep_counts:
|
||||
ep_counts[cur_indexer_id] = 1
|
||||
|
@ -3640,6 +3644,8 @@ class Manage(MainHandler):
|
|||
[curShow.indexerid])
|
||||
|
||||
for curResult in sqlResults:
|
||||
if not sickbeard.SEARCH_UNAIRED and 1 == curResult['airdate']:
|
||||
continue
|
||||
curEpCat = curShow.getOverview(int(curResult['status']))
|
||||
if curEpCat:
|
||||
epCats[str(curResult['season']) + 'x' + str(curResult['episode'])] = curEpCat
|
||||
|
|
Loading…
Reference in a new issue