bigboard r7408 - in trunk/bigboard: . libbig stocks/twitter



Author: marinaz
Date: Thu Jun 26 20:59:14 2008
New Revision: 7408
URL: http://svn.gnome.org/viewvc/bigboard?rev=7408&view=rev

Log:
Check Twitter user credentials by making an asynchronous request to Twitter.

Move AsyncHTTPFetcherWithAuth to http.py


Modified:
   trunk/bigboard/google.py
   trunk/bigboard/libbig/http.py
   trunk/bigboard/stocks/twitter/TwitterStock.py
   trunk/bigboard/stocks/twitter/stock.css

Modified: trunk/bigboard/google.py
==============================================================================
--- trunk/bigboard/google.py	(original)
+++ trunk/bigboard/google.py	Thu Jun 26 20:59:14 2008
@@ -5,7 +5,7 @@
 
 import bigboard.globals as globals
 from bigboard.libbig.singletonmixin import Singleton
-from bigboard.libbig.http import AsyncHTTPFetcher
+from bigboard.libbig.http import AsyncHTTPFetcherWithAuth
 from bigboard import libbig
 from bigboard.workboard import WorkBoard
 import libbig.logutil
@@ -187,35 +187,6 @@
     def get_new_mails(self):
         return self.__mails
 
-class AsyncHTTPFetcherWithAuth(object):
-    """Small proxy class which expects username/password combinations for fetch(),
-    and supports invoking a callback on 401."""
-    def __init__(self):
-        super(AsyncHTTPFetcherWithAuth, self).__init__()
-        self.__fetcher = AsyncHTTPFetcher()
-        
-    def fetch(self, url, username, password, cb, errcb, authcb):
-        self.__fetcher.fetch_extended(url=url, cb=cb, 
-                                      no_store=True,
-                                      response_errcb=functools.partial(self.__handle_response_error, authcb, errcb),
-                                      setupfn=functools.partial(self.__http_setupfn, username, password))
-        
-    def __http_setupfn(self, username, password, h):
-        h.add_credentials(username, password)
-        h.follow_all_redirects = True
-        
-    def __handle_response_error(self, authcb, errcb, url, response, content):
-        if response and response.status == 401:
-            _logger.debug("auth failure for fetch of %s; response message %s; invoking auth callback" % (url, response.reason))
-            gobject.idle_add(lambda: authcb(url) and False)
-        else:
-            if response: 
-                _logger.error("caught error for fetch of %s (status %s)", url, response.status)
-            else:
-                _logger.error("caught error for fetch of %s, response is None, possibly the network connection is down", url)
-            # in my experience sys.exc_info() is some kind of junk here, while "e" is useful
-            gobject.idle_add(lambda: errcb(url, response) and False)
-
 class GooglePollAction(object):
     def __init__(self, google):
         self.__google = google

Modified: trunk/bigboard/libbig/http.py
==============================================================================
--- trunk/bigboard/libbig/http.py	(original)
+++ trunk/bigboard/libbig/http.py	Thu Jun 26 20:59:14 2008
@@ -1,5 +1,5 @@
 import os,sys
-import threading, logging, urllib2, cookielib, urllib, StringIO, httplib
+import threading, logging, urllib2, cookielib, urllib, StringIO, httplib, functools
 import xml.dom.minidom, urlparse
 
 import gobject
@@ -8,6 +8,8 @@
 from bigboard.libbig.singletonmixin import Singleton
 import bigboard.httplib2 as httplib2
 
+_logger = logging.getLogger("bigboard.libbig.Http")
+
 class ThreadsafeFileCache(httplib2.FileCache):
     __lock = threading.Lock()
     
@@ -193,3 +195,31 @@
             kwargs['is_refetch'] = True
         cb(url, fdata, **kwargs)
     
+class AsyncHTTPFetcherWithAuth(object):
+    """Small proxy class which expects username/password combinations for fetch(),
+    and supports invoking a callback on 401."""
+    def __init__(self):
+        super(AsyncHTTPFetcherWithAuth, self).__init__()
+        self.__fetcher = AsyncHTTPFetcher()
+        
+    def fetch(self, url, username, password, cb, errcb, authcb, **kwargs):
+        self.__fetcher.fetch_extended(url=url, cb=cb, 
+                                      no_store=True,
+                                      response_errcb=functools.partial(self.__handle_response_error, authcb, errcb),
+                                      setupfn=functools.partial(self.__http_setupfn, username, password), **kwargs)
+        
+    def __http_setupfn(self, username, password, h):
+        h.add_credentials(username, password)
+        h.follow_all_redirects = True
+        
+    def __handle_response_error(self, authcb, errcb, url, response, content):
+        if response and response.status == 401:
+            _logger.debug("auth failure for fetch of %s; response message %s; invoking auth callback" % (url, response.reason))
+            gobject.idle_add(lambda: authcb(url) and False)
+        else:
+            if response: 
+                _logger.error("caught error for fetch of %s (status %s)", url, response.status)
+            else:
+                _logger.error("caught error for fetch of %s, response is None, possibly the network connection is down", url)
+            # in my experience sys.exc_info() is some kind of junk here, while "e" is useful
+            gobject.idle_add(lambda: errcb(url, response) and False)

Modified: trunk/bigboard/stocks/twitter/TwitterStock.py
==============================================================================
--- trunk/bigboard/stocks/twitter/TwitterStock.py	(original)
+++ trunk/bigboard/stocks/twitter/TwitterStock.py	Thu Jun 26 20:59:14 2008
@@ -1,13 +1,17 @@
 import logging, dbus
+import urllib
 import hippo
 from bigboard.stock import Stock
 import bigboard.accounts_dialog as accounts_dialog
 import bigboard.libbig.gutil as gutil
 from bigboard.libbig.logutil import log_except
+import bigboard.libbig as libbig
+from bigboard.libbig.http import AsyncHTTPFetcherWithAuth
 
 _logger = logging.getLogger('bigboard.stocks.TwitterStock')
 
 LOGIN_TO_TWITTER_STRING = "Login to Twitter"
+FAILED_TO_LOGIN_STRING = "Failed to login."
 
 TWITTER_KIND = "twitter"
 
@@ -22,6 +26,10 @@
         self.__login_button.connect('activated', lambda button: self.__open_login_dialog())
         self.__box.append(self.__login_button)
 
+        self._add_more_button(self.__on_more_button)
+
+        self.__fetcher = AsyncHTTPFetcherWithAuth()
+
         # even though the account system can theoretically return multiple Twitter accounts, this stock
         # only supports one -- the last one that was added
         self.__twitter_account = None
@@ -78,7 +86,7 @@
     
     @log_except(_logger)
     def __on_account_removed(self, acct_path):
-        _logger.debug("in on account removed")
+        _logger.debug("in __on_account_removed")
         if self.__twitter_account and self.__twitter_account.GetObjectPath() == acct_path: 
             _logger.debug("in __on_account_removed for %s", acct_path)   
             self.__twitter_account_changed_signal_match.remove()
@@ -86,19 +94,68 @@
             self.__twitter_account = None
             #TODO: will need to stop the polling action here
             self.__box.remove_all() 
-            self.__login_button.set_property('text', LOGIN_TO_TWITTER_STRING) 
             self.__box.append(self.__login_button)
 
     @log_except(_logger)
     def __on_twitter_account_changed(self):
         _logger.debug("will change stuff")
+        username = self.__twitter_account.GetUsername()
+        password = self.__twitter_account.GetPassword() 
+        if password != "":
+            self.__box.remove_all()
+            checking = hippo.CanvasText(text="Checking credentials for " + username + "...",
+                                          size_mode=hippo.CANVAS_SIZE_WRAP_WORD, classes="info")
+            self.__box.append(checking)
+            self.__fetcher.fetch("http://twitter.com/account/verify_credentials.json";, 
+                                 username, password,
+                                 lambda url, data: self.__on_twitter_response(url, data, username, password), 
+                                 lambda url, resp: self.__on_twitter_error(url, resp, username, password),
+                                 lambda url: self.__on_auth_failed(username, password),
+                                 data = urllib.urlencode({}))
+        else:
+            self.__add_login_button()  
+
+    def __on_twitter_response(self, url, data, username, password):
+        _logger.debug("Authentication must be good")
+        if self.__same_credentials(username, password):
+            self.__box.remove_all()
+            hello_message = hippo.CanvasText(text="Hello Twitter User " + self.__twitter_account.GetUsername() ,
+                                             size_mode=hippo.CANVAS_SIZE_WRAP_WORD)
+            self.__box.append(hello_message)
+
+    def __on_twitter_error(self, url, resp, username, password):
+        status = resp and str(resp.status) or "No response"
+        _logger.debug("There was a Twitter error. Response: %s" % status)
+        if self.__same_credentials(username, password):
+            self.__add_login_button(True)
+
+    def __on_auth_failed(self, username, password):
+        _logger.debug("There was an authentication failure")
+        if self.__same_credentials(username, password):
+            self.__add_login_button(True)
+
+    def __same_credentials(self, username, password):
+        return self.__twitter_account and self.__twitter_account.GetUsername() == username and self.__twitter_account.GetPassword() == password
+
+    def __add_login_button(self, failed_to_login = False):
         self.__box.remove_all()
-        hello_message = hippo.CanvasText(text="Hello Twitter User " + self.__twitter_account.GetUsername() , \
+        if failed_to_login:
+            error = hippo.CanvasText(text=FAILED_TO_LOGIN_STRING, size_mode=hippo.CANVAS_SIZE_WRAP_WORD, classes="error")
+            self.__box.append(error) 
+        hello_message = hippo.CanvasText(text="Hello Twitter User " + self.__twitter_account.GetUsername(),
                                          size_mode=hippo.CANVAS_SIZE_WRAP_WORD)
-        self.__box.append(hello_message)
-        if self.__twitter_account.GetPassword() == "":
-            self.__box.append(self.__login_button)                    
-
+        self.__box.append(hello_message)                           
+        self.__box.append(self.__login_button) 
+ 
     def __open_login_dialog(self):
         accounts_dialog.open_dialog(["twitter"])
 
+    def __on_more_button(self):
+        if self.__twitter_account:
+            url = "http://twitter.com/home";
+        else:
+            url = "http://twitter.com";
+        libbig.show_url(url)
+
+
+

Modified: trunk/bigboard/stocks/twitter/stock.css
==============================================================================
--- trunk/bigboard/stocks/twitter/stock.css	(original)
+++ trunk/bigboard/stocks/twitter/stock.css	Thu Jun 26 20:59:14 2008
@@ -1 +1,7 @@
-/* nothing here */
+.info {
+    color: #00AABB;
+}
+
+.error {
+    color: #CC1122;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]