abstract oauth based api's out of the linkdrop api

This commit is contained in:
mixedpuppy 2010-09-02 15:24:50 -07:00
Родитель ac734c4751
Коммит 7fb9138354
5 изменённых файлов: 91 добавлений и 62 удалений

Просмотреть файл

@ -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