X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;ds=sidebyside;f=src%2Fgv_backend.py;h=4d6e19c54ef959f01c5e9f5e9d70d88534d2f776;hb=f40854ec9cdac528f81ca2414d202d980cd486df;hp=0b1ca4bbad825e674842d546c1422ca06079cf44;hpb=9592bec02d9e78fd538a2300dbb0e625b5d32726;p=gc-dialer diff --git a/src/gv_backend.py b/src/gv_backend.py index 0b1ca4b..4d6e19c 100644 --- a/src/gv_backend.py +++ b/src/gv_backend.py @@ -1,7 +1,7 @@ #!/usr/bin/python """ -DialCentral - Front end for Google's Grand Central service. +DialCentral - Front end for Google's GoogleVoice service. Copyright (C) 2008 Eric Warnke ericew AT gmail DOT com This library is free software; you can redistribute it and/or @@ -33,8 +33,7 @@ import urllib2 import time import datetime import itertools -import warnings -import traceback +import logging from xml.sax import saxutils from xml.etree import ElementTree @@ -47,6 +46,7 @@ except ImportError: simplejson = None +_moduleLogger = logging.getLogger("gv_backend") _TRUE_REGEX = re.compile("true") _FALSE_REGEX = re.compile("false") @@ -98,22 +98,9 @@ def itergroup(iterator, count, padValue = None): return itertools.izip(*nIterators) -def abbrev_relative_date(date): - """ - >>> abbrev_relative_date("42 hours ago") - '42 h' - >>> abbrev_relative_date("2 days ago") - '2 d' - >>> abbrev_relative_date("4 weeks ago") - '4 w' - """ - parts = date.split(" ") - return "%s %s" % (parts[0], parts[1][0]) - - class GVDialer(object): """ - This class encapsulates all of the knowledge necessary to interace with the grandcentral servers + This class encapsulates all of the knowledge necessary to interact with the GoogleVoice servers the functions include login, setting up a callback number, and initalting a callback """ @@ -146,8 +133,8 @@ class GVDialer(object): try: self._grab_account_info() - except StandardError, e: - warnings.warn(traceback.format_exc()) + except Exception, e: + _moduleLogger.exception(str(e)) return False self._browser.cookies.save() @@ -158,7 +145,7 @@ class GVDialer(object): def login(self, username, password): """ - Attempt to login to grandcentral + Attempt to login to GoogleVoice @returns Whether login was successful or not """ if self.is_authed(): @@ -176,7 +163,7 @@ class GVDialer(object): try: loginSuccessOrFailurePage = self._browser.download(self._loginURL, loginPostData) except urllib2.URLError, e: - warnings.warn(traceback.format_exc()) + _moduleLogger.exception(str(e)) raise RuntimeError("%s is not accesible" % self._loginURL) return self.is_authed() @@ -207,7 +194,7 @@ class GVDialer(object): } callSuccessPage = self._browser.download(self._clicktocallURL, clickToCallData, None, otherData) except urllib2.URLError, e: - warnings.warn(traceback.format_exc()) + _moduleLogger.exception(str(e)) raise RuntimeError("%s is not accesible" % self._clicktocallURL) if self._gvDialingStrRe.search(callSuccessPage) is None: @@ -232,7 +219,7 @@ class GVDialer(object): } smsSuccessPage = self._browser.download(self._sendSmsURL, smsData, None, otherData) except urllib2.URLError, e: - warnings.warn(traceback.format_exc()) + _moduleLogger.exception(str(e)) raise RuntimeError("%s is not accesible" % self._sendSmsURL) return True @@ -250,7 +237,7 @@ class GVDialer(object): def get_account_number(self): """ - @returns The grand central phone number + @returns The GoogleVoice phone number """ return self._accountNum @@ -296,32 +283,16 @@ class GVDialer(object): def set_callback_number(self, callbacknumber): """ - Set the number that grandcental calls + Set the number that GoogleVoice calls @param callbacknumber should be a proper 10 digit number """ self._callbackNumber = callbacknumber - - # Currently this isn't working out in GoogleVoice, but thats ok, we pass the callback on dial - #callbackPostData = urllib.urlencode({ - # '_rnr_se': self._token, - # 'phone': callbacknumber - #}) - #try: - # callbackSetPage = self._browser.download(self._setforwardURL, callbackPostData) - # self._browser.cookies.save() - #except urllib2.URLError, e: - # warnings.warn(traceback.format_exc()) - # raise RuntimeError("%s is not accesible" % self._setforwardURL) - return True def get_callback_number(self): """ @returns Current callback number or None """ - #for c in self._browser.cookies: - # if c.name == "gv-ph": - # return c.value return self._callbackNumber def get_recent(self): @@ -334,7 +305,6 @@ class GVDialer(object): ] sortedRecent.sort(reverse = True) for exactDate, name, number, relativeDate, action in sortedRecent: - relativeDate = abbrev_relative_date(relativeDate) yield name, number, relativeDate, action def get_addressbooks(self): @@ -370,7 +340,7 @@ class GVDialer(object): try: contactsPage = self._browser.download(contactsPageUrl) except urllib2.URLError, e: - warnings.warn(traceback.format_exc()) + _moduleLogger.exception(str(e)) raise RuntimeError("%s is not accesible" % contactsPageUrl) for contact_match in self._contactsRe.finditer(contactsPage): contactId = contact_match.group(1) @@ -397,7 +367,7 @@ class GVDialer(object): try: detailPage = self._browser.download(self._contactDetailURL + '/' + contactId) except urllib2.URLError, e: - warnings.warn(traceback.format_exc()) + _moduleLogger.exception(str(e)) raise RuntimeError("%s is not accesible" % self._contactDetailURL) for detail_match in self._contactDetailPhoneRe.finditer(detailPage): @@ -412,7 +382,7 @@ class GVDialer(object): try: voicemailPage = self._browser.download(self._voicemailURL) except urllib2.URLError, e: - warnings.warn(traceback.format_exc()) + _moduleLogger.exception(str(e)) raise RuntimeError("%s is not accesible" % self._voicemailURL) voicemailHtml = self._grab_html(voicemailPage) parsedVoicemail = self._parse_voicemail(voicemailHtml) @@ -421,7 +391,7 @@ class GVDialer(object): try: smsPage = self._browser.download(self._smsURL) except urllib2.URLError, e: - warnings.warn(traceback.format_exc()) + _moduleLogger.exception(str(e)) raise RuntimeError("%s is not accesible" % self._smsURL) smsHtml = self._grab_html(smsPage) parsedSms = self._parse_sms(smsHtml) @@ -431,7 +401,6 @@ class GVDialer(object): sortedMessages = list(allMessages) sortedMessages.sort(reverse=True) for exactDate, header, number, relativeDate, message in sortedMessages: - relativeDate = abbrev_relative_date(relativeDate) yield header, number, relativeDate, message def _grab_json(self, flatXml): @@ -464,7 +433,7 @@ class GVDialer(object): if anGroup is not None: self._accountNum = anGroup.group(1) else: - warnings.warn("Could not extract account number from GoogleVoice", UserWarning, 2) + _moduleLogger.debug("Could not extract account number from GoogleVoice") self._callbackNumbers = {} for match in self._callbackRe.finditer(page): @@ -493,14 +462,14 @@ class GVDialer(object): @returns Iterable of (personsName, phoneNumber, exact date, relative date, action) """ for action, url in ( - ("Recieved", self._receivedCallsURL), + ("Received", self._receivedCallsURL), ("Missed", self._missedCallsURL), ("Placed", self._placedCallsURL), ): try: flatXml = self._browser.download(url) except urllib2.URLError, e: - warnings.warn(traceback.format_exc()) + _moduleLogger.exception(str(e)) raise RuntimeError("%s is not accesible" % url) allRecentHtml = self._grab_html(flatXml) @@ -517,14 +486,24 @@ class GVDialer(object): header = "Unknown" yield header, recentCallData["number"], exactTime, recentCallData["relTime"], action - _seperateVoicemailsRegex = re.compile(r"""^\s*
""", re.MULTILINE | re.DOTALL) + _seperateVoicemailsRegex = re.compile(r"""^\s*
""", re.MULTILINE | re.DOTALL) _exactVoicemailTimeRegex = re.compile(r"""(.*?)""", re.MULTILINE) _relativeVoicemailTimeRegex = re.compile(r"""(.*?)""", re.MULTILINE) _voicemailNameRegex = re.compile(r"""(.*?)""", re.MULTILINE | re.DOTALL) _voicemailNumberRegex = re.compile(r"""""", re.MULTILINE) _prettyVoicemailNumberRegex = re.compile(r"""(.*?)""", re.MULTILINE) _voicemailLocationRegex = re.compile(r""".*?(.*?)""", re.MULTILINE) - _voicemailMessageRegex = re.compile(r"""(.*?)""", re.MULTILINE) + #_voicemailMessageRegex = re.compile(r"""(.*?)""", re.MULTILINE) + #_voicemailMessageRegex = re.compile(r"""(.*?)""", re.MULTILINE) + _voicemailMessageRegex = re.compile(r"""((.*?)|(.*?))""", re.MULTILINE) + + @staticmethod + def _interpret_voicemail_regex(group): + quality, content, number = group.group(2), group.group(3), group.group(4) + if quality is not None and content is not None: + return quality, content + elif number is not None: + return "high", number def _parse_voicemail(self, voicemailHtml): splitVoicemail = self._seperateVoicemailsRegex.split(voicemailHtml) @@ -546,7 +525,7 @@ class GVDialer(object): messageGroups = self._voicemailMessageRegex.finditer(messageHtml) messageParts = ( - (group.group(1).strip(), group.group(2).strip()) + self._interpret_voicemail_regex(group) for group in messageGroups ) if messageGroups else () @@ -583,7 +562,7 @@ class GVDialer(object): )).strip() if not message: message = "No Transcription" - yield exactTime, header, voicemailData["number"], voicemailData["relTime"], message + yield exactTime, header, voicemailData["number"], voicemailData["relTime"], (message, ) _smsFromRegex = re.compile(r"""(.*?)""", re.MULTILINE | re.DOTALL) _smsTextRegex = re.compile(r"""(.*?)""", re.MULTILINE | re.DOTALL) @@ -635,17 +614,16 @@ class GVDialer(object): header = "Unknown" number = messageData["number"] relativeTime = messageData["relTime"] - message = "\n".join(( + messages = [ "%s: %s" % (messagePart[0], messagePart[-1]) for messagePart in messageData["messageParts"] - )) - if not message: - message = "No Transcription" - yield exactTime, header, number, relativeTime, message + ] + if not messages: + messages = ("No Transcription", ) + yield exactTime, header, number, relativeTime, messages def test_backend(username, password): - import pprint backend = GVDialer() print "Authenticated: ", backend.is_authed() print "Login?: ", backend.login(username, password) @@ -654,6 +632,7 @@ def test_backend(username, password): print "Account: ", backend.get_account_number() print "Callback: ", backend.get_callback_number() # print "All Callback: ", + import pprint # pprint.pprint(backend.get_callback_numbers()) # print "Recent: ", # pprint.pprint(list(backend.get_recent())) @@ -661,5 +640,7 @@ def test_backend(username, password): # for contact in backend.get_contacts(): # print contact # pprint.pprint(list(backend.get_contact_details(contact[0]))) + for message in backend.get_messages(): + pprint.pprint(message) return backend