summaryrefslogtreecommitdiff
path: root/sleekxmpp/roster
diff options
context:
space:
mode:
Diffstat (limited to 'sleekxmpp/roster')
-rw-r--r--sleekxmpp/roster/item.py31
-rw-r--r--sleekxmpp/roster/multi.py49
-rw-r--r--sleekxmpp/roster/single.py35
3 files changed, 63 insertions, 52 deletions
diff --git a/sleekxmpp/roster/item.py b/sleekxmpp/roster/item.py
index 6ed1e42d..6e9c0d01 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..9a04aebb 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..f8c9c781 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,13 +61,14 @@ 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'):
self._version = self.db.version(self.jid)
for jid in self.db.entries(self.jid):
self.add(jid)
-
+
@property
def version(self):
"""Retrieve the roster's version ID."""
@@ -146,7 +149,7 @@ class RosterNode(object):
self.db = db
existing_entries = set(self._jids)
new_entries = set(self.db.entries(self.jid, {}))
-
+
for jid in existing_entries:
self._jids[jid].set_backend(db, save)
for jid in new_entries - existing_entries:
@@ -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: