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
@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):
]
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):
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):
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):
"""
@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)
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: