SECURE_URL_BASE = "https://www.google.com/voice/"
SECURE_MOBILE_URL_BASE = SECURE_URL_BASE + "mobile/"
- self._forwardURL = SECURE_MOBILE_URL_BASE + "phones"
self._tokenURL = SECURE_URL_BASE + "m"
self._callUrl = SECURE_URL_BASE + "call/connect"
self._callCancelURL = SECURE_URL_BASE + "call/cancel"
self._XML_MISSED_URL = SECURE_URL_BASE + "inbox/recent/missed/"
self._galxRe = re.compile(r"""<input.*?name="GALX".*?value="(.*?)".*?/>""", re.MULTILINE | re.DOTALL)
- self._tokenRe = re.compile(r"""<input.*?name="_rnr_se".*?value="(.*?)"\s*/>""")
- self._accountNumRe = re.compile(r"""<b class="ms\d">(.{14})</b></div>""")
- self._callbackRe = re.compile(r"""\s+(.*?):\s*(.*?)<br\s*/>\s*$""", re.M)
self._seperateVoicemailsRegex = re.compile(r"""^\s*<div id="(\w+)"\s* class=".*?gc-message.*?">""", re.MULTILINE | re.DOTALL)
self._exactVoicemailTimeRegex = re.compile(r"""<span class="gc-message-time">(.*?)</span>""", re.MULTILINE)
def is_quick_login_possible(self):
"""
- @returns True then is_authed might be enough to login, else full login is required
+ @returns True then refresh_account_info might be enough to login, else full login is required
"""
return self._loadedFromCookies or 0.0 < self._lastAuthed
- def is_authed(self, force = False):
- """
- Attempts to detect a current session
- @note Once logged in try not to reauth more than once a minute.
- @returns If authenticated
- @blocks
- """
- isRecentledAuthed = (time.time() - self._lastAuthed) < 120
- isPreviouslyAuthed = self._token is not None
- if isRecentledAuthed and isPreviouslyAuthed and not force:
- return True
-
+ def refresh_account_info(self):
try:
- page = self._get_page(self._forwardURL)
- self._grab_account_info(page)
+ page = self._get_page(self._JSON_CONTACTS_URL)
+ accountData = self._grab_account_info(page)
except Exception, e:
_moduleLogger.exception(str(e))
- return False
+ return None
self._browser.save_cookies()
self._lastAuthed = time.time()
- return True
+ return accountData
def _get_token(self):
tokenPage = self._get_page(self._tokenURL)
"btmpl": "mobile",
"PersistentCookie": "yes",
"GALX": token,
- "continue": self._forwardURL,
+ "continue": self._JSON_CONTACTS_URL,
}
loginSuccessOrFailurePage = self._get_page(self._loginURL, loginData)
loginSuccessOrFailurePage = self._login(username, password, galxToken)
try:
- self._grab_account_info(loginSuccessOrFailurePage)
+ accountData = self._grab_account_info(loginSuccessOrFailurePage)
except Exception, e:
# Retry in case the redirect failed
- # luckily is_authed does everything we need for a retry
- loggedIn = self.is_authed(True)
- if not loggedIn:
+ # luckily refresh_account_info does everything we need for a retry
+ accountData = self.refresh_account_info()
+ if accountData is None:
_moduleLogger.exception(str(e))
- return False
+ return None
_moduleLogger.info("Redirection failed on initial login attempt, auto-corrected for this")
self._browser.save_cookies()
self._lastAuthed = time.time()
- return True
+ return accountData
def persist(self):
self._browser.save_cookies()
return flatHtml
def _grab_account_info(self, page):
- tokenGroup = self._tokenRe.search(page)
- if tokenGroup is None:
- raise RuntimeError("Could not extract authentication token from GoogleVoice")
- self._token = tokenGroup.group(1)
-
- anGroup = self._accountNumRe.search(page)
- if anGroup is not None:
- self._accountNum = anGroup.group(1)
- else:
- _moduleLogger.debug("Could not extract account number from GoogleVoice")
-
- self._callbackNumbers = {}
- for match in self._callbackRe.finditer(page):
- callbackNumber = match.group(2)
- callbackName = match.group(1)
- self._callbackNumbers[callbackNumber] = callbackName
+ accountData = parse_json(page)
+ self._token = accountData["r"]
+ self._accountNum = accountData["number"]["raw"]
+ for callback in accountData["phones"].itervalues():
+ self._callbackNumbers[callback["phoneNumber"]] = callback["name"]
if len(self._callbackNumbers) == 0:
_moduleLogger.debug("Could not extract callback numbers from GoogleVoice (the troublesome page follows):\n%s" % page)
+ return accountData
def _send_validation(self, number):
if not self.is_valid_syntax(number):
raise ValueError('Number is not valid: "%s"' % number)
- elif not self.is_authed():
- raise RuntimeError("Not Authenticated")
return number
def _parse_recent(self, recentPages):
browser = backend._browser
_TEST_WEBPAGES = [
- ("forward", backend._forwardURL),
("token", backend._tokenURL),
("login", backend._loginURL),
("isdnd", backend._isDndURL),
backend._grab_account_info(loginSuccessOrFailurePage)
except Exception:
# Retry in case the redirect failed
- # luckily is_authed does everything we need for a retry
- loggedIn = backend.is_authed(True)
+ # luckily refresh_account_info does everything we need for a retry
+ loggedIn = backend.refresh_account_info() is not None
if not loggedIn:
raise