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