Favorites support
[gonvert] / src / util / tp_utils.py
1 #!/usr/bin/env python
2
3 import logging
4
5 import dbus
6 import telepathy
7
8 import util.go_utils as gobject_utils
9 import misc
10
11
12 _moduleLogger = logging.getLogger(__name__)
13 DBUS_PROPERTIES = 'org.freedesktop.DBus.Properties'
14
15
16 class WasMissedCall(object):
17
18         def __init__(self, bus, conn, chan, on_success, on_error):
19                 self.__on_success = on_success
20                 self.__on_error = on_error
21
22                 self._requested = None
23                 self._didMembersChange = False
24                 self._didClose = False
25                 self._didReport = False
26
27                 self._onTimeout = gobject_utils.Timeout(self._on_timeout)
28                 self._onTimeout.start(seconds=10)
29
30                 chan[telepathy.interfaces.CHANNEL_INTERFACE_GROUP].connect_to_signal(
31                         "MembersChanged",
32                         self._on_members_changed,
33                 )
34
35                 chan[telepathy.interfaces.CHANNEL].connect_to_signal(
36                         "Closed",
37                         self._on_closed,
38                 )
39
40                 chan[DBUS_PROPERTIES].GetAll(
41                         telepathy.interfaces.CHANNEL_INTERFACE,
42                         reply_handler = self._on_got_all,
43                         error_handler = self._on_error,
44                 )
45
46         def cancel(self):
47                 self._report_error("by request")
48
49         def _report_missed_if_ready(self):
50                 if self._didReport:
51                         pass
52                 elif self._requested is not None and (self._didMembersChange or self._didClose):
53                         if self._requested:
54                                 self._report_error("wrong direction")
55                         elif self._didClose:
56                                 self._report_success()
57                         else:
58                                 self._report_error("members added")
59                 else:
60                         if self._didClose:
61                                 self._report_error("closed too early")
62
63         def _report_success(self):
64                 assert not self._didReport
65                 self._didReport = True
66                 self._onTimeout.cancel()
67                 self.__on_success(self)
68
69         def _report_error(self, reason):
70                 assert not self._didReport
71                 self._didReport = True
72                 self._onTimeout.cancel()
73                 self.__on_error(self, reason)
74
75         @misc.log_exception(_moduleLogger)
76         def _on_got_all(self, properties):
77                 self._requested = properties["Requested"]
78                 self._report_missed_if_ready()
79
80         @misc.log_exception(_moduleLogger)
81         def _on_members_changed(self, message, added, removed, lp, rp, actor, reason):
82                 if added:
83                         self._didMembersChange = True
84                         self._report_missed_if_ready()
85
86         @misc.log_exception(_moduleLogger)
87         def _on_closed(self):
88                 self._didClose = True
89                 self._report_missed_if_ready()
90
91         @misc.log_exception(_moduleLogger)
92         def _on_error(self, *args):
93                 self._report_error(args)
94
95         @misc.log_exception(_moduleLogger)
96         def _on_timeout(self):
97                 self._report_error("timeout")
98                 return False
99
100
101 class NewChannelSignaller(object):
102
103         def __init__(self, on_new_channel):
104                 self._sessionBus = dbus.SessionBus()
105                 self._on_user_new_channel = on_new_channel
106
107         def start(self):
108                 self._sessionBus.add_signal_receiver(
109                         self._on_new_channel,
110                         "NewChannel",
111                         "org.freedesktop.Telepathy.Connection",
112                         None,
113                         None
114                 )
115
116         def stop(self):
117                 self._sessionBus.remove_signal_receiver(
118                         self._on_new_channel,
119                         "NewChannel",
120                         "org.freedesktop.Telepathy.Connection",
121                         None,
122                         None
123                 )
124
125         @misc.log_exception(_moduleLogger)
126         def _on_new_channel(
127                 self, channelObjectPath, channelType, handleType, handle, supressHandler
128         ):
129                 connObjectPath = channel_path_to_conn_path(channelObjectPath)
130                 serviceName = path_to_service_name(channelObjectPath)
131                 try:
132                         self._on_user_new_channel(
133                                 self._sessionBus, serviceName, connObjectPath, channelObjectPath, channelType
134                         )
135                 except Exception:
136                         _moduleLogger.exception("Blocking exception from being passed up")
137
138
139 class EnableSystemContactIntegration(object):
140
141         ACCOUNT_MGR_NAME = "org.freedesktop.Telepathy.AccountManager"
142         ACCOUNT_MGR_PATH = "/org/freedesktop/Telepathy/AccountManager"
143         ACCOUNT_MGR_IFACE_QUERY = "com.nokia.AccountManager.Interface.Query"
144         ACCOUNT_IFACE_COMPAT = "com.nokia.Account.Interface.Compat"
145         ACCOUNT_IFACE_COMPAT_PROFILE = "com.nokia.Account.Interface.Compat.Profile"
146         DBUS_PROPERTIES = 'org.freedesktop.DBus.Properties'
147
148         def __init__(self, profileName):
149                 self._bus = dbus.SessionBus()
150                 self._profileName = profileName
151
152         def start(self):
153                 self._accountManager = self._bus.get_object(
154                         self.ACCOUNT_MGR_NAME,
155                         self.ACCOUNT_MGR_PATH,
156                 )
157                 self._accountManagerQuery = dbus.Interface(
158                         self._accountManager,
159                         dbus_interface=self.ACCOUNT_MGR_IFACE_QUERY,
160                 )
161
162                 self._accountManagerQuery.FindAccounts(
163                         {
164                                 self.ACCOUNT_IFACE_COMPAT_PROFILE: self._profileName,
165                         },
166                         reply_handler = self._on_found_accounts_reply,
167                         error_handler = self._on_error,
168                 )
169
170         @misc.log_exception(_moduleLogger)
171         def _on_found_accounts_reply(self, accountObjectPaths):
172                 for accountObjectPath in accountObjectPaths:
173                         print accountObjectPath
174                         account = self._bus.get_object(
175                                 self.ACCOUNT_MGR_NAME,
176                                 accountObjectPath,
177                         )
178                         accountProperties = dbus.Interface(
179                                 account,
180                                 self.DBUS_PROPERTIES,
181                         )
182                         accountProperties.Set(
183                                 self.ACCOUNT_IFACE_COMPAT,
184                                 "SecondaryVCardFields",
185                                 ["TEL"],
186                                 reply_handler = self._on_field_set,
187                                 error_handler = self._on_error,
188                         )
189
190         @misc.log_exception(_moduleLogger)
191         def _on_field_set(self):
192                 _moduleLogger.info("SecondaryVCardFields Set")
193
194         @misc.log_exception(_moduleLogger)
195         def _on_error(self, error):
196                 _moduleLogger.error("%r" % (error, ))
197
198
199 def channel_path_to_conn_path(channelObjectPath):
200         """
201         >>> channel_path_to_conn_path("/org/freedesktop/Telepathy/ConnectionManager/theonering/gv/USERNAME/Channel1")
202         '/org/freedesktop/Telepathy/ConnectionManager/theonering/gv/USERNAME'
203         """
204         return channelObjectPath.rsplit("/", 1)[0]
205
206
207 def path_to_service_name(path):
208         """
209         >>> path_to_service_name("/org/freedesktop/Telepathy/ConnectionManager/theonering/gv/USERNAME/Channel1")
210         'org.freedesktop.Telepathy.ConnectionManager.theonering.gv.USERNAME'
211         """
212         return ".".join(path[1:].split("/")[0:7])
213
214
215 def cm_from_path(path):
216         """
217         >>> cm_from_path("/org/freedesktop/Telepathy/ConnectionManager/theonering/gv/USERNAME/Channel1")
218         'theonering'
219         """
220         return path[1:].split("/")[4]