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 def __init__(self, cookieFile = None):
44 self._gvoice = gvoice.GVoiceBackend(cookieFile)
46 def is_quick_login_possible(self):
48 @returns True then refresh_account_info might be enough to login, else full login is required
50 return self._gvoice.is_quick_login_possible()
52 def refresh_account_info(self):
53 return self._gvoice.refresh_account_info()
55 def login(self, username, password):
57 Attempt to login to GoogleVoice
58 @returns Whether login was successful or not
60 return self._gvoice.login(username, password)
63 return self._gvoice.logout()
66 return self._gvoice.persist()
69 return self._gvoice.is_dnd()
71 def set_dnd(self, doNotDisturb):
72 return self._gvoice.set_dnd(doNotDisturb)
74 def call(self, outgoingNumber):
76 This is the main function responsible for initating the callback
78 return self._gvoice.call(outgoingNumber)
80 def cancel(self, outgoingNumber=None):
82 Cancels a call matching outgoing and forwarding numbers (if given).
83 Will raise an error if no matching call is being placed
85 return self._gvoice.cancel(outgoingNumber)
87 def send_sms(self, phoneNumbers, message):
88 self._gvoice.send_sms(phoneNumbers, message)
90 def search(self, query):
92 Search your Google Voice Account history for calls, voicemails, and sms
93 Returns ``Folder`` instance containting matching messages
95 return self._gvoice.search(query)
97 def get_feed(self, feed):
98 return self._gvoice.get_feed(feed)
100 def download(self, messageId, adir):
102 Download a voicemail or recorded call MP3 matching the given ``msg``
103 which can either be a ``Message`` instance, or a SHA1 identifier.
104 Saves files to ``adir`` (defaults to current directory).
105 Message hashes can be found in ``self.voicemail().messages`` for example.
106 Returns location of saved file.
108 return self._gvoice.download(messageId, adir)
110 def is_valid_syntax(self, number):
112 @returns If This number be called ( syntax validation only )
114 return self._gvoice.is_valid_syntax(number)
116 def get_account_number(self):
118 @returns The GoogleVoice phone number
120 return self._gvoice.get_account_number()
122 def get_callback_numbers(self):
124 @returns a dictionary mapping call back numbers to descriptions
125 @note These results are cached for 30 minutes.
127 return self._gvoice.get_callback_numbers()
129 def set_callback_number(self, callbacknumber):
131 Set the number that GoogleVoice calls
132 @param callbacknumber should be a proper 10 digit number
134 return self._gvoice.set_callback_number(callbacknumber)
136 def get_callback_number(self):
138 @returns Current callback number or None
140 return self._gvoice.get_callback_number()
142 def get_recent(self):
144 @returns Iterable of (personsName, phoneNumber, exact date, relative date, action)
146 return list(self._gvoice.get_recent())
148 def get_contacts(self):
150 @returns Fresh dictionary of items
152 return dict(self._gvoice.get_contacts())
154 def get_messages(self):
155 return list(self._get_messages())
157 def _get_messages(self):
158 voicemails = self._gvoice.get_voicemails()
159 smss = self._gvoice.get_texts()
160 conversations = itertools.chain(voicemails, smss)
161 for conversation in conversations:
162 messages = conversation.messages
164 (message.whoFrom, self._format_message(message), message.when)
165 for message in messages
169 "id": conversation.id,
170 "contactId": conversation.contactId,
171 "name": conversation.name,
172 "time": conversation.time,
173 "relTime": conversation.relTime,
174 "prettyNumber": conversation.prettyNumber,
175 "number": conversation.number,
176 "location": conversation.location,
177 "messageParts": messageParts,
178 "type": conversation.type,
179 "isRead": conversation.isRead,
180 "isTrash": conversation.isTrash,
181 "isSpam": conversation.isSpam,
182 "isArchived": conversation.isArchived,
186 def clear_caches(self):
189 def get_addressbooks(self):
191 @returns Iterable of (Address Book Factory, Book Id, Book Name)
195 def open_addressbook(self, bookId):
199 def contact_source_short_name(contactId):
204 return "Google Voice"
206 def _format_message(self, message):
207 messagePartFormat = {
213 messagePartFormat[text.accuracy] % io_utils.escape(text.text)
214 for text in message.body
218 def sort_messages(allMessages):
219 sortableAllMessages = [
220 (message["time"], message)
221 for message in allMessages
223 sortableAllMessages.sort(reverse=True)
226 for (exactTime, message) in sortableAllMessages
230 def decorate_recent(recentCallData):
232 @returns (personsName, phoneNumber, date, action)
234 contactId = recentCallData["contactId"]
235 if recentCallData["name"]:
236 header = recentCallData["name"]
237 elif recentCallData["prettyNumber"]:
238 header = recentCallData["prettyNumber"]
239 elif recentCallData["location"]:
240 header = recentCallData["location"]
244 number = recentCallData["number"]
245 relTime = recentCallData["relTime"]
246 action = recentCallData["action"]
247 return contactId, header, number, relTime, action
250 def decorate_message(messageData):
251 contactId = messageData["contactId"]
252 exactTime = messageData["time"]
253 if messageData["name"]:
254 header = messageData["name"]
255 elif messageData["prettyNumber"]:
256 header = messageData["prettyNumber"]
259 number = messageData["number"]
260 relativeTime = messageData["relTime"]
262 messageParts = list(messageData["messageParts"])
263 if len(messageParts) == 0:
264 messages = ("No Transcription", )
265 elif len(messageParts) == 1:
266 messages = (messageParts[0][1], )
269 "<b>%s</b>: %s" % (messagePart[0], messagePart[1])
270 for messagePart in messageParts
273 decoratedResults = contactId, header, number, relativeTime, messages
274 return decoratedResults