1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-08-13 16:53:54 -04:00

Merge branch 'dev'

This commit is contained in:
echel0n 2014-08-31 12:57:14 -07:00
commit fc9e451f15
53 changed files with 2205 additions and 1789 deletions

View File

@ -26,6 +26,7 @@
#end if
<script type="text/javascript" src="$sbRoot/js/config.js?$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/rootDirs.js?$sbPID"></script>
<div id="config">
<div id="config-content">
@ -167,6 +168,14 @@
</label>
</div>
<div class="field-pair">
<label class="clearfix">
<span class="component-title">Show Root Directories</span>
<span class="component-desc">Set root directories for where you want your shows to be.</span>
#include $os.path.join($sickbeard.PROG_DIR, "gui/slick/interfaces/default/inc_rootDirs.tmpl")
</label>
</div>
<input type="submit" class="btn config_submitter" value="Save Changes" />
</fieldset>
</div><!-- /component-group1 //-->

View File

@ -156,14 +156,24 @@ var show_nzb_providers = #if $sickbeard.USE_NZBS then "true" else "false"#;
</div>
#end if
#if $hasattr($curNewznabProvider, 'backlog_only'):
#if $hasattr($curNewznabProvider, 'enable_daily'):
<div class="field-pair">
<input type="checkbox" name="${curNewznabProvider.getID()}_backlog_only" id="${curNewznabProvider.getID()}_backlog_only" #if $curNewznabProvider.backlog_only then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="${curNewznabProvider.getID()}_backlog_only">
<span class="component-title">Backlog Only</span>
<input type="checkbox" name="${curNewznabProvider.getID()}_enable_daily" id="${curNewznabProvider.getID()}_enable_daily" #if $curNewznabProvider.enable_daily then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="${curNewznabProvider.getID()}_enable_daily">
<span class="component-title">Enable Daily Searches</span>
<span class="component-desc">
Sets the provider to only be used for<br>
backlog searches.</span>
Enables daily searches</span>
</label>
</div>
#end if
#if $hasattr($curNewznabProvider, 'enable_backlog'):
<div class="field-pair">
<input type="checkbox" name="${curNewznabProvider.getID()}_enable_backlog" id="${curNewznabProvider.getID()}_enable_backlog" #if $curNewznabProvider.enable_backlog then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="${curNewznabProvider.getID()}_enable_backlog">
<span class="component-title">Enable Backlog Searches</span>
<span class="component-desc">
Enables backlog searches</span>
</label>
</div>
#end if
@ -190,12 +200,12 @@ var show_nzb_providers = #if $sickbeard.USE_NZBS then "true" else "false"#;
When searching for complete seasons<br>
you can choose to have it look for season<br>
packs ONLY or choose to have it build a<br>
complete season from just single episodes.</span>
complete season from just single episodes.<br></span>
<span class="component-title"></span>
<input type="radio" name="${curNewznabProvider.getID()}_search_mode" id="${curNewznabProvider.getID()}_search_mode_sponly" value="sponly" class="radio" #if $curNewznabProvider.search_mode=="sponly" then "checked=\"checked\"" else ""# />Season Packs ONLY!<br />
<span class="component-title"></span>
<input type="radio" name="${curNewznabProvider.getID()}_search_mode" id="${curNewznabProvider.getID()}_search_mode_eponly" value="eponly" class="radio" #if $curNewznabProvider.search_mode=="eponly" then "checked=\"checked\"" else ""# />Episodes ONLY!<br />
<span class="component-title"></span>
<input type="radio" name="${curNewznabProvider.getID()}_search_mode" id="${curNewznabProvider.getID()}_search_mode_sponly" value="sponly" class="radio" #if $curNewznabProvider.search_mode=="sponly" then "checked=\"checked\"" else ""# />Season Packs ONLY!<br />
<span class="component-title"></span>
<input type="radio" name="${curNewznabProvider.getID()}_search_mode" id="${curNewznabProvider.getID()}_search_mode_eponly" value="eponly" class="radio" #if $curNewznabProvider.search_mode=="eponly" then "checked=\"checked\"" else ""# />Episodes ONLY!<br />
</span>
</label>
</div>
@ -224,14 +234,24 @@ var show_nzb_providers = #if $sickbeard.USE_NZBS then "true" else "false"#;
</div>
#end if
#if $hasattr($curNzbProvider, 'backlog_only'):
#if $hasattr($curNzbProvider, 'enable_daily'):
<div class="field-pair">
<input type="checkbox" name="${curNzbProvider.getID()}_backlog_only" id="${curNzbProvider.getID()}_backlog_only" #if $curNzbProvider.backlog_only then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="${curNzbProvider.getID()}_backlog_only">
<span class="component-title">Backlog Only</span>
<input type="checkbox" name="${curNzbProvider.getID()}_enable_daily" id="${curNzbProvider.getID()}_enable_daily" #if $curNzbProvider.enable_daily then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="${curNzbProvider.getID()}_enable_daily">
<span class="component-title">Enable Daily Searches</span>
<span class="component-desc">
Sets the provider to only be used for<br>
backlog searches.</span>
Enables daily searches</span>
</label>
</div>
#end if
#if $hasattr($curNzbProvider, 'enable_backlog'):
<div class="field-pair">
<input type="checkbox" name="${curNzbProvider.getID()}_enable_backlog" id="${curNzbProvider.getID()}_enable_backlog" #if $curNzbProvider.enable_backlog then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="${curNzbProvider.getID()}_enable_backlog">
<span class="component-title">Enable Backlog Searches</span>
<span class="component-desc">
Enables backlog searches</span>
</label>
</div>
#end if
@ -440,14 +460,24 @@ var show_nzb_providers = #if $sickbeard.USE_NZBS then "true" else "false"#;
</div>
#end if
#if $hasattr($curTorrentProvider, 'backlog_only'):
#if $hasattr($curTorrentProvider, 'enable_daily'):
<div class="field-pair">
<input type="checkbox" name="${curTorrentProvider.getID()}_backlog_only" id="${curTorrentProvider.getID()}_backlog_only" #if $curTorrentProvider.backlog_only then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="${curTorrentProvider.getID()}_backlog_only">
<span class="component-title">Backlog Only</span>
<input type="checkbox" name="${curTorrentProvider.getID()}_enable_daily" id="${curTorrentProvider.getID()}_enable_daily" #if $curTorrentProvider.enable_daily then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="${curTorrentProvider.getID()}_enable_daily">
<span class="component-title">Enable Daily Searches</span>
<span class="component-desc">
Sets the provider to only be used for<br>
backlog searches.</span>
Enables daily searches</span>
</label>
</div>
#end if
#if $hasattr($curTorrentProvider, 'enable_backlog'):
<div class="field-pair">
<input type="checkbox" name="${curTorrentProvider.getID()}_enable_backlog" id="${curTorrentProvider.getID()}_enable_backlog" #if $curTorrentProvider.enable_backlog then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="${curTorrentProvider.getID()}_enable_backlog">
<span class="component-title">Enable Backlog Searches</span>
<span class="component-desc">
Enables backlog searches</span>
</label>
</div>
#end if

View File

@ -147,6 +147,7 @@ a > i.icon-question-sign { background-image: url("$sbRoot/images/glyphicons-half
\$("#SubMenu a[href*='/home/logout/']").addClass('btn').html('<span class="ui-icon ui-icon-power pull-left"></span> Logout');
\$("#SubMenu a:contains('Edit')").addClass('btn').html('<span class="ui-icon ui-icon-pencil pull-left"></span> Edit');
\$("#SubMenu a:contains('Delete')").addClass('btn').html('<span class="ui-icon ui-icon-trash pull-left"></span> Delete');
\$("#SubMenu a:contains('Remove')").addClass('btn').html('<span class="ui-icon ui-icon-trash pull-left"></span> Remove');
\$("#SubMenu a:contains('Clear History')").addClass('btn confirm').html('<span class="ui-icon ui-icon-trash pull-left"></span> Clear History');
\$("#SubMenu a:contains('Trim History')").addClass('btn confirm').html('<span class="ui-icon ui-icon-trash pull-left"></span> Trim History');
\$("#SubMenu a[href$='/errorlogs/clearerrors/']").addClass('btn').html('<span class="ui-icon ui-icon-trash pull-left"></span> Clear Errors');

View File

@ -102,6 +102,7 @@
#end if
<!-- <th>Force Metadata Regen <input type="checkbox" class="bulkCheck" id="metadataCheck" /></th>//-->
<th width="1%">Delete<br/><input type="checkbox" class="bulkCheck" id="deleteCheck" /></th>
<th width="1%">Remove<br/><input type="checkbox" class="bulkCheck" id="removeCheck" /></th>
</tr>
</thead>
<tfoot>
@ -120,6 +121,7 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
#set $curRename_disabled = ""
#set $curSubtitle_disabled = ""
#set $curDelete_disabled = ""
#set $curRemove_disabled = ""
#if $sickbeard.showQueueScheduler.action.isBeingUpdated($curShow) or $sickbeard.showQueueScheduler.action.isInUpdateQueue($curShow):
#set $curUpdate_disabled = "disabled=\"disabled\" "
@ -141,6 +143,10 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
#set $curDelete = "disabled=\"disabled\" "
#end if
#set $curDelete = "<input type=\"checkbox\" class=\"deleteCheck\" id=\"delete-"+str($curShow.indexerid)+"\" "+$curDelete_disabled+"/>"
#if $sickbeard.showQueueScheduler.action.isBeingRenamed($curShow) or $sickbeard.showQueueScheduler.action.isInRenameQueue($curShow) or $sickbeard.showQueueScheduler.action.isInRefreshQueue($curShow):
#set $curRemove = "disabled=\"disabled\" "
#end if
#set $curRemove = "<input type=\"checkbox\" class=\"removeCheck\" id=\"remove-"+str($curShow.indexerid)+"\" "+$curRemove_disabled+"/>"
<tr>
<td align="center"><input type="checkbox" class="editCheck" id="edit-$curShow.indexerid" /></td>
@ -163,6 +169,7 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
<td align="center">$curSubtitle</td>
#end if
<td align="center">$curDelete</td>
<td align="center">$curRemove</td>
</tr>
#end for
</tbody>

View File

@ -27,6 +27,7 @@
#set $cur_index = $root_dir_list.index($cur_dir)
<div style="padding: 6px 0 3px 25px;">
<input class="btn edit_root_dir" type="button" class="edit_root_dir" id="edit_root_dir_$cur_index" value="Edit" />
<input class="btn delete_root_dir" type="button" class="delete_root_dir" id="delete_root_dir_$cur_index" value="Delete" />
$cur_dir => <span id="display_new_root_dir_$cur_index">$cur_dir</span>
</div>
<input type="hidden" name="orig_root_dir_$cur_index" value="$cur_dir" />

View File

@ -63,7 +63,7 @@ $(document).ready(function(){
$('#Torrent_username').show();
$('#Torrent_Path').show();
$('#Torrent_Ratio').show();
$('#Torrent_Seed_Time').hide();
$('#Torrent_Seed_Time').show();
$('#Torrent_High_Bandwidth').show();
$('#Torrent_Label').hide();
$('#host_desc').html('Transmission Host');

View File

@ -22,4 +22,10 @@ $(document).ready(function(){
});
$('.delete_root_dir').click(function(){
var cur_id = find_dir_index($(this).attr('id'));
$('#new_root_dir_'+cur_id).val(null);
$('#display_new_root_dir_'+cur_id).html('<b>DELETED</b>');
});
});

View File

@ -24,6 +24,7 @@ $(document).ready(function(){
var renameArr = new Array()
var subtitleArr = new Array()
var deleteArr = new Array()
var removeArr = new Array()
var metadataArr = new Array()
$('.updateCheck').each(function() {
@ -56,6 +57,12 @@ $(document).ready(function(){
}
});
$('.removeCheck').each(function() {
if (this.checked == true) {
removeArr.push($(this).attr('id').split('-')[1])
}
});
/*
$('.metadataCheck').each(function() {
if (this.checked == true) {
@ -63,10 +70,10 @@ $(document).ready(function(){
}
});
*/
if (updateArr.length+refreshArr.length+renameArr.length+subtitleArr.length+deleteArr.length+metadataArr.length == 0)
if (updateArr.length+refreshArr.length+renameArr.length+subtitleArr.length+deleteArr.length+removeArr.length+metadataArr.length == 0)
return false
url = 'massUpdate?toUpdate='+updateArr.join('|')+'&toRefresh='+refreshArr.join('|')+'&toRename='+renameArr.join('|')+'&toSubtitle='+subtitleArr.join('|')+'&toDelete='+deleteArr.join('|')+'&toMetadata='+metadataArr.join('|')
url = 'massUpdate?toUpdate='+updateArr.join('|')+'&toRefresh='+refreshArr.join('|')+'&toRename='+renameArr.join('|')+'&toSubtitle='+subtitleArr.join('|')+'&toDelete='+deleteArr.join('|')+'&toRemove='+removeArr.join('|')+'&toMetadata='+metadataArr.join('|')
window.location.href = url
@ -83,7 +90,7 @@ $(document).ready(function(){
});
});
['.editCheck', '.updateCheck', '.refreshCheck', '.renameCheck', '.deleteCheck'].forEach(function(name) {
['.editCheck', '.updateCheck', '.refreshCheck', '.renameCheck', '.deleteCheck', '.removeCheck'].forEach(function(name) {
var lastCheck = null;
$(name).click(function(event) {

View File

@ -244,23 +244,56 @@ class Connection(threading.Thread):
"""
return self.handle(PushAckCommand(nid), callback)
def notifyadd(self, aid=None, gid=None, type=None, priority=None, callback=None):
def notification(self, aid=None, gid=None, type=None, priority=None, callback=None):
"""
Add a notification
parameters:
aid - Anime id
gid - Group id
type - Type of notification: type=> 0=all, 1=new, 2=group, 3=complete
priority - low = 0, medium = 1, high = 2 (unconfirmed)
structure of parameters:
[aid={int}|gid={int}]&type={int}&priority={int}
"""
return self.handle(Notification(aid, gid, type, priority), callback)
def notifyadd(self, aid=None, gid=None, type=None, priority=None, callback=None):
"""
Add a notification
parameters:
aid - Anime id
gid - Group id
type - Type of notification: type=> 0=all, 1=new, 2=group, 3=complete
priority - low = 0, medium = 1, high = 2 (unconfirmed)
structure of parameters:
[aid={int}|gid={int}]&type={int}&priority={int}
"""
return self.handle(NotifyAddCommand(aid, gid, type, priority), callback)
def notifydel(self, aid=None, gid=None, type=None, priority=None, callback=None):
"""
Add a notification
parameters:
aid - Anime id
gid - Group id
type - Type of notification: type=> 0=all, 1=new, 2=group, 3=complete
priority - low = 0, medium = 1, high = 2 (unconfirmed)
structure of parameters:
[aid={int}|gid={int}]&type={int}&priority={int}
"""
return self.handle(NotifyDelCommand(aid, gid, type, priority), callback)
def notify(self, buddy=None, callback=None):
"""

View File

@ -99,9 +99,18 @@ class aniDBabstractObject(object):
priority - low = 0, medium = 1, high = 2 (unconfirmed)
"""
if (self.aid):
if self.aid:
self.aniDB.notifyadd(aid=self.aid, type=1, priority=1)
def del_notification(self):
"""
type - Type of notification: type=> 0=all, 1=new, 2=group, 3=complete
priority - low = 0, medium = 1, high = 2 (unconfirmed)
"""
if self.aid:
self.aniDB.notifydel(aid=self.aid, type=1, priority=1)
class Anime(aniDBabstractObject):
def __init__(self, aniDB, name=None, aid=None, tvdbid=None, paramsA=None, autoCorrectName=False, load=False):

View File

@ -103,6 +103,14 @@ class PushAckCommand(Command):
Command.__init__(self, 'PUSHACK', **parameters)
class Notification(Command):
def __init__(self, aid=None, gid=None, type=None, priority=None):
if not (aid or gid) or (aid and gid):
raise AniDBIncorrectParameterError, "You must provide aid OR gid for NOTIFICATION command"
parameters = {'aid': aid, "gid": gid, "type": type, "priority": priority}
Command.__init__(self, 'NOTIFICATION', **parameters)
class NotifyAddCommand(Command):
def __init__(self, aid=None, gid=None, type=None, priority=None):
if not (aid or gid) or (aid and gid):
@ -111,6 +119,14 @@ class NotifyAddCommand(Command):
Command.__init__(self, 'NOTIFICATIONADD', **parameters)
class NotifyDelCommand(Command):
def __init__(self, aid=None, gid=None, type=None, priority=None):
if not (aid or gid) or (aid and gid):
raise AniDBIncorrectParameterError, "You must provide aid OR gid for NOTIFICATIONDEL command"
parameters = {'aid': aid, "gid": gid, "type": type, "priority": priority}
Command.__init__(self, 'NOTIFICATIONDEL', **parameters)
class NotifyCommand(Command):
def __init__(self, buddy=None):
parameters = {'buddy': buddy}

View File

@ -15,23 +15,30 @@
# You should have received a copy of the GNU General Public License
# along with aDBa. If not, see <http://www.gnu.org/licenses/>.
class AniDBError(Exception):
pass
pass
class AniDBIncorrectParameterError(AniDBError):
pass
pass
class AniDBCommandTimeoutError(AniDBError):
pass
pass
class AniDBMustAuthError(AniDBError):
pass
pass
class AniDBPacketCorruptedError(AniDBError):
pass
pass
class AniDBBannedError(AniDBError):
pass
pass
class AniDBInternalError(AniDBError):
pass
pass

File diff suppressed because it is too large Load Diff

View File

@ -628,21 +628,10 @@ class Tvdb:
"""Loads a URL using caching, returns an ElementTree of the source
"""
try:
src = self._loadUrl(url, params=params, language=language)
src = [src[item] for item in src][0] if src else []
src = self._loadUrl(url, params=params, language=language).values()[0]
return src
except:
errormsg = "There was an error with the XML retrieved from thetvdb.com:"
if self.config['cache_enabled']:
errormsg += "\nFirst try emptying the cache folder at..\n%s" % (
self.config['cache_location']
)
errormsg += "\nIf this does not resolve the issue, please try again later. If the error persists, report a bug on"
errormsg += "\nhttp://dbr.lighthouseapp.com/projects/13342-tvdb_api/overview\n"
raise tvdb_error(errormsg)
return src
return []
def _setItem(self, sid, seas, ep, attrib, value):
"""Creates a new episode, creating Show(), Season() and
@ -692,8 +681,12 @@ class Tvdb:
series = series.encode("utf-8")
log().debug("Searching for show %s" % series)
self.config['params_getSeries']['seriesname'] = series
seriesEt = self._getetsrc(self.config['url_getSeries'], self.config['params_getSeries'])
return [seriesEt[item] for item in seriesEt][0] if seriesEt else []
try:
seriesFound = self._getetsrc(self.config['url_getSeries'], self.config['params_getSeries']).values()[0]
return seriesFound
except:
return []
def _getSeries(self, series):
"""This searches TheTVDB.com for the series name,

View File

@ -1,5 +1,5 @@
# !/usr/bin/env python2
#encoding:utf-8
# encoding:utf-8
#author:echel0n
#project:tvrage_api
#repository:http://github.com/echel0n/tvrage_api
@ -393,7 +393,6 @@ class TVRage:
except ImportError:
return os.path.join(tempfile.gettempdir(), "tvrage_api")
return os.path.join(tempfile.gettempdir(), "tvrage_api-%s" % (uid))
#@retry(tvrage_error)
@ -455,7 +454,7 @@ class TVRage:
if key == 'genre':
value = value['genre']
if not value:
value=[]
value = []
if not isinstance(value, list):
value = [value]
value = filter(None, value)
@ -470,9 +469,9 @@ class TVRage:
value = parse(value, fuzzy=True).date()
value = value.strftime("%Y-%m-%d")
#if key == 'airs_time':
# value = parse(value).time()
# value = value.strftime("%I:%M %p")
#if key == 'airs_time':
# value = parse(value).time()
# value = value.strftime("%I:%M %p")
except:
pass
@ -489,20 +488,10 @@ class TVRage:
"""
try:
src = self._loadUrl(url, params)
src = [src[item] for item in src][0] if src else []
src = self._loadUrl(url, params).values()[0]
return src
except:
errormsg = "There was an error with the XML retrieved from tvrage.com"
if self.config['cache_enabled']:
errormsg += "\nFirst try emptying the cache folder at..\n%s" % (
self.config['cache_location']
)
errormsg += "\nIf this does not resolve the issue, please try again later. If the error persists, report a bug on\n"
raise tvrage_error(errormsg)
return src
return []
def _setItem(self, sid, seas, ep, attrib, value):
"""Creates a new episode, creating Show(), Season() and
@ -557,8 +546,12 @@ class TVRage:
series = series.encode("utf-8")
log().debug("Searching for show %s" % series)
self.config['params_getSeries']['show'] = series
seriesEt = self._getetsrc(self.config['url_getSeries'], self.config['params_getSeries'])
return [seriesEt[item] for item in seriesEt][0] if seriesEt else []
try:
seriesFound = self._getetsrc(self.config['url_getSeries'], self.config['params_getSeries']).values()[0]
return seriesFound
except:
return []
def _getSeries(self, series):
"""This searches tvrage.com for the series name,
@ -632,7 +625,7 @@ class TVRage:
ep_no = int(episode['episodenumber'])
self._setItem(sid, seas_no, ep_no, 'seasonnumber', seas_no)
for k,v in episode.items():
for k, v in episode.items():
try:
k = k.lower()
if v is not None:

View File

@ -981,10 +981,16 @@ def initialize(consoleLogging=True):
curTorrentProvider.search_fallback = bool(check_setting_int(CFG, curTorrentProvider.getID().upper(),
curTorrentProvider.getID() + '_search_fallback',
0))
if hasattr(curTorrentProvider, 'backlog_only'):
curTorrentProvider.backlog_only = bool(check_setting_int(CFG, curTorrentProvider.getID().upper(),
curTorrentProvider.getID() + '_backlog_only',
0))
if hasattr(curTorrentProvider, 'enable_daily'):
curTorrentProvider.enable_daily = bool(check_setting_int(CFG, curTorrentProvider.getID().upper(),
curTorrentProvider.getID() + '_enable_daily',
1))
if hasattr(curTorrentProvider, 'enable_backlog'):
curTorrentProvider.enable_backlog = bool(check_setting_int(CFG, curTorrentProvider.getID().upper(),
curTorrentProvider.getID() + '_enable_backlog',
1))
for curNzbProvider in [curProvider for curProvider in providers.sortedProviderList() if
curProvider.providerType == GenericProvider.NZB]:
@ -1004,10 +1010,15 @@ def initialize(consoleLogging=True):
curNzbProvider.search_fallback = bool(check_setting_int(CFG, curNzbProvider.getID().upper(),
curNzbProvider.getID() + '_search_fallback',
0))
if hasattr(curNzbProvider, 'backlog_only'):
curNzbProvider.backlog_only = bool(check_setting_int(CFG, curNzbProvider.getID().upper(),
curNzbProvider.getID() + '_backlog_only',
0))
if hasattr(curNzbProvider, 'enable_daily'):
curNzbProvider.enable_daily = bool(check_setting_int(CFG, curNzbProvider.getID().upper(),
curNzbProvider.getID() + '_enable_daily',
1))
if hasattr(curNzbProvider, 'enable_backlog'):
curNzbProvider.enable_backlog = bool(check_setting_int(CFG, curNzbProvider.getID().upper(),
curNzbProvider.getID() + '_enable_backlog',
1))
if not os.path.isfile(CONFIG_FILE):
logger.log(u"Unable to find '" + CONFIG_FILE + "', all settings will be default!", logger.DEBUG)
@ -1124,6 +1135,7 @@ def initialize(consoleLogging=True):
__INITIALIZED__ = True
return True
def start():
global __INITIALIZED__, backlogSearchScheduler, \
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
@ -1278,6 +1290,7 @@ def halt():
__INITIALIZED__ = False
started = False
def sig_handler(signum=None, frame=None):
if type(signum) != type(None):
logger.log(u"Signal %i caught, saving and exiting..." % int(signum))
@ -1462,9 +1475,12 @@ def save_config():
if hasattr(curTorrentProvider, 'search_fallback'):
new_config[curTorrentProvider.getID().upper()][curTorrentProvider.getID() + '_search_fallback'] = int(
curTorrentProvider.search_fallback)
if hasattr(curTorrentProvider, 'backlog_only'):
new_config[curTorrentProvider.getID().upper()][curTorrentProvider.getID() + '_backlog_only'] = int(
curTorrentProvider.backlog_only)
if hasattr(curTorrentProvider, 'enable_daily'):
new_config[curTorrentProvider.getID().upper()][curTorrentProvider.getID() + '_enable_daily'] = int(
curTorrentProvider.enable_daily)
if hasattr(curTorrentProvider, 'enable_backlog'):
new_config[curTorrentProvider.getID().upper()][curTorrentProvider.getID() + '_enable_backlog'] = int(
curTorrentProvider.enable_backlog)
for curNzbProvider in [curProvider for curProvider in providers.sortedProviderList() if
curProvider.providerType == GenericProvider.NZB]:
@ -1483,9 +1499,12 @@ def save_config():
if hasattr(curNzbProvider, 'search_fallback'):
new_config[curNzbProvider.getID().upper()][curNzbProvider.getID() + '_search_fallback'] = int(
curNzbProvider.search_fallback)
if hasattr(curNzbProvider, 'backlog_only'):
new_config[curNzbProvider.getID().upper()][curNzbProvider.getID() + '_backlog_only'] = int(
curNzbProvider.backlog_only)
if hasattr(curNzbProvider, 'enable_daily'):
new_config[curNzbProvider.getID().upper()][curNzbProvider.getID() + '_enable_daily'] = int(
curNzbProvider.enable_daily)
if hasattr(curNzbProvider, 'enable_backlog'):
new_config[curNzbProvider.getID().upper()][curNzbProvider.getID() + '_enable_backlog'] = int(
curNzbProvider.enable_backlog)
new_config['NZBs'] = {}
new_config['NZBs']['nzbs'] = int(NZBS)

View File

@ -22,6 +22,7 @@ import string
from tornado.httputil import HTTPHeaders
from tornado.web import RequestHandler
from sickbeard import encodingKludge as ek
from sickbeard import logger
# use the built-in if it's available (python 2.6), if not use the included library
try:
@ -80,7 +81,12 @@ def foldersAtPath(path, includeParent=False, includeFiles=False):
if path == parentPath and os.name == 'nt':
parentPath = ""
fileList = [{'name': filename, 'path': ek.ek(os.path.join, path, filename)} for filename in ek.ek(os.listdir, path)]
try:
fileList = [{'name': filename, 'path': ek.ek(os.path.join, path, filename)} for filename in ek.ek(os.listdir, path)]
except OSError, e:
logger.log(u"Unable to open " + path + ": " + repr(e) + " / " + str(e), logger.WARNING)
fileList = [{'name': filename, 'path': ek.ek(os.path.join, parentPath, filename)} for filename in ek.ek(os.listdir, parentPath)]
if not includeFiles:
fileList = filter(lambda entry: ek.ek(os.path.isdir, entry['path']), fileList)

View File

@ -148,8 +148,10 @@ class TorrentSearchResult(SearchResult):
resultType = "torrent"
# torrent hash
content = None
hash = None
class AllShowsListUI:
"""
This class is for indexer api. Instead of prompting with a UI to pick the
@ -178,7 +180,7 @@ class AllShowsListUI:
seriesnames.append(curShow['seriesname'])
if 'aliasnames' in curShow:
seriesnames.extend(curShow['aliasnames'].split('|'))
for name in seriesnames:
if searchterm.lower() in name.lower():
if 'firstaired' not in curShow:
@ -192,6 +194,7 @@ class AllShowsListUI:
return searchResults
class ShowListUI:
"""
This class is for tvdb-api. Instead of prompting with a UI to pick the
@ -225,7 +228,7 @@ class Proper:
self.quality = Quality.UNKNOWN
self.release_group = None
self.version = -1
self.show = show
self.indexer = None
self.indexerid = -1

View File

@ -104,6 +104,24 @@ class TransmissionAPI(GenericClient):
return self.response.json()['result'] == "success"
def _set_torrent_seed_time(self, result):
if sickbeard.TORRENT_SEED_TIME:
time = 60 * float(sickbeard.TORRENT_SEED_TIME)
arguments = {'ids': [result.hash],
'seedIdleLimit': time,
'seedIdleMode': 1
}
post_data = json.dumps({'arguments': arguments,
'method': 'torrent-set',
})
self._request(method='post', data=post_data)
return self.response.json()['result'] == "success"
else:
return True
def _set_torrent_priority(self, result):
arguments = {'ids': [result.hash]}

View File

@ -40,67 +40,37 @@ class DailySearcher():
self.amActive = True
didSearch = False
logger.log(u"Searching for coming episodes and 1 weeks worth of previously WANTED episodes ...")
providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and not x.backlog_only]
for curProviderCount, curProvider in enumerate(providers):
curDate = datetime.date.today().toordinal()
logger.log(u"Updating [" + curProvider.name + "] RSS cache ...")
myDB = db.DBConnection()
sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE status = ? AND season > 0 AND airdate <= ?",
[common.UNAIRED, curDate])
sql_l = []
for sqlEp in sqlResults:
try:
curProvider.cache.updateCache()
except exceptions.AuthException, e:
logger.log(u"Authentication error: " + ex(e), logger.ERROR)
continue
except Exception, e:
logger.log(u"Error while updating cache for " + curProvider.name + ", skipping: " + ex(e), logger.ERROR)
logger.log(traceback.format_exc(), logger.DEBUG)
show = helpers.findCertainShow(sickbeard.showList, int(sqlEp["showid"]))
except exceptions.MultipleShowObjectsException:
logger.log(u"ERROR: expected to find a single show matching " + sqlEp["showid"])
continue
didSearch = True
ep = show.getEpisode(int(sqlEp["season"]), int(sqlEp["episode"]))
with ep.lock:
if ep.show.paused:
ep.status = common.SKIPPED
else:
ep.status = common.WANTED
if didSearch:
logger.log(u"Searching for coming episodes and 1 weeks worth of previously WANTED episodes ...")
fromDate = datetime.date.today() - datetime.timedelta(weeks=1)
curDate = datetime.date.today()
sql_l.append(ep.get_sql())
if len(sql_l) > 0:
myDB = db.DBConnection()
sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE status in (?,?) AND airdate >= ? AND airdate <= ?",
[common.UNAIRED, common.WANTED, fromDate.toordinal(), curDate.toordinal()])
myDB.mass_action(sql_l)
sql_l = []
for sqlEp in sqlResults:
try:
show = helpers.findCertainShow(sickbeard.showList, int(sqlEp["showid"]))
except exceptions.MultipleShowObjectsException:
logger.log(u"ERROR: expected to find a single show matching " + sqlEp["showid"])
continue
ep = show.getEpisode(int(sqlEp["season"]), int(sqlEp["episode"]))
with ep.lock:
if ep.show.paused:
ep.status = common.SKIPPED
if ep.status == common.UNAIRED:
logger.log(u"New episode " + ep.prettyName() + " airs today, setting status to WANTED")
ep.status = common.WANTED
sql_l.append(ep.get_sql())
if ep.status == common.WANTED:
dailysearch_queue_item = sickbeard.search_queue.DailySearchQueueItem(show, [ep])
sickbeard.searchQueueScheduler.action.add_item(dailysearch_queue_item)
else:
logger.log(u"Could not find any wanted episodes for the last 7 days to search for")
if len(sql_l) > 0:
myDB = db.DBConnection()
myDB.mass_action(sql_l)
else:
logger.log(
u"No NZB/Torrent providers found or enabled in the sickrage config. Please check your settings.",
logger.ERROR)
# queue episode for daily search
dailysearch_queue_item = sickbeard.search_queue.DailySearchQueueItem()
sickbeard.searchQueueScheduler.action.add_item(dailysearch_queue_item)
self.amActive = False

View File

@ -210,21 +210,17 @@ def _remove_file_failed(file):
except:
pass
def findCertainShow(showList, indexerid):
if not showList:
return None
results = []
if indexerid:
if showList and indexerid:
results = filter(lambda x: int(x.indexerid) == int(indexerid), showList)
if len(results):
if len(results) == 1:
return results[0]
elif len(results) > 1:
raise MultipleShowObjectsException()
def makeDir(path):
if not ek.ek(os.path.isdir, path):
try:

View File

@ -11,7 +11,7 @@
# SickRage is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with SickRage. If not, see <http://www.gnu.org/licenses/>.
@ -63,6 +63,7 @@ def sortedProviderList():
return newList
def makeProviderList():
return [x.provider for x in [getProviderModule(y) for y in __all__] if x]
@ -96,6 +97,8 @@ def getNewznabProviderList(data):
providerDict[curDefault.name].needs_auth = curDefault.needs_auth
providerDict[curDefault.name].search_mode = curDefault.search_mode
providerDict[curDefault.name].search_fallback = curDefault.search_fallback
providerDict[curDefault.name].enable_daily = curDefault.enable_daily
providerDict[curDefault.name].enable_backlog = curDefault.enable_backlog
return filter(lambda x: x, providerList)
@ -106,20 +109,28 @@ def makeNewznabProvider(configString):
search_mode = 'eponly'
search_fallback = 0
enable_daily = 0
enable_backlog = 0
try:
name, url, key, catIDs, enabled, search_mode, search_fallback = configString.split('|')
values = configString.split('|')
if len(values) == 9:
name, url, key, catIDs, enabled, search_mode, search_fallback, enable_daily, enable_backlog = values
else:
name = values[0]
url = values[1]
key = values[2]
catIDs = values[3]
enabled = values[4]
except ValueError:
try:
name, url, key, catIDs, enabled = configString.split('|')
except ValueError:
logger.log(u"Skipping Newznab provider string: '" + configString + "', incorrect format", logger.ERROR)
return None
logger.log(u"Skipping Newznab provider string: '" + configString + "', incorrect format", logger.ERROR)
return None
newznab = sys.modules['sickbeard.providers.newznab']
newProvider = newznab.NewznabProvider(name, url, key=key, catIDs=catIDs, search_mode=search_mode,
search_fallback=search_fallback)
search_fallback=search_fallback, enable_daily=enable_daily,
enable_backlog=enable_backlog)
newProvider.enabled = enabled == '1'
return newProvider
@ -146,33 +157,36 @@ def makeTorrentRssProvider(configString):
cookies = None
search_mode = 'eponly'
search_fallback = 0
backlog_only = 0
enable_daily = 0
enable_backlog = 0
try:
name, url, cookies, enabled, search_mode, search_fallback, backlog_only = configString.split('|')
values = configString.split('|')
if len(values) == 8:
name, url, cookies, enabled, search_mode, search_fallback, enable_daily, enable_backlog = values
else:
name = values[0]
url = values[1]
enabled = values[3]
except ValueError:
try:
name, url, enabled, search_mode, search_fallback, backlog_only = configString.split('|')
except ValueError:
try:
name, url, enabled = configString.split('|')
except ValueError:
logger.log(u"Skipping RSS Torrent provider string: '" + configString + "', incorrect format", logger.ERROR)
return None
logger.log(u"Skipping RSS Torrent provider string: '" + configString + "', incorrect format",
logger.ERROR)
return None
try:
torrentRss = sys.modules['sickbeard.providers.rsstorrent']
except:
return
newProvider = torrentRss.TorrentRssProvider(name, url, cookies, search_mode, search_fallback, backlog_only)
newProvider = torrentRss.TorrentRssProvider(name, url, cookies, search_mode, search_fallback, enable_daily,
enable_backlog)
newProvider.enabled = enabled == '1'
return newProvider
def getDefaultNewznabProviders():
return 'Sick Beard Index|http://lolo.sickbeard.com/|0|5030,5040|0|eponly|0!!!NZBs.org|https://nzbs.org/||5030,5040|0|eponly|0!!!Usenet-Crawler|https://www.usenet-crawler.com/||5030,5040|0|eponly|0'
return 'Sick Beard Index|http://lolo.sickbeard.com/|0|5030,5040|0|eponly|0|0|0!!!NZBs.org|https://nzbs.org/|0|5030,5040|0|eponly|0|0|0!!!Usenet-Crawler|https://www.usenet-crawler.com/|0|5030,5040|0|eponly|0|0|0'
def getProviderModule(name):

View File

@ -133,7 +133,7 @@ class AnimezbCache(tvcache.TVCache):
# only poll Animezb every 20 minutes max
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
params = {
"cat": "anime".encode('utf-8'),

View File

@ -274,7 +274,7 @@ class BitSoupCache(tvcache.TVCache):
# only poll TorrentBytes every 20 minutes max
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['']}
return self.provider._doSearch(search_params)

View File

@ -297,7 +297,7 @@ class BTNCache(tvcache.TVCache):
# At least 15 minutes between queries
self.minTime = 15
def _getDailyData(self):
def _getRSSData(self):
# Get the torrents uploaded since last check.
seconds_since_last_update = math.ceil(time.time() - time.mktime(self._getLastUpdate().timetuple()))

View File

@ -174,7 +174,7 @@ class EZRSSCache(tvcache.TVCache):
# only poll EZRSS every 15 minutes max
self.minTime = 15
def _getDailyData(self):
def _getRSSData(self):
rss_url = self.provider.url + 'feed/'
logger.log(self.provider.name + " cache update URL: " + rss_url, logger.DEBUG)

View File

@ -128,7 +128,7 @@ class FanzubCache(tvcache.TVCache):
# only poll Fanzub every 20 minutes max
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
params = {
"cat": "anime".encode('utf-8'),

View File

@ -306,7 +306,7 @@ class FreshOnTVCache(tvcache.TVCache):
# poll delay in minutes
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['']}
return self.provider._doSearch(search_params)

View File

@ -55,7 +55,8 @@ class GenericProvider:
self.search_mode = None
self.search_fallback = False
self.backlog_only = False
self.enable_daily = False
self.enable_backlog = False
self.cache = tvcache.TVCache(self)
@ -194,8 +195,8 @@ class GenericProvider:
return True
def searchRSS(self, episodes):
return self.cache.findNeededEpisodes(episodes)
def searchRSS(self):
return self.cache.findNeededEpisodes()
def getQuality(self, item, anime=False):
"""
@ -254,10 +255,15 @@ class GenericProvider:
searched_scene_season = None
for epObj in episodes:
# check cache for results
cacheResult = self.cache.searchCache([epObj], manualSearch)
if len(cacheResult):
results.update({epObj.episode: cacheResult[epObj]})
# search cache for episode result
cacheResult = self.cache.searchCache(epObj, manualSearch)
if cacheResult:
if epObj not in results:
results = [cacheResult]
else:
results.append(cacheResult)
# found result, search next episode
continue
# skip if season already searched

View File

@ -204,7 +204,7 @@ class HDBitsCache(tvcache.TVCache):
# only poll HDBits every 15 minutes max
self.minTime = 15
def _getDailyData(self):
def _getRSSData(self):
parsedJSON = self.provider.getURL(self.provider.rss_url, post_data=self.provider._make_post_data_JSON(), json=True)
if not self.provider._checkAuthFromData(parsedJSON):

View File

@ -336,7 +336,7 @@ class HDTorrentsCache(tvcache.TVCache):
# only poll HDTorrents every 10 minutes max
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': []}
return self.provider._doSearch(search_params)

View File

@ -276,7 +276,7 @@ class IPTorrentsCache(tvcache.TVCache):
# Only poll IPTorrents every 10 minutes max
self.minTime = 10
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['']}
return self.provider._doSearch(search_params)

View File

@ -355,7 +355,7 @@ class KATCache(tvcache.TVCache):
# only poll ThePirateBay every 10 minutes max
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['rss']}
return self.provider._doSearch(search_params)

View File

@ -33,14 +33,14 @@ from sickbeard import classes
from sickbeard import helpers
from sickbeard import scene_exceptions
from sickbeard import encodingKludge as ek
from sickbeard.common import cpu_presets
from sickbeard import logger
from sickbeard import tvcache
from sickbeard.exceptions import ex, AuthException
class NewznabProvider(generic.NZBProvider):
def __init__(self, name, url, key='', catIDs='5030,5040', search_mode='eponly', search_fallback=False):
def __init__(self, name, url, key='', catIDs='5030,5040', search_mode='eponly', search_fallback=False,
enable_daily=False, enable_backlog=False):
generic.NZBProvider.__init__(self, name)
@ -52,6 +52,8 @@ class NewznabProvider(generic.NZBProvider):
self.search_mode = search_mode
self.search_fallback = search_fallback
self.enable_daily = enable_daily
self.enable_backlog = enable_backlog
# a 0 in the key spot indicates that no key is needed
if self.key == '0':
@ -71,10 +73,13 @@ class NewznabProvider(generic.NZBProvider):
def configStr(self):
return self.name + '|' + self.url + '|' + self.key + '|' + self.catIDs + '|' + str(
int(self.enabled)) + '|' + self.search_mode + '|' + str(int(self.search_fallback))
int(self.enabled)) + '|' + self.search_mode + '|' + str(int(self.search_fallback)) + '|' + str(
int(self.enable_daily)) + '|' + str(int(self.enable_backlog))
def imageName(self):
if ek.ek(os.path.isfile, ek.ek(os.path.join, sickbeard.PROG_DIR, 'gui', sickbeard.GUI_NAME, 'images', 'providers', self.getID() + '.png')):
if ek.ek(os.path.isfile,
ek.ek(os.path.join, sickbeard.PROG_DIR, 'gui', sickbeard.GUI_NAME, 'images', 'providers',
self.getID() + '.png')):
return self.getID() + '.png'
return 'newznab.png'
@ -99,16 +104,17 @@ class NewznabProvider(generic.NZBProvider):
# search
rid = helpers.mapIndexersToShow(ep_obj.show)[2]
if rid:
cur_params['rid'] = rid
cur_return = cur_params.copy()
cur_return['rid'] = rid
to_return.append(cur_return)
# add new query strings for exceptions
name_exceptions = list(
set(scene_exceptions.get_scene_exceptions(ep_obj.show.indexerid) + [ep_obj.show.name]))
for cur_exception in name_exceptions:
if 'q' in cur_params:
cur_params['q'] = helpers.sanitizeSceneName(cur_exception) + '.' + cur_params['q']
to_return.append(cur_params)
else:
# add new query strings for exceptions
name_exceptions = list(
set(scene_exceptions.get_scene_exceptions(ep_obj.show.indexerid) + [ep_obj.show.name]))
for cur_exception in name_exceptions:
if 'q' in cur_params:
cur_params['q'] = helpers.sanitizeSceneName(cur_exception) + '.' + cur_params['q']
to_return.append(cur_params)
return to_return
@ -132,14 +138,16 @@ class NewznabProvider(generic.NZBProvider):
# search
rid = helpers.mapIndexersToShow(ep_obj.show)[2]
if rid:
params['rid'] = rid
cur_return = params.copy()
cur_return['rid'] = rid
to_return.append(cur_return)
# add new query strings for exceptions
name_exceptions = list(
set(scene_exceptions.get_scene_exceptions(ep_obj.show.indexerid) + [ep_obj.show.name]))
for cur_exception in name_exceptions:
params['q'] = helpers.sanitizeSceneName(cur_exception)
to_return.append(params)
else:
# add new query strings for exceptions
name_exceptions = list(set(scene_exceptions.get_scene_exceptions(ep_obj.show.indexerid) + [ep_obj.show.name]))
for cur_exception in name_exceptions:
params['q'] = helpers.sanitizeSceneName(cur_exception)
to_return.append(params)
return to_return
@ -234,7 +242,9 @@ class NewznabProvider(generic.NZBProvider):
# if there are more items available then the amount given in one call, grab some more
if (total - params['limit']) > offset == params['offset']:
params['offset'] += params['limit']
logger.log(str(total - params['offset']) + " more items to be fetched from provider. Fetching another " + str(params['limit']) + " items.", logger.DEBUG)
logger.log(str(
total - params['offset']) + " more items to be fetched from provider. Fetching another " + str(
params['limit']) + " items.", logger.DEBUG)
else:
break
@ -327,21 +337,18 @@ class NewznabCache(tvcache.TVCache):
def updateCache(self):
# delete anything older then 7 days
self._clearCache()
if not self.shouldUpdate():
return
if self._checkAuth(None):
if self.shouldUpdate() and self._checkAuth(None):
data = self._getRSSData()
# as long as the http request worked we count this as an update
if data:
self.setLastUpdate()
else:
if not data:
return []
self.setLastUpdate()
# clear cache
self._clearCache()
if self._checkAuth(data):
items = data.entries
cl = []
@ -360,7 +367,6 @@ class NewznabCache(tvcache.TVCache):
return []
# overwrite method with that parses the rageid from the newznab feed
def _parseItem(self, item):
title = item.title

View File

@ -318,7 +318,7 @@ class NextGenCache(tvcache.TVCache):
# Only poll NextGen every 10 minutes max
self.minTime = 10
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['']}
return self.provider._doSearch(search_params)

View File

@ -126,7 +126,7 @@ class NyaaCache(tvcache.TVCache):
# only poll NyaaTorrents every 15 minutes max
self.minTime = 15
def _getDailyData(self):
def _getRSSData(self):
params = {
"page": 'rss', # Use RSS page
"order": '1', # Sort Descending By Date

View File

@ -174,7 +174,7 @@ class OmgwtfnzbsCache(tvcache.TVCache):
return (title, url)
def _getDailyData(self):
def _getRSSData(self):
params = {'user': provider.username,
'api': provider.api_key,
'eng': 1,

View File

@ -34,8 +34,10 @@ from lib import requests
from lib.requests import exceptions
from lib.bencode import bdecode
class TorrentRssProvider(generic.TorrentProvider):
def __init__(self, name, url, cookies='', search_mode='eponly', search_fallback=False, backlog_only=False):
def __init__(self, name, url, cookies='', search_mode='eponly', search_fallback=False, enable_daily=False,
enable_backlog=False):
generic.TorrentProvider.__init__(self, name)
self.cache = TorrentRssCache(self)
self.url = re.sub('\/$', '', url)
@ -46,14 +48,19 @@ class TorrentRssProvider(generic.TorrentProvider):
self.search_mode = search_mode
self.search_fallback = search_fallback
self.backlog_only = backlog_only
self.enable_daily = enable_daily
self.enable_backlog = enable_backlog
self.cookies = cookies
def configStr(self):
return self.name + '|' + self.url + '|' + self.cookies + '|' + str(int(self.enabled)) + '|' + self.search_mode + '|' + str(int(self.search_fallback)) + '|' + str(int(self.backlog_only))
return self.name + '|' + self.url + '|' + self.cookies + '|' + str(
int(self.enabled)) + '|' + self.search_mode + '|' + str(int(self.search_fallback)) + '|' + str(
int(self.enable_daily)) + '|' + str(int(self.enable_backlog))
def imageName(self):
if ek.ek(os.path.isfile, ek.ek(os.path.join, sickbeard.PROG_DIR, 'gui', sickbeard.GUI_NAME, 'images', 'providers', self.getID() + '.png')):
if ek.ek(os.path.isfile,
ek.ek(os.path.join, sickbeard.PROG_DIR, 'gui', sickbeard.GUI_NAME, 'images', 'providers',
self.getID() + '.png')):
return self.getID() + '.png'
return 'torrentrss.png'
@ -91,12 +98,12 @@ class TorrentRssProvider(generic.TorrentProvider):
try:
if self.cookies:
cookie_validator=re.compile("^(\w+=\w+)(;\w+=\w+)*$")
cookie_validator = re.compile("^(\w+=\w+)(;\w+=\w+)*$")
if not cookie_validator.match(self.cookies):
return (False, 'Cookie is not correctly formatted: ' + self.cookies)
items = self.cache._getDailyData()
items = self.cache._getRSSData()
if not len(items) > 0:
return (False, 'No items found in the RSS feed ' + self.url)
@ -144,17 +151,18 @@ class TorrentRssProvider(generic.TorrentProvider):
def seedRatio(self):
return self.ratio
class TorrentRssCache(tvcache.TVCache):
def __init__(self, provider):
tvcache.TVCache.__init__(self, provider)
self.minTime = 15
def _getDailyData(self):
def _getRSSData(self):
logger.log(u"TorrentRssCache cache update URL: " + self.provider.url, logger.DEBUG)
request_headers = None
if self.provider.cookies:
request_headers = { 'Cookie': self.provider.cookies }
request_headers = {'Cookie': self.provider.cookies}
data = self.getRSSFeed(self.provider.url, request_headers=request_headers)

View File

@ -312,7 +312,7 @@ class SCCCache(tvcache.TVCache):
# only poll SCC every 10 minutes max
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['']}
return self.provider._doSearch(search_params)

View File

@ -252,7 +252,7 @@ class SpeedCDCache(tvcache.TVCache):
# only poll Speedcd every 20 minutes max
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['']}
return self.provider._doSearch(search_params)

View File

@ -338,7 +338,7 @@ class ThePirateBayCache(tvcache.TVCache):
# only poll ThePirateBay every 10 minutes max
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['rss']}
return self.provider._doSearch(search_params)

View File

@ -274,7 +274,7 @@ class TorrentBytesCache(tvcache.TVCache):
# only poll TorrentBytes every 20 minutes max
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['']}
return self.provider._doSearch(search_params)

View File

@ -277,7 +277,7 @@ class TorrentDayCache(tvcache.TVCache):
# Only poll IPTorrents every 10 minutes max
self.minTime = 10
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['']}
return self.provider._doSearch(search_params)

View File

@ -275,7 +275,7 @@ class TorrentLeechCache(tvcache.TVCache):
# only poll TorrentLeech every 20 minutes max
self.minTime = 20
def _getDailyData(self):
def _getRSSData(self):
search_params = {'RSS': ['']}
return self.provider._doSearch(search_params)

View File

@ -83,7 +83,7 @@ class TvTorrentsCache(tvcache.TVCache):
# only poll TvTorrents every 15 minutes max
self.minTime = 15
def _getDailyData(self):
def _getRSSData(self):
# These will be ignored on the serverside.
ignore_regex = "all.month|month.of|season[\s\d]*complete"

View File

@ -40,17 +40,17 @@ class RSSFeeds:
fc = cache.Cache(fs)
feed = fc.fetch(url, False, False, request_headers)
if not feed or not feed.entries:
logger.log(u"RSS error loading url: " + url, logger.DEBUG)
return
elif 'error' in feed.feed:
err_code = feed.feed['error']['code']
err_desc = feed.feed['error']['description']
if feed:
if 'entries' in feed:
return feed
elif 'error' in feed.feed:
err_code = feed.feed['error']['code']
err_desc = feed.feed['error']['description']
logger.log(
u"RSS ERROR:[%s] CODE:[%s]" % (err_desc, err_code), logger.DEBUG)
return
logger.log(
u"RSS ERROR:[%s] CODE:[%s]" % (err_desc, err_code), logger.DEBUG)
else:
return feed
logger.log(u"RSS error loading url: " + url, logger.DEBUG)
except Exception as e:
logger.log(u"RSS error: " + ex(e), logger.DEBUG)

View File

@ -53,7 +53,7 @@ def get_scene_numbering(indexer_id, indexer, season, episode, fallback_to_xem=Tr
return (season, episode)
showObj = sickbeard.helpers.findCertainShow(sickbeard.showList, int(indexer_id))
if not showObj.is_scene:
if showObj and not showObj.is_scene:
return (season, episode)
result = find_scene_numbering(int(indexer_id), int(indexer), season, episode)
@ -105,7 +105,7 @@ def get_scene_absolute_numbering(indexer_id, indexer, absolute_number, fallback_
indexer = int(indexer)
showObj = sickbeard.helpers.findCertainShow(sickbeard.showList, indexer_id)
if not showObj.is_scene:
if showObj and not showObj.is_scene:
return absolute_number
result = find_scene_absolute_numbering(indexer_id, indexer, absolute_number)

View File

@ -336,23 +336,21 @@ def filterSearchResults(show, season, results):
return foundResults
def searchForNeededEpisodes(show, episodes):
def searchForNeededEpisodes():
foundResults = {}
didSearch = False
origThreadName = threading.currentThread().name
providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and not x.backlog_only]
for curProviderCount, curProvider in enumerate(providers):
if curProvider.anime_only and not show.is_anime:
logger.log(u"" + str(show.name) + " is not an anime, skiping", logger.DEBUG)
continue
providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and x.enable_daily]
for curProvider in providers:
threading.currentThread().name = origThreadName + " :: [" + curProvider.name + "]"
try:
curFoundResults = curProvider.searchRSS(episodes)
curProvider.cache.updateCache()
curFoundResults = curProvider.searchRSS()
except exceptions.AuthException, e:
logger.log(u"Authentication error: " + ex(e), logger.ERROR)
continue
@ -374,6 +372,12 @@ def searchForNeededEpisodes(show, episodes):
logger.DEBUG)
continue
# find the best result for the current episode
bestResult = None
for curResult in curFoundResults[curEp]:
if not bestResult or bestResult.quality < curResult.quality:
bestResult = curResult
bestResult = pickBestResult(curFoundResults[curEp], curEp.show)
# if all results were rejected move on to the next episode
@ -400,7 +404,7 @@ def searchForNeededEpisodes(show, episodes):
u"No NZB/Torrent providers found or enabled in the sickrage config for daily searches. Please check your settings.",
logger.ERROR)
return foundResults.values() if len(foundResults) else {}
return foundResults.values()
def searchProviders(show, season, episodes, manualSearch=False):
@ -409,6 +413,9 @@ def searchProviders(show, season, episodes, manualSearch=False):
didSearch = False
# build name cache for show
sickbeard.name_cache.buildNameCache(show)
# check if we want to search for season packs instead of just season/episode
seasonSearch = False
if not manualSearch:
@ -418,7 +425,7 @@ def searchProviders(show, season, episodes, manualSearch=False):
origThreadName = threading.currentThread().name
providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive()]
providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and x.enable_backlog]
for providerNum, curProvider in enumerate(providers):
if curProvider.anime_only and not show.is_anime:
logger.log(u"" + str(show.name) + " is not an anime, skiping", logger.DEBUG)
@ -442,6 +449,7 @@ def searchProviders(show, season, episodes, manualSearch=False):
logger.log(u"Searching for episodes we need from " + show.name + " Season " + str(season))
try:
curProvider.cache.updateCache()
searchResults = curProvider.findSearchResults(show, season, episodes, search_mode, manualSearch)
except exceptions.AuthException, e:
logger.log(u"Authentication error: " + ex(e), logger.ERROR)

View File

@ -29,6 +29,7 @@ from sickbeard import logger
from sickbeard import ui
from sickbeard import common
class BacklogSearchScheduler(scheduler.Scheduler):
def forceSearch(self):
self.action._set_lastBacklog(1)
@ -40,11 +41,12 @@ class BacklogSearchScheduler(scheduler.Scheduler):
else:
return datetime.date.fromordinal(self.action._lastBacklog + self.action.cycleTime)
class BacklogSearcher:
def __init__(self):
self._lastBacklog = self._get_lastBacklog()
self.cycleTime = sickbeard.BACKLOG_FREQUENCY/60/24
self.cycleTime = sickbeard.BACKLOG_FREQUENCY / 60 / 24
self.lock = threading.Lock()
self.amActive = False
self.amPaused = False
@ -99,7 +101,7 @@ class BacklogSearcher:
if len(segments):
backlog_queue_item = search_queue.BacklogQueueItem(curShow, segments)
sickbeard.searchQueueScheduler.action.add_item(backlog_queue_item) #@UndefinedVariable
sickbeard.searchQueueScheduler.action.add_item(backlog_queue_item) # @UndefinedVariable
else:
logger.log(u"Nothing needs to be downloaded for " + str(curShow.name) + ", skipping this season",
logger.DEBUG)
@ -132,14 +134,14 @@ class BacklogSearcher:
return self._lastBacklog
def _get_segments(self, show, fromDate):
anyQualities, bestQualities = common.Quality.splitQuality(show.quality) #@UnusedVariable
anyQualities, bestQualities = common.Quality.splitQuality(show.quality) # @UnusedVariable
logger.log(u"Seeing if we need anything from " + show.name)
myDB = db.DBConnection()
if show.air_by_date:
sqlResults = myDB.select(
"SELECT ep.status, ep.season, ep.episode FROM tv_episodes ep, tv_shows show WHERE season != 0 AND ep.showid = show.indexer_id AND show.paused = 0 ANd ep.airdate > ? AND ep.showid = ? AND show.air_by_date = 1",
"SELECT ep.status, ep.season, ep.episode FROM tv_episodes ep, tv_shows show WHERE season != 0 AND ep.showid = show.indexer_id AND show.paused = 0 AND ep.airdate > ? AND ep.showid = ? AND show.air_by_date = 1",
[fromDate.toordinal(), show.indexerid])
else:
sqlResults = myDB.select(

View File

@ -72,34 +72,27 @@ class SearchQueue(generic_queue.GenericQueue):
return False
def add_item(self, item):
if isinstance(item, (DailySearchQueueItem, BacklogQueueItem, ManualSearchQueueItem, FailedQueueItem)) \
and not self.is_in_queue(item.show, item.segment):
sickbeard.name_cache.buildNameCache(item.show)
if isinstance(item, DailySearchQueueItem) or (
isinstance(item, (BacklogQueueItem, ManualSearchQueueItem, FailedQueueItem)) and not self.is_in_queue(
item.show, item.segment)):
generic_queue.GenericQueue.add_item(self, item)
else:
logger.log(u"Not adding item, it's already in the queue", logger.DEBUG)
class DailySearchQueueItem(generic_queue.QueueItem):
def __init__(self, show, segment):
def __init__(self):
generic_queue.QueueItem.__init__(self, 'Daily Search', DAILY_SEARCH)
self.priority = generic_queue.QueuePriorities.HIGH
self.name = 'DAILYSEARCH-' + str(show.indexerid)
self.show = show
self.segment = segment
def run(self):
generic_queue.QueueItem.run(self)
try:
logger.log("Beginning daily search for [" + self.show.name + "]")
foundResults = search.searchForNeededEpisodes(self.show, self.segment)
logger.log("Beginning daily search for new episodes")
foundResults = search.searchForNeededEpisodes()
if not len(foundResults):
logger.log(u"No needed episodes found during daily search for [" + self.show.name + "]")
logger.log(u"No needed episodes found")
else:
for result in foundResults:
# just use the first result for now
@ -115,6 +108,7 @@ class DailySearchQueueItem(generic_queue.QueueItem):
self.finish()
class ManualSearchQueueItem(generic_queue.QueueItem):
def __init__(self, show, segment):
generic_queue.QueueItem.__init__(self, 'Manual Search', MANUAL_SEARCH)
@ -169,7 +163,7 @@ class BacklogQueueItem(generic_queue.QueueItem):
try:
for season in self.segment:
sickbeard.searchBacklog.BacklogSearcher.currentSearchInfo = {
'title': self.show.name + " Season " + str(season)}
'title': self.show.name + " Season " + str(season)}
wantedEps = self.segment[season]

View File

@ -23,6 +23,7 @@ import datetime
import threading
import re
import glob
import stat
import traceback
import sickbeard
@ -962,7 +963,7 @@ class TVShow(object):
return self.nextaired
def deleteShow(self):
def deleteShow(self, full=False):
sql_l = [["DELETE FROM tv_episodes WHERE showid = ?", [self.indexerid]],
["DELETE FROM tv_shows WHERE indexer_id = ?", [self.indexerid]],
@ -973,7 +974,6 @@ class TVShow(object):
myDB = db.DBConnection()
myDB.mass_action(sql_l)
# remove self from show list
sickbeard.showList = [x for x in sickbeard.showList if int(x.indexerid) != self.indexerid]
@ -983,6 +983,24 @@ class TVShow(object):
logger.log(u"Deleting cache file " + cache_file)
os.remove(cache_file)
# remove entire show folder
if full:
try:
logger.log(u"Deleting show folder " + self.location)
# check first the read-only attribute
file_attribute = ek.ek(os.stat, self.location)[0]
if (not file_attribute & stat.S_IWRITE):
# File is read-only, so make it writeable
logger.log('Read only mode on folder ' + self.location + ' Will try to make it writeable', logger.DEBUG)
try:
ek.ek(os.chmod, self.location, stat.S_IWRITE)
except:
logger.log(u'Cannot change permissions of ' + self.location, logger.WARNING)
ek.ek(os.rmdir, self.location)
except OSError, e:
logger.log(u"Unable to delete " + self.location + ": " + repr(e) + " / " + str(e), logger.WARNING)
def populateCache(self):
cache_inst = image_cache.ImageCache()

View File

@ -89,26 +89,17 @@ class TVCache():
def _clearCache(self):
if self.shouldClearCache():
logger.log(u"Clearing items older than 1 week from " + self.provider.name + " cache")
curDate = datetime.date.today() - datetime.timedelta(weeks=1)
myDB = self._getDB()
myDB.action("DELETE FROM [" + self.providerID + "] WHERE time < ?", [int(time.mktime(curDate.timetuple()))])
myDB.action("DELETE FROM [" + self.providerID + "] WHERE 1")
def _get_title_and_url(self, item):
# override this in the provider if daily search has a different data layout to backlog searches
return self.provider._get_title_and_url(item)
def _getRSSData(self):
data = None
return data
def _getDailyData(self):
return None
def _checkAuth(self):
return self.provider._checkAuth()
@ -116,10 +107,9 @@ class TVCache():
return True
def updateCache(self):
if self.shouldUpdate() and self._checkAuth():
# as long as the http request worked we count this as an update
data = self._getDailyData()
data = self._getRSSData()
if not data:
return []
@ -230,8 +220,6 @@ class TVCache():
def shouldClearCache(self):
# if daily search hasn't used our previous results yet then don't clear the cache
if self.lastUpdate > self.lastSearch:
logger.log(
u"Daily search has not yet used our last cache results, not clearing cache ...", logger.DEBUG)
return False
return True
@ -289,9 +277,9 @@ class TVCache():
[name, season, episodeText, parse_result.show.indexerid, url, curTimestamp, quality, release_group, version]]
def searchCache(self, episodes, manualSearch=False):
neededEps = self.findNeededEpisodes(episodes, manualSearch)
return neededEps
def searchCache(self, episode, manualSearch=False):
neededEps = self.findNeededEpisodes(episode, manualSearch)
return neededEps[episode]
def listPropers(self, date=None, delimiter="."):
myDB = self._getDB()
@ -303,69 +291,84 @@ class TVCache():
return filter(lambda x: x['indexerid'] != 0, myDB.select(sql))
def findNeededEpisodes(self, episodes, manualSearch=False):
def findNeededEpisodes(self, episode=None, manualSearch=False):
neededEps = {}
for epObj in episodes:
myDB = self._getDB()
if episode:
neededEps[episode] = []
myDB = self._getDB()
if not episode:
sqlResults = myDB.select("SELECT * FROM [" + self.providerID + "]")
else:
sqlResults = myDB.select(
"SELECT * FROM [" + self.providerID + "] WHERE indexerid = ? AND season = ? AND episodes LIKE ?",
[epObj.show.indexerid, epObj.season, "%|" + str(epObj.episode) + "|%"])
[episode.show.indexerid, episode.season, "%|" + str(episode.episode) + "|%"])
# for each cache entry
for curResult in sqlResults:
# for each cache entry
for curResult in sqlResults:
# skip non-tv crap (but allow them for Newzbin cause we assume it's filtered well)
if self.providerID != 'newzbin' and not show_name_helpers.filterBadReleases(curResult["name"]):
continue
# skip non-tv crap
if not show_name_helpers.filterBadReleases(curResult["name"]):
continue
# get the show object, or if it's not one of our shows then ignore it
try:
showObj = helpers.findCertainShow(sickbeard.showList, int(curResult["indexerid"]))
except MultipleShowObjectsException:
showObj = None
# get the show object, or if it's not one of our shows then ignore it
showObj = helpers.findCertainShow(sickbeard.showList, int(curResult["indexerid"]))
if not showObj:
continue
if not showObj:
continue
# skip if provider is anime only and show is not anime
if self.provider.anime_only and not showObj.is_anime:
logger.log(u"" + str(showObj.name) + " is not an anime, skiping", logger.DEBUG)
continue
# get season and ep data (ignoring multi-eps for now)
curSeason = int(curResult["season"])
if curSeason == -1:
continue
curEp = curResult["episodes"].split("|")[1]
if not curEp:
continue
curEp = int(curEp)
curQuality = int(curResult["quality"])
curReleaseGroup = curResult["release_group"]
curVersion = curResult["version"]
# get season and ep data (ignoring multi-eps for now)
curSeason = int(curResult["season"])
if curSeason == -1:
continue
curEp = curResult["episodes"].split("|")[1]
if not curEp:
continue
curEp = int(curEp)
# if the show says we want that episode then add it to the list
if not showObj.wantEpisode(curSeason, curEp, curQuality, manualSearch):
logger.log(u"Skipping " + curResult["name"] + " because we don't want an episode that's " +
Quality.qualityStrings[curQuality], logger.DEBUG)
continue
curQuality = int(curResult["quality"])
curReleaseGroup = curResult["release_group"]
curVersion = curResult["version"]
# build a result object
title = curResult["name"]
url = curResult["url"]
# if the show says we want that episode then add it to the list
if not showObj.wantEpisode(curSeason, curEp, curQuality, manualSearch):
logger.log(u"Skipping " + curResult["name"] + " because we don't want an episode that's " +
Quality.qualityStrings[curQuality], logger.DEBUG)
continue
logger.log(u"Found result " + title + " at " + url)
# build name cache for show
sickbeard.name_cache.buildNameCache(showObj)
result = self.provider.getResult([epObj])
result.show = showObj
result.url = url
result.name = title
result.quality = curQuality
result.release_group = curReleaseGroup
result.version = curVersion
result.content = None
if episode:
epObj = episode
else:
epObj = showObj.getEpisode(curSeason, curEp)
# add it to the list
if epObj not in neededEps:
neededEps[epObj] = [result]
else:
neededEps[epObj].append(result)
# build a result object
title = curResult["name"]
url = curResult["url"]
logger.log(u"Found result " + title + " at " + url)
result = self.provider.getResult([epObj])
result.show = showObj
result.url = url
result.name = title
result.quality = curQuality
result.release_group = curReleaseGroup
result.version = curVersion
result.content = None
# add it to the list
if epObj not in neededEps:
neededEps[epObj] = [result]
else:
neededEps[epObj].append(result)
# datetime stamp this search so cache gets cleared
self.setLastSearch()

View File

@ -1036,8 +1036,10 @@ class Manage(MainHandler):
return _munge(t)
def massEditSubmit(self, paused=None, anime=None, sports=None, scene=None, flatten_folders=None, quality_preset=False,
subtitles=None, air_by_date=None, anyQualities=[], bestQualities=[], toEdit=None, *args, **kwargs):
def massEditSubmit(self, paused=None, anime=None, sports=None, scene=None, flatten_folders=None,
quality_preset=False,
subtitles=None, air_by_date=None, anyQualities=[], bestQualities=[], toEdit=None, *args,
**kwargs):
dir_map = {}
for cur_arg in kwargs:
@ -1112,7 +1114,8 @@ class Manage(MainHandler):
exceptions_list = []
curErrors += Home(self.application, self.request).editShow(curShow, new_show_dir, anyQualities, bestQualities, exceptions_list,
curErrors += Home(self.application, self.request).editShow(curShow, new_show_dir, anyQualities,
bestQualities, exceptions_list,
flatten_folders=new_flatten_folders,
paused=new_paused, sports=new_sports,
subtitles=new_subtitles, anime=new_anime,
@ -1131,7 +1134,7 @@ class Manage(MainHandler):
redirect("/manage/")
def massUpdate(self, toUpdate=None, toRefresh=None, toRename=None, toDelete=None, toMetadata=None, toSubtitle=None):
def massUpdate(self, toUpdate=None, toRefresh=None, toRename=None, toDelete=None, toRemove=None, toMetadata=None, toSubtitle=None):
if toUpdate is not None:
toUpdate = toUpdate.split('|')
@ -1158,6 +1161,11 @@ class Manage(MainHandler):
else:
toDelete = []
if toRemove is not None:
toRemove = toRemove.split('|')
else:
toRemove = []
if toMetadata is not None:
toMetadata = toMetadata.split('|')
else:
@ -1169,7 +1177,7 @@ class Manage(MainHandler):
renames = []
subtitles = []
for curShowID in set(toUpdate + toRefresh + toRename + toSubtitle + toDelete + toMetadata):
for curShowID in set(toUpdate + toRefresh + toRename + toSubtitle + toDelete + toRemove + toMetadata):
if curShowID == '':
continue
@ -1180,10 +1188,15 @@ class Manage(MainHandler):
continue
if curShowID in toDelete:
showObj.deleteShow()
showObj.deleteShow(True)
# don't do anything else if it's being deleted
continue
if curShowID in toRemove:
showObj.deleteShow()
# don't do anything else if it's being remove
continue
if curShowID in toUpdate:
try:
sickbeard.showQueueScheduler.action.updateShow(showObj, True) # @UndefinedVariable
@ -1601,7 +1614,8 @@ class ConfigSearch(MainHandler):
def saveSearch(self, use_nzbs=None, use_torrents=None, nzb_dir=None, sab_username=None, sab_password=None,
sab_apikey=None, sab_category=None, sab_host=None, nzbget_username=None, nzbget_password=None,
nzbget_category=None, nzbget_priority=100, nzbget_host=None, nzbget_use_https=None, dailysearch_frequency=None,
nzbget_category=None, nzbget_priority=100, nzbget_host=None, nzbget_use_https=None,
dailysearch_frequency=None,
nzb_method=None, torrent_method=None, usenet_retention=None, backlog_frequency=None,
download_propers=None, check_propers_interval=None, allow_high_priority=None,
backlog_startup=None, dailysearch_startup=None,
@ -1992,19 +2006,42 @@ class ConfigProviders(MainHandler):
cur_url = config.clean_url(cur_url)
newProvider = newznab.NewznabProvider(cur_name, cur_url, key=cur_key)
cur_id = newProvider.getID()
# if it already exists then update it
if cur_id in newznabProviderDict:
newznabProviderDict[cur_id].name = cur_name
newznabProviderDict[cur_id].url = cur_url
newznabProviderDict[cur_id].key = cur_key
# a 0 in the key spot indicates that no key is needed
if cur_key == '0':
newznabProviderDict[cur_id].needs_auth = False
else:
newznabProviderDict[cur_id].needs_auth = True
try:
newznabProviderDict[cur_id].search_mode = str(kwargs[cur_id + '_search_mode']).strip()
except:
pass
try:
newznabProviderDict[cur_id].search_fallback = config.checkbox_to_value(
kwargs[cur_id + '_search_fallback'])
except:
pass
try:
newznabProviderDict[cur_id].enable_daily = config.checkbox_to_value(
kwargs[cur_id + '_enable_daily'])
except:
pass
try:
newznabProviderDict[cur_id].enable_backlog = config.checkbox_to_value(
kwargs[cur_id + '_enable_backlog'])
except:
pass
else:
sickbeard.newznabProviderList.append(newProvider)
@ -2161,12 +2198,19 @@ class ConfigProviders(MainHandler):
except:
curTorrentProvider.search_fallback = 0
if hasattr(curTorrentProvider, 'backlog_only'):
if hasattr(curTorrentProvider, 'enable_daily'):
try:
curTorrentProvider.backlog_only = config.checkbox_to_value(
kwargs[curTorrentProvider.getID() + '_backlog_only'])
curTorrentProvider.enable_daily = config.checkbox_to_value(
kwargs[curTorrentProvider.getID() + '_enable_daily'])
except:
curTorrentProvider.backlog_only = 0
curTorrentProvider.enable_daily = 1
if hasattr(curTorrentProvider, 'enable_backlog'):
try:
curTorrentProvider.enable_backlog = config.checkbox_to_value(
kwargs[curTorrentProvider.getID() + '_enable_backlog'])
except:
curTorrentProvider.enable_backlog = 1
for curNzbProvider in [curProvider for curProvider in sickbeard.providers.sortedProviderList() if
curProvider.providerType == sickbeard.GenericProvider.NZB]:
@ -2196,12 +2240,19 @@ class ConfigProviders(MainHandler):
except:
curNzbProvider.search_fallback = 0
if hasattr(curNzbProvider, 'backlog_only'):
if hasattr(curNzbProvider, 'enable_daily'):
try:
curNzbProvider.backlog_only = config.checkbox_to_value(
kwargs[curNzbProvider.getID() + '_backlog_only'])
curNzbProvider.enable_daily = config.checkbox_to_value(
kwargs[curNzbProvider.getID() + '_enable_daily'])
except:
curNzbProvider.backlog_only = 0
curNzbProvider.enable_daily = 1
if hasattr(curNzbProvider, 'enable_backlog'):
try:
curNzbProvider.enable_backlog = config.checkbox_to_value(
kwargs[curNzbProvider.getID() + '_enable_backlog'])
except:
curNzbProvider.enable_backlog = 1
sickbeard.NEWZNAB_DATA = '!!!'.join([x.configStr() for x in sickbeard.newznabProviderList])
sickbeard.PROVIDER_ORDER = provider_list
@ -2796,8 +2847,9 @@ class NewHomeAddShows(MainHandler):
final_results = []
logger.log(u"Getting recommended shows from Trakt.tv", logger.DEBUG)
recommendedlist = TraktCall("recommendations/shows.json/%API%", sickbeard.TRAKT_API, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD)
recommendedlist = TraktCall("recommendations/shows.json/%API%", sickbeard.TRAKT_API, sickbeard.TRAKT_USERNAME,
sickbeard.TRAKT_PASSWORD)
if recommendedlist == 'NULL':
logger.log(u"No shows found in your recommendedlist, aborting recommendedlist update", logger.DEBUG)
return
@ -2807,7 +2859,8 @@ class NewHomeAddShows(MainHandler):
return
map(final_results.append,
([int(show['tvdb_id'] or 0) if sickbeard.TRAKT_DEFAULT_INDEXER == 1 else int(show['tvdb_id'] or 0), show['url'], show['title'], show['overview'],
([int(show['tvdb_id'] or 0) if sickbeard.TRAKT_DEFAULT_INDEXER == 1 else int(show['tvdb_id'] or 0),
show['url'], show['title'], show['overview'],
datetime.date.fromtimestamp(int(show['first_aired']) / 1000.0).strftime('%Y%m%d')] for show in
recommendedlist if not helpers.findCertainShow(sickbeard.showList, indexerid=int(show['tvdb_id']))))
@ -3563,7 +3616,10 @@ class Home(MainHandler):
if not sickbeard.showQueueScheduler.action.isBeingAdded(showObj): # @UndefinedVariable
if not sickbeard.showQueueScheduler.action.isBeingUpdated(showObj): # @UndefinedVariable
t.submenu.append(
{'title': 'Delete', 'path': 'home/deleteShow?show=%d' % showObj.indexerid, 'confirm': True})
{'title': 'Delete', 'path': 'home/deleteShow?show=%d&amp;full=1' % showObj.indexerid,
'confirm': True})
t.submenu.append(
{'title': 'Remove', 'path': 'home/deleteShow?show=%d' % showObj.indexerid, 'confirm': True})
t.submenu.append({'title': 'Re-scan files', 'path': 'home/refreshShow?show=%d' % showObj.indexerid})
t.submenu.append(
{'title': 'Force Full Update', 'path': 'home/updateShow?show=%d&amp;force=1' % showObj.indexerid})
@ -3895,7 +3951,7 @@ class Home(MainHandler):
redirect("/home/displayShow?show=" + show)
def deleteShow(self, show=None):
def deleteShow(self, show=None, full=0):
if show is None:
return self._genericMessage("Error", "Invalid show ID")
@ -3913,7 +3969,7 @@ class Home(MainHandler):
# remove show from trakt.tv library
sickbeard.traktCheckerScheduler.action.removeShowFromTraktLibrary(showObj)
showObj.deleteShow()
showObj.deleteShow(bool(full))
ui.notifications.message('<b>%s</b> has been deleted' % showObj.name)
redirect("/home/")