diff options
Diffstat (limited to 'src/common/xmpp/roster_nb.py')
-rw-r--r-- | src/common/xmpp/roster_nb.py | 314 |
1 files changed, 211 insertions, 103 deletions
diff --git a/src/common/xmpp/roster_nb.py b/src/common/xmpp/roster_nb.py index 715476b9e..f343c8341 100644 --- a/src/common/xmpp/roster_nb.py +++ b/src/common/xmpp/roster_nb.py @@ -16,10 +16,11 @@ # $Id: roster.py,v 1.17 2005/05/02 08:38:49 snakeru Exp $ -''' + +""" Simple roster implementation. Can be used though for different tasks like mass-renaming of contacts. -''' +""" from protocol import JID, Iq, Presence, Node, NodeProcessed, NS_MUC_USER, NS_ROSTER from plugin import PlugIn @@ -29,15 +30,18 @@ log = logging.getLogger('gajim.c.x.roster_nb') class NonBlockingRoster(PlugIn): - ''' Defines a plenty of methods that will allow you to manage roster. - Also automatically track presences from remote JIDs taking into - account that every JID can have multiple resources connected. Does not - currently support 'error' presences. - You can also use mapping interface for access to the internal representation of - contacts in roster. - ''' + """ + Defines a plenty of methods that will allow you to manage roster. Also + automatically track presences from remote JIDs taking into account that + every JID can have multiple resources connected. Does not currently support + 'error' presences. You can also use mapping interface for access to the + internal representation of contacts in roster + """ + def __init__(self, version=''): - ''' Init internal variables. ''' + """ + Init internal variables + """ PlugIn.__init__(self) self.version = version self._data = {} @@ -45,11 +49,15 @@ class NonBlockingRoster(PlugIn): self._exported_methods=[self.getRoster] self.received_from_server = False - def Request(self,force=0): - ''' Request roster from server if it were not yet requested - (or if the 'force' argument is set). ''' - if self.set is None: self.set=0 - elif not force: return + def Request(self, force=0): + """ + Request roster from server if it were not yet requested (or if the + 'force' argument is set) + """ + if self.set is None: + self.set = 0 + elif not force: + return iq = Iq('get',NS_ROSTER) iq.setTagAttr('query', 'ver', self.version) @@ -59,9 +67,11 @@ class NonBlockingRoster(PlugIn): log.info('Roster requested from server') return id_ - def RosterIqHandler(self,dis,stanza): - ''' Subscription tracker. Used internally for setting items state in - internal roster representation. ''' + def RosterIqHandler(self, dis, stanza): + """ + Subscription tracker. Used internally for setting items state in internal + roster representation + """ sender = stanza.getAttr('from') if not sender is None and not sender.bareMatch( self._owner.User + '@' + self._owner.Server): @@ -85,15 +95,19 @@ class NonBlockingRoster(PlugIn): self._data[jid]['subscription']=item.getAttr('subscription') self._data[jid]['groups']=[] if not self._data[jid].has_key('resources'): self._data[jid]['resources']={} - for group in item.getTags('group'): self._data[jid]['groups'].append(group.getData()) + for group in item.getTags('group'): + if group.getData() not in self._data[jid]['groups']: + self._data[jid]['groups'].append(group.getData()) self._data[self._owner.User+'@'+self._owner.Server]={'resources':{},'name':None,'ask':None,'subscription':None,'groups':None,} self.set=1 # Looks like we have a workaround # raise NodeProcessed # a MUST. Otherwise you'll get back an <iq type='error'/> - def PresenceHandler(self,dis,pres): - ''' Presence tracker. Used internally for setting items' resources state in - internal roster representation. ''' + def PresenceHandler(self, dis, pres): + """ + Presence tracker. Used internally for setting items' resources state in + internal roster representation + """ if pres.getTag('x', namespace=NS_MUC_USER): return jid=pres.getFrom() @@ -118,112 +132,204 @@ class NonBlockingRoster(PlugIn): elif typ=='unavailable' and item['resources'].has_key(jid.getResource()): del item['resources'][jid.getResource()] # Need to handle type='error' also - def _getItemData(self,jid,dataname): - ''' Return specific jid's representation in internal format. Used internally. ''' - jid=jid[:(jid+'/').find('/')] + def _getItemData(self, jid, dataname): + """ + Return specific jid's representation in internal format. Used internally + """ + jid = jid[:(jid+'/').find('/')] return self._data[jid][dataname] - def _getResourceData(self,jid,dataname): - ''' Return specific jid's resource representation in internal format. Used internally. ''' - if jid.find('/')+1: - jid,resource=jid.split('/',1) - if self._data[jid]['resources'].has_key(resource): return self._data[jid]['resources'][resource][dataname] + + def _getResourceData(self, jid, dataname): + """ + Return specific jid's resource representation in internal format. Used + internally + """ + if jid.find('/') + 1: + jid, resource = jid.split('/', 1) + if self._data[jid]['resources'].has_key(resource): + return self._data[jid]['resources'][resource][dataname] elif self._data[jid]['resources'].keys(): - lastpri=-129 + lastpri = -129 for r in self._data[jid]['resources'].keys(): - if int(self._data[jid]['resources'][r]['priority'])>lastpri: resource,lastpri=r,int(self._data[jid]['resources'][r]['priority']) + if int(self._data[jid]['resources'][r]['priority']) > lastpri: + resource,lastpri=r,int(self._data[jid]['resources'][r]['priority']) return self._data[jid]['resources'][resource][dataname] - def delItem(self,jid): - ''' Delete contact 'jid' from roster.''' - self._owner.send(Iq('set',NS_ROSTER,payload=[Node('item',{'jid':jid,'subscription':'remove'})])) - def getAsk(self,jid): - ''' Returns 'ask' value of contact 'jid'.''' - return self._getItemData(jid,'ask') - def getGroups(self,jid): - ''' Returns groups list that contact 'jid' belongs to.''' - return self._getItemData(jid,'groups') - def getName(self,jid): - ''' Returns name of contact 'jid'.''' - return self._getItemData(jid,'name') - def getPriority(self,jid): - ''' Returns priority of contact 'jid'. 'jid' should be a full (not bare) JID.''' - return self._getResourceData(jid,'priority') + + def delItem(self, jid): + """ + Delete contact 'jid' from roster + """ + self._owner.send(Iq('set', NS_ROSTER, payload=[Node('item', {'jid': jid, 'subscription': 'remove'})])) + + def getAsk(self, jid): + """ + Return 'ask' value of contact 'jid' + """ + return self._getItemData(jid, 'ask') + + def getGroups(self, jid): + """ + Return groups list that contact 'jid' belongs to + """ + return self._getItemData(jid, 'groups') + + def getName(self, jid): + """ + Return name of contact 'jid' + """ + return self._getItemData(jid, 'name') + + def getPriority(self, jid): + """ + Return priority of contact 'jid'. 'jid' should be a full (not bare) JID + """ + return self._getResourceData(jid, 'priority') + def getRawRoster(self): - ''' Returns roster representation in internal format. ''' + """ + Return roster representation in internal format + """ return self._data - def getRawItem(self,jid): - ''' Returns roster item 'jid' representation in internal format. ''' + + def getRawItem(self, jid): + """ + Return roster item 'jid' representation in internal format + """ return self._data[jid[:(jid+'/').find('/')]] + def getShow(self, jid): - ''' Returns 'show' value of contact 'jid'. 'jid' should be a full (not bare) JID.''' - return self._getResourceData(jid,'show') + """ + Return 'show' value of contact 'jid'. 'jid' should be a full (not bare) + JID + """ + return self._getResourceData(jid, 'show') + def getStatus(self, jid): - ''' Returns 'status' value of contact 'jid'. 'jid' should be a full (not bare) JID.''' - return self._getResourceData(jid,'status') - def getSubscription(self,jid): - ''' Returns 'subscription' value of contact 'jid'.''' - return self._getItemData(jid,'subscription') - def getResources(self,jid): - ''' Returns list of connected resources of contact 'jid'.''' + """ + Return 'status' value of contact 'jid'. 'jid' should be a full (not bare) + JID + """ + return self._getResourceData(jid, 'status') + + def getSubscription(self, jid): + """ + Return 'subscription' value of contact 'jid' + """ + return self._getItemData(jid, 'subscription') + + def getResources(self, jid): + """ + Return list of connected resources of contact 'jid' + """ return self._data[jid[:(jid+'/').find('/')]]['resources'].keys() - def setItem(self,jid,name=None,groups=[]): - ''' Renames contact 'jid' and sets the groups list that it now belongs to.''' - iq=Iq('set',NS_ROSTER) - query=iq.getTag('query') - attrs={'jid':jid} - if name: attrs['name']=name - item=query.setTag('item',attrs) - for group in groups: item.addChild(node=Node('group',payload=[group])) + + def setItem(self, jid, name=None, groups=[]): + """ + Rename contact 'jid' and sets the groups list that it now belongs to + """ + iq = Iq('set',NS_ROSTER) + query = iq.getTag('query') + attrs = {'jid': jid} + if name: + attrs['name'] = name + item = query.setTag('item' ,attrs) + for group in groups: + item.addChild(node=Node('group', payload=[group])) self._owner.send(iq) - def setItemMulti(self,items): - ''' Renames multiple contacts and sets their group lists.''' - iq=Iq('set',NS_ROSTER) - query=iq.getTag('query') + + def setItemMulti(self, items): + """ + Rename multiple contacts and sets their group lists + """ + iq = Iq('set', NS_ROSTER) + query = iq.getTag('query') for i in items: - attrs={'jid':i['jid']} - if i['name']: attrs['name']=i['name'] - item=query.setTag('item',attrs) - for group in i['groups']: item.addChild(node=Node('group',payload=[group])) + attrs = {'jid': i['jid']} + if i['name']: + attrs['name'] = i['name'] + item = query.setTag('item', attrs) + for group in i['groups']: + item.addChild(node=Node('group', payload=[group])) self._owner.send(iq) + def getItems(self): - ''' Return list of all [bare] JIDs that the roster is currently tracks.''' + """ + Return list of all [bare] JIDs that the roster is currently tracks + """ return self._data.keys() + def keys(self): - ''' Same as getItems. Provided for the sake of dictionary interface.''' + """ + Same as getItems. Provided for the sake of dictionary interface + """ return self._data.keys() - def __getitem__(self,item): - ''' Get the contact in the internal format. Raises KeyError if JID 'item' is not in roster.''' + + def __getitem__(self, item): + """ + Get the contact in the internal format. Raises KeyError if JID 'item' is + not in roster + """ return self._data[item] + def getItem(self,item): - ''' Get the contact in the internal format (or None if JID 'item' is not in roster).''' - if self._data.has_key(item): return self._data[item] - def Subscribe(self,jid): - ''' Send subscription request to JID 'jid'.''' - self._owner.send(Presence(jid,'subscribe')) + """ + Get the contact in the internal format (or None if JID 'item' is not in + roster) + """ + if self._data.has_key(item): + return self._data[item] + + def Subscribe(self, jid): + """ + Send subscription request to JID 'jid' + """ + self._owner.send(Presence(jid, 'subscribe')) + def Unsubscribe(self,jid): - ''' Ask for removing our subscription for JID 'jid'.''' - self._owner.send(Presence(jid,'unsubscribe')) - def Authorize(self,jid): - ''' Authorise JID 'jid'. Works only if these JID requested auth previously. ''' - self._owner.send(Presence(jid,'subscribed')) - def Unauthorize(self,jid): - ''' Unauthorise JID 'jid'. Use for declining authorisation request - or for removing existing authorization. ''' - self._owner.send(Presence(jid,'unsubscribed')) + """ + Ask for removing our subscription for JID 'jid' + """ + self._owner.send(Presence(jid, 'unsubscribe')) + + def Authorize(self, jid): + """ + Authorize JID 'jid'. Works only if these JID requested auth previously + """ + self._owner.send(Presence(jid, 'subscribed')) + + def Unauthorize(self, jid): + """ + Unauthorise JID 'jid'. Use for declining authorisation request or for + removing existing authorization + """ + self._owner.send(Presence(jid, 'unsubscribed')) + def getRaw(self): - '''Returns the internal data representation of the roster.''' + """ + Return the internal data representation of the roster + """ return self._data + def setRaw(self, data): - '''Returns the internal data representation of the roster.''' + """ + Return the internal data representation of the roster + """ self._data = data - self._data[self._owner.User+'@'+self._owner.Server]={'resources':{},'name':None,'ask':None,'subscription':None,'groups':None,} - self.set=1 - # copypasted methods for roster.py from constructor to here - + self._data[self._owner.User + '@' + self._owner.Server] = { + 'resources': {}, + 'name': None, + 'ask': None, + 'subscription': None, + 'groups': None + } + self.set = 1 def plugin(self, owner, request=1): - ''' Register presence and subscription trackers in the owner's dispatcher. - Also request roster from server if the 'request' argument is set. - Used internally.''' + """ + Register presence and subscription trackers in the owner's dispatcher. + Also request roster from server if the 'request' argument is set. Used + internally + """ self._owner.RegisterHandler('iq', self.RosterIqHandler, 'result', NS_ROSTER, makefirst = 1) self._owner.RegisterHandler('iq', self.RosterIqHandler, 'set', NS_ROSTER) self._owner.RegisterHandler('presence', self.PresenceHandler) @@ -242,7 +348,9 @@ class NonBlockingRoster(PlugIn): return True def getRoster(self, on_ready=None, force=False): - ''' Requests roster from server if neccessary and returns self. ''' + """ + Request roster from server if neccessary and returns self + """ return_self = True if not self.set: self.on_ready = on_ready |