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 is_authed might be enough to login, else full login is required
50 return self._gvoice.is_quick_login_possible()
52 def is_authed(self, force = False):
54 Attempts to detect a current session
55 @note Once logged in try not to reauth more than once a minute.
56 @returns If authenticated
58 return self._gvoice.is_authed(force)
60 def login(self, username, password):
62 Attempt to login to GoogleVoice
63 @returns Whether login was successful or not
65 return self._gvoice.login(username, password)
68 return self._gvoice.logout()
71 return self._gvoice.persist()
74 return self._gvoice.is_dnd()
76 def set_dnd(self, doNotDisturb):
77 return self._gvoice.set_dnd(doNotDisturb)
79 def call(self, outgoingNumber):
81 This is the main function responsible for initating the callback
83 return self._gvoice.call(outgoingNumber)
85 def cancel(self, outgoingNumber=None):
87 Cancels a call matching outgoing and forwarding numbers (if given).
88 Will raise an error if no matching call is being placed
90 return self._gvoice.cancel(outgoingNumber)
92 def send_sms(self, phoneNumbers, message):
93 self._gvoice.send_sms(phoneNumbers, message)
95 def search(self, query):
97 Search your Google Voice Account history for calls, voicemails, and sms
98 Returns ``Folder`` instance containting matching messages
100 return self._gvoice.search(query)
102 def get_feed(self, feed):
103 return self._gvoice.get_feed(feed)
105 def download(self, messageId, adir):
107 Download a voicemail or recorded call MP3 matching the given ``msg``
108 which can either be a ``Message`` instance, or a SHA1 identifier.
109 Saves files to ``adir`` (defaults to current directory).
110 Message hashes can be found in ``self.voicemail().messages`` for example.
111 Returns location of saved file.
113 return self._gvoice.download(messageId, adir)
115 def is_valid_syntax(self, number):
117 @returns If This number be called ( syntax validation only )
119 return self._gvoice.is_valid_syntax(number)
121 def get_account_number(self):
123 @returns The GoogleVoice phone number
125 return self._gvoice.get_account_number()
127 def get_callback_numbers(self):
129 @returns a dictionary mapping call back numbers to descriptions
130 @note These results are cached for 30 minutes.
132 return self._gvoice.get_callback_numbers()
134 def set_callback_number(self, callbacknumber):
136 Set the number that GoogleVoice calls
137 @param callbacknumber should be a proper 10 digit number
139 return self._gvoice.set_callback_number(callbacknumber)
141 def get_callback_number(self):
143 @returns Current callback number or None
145 return self._gvoice.get_callback_number()
147 def get_recent(self):
149 @returns Iterable of (personsName, phoneNumber, exact date, relative date, action)
151 return list(self._gvoice.get_recent())
153 def get_contacts(self):
155 @returns Fresh dictionary of items
157 return dict(self._gvoice.get_contacts())
159 def get_messages(self):
160 return list(self._get_messages())
162 def _get_messages(self):
163 voicemails = self._gvoice.get_voicemails()
164 smss = self._gvoice.get_texts()
165 conversations = itertools.chain(voicemails, smss)
166 for conversation in conversations:
167 messages = conversation.messages
169 (message.whoFrom, self._format_message(message), message.when)
170 for message in messages
174 "id": conversation.id,
175 "contactId": conversation.contactId,
176 "name": conversation.name,
177 "time": conversation.time,
178 "relTime": conversation.relTime,
179 "prettyNumber": conversation.prettyNumber,
180 "number": conversation.number,
181 "location": conversation.location,
182 "messageParts": messageParts,
183 "type": conversation.type,
184 "isRead": conversation.isRead,
185 "isTrash": conversation.isTrash,
186 "isSpam": conversation.isSpam,
187 "isArchived": conversation.isArchived,
191 def clear_caches(self):
194 def get_addressbooks(self):
196 @returns Iterable of (Address Book Factory, Book Id, Book Name)
200 def open_addressbook(self, bookId):
204 def contact_source_short_name(contactId):
209 return "Google Voice"
211 def _format_message(self, message):
212 messagePartFormat = {
218 messagePartFormat[text.accuracy] % io_utils.escape(text.text)
219 for text in message.body
223 def sort_messages(allMessages):
224 sortableAllMessages = [
225 (message["time"], message)
226 for message in allMessages
228 sortableAllMessages.sort(reverse=True)
231 for (exactTime, message) in sortableAllMessages
235 def decorate_recent(recentCallData):
237 @returns (personsName, phoneNumber, date, action)
239 contactId = recentCallData["contactId"]
240 if recentCallData["name"]:
241 header = recentCallData["name"]
242 elif recentCallData["prettyNumber"]:
243 header = recentCallData["prettyNumber"]
244 elif recentCallData["location"]:
245 header = recentCallData["location"]
249 number = recentCallData["number"]
250 relTime = recentCallData["relTime"]
251 action = recentCallData["action"]
252 return contactId, header, number, relTime, action
255 def decorate_message(messageData):
256 contactId = messageData["contactId"]
257 exactTime = messageData["time"]
258 if messageData["name"]:
259 header = messageData["name"]
260 elif messageData["prettyNumber"]:
261 header = messageData["prettyNumber"]
264 number = messageData["number"]
265 relativeTime = messageData["relTime"]
267 messageParts = list(messageData["messageParts"])
268 if len(messageParts) == 0:
269 messages = ("No Transcription", )
270 elif len(messageParts) == 1:
271 messages = (messageParts[0][1], )
274 "<b>%s</b>: %s" % (messagePart[0], messagePart[1])
275 for messagePart in messageParts
278 decoratedResults = contactId, header, number, relativeTime, messages
279 return decoratedResults