Various bug fixes and tweaks found through 0, 1, and 2
[gc-dialer] / src / gv_backend.py
index e8a3749..29021c2 100644 (file)
@@ -128,7 +128,7 @@ class GVDialer(object):
                @returns If authenticated
                """
 
-               if (time.time() - self._lastAuthed) < 60 and not force:
+               if (time.time() - self._lastAuthed) < 120 and not force:
                        return True
 
                try:
@@ -275,10 +275,9 @@ class GVDialer(object):
                @returns a dictionary mapping call back numbers to descriptions
                @note These results are cached for 30 minutes.
                """
-               if time.time() - self._lastAuthed < 1800 or self.is_authed():
-                       return self._callbackNumbers
-
-               return {}
+               if not self.is_authed():
+                       return {}
+               return self._callbackNumbers
 
        _setforwardURL = "https://www.google.com//voice/m/setphone"
 
@@ -288,26 +287,28 @@ class GVDialer(object):
                @param callbacknumber should be a proper 10 digit number
                """
                self._callbackNumber = callbacknumber
-               callbackPostData = urllib.urlencode({
-                       '_rnr_se': self._token,
-                       'phone': callbacknumber
-               })
-               try:
-                       callbackSetPage = self._browser.download(self._setforwardURL, callbackPostData)
-               except urllib2.URLError, e:
-                       warnings.warn(traceback.format_exc())
-                       raise RuntimeError("%s is not accesible" % self._setforwardURL)
 
-               self._browser.cookies.save()
+               # 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
+               #for c in self._browser.cookies:
+               #       if c.name == "gv-ph":
+               #               return c.value
                return self._callbackNumber
 
        def get_recent(self):
@@ -372,7 +373,7 @@ class GVDialer(object):
                        for contact in self.__contacts:
                                yield contact
 
-       _contactDetailPhoneRe = re.compile(r"""<div.*?>([0-9\-\(\) \t]+?)<span.*?>\((\w+)\)</span>""", re.S)
+       _contactDetailPhoneRe = re.compile(r"""<div.*?>([0-9+\-\(\) \t]+?)<span.*?>\((\w+)\)</span>""", re.S)
        _contactDetailURL = "https://www.google.com/voice/mobile/contact"
 
        def get_contact_details(self, contactId):
@@ -476,10 +477,10 @@ class GVDialer(object):
                """
                @returns Iterable of (personsName, phoneNumber, exact date, relative date, action)
                """
-               for url in (
-                       self._receivedCallsURL,
-                       self._missedCallsURL,
-                       self._placedCallsURL,
+               for action, url in (
+                       ("Received", self._receivedCallsURL),
+                       ("Missed", self._missedCallsURL),
+                       ("Placed", self._placedCallsURL),
                ):
                        try:
                                flatXml = self._browser.download(url)
@@ -487,30 +488,28 @@ class GVDialer(object):
                                warnings.warn(traceback.format_exc())
                                raise RuntimeError("%s is not accesible" % url)
 
-                       allRecentData = self._grab_json(flatXml)
-                       for recentCallData in allRecentData["messages"].itervalues():
-                               number = recentCallData["displayNumber"]
-                               exactDate = recentCallData["displayStartDateTime"]
-                               relativeDate = recentCallData["relativeStartTime"]
-                               action = ", ".join((
-                                       label.title()
-                                       for label in recentCallData["labels"]
-                                               if label.lower() != "all" and label.lower() != "inbox"
-                               ))
-                               number = saxutils.unescape(number)
-                               exactDate = saxutils.unescape(exactDate)
-                               exactDate = datetime.datetime.strptime(exactDate, "%m/%d/%y %I:%M %p")
-                               relativeDate = saxutils.unescape(relativeDate)
-                               action = saxutils.unescape(action)
-                               yield "", number, exactDate, relativeDate, action
-
-       _seperateVoicemailsRegex = re.compile(r"""^\s*<div id="(\w+)"\s* class="gc-message.*?">""", re.MULTILINE | re.DOTALL)
+                       allRecentHtml = self._grab_html(flatXml)
+                       allRecentData = self._parse_voicemail(allRecentHtml)
+                       for recentCallData in allRecentData:
+                               exactTime = recentCallData["time"]
+                               if recentCallData["name"]:
+                                       header = recentCallData["name"]
+                               elif recentCallData["prettyNumber"]:
+                                       header = recentCallData["prettyNumber"]
+                               elif recentCallData["location"]:
+                                       header = recentCallData["location"]
+                               else:
+                                       header = "Unknown"
+                               yield header, recentCallData["number"], exactTime, recentCallData["relTime"], action
+
+       _seperateVoicemailsRegex = re.compile(r"""^\s*<div id="(\w+)"\s* class=".*?gc-message.*?">""", re.MULTILINE | re.DOTALL)
        _exactVoicemailTimeRegex = re.compile(r"""<span class="gc-message-time">(.*?)</span>""", re.MULTILINE)
        _relativeVoicemailTimeRegex = re.compile(r"""<span class="gc-message-relative">(.*?)</span>""", re.MULTILINE)
+       _voicemailNameRegex = re.compile(r"""<a class=.*?gc-message-name-link.*?>(.*?)</a>""", re.MULTILINE | re.DOTALL)
        _voicemailNumberRegex = re.compile(r"""<input type="hidden" class="gc-text gc-quickcall-ac" value="(.*?)"/>""", re.MULTILINE)
        _prettyVoicemailNumberRegex = re.compile(r"""<span class="gc-message-type">(.*?)</span>""", re.MULTILINE)
        _voicemailLocationRegex = re.compile(r"""<span class="gc-message-location">.*?<a.*?>(.*?)</a></span>""", re.MULTILINE)
-       _voicemailMessageRegex = re.compile(r"""<span class="gc-word-(.*?)">(.*?)</span>""", re.MULTILINE)
+       _voicemailMessageRegex = re.compile(r"""<span id="\d+-\d+" class="gc-word-(.*?)">(.*?)</span>""", re.MULTILINE)
 
        def _parse_voicemail(self, voicemailHtml):
                splitVoicemail = self._seperateVoicemailsRegex.split(voicemailHtml)
@@ -523,6 +522,8 @@ class GVDialer(object):
                        locationGroup = self._voicemailLocationRegex.search(messageHtml)
                        location = locationGroup.group(1).strip() if locationGroup else ""
 
+                       nameGroup = self._voicemailNameRegex.search(messageHtml)
+                       name = nameGroup.group(1).strip() if nameGroup else ""
                        numberGroup = self._voicemailNumberRegex.search(messageHtml)
                        number = numberGroup.group(1).strip() if numberGroup else ""
                        prettyNumberGroup = self._prettyVoicemailNumberRegex.search(messageHtml)
@@ -536,6 +537,7 @@ class GVDialer(object):
 
                        yield {
                                "id": messageId.strip(),
+                               "name": name,
                                "time": exactTime,
                                "relTime": relativeTime,
                                "prettyNumber": prettyNumber,
@@ -552,7 +554,14 @@ class GVDialer(object):
                }
                for voicemailData in parsedVoicemail:
                        exactTime = voicemailData["time"]
-                       header = "%s %s" % (voicemailData["prettyNumber"], voicemailData["location"])
+                       if voicemailData["name"]:
+                               header = voicemailData["name"]
+                       elif voicemailData["prettyNumber"]:
+                               header = voicemailData["prettyNumber"]
+                       elif voicemailData["location"]:
+                               header = voicemailData["location"]
+                       else:
+                               header = "Unknown"
                        message = " ".join((
                                messagePartFormat[quality] % part
                                for (quality, part) in voicemailData["messageParts"]
@@ -574,6 +583,8 @@ class GVDialer(object):
                        relativeTimeGroup = self._relativeVoicemailTimeRegex.search(messageHtml)
                        relativeTime = relativeTimeGroup.group(1).strip() if relativeTimeGroup else ""
 
+                       nameGroup = self._voicemailNameRegex.search(messageHtml)
+                       name = nameGroup.group(1).strip() if nameGroup else ""
                        numberGroup = self._voicemailNumberRegex.search(messageHtml)
                        number = numberGroup.group(1).strip() if numberGroup else ""
                        prettyNumberGroup = self._prettyVoicemailNumberRegex.search(messageHtml)
@@ -590,6 +601,7 @@ class GVDialer(object):
 
                        yield {
                                "id": messageId.strip(),
+                               "name": name,
                                "time": exactTime,
                                "relTime": relativeTime,
                                "prettyNumber": prettyNumber,
@@ -600,11 +612,16 @@ class GVDialer(object):
        def _decorate_sms(self, parsedSms):
                for messageData in parsedSms:
                        exactTime = messageData["time"]
-                       header = "%s" % (messageData["prettyNumber"])
+                       if messageData["name"]:
+                               header = messageData["name"]
+                       elif messageData["prettyNumber"]:
+                               header = messageData["prettyNumber"]
+                       else:
+                               header = "Unknown"
                        number = messageData["number"]
                        relativeTime = messageData["relTime"]
                        message = "\n".join((
-                               "<b>%s (%s)</b>: %s" % messagePart
+                               "<b>%s</b>: %s" % (messagePart[0], messagePart[-1])
                                for messagePart in messageData["messageParts"]
                        ))
                        if not message: