X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=src%2Fgc_backend.py;h=e1573db59b793f8914d4ecb3e4bf2f52534f96c7;hb=800d975c587d923407147ff9cf5edf3565591b34;hp=c6007134eaed77593773c0d300e08db87d2be690;hpb=97958f9f40a578befa452f4d1769d752693a72e6;p=gc-dialer diff --git a/src/gc_backend.py b/src/gc_backend.py index c600713..e1573db 100644 --- a/src/gc_backend.py +++ b/src/gc_backend.py @@ -1,6 +1,6 @@ #!/usr/bin/python -# GC Dialer - Front end for Google's Grand Central service. +# DialCentral - Front end for Google's Grand Central service. # Copyright (C) 2008 Eric Warnke ericew AT gmail DOT com # # This library is free software; you can redistribute it and/or @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """ -Grandcentral Dialer backend code +Grandcentral backend code """ @@ -31,6 +31,11 @@ import warnings from browser_emu import MozillaEmulator +import socket + + +socket.setdefaulttimeout(5) + class GCDialer(object): """ @@ -46,8 +51,7 @@ class GCDialer(object): _inboxRe = re.compile(r""".*?(voicemail|received|missed|call return).*?\s+\s+\s+(.*?)\s+ \| \s+(.*?)\s?\s+
\s+(.*?)\s?(.*?)""", re.S) _contactsNextRe = re.compile(r""".*Next""", re.S) - _contactDetailGroupRe = re.compile(r"""Group:\s*(\w*)""", re.S) - _contactDetailPhoneRe = re.compile(r"""(\w+):[0-9\-\(\) \t]*?call""", re.S) + _contactDetailPhoneRe = re.compile(r"""(\w+):[0-9\-\(\) \t]*?call""", re.S) _validateRe = re.compile("^[0-9]{10,}$") @@ -61,11 +65,9 @@ class GCDialer(object): def __init__(self, cookieFile = None): # Important items in this function are the setup of the browser emulation and cookie file - self._msg = "" - self._browser = MozillaEmulator(None, 0) if cookieFile is None: - cookieFile = os.path.join(os.path.expanduser("~"), ".gc_dialer_cookies.txt") + cookieFile = os.path.join(os.path.expanduser("~"), ".gc_cookies.txt") self._browser.cookies.filename = cookieFile if os.path.isfile(cookieFile): self._browser.cookies.load() @@ -75,6 +77,8 @@ class GCDialer(object): self._callbackNumbers = {} self._lastAuthed = 0.0 + self.__contacts = None + def is_authed(self, force = False): """ Attempts to detect a current session and pull the auth token ( a_t ) from the page. @@ -82,14 +86,13 @@ class GCDialer(object): @returns If authenticated """ - if time.time() - self._lastAuthed < 60 and not force: + if (time.time() - self._lastAuthed) < 60 and not force: return True try: forwardSelectionPage = self._browser.download(GCDialer._forwardselectURL) except urllib2.URLError, e: - warnings.warn("%s is not accesible" % GCDialer._forwardselectURL, UserWarning, 2) - return False + raise RuntimeError("%s is not accesible" % GCDialer._forwardselectURL) self._browser.cookies.save() if GCDialer._isLoginPageRe.search(forwardSelectionPage) is None: @@ -112,8 +115,7 @@ class GCDialer(object): try: loginSuccessOrFailurePage = self._browser.download(GCDialer._loginURL, loginPostData) except urllib2.URLError, e: - warnings.warn("%s is not accesible" % GCDialer._loginURL, UserWarning, 2) - return False + raise RuntimeError("%s is not accesible" % GCDialer._loginURL) return self.is_authed() @@ -122,20 +124,19 @@ class GCDialer(object): self._browser.cookies.clear() self._browser.cookies.save() + self.clear_caches() + def dial(self, number): """ This is the main function responsible for initating the callback """ - self._msg = "" - # If the number is not valid throw exception if not self.is_valid_syntax(number): raise ValueError('number is not valid') # No point if we don't have the magic cookie if not self.is_authed(): - self._msg = "Not authenticated" - return False + raise RuntimeError("Not Authenticated") # Strip leading 1 from 11 digit dialing if len(number) == 11 and number[0] == 1: @@ -148,20 +149,15 @@ class GCDialer(object): {'Referer' : 'http://www.grandcentral.com/mobile/messages'} ) except urllib2.URLError, e: - warnings.warn("%s is not accesible" % GCDialer._clicktocallURL, UserWarning, 2) - return False + raise RuntimeError("%s is not accesible" % GCDialer._clicktocallURL) - if GCDialer._gcDialingStrRe.search(callSuccessPage) is not None: - return True - else: - self._msg = "Grand Central returned an error" - return False + if GCDialer._gcDialingStrRe.search(callSuccessPage) is None: + raise RuntimeError("Grand Central returned an error") - self._msg = "Unknown Error" - return False + return True def clear_caches(self): - pass + self.__contacts = None def is_valid_syntax(self, number): """ @@ -226,8 +222,7 @@ class GCDialer(object): try: callbackSetPage = self._browser.download(GCDialer._setforwardURL, callbackPostData) except urllib2.URLError, e: - warnings.warn("%s is not accesible" % GCDialer._setforwardURL, UserWarning, 2) - return False + raise RuntimeError("%s is not accesible" % GCDialer._setforwardURL) self._browser.cookies.save() return True @@ -248,8 +243,7 @@ class GCDialer(object): try: recentCallsPage = self._browser.download(GCDialer._inboxallURL) except urllib2.URLError, e: - warnings.warn("%s is not accesible" % GCDialer._inboxallURL, UserWarning, 2) - return + raise RuntimeError("%s is not accesible" % GCDialer._inboxallURL) for match in self._inboxRe.finditer(recentCallsPage): phoneNumber = match.group(4) @@ -263,12 +257,12 @@ class GCDialer(object): @returns Iterable of (Address Book Factory, Book Id, Book Name) """ yield self, "", "" - + def open_addressbook(self, bookId): return self @staticmethod - def factory_short_name(): + def contact_source_short_name(contactId): return "GC" @staticmethod @@ -279,24 +273,39 @@ class GCDialer(object): """ @returns Iterable of (contact id, contact name) """ - contactsPagesUrls = [GCDialer._contactsURL] - for contactsPageUrl in contactsPagesUrls: - contactsPage = self._browser.download(contactsPageUrl) - for contact_match in self._contactsRe.finditer(contactsPage): - contactId = contact_match.group(1) - contactName = contact_match.group(2) - yield contactId, contactName - - next_match = self._contactsNextRe.match(contactsPage) - if next_match is not None: - newContactsPageUrl = self._contactsURL + next_match.group(1) - contactsPagesUrls.append(newContactsPageUrl) - + if self.__contacts is None: + self.__contacts = [] + + contactsPagesUrls = [GCDialer._contactsURL] + for contactsPageUrl in contactsPagesUrls: + try: + contactsPage = self._browser.download(contactsPageUrl) + except urllib2.URLError, e: + raise RuntimeError("%s is not accesible" % contactsPageUrl) + for contact_match in self._contactsRe.finditer(contactsPage): + contactId = contact_match.group(1) + contactName = contact_match.group(2) + contact = contactId, contactName + self.__contacts.append(contact) + yield contact + + next_match = self._contactsNextRe.match(contactsPage) + if next_match is not None: + newContactsPageUrl = self._contactsURL + next_match.group(1) + contactsPagesUrls.append(newContactsPageUrl) + else: + for contact in self.__contacts: + yield contact + def get_contact_details(self, contactId): """ @returns Iterable of (Phone Type, Phone Number) """ - detailPage = self._browser.download(GCDialer._contactDetailURL + '/' + contactId) + try: + detailPage = self._browser.download(GCDialer._contactDetailURL + '/' + contactId) + except urllib2.URLError, e: + raise RuntimeError("%s is not accesible" % GCDialer._contactDetailURL) + for detail_match in self._contactDetailPhoneRe.finditer(detailPage): phoneType = detail_match.group(1) phoneNumber = detail_match.group(2)