Prefixing more hacks with HACK to make it easier to remove later
[theonering] / src / channel / contact_list.py
1 import logging
2
3 import telepathy
4
5 import util.go_utils as gobject_utils
6 import util.coroutines as coroutines
7 import gtk_toolbox
8 import handle
9
10
11 _moduleLogger = logging.getLogger("channel.contact_list")
12
13
14 class AbstractListChannel(
15                 telepathy.server.ChannelTypeContactList,
16                 telepathy.server.ChannelInterfaceGroup,
17         ):
18         "Abstract Contact List channels"
19
20         def __init__(self, connection, manager, props, h):
21                 self._manager = manager
22                 self._props = props
23
24                 try:
25                         # HACK Older python-telepathy way
26                         telepathy.server.ChannelTypeContactList.__init__(self, connection, h)
27                 except TypeError:
28                         # HACK Newer python-telepathy way
29                         telepathy.server.ChannelTypeContactList.__init__(self, connection, manager, props)
30                 telepathy.server.ChannelInterfaceGroup.__init__(self)
31
32                 self._session = connection.session
33
34
35 class AllContactsListChannel(AbstractListChannel):
36         """
37         The group of contacts for whom you receive presence
38         """
39
40         def __init__(self, connection, manager, props, h):
41                 AbstractListChannel.__init__(self, connection, manager, props, h)
42
43                 self._callback = coroutines.func_sink(
44                         coroutines.expand_positional(
45                                 self._on_contacts_refreshed
46                         )
47                 )
48                 self._session.addressbook.updateSignalHandler.register_sink(
49                         self._callback
50                 )
51
52                 self.GroupFlagsChanged(0, 0)
53
54                 addressbook = connection.session.addressbook
55                 contacts = addressbook.get_contacts()
56                 self._process_refresh(addressbook, contacts, [])
57
58         @gtk_toolbox.log_exception(_moduleLogger)
59         def Close(self):
60                 self.close()
61
62         def close(self):
63                 self._session.addressbook.updateSignalHandler.unregister_sink(
64                         self._callback
65                 )
66                 self._callback = None
67
68                 telepathy.server.ChannelTypeContactList.Close(self)
69                 if self._manager.channel_exists(self._props):
70                         # HACK Older python-telepathy requires doing this manually
71                         self._manager.remove_channel(self)
72                 self.remove_from_connection()
73
74         @gobject_utils.async
75         @gtk_toolbox.log_exception(_moduleLogger)
76         def _on_contacts_refreshed(self, addressbook, added, removed, changed):
77                 self._process_refresh(addressbook, added, removed)
78
79         def _process_refresh(self, addressbook, added, removed):
80                 connection = self._conn
81                 handlesAdded = [
82                         handle.create_handle(connection, "contact", contactId, phoneNumber)
83                         for contactId in added
84                         for (phoneType, phoneNumber) in addressbook.get_contact_details(contactId)
85                 ]
86                 handlesRemoved = [
87                         handle.create_handle(connection, "contact", contactId, phoneNumber)
88                         for contactId in removed
89                         for (phoneType, phoneNumber) in addressbook.get_contact_details(contactId)
90                 ]
91                 message = ""
92                 actor = 0
93                 reason = telepathy.CHANNEL_GROUP_CHANGE_REASON_NONE
94                 self.MembersChanged(
95                         message,
96                         handlesAdded, handlesRemoved,
97                         (), (),
98                         actor,
99                         reason,
100                 )
101
102
103 def create_contact_list_channel(connection, h):
104         if h.get_name() == 'subscribe':
105                 # The group of contacts for whom you receive presence
106                 ChannelClass = AllContactsListChannel
107         elif h.get_name() == 'publish':
108                 # The group of contacts who may receive your presence
109                 ChannelClass = AllContactsListChannel
110         elif h.get_name() == 'hide':
111                 # A group of contacts who are on the publish list but are temporarily
112                 # disallowed from receiving your presence
113                 # This doesn't make sense to support
114                 _moduleLogger.warn("Unsuported type %s" % h.get_name())
115         elif h.get_name() == 'allow':
116                 # A group of contacts who may send you messages
117                 # @todo Allow-List would be cool to support
118                 _moduleLogger.warn("Unsuported type %s" % h.get_name())
119         elif h.get_name() == 'deny':
120                 # A group of contacts who may not send you messages
121                 # @todo Deny-List would be cool to support
122                 _moduleLogger.warn("Unsuported type %s" % h.get_name())
123         elif h.get_name() == 'stored':
124                 # On protocols where the user's contacts are stored, this contact list
125                 # contains all stored contacts regardless of subscription status.
126                 ChannelClass = AllContactsListChannel
127         else:
128                 raise TypeError("Unknown list type : " + h.get_name())
129         return ChannelClass(connection, h)
130
131