From 006df6ff75871a42b06f442833f0726704f74f33 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 11 Jun 2007 16:42:00 +0000 Subject: Make Buddy responsible for initial property lookup when a Tp handle is added --- diff --git a/src/buddy.py b/src/buddy.py index 5c0a877..96698c8 100644 --- a/src/buddy.py +++ b/src/buddy.py @@ -295,6 +295,64 @@ class Buddy(ExportedGObject): self._handles[tp_client] = (handle, uid) self.TelepathyHandleAdded(conn.service_name, conn.object_path, handle) + # FIXME: we should probably have a class SomeoneElse(Buddy) for + # everyone who's not the owner + if not self._owner: + self._discover_properties(tp_client, handle, uid) + + def _discover_properties(self, tp_client, handle, uid): + conn = tp_client.get_connection() + + accumulator = {} + + def got_aliases(aliases): + try: + _logger.debug('Buddy %s nick set to %s', self._object_id, + aliases[0]) + accumulator.update({'nick': aliases[0]}) + finally: + self.set_properties(accumulator) + def aliases_error(e): + try: + _logger.warning('Error getting buddy properties for %s: ' + '%s', uid, e) + finally: + self.set_properties(accumulator) + + def get_alias(): + accumulator.setdefault('nick', uid) + if CONN_INTERFACE_ALIASING in conn: + conn[CONN_INTERFACE_ALIASING].RequestAliases([handle], + reply_handler=got_aliases, + error_handler=aliases_error) + else: + self.set_properties(accumulator) + + def got_properties(props): + try: + _logger.debug('Buddy %s properties are %r', self._object_id, + props) + accumulator.update(props) + finally: + get_alias() + def properties_error(e): + try: + _logger.warning('Error getting buddy properties for %s: ' + '%s', uid, e) + finally: + get_alias() + + # Kick off the first request, which is for the properties. + # Chain from there to the aliases request; chain from *there* to + # setting the accumulated properties. + accumulator['color'] = 'white' + if CONN_INTERFACE_BUDDY_INFO in conn: + conn[CONN_INTERFACE_BUDDY_INFO].GetProperties(handle, + byte_arrays=True, reply_handler=got_properties, + error_handler=properties_error) + else: + get_alias() + @dbus.service.signal(_BUDDY_INTERFACE, signature='sou') def TelepathyHandleAdded(self, tp_conn_name, tp_conn_path, handle): """Another Telepathy handle has become associated with the buddy. diff --git a/src/presenceservice.py b/src/presenceservice.py index e5505a5..22e76c3 100644 --- a/src/presenceservice.py +++ b/src/presenceservice.py @@ -211,19 +211,20 @@ class PresenceService(ExportedGObject): self._buddies[objid] = buddy return buddy - def _contact_online(self, tp, objid, handle, identifier, props): + def _contact_online(self, tp, objid, handle, identifier): _logger.debug('Handle %u, .../%s is now online', handle, objid) buddy = self.get_buddy(objid) self._handles_buddies[tp][handle] = buddy # store the handle of the buddy for this CM buddy.add_telepathy_handle(tp, handle, identifier) - buddy.set_properties(props) - # kick off a request for their current activities - # FIXME: move this to the Buddy? conn = tp.get_connection() + # Kick off a request for their current activities. This isn't done + # internally by the Buddy itself, because when we get the activities + # back, we actually want to feed them to the Activity objects. + def got_activities(activities): self._buddy_activities_changed(tp, handle, activities) conn[CONN_INTERFACE_BUDDY_INFO].GetActivities(handle, diff --git a/src/server_plugin.py b/src/server_plugin.py index 3efd696..b1060b2 100644 --- a/src/server_plugin.py +++ b/src/server_plugin.py @@ -20,6 +20,7 @@ import logging import os import sys +from itertools import izip from string import hexdigits # Other libraries @@ -452,87 +453,15 @@ class ServerPlugin(gobject.GObject): self.emit("contact-offline", handle) del self._online_contacts[handle] - def _contact_online_aliases_cb(self, handle, props, aliases): - """Handle contact's alias being received (do further queries)""" - if not self._conn or not aliases or not len(aliases): - _logger.debug("Handle %s - No aliases", handle) - self._contact_offline(handle) - return - - props['nick'] = aliases[0] - - jid = self._conn[CONN_INTERFACE].InspectHandles(HANDLE_TYPE_CONTACT, - [handle])[0] - self._online_contacts[handle] = jid - objid = self.identify_contacts(None, [handle])[handle] - - self.emit("contact-online", objid, handle, jid, props) - - def _contact_online_aliases_error_cb(self, handle, props, retry, err): - """Handle failure to retrieve given user's alias/information""" - if retry: - _logger.debug("Handle %s - Error getting nickname (will retry):" - "%s", handle, err) - self._conn[CONN_INTERFACE_ALIASING].RequestAliases([handle], - reply_handler=lambda *args: self._contact_online_aliases_cb( - handle, props, *args), - error_handler=lambda e: self._contact_online_aliases_error_cb( - handle, props, False, e)) - else: - _logger.debug("Handle %s - Error getting nickname: %s", - handle, err) - self._contact_offline(handle) - - def _contact_online_properties_cb(self, handle, props): - """Handle failure to retrieve given user's alias/information""" - if not props.has_key('key'): - _logger.debug("Handle %s - invalid key.", handle) - self._contact_offline(handle) - return - if not props.has_key('color'): - _logger.debug("Handle %s - invalid color.", handle) - self._contact_offline(handle) - return - - self._conn[CONN_INTERFACE_ALIASING].RequestAliases([handle], - reply_handler=lambda *args: self._contact_online_aliases_cb( - handle, props, *args), - error_handler=lambda e: self._contact_online_aliases_error_cb( - handle, props, True, e)) - - def _contact_online_request_properties(self, handle, tries): - self._conn[CONN_INTERFACE_BUDDY_INFO].GetProperties(handle, - byte_arrays=True, - reply_handler=lambda *args: self._contact_online_properties_cb( - handle, *args), - error_handler=lambda e: self._contact_online_properties_error_cb( - handle, tries, e)) - return False - - def _contact_online_properties_error_cb(self, handle, tries, err): - """Handle error retrieving property-set for a user (handle)""" - if tries <= 3: - _logger.debug("Handle %s - Error getting properties (will retry):" - " %s", handle, err) - tries += 1 - gobject.timeout_add(1000, self._contact_online_request_properties, - handle, tries) - else: - _logger.debug("Handle %s - Error getting properties: %s", - handle, err) - self._contact_offline(handle) - def _contacts_online(self, handles): """Handle contacts coming online""" relevant = [] for handle in handles: if handle == self.self_handle: - jid = self._conn[CONN_INTERFACE].InspectHandles( - HANDLE_TYPE_CONTACT, [handle])[0] - self._online_contacts[handle] = jid # ignore network events for Owner property changes since those # are handled locally + pass elif (handle in self._subscribe_members or handle in self._subscribe_local_pending or handle in self._subscribe_remote_pending): @@ -540,9 +469,14 @@ class ServerPlugin(gobject.GObject): # else it's probably a channel-specific handle - can't create a # Buddy object for those yet - for handle in relevant: - self._online_contacts[handle] = None - self._contact_online_request_properties(handle, 1) + jids = self._conn[CONN_INTERFACE].InspectHandles( + HANDLE_TYPE_CONTACT, relevant) + + objids = self.identify_contacts(None, relevant, jids) + + for handle, jid, objid in izip(relevant, jids, objids): + self._online_contacts[handle] = jid + self.emit('contact-online', objid, handle, jid) def _subscribe_members_changed_cb(self, message, added, removed, local_pending, remote_pending, @@ -689,7 +623,7 @@ class ServerPlugin(gobject.GObject): """ return (hostname == 'olpc.collabora.co.uk') - def identify_contacts(self, tp_chan, handles): + def identify_contacts(self, tp_chan, handles, identifiers=None): """Work out the "best" unique identifier we can for the given handles, in the context of the given channel (which may be None), using only 'fast' connection manager API (that does not involve network @@ -732,6 +666,7 @@ class ServerPlugin(gobject.GObject): group = tp_chan[CHANNEL_INTERFACE_GROUP] if (group.GetGroupFlags() & CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES): + identifiers = None owners = group.GetHandleOwners(handles) for i, owner in enumerate(owners): if owner == 0: @@ -739,11 +674,12 @@ class ServerPlugin(gobject.GObject): else: group = None - jids = self._conn[CONN_INTERFACE].InspectHandles(HANDLE_TYPE_CONTACT, - owners) + if identifiers is None: + identifiers = self._conn[CONN_INTERFACE].InspectHandles( + HANDLE_TYPE_CONTACT, identifiers) ret = {} - for handle, jid in zip(handles, jids): + for handle, jid in izip(handles, identifiers): # special-case the Owner - we always know who we are if (handle == self.self_handle or (group is not None and handle == group.GetSelfHandle())): -- cgit v0.9.1