47a31dd70e99087c93bb0aa77fb5990ee23fa772
[theonering] / src / channel / debug_prompt.py
1 from __future__ import with_statement
2
3 import os
4 import cmd
5 import StringIO
6 import time
7 import datetime
8 import logging
9
10 import telepathy
11
12 import constants
13 import tp
14 import util.misc as misc_utils
15 import util.go_utils as gobject_utils
16 import gvoice
17
18
19 _moduleLogger = logging.getLogger(__name__)
20
21
22 class DebugPromptChannel(tp.ChannelTypeText, cmd.Cmd):
23
24         def __init__(self, connection, manager, props, contactHandle):
25                 self.__manager = manager
26                 self.__props = props
27
28                 cmd.Cmd.__init__(self, "Debug Prompt")
29                 self.use_rawinput = False
30                 tp.ChannelTypeText.__init__(self, connection, manager, props)
31                 self.__nextRecievedId = 0
32                 self.__lastMessageTimestamp = datetime.datetime(1, 1, 1)
33
34                 self.__otherHandle = contactHandle
35
36         @misc_utils.log_exception(_moduleLogger)
37         def Send(self, messageType, text):
38                 if messageType != telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL:
39                         raise telepathy.errors.NotImplemented("Unhandled message type: %r" % messageType)
40
41                 self.Sent(int(time.time()), messageType, text)
42
43                 oldStdin, oldStdout = self.stdin, self.stdout
44                 try:
45                         self.stdin = currentStdin = StringIO.StringIO()
46                         self.stdout = currentStdout = StringIO.StringIO()
47                         self.onecmd(text)
48                 finally:
49                         self.stdin, self.stdout = oldStdin, oldStdout
50
51                 stdoutData = currentStdout.getvalue().strip()
52                 if stdoutData:
53                         self._report_new_message(stdoutData)
54
55         @misc_utils.log_exception(_moduleLogger)
56         def Close(self):
57                 self.close()
58
59         def close(self):
60                 _moduleLogger.debug("Closing debug")
61                 tp.ChannelTypeText.Close(self)
62                 self.remove_from_connection()
63
64         def _report_new_message(self, message):
65                 currentReceivedId = self.__nextRecievedId
66
67                 timestamp = int(time.time())
68                 type = telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL
69
70                 self.Received(currentReceivedId, timestamp, self.__otherHandle, type, 0, message.strip())
71
72                 self.__nextRecievedId += 1
73
74         def do_reset_state_machine(self, args):
75                 try:
76                         args = args.strip().lower()
77                         if not args:
78                                 args  = "all"
79                         if args == "all":
80                                 for machine in self._conn.session.stateMachine._machines:
81                                         machine.reset_timers()
82                         elif args == "contacts":
83                                 self._conn.session.addressbookStateMachine.reset_timers()
84                         elif args == "voicemail":
85                                 self._conn.session.voicemailsStateMachine.reset_timers()
86                         elif args == "texts":
87                                 self._conn.session.textsStateMachine.reset_timers()
88                         else:
89                                 self._report_new_message('Unknown machine "%s"' % (args, ))
90                 except Exception, e:
91                         self._report_new_message(str(e))
92
93         def help_reset_state_machine(self):
94                 self._report_new_message("""Reset the refreshing state machine.
95 "reset_state_machine" - resets all
96 "reset_state_machine all"
97 "reset_state_machine contacts"
98 "reset_state_machine voicemail"
99 "reset_state_machine texts"
100 """)
101
102         def do_get_state(self, args):
103                 if args:
104                         self._report_new_message("No arguments supported")
105                         return
106
107                 try:
108                         state = self._conn.session.stateMachine.state
109                         self._report_new_message(str(state))
110                 except Exception, e:
111                         self._report_new_message(str(e))
112
113         def help_get_state(self):
114                 self._report_new_message("Print the current state the refreshing state machine is in")
115
116         def do_get_polling(self, args):
117                 if args:
118                         self._report_new_message("No arguments supported")
119                         return
120                 self._report_new_message("\n".join((
121                         "Contacts:", repr(self._conn.session.addressbookStateMachine)
122                 )))
123                 self._report_new_message("\n".join((
124                         "Voicemail:", repr(self._conn.session.voicemailsStateMachine)
125                 )))
126                 self._report_new_message("\n".join((
127                         "Texts:", repr(self._conn.session.textsStateMachine)
128                 )))
129
130         def help_get_polling(self):
131                 self._report_new_message("Prints the frequency each of the state machines updates")
132
133         def do_get_state_status(self, args):
134                 if args:
135                         self._report_new_message("No arguments supported")
136                         return
137                 self._report_new_message("\n".join((
138                         "Contacts:", str(self._conn.session.addressbookStateMachine)
139                 )))
140                 self._report_new_message("\n".join((
141                         "Voicemail:", str(self._conn.session.voicemailsStateMachine)
142                 )))
143                 self._report_new_message("\n".join((
144                         "Texts:", str(self._conn.session.textsStateMachine)
145                 )))
146
147         def help_get_state_status(self):
148                 self._report_new_message("Prints the current setting for the state machines")
149
150         def do_is_authed(self, args):
151                 le = gobject_utils.AsyncLinearExecution(self._conn.session.pool, self._is_authed)
152                 le.start(args)
153
154         @misc_utils.log_exception(_moduleLogger)
155         def _is_authed(self, args):
156                 if args:
157                         self._report_new_message("No arguments supported")
158                         return
159
160                 try:
161                         isAuthed = yield (
162                                 self._conn.session.backend.is_authed,
163                                 (),
164                                 {}
165                         )
166                         self._report_new_message(str(isAuthed))
167                 except Exception, e:
168                         self._report_new_message(str(e))
169
170         def help_is_authed(self):
171                 self._report_new_message("Print whether logged in to Google Voice")
172
173         def do_is_dnd(self, args):
174                 le = gobject_utils.AsyncLinearExecution(self._conn.session.pool, self._is_dnd)
175                 le.start(args)
176
177         @misc_utils.log_exception(_moduleLogger)
178         def _is_dnd(self, args):
179                 if args:
180                         self._report_new_message("No arguments supported")
181                         return
182
183                 try:
184                         isDnd = yield (
185                                 self._conn.session.backend.is_dnd,
186                                 (),
187                                 {}
188                         )
189                         self._report_new_message(str(isDnd))
190                 except Exception, e:
191                         self._report_new_message(str(e))
192
193         def help_is_dnd(self):
194                 self._report_new_message("Print whether Do-Not-Disturb mode enabled on the Google Voice account")
195
196         def do_get_account_number(self, args):
197                 if args:
198                         self._report_new_message("No arguments supported")
199                         return
200
201                 try:
202                         number = self._conn.session.backend.get_account_number()
203                         self._report_new_message(number)
204                 except Exception, e:
205                         self._report_new_message(str(e))
206
207         def help_get_account_number(self):
208                 self._report_new_message("Print the Google Voice account number")
209
210         def do_get_callback_numbers(self, args):
211                 if args:
212                         self._report_new_message("No arguments supported")
213                         return
214
215                 try:
216                         numbers = self._conn.session.backend.get_callback_numbers()
217                         numbersDisplay = "\n".join(
218                                 "%s: %s" % (name, number)
219                                 for (number, name) in numbers.iteritems()
220                         )
221                         self._report_new_message(numbersDisplay)
222                 except Exception, e:
223                         self._report_new_message(str(e))
224
225         def help_get_callback_numbers(self):
226                 self._report_new_message("Print a list of all configured callback numbers")
227
228         def do_get_sane_callback_number(self, args):
229                 if args:
230                         self._report_new_message("No arguments supported")
231                         return
232
233                 try:
234                         number = gvoice.backend.get_sane_callback(self._conn.session.backend)
235                         self._report_new_message(number)
236                 except Exception, e:
237                         self._report_new_message(str(e))
238
239         def help_get_sane_callback_number(self):
240                 self._report_new_message("Print the best guess of callback numbers to use")
241
242         def do_get_callback_number(self, args):
243                 if args:
244                         self._report_new_message("No arguments supported")
245                         return
246
247                 try:
248                         number = self._conn.session.backend.get_callback_number()
249                         self._report_new_message(number)
250                 except Exception, e:
251                         self._report_new_message(str(e))
252
253         def help_get_callback_number(self):
254                 self._report_new_message("Print the callback number currently enabled")
255
256         def do_call(self, args):
257                 le = gobject_utils.AsyncLinearExecution(self._conn.session.pool, self._call)
258                 le.start(args)
259
260         @misc_utils.log_exception(_moduleLogger)
261         def _call(self, args):
262                 if not args:
263                         self._report_new_message("Must specify the phone number and only the phone nunber")
264                         return
265
266                 try:
267                         number = args
268                         yield (
269                                 self._conn.session.backend.call,
270                                 (number),
271                                 {}
272                         )
273                 except Exception, e:
274                         self._report_new_message(str(e))
275
276         def help_call(self):
277                 self._report_new_message("\n".join(["call NUMBER", "Initiate a callback, Google forwarding the call to the callback number"]))
278
279         def do_send_sms(self, args):
280                 le = gobject_utils.AsyncLinearExecution(self._conn.session.pool, self._send_sms)
281                 le.start(args)
282
283         @misc_utils.log_exception(_moduleLogger)
284         def _send_sms(self, args):
285                 args = args.split(" ")
286                 if 1 < len(args):
287                         self._report_new_message("Must specify the phone number and then message")
288                         return
289
290                 try:
291                         number = args[0]
292                         message = " ".join(args[1:])
293                         yield (
294                                 self._conn.session.backend.send_sms,
295                                 ([number], message),
296                                 {},
297                         )
298                 except Exception, e:
299                         self._report_new_message(str(e))
300
301         def help_send_sms(self):
302                 self._report_new_message("\n".join(["send_sms NUMBER MESSAGE0 MESSAGE1 ...", "Send an sms to number NUMBER"]))
303
304         def do_version(self, args):
305                 if args:
306                         self._report_new_message("No arguments supported")
307                         return
308                 self._report_new_message("%s-%s" % (constants.__version__, constants.__build__))
309
310         def help_version(self):
311                 self._report_new_message("Prints the version (hint: %s-%s)" % (constants.__version__, constants.__build__))
312
313         def do_grab_log(self, args):
314                 if args:
315                         self._report_new_message("No arguments supported")
316                         return
317
318                 try:
319                         publishProps = self._conn.generate_props(telepathy.CHANNEL_TYPE_FILE_TRANSFER, self.__otherHandle, False)
320                         self._conn._channel_manager.channel_for_props(publishProps, signal=True)
321                 except Exception, e:
322                         self._report_new_message(str(e))
323
324         def help_grab_log(self):
325                 self._report_new_message("Download the debug log for including with bug report")
326                 self._report_new_message("Warning: this may contain sensitive information")
327
328         def do_save_log(self, args):
329                 if not args:
330                         self._report_new_message("Must specify a filename to save the log to")
331                         return
332
333                 try:
334                         filename = os.path.expanduser(args)
335                         with open(constants._user_logpath_, "r") as f:
336                                 logLines = f.xreadlines()
337                                 log = "".join(logLines)
338                         with open(filename, "w") as f:
339                                 f.write(log)
340                 except Exception, e:
341                         self._report_new_message(str(e))
342
343         def help_save_log(self):
344                 self._report_new_message("Save the log to a specified location")