From c0074f95b160f4766168ed2cae955709bf38d124 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Wed, 11 Jan 2012 16:39:55 -0800 Subject: [PATCH] update_caps() can now do presence broadcasting. As part of adding this feature: - fixed bug in update_caps() not assigning verstrings - fixed xep_0004 typo - can now use None as a roster key which will map to boundjid.bare - fixed using JID objects in disco node handlers - fixed failing test related to get_roster Several of these bugs I've fixed before, so I either didn't push them earlier, or I clobbered something when merging. *shrug* --- setup.py | 1 + sleekxmpp/plugins/xep_0004/stanza/field.py | 2 +- sleekxmpp/plugins/xep_0030/disco.py | 4 ++++ sleekxmpp/plugins/xep_0115/caps.py | 24 ++++++++++++++++++---- sleekxmpp/roster/multi.py | 2 ++ sleekxmpp/roster/single.py | 11 ++++++++++ tests/test_stream_roster.py | 3 ++- 7 files changed, 41 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 954a102..b86dc1f 100755 --- a/setup.py +++ b/setup.py @@ -68,6 +68,7 @@ packages = [ 'sleekxmpp', 'sleekxmpp/plugins/xep_0085', 'sleekxmpp/plugins/xep_0086', 'sleekxmpp/plugins/xep_0092', + 'sleekxmpp/plugins/xep_0115', 'sleekxmpp/plugins/xep_0128', 'sleekxmpp/plugins/xep_0199', 'sleekxmpp/plugins/xep_0202', diff --git a/sleekxmpp/plugins/xep_0004/stanza/field.py b/sleekxmpp/plugins/xep_0004/stanza/field.py index 6814e15..8156997 100644 --- a/sleekxmpp/plugins/xep_0004/stanza/field.py +++ b/sleekxmpp/plugins/xep_0004/stanza/field.py @@ -93,7 +93,7 @@ class FormField(ElementBase): if valXML.text is None: valXML.text = '' values.append(valXML.text) - if self._type == 'text-multi' and condense: + if self._type == 'text-multi' and convert: values = "\n".join(values) return values else: diff --git a/sleekxmpp/plugins/xep_0030/disco.py b/sleekxmpp/plugins/xep_0030/disco.py index 10f9ef4..58f4f20 100644 --- a/sleekxmpp/plugins/xep_0030/disco.py +++ b/sleekxmpp/plugins/xep_0030/disco.py @@ -357,6 +357,7 @@ class xep_0030(base_plugin): else: if str(jid) == str(self.xmpp.boundjid): local = True + jid = jid.full if local or jid in (None, ''): log.debug("Looking up local disco#info data " + \ @@ -626,6 +627,9 @@ class xep_0030(base_plugin): node -- The node requested. data -- Optional, custom data to pass to the handler. """ + if isinstance(jid, JID): + jid = jid.full + if jid in (None, ''): if self.xmpp.is_component: jid = self.xmpp.boundjid.full diff --git a/sleekxmpp/plugins/xep_0115/caps.py b/sleekxmpp/plugins/xep_0115/caps.py index d3e62ab..289bb8d 100644 --- a/sleekxmpp/plugins/xep_0115/caps.py +++ b/sleekxmpp/plugins/xep_0115/caps.py @@ -65,10 +65,11 @@ class xep_0115(base_plugin): self.xmpp.add_event_handler('entity_caps', self._process_caps, threaded=True) - self.xmpp.register_feature('caps', - self._handle_caps_feature, - restart=False, - order=10010) + if not self.xmpp.is_component: + self.xmpp.register_feature('caps', + self._handle_caps_feature, + restart=False, + order=10010) def post_init(self): base_plugin.post_init(self) @@ -256,6 +257,21 @@ class xep_0115(base_plugin): info=info) self.cache_caps(ver, info) self.assign_verstring(jid, ver) + + if self.broadcast: + # Check if we've sent directed presence. If we haven't, we + # can just send a normal presence stanza. If we have, then + # we will send presence to each contact individually so + # that we don't clobber existing statuses. + directed = False + for contact in self.xmpp.roster[jid]: + if self.xmpp.roster[jid][contact].last_status is not None: + directed = True + if not directed: + self.xmpp.roster[jid].send_last_presence() + else: + for contact in self.xmpp.roster[jid]: + self.xmpp.roster[jid][contact].send_last_presence() except XMPPError: return diff --git a/sleekxmpp/roster/multi.py b/sleekxmpp/roster/multi.py index 36c7e2a..2887681 100644 --- a/sleekxmpp/roster/multi.py +++ b/sleekxmpp/roster/multi.py @@ -68,6 +68,8 @@ class Roster(object): """ if isinstance(key, JID): key = key.bare + if key is None: + key = self.xmpp.boundjid.bare if key not in self._rosters: self.add(key) self._rosters[key].auto_authorize = self.auto_authorize diff --git a/sleekxmpp/roster/single.py b/sleekxmpp/roster/single.py index 903333a..c2f8e76 100644 --- a/sleekxmpp/roster/single.py +++ b/sleekxmpp/roster/single.py @@ -286,5 +286,16 @@ class RosterNode(object): self.xmpp.event('sent_presence') self.xmpp.sentpresence = True + def send_last_presence(self): + if self.last_status is None: + self.send_presence() + else: + pres = self.last_status + if self.xmpp.is_component: + pres['from'] = self.jid + else: + del pres['from'] + pres.send() + def __repr__(self): return repr(self._jids) diff --git a/tests/test_stream_roster.py b/tests/test_stream_roster.py index 1f83f0e..eb6d2f4 100644 --- a/tests/test_stream_roster.py +++ b/tests/test_stream_roster.py @@ -125,7 +125,8 @@ class TestStreamRoster(SleekTest): # Since get_roster blocks, we need to run it in a thread. t = threading.Thread(name='get_roster', target=self.xmpp.get_roster, - kwargs={str('callback'): roster_callback}) + kwargs={str('block'): False, + str('callback'): roster_callback}) t.start() self.send("""