@returns If authenticated
"""
- if (time.time() - self._lastAuthed) < 60 and not force:
+ if (time.time() - self._lastAuthed) < 120 and not force:
return True
try:
@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"
@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):
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):
"""
@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)
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)
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)
yield {
"id": messageId.strip(),
+ "name": name,
"time": exactTime,
"relTime": relativeTime,
"prettyNumber": prettyNumber,
}
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"]
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)
yield {
"id": messageId.strip(),
+ "name": name,
"time": exactTime,
"relTime": relativeTime,
"prettyNumber": prettyNumber,
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: