1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-12-13 11:32:20 -05: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,7 +200,7 @@ 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 />
@ -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,6 +244,23 @@ class Connection(threading.Thread):
"""
return self.handle(PushAckCommand(nid), callback)
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
@ -261,6 +278,22 @@ class Connection(threading.Thread):
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
class AniDBIncorrectParameterError(AniDBError):
pass
class AniDBCommandTimeoutError(AniDBError):
pass
class AniDBMustAuthError(AniDBError):
pass
class AniDBPacketCorruptedError(AniDBError):
pass
class AniDBBannedError(AniDBError):
pass
class AniDBInternalError(AniDBError):
pass

View File

@ -18,6 +18,7 @@
from types import FunctionType
from aniDBmaper import AniDBMaper
class ResponseResolver:
def __init__(self, data):
restag, rescode, resstr, datalines = self.parse(data)
@ -42,7 +43,6 @@ class ResponseResolver:
for line in lines:
datalines.append(line.split('|'))
return restag, rescode, resstr, datalines
def resolve(self, cmd):
@ -59,7 +59,8 @@ class Response:
self.maper = AniDBMaper()
def __repr__(self):
tmp="%s(%s,%s,%s) %s\n"%(self.__class__.__name__,repr(self.restag),repr(self.rescode),repr(self.resstr),repr(self.attrs))
tmp = "%s(%s,%s,%s) %s\n" % (
self.__class__.__name__, repr(self.restag), repr(self.rescode), repr(self.resstr), repr(self.attrs))
m = 0
for line in self.datalines:
@ -95,6 +96,7 @@ class Response:
if self.req:
self.req.handle(self)
class LoginAcceptedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -117,6 +119,7 @@ class LoginAcceptedResponse(Response):
else:
self.codehead = ('sesskey',)
class LoginAcceptedNewVerResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -139,6 +142,7 @@ class LoginAcceptedNewVerResponse(Response):
else:
self.codehead = ('sesskey',)
class LoggedOutResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -153,6 +157,7 @@ class LoggedOutResponse(Response):
self.codetail = ()
self.coderep = ()
class ResourceResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -167,6 +172,7 @@ class ResourceResponse(Response):
self.codetail = ()
self.coderep = ()
class StatsResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -181,6 +187,7 @@ class StatsResponse(Response):
self.codetail = ()
self.coderep = ()
class TopResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -195,6 +202,7 @@ class TopResponse(Response):
self.codetail = ()
self.coderep = ()
class UptimeResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -210,6 +218,7 @@ class UptimeResponse(Response):
self.codetail = ('uptime',)
self.coderep = ()
class EncryptionEnabledResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -225,6 +234,7 @@ class EncryptionEnabledResponse(Response):
self.codetail = ()
self.coderep = ()
class MylistEntryAddedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -240,6 +250,7 @@ class MylistEntryAddedResponse(Response):
self.codetail = ('entrycnt',)
self.coderep = ()
class MylistEntryDeletedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -255,6 +266,7 @@ class MylistEntryDeletedResponse(Response):
self.codetail = ('entrycnt',)
self.coderep = ()
class AddedFileResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -269,6 +281,7 @@ class AddedFileResponse(Response):
self.codetail = ()
self.coderep = ()
class AddedStreamResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -283,6 +296,7 @@ class AddedStreamResponse(Response):
self.codetail = ()
self.coderep = ()
class EncodingChangedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -296,8 +310,8 @@ class EncodingChangedResponse(Response):
self.codetail = ()
self.coderep = ()
class FileResponse(Response):
class FileResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
attributes:
@ -363,6 +377,7 @@ class FileResponse(Response):
self.codetail = tuple(['fid'] + codeListF + codeListA)
class MylistResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -387,6 +402,7 @@ class MylistResponse(Response):
self.codetail = ('lid', 'fid', 'eid', 'aid', 'gid', 'date', 'state', 'viewdate', 'storage', 'source', 'other')
self.coderep = ()
class MylistStatsResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -414,12 +430,35 @@ class MylistStatsResponse(Response):
Response.__init__(self, cmd, restag, rescode, resstr, datalines)
self.codestr = 'MYLIST_STATS'
self.codehead = ()
self.codetail=('animes', 'eps', 'files', 'filesizes', 'animesadded', 'epsadded', 'filesadded', 'groupsadded', 'leechperc', 'lameperc', 'viewedofdb', 'mylistofdb', 'viewedofmylist', 'viewedeps', 'votes', 'reviews')
self.codetail = (
'animes', 'eps', 'files', 'filesizes', 'animesadded', 'epsadded', 'filesadded', 'groupsadded', 'leechperc',
'lameperc', 'viewedofdb', 'mylistofdb', 'viewedofmylist', 'viewedeps', 'votes', 'reviews')
self.coderep = ()
class NotificationResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
attributes:
data:
nid - notification id
unknown - unsure what this parameter is
type - Type of notification: type=> 0=all, 1=new, 2=group, 3=complete
aid - anime id
priority - low = 0, medium = 1, high = 2 (unconfirmed)
date - date notification subscribed to
"""
Response.__init__(self, cmd, restag, rescode, resstr, datalines)
self.codestr = 'NOTIFICATION'
self.codehead = ()
self.codetail = ('nid', 'unknown', 'type', 'aid', 'priority', 'date')
self.coderep = ()
class AnimeResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
Response.__init__(self, cmd, restag, rescode, resstr, datalines)
self.codestr = 'ANIME'
self.codehead = ()
@ -430,6 +469,7 @@ class AnimeResponse(Response):
codeList = self.maper.getAnimeCodesA(amask)
self.codetail = tuple(codeList)
class AnimeBestMatchResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -444,6 +484,7 @@ class AnimeBestMatchResponse(Response):
self.codetail = ()
self.coderep = ()
class RandomanimeResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -458,6 +499,7 @@ class RandomanimeResponse(Response):
self.codetail = ()
self.coderep = ()
class EpisodeResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -481,6 +523,7 @@ class EpisodeResponse(Response):
self.codetail = ('eid', 'aid', 'length', 'rating', 'votes', 'epno', 'name', 'romaji', 'kanji')
self.coderep = ()
class ProducerResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -502,6 +545,7 @@ class ProducerResponse(Response):
self.codetail = ('pid', 'name', 'shortname', 'othername', 'type', 'pic', 'url')
self.coderep = ()
class GroupResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -523,9 +567,11 @@ class GroupResponse(Response):
Response.__init__(self, cmd, restag, rescode, resstr, datalines)
self.codestr = 'GROUP'
self.codehead = ()
self.codetail=('gid', 'rating', 'votes', 'animes', 'files', 'name', 'shortname', 'ircchannel', 'ircserver', 'url')
self.codetail = (
'gid', 'rating', 'votes', 'animes', 'files', 'name', 'shortname', 'ircchannel', 'ircserver', 'url')
self.coderep = ()
class GroupstatusResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -550,6 +596,7 @@ class GroupstatusResponse(Response):
self.codetail = ('gid', 'name', 'state', ' last_episode_number', 'rating', 'votes', 'episode_range')
self.coderep = ()
class BuddyListResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -570,6 +617,7 @@ class BuddyListResponse(Response):
self.codetail = ('uid', 'username', 'state')
self.coderep = ()
class BuddyStateResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -589,6 +637,7 @@ class BuddyStateResponse(Response):
self.codetail = ('uid', 'state')
self.coderep = ()
class BuddyAddedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -603,6 +652,7 @@ class BuddyAddedResponse(Response):
self.codetail = ()
self.coderep = ()
class BuddyDeletedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -617,6 +667,7 @@ class BuddyDeletedResponse(Response):
self.codetail = ()
self.coderep = ()
class BuddyAcceptedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -631,6 +682,7 @@ class BuddyAcceptedResponse(Response):
self.codetail = ()
self.coderep = ()
class BuddyDeniedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -645,6 +697,7 @@ class BuddyDeniedResponse(Response):
self.codetail = ()
self.coderep = ()
class VotedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -660,6 +713,7 @@ class VotedResponse(Response):
self.codetail = ('name',)
self.coderep = ()
class VoteFoundResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -676,6 +730,7 @@ class VoteFoundResponse(Response):
self.codetail = ('name', 'value')
self.coderep = ()
class VoteUpdatedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -692,6 +747,7 @@ class VoteUpdatedResponse(Response):
self.codetail = ('name', 'value')
self.coderep = ()
class VoteRevokedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -709,7 +765,6 @@ class VoteRevokedResponse(Response):
self.coderep = ()
class NotificationAddedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -725,6 +780,22 @@ class NotificationAddedResponse(Response):
self.codetail = ('nid')
self.coderep = ()
class NotificationDeletedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
attributes:
data:
nid - notofication id
"""
Response.__init__(self, cmd, restag, rescode, resstr, datalines)
self.codestr = 'NOTIFICATION_ITEM_DELETED'
self.codehead = ()
self.codetail = ()
self.coderep = ()
class NotificationUpdatedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -740,6 +811,26 @@ class NotificationUpdatedResponse(Response):
self.codetail = ('nid')
self.coderep = ()
class MultipleNotificationResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
attributes:
data:
nid - notification id
type -
priority -
"""
Response.__init__(self, cmd, restag, rescode, resstr, datalines)
self.codestr = 'MULTIPLE NOTIFICATION ITEMS'
self.codehead = ()
self.codetail = ()
self.coderep = ('nid', 'type', 'priority',)
class NotificationEnabledResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -754,6 +845,7 @@ class NotificationEnabledResponse(Response):
self.codetail = ()
self.coderep = ()
class NotificationNotifyResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -773,6 +865,7 @@ class NotificationNotifyResponse(Response):
self.codetail = ('aid', 'date', 'count', 'name')
self.coderep = ()
class NotificationMessageResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -793,6 +886,7 @@ class NotificationMessageResponse(Response):
self.codetail = ('type', 'date', 'uid', 'name', 'subject')
self.coderep = ()
class NotificationBuddyResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -810,6 +904,7 @@ class NotificationBuddyResponse(Response):
self.codetail = ('uid', 'type')
self.coderep = ()
class NotificationShutdownResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -827,6 +922,7 @@ class NotificationShutdownResponse(Response):
self.codetail = ('time', 'comment')
self.coderep = ()
class PushackConfirmedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -841,6 +937,7 @@ class PushackConfirmedResponse(Response):
self.codetail = ()
self.coderep = ()
class NotifyackSuccessfulMResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -855,6 +952,7 @@ class NotifyackSuccessfulMResponse(Response):
self.codetail = ()
self.coderep = ()
class NotifyackSuccessfulNResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -869,7 +967,8 @@ class NotifyackSuccessfulNResponse(Response):
self.codetail = ()
self.coderep = ()
class NotificationResponse(Response):
class NotificationStateResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
attributes:
@ -892,6 +991,7 @@ class NotificationResponse(Response):
else:
self.codetail = ('notifies', 'msgs')
class NotifylistResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -908,6 +1008,7 @@ class NotifylistResponse(Response):
self.codetail = ('type', 'nid')
self.coderep = ()
class NotifygetMessageResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -929,6 +1030,7 @@ class NotifygetMessageResponse(Response):
self.codetail = ('nid', 'uid', 'uname', 'date', 'type', 'title', 'body')
self.coderep = ()
class NotifygetNotifyResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -940,14 +1042,15 @@ class NotifygetNotifyResponse(Response):
count - count
date - date
name - anime name
fid - comma separated list of fids
"""
Response.__init__(self, cmd, restag, rescode, resstr, datalines)
self.codestr = 'NOTIFYGET_NOTIFY'
self.codehead = ()
self.codetail=('aid', 'type', 'count', 'date', 'name')
self.codetail = ('aid', 'type', 'count', 'date', 'name', 'fid')
self.coderep = ()
class SendmsgSuccessfulResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -962,6 +1065,7 @@ class SendmsgSuccessfulResponse(Response):
self.codetail = ()
self.coderep = ()
class UserResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -977,6 +1081,7 @@ class UserResponse(Response):
self.codetail = ('uid',)
self.coderep = ()
class PongResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -991,6 +1096,7 @@ class PongResponse(Response):
self.codetail = ()
self.coderep = ()
class AuthpongResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1005,6 +1111,7 @@ class AuthpongResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchResourceResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1019,6 +1126,7 @@ class NoSuchResourceResponse(Response):
self.codetail = ()
self.coderep = ()
class ApiPasswordNotDefinedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1033,6 +1141,7 @@ class ApiPasswordNotDefinedResponse(Response):
self.codetail = ()
self.coderep = ()
class FileAlreadyInMylistResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1047,6 +1156,7 @@ class FileAlreadyInMylistResponse(Response):
self.codetail = ()
self.coderep = ()
class MylistEntryEditedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1062,6 +1172,7 @@ class MylistEntryEditedResponse(Response):
self.codetail = ('entries',)
self.coderep = ()
class MultipleMylistEntriesResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1085,6 +1196,7 @@ class MultipleMylistEntriesResponse(Response):
self.codetail = ('name', 'eps', 'unknowneps', 'hddeps', 'cdeps', 'deletedeps', 'watchedeps')
self.coderep = ('gshortname', 'geps')
class SizeHashExistsResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1099,6 +1211,7 @@ class SizeHashExistsResponse(Response):
self.codetail = ()
self.coderep = ()
class InvalidDataResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1113,6 +1226,7 @@ class InvalidDataResponse(Response):
self.codetail = ()
self.coderep = ()
class StreamnoidUsedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1127,6 +1241,7 @@ class StreamnoidUsedResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchFileResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1141,6 +1256,7 @@ class NoSuchFileResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchEntryResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1155,6 +1271,7 @@ class NoSuchEntryResponse(Response):
self.codetail = ()
self.coderep = ()
class MultipleFilesFoundResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1170,6 +1287,22 @@ class MultipleFilesFoundResponse(Response):
self.codetail = ()
self.coderep = ('fid',)
class NoSuchNotificationResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
attributes:
data:
"""
Response.__init__(self, cmd, restag, rescode, resstr, datalines)
self.codestr = 'NO_SUCH_NOTIFICATION'
self.codehead = ()
self.codetail = ()
self.coderep = ()
class NoGroupsFoundResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1184,6 +1317,7 @@ class NoGroupsFoundResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchAnimeResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1198,6 +1332,7 @@ class NoSuchAnimeResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchEpisodeResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1212,6 +1347,7 @@ class NoSuchEpisodeResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchProducerResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1226,6 +1362,7 @@ class NoSuchProducerResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchGroupResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1240,6 +1377,7 @@ class NoSuchGroupResponse(Response):
self.codetail = ()
self.coderep = ()
class BuddyAlreadyAddedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1254,6 +1392,7 @@ class BuddyAlreadyAddedResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchBuddyResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1268,6 +1407,7 @@ class NoSuchBuddyResponse(Response):
self.codetail = ()
self.coderep = ()
class BuddyAlreadyAcceptedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1282,6 +1422,7 @@ class BuddyAlreadyAcceptedResponse(Response):
self.codetail = ()
self.coderep = ()
class BuddyAlreadyDeniedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1296,6 +1437,7 @@ class BuddyAlreadyDeniedResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchVoteResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1310,6 +1452,7 @@ class NoSuchVoteResponse(Response):
self.codetail = ()
self.coderep = ()
class InvalidVoteTypeResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1324,6 +1467,7 @@ class InvalidVoteTypeResponse(Response):
self.codetail = ()
self.coderep = ()
class InvalidVoteValueResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1338,6 +1482,7 @@ class InvalidVoteValueResponse(Response):
self.codetail = ()
self.coderep = ()
class PermvoteNotAllowedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1353,6 +1498,7 @@ class PermvoteNotAllowedResponse(Response):
self.codetail = ('aname',)
self.coderep = ()
class AlreadyPermvotedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1368,6 +1514,7 @@ class AlreadyPermvotedResponse(Response):
self.codetail = ('name',)
self.coderep = ()
class NotificationDisabledResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1382,6 +1529,7 @@ class NotificationDisabledResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchPacketPendingResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1396,6 +1544,7 @@ class NoSuchPacketPendingResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchEntryMResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1410,6 +1559,7 @@ class NoSuchEntryMResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchEntryNResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1424,6 +1574,7 @@ class NoSuchEntryNResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchMessageResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1438,6 +1589,7 @@ class NoSuchMessageResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchNotifyResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1452,6 +1604,7 @@ class NoSuchNotifyResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchUserResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1466,6 +1619,7 @@ class NoSuchUserResponse(Response):
self.codetail = ()
self.coderep = ()
class NoChanges(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1480,6 +1634,7 @@ class NoChanges(Response):
self.codetail = ()
self.coderep = ()
class NotLoggedInResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1494,6 +1649,7 @@ class NotLoggedInResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchMylistFileResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1508,6 +1664,7 @@ class NoSuchMylistFileResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchMylistEntryResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1522,6 +1679,7 @@ class NoSuchMylistEntryResponse(Response):
self.codetail = ()
self.coderep = ()
class LoginFailedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1536,6 +1694,7 @@ class LoginFailedResponse(Response):
self.codetail = ()
self.coderep = ()
class LoginFirstResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1550,6 +1709,7 @@ class LoginFirstResponse(Response):
self.codetail = ()
self.coderep = ()
class AccessDeniedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1564,6 +1724,7 @@ class AccessDeniedResponse(Response):
self.codetail = ()
self.coderep = ()
class ClientVersionOutdatedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1578,6 +1739,7 @@ class ClientVersionOutdatedResponse(Response):
self.codetail = ()
self.coderep = ()
class ClientBannedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1592,6 +1754,7 @@ class ClientBannedResponse(Response):
self.codetail = ()
self.coderep = ()
class IllegalInputOrAccessDeniedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1606,6 +1769,7 @@ class IllegalInputOrAccessDeniedResponse(Response):
self.codetail = ()
self.coderep = ()
class InvalidSessionResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1620,6 +1784,7 @@ class InvalidSessionResponse(Response):
self.codetail = ()
self.coderep = ()
class NoSuchEncryptionTypeResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1634,6 +1799,7 @@ class NoSuchEncryptionTypeResponse(Response):
self.codetail = ()
self.coderep = ()
class EncodingNotSupportedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1648,6 +1814,7 @@ class EncodingNotSupportedResponse(Response):
self.codetail = ()
self.coderep = ()
class BannedResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1662,6 +1829,7 @@ class BannedResponse(Response):
self.codetail = ()
self.coderep = ()
class UnknownCommandResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1676,6 +1844,7 @@ class UnknownCommandResponse(Response):
self.codetail = ()
self.coderep = ()
class InternalServerErrorResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1690,6 +1859,7 @@ class InternalServerErrorResponse(Response):
self.codetail = ()
self.coderep = ()
class AnidbOutOfServiceResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1704,6 +1874,7 @@ class AnidbOutOfServiceResponse(Response):
self.codetail = ()
self.coderep = ()
class ServerBusyResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1718,6 +1889,7 @@ class ServerBusyResponse(Response):
self.codetail = ()
self.coderep = ()
class ApiViolationResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1732,6 +1904,7 @@ class ApiViolationResponse(Response):
self.codetail = ()
self.coderep = ()
class VersionResponse(Response):
def __init__(self, cmd, restag, rescode, resstr, datalines):
"""
@ -1765,6 +1938,7 @@ responses={
'220': FileResponse,
'221': MylistResponse,
'222': MylistStatsResponse,
'224': NotificationResponse,
'225': GroupstatusResponse,
'230': AnimeResponse,
'231': AnimeBestMatchResponse,
@ -1772,7 +1946,9 @@ responses={
'240': EpisodeResponse,
'245': ProducerResponse,
'246': NotificationAddedResponse,
'247': NotificationDeletedResponse,
'248': NotificationUpdatedResponse,
'249': MultipleNotificationResponse,
'250': GroupResponse,
'253': BuddyListResponse,
'254': BuddyStateResponse,
@ -1792,7 +1968,7 @@ responses={
'280': PushackConfirmedResponse,
'281': NotifyackSuccessfulMResponse,
'282': NotifyackSuccessfulNResponse,
'290':NotificationResponse,
'290': NotificationStateResponse,
'291': NotifylistResponse,
'292': NotifygetMessageResponse,
'293': NotifygetNotifyResponse,
@ -1811,6 +1987,7 @@ responses={
'320': NoSuchFileResponse,
'321': NoSuchEntryResponse,
'322': MultipleFilesFoundResponse,
'324': NoSuchNotificationResponse,
'325': NoGroupsFoundResponse,
'330': NoSuchAnimeResponse,
'340': NoSuchEpisodeResponse,

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 []
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)
src = self._loadUrl(url, params=params, language=language).values()[0]
return src
except:
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

@ -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)
@ -489,20 +488,10 @@ class TVRage:
"""
try:
src = self._loadUrl(url, params)
src = [src[item] for item in src][0] if src else []
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)
src = self._loadUrl(url, params).values()[0]
return src
except:
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,

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 = ""
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
@ -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

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,34 +40,13 @@ class DailySearcher():
self.amActive = True
didSearch = False
providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and not x.backlog_only]
for curProviderCount, curProvider in enumerate(providers):
logger.log(u"Updating [" + curProvider.name + "] RSS cache ...")
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)
continue
didSearch = True
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()
curDate = datetime.date.today().toordinal()
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()])
sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE status = ? AND season > 0 AND airdate <= ?",
[common.UNAIRED, curDate])
sql_l = []
for sqlEp in sqlResults:
@ -81,26 +60,17 @@ class DailySearcher():
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")
else:
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

@ -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,12 +109,19 @@ 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('|')
except ValueError:
try:
name, url, key, catIDs, enabled = 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:
logger.log(u"Skipping Newznab provider string: '" + configString + "', incorrect format", logger.ERROR)
return None
@ -119,7 +129,8 @@ def makeNewznabProvider(configString):
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,18 +157,20 @@ 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)
logger.log(u"Skipping RSS Torrent provider string: '" + configString + "', incorrect format",
logger.ERROR)
return None
try:
@ -165,14 +178,15 @@ def makeTorrentRssProvider(configString):
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,9 +104,10 @@ class NewznabProvider(generic.NZBProvider):
# search
rid = helpers.mapIndexersToShow(ep_obj.show)[2]
if rid:
cur_params['rid'] = rid
to_return.append(cur_params)
else:
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]))
@ -132,11 +138,13 @@ class NewznabProvider(generic.NZBProvider):
# search
rid = helpers.mapIndexersToShow(ep_obj.show)[2]
if rid:
params['rid'] = rid
to_return.append(params)
else:
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]))
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)
@ -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'
@ -95,7 +102,7 @@ class TorrentRssProvider(generic.TorrentProvider):
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,12 +151,13 @@ 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

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
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
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,6 +41,7 @@ class BacklogSearchScheduler(scheduler.Scheduler):
else:
return datetime.date.fromordinal(self.action._lastBacklog + self.action.cycleTime)
class BacklogSearcher:
def __init__(self):
@ -139,7 +141,7 @@ class BacklogSearcher:
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)

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,31 +291,37 @@ 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:
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:
# 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"]):
# 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
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:
@ -336,6 +330,7 @@ class TVCache():
if not curEp:
continue
curEp = int(curEp)
curQuality = int(curResult["quality"])
curReleaseGroup = curResult["release_group"]
curVersion = curResult["version"]
@ -346,6 +341,14 @@ class TVCache():
Quality.qualityStrings[curQuality], logger.DEBUG)
continue
# build name cache for show
sickbeard.name_cache.buildNameCache(showObj)
if episode:
epObj = episode
else:
epObj = showObj.getEpisode(curSeason, curEp)
# build a result object
title = curResult["name"]
url = curResult["url"]

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,7 +2847,8 @@ 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)
@ -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/")