Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/server_plugin.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/server_plugin.py')
-rw-r--r--src/server_plugin.py93
1 files changed, 45 insertions, 48 deletions
diff --git a/src/server_plugin.py b/src/server_plugin.py
index 0b4cdd2..4d0c579 100644
--- a/src/server_plugin.py
+++ b/src/server_plugin.py
@@ -67,17 +67,16 @@ class ServerPlugin(gobject.GObject):
to implement the PresenceService.
"""
__gsignals__ = {
- 'contact-online':
- # Contact has come online and we've discovered all their buddy
- # properties.
+ 'contacts-online':
+ # Contacts in the subscribe list have come online.
# args:
- # contact identification (based on key ID or JID): str
- # contact handle: int or long
- # contact identifier (JID): str or unicode
- (gobject.SIGNAL_RUN_FIRST, None, [str, object, object]),
- 'contact-offline':
- # Contact has gone offline.
- # args: contact handle
+ # contact identification (based on key ID or JID): list of str
+ # contact handle: list of int or long
+ # contact identifier (JID): list of str or unicode
+ (gobject.SIGNAL_RUN_FIRST, None, [object, object, object]),
+ 'contacts-offline':
+ # Contacts in the subscribe list have gone offline.
+ # args: iterable over contact handles
(gobject.SIGNAL_RUN_FIRST, None, [object]),
'status':
# Connection status changed.
@@ -114,7 +113,8 @@ class ServerPlugin(gobject.GObject):
self._matches = []
self._registry = registry
- self._online_contacts = {} # handle -> jid
+ #: set of contact handles: those for whom we've emitted contacts-online
+ self._online_contacts = set()
self._owner = owner
self.self_handle = None
@@ -308,8 +308,7 @@ class ServerPlugin(gobject.GObject):
# FIXME: do this async?
self.self_handle = self._conn[CONN_INTERFACE].GetSelfHandle()
self.self_identifier = self._conn[CONN_INTERFACE].InspectHandles(
- HANDLE_TYPE_CONTACT, self.self_handle)[0]
- self._online_contacts[self.self_handle] = self.self_identifier
+ HANDLE_TYPE_CONTACT, [self.self_handle])[0]
# request subscriptions from people subscribed to us if we're not
# subscribed to them
@@ -417,21 +416,18 @@ class ServerPlugin(gobject.GObject):
self._conn = None
self._conn_status = CONNECTION_STATUS_DISCONNECTED
- for handle in self._online_contacts.keys():
- self._contact_offline(handle)
- self._online_contacts = {}
+ if self._online_contacts:
+ self._contacts_offline(self._online_contacts)
if self._reconnect_id > 0:
gobject.source_remove(self._reconnect_id)
self._reconnect_id = 0
- def _contact_offline(self, handle):
- """Handle contact going offline (send message, update set)"""
- if not self._online_contacts.has_key(handle):
- return
- if self._online_contacts[handle]:
- self.emit("contact-offline", handle)
- del self._online_contacts[handle]
+ def _contacts_offline(self, handles):
+ """Handle contacts going offline (send message, update set)"""
+ self._online_contacts -= handles
+ _logger.debug('Contacts now offline: %r', handles)
+ self.emit("contacts-offline", handles)
def _contacts_online(self, handles):
"""Handle contacts coming online"""
@@ -449,14 +445,22 @@ class ServerPlugin(gobject.GObject):
# else it's probably a channel-specific handle - can't create a
# Buddy object for those yet
+ if not relevant:
+ return
+
jids = self._conn[CONN_INTERFACE].InspectHandles(
HANDLE_TYPE_CONTACT, relevant)
- objids = self.identify_contacts(None, relevant, jids)
+ handle_to_objid = self.identify_contacts(None, relevant, jids)
+ objids = []
+ for handle in relevant:
+ objids.append(handle_to_objid[handle])
- for handle, jid, objid in izip(relevant, jids, objids):
- self._online_contacts[handle] = jid
- self.emit('contact-online', objid, handle, jid)
+ self._online_contacts |= frozenset(relevant)
+ _logger.debug('Contacts now online:')
+ for handle, objid in izip(relevant, objids):
+ _logger.debug(' %u .../%s', handle, objid)
+ self.emit('contacts-online', objids, relevant, jids)
def _subscribe_members_changed_cb(self, message, added, removed,
local_pending, remote_pending,
@@ -496,31 +500,24 @@ class ServerPlugin(gobject.GObject):
def _presence_update_cb(self, presence):
"""Send update for online/offline status of presence"""
- now_online = []
- now_offline = []
+ now_online = set()
+ now_offline = set(presence.iterkeys())
for handle in presence:
timestamp, statuses = presence[handle]
- online = handle in self._online_contacts
for status, params in statuses.items():
- if not online and status == "offline":
- # weren't online in the first place...
- continue
- jid = self._conn[CONN_INTERFACE].InspectHandles(
- HANDLE_TYPE_CONTACT, [handle])[0]
- olstr = "ONLINE"
- if not online: olstr = "OFFLINE"
- _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"]:
- now_online.append(handle)
- elif status in ["offline", "invisible"]:
- now_offline.append(handle)
-
- self._contacts_online(now_online)
- for handle in now_offline:
- self._contact_offline(handle)
+ # FIXME: use correct logic involving the GetStatuses method
+ if status in ["available", "away", "brb", "busy", "dnd", "xa"]:
+ now_online.add(handle)
+ now_offline.discard(handle)
+
+ now_online -= self._online_contacts
+ now_offline &= self._online_contacts
+
+ if now_online:
+ self._contacts_online(now_online)
+ if now_offline:
+ self._contacts_offline(now_offline)
def _new_channel_cb(self, object_path, channel_type, handle_type, handle,
suppress_handler):