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