diff --git a/gui/slick/interfaces/default/config_general.tmpl b/gui/slick/interfaces/default/config_general.tmpl index 7a62ef12..8b15b25e 100644 --- a/gui/slick/interfaces/default/config_general.tmpl +++ b/gui/slick/interfaces/default/config_general.tmpl @@ -26,6 +26,7 @@ #end if +
@@ -167,6 +168,14 @@
+
+ +
+
diff --git a/gui/slick/interfaces/default/config_providers.tmpl b/gui/slick/interfaces/default/config_providers.tmpl index 453f0213..b0aae4eb 100644 --- a/gui/slick/interfaces/default/config_providers.tmpl +++ b/gui/slick/interfaces/default/config_providers.tmpl @@ -156,14 +156,24 @@ var show_nzb_providers = #if $sickbeard.USE_NZBS then "true" else "false"#; #end if - #if $hasattr($curNewznabProvider, 'backlog_only'): + #if $hasattr($curNewznabProvider, 'enable_daily'):
- -
+ #end if + + #if $hasattr($curNewznabProvider, 'enable_backlog'): +
+ +
#end if @@ -190,12 +200,12 @@ var show_nzb_providers = #if $sickbeard.USE_NZBS then "true" else "false"#; When searching for complete seasons
you can choose to have it look for season
packs ONLY or choose to have it build a
- complete season from just single episodes. + complete season from just single episodes.
- - Season Packs ONLY!
- - Episodes ONLY!
+ + Season Packs ONLY!
+ + Episodes ONLY!
@@ -224,14 +234,24 @@ var show_nzb_providers = #if $sickbeard.USE_NZBS then "true" else "false"#; #end if - #if $hasattr($curNzbProvider, 'backlog_only'): + #if $hasattr($curNzbProvider, 'enable_daily'):
- -
+ #end if + + #if $hasattr($curNzbProvider, 'enable_backlog'): +
+ +
#end if @@ -440,14 +460,24 @@ var show_nzb_providers = #if $sickbeard.USE_NZBS then "true" else "false"#; #end if - #if $hasattr($curTorrentProvider, 'backlog_only'): + #if $hasattr($curTorrentProvider, 'enable_daily'):
- -
+ #end if + + #if $hasattr($curTorrentProvider, 'enable_backlog'): +
+ +
#end if diff --git a/gui/slick/interfaces/default/inc_top.tmpl b/gui/slick/interfaces/default/inc_top.tmpl index 5c9746bd..a48ba280 100644 --- a/gui/slick/interfaces/default/inc_top.tmpl +++ b/gui/slick/interfaces/default/inc_top.tmpl @@ -147,6 +147,7 @@ a > i.icon-question-sign { background-image: url("$sbRoot/images/glyphicons-half \$("#SubMenu a[href*='/home/logout/']").addClass('btn').html(' Logout'); \$("#SubMenu a:contains('Edit')").addClass('btn').html(' Edit'); \$("#SubMenu a:contains('Delete')").addClass('btn').html(' Delete'); + \$("#SubMenu a:contains('Remove')").addClass('btn').html(' Remove'); \$("#SubMenu a:contains('Clear History')").addClass('btn confirm').html(' Clear History'); \$("#SubMenu a:contains('Trim History')").addClass('btn confirm').html(' Trim History'); \$("#SubMenu a[href$='/errorlogs/clearerrors/']").addClass('btn').html(' Clear Errors'); diff --git a/gui/slick/interfaces/default/manage.tmpl b/gui/slick/interfaces/default/manage.tmpl index 64882eca..c20e8199 100644 --- a/gui/slick/interfaces/default/manage.tmpl +++ b/gui/slick/interfaces/default/manage.tmpl @@ -102,6 +102,7 @@ #end if Delete
+ Remove
@@ -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 = "" +#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 = "" @@ -163,6 +169,7 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name)) $curSubtitle #end if $curDelete + $curRemove #end for diff --git a/gui/slick/interfaces/default/manage_massEdit.tmpl b/gui/slick/interfaces/default/manage_massEdit.tmpl index ea7bfef7..86c6166e 100644 --- a/gui/slick/interfaces/default/manage_massEdit.tmpl +++ b/gui/slick/interfaces/default/manage_massEdit.tmpl @@ -27,6 +27,7 @@ #set $cur_index = $root_dir_list.index($cur_dir)
+ $cur_dir => $cur_dir
diff --git a/gui/slick/js/configSearch.js b/gui/slick/js/configSearch.js index cec16e27..f94630c0 100644 --- a/gui/slick/js/configSearch.js +++ b/gui/slick/js/configSearch.js @@ -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'); diff --git a/gui/slick/js/massEdit.js b/gui/slick/js/massEdit.js index 1ddc541b..b5755224 100644 --- a/gui/slick/js/massEdit.js +++ b/gui/slick/js/massEdit.js @@ -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('DELETED'); + }); }); \ No newline at end of file diff --git a/gui/slick/js/massUpdate.js b/gui/slick/js/massUpdate.js index 42469672..b27f574c 100644 --- a/gui/slick/js/massUpdate.js +++ b/gui/slick/js/massUpdate.js @@ -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) { diff --git a/lib/adba/__init__.py b/lib/adba/__init__.py index 59de2d92..93817404 100644 --- a/lib/adba/__init__.py +++ b/lib/adba/__init__.py @@ -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): """ diff --git a/lib/adba/aniDBAbstracter.py b/lib/adba/aniDBAbstracter.py index 428bfa29..64ebd851 100644 --- a/lib/adba/aniDBAbstracter.py +++ b/lib/adba/aniDBAbstracter.py @@ -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): diff --git a/lib/adba/aniDBcommands.py b/lib/adba/aniDBcommands.py index 190234bf..74d62806 100644 --- a/lib/adba/aniDBcommands.py +++ b/lib/adba/aniDBcommands.py @@ -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} diff --git a/lib/adba/aniDBerrors.py b/lib/adba/aniDBerrors.py index 67f3e980..72f282f1 100644 --- a/lib/adba/aniDBerrors.py +++ b/lib/adba/aniDBerrors.py @@ -15,23 +15,30 @@ # You should have received a copy of the GNU General Public License # along with aDBa. If not, see . + 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 diff --git a/lib/adba/aniDBresponses.py b/lib/adba/aniDBresponses.py index f2c6f132..7504ce17 100644 --- a/lib/adba/aniDBresponses.py +++ b/lib/adba/aniDBresponses.py @@ -18,1839 +18,2016 @@ from types import FunctionType from aniDBmaper import AniDBMaper + class ResponseResolver: - def __init__(self,data): - restag,rescode,resstr,datalines=self.parse(data) - - self.restag=restag - self.rescode=rescode - self.resstr=resstr - self.datalines=datalines + def __init__(self, data): + restag, rescode, resstr, datalines = self.parse(data) - def parse(self,data): - resline=data.split('\n',1)[0] - lines=data.split('\n')[1:-1] + self.restag = restag + self.rescode = rescode + self.resstr = resstr + self.datalines = datalines - rescode,resstr=resline.split(' ',1) - if rescode[0]=='T': - restag=rescode - rescode,resstr=resstr.split(' ',1) - else: - restag=None + def parse(self, data): + resline = data.split('\n', 1)[0] + lines = data.split('\n')[1:-1] - datalines=[] - for line in lines: - datalines.append(line.split('|')) - - - return restag,rescode,resstr,datalines - - def resolve(self,cmd): - return responses[self.rescode](cmd,self.restag,self.rescode,self.resstr,self.datalines) + rescode, resstr = resline.split(' ', 1) + if rescode[0] == 'T': + restag = rescode + rescode, resstr = resstr.split(' ', 1) + else: + restag = None + + datalines = [] + for line in lines: + datalines.append(line.split('|')) + + return restag, rescode, resstr, datalines + + def resolve(self, cmd): + return responses[self.rescode](cmd, self.restag, self.rescode, self.resstr, self.datalines) class Response: - def __init__(self,cmd,restag,rescode,resstr,rawlines): - self.req=cmd - self.restag=restag - self.rescode=rescode - self.resstr=resstr - self.rawlines=rawlines - self.maper = AniDBMaper() + def __init__(self, cmd, restag, rescode, resstr, rawlines): + self.req = cmd + self.restag = restag + self.rescode = rescode + self.resstr = resstr + self.rawlines = rawlines + 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)) - - m=0 - for line in self.datalines: - for k,v in line.iteritems(): - if len(k)>m: - m=len(k) - - for line in self.datalines: - tmp+=" Line:\n" - for k,v in line.iteritems(): - tmp+=" %s:%s %s\n"%(k,(m-len(k))*' ',v) - return tmp + 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)) + + m = 0 + for line in self.datalines: + for k, v in line.iteritems(): + if len(k) > m: + m = len(k) + + for line in self.datalines: + tmp += " Line:\n" + for k, v in line.iteritems(): + tmp += " %s:%s %s\n" % (k, (m - len(k)) * ' ', v) + return tmp + + def parse(self): + tmp = self.resstr.split(' ', len(self.codehead)) + self.attrs = dict(zip(self.codehead, tmp[:-1])) + self.resstr = tmp[-1] + + self.datalines = [] + for rawline in self.rawlines: + normal = dict(zip(self.codetail, rawline)) + rawline = rawline[len(self.codetail):] + rep = [] + if len(self.coderep): + while rawline: + tmp = dict(zip(self.coderep, rawline)) + rawline = rawline[len(self.coderep):] + rep.append(tmp) + # normal['rep']=rep + self.datalines.append(normal) + + def handle(self): + if self.req: + self.req.handle(self) - def parse(self): - tmp=self.resstr.split(' ',len(self.codehead)) - self.attrs=dict(zip(self.codehead,tmp[:-1])) - self.resstr=tmp[-1] - - self.datalines=[] - for rawline in self.rawlines: - normal=dict(zip(self.codetail,rawline)) - rawline=rawline[len(self.codetail):] - rep=[] - if len(self.coderep): - while rawline: - tmp=dict(zip(self.coderep,rawline)) - rawline=rawline[len(self.coderep):] - rep.append(tmp) - #normal['rep']=rep - self.datalines.append(normal) - - def handle(self): - if self.req: - self.req.handle(self) class LoginAcceptedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: - sesskey - session key - address - your address (ip:port) as seen by the server + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + sesskey - session key + address - your address (ip:port) as seen by the server - data: + data: - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='LOGIN_ACCEPTED' - self.codetail=() - self.coderep=() + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'LOGIN_ACCEPTED' + self.codetail = () + self.coderep = () + + nat = cmd.parameters['nat'] + nat = int(nat == None and nat or '0') + if nat: + self.codehead = ('sesskey', 'address') + else: + self.codehead = ('sesskey',) - nat=cmd.parameters['nat'] - nat=int(nat==None and nat or '0') - if nat: - self.codehead=('sesskey','address') - else: - self.codehead=('sesskey',) class LoginAcceptedNewVerResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: - sesskey - session key - address - your address (ip:port) as seen by the server + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + sesskey - session key + address - your address (ip:port) as seen by the server - data: + data: - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='LOGIN_ACCEPTED_NEW_VER' - self.codetail=() - self.coderep=() + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'LOGIN_ACCEPTED_NEW_VER' + self.codetail = () + self.coderep = () + + nat = cmd.parameters['nat'] + nat = int(nat == None and nat or '0') + if nat: + self.codehead = ('sesskey', 'address') + else: + self.codehead = ('sesskey',) - nat=cmd.parameters['nat'] - nat=int(nat==None and nat or '0') - if nat: - self.codehead=('sesskey','address') - else: - self.codehead=('sesskey',) class LoggedOutResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'LOGGED_OUT' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='LOGGED_OUT' - self.codehead=() - self.codetail=() - self.coderep=() class ResourceResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'RESOURCE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='RESOURCE' - self.codehead=() - self.codetail=() - self.coderep=() class StatsResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'STATS' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='STATS' - self.codehead=() - self.codetail=() - self.coderep=() class TopResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'TOP' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='TOP' - self.codehead=() - self.codetail=() - self.coderep=() class UptimeResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - uptime - udpserver uptime in milliseconds + data: + uptime - udpserver uptime in milliseconds + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'UPTIME' + self.codehead = () + self.codetail = ('uptime',) + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='UPTIME' - self.codehead=() - self.codetail=('uptime',) - self.coderep=() class EncryptionEnabledResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: - salt - salt + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + salt - salt - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ENCRYPTION_ENABLED' + self.codehead = ('salt',) + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='ENCRYPTION_ENABLED' - self.codehead=('salt',) - self.codetail=() - self.coderep=() class MylistEntryAddedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - entrycnt - number of entries added + data: + entrycnt - number of entries added + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'MYLIST_ENTRY_ADDED' + self.codehead = () + self.codetail = ('entrycnt',) + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='MYLIST_ENTRY_ADDED' - self.codehead=() - self.codetail=('entrycnt',) - self.coderep=() class MylistEntryDeletedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - entrycnt - number of entries + data: + entrycnt - number of entries + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'MYLIST_ENTRY_DELETED' + self.codehead = () + self.codetail = ('entrycnt',) + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='MYLIST_ENTRY_DELETED' - self.codehead=() - self.codetail=('entrycnt',) - self.coderep=() class AddedFileResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ADDED_FILE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='ADDED_FILE' - self.codehead=() - self.codetail=() - self.coderep=() class AddedStreamResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ADDED_STREAM' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='ADDED_STREAM' - self.codehead=() - self.codetail=() - self.coderep=() class EncodingChangedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + + data: + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ENCODING_CHANGED' + self.codehead = () + self.codetail = () + self.coderep = () - data: - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='ENCODING_CHANGED' - self.codehead=() - self.codetail=() - self.coderep=() class FileResponse(Response): - - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + + data: + eid episode id + gid group id + lid mylist id + state state + size size + ed2k ed2k + md5 md5 + sha1 sha1 + crc32 crc32 + dublang dub language + sublang sub language + quality quality + source source + audiocodec audio codec + audiobitrate audio bitrate + videocodec video codec + videobitrate video bitrate + resolution video resolution + filetype file type (extension) + length length in seconds + description description + filename anidb file name + gname group name + gshortname group short name + epno number of episode + epname ep english name + epromaji ep romaji name + epkanji ep kanji name + totaleps anime total episodes + lastep last episode nr (highest, not special) + year year + type type + romaji romaji name + kanji kanji name + name english name + othername other name + shortnames short name list + synonyms synonym list + categories category list + relatedaids related aid list + producernames producer name list + producerids producer id list + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'FILE' + self.codehead = () + self.coderep = () + + fmask = cmd.parameters['fmask'] + amask = cmd.parameters['amask'] + + codeListF = self.maper.getFileCodesF(fmask) + codeListA = self.maper.getFileCodesA(amask) + # print "File - codelistF: "+str(codeListF) + #print "File - codelistA: "+str(codeListA) + + + self.codetail = tuple(['fid'] + codeListF + codeListA) - data: - eid episode id - gid group id - lid mylist id - state state - size size - ed2k ed2k - md5 md5 - sha1 sha1 - crc32 crc32 - dublang dub language - sublang sub language - quality quality - source source - audiocodec audio codec - audiobitrate audio bitrate - videocodec video codec - videobitrate video bitrate - resolution video resolution - filetype file type (extension) - length length in seconds - description description - filename anidb file name - gname group name - gshortname group short name - epno number of episode - epname ep english name - epromaji ep romaji name - epkanji ep kanji name - totaleps anime total episodes - lastep last episode nr (highest, not special) - year year - type type - romaji romaji name - kanji kanji name - name english name - othername other name - shortnames short name list - synonyms synonym list - categories category list - relatedaids related aid list - producernames producer name list - producerids producer id list - - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='FILE' - self.codehead=() - self.coderep=() - - fmask=cmd.parameters['fmask'] - amask=cmd.parameters['amask'] - - codeListF = self.maper.getFileCodesF(fmask) - codeListA = self.maper.getFileCodesA(amask) - #print "File - codelistF: "+str(codeListF) - #print "File - codelistA: "+str(codeListA) - - - self.codetail=tuple(['fid']+codeListF+codeListA) class MylistResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + + data: + lid - mylist id + fid - file id + eid - episode id + aid - anime id + gid - group id + date - date when you added this to mylist + state - the location of the file + viewdate - date when you marked this watched + storage - for example the title of the cd you have this on + source - where you got the file (bittorrent,dc++,ed2k,...) + other - other data regarding this file + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'MYLIST' + self.codehead = () + self.codetail = ('lid', 'fid', 'eid', 'aid', 'gid', 'date', 'state', 'viewdate', 'storage', 'source', 'other') + self.coderep = () - data: - lid - mylist id - fid - file id - eid - episode id - aid - anime id - gid - group id - date - date when you added this to mylist - state - the location of the file - viewdate - date when you marked this watched - storage - for example the title of the cd you have this on - source - where you got the file (bittorrent,dc++,ed2k,...) - other - other data regarding this file - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='MYLIST' - self.codehead=() - 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): - """ - attributes: - - data: - animes - animes - eps - eps - files - files - filesizes - size of files - animesadded - added animes - epsadded - added eps - filesadded - added files - groupsadded - added groups - leechperc - leech % - lameperc - lame % - viewedofdb - viewed % of db - mylistofdb - mylist % of db - viewedofmylist - viewed % of mylist - viewedeps - number of viewed eps - votes - votes - reviews - reviews - - """ - 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.coderep=() + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + + data: + animes - animes + eps - eps + files - files + filesizes - size of files + animesadded - added animes + epsadded - added eps + filesadded - added files + groupsadded - added groups + leechperc - leech % + lameperc - lame % + viewedofdb - viewed % of db + mylistofdb - mylist % of db + viewedofmylist - viewed % of mylist + viewedeps - number of viewed eps + votes - votes + reviews - reviews + + """ + 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.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=() - self.coderep=() - - #TODO: impl random anime - amask = cmd.parameters['amask'] - codeList = self.maper.getAnimeCodesA(amask) - self.codetail=tuple(codeList) + def __init__(self, cmd, restag, rescode, resstr, datalines): + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ANIME' + self.codehead = () + self.coderep = () + + # TODO: impl random anime + amask = cmd.parameters['amask'] + codeList = self.maper.getAnimeCodesA(amask) + self.codetail = tuple(codeList) + class AnimeBestMatchResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ANIME_BEST_MATCH' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='ANIME_BEST_MATCH' - self.codehead=() - self.codetail=() - self.coderep=() class RandomanimeResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'RANDOMANIME' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='RANDOMANIME' - self.codehead=() - self.codetail=() - self.coderep=() class EpisodeResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - eid - episode id - aid - anime id - length - length - rating - rating - votes - votes - epno - number of episode - name - english name of episode - romaji - romaji name of episode - kanji - kanji name of episode + data: + eid - episode id + aid - anime id + length - length + rating - rating + votes - votes + epno - number of episode + name - english name of episode + romaji - romaji name of episode + kanji - kanji name of episode + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'EPISODE' + self.codehead = () + self.codetail = ('eid', 'aid', 'length', 'rating', 'votes', 'epno', 'name', 'romaji', 'kanji') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='EPISODE' - self.codehead=() - self.codetail=('eid', 'aid', 'length', 'rating', 'votes', 'epno', 'name', 'romaji', 'kanji') - self.coderep=() class ProducerResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - pid - producer id - name - name of producer - shortname - short name - othername - other name - type - type - pic - picture name - url - home page url + data: + pid - producer id + name - name of producer + shortname - short name + othername - other name + type - type + pic - picture name + url - home page url + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'PRODUCER' + self.codehead = () + self.codetail = ('pid', 'name', 'shortname', 'othername', 'type', 'pic', 'url') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='PRODUCER' - self.codehead=() - self.codetail=('pid', 'name', 'shortname', 'othername', 'type', 'pic', 'url') - self.coderep=() class GroupResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + + data: + gid - group id + rating - rating + votes - votes + animes - anime count + files - file count + name - name + shortname - short + ircchannel - irc channel + ircserver - irc server + url - url + + """ + 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.coderep = () - data: - gid - group id - rating - rating - votes - votes - animes - anime count - files - file count - name - name - shortname - short - ircchannel - irc channel - ircserver - irc server - url - url - """ - 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.coderep=() - class GroupstatusResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - gid - group id - rating - rating - votes - votes - animes - anime count - files - file count - name - name - shortname - short - ircchannel - irc channel - ircserver - irc server - url - url + data: + gid - group id + rating - rating + votes - votes + animes - anime count + files - file count + name - name + shortname - short + ircchannel - irc channel + ircserver - irc server + url - url + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'GROUPSTATUS' + self.codehead = () + self.codetail = ('gid', 'name', 'state', ' last_episode_number', 'rating', 'votes', 'episode_range') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='GROUPSTATUS' - self.codehead=() - 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): - """ - attributes: - start - mylist entry number of first buddy on this packet - end - mylist entry number of last buddy on this packet - total - total number of buddies on mylist + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + start - mylist entry number of first buddy on this packet + end - mylist entry number of last buddy on this packet + total - total number of buddies on mylist - data: - uid - uid - name - username - state - state + data: + uid - uid + name - username + state - state + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'BUDDY_LIST' + self.codehead = ('start', 'end', 'total') + self.codetail = ('uid', 'username', 'state') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='BUDDY_LIST' - self.codehead=('start', 'end', 'total') - self.codetail=('uid', 'username', 'state') - self.coderep=() class BuddyStateResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: - start - mylist entry number of first buddy on this packet - end - mylist entry number of last buddy on this packet - total - total number of buddies on mylist + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + start - mylist entry number of first buddy on this packet + end - mylist entry number of last buddy on this packet + total - total number of buddies on mylist - data: - uid - uid - state - online state + data: + uid - uid + state - online state + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'BUDDY_STATE' + self.codehead = ('start', 'end', 'total') + self.codetail = ('uid', 'state') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='BUDDY_STATE' - self.codehead=('start', 'end', 'total') - self.codetail=('uid', 'state') - self.coderep=() class BuddyAddedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'BUDDY_ADDED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='BUDDY_ADDED' - self.codehead=() - self.codetail=() - self.coderep=() class BuddyDeletedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'BUDDY_DELETED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='BUDDY_DELETED' - self.codehead=() - self.codetail=() - self.coderep=() class BuddyAcceptedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'BUDDY_ACCEPTED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='BUDDY_ACCEPTED' - self.codehead=() - self.codetail=() - self.coderep=() class BuddyDeniedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'BUDDY_DENIED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='BUDDY_DENIED' - self.codehead=() - self.codetail=() - self.coderep=() class VotedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - name - aname/ename/gname + data: + name - aname/ename/gname + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'VOTED' + self.codehead = () + self.codetail = ('name',) + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='VOTED' - self.codehead=() - self.codetail=('name',) - self.coderep=() class VoteFoundResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - name - aname/ename/gname - value - vote value + data: + name - aname/ename/gname + value - vote value + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'VOTE_FOUND' + self.codehead = () + self.codetail = ('name', 'value') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='VOTE_FOUND' - self.codehead=() - self.codetail=('name', 'value') - self.coderep=() class VoteUpdatedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - name - aname/ename/gname - value - vote value + data: + name - aname/ename/gname + value - vote value + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'VOTE_UPDATED' + self.codehead = () + self.codetail = ('name', 'value') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='VOTE_UPDATED' - self.codehead=() - self.codetail=('name', 'value') - self.coderep=() class VoteRevokedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - name - aname/ename/gname - value - vote value - - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='VOTE_REVOKED' - self.codehead=() - self.codetail=('name', 'value') - self.coderep=() + data: + name - aname/ename/gname + value - vote value + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'VOTE_REVOKED' + self.codehead = () + self.codetail = ('name', 'value') + self.coderep = () class NotificationAddedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - nid - notofication id + data: + nid - notofication id + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFICATION_ITEM_ADDED' + self.codehead = () + 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 = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFICATION_ITEM_ADDED' - self.codehead=() - self.codetail=('nid') - self.coderep=() class NotificationUpdatedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - nid - notofication id + data: + nid - notofication id + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFICATION_ITEM_UPDATED' + self.codehead = () + 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',) - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFICATION_ITEM_UPDATED' - self.codehead=() - self.codetail=('nid') - self.coderep=() class NotificationEnabledResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFICATION_ENABLED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFICATION_ENABLED' - self.codehead=() - self.codetail=() - self.coderep=() class NotificationNotifyResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: - nid - notify packet id + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + nid - notify packet id - data: - aid - anime id - date - date - count - count - name - name of the anime + data: + aid - anime id + date - date + count - count + name - name of the anime + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFICATION_NOTIFY' + self.codehead = ('nid',) + self.codetail = ('aid', 'date', 'count', 'name') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFICATION_NOTIFY' - self.codehead=('nid',) - self.codetail=('aid', 'date', 'count', 'name') - self.coderep=() class NotificationMessageResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: - nid - notify packet id + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + nid - notify packet id - data: - type - type - date - date - uid - user id of the sender - name - name of the sender - subject - subject + data: + type - type + date - date + uid - user id of the sender + name - name of the sender + subject - subject + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFICATION_MESSAGE' + self.codehead = ('nid',) + self.codetail = ('type', 'date', 'uid', 'name', 'subject') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFICATION_MESSAGE' - self.codehead=('nid',) - self.codetail=('type', 'date', 'uid', 'name', 'subject') - self.coderep=() class NotificationBuddyResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: - nid - notify packet id + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + nid - notify packet id - data: - uid - buddy uid - type - event type + data: + uid - buddy uid + type - event type + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFICATION_BUDDY' + self.codehead = ('notify_packet_id',) + self.codetail = ('uid', 'type') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFICATION_BUDDY' - self.codehead=('notify_packet_id',) - self.codetail=('uid', 'type') - self.coderep=() class NotificationShutdownResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: - nid - notify packet id + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + nid - notify packet id - data: - time - time offline - comment - comment + data: + time - time offline + comment - comment + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFICATION_SHUTDOWN' + self.codehead = ('nid',) + self.codetail = ('time', 'comment') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFICATION_SHUTDOWN' - self.codehead=('nid',) - self.codetail=('time', 'comment') - self.coderep=() class PushackConfirmedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'PUSHACK_CONFIRMED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='PUSHACK_CONFIRMED' - self.codehead=() - self.codetail=() - self.coderep=() class NotifyackSuccessfulMResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFYACK_SUCCESSFUL_M' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFYACK_SUCCESSFUL_M' - self.codehead=() - self.codetail=() - self.coderep=() class NotifyackSuccessfulNResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFYACK_SUCCESSFUL_N' - self.codehead=() - self.codetail=() - self.coderep=() + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFYACK_SUCCESSFUL_N' + self.codehead = () + self.codetail = () + self.coderep = () -class NotificationResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: - data: - notifies - pending notifies - msgs - pending msgs - buddys - number of online buddys - - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFICATION' - self.codehead=() - self.coderep=() +class NotificationStateResponse(Response): + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: + + data: + notifies - pending notifies + msgs - pending msgs + buddys - number of online buddys + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFICATION' + self.codehead = () + self.coderep = () + + buddy = cmd.parameters['buddy'] + buddy = int(buddy != None and buddy or '0') + if buddy: + self.codetail = ('notifies', 'msgs', 'buddys') + else: + self.codetail = ('notifies', 'msgs') - buddy=cmd.parameters['buddy'] - buddy=int(buddy!=None and buddy or '0') - if buddy: - self.codetail=('notifies','msgs','buddys') - else: - self.codetail=('notifies','msgs') class NotifylistResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - type - type - nid - notify id + data: + type - type + nid - notify id + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFYLIST' + self.codehead = () + self.codetail = ('type', 'nid') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFYLIST' - self.codehead=() - self.codetail=('type', 'nid') - self.coderep=() class NotifygetMessageResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - nid - notify id - uid - from user id - uname - from username - date - date - type - type - title - title - body - body + data: + nid - notify id + uid - from user id + uname - from username + date - date + type - type + title - title + body - body + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFYGET_MESSAGE' + self.codehead = () + self.codetail = ('nid', 'uid', 'uname', 'date', 'type', 'title', 'body') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFYGET_MESSAGE' - self.codehead=() - self.codetail=('nid', 'uid', 'uname', 'date', 'type', 'title', 'body') - self.coderep=() class NotifygetNotifyResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - aid - aid - type - type - count - count - date - date - name - anime name + data: + aid - aid + type - type + 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', 'fid') + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFYGET_NOTIFY' - self.codehead=() - self.codetail=('aid', 'type', 'count', 'date', 'name') - self.coderep=() class SendmsgSuccessfulResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'SENDMSG_SUCCESSFUL' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='SENDMSG_SUCCESSFUL' - self.codehead=() - self.codetail=() - self.coderep=() class UserResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - uid - user id + data: + uid - user id + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'USER' + self.codehead = () + self.codetail = ('uid',) + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='USER' - self.codehead=() - self.codetail=('uid',) - self.coderep=() class PongResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'PONG' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='PONG' - self.codehead=() - self.codetail=() - self.coderep=() class AuthpongResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'AUTHPONG' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='AUTHPONG' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchResourceResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_RESOURCE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_RESOURCE' - self.codehead=() - self.codetail=() - self.coderep=() class ApiPasswordNotDefinedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'API_PASSWORD_NOT_DEFINED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='API_PASSWORD_NOT_DEFINED' - self.codehead=() - self.codetail=() - self.coderep=() class FileAlreadyInMylistResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'FILE_ALREADY_IN_MYLIST' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='FILE_ALREADY_IN_MYLIST' - self.codehead=() - self.codetail=() - self.coderep=() class MylistEntryEditedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - entries - number of entries edited + data: + entries - number of entries edited + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'MYLIST_ENTRY_EDITED' + self.codehead = () + self.codetail = ('entries',) + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='MYLIST_ENTRY_EDITED' - self.codehead=() - self.codetail=('entries',) - self.coderep=() class MultipleMylistEntriesResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - name - anime title - eps - episodes - unknowneps - eps with state unknown - hddeps - eps with state on hdd - cdeps - eps with state on cd - deletedeps - eps with state deleted - watchedeps - watched eps - gshortname - group short name - geps - eps for group + data: + name - anime title + eps - episodes + unknowneps - eps with state unknown + hddeps - eps with state on hdd + cdeps - eps with state on cd + deletedeps - eps with state deleted + watchedeps - watched eps + gshortname - group short name + geps - eps for group + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'MULTIPLE_MYLIST_ENTRIES' + self.codehead = () + self.codetail = ('name', 'eps', 'unknowneps', 'hddeps', 'cdeps', 'deletedeps', 'watchedeps') + self.coderep = ('gshortname', 'geps') - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='MULTIPLE_MYLIST_ENTRIES' - self.codehead=() - self.codetail=('name', 'eps', 'unknowneps', 'hddeps', 'cdeps', 'deletedeps', 'watchedeps') - self.coderep=('gshortname', 'geps') class SizeHashExistsResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'SIZE_HASH_EXISTS' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='SIZE_HASH_EXISTS' - self.codehead=() - self.codetail=() - self.coderep=() class InvalidDataResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'INVALID_DATA' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='INVALID_DATA' - self.codehead=() - self.codetail=() - self.coderep=() class StreamnoidUsedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'STREAMNOID_USED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='STREAMNOID_USED' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchFileResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_FILE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_FILE' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchEntryResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_ENTRY' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_ENTRY' - self.codehead=() - self.codetail=() - self.coderep=() class MultipleFilesFoundResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - fid - file id + data: + fid - file id + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'MULTIPLE_FILES_FOUND' + self.codehead = () + 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 = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='MULTIPLE_FILES_FOUND' - self.codehead=() - self.codetail=() - self.coderep=('fid',) class NoGroupsFoundResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO GROUPS FOUND' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO GROUPS FOUND' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchAnimeResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_ANIME' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_ANIME' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchEpisodeResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_EPISODE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_EPISODE' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchProducerResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_PRODUCER' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_PRODUCER' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchGroupResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_GROUP' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_GROUP' - self.codehead=() - self.codetail=() - self.coderep=() class BuddyAlreadyAddedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'BUDDY_ALREADY_ADDED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='BUDDY_ALREADY_ADDED' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchBuddyResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_BUDDY' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_BUDDY' - self.codehead=() - self.codetail=() - self.coderep=() class BuddyAlreadyAcceptedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'BUDDY_ALREADY_ACCEPTED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='BUDDY_ALREADY_ACCEPTED' - self.codehead=() - self.codetail=() - self.coderep=() class BuddyAlreadyDeniedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'BUDDY_ALREADY_DENIED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='BUDDY_ALREADY_DENIED' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchVoteResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_VOTE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_VOTE' - self.codehead=() - self.codetail=() - self.coderep=() class InvalidVoteTypeResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'INVALID_VOTE_TYPE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='INVALID_VOTE_TYPE' - self.codehead=() - self.codetail=() - self.coderep=() class InvalidVoteValueResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'INVALID_VOTE_VALUE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='INVALID_VOTE_VALUE' - self.codehead=() - self.codetail=() - self.coderep=() class PermvoteNotAllowedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - aname - name of the anime + data: + aname - name of the anime + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'PERMVOTE_NOT_ALLOWED' + self.codehead = () + self.codetail = ('aname',) + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='PERMVOTE_NOT_ALLOWED' - self.codehead=() - self.codetail=('aname',) - self.coderep=() class AlreadyPermvotedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - name - aname/ename/gname + data: + name - aname/ename/gname + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ALREADY_PERMVOTED' + self.codehead = () + self.codetail = ('name',) + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='ALREADY_PERMVOTED' - self.codehead=() - self.codetail=('name',) - self.coderep=() class NotificationDisabledResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOTIFICATION_DISABLED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOTIFICATION_DISABLED' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchPacketPendingResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_PACKET_PENDING' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_PACKET_PENDING' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchEntryMResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_ENTRY_M' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_ENTRY_M' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchEntryNResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_ENTRY_N' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_ENTRY_N' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchMessageResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_MESSAGE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_MESSAGE' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchNotifyResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_NOTIFY' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_NOTIFY' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchUserResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_USER' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_USER' - self.codehead=() - self.codetail=() - self.coderep=() class NoChanges(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_CHANGES' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_CHANGES' - self.codehead=() - self.codetail=() - self.coderep=() class NotLoggedInResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NOT_LOGGED_IN' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NOT_LOGGED_IN' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchMylistFileResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_MYLIST_FILE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_MYLIST_FILE' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchMylistEntryResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_MYLIST_ENTRY' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_MYLIST_ENTRY' - self.codehead=() - self.codetail=() - self.coderep=() class LoginFailedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'LOGIN_FAILED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='LOGIN_FAILED' - self.codehead=() - self.codetail=() - self.coderep=() class LoginFirstResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'LOGIN_FIRST' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='LOGIN_FIRST' - self.codehead=() - self.codetail=() - self.coderep=() class AccessDeniedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ACCESS_DENIED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='ACCESS_DENIED' - self.codehead=() - self.codetail=() - self.coderep=() class ClientVersionOutdatedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'CLIENT_VERSION_OUTDATED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='CLIENT_VERSION_OUTDATED' - self.codehead=() - self.codetail=() - self.coderep=() class ClientBannedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'CLIENT_BANNED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='CLIENT_BANNED' - self.codehead=() - self.codetail=() - self.coderep=() class IllegalInputOrAccessDeniedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ILLEGAL_INPUT_OR_ACCESS_DENIED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='ILLEGAL_INPUT_OR_ACCESS_DENIED' - self.codehead=() - self.codetail=() - self.coderep=() class InvalidSessionResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'INVALID_SESSION' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='INVALID_SESSION' - self.codehead=() - self.codetail=() - self.coderep=() class NoSuchEncryptionTypeResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'NO_SUCH_ENCRYPTION_TYPE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='NO_SUCH_ENCRYPTION_TYPE' - self.codehead=() - self.codetail=() - self.coderep=() class EncodingNotSupportedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ENCODING_NOT_SUPPORTED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='ENCODING_NOT_SUPPORTED' - self.codehead=() - self.codetail=() - self.coderep=() class BannedResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'BANNED' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='BANNED' - self.codehead=() - self.codetail=() - self.coderep=() class UnknownCommandResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'UNKNOWN_COMMAND' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='UNKNOWN_COMMAND' - self.codehead=() - self.codetail=() - self.coderep=() class InternalServerErrorResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'INTERNAL_SERVER_ERROR' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='INTERNAL_SERVER_ERROR' - self.codehead=() - self.codetail=() - self.coderep=() class AnidbOutOfServiceResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'ANIDB_OUT_OF_SERVICE' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='ANIDB_OUT_OF_SERVICE' - self.codehead=() - self.codetail=() - self.coderep=() class ServerBusyResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'SERVER_BUSY' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='SERVER_BUSY' - self.codehead=() - self.codetail=() - self.coderep=() class ApiViolationResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: + data: + + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'API_VIOLATION' + self.codehead = () + self.codetail = () + self.coderep = () - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='API_VIOLATION' - self.codehead=() - self.codetail=() - self.coderep=() class VersionResponse(Response): - def __init__(self,cmd,restag,rescode,resstr,datalines): - """ - attributes: + def __init__(self, cmd, restag, rescode, resstr, datalines): + """ + attributes: - data: - version - server version + data: + version - server version - """ - Response.__init__(self,cmd,restag,rescode,resstr,datalines) - self.codestr='VERSION' - self.codehead=() - self.codetail=('version',) - self.coderep=() + """ + Response.__init__(self, cmd, restag, rescode, resstr, datalines) + self.codestr = 'VERSION' + self.codehead = () + self.codetail = ('version',) + self.coderep = () -responses={ - '200':LoginAcceptedResponse, - '201':LoginAcceptedNewVerResponse, - '203':LoggedOutResponse, - '205':ResourceResponse, - '206':StatsResponse, - '207':TopResponse, - '208':UptimeResponse, - '209':EncryptionEnabledResponse, - '210':MylistEntryAddedResponse, - '211':MylistEntryDeletedResponse, - '214':AddedFileResponse, - '215':AddedStreamResponse, - '219':EncodingChangedResponse, - '220':FileResponse, - '221':MylistResponse, - '222':MylistStatsResponse, - '225':GroupstatusResponse, - '230':AnimeResponse, - '231':AnimeBestMatchResponse, - '232':RandomanimeResponse, - '240':EpisodeResponse, - '245':ProducerResponse, - '246':NotificationAddedResponse, - '248':NotificationUpdatedResponse, - '250':GroupResponse, - '253':BuddyListResponse, - '254':BuddyStateResponse, - '255':BuddyAddedResponse, - '256':BuddyDeletedResponse, - '257':BuddyAcceptedResponse, - '258':BuddyDeniedResponse, - '260':VotedResponse, - '261':VoteFoundResponse, - '262':VoteUpdatedResponse, - '263':VoteRevokedResponse, - '270':NotificationEnabledResponse, - '271':NotificationNotifyResponse, - '272':NotificationMessageResponse, - '273':NotificationBuddyResponse, - '274':NotificationShutdownResponse, - '280':PushackConfirmedResponse, - '281':NotifyackSuccessfulMResponse, - '282':NotifyackSuccessfulNResponse, - '290':NotificationResponse, - '291':NotifylistResponse, - '292':NotifygetMessageResponse, - '293':NotifygetNotifyResponse, - '294':SendmsgSuccessfulResponse, - '295':UserResponse, - '300':PongResponse, - '301':AuthpongResponse, - '305':NoSuchResourceResponse, - '309':ApiPasswordNotDefinedResponse, - '310':FileAlreadyInMylistResponse, - '311':MylistEntryEditedResponse, - '312':MultipleMylistEntriesResponse, - '314':SizeHashExistsResponse, - '315':InvalidDataResponse, - '316':StreamnoidUsedResponse, - '320':NoSuchFileResponse, - '321':NoSuchEntryResponse, - '322':MultipleFilesFoundResponse, - '325':NoGroupsFoundResponse, - '330':NoSuchAnimeResponse, - '340':NoSuchEpisodeResponse, - '345':NoSuchProducerResponse, - '350':NoSuchGroupResponse, - '355':BuddyAlreadyAddedResponse, - '356':NoSuchBuddyResponse, - '357':BuddyAlreadyAcceptedResponse, - '358':BuddyAlreadyDeniedResponse, - '360':NoSuchVoteResponse, - '361':InvalidVoteTypeResponse, - '362':InvalidVoteValueResponse, - '363':PermvoteNotAllowedResponse, - '364':AlreadyPermvotedResponse, - '370':NotificationDisabledResponse, - '380':NoSuchPacketPendingResponse, - '381':NoSuchEntryMResponse, - '382':NoSuchEntryNResponse, - '392':NoSuchMessageResponse, - '393':NoSuchNotifyResponse, - '394':NoSuchUserResponse, - '399':NoChanges, - '403':NotLoggedInResponse, - '410':NoSuchMylistFileResponse, - '411':NoSuchMylistEntryResponse, - '500':LoginFailedResponse, - '501':LoginFirstResponse, - '502':AccessDeniedResponse, - '503':ClientVersionOutdatedResponse, - '504':ClientBannedResponse, - '505':IllegalInputOrAccessDeniedResponse, - '506':InvalidSessionResponse, - '509':NoSuchEncryptionTypeResponse, - '519':EncodingNotSupportedResponse, - '555':BannedResponse, - '598':UnknownCommandResponse, - '600':InternalServerErrorResponse, - '601':AnidbOutOfServiceResponse, - '602':ServerBusyResponse, - '666':ApiViolationResponse, - '998':VersionResponse +responses = { + '200': LoginAcceptedResponse, + '201': LoginAcceptedNewVerResponse, + '203': LoggedOutResponse, + '205': ResourceResponse, + '206': StatsResponse, + '207': TopResponse, + '208': UptimeResponse, + '209': EncryptionEnabledResponse, + '210': MylistEntryAddedResponse, + '211': MylistEntryDeletedResponse, + '214': AddedFileResponse, + '215': AddedStreamResponse, + '219': EncodingChangedResponse, + '220': FileResponse, + '221': MylistResponse, + '222': MylistStatsResponse, + '224': NotificationResponse, + '225': GroupstatusResponse, + '230': AnimeResponse, + '231': AnimeBestMatchResponse, + '232': RandomanimeResponse, + '240': EpisodeResponse, + '245': ProducerResponse, + '246': NotificationAddedResponse, + '247': NotificationDeletedResponse, + '248': NotificationUpdatedResponse, + '249': MultipleNotificationResponse, + '250': GroupResponse, + '253': BuddyListResponse, + '254': BuddyStateResponse, + '255': BuddyAddedResponse, + '256': BuddyDeletedResponse, + '257': BuddyAcceptedResponse, + '258': BuddyDeniedResponse, + '260': VotedResponse, + '261': VoteFoundResponse, + '262': VoteUpdatedResponse, + '263': VoteRevokedResponse, + '270': NotificationEnabledResponse, + '271': NotificationNotifyResponse, + '272': NotificationMessageResponse, + '273': NotificationBuddyResponse, + '274': NotificationShutdownResponse, + '280': PushackConfirmedResponse, + '281': NotifyackSuccessfulMResponse, + '282': NotifyackSuccessfulNResponse, + '290': NotificationStateResponse, + '291': NotifylistResponse, + '292': NotifygetMessageResponse, + '293': NotifygetNotifyResponse, + '294': SendmsgSuccessfulResponse, + '295': UserResponse, + '300': PongResponse, + '301': AuthpongResponse, + '305': NoSuchResourceResponse, + '309': ApiPasswordNotDefinedResponse, + '310': FileAlreadyInMylistResponse, + '311': MylistEntryEditedResponse, + '312': MultipleMylistEntriesResponse, + '314': SizeHashExistsResponse, + '315': InvalidDataResponse, + '316': StreamnoidUsedResponse, + '320': NoSuchFileResponse, + '321': NoSuchEntryResponse, + '322': MultipleFilesFoundResponse, + '324': NoSuchNotificationResponse, + '325': NoGroupsFoundResponse, + '330': NoSuchAnimeResponse, + '340': NoSuchEpisodeResponse, + '345': NoSuchProducerResponse, + '350': NoSuchGroupResponse, + '355': BuddyAlreadyAddedResponse, + '356': NoSuchBuddyResponse, + '357': BuddyAlreadyAcceptedResponse, + '358': BuddyAlreadyDeniedResponse, + '360': NoSuchVoteResponse, + '361': InvalidVoteTypeResponse, + '362': InvalidVoteValueResponse, + '363': PermvoteNotAllowedResponse, + '364': AlreadyPermvotedResponse, + '370': NotificationDisabledResponse, + '380': NoSuchPacketPendingResponse, + '381': NoSuchEntryMResponse, + '382': NoSuchEntryNResponse, + '392': NoSuchMessageResponse, + '393': NoSuchNotifyResponse, + '394': NoSuchUserResponse, + '399': NoChanges, + '403': NotLoggedInResponse, + '410': NoSuchMylistFileResponse, + '411': NoSuchMylistEntryResponse, + '500': LoginFailedResponse, + '501': LoginFirstResponse, + '502': AccessDeniedResponse, + '503': ClientVersionOutdatedResponse, + '504': ClientBannedResponse, + '505': IllegalInputOrAccessDeniedResponse, + '506': InvalidSessionResponse, + '509': NoSuchEncryptionTypeResponse, + '519': EncodingNotSupportedResponse, + '555': BannedResponse, + '598': UnknownCommandResponse, + '600': InternalServerErrorResponse, + '601': AnidbOutOfServiceResponse, + '602': ServerBusyResponse, + '666': ApiViolationResponse, + '998': VersionResponse } diff --git a/lib/tvdb_api/tvdb_api.py b/lib/tvdb_api/tvdb_api.py index bb81599d..68071a29 100644 --- a/lib/tvdb_api/tvdb_api.py +++ b/lib/tvdb_api/tvdb_api.py @@ -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, diff --git a/lib/tvrage_api/tvrage_api.py b/lib/tvrage_api/tvrage_api.py index 24bc2f9f..09943837 100644 --- a/lib/tvrage_api/tvrage_api.py +++ b/lib/tvrage_api/tvrage_api.py @@ -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: diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index c9390ac2..88248e48 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -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) diff --git a/sickbeard/browser.py b/sickbeard/browser.py index 86fb54ba..72d47bd0 100644 --- a/sickbeard/browser.py +++ b/sickbeard/browser.py @@ -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) diff --git a/sickbeard/classes.py b/sickbeard/classes.py index 3622d6ea..962df06e 100644 --- a/sickbeard/classes.py +++ b/sickbeard/classes.py @@ -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 diff --git a/sickbeard/clients/transmission.py b/sickbeard/clients/transmission.py index 100f3d19..af55f9ef 100644 --- a/sickbeard/clients/transmission.py +++ b/sickbeard/clients/transmission.py @@ -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]} diff --git a/sickbeard/dailysearcher.py b/sickbeard/dailysearcher.py index e7c4d13e..221b6b8d 100644 --- a/sickbeard/dailysearcher.py +++ b/sickbeard/dailysearcher.py @@ -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 \ No newline at end of file diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py index d95ce049..a1c87a63 100644 --- a/sickbeard/helpers.py +++ b/sickbeard/helpers.py @@ -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: diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py index 0076a0cf..e4b97e7d 100755 --- a/sickbeard/providers/__init__.py +++ b/sickbeard/providers/__init__.py @@ -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 . @@ -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): diff --git a/sickbeard/providers/animezb.py b/sickbeard/providers/animezb.py index 69b0db91..2260227b 100644 --- a/sickbeard/providers/animezb.py +++ b/sickbeard/providers/animezb.py @@ -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'), diff --git a/sickbeard/providers/bitsoup.py b/sickbeard/providers/bitsoup.py index 2500353a..1dce5355 100644 --- a/sickbeard/providers/bitsoup.py +++ b/sickbeard/providers/bitsoup.py @@ -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) diff --git a/sickbeard/providers/btn.py b/sickbeard/providers/btn.py index 4786ff91..6f16ea65 100644 --- a/sickbeard/providers/btn.py +++ b/sickbeard/providers/btn.py @@ -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())) diff --git a/sickbeard/providers/ezrss.py b/sickbeard/providers/ezrss.py index feb1765e..6249c7ec 100644 --- a/sickbeard/providers/ezrss.py +++ b/sickbeard/providers/ezrss.py @@ -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) diff --git a/sickbeard/providers/fanzub.py b/sickbeard/providers/fanzub.py index 0ad73ccb..3f590778 100644 --- a/sickbeard/providers/fanzub.py +++ b/sickbeard/providers/fanzub.py @@ -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'), diff --git a/sickbeard/providers/freshontv.py b/sickbeard/providers/freshontv.py index bab6ea7d..874a934f 100755 --- a/sickbeard/providers/freshontv.py +++ b/sickbeard/providers/freshontv.py @@ -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) diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py index 6241e2a8..95bdc169 100644 --- a/sickbeard/providers/generic.py +++ b/sickbeard/providers/generic.py @@ -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 diff --git a/sickbeard/providers/hdbits.py b/sickbeard/providers/hdbits.py index 85cd6017..19a31cc5 100644 --- a/sickbeard/providers/hdbits.py +++ b/sickbeard/providers/hdbits.py @@ -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): diff --git a/sickbeard/providers/hdtorrents.py b/sickbeard/providers/hdtorrents.py index a02afbad..e011d010 100644 --- a/sickbeard/providers/hdtorrents.py +++ b/sickbeard/providers/hdtorrents.py @@ -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) diff --git a/sickbeard/providers/iptorrents.py b/sickbeard/providers/iptorrents.py index e24bb328..2313efb9 100644 --- a/sickbeard/providers/iptorrents.py +++ b/sickbeard/providers/iptorrents.py @@ -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) diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py index a24eead5..5bea6248 100644 --- a/sickbeard/providers/kat.py +++ b/sickbeard/providers/kat.py @@ -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) diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py index 9065efc5..d4686b52 100755 --- a/sickbeard/providers/newznab.py +++ b/sickbeard/providers/newznab.py @@ -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 diff --git a/sickbeard/providers/nextgen.py b/sickbeard/providers/nextgen.py index 09cca9b9..de5ab0c9 100644 --- a/sickbeard/providers/nextgen.py +++ b/sickbeard/providers/nextgen.py @@ -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) diff --git a/sickbeard/providers/nyaatorrents.py b/sickbeard/providers/nyaatorrents.py index 2ac991cb..d7f9e3b7 100644 --- a/sickbeard/providers/nyaatorrents.py +++ b/sickbeard/providers/nyaatorrents.py @@ -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 diff --git a/sickbeard/providers/omgwtfnzbs.py b/sickbeard/providers/omgwtfnzbs.py index 2e0728c2..59985055 100644 --- a/sickbeard/providers/omgwtfnzbs.py +++ b/sickbeard/providers/omgwtfnzbs.py @@ -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, diff --git a/sickbeard/providers/rsstorrent.py b/sickbeard/providers/rsstorrent.py index 936b4623..3cf27c8a 100644 --- a/sickbeard/providers/rsstorrent.py +++ b/sickbeard/providers/rsstorrent.py @@ -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) diff --git a/sickbeard/providers/scc.py b/sickbeard/providers/scc.py index 2dc0c31f..36439489 100644 --- a/sickbeard/providers/scc.py +++ b/sickbeard/providers/scc.py @@ -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) diff --git a/sickbeard/providers/speedcd.py b/sickbeard/providers/speedcd.py index a2ee3bb9..9839b880 100644 --- a/sickbeard/providers/speedcd.py +++ b/sickbeard/providers/speedcd.py @@ -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) diff --git a/sickbeard/providers/thepiratebay.py b/sickbeard/providers/thepiratebay.py index dd7d841d..eaf970f7 100644 --- a/sickbeard/providers/thepiratebay.py +++ b/sickbeard/providers/thepiratebay.py @@ -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) diff --git a/sickbeard/providers/torrentbytes.py b/sickbeard/providers/torrentbytes.py index d8f646cb..dd7f39d9 100644 --- a/sickbeard/providers/torrentbytes.py +++ b/sickbeard/providers/torrentbytes.py @@ -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) diff --git a/sickbeard/providers/torrentday.py b/sickbeard/providers/torrentday.py index e1d78d8d..eacaa21e 100644 --- a/sickbeard/providers/torrentday.py +++ b/sickbeard/providers/torrentday.py @@ -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) diff --git a/sickbeard/providers/torrentleech.py b/sickbeard/providers/torrentleech.py index 69401a55..8dfb1731 100644 --- a/sickbeard/providers/torrentleech.py +++ b/sickbeard/providers/torrentleech.py @@ -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) diff --git a/sickbeard/providers/tvtorrents.py b/sickbeard/providers/tvtorrents.py index b9364a49..227c1941 100644 --- a/sickbeard/providers/tvtorrents.py +++ b/sickbeard/providers/tvtorrents.py @@ -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" diff --git a/sickbeard/rssfeeds.py b/sickbeard/rssfeeds.py index 9c59f9d9..6bbc975c 100644 --- a/sickbeard/rssfeeds.py +++ b/sickbeard/rssfeeds.py @@ -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) \ No newline at end of file diff --git a/sickbeard/scene_numbering.py b/sickbeard/scene_numbering.py index 49e25dd8..79786a53 100644 --- a/sickbeard/scene_numbering.py +++ b/sickbeard/scene_numbering.py @@ -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) diff --git a/sickbeard/search.py b/sickbeard/search.py index 0668c216..f9b651a4 100644 --- a/sickbeard/search.py +++ b/sickbeard/search.py @@ -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) diff --git a/sickbeard/searchBacklog.py b/sickbeard/searchBacklog.py index 4bccad8f..1abe44c7 100644 --- a/sickbeard/searchBacklog.py +++ b/sickbeard/searchBacklog.py @@ -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( diff --git a/sickbeard/search_queue.py b/sickbeard/search_queue.py index bbda755a..5616fc15 100644 --- a/sickbeard/search_queue.py +++ b/sickbeard/search_queue.py @@ -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] diff --git a/sickbeard/tv.py b/sickbeard/tv.py index 6e32c325..862838f3 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -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() diff --git a/sickbeard/tvcache.py b/sickbeard/tvcache.py index 96b79499..1dd52d49 100644 --- a/sickbeard/tvcache.py +++ b/sickbeard/tvcache.py @@ -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() diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 5c24086f..f05bf557 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -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&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&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('%s has been deleted' % showObj.name) redirect("/home/")