PresenceService fixes; request buddy presence when using existing connection

This commit is contained in:
Dan Williams 2007-02-28 22:13:27 -05:00
parent 48e9887d92
commit 57b887df30
3 changed files with 55 additions and 76 deletions

View File

@ -32,11 +32,13 @@ class Buddy(dbus.service.Object):
"""Represents another person on the network and keeps track of the """Represents another person on the network and keeps track of the
activities and resources they make available for sharing.""" activities and resources they make available for sharing."""
def __init__(self, bus_name, object_id, handle=None): def __init__(self, bus_name, object_id, key=None):
if not bus_name: if not bus_name:
raise ValueError("DBus bus name must be valid") raise ValueError("DBus bus name must be valid")
if not object_id or not isinstance(object_id, int): if not object_id or not isinstance(object_id, int):
raise ValueError("object id must be a valid number") raise ValueError("object id must be a valid number")
if not key:
raise ValueError("key must be valid")
self._bus_name = bus_name self._bus_name = bus_name
self._object_id = object_id self._object_id = object_id
@ -45,13 +47,12 @@ class Buddy(dbus.service.Object):
dbus.service.Object.__init__(self, self._bus_name, self._object_path) dbus.service.Object.__init__(self, self._bus_name, self._object_path)
self._activities = {} # Activity ID -> Activity self._activities = {} # Activity ID -> Activity
self.handles = {} # tp client -> handle self.handles = {} # tp client -> handle
self._key = key
self._icon = None self._icon = None
self._name = None self._nick = None
self._color = None self._color = None
self._key = None
self._current_activity = None self._current_activity = None
# dbus signals # dbus signals
@ -96,7 +97,7 @@ class Buddy(dbus.service.Object):
in_signature="", out_signature="a{sv}") in_signature="", out_signature="a{sv}")
def GetProperties(self): def GetProperties(self):
props = {} props = {}
props['name'] = self.get_name() props['nick'] = self.get_nick()
props['owner'] = self.is_owner() props['owner'] = self.is_owner()
props['key'] = self.get_key() props['key'] = self.get_key()
color = self.get_color() color = self.get_color()
@ -135,8 +136,8 @@ class Buddy(dbus.service.Object):
"""Return the buddies icon, if any.""" """Return the buddies icon, if any."""
return self._icon return self._icon
def get_name(self): def get_nick(self):
return self._name return self._nick
def get_color(self): def get_color(self):
return self._color return self._color
@ -155,15 +156,15 @@ class Buddy(dbus.service.Object):
self._icon = icon self._icon = icon
self.IconChanged(icon) self.IconChanged(icon)
def _set_name(self, name): def _set_nick(self, nick):
self._name = name self._nick = nick
def _set_color(self, color): def _set_color(self, color):
self._color = color self._color = color
def set_properties(self, properties): def set_properties(self, properties):
if "name" in properties.keys(): if "nick" in properties.keys():
self._set_name(properties["name"]) self._set_nick(properties["nick"])
if "color" in properties.keys(): if "color" in properties.keys():
self._set_color(properties["color"]) self._set_color(properties["color"])
self.PropertyChanged(properties) self.PropertyChanged(properties)
@ -181,12 +182,12 @@ class Owner(Buddy):
"""Class representing the owner of the machine. This is the client """Class representing the owner of the machine. This is the client
portion of the Owner, paired with the server portion in Owner.py.""" portion of the Owner, paired with the server portion in Owner.py."""
def __init__(self, ps, bus_name, object_id): def __init__(self, ps, bus_name, object_id):
Buddy.__init__(self, bus_name, object_id) key = profile.get_pubkey()
Buddy.__init__(self, bus_name, object_id, key=key)
self._ps = ps self._ps = ps
self._name = profile.get_nick_name() self._name = profile.get_nick_name()
self._color = profile.get_color().to_string() self._color = profile.get_color().to_string()
self._key = profile.get_pubkey()
# dbus methods # dbus methods
@dbus.service.method(_OWNER_INTERFACE, @dbus.service.method(_OWNER_INTERFACE,

View File

@ -82,13 +82,11 @@ class PresenceService(dbus.service.Object):
new_buddy = False new_buddy = False
key = props['key'] key = props['key']
buddy = self._buddies.get(key) buddy = self._buddies.get(key)
if not buddy: if not buddy:
# we don't know yet this buddy # we don't know yet this buddy
objid = self._get_next_object_id() objid = self._get_next_object_id()
buddy = Buddy(self._bus_name, objid, handle=handle) buddy = Buddy(self._bus_name, objid, key=key)
buddy.set_key(key) print "New buddy %s" % key
print "create buddy", key
self._buddies[key] = buddy self._buddies[key] = buddy
new_buddy = True new_buddy = True
@ -101,6 +99,7 @@ class PresenceService(dbus.service.Object):
if new_buddy: if new_buddy:
self.BuddyAppeared(buddy.object_path()) self.BuddyAppeared(buddy.object_path())
buddy.set_properties(props) buddy.set_properties(props)
print "New buddy properties %s" % props
def _contact_offline(self, tp, handle): def _contact_offline(self, tp, handle):
buddy = self._handles[tp].pop(handle) buddy = self._handles[tp].pop(handle)
@ -108,13 +107,10 @@ class PresenceService(dbus.service.Object):
# the handle of the buddy for this CM is not valid anymore # the handle of the buddy for this CM is not valid anymore
buddy.handles.pop(tp) buddy.handles.pop(tp)
if not buddy.handles: if not buddy.handles:
# we remove the last handle of the buddy, so we don't see
# it anymore.
self._buddies.pop(key)
print "remove buddy"
self.BuddyDisappeared(buddy.object_path()) self.BuddyDisappeared(buddy.object_path())
print "Buddy %s gone" % buddy.get_key()
self._buddies.pop(key)
def _get_next_object_id(self): def _get_next_object_id(self):
"""Increment and return the object ID counter.""" """Increment and return the object ID counter."""
@ -123,15 +119,15 @@ class PresenceService(dbus.service.Object):
def _avatar_updated(self, tp, handle, avatar): def _avatar_updated(self, tp, handle, avatar):
buddy = self._handles[tp].get(handle) buddy = self._handles[tp].get(handle)
if buddy and not buddy.is_owner():
if buddy: print "Buddy %s icon updated" % buddy.get_key()
buddy.set_icon(avatar) buddy.set_icon(avatar)
def _properties_changed(self, tp, handle, prop): def _properties_changed(self, tp, handle, prop):
buddy = self._handles[tp].get(handle) buddy = self._handles[tp].get(handle)
if buddy: if buddy:
buddy.set_properties(prop) buddy.set_properties(prop)
print "Buddy %s properties updated" % buddy.get_key()
def _activities_changed(self, tp, handle, prop): def _activities_changed(self, tp, handle, prop):
pass pass

View File

@ -91,7 +91,7 @@ class ServerPlugin(gobject.GObject):
self._icon_cache = BuddyIconCache() self._icon_cache = BuddyIconCache()
self._gabble_mgr = registry.GetManager('gabble') self._gabble_mgr = registry.GetManager('gabble')
self._online_contacts = set() # handles of online contacts self._online_contacts = {} # handle -> jid
self._account = self._get_account_info() self._account = self._get_account_info()
self._conn = self._init_connection() self._conn = self._init_connection()
@ -140,7 +140,6 @@ class ServerPlugin(gobject.GObject):
acct = self._account.copy() acct = self._account.copy()
# Create a new connection # Create a new connection
print acct
name, path = self._gabble_mgr[CONN_MGR_INTERFACE].RequestConnection(_PROTOCOL, acct) name, path = self._gabble_mgr[CONN_MGR_INTERFACE].RequestConnection(_PROTOCOL, acct)
conn = Connection(name, path) conn = Connection(name, path)
del acct del acct
@ -185,30 +184,12 @@ class ServerPlugin(gobject.GObject):
not_subscribed = list(set(publish_handles) - set(subscribe_handles)) not_subscribed = list(set(publish_handles) - set(subscribe_handles))
self_handle = self._conn[CONN_INTERFACE].GetSelfHandle() self_handle = self._conn[CONN_INTERFACE].GetSelfHandle()
self._online_contacts.add(self_handle) self._online_contacts[self_handle] = self._account['account']
for handle in not_subscribed: for handle in not_subscribed:
# request subscriptions from people subscribed to us if we're not subscribed to them # request subscriptions from people subscribed to us if we're not subscribed to them
subscribe[CHANNEL_INTERFACE_GROUP].AddMembers([self_handle], '') subscribe[CHANNEL_INTERFACE_GROUP].AddMembers([self_handle], '')
# hack
self._conn._valid_interfaces.add(CONN_INTERFACE_ALIASING)
self._conn[CONN_INTERFACE_ALIASING].connect_to_signal('AliasesChanged', self._alias_changed_cb)
#if CONN_INTERFACE_ALIASING in self._conn:
# aliases = self._conn[CONN_INTERFACE_ALIASING].RequestAliases(subscribe_handles)
#else:
# aliases = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, subscribe_handles)
#for handle, alias in zip(subscribe_handles, aliases):
# print alias
# self.buddies[handle].alias = alias
# hack
self._conn._valid_interfaces.add(CONN_INTERFACE_AVATARS)
self._conn[CONN_INTERFACE_AVATARS].connect_to_signal('AvatarUpdated', self._avatar_updated_cb)
# hack # hack
self._conn._valid_interfaces.add(CONN_INTERFACE_BUDDY_INFO) self._conn._valid_interfaces.add(CONN_INTERFACE_BUDDY_INFO)
if CONN_INTERFACE_BUDDY_INFO not in self._conn.get_valid_interfaces(): if CONN_INTERFACE_BUDDY_INFO not in self._conn.get_valid_interfaces():
@ -216,11 +197,22 @@ class ServerPlugin(gobject.GObject):
self.disconnect() self.disconnect()
return return
self._set_self_buddy_info()
self._conn[CONN_INTERFACE_BUDDY_INFO].connect_to_signal('PropertiesChanged', self._properties_changed_cb) self._conn[CONN_INTERFACE_BUDDY_INFO].connect_to_signal('PropertiesChanged', self._properties_changed_cb)
self._conn[CONN_INTERFACE_BUDDY_INFO].connect_to_signal('ActivitiesChanged', self._activities_changed_cb) self._conn[CONN_INTERFACE_BUDDY_INFO].connect_to_signal('ActivitiesChanged', self._activities_changed_cb)
# hack
self._conn._valid_interfaces.add(CONN_INTERFACE_AVATARS)
self._conn[CONN_INTERFACE_AVATARS].connect_to_signal('AvatarUpdated', self._avatar_updated_cb)
# hack
self._conn._valid_interfaces.add(CONN_INTERFACE_ALIASING)
self._conn[CONN_INTERFACE_ALIASING].connect_to_signal('AliasesChanged', self._alias_changed_cb)
self._set_self_buddy_info()
# Request presence for everyone on the channel
self._conn[CONN_INTERFACE_PRESENCE].GetPresence(subscribe_handles)
def _set_self_buddy_info(self): def _set_self_buddy_info(self):
# Set our OLPC buddy properties # Set our OLPC buddy properties
props = {} props = {}
@ -276,56 +268,47 @@ class ServerPlugin(gobject.GObject):
def disconnect(self): def disconnect(self):
self._conn[CONN_INTERFACE].Disconnect() self._conn[CONN_INTERFACE].Disconnect()
def _contact_go_offline(self, handle): def _contact_offline(self, handle):
jid = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0]
print jid, "offline"
self._online_contacts.remove(handle)
self.emit("contact-offline", handle) self.emit("contact-offline", handle)
del self._online_contacts[handle]
def _contact_go_online(self, handle): def _contact_online(self, handle):
jid = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0]
print jid, "online"
try: try:
props = self._conn[CONN_INTERFACE_BUDDY_INFO].GetProperties(handle) props = self._conn[CONN_INTERFACE_BUDDY_INFO].GetProperties(handle)
except dbus.DBusException, e: except dbus.DBusException, e:
if str(e).startswith("org.freedesktop.DBus.Error.NoReply"): if str(e).startswith("org.freedesktop.DBus.Error.NoReply"):
raise InvalidBuddyError("couldn't get properties") raise InvalidBuddyError("couldn't get properties")
name = self._conn[CONN_INTERFACE_ALIASING].RequestAliases([handle])[0]
if not props.has_key('color'): if not props.has_key('color'):
raise InvalidBuddyError("no color") raise InvalidBuddyError("no color")
if not props.has_key('key'): if not props.has_key('key'):
raise InvalidBuddyError("no key") raise InvalidBuddyError("no key")
if not name:
raise InvalidBuddyError("no name")
self._online_contacts.add(handle) jid = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0]
nick = self._conn[CONN_INTERFACE_ALIASING].RequestAliases([handle])[0]
if not nick:
raise InvalidBuddyError("no name")
props['nick'] = nick
self._online_contacts[handle] = jid
self.emit("contact-online", handle, props) self.emit("contact-online", handle, props)
def _presence_update_cb(self, presence): def _presence_update_cb(self, presence):
for handle in presence: for handle in presence:
timestamp, statuses = presence[handle] timestamp, statuses = presence[handle]
name = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0]
online = handle in self._online_contacts online = handle in self._online_contacts
for status, params in statuses.items(): for status, params in statuses.items():
print "Handle %s now online=%s with status %s" % (handle, online, status)
if not online and status in ["available", "away", "brb", "busy", "dnd", "xa"]: if not online and status in ["available", "away", "brb", "busy", "dnd", "xa"]:
try: try:
self._contact_go_online(handle) self._contact_online(handle)
except InvalidBuddyError, e: except InvalidBuddyError, e:
print "Not adding %s because %s" % (handle, e) print "Not adding %s because %s" % (handle, e)
elif online and status in ["offline", "invisible"]: elif online and status in ["offline", "invisible"]:
self._contact_go_offline(handle) self._contact_offline(handle)
def _avatar_updated_cb(self, handle, new_avatar_token): def _avatar_updated_cb(self, handle, new_avatar_token):
jid = self._conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0] jid = self._online_contacts[handle]
icon = self._icon_cache.get_icon(jid, new_avatar_token) icon = self._icon_cache.get_icon(jid, new_avatar_token)
if not icon: if not icon:
# cache miss # cache miss
avatar, mime_type = self._conn[CONN_INTERFACE_AVATARS].RequestAvatar(handle) avatar, mime_type = self._conn[CONN_INTERFACE_AVATARS].RequestAvatar(handle)
@ -335,11 +318,10 @@ class ServerPlugin(gobject.GObject):
self.emit("avatar-updated", handle, icon) self.emit("avatar-updated", handle, icon)
def _alias_changed_cb(self, aliases): def _alias_changed_cb(self, aliases):
print "alias changed cb"
for handle, alias in aliases: for handle, alias in aliases:
name = self._conn[CONN_INTERFACE_ALIASING].RequestAliases([handle])[0] nick = self._conn[CONN_INTERFACE_ALIASING].RequestAliases([handle])[0]
print "new alias", handle, alias, name prop = {'nick': nick}
prop = {'name': name} print "Buddy %s alias changed to %s" % (handle, nick)
self._properties_changed_cb(handle, prop) self._properties_changed_cb(handle, prop)
def _properties_changed_cb(self, contact, properties): def _properties_changed_cb(self, contact, properties):