Bump to 0.8.24
[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                 self._conn.add_logger(self)
36
37         @misc_utils.log_exception(_moduleLogger)
38         def Send(self, messageType, text):
39                 if messageType != telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL:
40                         raise telepathy.errors.NotImplemented("Unhandled message type: %r" % messageType)
41
42                 self.Sent(int(time.time()), messageType, text)
43
44                 oldStdin, oldStdout = self.stdin, self.stdout
45                 try:
46                         self.stdin = currentStdin = StringIO.StringIO()
47                         self.stdout = currentStdout = StringIO.StringIO()
48                         self.onecmd(text)
49                 finally:
50                         self.stdin, self.stdout = oldStdin, oldStdout
51
52                 stdoutData = currentStdout.getvalue().strip()
53                 if stdoutData:
54                         self._report_new_message(stdoutData)
55
56         @misc_utils.log_exception(_moduleLogger)
57         def Close(self):
58                 self.close()
59
60         def close(self):
61                 _moduleLogger.debug("Closing debug")
62                 tp.ChannelTypeText.Close(self)
63                 self.remove_from_connection()
64                 self._conn.remove_logger(self)
65
66         def log_message(self, component, message):
67                 formattedMessage = "LOG: %s\n%s" % (component, message)
68                 self._report_new_message(formattedMessage)
69
70         def _report_new_message(self, message):
71                 currentReceivedId = self.__nextRecievedId
72
73                 timestamp = int(time.time())
74                 type = telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL
75
76                 self.Received(currentReceivedId, timestamp, self.__otherHandle, type, 0, message.strip())
77
78                 self.__nextRecievedId += 1
79
80         def do_quit(self, args):
81                 if args:
82                         self._report_new_message("No arguments supported")
83                         return
84
85                 try:
86                         self._conn.manager.quit_now()
87                 except Exception, e:
88                         self._report_new_message(str(e))
89
90         def help_quit(self):
91                 self._report_new_message("Shutdown the connection manager immediately, forcing it to be relaunched on reconnect")
92
93         def do_reset_state_machine(self, args):
94                 try:
95                         args = args.strip().lower()
96                         if not args:
97                                 args  = "all"
98                         if args == "all":
99                                 for machine in self._conn.session.stateMachine._machines:
100                                         machine.reset_timers(True)
101                         elif args == "contacts":
102                                 self._conn.session.addressbookStateMachine.reset_timers(True)
103                         elif args == "voicemail":
104                                 self._conn.session.voicemailsStateMachine.reset_timers(True)
105                         elif args == "texts":
106                                 self._conn.session.textsStateMachine.reset_timers(True)
107                         else:
108                                 self._report_new_message('Unknown machine "%s"' % (args, ))
109                 except Exception, e:
110                         self._report_new_message(str(e))
111
112         def help_reset_state_machine(self):
113                 self._report_new_message("""Reset the refreshing state machine.
114 "reset_state_machine" - resets all
115 "reset_state_machine all"
116 "reset_state_machine contacts"
117 "reset_state_machine voicemail"
118 "reset_state_machine texts"
119 """)
120
121         def do_update_now(self, args):
122                 try:
123                         args = args.strip().lower()
124                         if not args:
125                                 args  = "all"
126                         if args == "all":
127                                 for machine in self._conn.session.stateMachine._machines:
128                                         machine.update_now()
129                         elif args == "contacts":
130                                 self._conn.session.addressbookStateMachine.update_now()
131                         elif args == "voicemail":
132                                 self._conn.session.voicemailsStateMachine.update_now()
133                         elif args == "texts":
134                                 self._conn.session.textsStateMachine.update_now()
135                         else:
136                                 self._report_new_message('Unknown machine "%s"' % (args, ))
137                 except Exception, e:
138                         self._report_new_message(str(e))
139
140         def help_update_now(self):
141                 self._report_new_message("""Updates all the state machines now skipping there initialization time.
142 "update_now" - for all
143 "update_now all"
144 "update_now contacts"
145 "update_now voicemail"
146 "update_now texts"
147 """)
148
149         def do_get_state(self, args):
150                 if args:
151                         self._report_new_message("No arguments supported")
152                         return
153
154                 try:
155                         state = self._conn.session.stateMachine.state
156                         self._report_new_message(str(state))
157                 except Exception, e:
158                         self._report_new_message(str(e))
159
160         def help_get_state(self):
161                 self._report_new_message("Print the current state the refreshing state machine is in")
162
163         def do_get_polling(self, args):
164                 if args:
165                         self._report_new_message("No arguments supported")
166                         return
167                 self._report_new_message("\n".join((
168                         "Contacts:", repr(self._conn.session.addressbookStateMachine)
169                 )))
170                 self._report_new_message("\n".join((
171                         "Voicemail:", repr(self._conn.session.voicemailsStateMachine)
172                 )))
173                 self._report_new_message("\n".join((
174                         "Texts:", repr(self._conn.session.textsStateMachine)
175                 )))
176
177         def help_get_polling(self):
178                 self._report_new_message("Prints the frequency each of the state machines updates")
179
180         def do_get_state_status(self, args):
181                 if args:
182                         self._report_new_message("No arguments supported")
183                         return
184                 self._report_new_message("\n".join((
185                         "Contacts:", str(self._conn.session.addressbookStateMachine)
186                 )))
187                 self._report_new_message("\n".join((
188                         "Voicemail:", str(self._conn.session.voicemailsStateMachine)
189                 )))
190                 self._report_new_message("\n".join((
191                         "Texts:", str(self._conn.session.textsStateMachine)
192                 )))
193
194         def help_get_state_status(self):
195                 self._report_new_message("Prints the current setting for the state machines")
196
197         def do_is_authed(self, args):
198                 le = gobject_utils.AsyncLinearExecution(self._conn.session.pool, self._is_authed)
199                 le.start(args)
200
201         @misc_utils.log_exception(_moduleLogger)
202         def _is_authed(self, args):
203                 if args:
204                         self._report_new_message("No arguments supported")
205                         return
206
207                 try:
208                         isAuthed = yield (
209                                 self._conn.session.backend.is_authed,
210                                 (),
211                                 {}
212                         )
213                         self._report_new_message(str(isAuthed))
214                 except Exception, e:
215                         self._report_new_message(str(e))
216                         return
217
218         def help_is_authed(self):
219                 self._report_new_message("Print whether logged in to Google Voice")
220
221         def do_is_dnd(self, args):
222                 le = gobject_utils.AsyncLinearExecution(self._conn.session.pool, self._is_dnd)
223                 le.start(args)
224
225         @misc_utils.log_exception(_moduleLogger)
226         def _is_dnd(self, args):
227                 if args:
228                         self._report_new_message("No arguments supported")
229                         return
230
231                 try:
232                         isDnd = yield (
233                                 self._conn.session.backend.is_dnd,
234                                 (),
235                                 {}
236                         )
237                         self._report_new_message(str(isDnd))
238                 except Exception, e:
239                         self._report_new_message(str(e))
240                         return
241
242         def help_is_dnd(self):
243                 self._report_new_message("Print whether Do-Not-Disturb mode enabled on the Google Voice account")
244
245         def do_get_account_number(self, args):
246                 if args:
247                         self._report_new_message("No arguments supported")
248                         return
249
250                 try:
251                         number = self._conn.session.backend.get_account_number()
252                         self._report_new_message(number)
253                 except Exception, e:
254                         self._report_new_message(str(e))
255
256         def help_get_account_number(self):
257                 self._report_new_message("Print the Google Voice account number")
258
259         def do_get_callback_numbers(self, args):
260                 if args:
261                         self._report_new_message("No arguments supported")
262                         return
263
264                 try:
265                         numbers = self._conn.session.backend.get_callback_numbers()
266                         numbersDisplay = "\n".join(
267                                 "%s: %s" % (name, number)
268                                 for (number, name) in numbers.iteritems()
269                         )
270                         self._report_new_message(numbersDisplay)
271                 except Exception, e:
272                         self._report_new_message(str(e))
273
274         def help_get_callback_numbers(self):
275                 self._report_new_message("Print a list of all configured callback numbers")
276
277         def do_get_sane_callback_number(self, args):
278                 if args:
279                         self._report_new_message("No arguments supported")
280                         return
281
282                 try:
283                         number = gvoice.backend.get_sane_callback(self._conn.session.backend)
284                         self._report_new_message(number)
285                 except Exception, e:
286                         self._report_new_message(str(e))
287
288         def help_get_sane_callback_number(self):
289                 self._report_new_message("Print the best guess of callback numbers to use")
290
291         def do_get_callback_number(self, args):
292                 if args:
293                         self._report_new_message("No arguments supported")
294                         return
295
296                 try:
297                         number = self._conn.session.backend.get_callback_number()
298                         self._report_new_message(number)
299                 except Exception, e:
300                         self._report_new_message(str(e))
301
302         def help_get_callback_number(self):
303                 self._report_new_message("Print the callback number currently enabled")
304
305         def do_call(self, args):
306                 le = gobject_utils.AsyncLinearExecution(self._conn.session.pool, self._call)
307                 le.start(args)
308
309         @misc_utils.log_exception(_moduleLogger)
310         def _call(self, args):
311                 if not args:
312                         self._report_new_message("Must specify the phone number and only the phone nunber")
313                         return
314
315                 try:
316                         number = args
317                         yield (
318                                 self._conn.session.backend.call,
319                                 (number, ),
320                                 {}
321                         )
322                 except Exception, e:
323                         self._report_new_message(str(e))
324
325         def help_call(self):
326                 self._report_new_message("\n".join(["call NUMBER", "Initiate a callback, Google forwarding the call to the callback number"]))
327
328         def do_send_sms(self, args):
329                 le = gobject_utils.AsyncLinearExecution(self._conn.session.pool, self._send_sms)
330                 le.start(args)
331
332         @misc_utils.log_exception(_moduleLogger)
333         def _send_sms(self, args):
334                 args = args.split(" ")
335                 if 1 < len(args):
336                         self._report_new_message("Must specify the phone number and then message")
337                         return
338
339                 try:
340                         number = args[0]
341                         message = " ".join(args[1:])
342                         yield (
343                                 self._conn.session.backend.send_sms,
344                                 ([number], message),
345                                 {},
346                         )
347                 except Exception, e:
348                         self._report_new_message(str(e))
349
350         def help_send_sms(self):
351                 self._report_new_message("\n".join(["send_sms NUMBER MESSAGE0 MESSAGE1 ...", "Send an sms to number NUMBER"]))
352
353         def do_version(self, args):
354                 if args:
355                         self._report_new_message("No arguments supported")
356                         return
357                 self._report_new_message("%s-%s" % (constants.__version__, constants.__build__))
358
359         def help_version(self):
360                 self._report_new_message("Prints the version (hint: %s-%s)" % (constants.__version__, constants.__build__))
361
362         def do_grab_log(self, args):
363                 if args:
364                         self._report_new_message("No arguments supported")
365                         return
366
367                 try:
368                         publishProps = self._conn.generate_props(telepathy.CHANNEL_TYPE_FILE_TRANSFER, self.__otherHandle, False)
369                         self._conn._channel_manager.channel_for_props(publishProps, signal=True)
370                 except Exception, e:
371                         self._report_new_message(str(e))
372
373         def help_grab_log(self):
374                 self._report_new_message("Download the debug log for including with bug report")
375                 self._report_new_message("Warning: this may contain sensitive information")
376
377         def do_save_log(self, args):
378                 if not args:
379                         self._report_new_message("Must specify a filename to save the log to")
380                         return
381
382                 try:
383                         filename = os.path.expanduser(args)
384                         with open(constants._user_logpath_, "r") as f:
385                                 logLines = f.xreadlines()
386                                 log = "".join(logLines)
387                         with open(filename, "w") as f:
388                                 f.write(log)
389                 except Exception, e:
390                         self._report_new_message(str(e))
391
392         def help_save_log(self):
393                 self._report_new_message("Save the log to a specified location")