Simplify tracking last sent presence using outgoing filters.

This commit is contained in:
Lance Stout 2012-06-18 17:28:58 -07:00
parent 62391a895a
commit ff6fc44215
4 changed files with 63 additions and 62 deletions

View file

@ -536,18 +536,8 @@ class BaseXMPP(XMLStream):
:param pfrom: The sender of the presence. :param pfrom: The sender of the presence.
:param pnick: Optional nickname of the presence's sender. :param pnick: Optional nickname of the presence's sender.
""" """
# Python2.6 chokes on Unicode strings for dict keys. self.make_presence(pshow, pstatus, ppriority, pto,
args = {str('pto'): pto, ptype, pfrom, pnick).send()
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)
def send_presence_subscription(self, pto, pfrom=None, def send_presence_subscription(self, pto, pfrom=None,
ptype='subscribe', pnick=None): ptype='subscribe', pnick=None):

View file

@ -307,34 +307,29 @@ class RosterItem(object):
p['from'] = self.owner p['from'] = self.owner
p.send() p.send()
def send_presence(self, ptype=None, pshow=None, pstatus=None, def send_presence(self, **kwargs):
ppriority=None, pnick=None):
""" """
Create, initialize, and send a Presence stanza. 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: Arguments:
pshow -- The presence's show value. pshow -- The presence's show value.
pstatus -- The presence's status message. pstatus -- The presence's status message.
ppriority -- This connections' priority. 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'. ptype -- The type of presence, such as 'subscribe'.
pnick -- Optional nickname of the presence's sender. pnick -- Optional nickname of the presence's sender.
""" """
p = self.xmpp.make_presence(pshow=pshow, if self.xmpp.is_component and not kwargs.get('pfrom', ''):
pstatus=pstatus, kwargs['pfrom'] = self.owner
ppriority=ppriority, if not kwargs.get('pto', ''):
ptype=ptype, kwargs['pto'] = self.jid
pnick=pnick, self.xmpp.send_presence(**kwargs)
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
def send_last_presence(self): def send_last_presence(self):
if self.last_status is None: if self.last_status is None:

View file

@ -6,9 +6,11 @@
See the file LICENSE for copying permission. See the file LICENSE for copying permission.
""" """
from sleekxmpp.stanza import Presence
from sleekxmpp.xmlstream import JID from sleekxmpp.xmlstream import JID
from sleekxmpp.roster import RosterNode from sleekxmpp.roster import RosterNode
class Roster(object): class Roster(object):
""" """
@ -55,6 +57,33 @@ class Roster(object):
for node in self.db.entries(None, {}): for node in self.db.entries(None, {}):
self.add(node) 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): def __getitem__(self, key):
""" """
Return the roster node for a JID. Return the roster node for a JID.
@ -121,29 +150,27 @@ class Roster(object):
for node in self: for node in self:
self[node].reset() self[node].reset()
def send_presence(self, pshow=None, pstatus=None, ppriority=None, def send_presence(self, **kwargs):
pto=None, pfrom=None, ptype=None, pnick=None):
""" """
Create, initialize, and send a Presence stanza. Create, initialize, and send a Presence stanza.
Forwards the send request to the appropriate roster to If no recipient is specified, send the presence immediately.
perform the actual sending. Otherwise, forward the send request to the recipient's roster
entry for processing.
Arguments: Arguments:
pshow -- The presence's show value. pshow -- The presence's show value.
pstatus -- The presence's status message. pstatus -- The presence's status message.
ppriority -- This connections' priority. ppriority -- This connections' priority.
pto -- The recipient of a directed presence. 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'. ptype -- The type of presence, such as 'subscribe'.
pfrom -- The sender of the presence.
pnick -- Optional nickname of the presence's sender. pnick -- Optional nickname of the presence's sender.
""" """
self[pfrom].send_presence(ptype=ptype, if self.xmpp.is_component and not kwargs.get('pfrom', ''):
pshow=pshow, kwargs['pfrom'] = self.jid
pstatus=pstatus, self.xmpp.send_presence(**kwargs)
ppriority=ppriority,
pnick=pnick,
pto=pto)
@property @property
def auto_authorize(self): def auto_authorize(self):

View file

@ -6,6 +6,8 @@
See the file LICENSE for copying permission. See the file LICENSE for copying permission.
""" """
import threading
from sleekxmpp.xmlstream import JID from sleekxmpp.xmlstream import JID
from sleekxmpp.roster import RosterItem from sleekxmpp.roster import RosterItem
@ -59,6 +61,7 @@ class RosterNode(object):
self.last_status = None self.last_status = None
self._version = '' self._version = ''
self._jids = {} self._jids = {}
self._last_status_lock = threading.Lock()
if self.db: if self.db:
if hasattr(self.db, 'version'): if hasattr(self.db, 'version'):
@ -291,8 +294,7 @@ class RosterNode(object):
for jid in self: for jid in self:
self[jid].reset() self[jid].reset()
def send_presence(self, ptype=None, pshow=None, pstatus=None, def send_presence(self, **kwargs):
ppriority=None, pnick=None, pto=None):
""" """
Create, initialize, and send a Presence stanza. Create, initialize, and send a Presence stanza.
@ -305,27 +307,14 @@ class RosterNode(object):
pstatus -- The presence's status message. pstatus -- The presence's status message.
ppriority -- This connections' priority. ppriority -- This connections' priority.
pto -- The recipient of a directed presence. 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'. ptype -- The type of presence, such as 'subscribe'.
pnick -- Optional nickname of the presence's sender.
""" """
if pto: if self.xmpp.is_component and not kwargs.get('pfrom', ''):
self[pto].send_presence(ptype, pshow, pstatus, kwargs['pfrom'] = self.jid
ppriority, pnick) self.xmpp.send_presence(**kwargs)
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
def send_last_presence(self): def send_last_presence(self):
if self.last_status is None: if self.last_status is None: