2724a45792e0fc5eb9713924f5cfe6907ba35376
[theonering] / src / connection.py
1 import weakref
2 import logging
3
4 import telepathy
5
6 import constants
7 import gtk_toolbox
8 import gvoice
9 import handle
10 import aliasing
11 import simple_presence
12 import channel_manager
13
14
15 _moduleLogger = logging.getLogger("connection")
16
17
18 class TheOneRingConnection(
19         telepathy.server.Connection,
20         aliasing.AliasingMixin,
21         simple_presence.SimplePresenceMixin,
22 ):
23
24         # Overriding a base class variable
25         # Should the forwarding number be handled by the alias or by an option?
26         _mandatory_parameters = {
27                 'username' : 's',
28                 'password' : 's',
29                 'forward' : 's',
30         }
31         # Overriding a base class variable
32         _optional_parameters = {
33         }
34         _parameter_defaults = {
35         }
36
37         def __init__(self, manager, parameters):
38                 try:
39                         self.check_parameters(parameters)
40                         account = unicode(parameters['username'])
41
42                         # Connection init must come first
43                         telepathy.server.Connection.__init__(
44                                 self,
45                                 constants._telepathy_protocol_name_,
46                                 account,
47                                 constants._telepathy_implementation_name_
48                         )
49                         aliasing.AliasingMixin.__init__(self)
50                         simple_presence.SimplePresenceMixin.__init__(self)
51
52                         self._manager = weakref.proxy(manager)
53                         self._credentials = (
54                                 parameters['username'].encode('utf-8'),
55                                 parameters['password'].encode('utf-8'),
56                         )
57                         self._callbackNumber = parameters['forward'].encode('utf-8')
58                         self._channelManager = channel_manager.ChannelManager(self)
59
60                         cookieFilePath = "%s/cookies.txt" % constants._data_path_
61                         self._session = gvoice.session.Session(cookieFilePath)
62
63                         self.set_self_handle(handle.create_handle(self, 'connection'))
64
65                         _moduleLogger.info("Connection to the account %s created" % account)
66                 except Exception, e:
67                         _moduleLogger.exception("Failed to create Connection")
68                         raise
69
70         @property
71         def manager(self):
72                 return self._manager
73
74         @property
75         def session(self):
76                 return self._session
77
78         @property
79         def username(self):
80                 return self._credentials[0]
81
82         def handle(self, handleType, handleId):
83                 self.check_handle(handleType, handleId)
84                 return self._handles[handleType, handleId]
85
86         @gtk_toolbox.log_exception(_moduleLogger)
87         def Connect(self):
88                 """
89                 For org.freedesktop.telepathy.Connection
90                 """
91                 _moduleLogger.info("Connecting...")
92                 self.StatusChanged(
93                         telepathy.CONNECTION_STATUS_CONNECTING,
94                         telepathy.CONNECTION_STATUS_REASON_REQUESTED
95                 )
96                 try:
97                         self.session.login(*self._credentials)
98                         self.session.backend.set_callback_number(self._callbackNumber)
99                 except gvoice.backend.NetworkError, e:
100                         _moduleLogger.exception("Connection Failed")
101                         self.StatusChanged(
102                                 telepathy.CONNECTION_STATUS_DISCONNECTED,
103                                 telepathy.CONNECTION_STATUS_REASON_NETWORK_ERROR
104                         )
105                 except Exception, e:
106                         _moduleLogger.exception("Connection Failed")
107                         self.StatusChanged(
108                                 telepathy.CONNECTION_STATUS_DISCONNECTED,
109                                 telepathy.CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED
110                         )
111                 else:
112                         _moduleLogger.info("Connected")
113                         self.StatusChanged(
114                                 telepathy.CONNECTION_STATUS_CONNECTED,
115                                 telepathy.CONNECTION_STATUS_REASON_REQUESTED
116                         )
117
118         @gtk_toolbox.log_exception(_moduleLogger)
119         def Disconnect(self):
120                 """
121                 For org.freedesktop.telepathy.Connection
122                 @bug Not properly logging out.  Cookie files need to be per connection and removed
123                 """
124                 _moduleLogger.info("Disconnecting")
125                 try:
126                         self.session.logout()
127                         _moduleLogger.info("Disconnected")
128                 except Exception:
129                         _moduleLogger.exception("Disconnecting Failed")
130                 self.StatusChanged(
131                         telepathy.CONNECTION_STATUS_DISCONNECTED,
132                         telepathy.CONNECTION_STATUS_REASON_REQUESTED
133                 )
134
135         @gtk_toolbox.log_exception(_moduleLogger)
136         def RequestChannel(self, type, handleType, handleId, suppressHandler):
137                 """
138                 For org.freedesktop.telepathy.Connection
139
140                 @param type DBus interface name for base channel type
141                 @param handleId represents a contact, list, etc according to handleType
142
143                 @returns DBus object path for the channel created or retrieved
144                 """
145                 self.check_connected()
146                 self.check_handle(handleType, handleId)
147
148                 channel = None
149                 channelManager = self._channelManager
150                 handle = self.handle(handleType, handleId)
151
152                 if type == telepathy.CHANNEL_TYPE_CONTACT_LIST:
153                         _moduleLogger.info("RequestChannel ContactList")
154                         channel = channelManager.channel_for_list(handle, suppressHandler)
155                 elif type == telepathy.CHANNEL_TYPE_TEXT:
156                         _moduleLogger.info("RequestChannel Text")
157                         channel = channelManager.channel_for_text(handle, suppressHandler)
158                 elif type == telepathy.CHANNEL_TYPE_STREAMED_MEDIA:
159                         _moduleLogger.info("RequestChannel Media")
160                         channel = channelManager.channel_for_call(handle, suppressHandler)
161                 else:
162                         raise telepathy.errors.NotImplemented("unknown channel type %s" % type)
163
164                 _moduleLogger.info("RequestChannel Object Path: %s" % channel._object_path)
165                 return channel._object_path
166
167         @gtk_toolbox.log_exception(_moduleLogger)
168         def RequestHandles(self, handleType, names, sender):
169                 """
170                 For org.freedesktop.telepathy.Connection
171                 Overiding telepathy.server.Connecton to allow custom handles
172                 """
173                 self.check_connected()
174                 self.check_handle_type(handleType)
175
176                 handles = []
177                 for name in names:
178                         name = name.encode('utf-8')
179                         if handleType == telepathy.HANDLE_TYPE_CONTACT:
180                                 _moduleLogger.info("RequestHandles Contact: %s" % name)
181                                 h = self._create_contact_handle(name)
182                         elif handleType == telepathy.HANDLE_TYPE_LIST:
183                                 # Support only server side (immutable) lists
184                                 _moduleLogger.info("RequestHandles List: %s" % name)
185                                 h = handle.create_handle(self, 'list', name)
186                         else:
187                                 raise telepathy.errors.NotAvailable('Handle type unsupported %d' % handleType)
188                         handles.append(h.id)
189                         self.add_client_handle(h, sender)
190                 return handles
191
192         def _create_contact_handle(self, requestedHandleName):
193                 requestedContactId, requestedContactNumber = handle.ContactHandle.from_handle_name(
194                         requestedHandleName
195                 )
196                 h = handle.create_handle(self, 'contact', requestedContactId, requestedContactNumber)
197                 return h
198
199         def _on_invite_text(self, contactId):
200                 """
201                 @todo Get externally initiated conversations working
202                 """
203                 h = self._create_contact_handle(contactId)
204
205                 channelManager = self._channelManager
206                 channel = channelManager.channel_for_text(handle)