abstract oauth based api's out of the linkdrop api
This commit is contained in:
Родитель
ac734c4751
Коммит
7fb9138354
|
@ -64,16 +64,16 @@ the contacts API that uses @me/@self.
|
|||
provider = request.POST['domain']
|
||||
session['oauth_provider'] = provider
|
||||
session.save()
|
||||
responder = get_provider(provider)
|
||||
return responder().request_access()
|
||||
service = get_provider(provider)
|
||||
return service.responder().request_access()
|
||||
|
||||
@json_exception_response
|
||||
def verify(self, *args, **kw):
|
||||
provider = session.pop('oauth_provider')
|
||||
session.save()
|
||||
responder = get_provider(provider)
|
||||
service = get_provider(provider)
|
||||
|
||||
auth = responder()
|
||||
auth = service.responder()
|
||||
access_key = auth.verify()
|
||||
data = auth.get_credentials(access_key)
|
||||
#import sys; print >> sys.stderr, data
|
||||
|
|
|
@ -10,7 +10,7 @@ from pylons.decorators.util import get_pylons
|
|||
|
||||
from linkdrop.lib.base import BaseController
|
||||
from linkdrop.lib.helpers import json_exception_response, api_response, api_entry, api_arg
|
||||
from linkdrop.lib.oauth.base import get_oauth_config
|
||||
from linkdrop.lib.oauth import get_provider
|
||||
|
||||
from linkdrop.model.meta import Session
|
||||
from linkdrop.model import Account, History
|
||||
|
@ -53,6 +53,7 @@ The 'send' namespace is used to send updates to our supported services.
|
|||
}
|
||||
return {'result': result, 'error': error}
|
||||
|
||||
provider = get_provider(domain)
|
||||
# even if we have a session key, we must have an account for that
|
||||
# user for the specified domain.
|
||||
try:
|
||||
|
@ -65,52 +66,7 @@ The 'send' namespace is used to send updates to our supported services.
|
|||
return {'result': result, 'error': error}
|
||||
|
||||
# send the item.
|
||||
if domain=="twitter.com":
|
||||
from twitter.oauth import OAuth
|
||||
from twitter.api import Twitter, TwitterHTTPError
|
||||
oauth_config = get_oauth_config(domain)
|
||||
auth = OAuth(token=acct.oauth_token,
|
||||
token_secret=acct.oauth_token_secret,
|
||||
consumer_key=oauth_config['consumer_key'],
|
||||
consumer_secret=oauth_config['consumer_secret'])
|
||||
try:
|
||||
api = Twitter(auth=auth)
|
||||
status = api.statuses.update(status=message)
|
||||
result[domain] = status['id']
|
||||
except TwitterHTTPError, exc:
|
||||
details = json.load(exc.e)
|
||||
if 'error' in details:
|
||||
msg = details['error']
|
||||
else:
|
||||
msg = str(details)
|
||||
error = {'provider': domain,
|
||||
'reason': msg,
|
||||
}
|
||||
elif domain=="facebook.com":
|
||||
url = "https://graph.facebook.com/me/feed?"+urllib.urlencode(dict(access_token=acct.oauth_token))
|
||||
body = urllib.urlencode({"message": message})
|
||||
resp, content = httplib2.Http().request(url, 'POST', body=body)
|
||||
response = json.loads(content)
|
||||
if 'id' in response:
|
||||
result[domain] = response['id']
|
||||
elif 'error' in response:
|
||||
import sys; print >> sys.stderr, repr(response)
|
||||
error = {'provider': domain,
|
||||
'reason': response['error'].get('message'),
|
||||
'type': response['error'].get('type')
|
||||
}
|
||||
if response['error'].get('type')=="OAuthInvalidRequestException":
|
||||
# status will be 401 if we need to reauthorize
|
||||
error['code'] = int(resp['status'])
|
||||
else:
|
||||
error = {'provider': domain,
|
||||
'reason': "unexpected facebook response: %r"% (response,)
|
||||
}
|
||||
log.error("unexpected facebook response: %r", response)
|
||||
else:
|
||||
error = {'provider': domain,
|
||||
'reason': "unsupported service %r" % (domain,)
|
||||
}
|
||||
result, error = provider.api(acct).sendmessage(message)
|
||||
|
||||
if error:
|
||||
assert not result
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
from linkdrop.lib.oauth.facebook_ import FacebookResponder
|
||||
from linkdrop.lib.oauth import facebook_
|
||||
#from linkdrop.lib.oauth.google_ import GoogleResponder
|
||||
#from linkdrop.lib.oauth.live_ import LiveResponder
|
||||
#from linkdrop.lib.oauth.openidconsumer import OpenIDResponder
|
||||
from linkdrop.lib.oauth.twitter_ import TwitterResponder
|
||||
from linkdrop.lib.oauth import twitter_
|
||||
#from linkdrop.lib.oauth.yahoo_ import YahooResponder
|
||||
|
||||
__all__ = ['get_provider']
|
||||
|
||||
# XXX need a better way to do this
|
||||
_providers = {
|
||||
TwitterResponder.domain: TwitterResponder,
|
||||
FacebookResponder.domain: FacebookResponder
|
||||
twitter_.domain: twitter_,
|
||||
facebook_.domain: facebook_
|
||||
}
|
||||
|
||||
def get_provider(provider):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# based on code from velruse
|
||||
# partially based on code from velruse
|
||||
|
||||
import urlparse
|
||||
try:
|
||||
|
@ -7,11 +7,14 @@ except ImportError:
|
|||
from cgi import parse_qs
|
||||
import json
|
||||
import httplib2
|
||||
import urllib
|
||||
|
||||
from pylons import config, request, response, session, tmpl_context as c, url
|
||||
from pylons.controllers.util import abort, redirect
|
||||
from linkdrop.lib.oauth.base import OAuth2
|
||||
|
||||
domain = 'facebook.com'
|
||||
|
||||
# borrowed from velruse
|
||||
def extract_fb_data(data):
|
||||
#import sys; print >> sys.stderr, data
|
||||
|
@ -83,14 +86,14 @@ def extract_fb_data(data):
|
|||
return profile
|
||||
|
||||
|
||||
class FacebookResponder(OAuth2):
|
||||
class responder(OAuth2):
|
||||
"""Handle Facebook OAuth login/authentication"""
|
||||
|
||||
profile_url = 'https://graph.facebook.com/me'
|
||||
domain = 'facebook.com'
|
||||
|
||||
def __init__(self):
|
||||
OAuth2.__init__(self, self.domain)
|
||||
OAuth2.__init__(self, domain)
|
||||
self.authorization_url = 'https://graph.facebook.com/oauth/authorize'
|
||||
self.access_token_url = 'https://graph.facebook.com/oauth/access_token'
|
||||
|
||||
|
@ -109,3 +112,38 @@ class FacebookResponder(OAuth2):
|
|||
|
||||
return result_data
|
||||
|
||||
class api():
|
||||
def __init__(self, account):
|
||||
self.access_token = account.oauth_token
|
||||
|
||||
def rawcall(self, url, body):
|
||||
url = url +"?"+urllib.urlencode(dict(access_token=self.access_token))
|
||||
resp, content = httplib2.Http().request(url, 'POST', body=urllib.urlencode(body))
|
||||
response = json.loads(content)
|
||||
result = error = None
|
||||
if 'id' in response:
|
||||
result = response
|
||||
result['facebook.com'] = response['id']
|
||||
elif 'error' in response:
|
||||
error = {'provider': domain,
|
||||
'reason': response['error'].get('message'),
|
||||
'type': response['error'].get('type')
|
||||
}
|
||||
if response['error'].get('type')=="OAuthInvalidRequestException":
|
||||
# status will be 401 if we need to reauthorize
|
||||
error['code'] = int(resp['status'])
|
||||
else:
|
||||
error = {'provider': domain,
|
||||
'reason': "unexpected facebook response: %r"% (response,)
|
||||
}
|
||||
log.error("unexpected facebook response: %r", response)
|
||||
return result, error
|
||||
|
||||
def sendmessage(self, message, options={}):
|
||||
url = "https://graph.facebook.com/me/feed"
|
||||
body = {
|
||||
"message": message
|
||||
}
|
||||
return self.rawcall(url, body)
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# based on code from velruse
|
||||
# partially based on code from velruse
|
||||
|
||||
import urlparse
|
||||
import json
|
||||
|
@ -7,19 +7,22 @@ import oauth2 as oauth
|
|||
|
||||
from pylons import config, request, response, session, tmpl_context as c, url
|
||||
from pylons.controllers.util import abort, redirect
|
||||
from linkdrop.lib.oauth.base import OAuth1
|
||||
from linkdrop.lib.oauth.base import OAuth1, get_oauth_config
|
||||
|
||||
class TwitterResponder(OAuth1):
|
||||
domain = 'twitter.com'
|
||||
|
||||
class responder(OAuth1):
|
||||
"""Handle Twitter OAuth login/authentication"""
|
||||
domain = 'twitter.com'
|
||||
|
||||
def __init__(self):
|
||||
OAuth1.__init__(self, self.domain)
|
||||
OAuth1.__init__(self, domain)
|
||||
self.request_token_url = 'https://twitter.com/oauth/request_token'
|
||||
self.access_token_url = 'https://twitter.com/oauth/access_token'
|
||||
self.authorization_url = 'https://twitter.com/oauth/authenticate'
|
||||
|
||||
def get_credentials(self, access_token):
|
||||
# XXX should call twitter.api.VerifyCredentials to get the user object
|
||||
# Setup the normalized poco contact object
|
||||
username = access_token['screen_name']
|
||||
userid = access_token['user_id']
|
||||
|
@ -39,3 +42,35 @@ class TwitterResponder(OAuth1):
|
|||
'oauth_token_secret': access_token['oauth_token_secret']}
|
||||
|
||||
return result_data
|
||||
|
||||
class api():
|
||||
def __init__(self, account):
|
||||
self.oauth_token = account.oauth_token
|
||||
self.oauth_token_secret = account.oauth_token_secret
|
||||
self.config = get_oauth_config(domain)
|
||||
|
||||
def rawcall(self, url, body):
|
||||
raise Exception("NOT IMPLEMENTED")
|
||||
|
||||
def sendmessage(self, message, options={}):
|
||||
from twitter.oauth import OAuth
|
||||
from twitter.api import Twitter, TwitterHTTPError
|
||||
auth = OAuth(token=self.oauth_token,
|
||||
token_secret=self.oauth_token_secret,
|
||||
consumer_key=self.config['consumer_key'],
|
||||
consumer_secret=self.config['consumer_secret'])
|
||||
result = error = None
|
||||
try:
|
||||
api = Twitter(auth=auth)
|
||||
result = api.statuses.update(status=message)
|
||||
result[domain] = result['id']
|
||||
except TwitterHTTPError, exc:
|
||||
details = json.load(exc.e)
|
||||
if 'error' in details:
|
||||
msg = details['error']
|
||||
else:
|
||||
msg = str(details)
|
||||
error = {'provider': domain,
|
||||
'reason': msg,
|
||||
}
|
||||
return result, error
|
||||
|
|
Загрузка…
Ссылка в новой задаче