From ff6fc44215c07ef112c59dec32ed753cd30a460c Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Mon, 18 Jun 2012 17:28:58 -0700 Subject: [PATCH] Simplify tracking last sent presence using outgoing filters. --- sleekxmpp/basexmpp.py | 14 ++--------- sleekxmpp/roster/item.py | 31 ++++++++++-------------- sleekxmpp/roster/multi.py | 49 +++++++++++++++++++++++++++++--------- sleekxmpp/roster/single.py | 31 ++++++++---------------- 4 files changed, 63 insertions(+), 62 deletions(-) diff --git a/sleekxmpp/basexmpp.py b/sleekxmpp/basexmpp.py index 4f48f809..099b6dd0 100644 --- a/sleekxmpp/basexmpp.py +++ b/sleekxmpp/basexmpp.py @@ -536,18 +536,8 @@ class BaseXMPP(XMLStream): :param pfrom: The sender of the presence. :param pnick: Optional nickname of the presence's sender. """ - # Python2.6 chokes on Unicode strings for dict keys. - args = {str('pto'): pto, - str('ptype'): ptype, - str('pshow'): pshow, - str('pstatus'): pstatus, - str('ppriority'): ppriority, - str('pnick'): pnick} - - if self.is_component: - self.roster[pfrom].send_presence(**args) - else: - self.client_roster.send_presence(**args) + self.make_presence(pshow, pstatus, ppriority, pto, + ptype, pfrom, pnick).send() def send_presence_subscription(self, pto, pfrom=None, ptype='subscribe', pnick=None): diff --git a/sleekxmpp/roster/item.py b/sleekxmpp/roster/item.py index 6ed1e42d..0acb5537 100644 --- a/sleekxmpp/roster/item.py +++ b/sleekxmpp/roster/item.py @@ -307,34 +307,29 @@ class RosterItem(object): p['from'] = self.owner p.send() - def send_presence(self, ptype=None, pshow=None, pstatus=None, - ppriority=None, pnick=None): + def send_presence(self, **kwargs): """ Create, initialize, and send a Presence stanza. + If no recipient is specified, send the presence immediately. + Otherwise, forward the send request to the recipient's roster + entry for processing. + Arguments: pshow -- The presence's show value. pstatus -- The presence's status message. ppriority -- This connections' priority. + pto -- The recipient of a directed presence. + pfrom -- The sender of a directed presence, which should + be the owner JID plus resource. ptype -- The type of presence, such as 'subscribe'. pnick -- Optional nickname of the presence's sender. """ - p = self.xmpp.make_presence(pshow=pshow, - pstatus=pstatus, - ppriority=ppriority, - ptype=ptype, - pnick=pnick, - pto=self.jid) - if self.xmpp.is_component: - p['from'] = self.owner - if p['type'] in p.showtypes or \ - p['type'] in ['available', 'unavailable']: - self.last_status = p - p.send() - - if not self.xmpp.sentpresence: - self.xmpp.event('sent_presence') - self.xmpp.sentpresence = True + if self.xmpp.is_component and not kwargs.get('pfrom', ''): + kwargs['pfrom'] = self.owner + if not kwargs.get('pto', ''): + kwargs['pto'] = self.jid + self.xmpp.send_presence(**kwargs) def send_last_presence(self): if self.last_status is None: diff --git a/sleekxmpp/roster/multi.py b/sleekxmpp/roster/multi.py index 6a60778b..dcd62e70 100644 --- a/sleekxmpp/roster/multi.py +++ b/sleekxmpp/roster/multi.py @@ -6,9 +6,11 @@ See the file LICENSE for copying permission. """ +from sleekxmpp.stanza import Presence from sleekxmpp.xmlstream import JID from sleekxmpp.roster import RosterNode + class Roster(object): """ @@ -55,6 +57,33 @@ class Roster(object): for node in self.db.entries(None, {}): self.add(node) + self.xmpp.add_filter('out', self._save_last_status) + + def _save_last_status(self, stanza): + + if isinstance(stanza, Presence): + sfrom = stanza['from'].full + sto = stanza['to'].full + + if not sfrom: + sfrom = self.xmpp.boundjid + + if stanza['type'] in stanza.showtypes or \ + stanza['type'] in ('available', 'unavailable'): + if sto: + self[sfrom][sto].last_status = stanza + else: + self[sfrom].last_status = stanza + with self[sfrom]._last_status_lock: + for jid in self[sfrom]: + self[sfrom][jid].last_status = None + + if not self.xmpp.sentpresence: + self.xmpp.event('sent_presence') + self.xmpp.sentpresence = True + + return stanza + def __getitem__(self, key): """ Return the roster node for a JID. @@ -121,29 +150,27 @@ class Roster(object): for node in self: self[node].reset() - def send_presence(self, pshow=None, pstatus=None, ppriority=None, - pto=None, pfrom=None, ptype=None, pnick=None): + def send_presence(self, **kwargs): """ Create, initialize, and send a Presence stanza. - Forwards the send request to the appropriate roster to - perform the actual sending. + If no recipient is specified, send the presence immediately. + Otherwise, forward the send request to the recipient's roster + entry for processing. Arguments: pshow -- The presence's show value. pstatus -- The presence's status message. ppriority -- This connections' priority. pto -- The recipient of a directed presence. + pfrom -- The sender of a directed presence, which should + be the owner JID plus resource. ptype -- The type of presence, such as 'subscribe'. - pfrom -- The sender of the presence. pnick -- Optional nickname of the presence's sender. """ - self[pfrom].send_presence(ptype=ptype, - pshow=pshow, - pstatus=pstatus, - ppriority=ppriority, - pnick=pnick, - pto=pto) + if self.xmpp.is_component and not kwargs.get('pfrom', ''): + kwargs['pfrom'] = self.jid + self.xmpp.send_presence(**kwargs) @property def auto_authorize(self): diff --git a/sleekxmpp/roster/single.py b/sleekxmpp/roster/single.py index 048b091e..d43a5041 100644 --- a/sleekxmpp/roster/single.py +++ b/sleekxmpp/roster/single.py @@ -6,6 +6,8 @@ See the file LICENSE for copying permission. """ +import threading + from sleekxmpp.xmlstream import JID from sleekxmpp.roster import RosterItem @@ -59,6 +61,7 @@ class RosterNode(object): self.last_status = None self._version = '' self._jids = {} + self._last_status_lock = threading.Lock() if self.db: if hasattr(self.db, 'version'): @@ -291,8 +294,7 @@ class RosterNode(object): for jid in self: self[jid].reset() - def send_presence(self, ptype=None, pshow=None, pstatus=None, - ppriority=None, pnick=None, pto=None): + def send_presence(self, **kwargs): """ Create, initialize, and send a Presence stanza. @@ -305,27 +307,14 @@ class RosterNode(object): pstatus -- The presence's status message. ppriority -- This connections' priority. pto -- The recipient of a directed presence. + pfrom -- The sender of a directed presence, which should + be the owner JID plus resource. ptype -- The type of presence, such as 'subscribe'. + pnick -- Optional nickname of the presence's sender. """ - if pto: - self[pto].send_presence(ptype, pshow, pstatus, - ppriority, pnick) - else: - p = self.xmpp.make_presence(pshow=pshow, - pstatus=pstatus, - ppriority=ppriority, - ptype=ptype, - pnick=pnick) - if self.xmpp.is_component: - p['from'] = self.jid - if p['type'] in p.showtypes or \ - p['type'] in ['available', 'unavailable']: - self.last_status = p - p.send() - - if not self.xmpp.sentpresence: - self.xmpp.event('sent_presence') - self.xmpp.sentpresence = True + if self.xmpp.is_component and not kwargs.get('pfrom', ''): + kwargs['pfrom'] = self.jid + self.xmpp.send_presence(**kwargs) def send_last_presence(self): if self.last_status is None: