Plenty of HACKs to get my code to work with Requests
[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                         self._requested = props[telepathy.interfaces.CHANNEL_INTERFACE + '.Requested']
26                         self._implement_property_get(
27                                 telepathy.interfaces.CHANNEL_INTERFACE,
28                                 {"Requested": lambda: self._requested}
29                         )
30                 except TypeError:
31                         # HACK Newer python-telepathy way
32                         telepathy.server.ChannelTypeContactList.__init__(self, connection, manager, props)
33                 telepathy.server.ChannelInterfaceGroup.__init__(self)
34
35                 self.__manager = manager
36                 self.__props = props
37                 self.__session = connection.session
38
39                 self._callback = coroutines.func_sink(
40                         coroutines.expand_positional(
41                                 self._on_contacts_refreshed
42                         )
43                 )
44                 self.__session.addressbook.updateSignalHandler.register_sink(
45                         self._callback
46                 )
47
48                 self.GroupFlagsChanged(0, 0)
49
50                 addressbook = connection.session.addressbook
51                 contacts = addressbook.get_contacts()
52                 self._process_refresh(addressbook, contacts, [])
53
54         def get_props(self):
55                 # HACK Older python-telepathy doesn't provide this
56                 _immutable_properties = {
57                         'ChannelType': telepathy.server.interfaces.CHANNEL_INTERFACE,
58                         'TargetHandle': telepathy.server.interfaces.CHANNEL_INTERFACE,
59                         'Interfaces': telepathy.server.interfaces.CHANNEL_INTERFACE,
60                         'TargetHandleType': telepathy.server.interfaces.CHANNEL_INTERFACE,
61                         'TargetID': telepathy.server.interfaces.CHANNEL_INTERFACE,
62                         'Requested': telepathy.server.interfaces.CHANNEL_INTERFACE
63                 }
64                 props = dict()
65                 for prop, iface in _immutable_properties.items():
66                         props[iface + '.' + prop] = \
67                                 self._prop_getters[iface][prop]()
68                 return props
69
70         @gtk_toolbox.log_exception(_moduleLogger)
71         def Close(self):
72                 self.close()
73
74         def close(self):
75                 self.__session.addressbook.updateSignalHandler.unregister_sink(
76                         self._callback
77                 )
78                 self._callback = None
79
80                 telepathy.server.ChannelTypeContactList.Close(self)
81                 if self.__manager.channel_exists(self.__props):
82                         # HACK Older python-telepathy requires doing this manually
83                         self.__manager.remove_channel(self)
84                 self.remove_from_connection()
85
86         @gtk_toolbox.log_exception(_moduleLogger)
87         def _on_contacts_refreshed(self, addressbook, added, removed, changed):
88                 self._process_refresh(addressbook, added, removed)
89
90         def _process_refresh(self, addressbook, added, removed):
91                 connection = self._conn
92                 handlesAdded = [
93                         handle.create_handle(connection, "contact", contactId, phoneNumber)
94                         for contactId in added
95                         for (phoneType, phoneNumber) in addressbook.get_contact_details(contactId)
96                 ]
97                 handlesRemoved = [
98                         handle.create_handle(connection, "contact", contactId, phoneNumber)
99                         for contactId in removed
100                         for (phoneType, phoneNumber) in addressbook.get_contact_details(contactId)
101                 ]
102                 message = ""
103                 actor = 0
104                 reason = telepathy.CHANNEL_GROUP_CHANGE_REASON_NONE
105                 self.MembersChanged(
106                         message,
107                         handlesAdded, handlesRemoved,
108                         (), (),
109                         actor,
110                         reason,
111                 )
112
113
114 def create_contact_list_channel(connection, manager, props, h):
115         if h.get_name() == 'subscribe':
116                 # The group of contacts for whom you receive presence
117                 ChannelClass = AllContactsListChannel
118         elif h.get_name() == 'publish':
119                 # The group of contacts who may receive your presence
120                 ChannelClass = AllContactsListChannel
121         elif h.get_name() == 'hide':
122                 # A group of contacts who are on the publish list but are temporarily
123                 # disallowed from receiving your presence
124                 # This doesn't make sense to support
125                 _moduleLogger.warn("Unsuported type %s" % h.get_name())
126         elif h.get_name() == 'allow':
127                 # A group of contacts who may send you messages
128                 # @todo Allow-List would be cool to support
129                 _moduleLogger.warn("Unsuported type %s" % h.get_name())
130         elif h.get_name() == 'deny':
131                 # A group of contacts who may not send you messages
132                 # @todo Deny-List would be cool to support
133                 _moduleLogger.warn("Unsuported type %s" % h.get_name())
134         elif h.get_name() == 'stored':
135                 # On protocols where the user's contacts are stored, this contact list
136                 # contains all stored contacts regardless of subscription status.
137                 ChannelClass = AllContactsListChannel
138         else:
139                 raise TypeError("Unknown list type : " + h.get_name())
140         return ChannelClass(connection, manager, props, h)
141
142