diff options
author | Marco Pesenti Gritti <marco@localhost.localdomain> | 2007-05-21 10:47:28 (GMT) |
---|---|---|
committer | Marco Pesenti Gritti <marco@localhost.localdomain> | 2007-05-21 10:47:28 (GMT) |
commit | 17b31427765d21591986b927955f6f5342201d82 (patch) | |
tree | 6848e43c192ec8411b0e4f87a1d8b6d9086de9ba /services/presence/server_plugin.py | |
parent | f1d67f661e22150381886784d80c79e0db542e17 (diff) | |
parent | 8c8dffe662b9b2491eed2e553e3165c827f1c3cc (diff) |
Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
Conflicts:
configure.ac
Diffstat (limited to 'services/presence/server_plugin.py')
-rw-r--r-- | services/presence/server_plugin.py | 121 |
1 files changed, 84 insertions, 37 deletions
diff --git a/services/presence/server_plugin.py b/services/presence/server_plugin.py index cd03c01..d4930c9 100644 --- a/services/presence/server_plugin.py +++ b/services/presence/server_plugin.py @@ -42,6 +42,8 @@ CONN_INTERFACE_ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties' _PROTOCOL = "jabber" +_logger = logging.getLogger('s-p-s.server_plugin') + class InvalidBuddyError(Exception): """(Unused) exception to indicate an invalid buddy specifier""" @@ -144,14 +146,14 @@ class ServerPlugin(gobject.GObject): self._ip4am.connect('address-changed', self._ip4_address_changed_cb) def _ip4_address_changed_cb(self, ip4am, address): - logging.debug("::: IP4 address now %s" % address) + _logger.debug("::: IP4 address now %s" % address) if address: - logging.debug("::: valid IP4 address, conn_status %s" % self._conn_status) + _logger.debug("::: valid IP4 address, conn_status %s" % self._conn_status) if self._conn_status == CONNECTION_STATUS_DISCONNECTED: - logging.debug("::: will connect") + _logger.debug("::: will connect") self.start() else: - logging.debug("::: invalid IP4 address, will disconnect") + _logger.debug("::: invalid IP4 address, will disconnect") self.cleanup() def _owner_property_changed_cb(self, owner, properties): @@ -169,7 +171,7 @@ class ServerPlugin(gobject.GObject): depending on which properties are present in the set of properties. """ - logging.debug("Owner properties changed: %s" % properties) + _logger.debug("Owner properties changed: %s" % properties) if properties.has_key("current-activity"): self._set_self_current_activity() @@ -185,7 +187,7 @@ class ServerPlugin(gobject.GObject): def _owner_icon_changed_cb(self, owner, icon): """Owner has changed their icon, forward to network""" - logging.debug("Owner icon changed to size %d" % len(str(icon))) + _logger.debug("Owner icon changed to size %d" % len(str(icon))) self._set_self_avatar(icon) def _get_account_info(self): @@ -250,7 +252,7 @@ class ServerPlugin(gobject.GObject): def _connect_error_cb(self, exception): """Handle connection failure""" - logging.debug("Connect error: %s" % exception) + _logger.debug("Connect error: %s" % exception) def _init_connection(self): """Set up our connection @@ -318,11 +320,22 @@ class ServerPlugin(gobject.GObject): # the group of contacts who may receive your presence publish = self._request_list_channel('publish') - publish_handles, local_pending, remote_pending = publish[CHANNEL_INTERFACE_GROUP].GetAllMembers() + self._publish_channel = publish + publish[CHANNEL_INTERFACE_GROUP].connect_to_signal('MembersChanged', + self._publish_members_changed_cb) + publish_handles, local_pending, remote_pending = \ + publish[CHANNEL_INTERFACE_GROUP].GetAllMembers() # the group of contacts for whom you wish to receive presence subscribe = self._request_list_channel('subscribe') - subscribe_handles = subscribe[CHANNEL_INTERFACE_GROUP].GetMembers() + self._subscribe_channel = subscribe + subscribe[CHANNEL_INTERFACE_GROUP].connect_to_signal('MembersChanged', + self._subscribe_members_changed_cb) + subscribe_handles, subscribe_lp, subscribe_rp = \ + subscribe[CHANNEL_INTERFACE_GROUP].GetAllMembers() + self._subscribe_members = set(subscribe_handles) + self._subscribe_local_pending = set(subscribe_lp) + self._subscribe_remote_pending = set(subscribe_rp) if local_pending: # accept pending subscriptions @@ -336,7 +349,7 @@ class ServerPlugin(gobject.GObject): subscribe[CHANNEL_INTERFACE_GROUP].AddMembers(not_subscribed, '') if CONN_INTERFACE_BUDDY_INFO not in self._conn.get_valid_interfaces(): - logging.debug('OLPC information not available') + _logger.debug('OLPC information not available') return False self._conn[CONN_INTERFACE_BUDDY_INFO].connect_to_signal('PropertiesChanged', @@ -362,8 +375,7 @@ class ServerPlugin(gobject.GObject): self._set_self_current_activity() self._set_self_avatar() - # Request presence for everyone on the channel - subscribe_handles = subscribe[CHANNEL_INTERFACE_GROUP].GetMembers() + # Request presence for everyone we're subscribed to self._conn[CONN_INTERFACE_PRESENCE].RequestPresence(subscribe_handles) return True @@ -394,7 +406,7 @@ class ServerPlugin(gobject.GObject): types, minw, minh, maxw, maxh, maxsize = self._conn[CONN_INTERFACE_AVATARS].GetAvatarRequirements() if not "image/jpeg" in types: - logging.debug("server does not accept JPEG format avatars.") + _logger.debug("server does not accept JPEG format avatars.") return img_data = _get_buddy_icon_at_size(icon_data, min(maxw, 96), min(maxh, 96), maxsize) @@ -414,7 +426,7 @@ class ServerPlugin(gobject.GObject): if (activity_id, handles[0]) in self._joined_activities: e = RuntimeError("Already joined activity %s" % activity_id) - logging.debug(str(e)) + _logger.debug(str(e)) self.emit(signal, activity_id, None, e, userdata) return @@ -425,7 +437,7 @@ class ServerPlugin(gobject.GObject): def _join_error_cb(self, activity_id, signal, userdata, err): e = Exception("Error joining/sharing activity %s: %s" % (activity_id, err)) - logging.debug(str(e)) + _logger.debug(str(e)) self.emit(signal, activity_id, None, e, userdata) def _internal_join_activity(self, activity_id, signal, userdata): @@ -470,7 +482,7 @@ class ServerPlugin(gobject.GObject): def _log_error_cb(self, msg, err): """Log a message (error) at debug level with prefix msg""" - logging.debug("Error %s: %s" % (msg, err)) + _logger.debug("Error %s: %s" % (msg, err)) def _set_self_olpc_properties(self): """Set color and key on our Telepathy server identity""" @@ -519,7 +531,7 @@ class ServerPlugin(gobject.GObject): # dont advertise a current activity that's not shared cur_activity = "" - logging.debug("Setting current activity to '%s' (handle %s)" % (cur_activity, cur_activity_handle)) + _logger.debug("Setting current activity to '%s' (handle %s)" % (cur_activity, cur_activity_handle)) self._conn[CONN_INTERFACE_BUDDY_INFO].SetCurrentActivity(cur_activity, cur_activity_handle, reply_handler=self._ignore_success_cb, @@ -549,17 +561,17 @@ class ServerPlugin(gobject.GObject): if status == CONNECTION_STATUS_CONNECTING: self._conn_status = status - logging.debug("status: connecting...") + _logger.debug("status: connecting...") elif status == CONNECTION_STATUS_CONNECTED: if self._connected_cb(): - logging.debug("status: connected") + _logger.debug("status: connected") self._conn_status = status else: self.cleanup() - logging.debug("status: was connected, but an error occurred") + _logger.debug("status: was connected, but an error occurred") elif status == CONNECTION_STATUS_DISCONNECTED: self.cleanup() - logging.debug("status: disconnected (reason %r)" % reason) + _logger.debug("status: disconnected (reason %r)" % reason) if reason == CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED: # FIXME: handle connection failure; retry later? pass @@ -580,7 +592,7 @@ class ServerPlugin(gobject.GObject): status -- CONNECTION_STATUS_* reason -- integer code describing the reason... """ - logging.debug("::: connection status changed to %s" % status) + _logger.debug("::: connection status changed to %s" % status) self._handle_connection_status_change(status, reason) def start(self): @@ -594,7 +606,7 @@ class ServerPlugin(gobject.GObject): otherwise initiate a connection and transfer control to _connect_reply_cb or _connect_error_cb """ - logging.debug("Starting up...") + _logger.debug("Starting up...") if self._reconnect_id > 0: gobject.source_remove(self._reconnect_id) @@ -602,10 +614,10 @@ class ServerPlugin(gobject.GObject): # Only init connection if we have a valid IP address if self._ip4am.props.address: - logging.debug("::: Have IP4 address %s, will connect" % self._ip4am.props.address) + _logger.debug("::: Have IP4 address %s, will connect" % self._ip4am.props.address) self._init_connection() else: - logging.debug("::: No IP4 address, postponing connection") + _logger.debug("::: No IP4 address, postponing connection") def cleanup(self): """If we still have a connection, disconnect it""" @@ -641,14 +653,14 @@ class ServerPlugin(gobject.GObject): def _contact_online_activities_error_cb(self, handle, err): """Handle contact's activity list being unavailable""" - logging.debug("Handle %s - Error getting activities: %s" % (handle, err)) + _logger.debug("Handle %s - Error getting activities: %s" % (handle, err)) # Don't drop the buddy if we can't get their activities, for now #self._contact_offline(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): - logging.debug("Handle %s - No aliases" % handle) + _logger.debug("Handle %s - No aliases" % handle) self._contact_offline(handle) return @@ -664,22 +676,22 @@ class ServerPlugin(gobject.GObject): def _contact_online_aliases_error_cb(self, handle, props, retry, err): """Handle failure to retrieve given user's alias/information""" if retry: - logging.debug("Handle %s - Error getting nickname (will retry): %s" % (handle, err)) + _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 *args: self._contact_online_aliases_error_cb(handle, props, False, *args)) else: - logging.debug("Handle %s - Error getting nickname: %s" % (handle, err)) + _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'): - logging.debug("Handle %s - invalid key." % handle) + _logger.debug("Handle %s - invalid key." % handle) self._contact_offline(handle) return if not props.has_key('color'): - logging.debug("Handle %s - invalid color." % handle) + _logger.debug("Handle %s - invalid color." % handle) self._contact_offline(handle) return @@ -699,15 +711,22 @@ class ServerPlugin(gobject.GObject): def _contact_online_properties_error_cb(self, handle, tries, err): """Handle error retrieving property-set for a user (handle)""" if tries <= 3: - logging.debug("Handle %s - Error getting properties (will retry): %s" % (handle, err)) + _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: - logging.debug("Handle %s - Error getting properties: %s" % (handle, err)) + _logger.debug("Handle %s - Error getting properties: %s" % (handle, err)) self._contact_offline(handle) def _contact_online(self, handle): """Handle a contact coming online""" + if (handle not in self._subscribe_members and + handle not in self._subscribe_local_pending and + handle not in self._subscribe_remote_pending): + # it's probably a channel-specific handle - can't create a Buddy + # object + return + self._online_contacts[handle] = None if handle == self._conn[CONN_INTERFACE].GetSelfHandle(): jid = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0] @@ -718,6 +737,34 @@ class ServerPlugin(gobject.GObject): self._contact_online_request_properties(handle, 1) + def _subscribe_members_changed_cb(self, added, removed, local_pending, + remote_pending, actor, reason): + for handle in added: + self._subscribe_members.add(handle) + for handle in local_pending: + self._subscribe_local_pending.add(handle) + for handle in remote_pending: + self._subscribe_remote_pending.add(handle) + for handle in removed: + self._subscribe_members.discard(handle) + self._subscribe_local_pending.discard(handle) + self._subscribe_remote_pending.discard(handle) + + def _publish_members_changed_cb(self, added, removed, local_pending, + remote_pending, actor, reason): + + if local_pending: + # accept all requested subscriptions + self._publish_channel[CHANNEL_INTERFACE_GROUP].AddMembers( + local_pending, '') + + # subscribe to people who've subscribed to us, if necessary + added = list(set(added) - self._subscribe_members + - self._subscribe_remote_pending) + if added: + self._subscribe_channel[CHANNEL_INTERFACE_GROUP].AddMembers( + added, '') + def _presence_update_cb(self, presence): """Send update for online/offline status of presence""" for handle in presence: @@ -730,7 +777,7 @@ class ServerPlugin(gobject.GObject): jid = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0] olstr = "ONLINE" if not online: olstr = "OFFLINE" - logging.debug("Handle %s (%s) was %s, status now '%s'." % (handle, jid, olstr, status)) + _logger.debug("Handle %s (%s) was %s, status now '%s'." % (handle, jid, olstr, status)) if not online and status in ["available", "away", "brb", "busy", "dnd", "xa"]: self._contact_online(handle) elif status in ["offline", "invisible"]: @@ -753,12 +800,12 @@ class ServerPlugin(gobject.GObject): return if not self._online_contacts.has_key(handle): - logging.debug("Handle %s unknown." % handle) + _logger.debug("Handle %s unknown." % handle) return jid = self._online_contacts[handle] if not jid: - logging.debug("Handle %s not valid yet..." % handle) + _logger.debug("Handle %s not valid yet..." % handle) return icon = self._icon_cache.get_icon(jid, new_avatar_token) @@ -814,7 +861,7 @@ class ServerPlugin(gobject.GObject): if not len(activity) or not util.validate_activity_id(activity): activity = None prop = {'current-activity': activity} - logging.debug("Handle %s: current activity now %s" % (handle, activity)) + _logger.debug("Handle %s: current activity now %s" % (handle, activity)) self._buddy_properties_changed_cb(handle, prop) def _new_channel_cb(self, object_path, channel_type, handle_type, handle, suppress_handler): |