From 9b5e20f30ede6b5d4bc2c224510ab30cb9138c69 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 30 Sep 2009 21:37:39 -0500 Subject: [PATCH] Slowly transforming things into the shape needed to be ready to get things working --- src/connection.py | 21 ++++++-------- src/gvoice/__init__.py | 5 ++++ src/gvoice/addressbook.py | 4 ++- src/gvoice/backend.py | 42 +++++++++++++++------------- src/gvoice/session.py | 67 +++++++++++++++++++++++++++++++++++++++++++++ src/location.py | 2 +- src/simple_presence.py | 2 +- 7 files changed, 108 insertions(+), 35 deletions(-) create mode 100644 src/gvoice/__init__.py create mode 100644 src/gvoice/session.py diff --git a/src/connection.py b/src/connection.py index 2fd3632..32b47c2 100644 --- a/src/connection.py +++ b/src/connection.py @@ -46,8 +46,7 @@ class TheOneRingConnection(telepathy.server.Connection, simple_presence.SimplePr self._channelManager = channel_manager.ChannelManager(self) cookieFilePath = "%s/cookies.txt" % constants._data_path_ - self._backend = gvoice.dialer.GVDialer(cookieFilePath) - self._addressbook = gvoice.addressbook.Addressbook(self._backend) + self._session = gvoice.session.Session(cookieFilePath) self.set_self_handle(handle.create_handle(self, 'connection')) @@ -61,12 +60,8 @@ class TheOneRingConnection(telepathy.server.Connection, simple_presence.SimplePr return self._manager @property - def gvoice_backend(self): - return self._backend - - @property - def addressbook(self): - return self._addressbook + def session(self): + return self._session @property def username(self): @@ -85,9 +80,9 @@ class TheOneRingConnection(telepathy.server.Connection, simple_presence.SimplePr telepathy.CONNECTION_STATUS_REASON_REQUESTED ) try: - self._backend.login(*self._credentials) - self._backend.set_callback_number(self._callbackNumber) - except gvoice.dialer.NetworkError: + self.session.login(*self._credentials) + self.session.backend.set_callback_number(self._callbackNumber) + except gvoice.backend.NetworkError: self.StatusChanged( telepathy.CONNECTION_STATUS_DISCONNECTED, telepathy.CONNECTION_STATUS_REASON_NETWORK_ERROR @@ -108,7 +103,7 @@ class TheOneRingConnection(telepathy.server.Connection, simple_presence.SimplePr For org.freedesktop.telepathy.Connection """ try: - self._backend.logout() + self.session.logout() _moduleLogger.info("Disconnected") except Exception: _moduleLogger.exception("Disconnecting Failed") @@ -171,7 +166,7 @@ class TheOneRingConnection(telepathy.server.Connection, simple_presence.SimplePr def _create_contact_handle(self, name): requestedContactId = name - contacts = self._addressbook.get_contacts() + contacts = self.session.addressbook.get_contacts() contactsFound = [ contactId for contactId in contacts if contactId == requestedContactId diff --git a/src/gvoice/__init__.py b/src/gvoice/__init__.py new file mode 100644 index 0000000..afabc11 --- /dev/null +++ b/src/gvoice/__init__.py @@ -0,0 +1,5 @@ +#!/usr/bin/python + +import backend +import addressbook +import session diff --git a/src/gvoice/addressbook.py b/src/gvoice/addressbook.py index aeb8de5..bdbd9d8 100644 --- a/src/gvoice/addressbook.py +++ b/src/gvoice/addressbook.py @@ -20,7 +20,9 @@ class Addressbook(object): self.updateSignalHandler = coroutines.CoTee() - def update(self): + def update(self, force=False): + if not force and self._contacts: + return oldContacts = self._contacts oldContactIds = set(self.get_contacts()) diff --git a/src/gvoice/backend.py b/src/gvoice/backend.py index 9029606..b578445 100755 --- a/src/gvoice/backend.py +++ b/src/gvoice/backend.py @@ -46,7 +46,7 @@ except ImportError: simplejson = None -_moduleLogger = logging.getLogger("gvoice.dialer") +_moduleLogger = logging.getLogger("gvoice.backend") _TRUE_REGEX = re.compile("true") _FALSE_REGEX = re.compile("false") @@ -98,7 +98,11 @@ def itergroup(iterator, count, padValue = None): return itertools.izip(*nIterators) -class GVDialer(object): +class NetworkError(RuntimeError): + pass + + +class GVoiceBackend(object): """ This class encapsulates all of the knowledge necessary to interact with the GoogleVoice servers the functions include login, setting up a callback number, and initalting a callback @@ -159,8 +163,8 @@ class GVDialer(object): try: loginSuccessOrFailurePage = self._browser.download(self._loginURL, loginPostData) except urllib2.URLError, e: - _moduleLogger.exception(str(e)) - raise RuntimeError("%s is not accesible" % self._loginURL) + _moduleLogger.exception("Translating error: %s" % str(e)) + raise NetworkError("%s is not accesible" % self._loginURL) try: self._grab_account_info(loginSuccessOrFailurePage) @@ -196,8 +200,8 @@ class GVDialer(object): } callSuccessPage = self._browser.download(self._clicktocallURL, clickToCallData, None, otherData) except urllib2.URLError, e: - _moduleLogger.exception(str(e)) - raise RuntimeError("%s is not accesible" % self._clicktocallURL) + _moduleLogger.exception("Translating error: %s" % str(e)) + raise NetworkError("%s is not accesible" % self._clicktocallURL) if self._gvDialingStrRe.search(callSuccessPage) is None: raise RuntimeError("Google Voice returned an error") @@ -221,8 +225,8 @@ class GVDialer(object): } smsSuccessPage = self._browser.download(self._sendSmsURL, smsData, None, otherData) except urllib2.URLError, e: - _moduleLogger.exception(str(e)) - raise RuntimeError("%s is not accesible" % self._sendSmsURL) + _moduleLogger.exception("Translating error: %s" % str(e)) + raise NetworkError("%s is not accesible" % self._sendSmsURL) return True @@ -282,8 +286,8 @@ class GVDialer(object): try: flatXml = self._browser.download(url) except urllib2.URLError, e: - _moduleLogger.exception(str(e)) - raise RuntimeError("%s is not accesible" % url) + _moduleLogger.exception("Translating error: %s" % str(e)) + raise NetworkError("%s is not accesible" % url) allRecentHtml = self._grab_html(flatXml) allRecentData = self._parse_voicemail(allRecentHtml) @@ -304,8 +308,8 @@ class GVDialer(object): try: contactsPage = self._browser.download(contactsPageUrl) except urllib2.URLError, e: - _moduleLogger.exception(str(e)) - raise RuntimeError("%s is not accesible" % contactsPageUrl) + _moduleLogger.exception("Translating error: %s" % str(e)) + raise NetworkError("%s is not accesible" % contactsPageUrl) for contact_match in self._contactsRe.finditer(contactsPage): contactId = contact_match.group(1) contactName = saxutils.unescape(contact_match.group(2)) @@ -327,8 +331,8 @@ class GVDialer(object): try: detailPage = self._browser.download(self._contactDetailURL + '/' + contactId) except urllib2.URLError, e: - _moduleLogger.exception(str(e)) - raise RuntimeError("%s is not accesible" % self._contactDetailURL) + _moduleLogger.exception("Translating error: %s" % str(e)) + raise NetworkError("%s is not accesible" % self._contactDetailURL) for detail_match in self._contactDetailPhoneRe.finditer(detailPage): phoneNumber = detail_match.group(1) @@ -342,8 +346,8 @@ class GVDialer(object): try: voicemailPage = self._browser.download(self._voicemailURL) except urllib2.URLError, e: - _moduleLogger.exception(str(e)) - raise RuntimeError("%s is not accesible" % self._voicemailURL) + _moduleLogger.exception("Translating error: %s" % str(e)) + raise NetworkError("%s is not accesible" % self._voicemailURL) voicemailHtml = self._grab_html(voicemailPage) parsedVoicemail = self._parse_voicemail(voicemailHtml) decoratedVoicemails = self._decorate_voicemail(parsedVoicemail) @@ -351,8 +355,8 @@ class GVDialer(object): try: smsPage = self._browser.download(self._smsURL) except urllib2.URLError, e: - _moduleLogger.exception(str(e)) - raise RuntimeError("%s is not accesible" % self._smsURL) + _moduleLogger.exception("Translating error: %s" % str(e)) + raise NetworkError("%s is not accesible" % self._smsURL) smsHtml = self._grab_html(smsPage) parsedSms = self._parse_sms(smsHtml) decoratedSms = self._decorate_sms(parsedSms) @@ -616,7 +620,7 @@ def decorate_message(messageData): def test_backend(username, password): - backend = GVDialer() + backend = GVoiceBackend() print "Authenticated: ", backend.is_authed() if not backend.is_authed(): print "Login?: ", backend.login(username, password) diff --git a/src/gvoice/session.py b/src/gvoice/session.py new file mode 100644 index 0000000..674baf7 --- /dev/null +++ b/src/gvoice/session.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +import logging + +import backend +import addressbook + + +_moduleLogger = logging.getLogger("gvoice.session") + + +class Session(object): + + def __init__(self, cookiePath): + self._cookiePath = cookiePath + self._username = None + self._password = None + self._backend = None + self._addressbook = None + + def login(self, username, password): + self._username = username + self._password = password + self._backend = backend.GVoiceBackend(self._cookiePath) + if not self._backend.is_authed(): + self._backend.login(self._username, self._password) + + def logout(self): + self._username = None + self._password = None + self._backend = None + self._addressbook = None + + def is_logged_in(self): + if self._backend is None: + return False + elif self._backend.is_authed(): + return True + else: + try: + loggedIn = self._backend.login(self._username, self._password) + except RuntimeError: + loggedIn = False + if loggedIn: + return True + else: + self.logout() + return False + + @property + def backend(self): + """ + Login enforcing backend + """ + assert self.is_logged_in(), "User not logged in" + return self._backend + + @property + def addressbook(self): + """ + Delay initialized addressbook + """ + if self._addressbook is None: + _moduleLogger.info("Initializing addressbook") + self._addressbook = addressbook.Addressbook(self.backend) + self._addressbook.update() + return self._addressbook diff --git a/src/location.py b/src/location.py index 1965255..24e73a0 100644 --- a/src/location.py +++ b/src/location.py @@ -7,7 +7,7 @@ class LocationMixin(telepathy.server.ConnectionInterfaceLocation): telepathy.server.ConnectionInterfaceLocation.__init__(self) @property - def gvoice_backend(self): + def session(self): """ @abstract """ diff --git a/src/simple_presence.py b/src/simple_presence.py index b309e14..b95c2ea 100644 --- a/src/simple_presence.py +++ b/src/simple_presence.py @@ -26,7 +26,7 @@ class SimplePresenceMixin(telepathy.server.ConnectionInterfaceSimplePresence): self._implement_property_get(dbus_interface, {'Statuses' : self._get_statuses}) @property - def gvoice_backend(self): + def session(self): """ @abstract """ -- 1.7.9.5