Merge pull request #262 from JackDandy/feature/AddSetWantedOnAddShow

Add option to the third step of "Add Show" to set episodes as wanted fro...
This commit is contained in:
JackDandy 2015-03-13 18:22:43 +00:00
commit d9d8bcdb0b
7 changed files with 131 additions and 67 deletions

View file

@ -10,6 +10,8 @@
* Change startup code cleanup and PEP8
* Change authentication credentials to display more securely on config pages
* Add a "Use as default home page" selector to General Config/Interface/User Interface
* Add option to the third step of "Add Show" to set episodes as wanted from the first and latest season, this triggers
a backlog search on those episodes after the show is added
* Change to improve the integrity of the already post processed video checker
* Add Kodi notifier and metadata
* Add priority, device, and sound support to Pushover notifier (port from midgetspy/sickbeard)

View file

@ -75,6 +75,8 @@
<div id="tableDiv"></div>
<br />
<p>If you tried to add a show, arrived here and can't see the folder, then that show may already be in your show list.</p>
<input class="btn btn-primary" type="button" value="Submit" id="submitShowDirs" />
</form>

View file

@ -26,6 +26,28 @@
#set global $bestQualities = $qualities[1]
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_qualityChooser.tmpl')
</div>
#try:
#if True == $enable_default_wanted:
<div class="field-pair alt">
<span class="component-title">From season 1 forward, set</span>
<span class="component-desc">
<label for="wanted-begin" style="padding-bottom:10px">
<input type="number" name="wanted-begin" id="wanted-begin" value="$sickbeard.WANTED_BEGIN_DEFAULT" class="form-control input-sm input75">
<span>episodes as wanted (10 ... 0, and where -1 is whole first season)</span>
</label>
</span>
<span class="component-title">From latest going back, set</span>
<span class="component-desc">
<label for="wanted-latest">
<input type="number" name="wanted-latest" id="wanted-latest" value="$sickbeard.WANTED_LATEST_DEFAULT" class="form-control input-sm input75">
<span>episodes as wanted (10 ... 0, and where -1 is whole latest season)</span>
</label>
</span>
</div>
#end if
#except (NameError, NotFound):
#pass
#end try
<div class="field-pair alt">
<label for="flatten_folders">
@ -86,4 +108,4 @@
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_blackwhitelist.tmpl')
#else
<input type="hidden" name="anime" id="anime" value="0" />
#end if
#end if

View file

@ -1,35 +1,39 @@
$(document).ready(function () {
$(document).ready(function(){
$('#saveDefaultsButton').click(function () {
var anyQualArray = [];
var bestQualArray = [];
$('#anyQualities option:selected').each(function (i, d) {
anyQualArray.push($(d).val());
});
$('#bestQualities option:selected').each(function (i, d) {
bestQualArray.push($(d).val());
});
$('#saveDefaultsButton').click(function() {
var anyQualArray = [], bestQualArray = [];
$.get(sbRoot + '/config/general/saveAddShowDefaults', {
defaultStatus: $('#statusSelect').val(),
anyQualities: anyQualArray.join(','),
bestQualities: bestQualArray.join(','),
defaultFlattenFolders: $('#flatten_folders').prop('checked'),
subtitles: $('#subtitles').prop('checked'),
anime: $('#anime').prop('checked'),
scene: $('#scene').prop('checked')
});
$('#anyQualities option:selected').each(function(i, d) {
anyQualArray.push($(d).val());
});
$('#bestQualities option:selected').each(function(i, d) {
bestQualArray.push($(d).val());
});
$(this).attr('disabled', true);
new PNotify({
title: 'Saved Defaults',
text: 'Your "add show" defaults have been set to your current selections.',
shadow: false
});
});
$.get(sbRoot + '/config/general/saveAddShowDefaults', {
default_status: $('#statusSelect').val(),
any_qualities: anyQualArray.join(','),
best_qualities: bestQualArray.join(','),
default_wanted_begin: $('#wanted-begin').val(),
default_wanted_latest: $('#wanted-latest').val(),
default_flatten_folders: $('#flatten_folders').prop('checked'),
default_scene: $('#scene').prop('checked'),
default_subtitles: $('#subtitles').prop('checked'),
default_anime: $('#anime').prop('checked')
});
$('#statusSelect, #qualityPreset, #flatten_folders, #anyQualities, #bestQualities, #subtitles, #scene, #anime').change(function () {
$('#saveDefaultsButton').attr('disabled', false);
});
new PNotify({
title: 'Saving Defaults',
text: 'Saving your "add show" defaults.',
shadow: false
});
$(this).attr('disabled', true);
});
$('#statusSelect, #qualityPreset, #anyQualities, #bestQualities, #wanted-begin, #wanted-latest,'
+ ' #flatten_folders, #scene, #subtitles, #anime').change(function() {
$('#saveDefaultsButton').attr('disabled', false);
});
});

View file

@ -166,6 +166,8 @@ METADATA_KODI = None
QUALITY_DEFAULT = None
STATUS_DEFAULT = None
WANTED_BEGIN_DEFAULT = None
WANTED_LATEST_DEFAULT = None
FLATTEN_FOLDERS_DEFAULT = False
SUBTITLES_DEFAULT = False
INDEXER_DEFAULT = None
@ -494,7 +496,7 @@ def initialize(consoleLogging=True):
PLEX_SERVER_HOST, PLEX_HOST, PLEX_USERNAME, PLEX_PASSWORD, DEFAULT_BACKLOG_FREQUENCY, MIN_BACKLOG_FREQUENCY, BACKLOG_STARTUP, SKIP_REMOVED_FILES, \
showUpdateScheduler, __INITIALIZED__, LAUNCH_BROWSER, TRASH_REMOVE_SHOW, TRASH_ROTATE_LOGS, HOME_SEARCH_FOCUS, SORT_ARTICLE, showList, loadingShowList, UPDATE_SHOWS_ON_START, SHOW_UPDATE_HOUR, \
NEWZNAB_DATA, NZBS, NZBS_UID, NZBS_HASH, INDEXER_DEFAULT, INDEXER_TIMEOUT, USENET_RETENTION, TORRENT_DIR, \
QUALITY_DEFAULT, FLATTEN_FOLDERS_DEFAULT, SUBTITLES_DEFAULT, STATUS_DEFAULT, RECENTSEARCH_STARTUP, \
QUALITY_DEFAULT, FLATTEN_FOLDERS_DEFAULT, SUBTITLES_DEFAULT, STATUS_DEFAULT, WANTED_BEGIN_DEFAULT, WANTED_LATEST_DEFAULT, RECENTSEARCH_STARTUP, \
GROWL_NOTIFY_ONSNATCH, GROWL_NOTIFY_ONDOWNLOAD, GROWL_NOTIFY_ONSUBTITLEDOWNLOAD, TWITTER_NOTIFY_ONSNATCH, TWITTER_NOTIFY_ONDOWNLOAD, TWITTER_NOTIFY_ONSUBTITLEDOWNLOAD, \
USE_GROWL, GROWL_HOST, GROWL_PASSWORD, USE_PROWL, PROWL_NOTIFY_ONSNATCH, PROWL_NOTIFY_ONDOWNLOAD, PROWL_NOTIFY_ONSUBTITLEDOWNLOAD, PROWL_API, PROWL_PRIORITY, PROG_DIR, \
USE_PYTIVO, PYTIVO_NOTIFY_ONSNATCH, PYTIVO_NOTIFY_ONDOWNLOAD, PYTIVO_NOTIFY_ONSUBTITLEDOWNLOAD, PYTIVO_UPDATE_LIBRARY, PYTIVO_HOST, PYTIVO_SHARE_NAME, PYTIVO_TIVO_NAME, \
@ -652,6 +654,8 @@ def initialize(consoleLogging=True):
QUALITY_DEFAULT = check_setting_int(CFG, 'General', 'quality_default', SD)
STATUS_DEFAULT = check_setting_int(CFG, 'General', 'status_default', SKIPPED)
WANTED_BEGIN_DEFAULT = check_setting_int(CFG, 'General', 'wanted_begin_default', 0)
WANTED_LATEST_DEFAULT = check_setting_int(CFG, 'General', 'wanted_latest_default', 0)
VERSION_NOTIFY = bool(check_setting_int(CFG, 'General', 'version_notify', 1))
AUTO_UPDATE = bool(check_setting_int(CFG, 'General', 'auto_update', 0))
NOTIFY_ON_UPDATE = bool(check_setting_int(CFG, 'General', 'notify_on_update', 1))
@ -1440,6 +1444,8 @@ def save_config():
new_config['General']['skip_removed_files'] = int(SKIP_REMOVED_FILES)
new_config['General']['quality_default'] = int(QUALITY_DEFAULT)
new_config['General']['status_default'] = int(STATUS_DEFAULT)
new_config['General']['wanted_begin_default'] = int(WANTED_BEGIN_DEFAULT)
new_config['General']['wanted_latest_default'] = int(WANTED_LATEST_DEFAULT)
new_config['General']['flatten_folders_default'] = int(FLATTEN_FOLDERS_DEFAULT)
new_config['General']['indexer_default'] = int(INDEXER_DEFAULT)
new_config['General']['indexer_timeout'] = int(INDEXER_TIMEOUT)

View file

@ -132,9 +132,11 @@ class ShowQueue(generic_queue.GenericQueue):
return queueItemObj
def addShow(self, indexer, indexer_id, showDir, default_status=None, quality=None, flatten_folders=None,
lang="en", subtitles=None, anime=None, scene=None, paused=None, blacklist=None, whitelist=None):
lang="en", subtitles=None, anime=None, scene=None, paused=None, blacklist=None, whitelist=None,
default_wanted_begin=None, default_wanted_latest=None):
queueItemObj = QueueItemAdd(indexer, indexer_id, showDir, default_status, quality, flatten_folders, lang,
subtitles, anime, scene, paused, blacklist, whitelist)
subtitles, anime, scene, paused, blacklist, whitelist,
default_wanted_begin, default_wanted_latest)
self.add_item(queueItemObj)
@ -191,12 +193,14 @@ class ShowQueueItem(generic_queue.QueueItem):
class QueueItemAdd(ShowQueueItem):
def __init__(self, indexer, indexer_id, showDir, default_status, quality, flatten_folders, lang, subtitles, anime,
scene, paused, blacklist, whitelist):
scene, paused, blacklist, whitelist, default_wanted_begin, default_wanted_latest):
self.indexer = indexer
self.indexer_id = indexer_id
self.showDir = showDir
self.default_status = default_status
self.default_wanted_begin = default_wanted_begin
self.default_wanted_latest = default_wanted_latest
self.quality = quality
self.flatten_folders = flatten_folders
self.lang = lang
@ -381,10 +385,36 @@ class QueueItemAdd(ShowQueueItem):
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:
logger.log(u"Launching backlog for this show since its episodes are WANTED")
# if they gave a number to start or number to end as wanted, then change those eps to it
def get_wanted_sql(wanted_max, sql_vars):
actual = 0
if wanted_max:
my_db = db.DBConnection()
sql = "UPDATE `tv_episodes` SET status=%s" % WANTED\
+ " WHERE indexerid IN "\
+ "(SELECT t1.indexerid FROM `tv_episodes` t1 JOIN "\
+ "(SELECT %s(season),showid,season FROM `tv_episodes` WHERE '%s'=showid" % (sql_vars[0], self.show.indexerid)\
+ " AND '0'<season ORDER BY season,episode) AS t2 ON t2.showid=t1.showid AND t2.season = t1.season"\
+ " ORDER BY episode %s%s)" % (sql_vars[1], (' LIMIT %s' % wanted_max, '')[-1 == wanted_max])\
+ ' AND status NOT IN (%s)' % ','.join([str(x) for x in sickbeard.common.Quality.DOWNLOADED + [sickbeard.common.UNAIRED]])
my_db.action(sql)
result = my_db.select("SELECT changes() as last FROM `tv_episodes`")
for cur_result in result:
actual = cur_result['last']
break
return actual
items_wanted = get_wanted_sql(self.default_wanted_begin, ['MIN', 'ASC'])
items_wanted += get_wanted_sql(self.default_wanted_latest, ['MAX', 'DESC'])
msg = ' the specified show into ' + self.showDir
# if started with WANTED eps then run the backlog
if WANTED == self.default_status or items_wanted:
logger.log(u'Launching backlog for this show since episodes are WANTED')
sickbeard.backlogSearchScheduler.action.searchBacklog([self.show]) #@UndefinedVariable
ui.notifications.message('Show added/search', 'Adding and searching for episodes of' + msg)
else:
ui.notifications.message('Show added', 'Adding' + msg)
self.show.writeMetadata()
self.show.updateMetadata()
@ -403,7 +433,7 @@ class QueueItemAdd(ShowQueueItem):
# Load XEM data to DB for show
sickbeard.scene_numbering.xem_refresh(self.show.indexerid, self.show.indexer, force=True)
# check if show has XEM mapping so we can determin if searches should go by scene numbering or indexer numbering.
# check if show has XEM mapping so we can determine if searches should go by scene numbering or indexer numbering.
if not self.scene and sickbeard.scene_numbering.get_xem_numbering_for_show(self.show.indexerid,
self.show.indexer):
self.show.scene = 1

View file

@ -2102,6 +2102,7 @@ class NewHomeAddShows(Home):
t = PageTemplate(headers=self.request.headers, file='home_newShow.tmpl')
t.submenu = self.HomeMenu()
t.enable_anime_options = True
t.enable_default_wanted = True
indexer, show_dir, indexer_id, show_name = self.split_extra_show(show_to_add)
@ -2253,7 +2254,7 @@ class NewHomeAddShows(Home):
def addNewShow(self, whichSeries=None, indexerLang='en', rootDir=None, defaultStatus=None,
anyQualities=None, bestQualities=None, flatten_folders=None, subtitles=None,
fullShowPath=None, other_shows=None, skipShow=None, providedIndexer=None, anime=None,
scene=None, blacklist=None, whitelist=None):
scene=None, blacklist=None, whitelist=None, default_wanted_begin=None, default_wanted_latest=None):
"""
Receive tvdb id, dir, and other options and create a show from them. If extra show dirs are
provided then it forwards back to newShow, if not it goes to /home.
@ -2315,18 +2316,17 @@ class NewHomeAddShows(Home):
# blanket policy - if the dir exists you should have used 'add existing show' numbnuts
if ek.ek(os.path.isdir, show_dir) and not fullShowPath:
ui.notifications.error('Unable to add show', 'Folder ' + show_dir + ' exists already')
ui.notifications.error('Unable to add show', u'Found existing folder: ' + show_dir)
return self.redirect('/home/addShows/existingShows/')
# don't create show dir if config says not to
if sickbeard.ADD_SHOWS_WO_DIR:
logger.log(u'Skipping initial creation of ' + show_dir + ' due to config.ini setting')
logger.log(u'Skipping initial creation due to config.ini setting (add_shows_wo_dir)')
else:
dir_exists = helpers.makeDir(show_dir)
if not dir_exists:
logger.log(u'Unable to create the folder ' + show_dir + ", can't add the show", logger.ERROR)
ui.notifications.error('Unable to add show',
'Unable to create the folder ' + show_dir + ", can't add the show")
logger.log(u'Unable to add show because can\'t create folder: ' + show_dir, logger.ERROR)
ui.notifications.error('Unable to add show', u'Can\'t create folder: ' + show_dir)
return self.redirect('/home/')
else:
@ -2353,11 +2353,15 @@ class NewHomeAddShows(Home):
bestQualities = [bestQualities]
newQuality = Quality.combineQualities(map(int, anyQualities), map(int, bestQualities))
default_wanted_begin = config.minimax(default_wanted_begin, 0, -1, 10)
default_wanted_latest = config.minimax(default_wanted_latest, 0, -1, 10)
# add the show
sickbeard.showQueueScheduler.action.addShow(indexer, indexer_id, show_dir, int(defaultStatus), newQuality,
flatten_folders, indexerLang, subtitles, anime,
scene, None, blacklist, whitelist) # @UndefinedVariable
ui.notifications.message('Show added', 'Adding the specified show into ' + show_dir)
scene, None, blacklist, whitelist,
default_wanted_begin, default_wanted_latest) # @UndefinedVariable
# ui.notifications.message('Show added', 'Adding the specified show into ' + show_dir)
return finishAddShow()
@ -2424,6 +2428,8 @@ class NewHomeAddShows(Home):
# add the show
sickbeard.showQueueScheduler.action.addShow(indexer, indexer_id, show_dir,
default_status=sickbeard.STATUS_DEFAULT,
default_wanted_begin=sickbeard.WANTED_BEGIN_DEFAULT,
default_wanted_latest=sickbeard.WANTED_LATEST_DEFAULT,
quality=sickbeard.QUALITY_DEFAULT,
flatten_folders=sickbeard.FLATTEN_FOLDERS_DEFAULT,
subtitles=sickbeard.SUBTITLES_DEFAULT,
@ -3300,29 +3306,21 @@ class ConfigGeneral(Config):
def saveRootDirs(self, rootDirString=None):
sickbeard.ROOT_DIRS = rootDirString
def saveAddShowDefaults(self, defaultStatus, anyQualities, bestQualities, defaultFlattenFolders, subtitles=False,
anime=False, scene=False):
def saveAddShowDefaults(self, default_status, any_qualities='', best_qualities='', default_wanted_begin=None,
default_wanted_latest=None, default_flatten_folders=False, default_scene=False,
default_subtitles=False, default_anime=False):
if anyQualities:
anyQualities = anyQualities.split(',')
else:
anyQualities = []
any_qualities = ([], any_qualities.split(','))[any(any_qualities)]
best_qualities = ([], best_qualities.split(','))[any(best_qualities)]
if bestQualities:
bestQualities = bestQualities.split(',')
else:
bestQualities = []
newQuality = Quality.combineQualities(map(int, anyQualities), map(int, bestQualities))
sickbeard.STATUS_DEFAULT = int(defaultStatus)
sickbeard.QUALITY_DEFAULT = int(newQuality)
sickbeard.FLATTEN_FOLDERS_DEFAULT = config.checkbox_to_value(defaultFlattenFolders)
sickbeard.SUBTITLES_DEFAULT = config.checkbox_to_value(subtitles)
sickbeard.ANIME_DEFAULT = config.checkbox_to_value(anime)
sickbeard.SCENE_DEFAULT = config.checkbox_to_value(scene)
sickbeard.STATUS_DEFAULT = int(default_status)
sickbeard.QUALITY_DEFAULT = int(Quality.combineQualities(map(int, any_qualities), map(int, best_qualities)))
sickbeard.WANTED_BEGIN_DEFAULT = config.minimax(default_wanted_begin, 0, -1, 10)
sickbeard.WANTED_LATEST_DEFAULT = config.minimax(default_wanted_latest, 0, -1, 10)
sickbeard.FLATTEN_FOLDERS_DEFAULT = config.checkbox_to_value(default_flatten_folders)
sickbeard.SCENE_DEFAULT = config.checkbox_to_value(default_scene)
sickbeard.SUBTITLES_DEFAULT = config.checkbox_to_value(default_subtitles)
sickbeard.ANIME_DEFAULT = config.checkbox_to_value(default_anime)
sickbeard.save_config()