4 DialCentral - Front end for Google's GoogleVoice service.
5 Copyright (C) 2008 Eric Warnke ericew AT gmail DOT com
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 Google Voice backend code
24 http://thatsmith.com/2009/03/google-voice-addon-for-firefox/
25 http://posttopic.com/topic/google-voice-add-on-development
28 from __future__ import with_statement
33 from gvoice import gvoice
35 from util import io as io_utils
38 _moduleLogger = logging.getLogger(__name__)
41 class GVDialer(object):
43 MESSAGE_TEXTS = "Text"
44 MESSAGE_VOICEMAILS = "Voicemail"
47 def __init__(self, cookieFile = None):
48 self._gvoice = gvoice.GVoiceBackend(cookieFile)
52 def is_quick_login_possible(self):
54 @returns True then refresh_account_info might be enough to login, else full login is required
56 return self._gvoice.is_quick_login_possible()
58 def refresh_account_info(self):
59 return self._gvoice.refresh_account_info()
61 def login(self, username, password):
63 Attempt to login to GoogleVoice
64 @returns Whether login was successful or not
66 return self._gvoice.login(username, password)
69 return self._gvoice.logout()
72 return self._gvoice.persist()
75 return self._gvoice.is_dnd()
77 def set_dnd(self, doNotDisturb):
78 return self._gvoice.set_dnd(doNotDisturb)
80 def call(self, outgoingNumber):
82 This is the main function responsible for initating the callback
84 return self._gvoice.call(outgoingNumber)
86 def cancel(self, outgoingNumber=None):
88 Cancels a call matching outgoing and forwarding numbers (if given).
89 Will raise an error if no matching call is being placed
91 return self._gvoice.cancel(outgoingNumber)
93 def send_sms(self, phoneNumbers, message):
94 self._gvoice.send_sms(phoneNumbers, message)
96 def search(self, query):
98 Search your Google Voice Account history for calls, voicemails, and sms
99 Returns ``Folder`` instance containting matching messages
101 return self._gvoice.search(query)
103 def get_feed(self, feed):
104 return self._gvoice.get_feed(feed)
106 def download(self, messageId, adir):
108 Download a voicemail or recorded call MP3 matching the given ``msg``
109 which can either be a ``Message`` instance, or a SHA1 identifier.
110 Saves files to ``adir`` (defaults to current directory).
111 Message hashes can be found in ``self.voicemail().messages`` for example.
112 Returns location of saved file.
114 return self._gvoice.download(messageId, adir)
116 def is_valid_syntax(self, number):
118 @returns If This number be called ( syntax validation only )
120 return self._gvoice.is_valid_syntax(number)
122 def get_account_number(self):
124 @returns The GoogleVoice phone number
126 return self._gvoice.get_account_number()
128 def get_callback_numbers(self):
130 @returns a dictionary mapping call back numbers to descriptions
131 @note These results are cached for 30 minutes.
133 return self._gvoice.get_callback_numbers()
135 def set_callback_number(self, callbacknumber):
137 Set the number that GoogleVoice calls
138 @param callbacknumber should be a proper 10 digit number
140 return self._gvoice.set_callback_number(callbacknumber)
142 def get_callback_number(self):
144 @returns Current callback number or None
146 return self._gvoice.get_callback_number()
148 def get_recent(self):
150 @returns Iterable of (personsName, phoneNumber, exact date, relative date, action)
152 return list(self._gvoice.get_recent())
154 def get_messages(self, messageType):
155 messages = list(self._get_messages(messageType))
156 messages.sort(key=lambda message: message["time"])
159 def _get_messages(self, messageType):
160 if messageType in [self.MESSAGE_VOICEMAILS, self.MESSAGE_ALL] or not self._voicemails:
161 self._voicemails = list(self._gvoice.get_voicemails())
162 voicemails = self._voicemails
163 if messageType in [self.MESSAGE_TEXTS, self.MESSAGE_ALL] or not self._texts:
164 self._texts = list(self._gvoice.get_texts())
167 conversations = itertools.chain(voicemails, smss)
168 for conversation in conversations:
169 messages = conversation.messages
171 (message.whoFrom, self._format_message(message), message.when)
172 for message in messages
176 "id": conversation.id,
177 "contactId": conversation.contactId,
178 "name": conversation.name,
179 "time": conversation.time,
180 "relTime": conversation.relTime,
181 "prettyNumber": conversation.prettyNumber,
182 "number": conversation.number,
183 "location": conversation.location,
184 "messageParts": messageParts,
185 "type": conversation.type,
186 "isRead": conversation.isRead,
187 "isTrash": conversation.isTrash,
188 "isSpam": conversation.isSpam,
189 "isArchived": conversation.isArchived,
193 def clear_caches(self):
196 def get_addressbooks(self):
198 @returns Iterable of (Address Book Factory, Book Id, Book Name)
202 def open_addressbook(self, bookId):
206 def contact_source_short_name(contactId):
211 return "Google Voice"
213 def _format_message(self, message):
214 messagePartFormat = {
220 messagePartFormat[text.accuracy] % io_utils.escape(text.text)
221 for text in message.body
225 def sort_messages(allMessages):
226 sortableAllMessages = [
227 (message["time"], message)
228 for message in allMessages
230 sortableAllMessages.sort(reverse=True)
233 for (exactTime, message) in sortableAllMessages
237 def decorate_recent(recentCallData):
239 @returns (personsName, phoneNumber, date, action)
241 contactId = recentCallData["contactId"]
242 if recentCallData["name"]:
243 header = recentCallData["name"]
244 elif recentCallData["prettyNumber"]:
245 header = recentCallData["prettyNumber"]
246 elif recentCallData["location"]:
247 header = recentCallData["location"]
251 number = recentCallData["number"]
252 relTime = recentCallData["relTime"]
253 action = recentCallData["action"]
254 return contactId, header, number, relTime, action
257 def decorate_message(messageData):
258 contactId = messageData["contactId"]
259 exactTime = messageData["time"]
260 if messageData["name"]:
261 header = messageData["name"]
262 elif messageData["prettyNumber"]:
263 header = messageData["prettyNumber"]
266 number = messageData["number"]
267 relativeTime = messageData["relTime"]
269 messageParts = list(messageData["messageParts"])
270 if len(messageParts) == 0:
271 messages = ("No Transcription", )
272 elif len(messageParts) == 1:
273 messages = (messageParts[0][1], )
276 "<b>%s</b>: %s" % (messagePart[0], messagePart[1])
277 for messagePart in messageParts
280 decoratedResults = contactId, header, number, relativeTime, messages
281 return decoratedResults