initial checki
[tpathy-callback] / src / SMSListener.py
1 #!/usr/bin/env python
2 '''
3 Created on 03.12.2009
4
5 @author: muelli
6 '''
7
8 import dbus.glib
9 import gobject
10 import logging; logging.basicConfig(level=logging.DEBUG)
11
12 import telepathy
13 from telepathy.interfaces import CLIENT, \
14                                  CLIENT_OBSERVER, \
15                                  CHANNEL
16
17
18 log = logging.getLogger("telepathy-callback")
19
20 sender = None
21 receiver = None
22 gsm_connection = None
23 gsm_account = None
24
25 def is_number(nr):
26     """Checks whether a given string looks like an international phone
27     number"""
28     return True
29
30 def handle_msg(msg, magic="call: ", filter=is_number):
31     """Handles a message, i.e. check for it containing the message containing
32     the magic keyword.
33     Returns the valid number or None
34     """
35     number_candidate = None
36     if msg.startswith(magic):
37         number_candidate = msg[len(magic):]
38         
39     retval = None
40     log.debug("Number candidate: %s" % number_candidate)
41     if number_candidate:
42         valid_number = filter(msg)
43         if valid_number:
44             retval = number_candidate
45             
46     return retval
47
48
49 def request_call(bus, number):
50     channel_dispatcher = bus.get_object('org.freedesktop.Telepathy.ChannelDispatcher',
51                         '/org/freedesktop/Telepathy/ChannelDispatcher')
52     request_args = {'org.freedesktop.Telepathy.Channel.ChannelType:':
53                             dbus.String('org.freedesktop.Telepathy.Channel.Type.StreamedMedia', variant_level=1),
54                 'org.freedesktop.Telepathy.Channel.TargetHandleType':
55                             dbus.String('Contact', variant_level=1),
56                 'org.freedesktop.Telepathy.Channel.TargetID':
57                             dbus.String(sender, variant_level=1),
58                 }
59     # Hopefully, the name of the Handler is correct
60     channel_request_object_name = channel_dispatcher.CreateChannel(gsm_account, request_args,
61                                     dbus.Int64(0),
62                                  "org.freedesktop.Telepathy.Client.Callback")
63     # Stupid DBus Binding don't return an object itself
64     # FIXME: Check whether the bus_name is correct
65     channel_request = bus.get_object('org.freedesktop.Telepathy.ChannelRequest',
66                                      channel_request_object_name)
67     log.debug("Returning Channel Request: %s", channel_request)
68     return channel_request
69
70 def received_message_handler(sender=None, *args, **kwargs):
71     """Listens on the MessageReceived signal by Telepathy.
72     Turns out, that most of the application logic landed here instead
73     of the class created below
74     """
75     print "received_message_handler: %s" % locals()
76     global receiver
77     
78     bus = dbus.SessionBus()
79     
80     if isinstance(sender, dbus.Array):
81         for elem in sender:
82             if isinstance(elem, dbus.Dictionary):
83                 msg = elem.get(u'content', None)
84                 if msg: 
85                     print "Message: %s" % msg
86                     # TODO: Check for Prefix
87                     number = handle_msg(msg)
88                     
89                     if not number == None:
90                         receiver = number
91                         assert sender != None, "Somehow Sender is None, although it should have been set earlier"
92                         
93                         # FIXME: Get connection object
94
95                         
96                         # TODO: Get GSM Account
97 #                        account_manager = bus.get_object('org.freedesktop.Telepathy.AccountManager',
98 #                                                '/org/freedesktop/Telepathy/AccountManager')
99 #                        accounts = account_manager.ValidAccounts()
100 #                        log.debug('Accounts: %s', accounts) 
101                         
102                         # TODO: Call Sender
103                         channel_request = request_call(bus, sender)
104                         # TODO: Listen on channel_request signal: Succeeded
105                         def opened_channel(*args, **kwargs):
106                             log.debug("Opened channel. %s", locals())
107                         
108                                       
109                         bus.add_signal_receiver(opened_channel,
110                                                "Succeeded" )
111                         log.debug("msg: %s, %s", channel_request, dir(channel_request))
112                         channel_request.Proceed()
113                         
114                         # TODO: Call Receiver
115                         channel_request = request_call(bus, receiver)
116                         bus.add_signal_receiver(opened_channel,
117                                                 "Succeeded" )
118                         channel_request.Proceed()
119                         
120                                                 
121                         
122                         
123
124 class Callback(dbus.service.Object, telepathy.server.DBusProperties):
125     name = 'org.freedesktop.Telepathy.Client.Callback'
126     def __init__(self, *args):
127         self.bus = dbus.SessionBus()
128         bus_name = dbus.service.BusName(Callback.name, bus = self.bus)
129         dbus.service.Object.__init__(self, bus_name, '/%s' % Callback.name.replace('.', '/'))
130         
131         self.log = logging.getLogger("Callback")
132         
133         self._interfaces = set()
134         
135         telepathy.server.DBusProperties.__init__(self)
136         
137         self._implement_property_get(CLIENT, {
138             'Interfaces': lambda: [ CLIENT_OBSERVER ],
139           })
140         self._implement_property_get(CLIENT_OBSERVER, {
141             'ObserverChannelFilter': lambda: dbus.Array([
142                     dbus.Dictionary({
143                         'org.freedesktop.Telepathy.Channel.ChannelType': dbus.String('org.freedesktop.Telepathy.Channel.Type.Text'),
144                         'org.freedesktop.Telepathy.Channel.TargetHandleType': dbus.UInt32(1),
145                     }, signature='sv'),
146                     dbus.Dictionary({
147                         'org.freedesktop.Telepathy.Channel.ChannelType': dbus.String('org.freedesktop.Telepathy.Channel.Type.Text'),
148                         'org.freedesktop.Telepathy.Channel.TargetHandleType': dbus.UInt32(2),
149                     }, signature='sv')
150
151                 ], signature='a{sv}')
152           })
153         
154         self.first_call = None
155         self.second_call = None
156         
157         
158         
159     def listen(self):
160         loop = gobject.MainLoop()
161         loop.run()
162
163     
164
165     @dbus.service.method('org.freedesktop.Telepathy.Client.Observer',
166                      in_signature='ooa(oa{sv})oaoa{sv}', out_signature='')
167     def ObserveChannels(self, account, connection, channels, dispatch_operation,
168                         requests_satisfied, observer_info):
169         global sender
170         global gsm_connection
171         global gsm_account
172         
173         print "Incoming"
174         print "account %s" % account
175         print "connection %s" % connection
176         print "\n\n"
177         log = file('/tmp/incoming','wa')
178         log.write( "Incoming channels on %s:" % (connection))
179         log.write("Locals: %s" % locals())
180         
181         sender = None
182         for channel_object, props in channels:
183             print "Channel: %s" % channel_object
184             for k, v in props.iteritems():
185                 print "k: %s :: %s " % (k, v)
186                 print ""
187                 
188             sender = props['org.freedesktop.Telepathy.Channel.InitiatorID']
189             # TODO: Check for SMS
190             gsm_connection = connection
191             gsm_account = account
192             self.bus.add_signal_receiver(received_message_handler,
193                                                "MessageReceived" )
194             print "\n\n"
195             log.write( " - %s :: %s" % (props[CHANNEL + '.ChannelType'],
196                                    props[CHANNEL + '.TargetID'])
197             )
198             
199         
200         print "Sender: %s" % sender    
201
202     
203     @dbus.service.method('org.freedesktop.Telepathy.Client.Handler',
204                      in_signature='ooa(oa{sv})aota{sv}', out_signature='')
205     def HandleChannels(self, account, connection, channels,
206                         requests_satisfied, user_action_time, handler_info):
207         self.log.debug("Hndling channels: %s", locals())
208         if self.first_call == None:
209             self.log.debug('first call set')
210             self.first_call = connection
211         elif self.second_call == None:
212             self.second_call = connection
213             self.log.debug('second call set')
214             
215             # TODO: Merge Calls
216             request_conference = "com.nokia.Telepathy.Channel.Interface.Conference"
217             conference_service = self.bus.get_object(request_conference)
218             request_args = [self.first_call, self.second_call]
219             handles = conference_service.get_dbus_method("AddMemberChannels", request_args)
220
221             
222         else:
223             self.log.critical("Handler got called but two calls apparently "\
224                                 "have been initiated: %s %s",
225                                 self.first_call, self.second_call)
226
227 if __name__ == '__main__':
228     myservice = Callback()
229     myservice.listen()