Commits

Josh VanderLinden committed 949e946

Updated Twibber to play nicely with the OAuth changes to Twitter yesterday. I updated the configuration wizard to support the 6-digit PIN and updated the various pieces to understand this change.

Comments (0)

Files changed (4)

         log.info('Terminating the application')
         self.checker.set()
         self.poster.set()
-        #self.client.disconnected()
 
         config.persist()
 
     __slots__ = ('username', '_password', 'last_tweet_id', 'last_update',
                  '_api', '_request_token', '_auth_url', '_access_token',
                  'has_shown_tweets', 'last_mention_update', 'last_mention_id',
-                 'last_direct_update', 'last_direct_id')
+                 'last_direct_update', 'last_direct_id', '_pin')
 
     def __init__(self, username=None, password='', last_tweet_id=0,
                  last_update=None, last_mention_update=None,
         self._request_token = None
         self._auth_url = None
         self._access_token = None
+        self._pin = None
         self.has_shown_tweets = False
 
     def __unicode__(self):
         if manual:
             webbrowser.open(self._auth_url)
 
-    def CompleteOAuth(self):
+    def CompleteOAuth(self, pin):
         """
         This must be called after we have the access key
         """
+        self._pin = pin
         if not self._access_token:
             api = OAuthApi(CONSUMER_KEY, CONSUMER_SECRET, self._request_token)
-            self._access_token = api.getAccessToken()
+            self._access_token = api.getAccessToken(self._pin)
 
         if self._access_token:
             api = OAuthApi(CONSUMER_KEY, CONSUMER_SECRET, self._access_token)
             str(self.last_tweet_id) or '',
             self._request_token.to_string() or '',
             self._auth_url or '',
-            self._access_token.to_string() or ''
+            self._access_token.to_string() or '',
+            self._pin or ''
         ]
         return base64.b64encode('&&&'.join(data))
 
             if len(data[5]):
                 user._access_token = oauth.OAuthToken.from_string(data[5])
             log.debug(data)
-            
+
+            user._pin = int(data[6])
+
             user.BeginOAuth(manual=False)
-            user.CompleteOAuth()
+            user.CompleteOAuth(user._pin)
         return user
     deserialize = classmethod(deserialize)
 
         'jabber_proxy_username': '',
         'jabber_proxy_password': ''
     }
-    
+
     _users = None
     _scheduled = None
     _filtered = None
         self.configfile = configfile
 
         # grab these values from the configuration
-        omit = ('twitter_users', 'default_user', 'filtered_tags', 
+        omit = ('twitter_users', 'default_user', 'filtered_tags',
                 'scheduled_tweets')
         self.to_grab = tuple(k for k in Config.Defaults.keys() if k not in omit)
 
             self.scheduled_tweets = self.scheduled_tweets
             self.filtered_tags = self.filtered_tags
             self.default_user = self.default_user
-    
+
             for key in self.to_grab:
                 self.set(key, getattr(self, key, self.get_default(key)))
-    
+
             out = open(self.configfile, 'wb')
             self.parser.write(out)
             out.close()
 #!/usr/bin/env python
-# 
+#
 # Copyright under GPLv3
 
 '''A class the inherits everything from python-twitter and allows oauth based access
 __author__ = "Hameedullah Khan <hameed@hameedkhan.net>"
 __version__ = "0.1"
 
-
 from twitter import Api, User
-
 import simplejson, oauth
 
-
-
 # Taken from oauth implementation at: http://github.com/harperreed/twitteroauth-python/tree/master
 REQUEST_TOKEN_URL = 'https://twitter.com/oauth/request_token'
 ACCESS_TOKEN_URL = 'https://twitter.com/oauth/access_token'
 AUTHORIZATION_URL = 'http://twitter.com/oauth/authorize'
 SIGNIN_URL = 'http://twitter.com/oauth/authenticate'
 
-
 class OAuthApi(Api):
     def __init__(self, consumer_key, consumer_secret, access_token=None):
         if access_token:
         self._signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1()
         self._access_token = access_token
 
-
     def _GetOpener(self):
         opener = self._urllib.build_opener()
         return opener
 
-    def _FetchUrl(self,
-                    url,
-                    post_data=None,
-                    parameters=None,
-                    no_cache=None):
+    def _FetchUrl(self, url, post_data=None, parameters=None, no_cache=None):
         '''Fetch a URL, optionally caching for a specified time.
-    
+
         Args:
           url: The URL to retrieve
-          post_data: 
+          post_data:
             A dict of (str, unicode) key/value pairs.  If set, POST will be used.
           parameters:
-            A dict whose key/value pairs should encoded and added 
+            A dict whose key/value pairs should encoded and added
             to the query string. [OPTIONAL]
           no_cache: If true, overrides the cache on the current request
-    
+
         Returns:
           A string containing the body of the response.
         '''
         # Build the extra parameters dict
         extra_params = {}
         if self._default_params:
-          extra_params.update(self._default_params)
+            extra_params.update(self._default_params)
         if parameters:
-          extra_params.update(parameters)
-    
+            extra_params.update(parameters)
+
         # Add key/value parameters to the query string of the url
         #url = self._BuildUrl(url, extra_params=extra_params)
-    
+
         if post_data:
             http_method = "POST"
             extra_params.update(post_data)
         else:
             http_method = "GET"
-        
-        req = self._makeOAuthRequest(url, parameters=extra_params, 
-                                                    http_method=http_method)
+
+        req = self._makeOAuthRequest(url, parameters=extra_params,
+                                     http_method=http_method)
         self._signRequest(req, self._signature_method)
 
-        
         # Get a url opener that can handle Oauth basic auth
         opener = self._GetOpener()
-        
+
         #encoded_post_data = self._EncodePostData(post_data)
 
         if post_data:
         else:
             url = req.to_url()
             encoded_post_data = ""
-            
-        no_cache=True
+
+        no_cache = True
         # Open and return the URL immediately if we're not going to cache
         # OR we are posting data
         if encoded_post_data or no_cache:
             key = self._username + ':' + url
           else:
             key = url
-    
+
           # See if it has been cached before
           last_cached = self._cache.GetCachedTime(key)
-    
+
           # If the cached version is outdated then fetch another and store it
           if not last_cached or time.time() >= last_cached + self._cache_timeout:
             url_data = opener.open(url).read()
             self._cache.Set(key, url_data)
           else:
             url_data = self._cache.Get(key)
-    
+
         # Always return the latest version
         return url_data
-    
+
     def _makeOAuthRequest(self, url, token=None,
-                                        parameters=None, http_method="GET"):
+                          parameters=None, http_method="GET"):
         '''Make a OAuth request from url and parameters
-        
+
         Args:
           url: The Url to use for creating OAuth Request
           parameters:
         if not token:
             token = self._access_token
         request = oauth.OAuthRequest.from_consumer_and_token(
-                            self._Consumer, token=token, 
-                            http_url=url, parameters=parameters, 
+                            self._Consumer, token=token,
+                            http_url=url, parameters=parameters,
                             http_method=http_method)
         return request
 
     def _signRequest(self, req, signature_method=oauth.OAuthSignatureMethod_HMAC_SHA1()):
         '''Sign a request
-        
+
         Reminder: Created this function so incase
         if I need to add anything to request before signing
-        
+
         Args:
           req: The OAuth request created via _makeOAuthRequest
           signate_method:
              The oauth signature method to use
         '''
         req.sign_request(signature_method, self._Consumer, self._access_token)
-    
 
     def getAuthorizationURL(self, token, url=AUTHORIZATION_URL):
         '''Create a signed authorization URL
-        
+
         Returns:
-          A signed OAuthRequest authorization URL 
+          A signed OAuthRequest authorization URL
         '''
         req = self._makeOAuthRequest(url, token=token)
         self._signRequest(req)
 
     def getSigninURL(self, token, url=SIGNIN_URL):
         '''Create a signed Sign-in URL
-        
+
         Returns:
-          A signed OAuthRequest Sign-in URL 
+          A signed OAuthRequest Sign-in URL
         '''
-        
         signin_url = self.getAuthorizationURL(token, url)
         return signin_url
-    
-    def getAccessToken(self, url=ACCESS_TOKEN_URL):
-        token = self._FetchUrl(url, no_cache=True)
-        return oauth.OAuthToken.from_string(token) 
+
+    def getAccessToken(self, pin, url=ACCESS_TOKEN_URL):
+        token = self._FetchUrl(url, parameters={'oauth_verifier': pin}, no_cache=True)
+        return oauth.OAuthToken.from_string(token)
 
     def getRequestToken(self, url=REQUEST_TOKEN_URL):
         '''Get a Request Token from Twitter
-        
+
         Returns:
           A OAuthToken object containing a request token
         '''
         resp = self._FetchUrl(url, no_cache=True)
         token = oauth.OAuthToken.from_string(resp)
         return token
-    
+
     def GetUserInfo(self, url='https://twitter.com/account/verify_credentials.json'):
         '''Get user information from twitter
-        
+
         Returns:
           Returns the twitter.User object
         '''
         data = simplejson.loads(json)
         self._CheckForTwitterError(data)
         return User.NewFromJsonDict(data)
-        
+
+"""
+    def CreateFriendship(self, user):
+        '''Befriends the user specified in the user parameter as the authenticating user.
+
+        The twitter.Api instance must be authenticated.
+
+        Args:
+        The ID or screen name of the user to befriend.
+        Returns:
+        A twitter.User instance representing the befriended user.
+        '''
+        url = 'http://twitter.com/friendships/create/create.json'
+        json = self._FetchUrl(url, post_data={'screen_name': user})
+        data = simplejson.loads(json)
+        self._CheckForTwitterError(data)
+        return User.NewFromJsonDict(data)
+"""
         self.users = config.users
 
         # build the GUI
-        self.sizer = make_page_title(self, 'Twitter Authentication')
+        self.sizer = make_page_title(self, 'Twitter Authorization')
         info = wx.StaticText(self, label='You must allow Twibber access to your'
-                'Twitter account in order to retrieve your updates.  In order '
+                ' Twitter account in order to retrieve your updates.  In order '
                 'to better protect your privacy, Twibber uses only OAuth, which'
                 ' means that you don\'t have to enter your Twitter username and'
                 ' password here.')
         self.sizer.Add(info)
 
         self.sizer.AddSpacer(10)
-    
+
         inst = wx.StaticText(self, label='Simply click the "Authorize Twibber" '
                 'button below.  This will open Twitter up in your web browser, '
                 'asking you to give Twibber read+write access to your '
-                'information. After you give Twibber access, come back to this '
-                'screen and click the "Finish Authorization" button.')
+                'information. After you give Twibber access, copy the 6-digit '
+                'PIN number and come back to this screen.  Enter the PIN '
+                'number in the box below and click the "Finish Authorization" '
+                'button.')
         inst.Wrap(400)
         self.sizer.Add(inst)
 
-        self.sizer.AddSpacer(10)
+        self.sizer.AddSpacer(20)
 
-        buttons = wx.BoxSizer(wx.HORIZONTAL)
-        self.sizer.Add(buttons)
+        bold = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+        bold.SetWeight(wx.BOLD)
+        bold.SetPointSize(14)
+        self.authorize = wx.Button(self, label="  Authorize Twibber  ")
+        self.authorize.SetFont(bold)
+        self.sizer.Add(self.authorize, 2, wx.ALIGN_CENTER_HORIZONTAL)
 
-        self.authorize = wx.Button(self, label="Authorize Twibber")
-        buttons.Add(self.authorize)
+        self.sizer.AddSpacer(20)
+
+        pin_sizer = wx.BoxSizer(wx.HORIZONTAL)
+        self.sizer.Add(pin_sizer, 0, wx.EXPAND)
+
+        pin_sizer.Add(
+            wx.StaticText(self, label='Your 6-digit PIN:'), 0,
+            wx.ALIGN_CENTER_VERTICAL)
+        pin_sizer.AddSpacer(10)
+
+        self.pin = wx.TextCtrl(self)
+        self.pin.Enable(False)
+        pin_sizer.Add(self.pin, 1, wx.EXPAND)
+        pin_sizer.AddSpacer(10)
 
         self.complete = wx.Button(self, label="Finish Authorization")
         self.complete.Enable(False)
-        buttons.Add(self.complete)
+        pin_sizer.Add(self.complete)
 
+        """
         self.sizer.AddSpacer(10)
 
         no_browser = wx.StaticText(self, label='If your browser does not open,'
 
         self.auth_url = wx.TextCtrl(self, style=wx.TE_MULTILINE)
         self.sizer.AddF(self.auth_url, sf(wx.TOP, 10))
+        """
 
         self.authorize.Bind(wx.EVT_BUTTON, self.BeginAuthorization)
         self.complete.Bind(wx.EVT_BUTTON, self.FinishAuthorization)
         """
         self.user = User()
         self.user.BeginOAuth()
-        self.auth_url.SetValue(self.user._auth_url)
+
         self.authorize.Enable(False)
+        self.pin.Enable(True)
         self.complete.Enable(True)
 
+        #self.auth_url.SetValue(self.user._auth_url)
+
     def FinishAuthorization(self, evt=None):
-        self.user.CompleteOAuth()
+        self.user.CompleteOAuth(self.pin.GetValue())
         try:
             log.info('Attempting to authenticate using OAuth')
             self.user.api._FetchUrl('http://twitter.com/account/verify_credentials.json')
         Enables and disabled the buttons
         """
         self.authorize.Enable(True)
+        self.pin.Enable(False)
         self.complete.Enable(False)
-        self.auth_url.SetValue('')
+        #self.auth_url.SetValue('')
 
     def ValidatePage(self, evt):
         if not self.authorized or len(self.users) <= 0:
     def __init__(self, parent, *args, **kwargs):
         from twibber import APP_TITLE
         title = APP_TITLE + ' Configuration Wizard'
-        style = wx.DEFAULT_FRAME_STYLE
+        style = wx.DEFAULT_FRAME_STYLE &~ wx.RESIZE_BORDER
         wizard.Wizard.__init__(self, parent, title=title, style=style)
         self.parent = parent
 
 
         # make sure we enable or disable the "as" command if the user changed
         # the number of Twitter users
-        self.parent.twibber.OnConfigChanged()
+        #self.parent.twibber.OnConfigChanged()
 
 class TwitterTray(wx.TaskBarIcon):
     """