When removing the async calls I ended up wiping information on a callback, so moving...
[theonering] / src / channel / contact_list.py
index 3fbd722..8f38fbd 100644 (file)
-import weakref
 import logging
 
 import telepathy
 
-import util.go_utils as gobject_utils
 import util.coroutines as coroutines
+import gtk_toolbox
 import handle
 
 
 _moduleLogger = logging.getLogger("channel.contact_list")
 
 
-class AbstractListChannel(
+class AllContactsListChannel(
                telepathy.server.ChannelTypeContactList,
                telepathy.server.ChannelInterfaceGroup,
        ):
-       "Abstract Contact List channels"
+       """
+       The group of contacts for whom you receive presence
+       """
 
-       def __init__(self, connection, h):
-               telepathy.server.ChannelTypeContactList.__init__(self, connection, h)
+       def __init__(self, connection, manager, props, h):
+               try:
+                       # HACK Older python-telepathy way
+                       telepathy.server.ChannelTypeContactList.__init__(self, connection, h)
+                       self._requested = props[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested']
+                       self._implement_property_get(
+                               telepathy.interfaces.CHANNEL_INTERFACE,
+                               {"Requested": lambda: self._requested}
+                       )
+               except TypeError:
+                       # HACK Newer python-telepathy way
+                       telepathy.server.ChannelTypeContactList.__init__(self, connection, manager, props)
                telepathy.server.ChannelInterfaceGroup.__init__(self)
 
-               self._conn_ref = weakref.ref(connection)
-               self._addessbook = connection.addressbook
+               self.__manager = manager
+               self.__props = props
+               self.__session = connection.session
 
+               self._callback = coroutines.func_sink(
+                       coroutines.expand_positional(
+                               self._on_contacts_refreshed
+                       )
+               )
+               self.__session.addressbook.updateSignalHandler.register_sink(
+                       self._callback
+               )
 
-class AllContactsListChannel(AbstractListChannel):
-       """
-       The group of contacts for whom you receive presence
-       """
-
-       def __init__(self, connection, h):
-               AbstractListChannel.__init__(self, connection, h)
-               self._addressbook.updateSignalHandle.register_sink(
-                       self._on_contacts_refreshed
+               self.GroupFlagsChanged(0, 0)
+
+               addressbook = connection.session.addressbook
+               contacts = addressbook.get_contacts()
+               self._process_refresh(addressbook, contacts, [])
+
+       def get_props(self):
+               # HACK Older python-telepathy doesn't provide this
+               _immutable_properties = {
+                       'ChannelType': telepathy.server.interfaces.CHANNEL_INTERFACE,
+                       'TargetHandle': telepathy.server.interfaces.CHANNEL_INTERFACE,
+                       'Interfaces': telepathy.server.interfaces.CHANNEL_INTERFACE,
+                       'TargetHandleType': telepathy.server.interfaces.CHANNEL_INTERFACE,
+                       'TargetID': telepathy.server.interfaces.CHANNEL_INTERFACE,
+                       'Requested': telepathy.server.interfaces.CHANNEL_INTERFACE
+               }
+               props = dict()
+               for prop, iface in _immutable_properties.items():
+                       props[iface + '.' + prop] = \
+                               self._prop_getters[iface][prop]()
+               return props
+
+       @gtk_toolbox.log_exception(_moduleLogger)
+       def Close(self):
+               self.close()
+
+       def close(self):
+               self.__session.addressbook.updateSignalHandler.unregister_sink(
+                       self._callback
                )
+               self._callback = None
 
-       @coroutines.func_sink
-       @coroutines.expand_positional
-       @gobject_utils.async
+               telepathy.server.ChannelTypeContactList.Close(self)
+               if self.__manager.channel_exists(self.__props):
+                       # HACK Older python-telepathy requires doing this manually
+                       self.__manager.remove_channel(self)
+               self.remove_from_connection()
+
+       @gtk_toolbox.log_exception(_moduleLogger)
        def _on_contacts_refreshed(self, addressbook, added, removed, changed):
-               connection = self._conn_ref()
+               self._process_refresh(addressbook, added, removed)
+
+       def _process_refresh(self, addressbook, added, removed):
+               connection = self._conn
                handlesAdded = [
-                       handle.create_handle(connection, "contact", contactId)
+                       handle.create_handle(connection, "contact", contactId, phoneNumber)
                        for contactId in added
+                       for (phoneType, phoneNumber) in addressbook.get_contact_details(contactId)
                ]
                handlesRemoved = [
-                       handle.create_handle(connection, "contact", contactId)
+                       handle.create_handle(connection, "contact", contactId, phoneNumber)
                        for contactId in removed
+                       for (phoneType, phoneNumber) in addressbook.get_contact_details(contactId)
                ]
                message = ""
                actor = 0
@@ -61,7 +111,7 @@ class AllContactsListChannel(AbstractListChannel):
                )
 
 
-def create_contact_list_channel(connection, h):
+def create_contact_list_channel(connection, manager, props, h):
        if h.get_name() == 'subscribe':
                # The group of contacts for whom you receive presence
                ChannelClass = AllContactsListChannel
@@ -75,11 +125,11 @@ def create_contact_list_channel(connection, h):
                _moduleLogger.warn("Unsuported type %s" % h.get_name())
        elif h.get_name() == 'allow':
                # A group of contacts who may send you messages
-               # @todo This would be cool to support
+               # @todo Allow-List would be cool to support
                _moduleLogger.warn("Unsuported type %s" % h.get_name())
        elif h.get_name() == 'deny':
                # A group of contacts who may not send you messages
-               # @todo This would be cool to support
+               # @todo Deny-List would be cool to support
                _moduleLogger.warn("Unsuported type %s" % h.get_name())
        elif h.get_name() == 'stored':
                # On protocols where the user's contacts are stored, this contact list
@@ -87,6 +137,6 @@ def create_contact_list_channel(connection, h):
                ChannelClass = AllContactsListChannel
        else:
                raise TypeError("Unknown list type : " + h.get_name())
-       return ChannelClass(connection, h)
+       return ChannelClass(connection, manager, props, h)