ade@google.com | ac41d84 | 2010-08-20 17:11:25 +0100 | [diff] [blame] | 1 | # Copyright (C) 2010 Google Inc. |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | # you may not use this file except in compliance with the License. |
| 5 | # You may obtain a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. |
| 14 | |
| 15 | __author__ = 'ade@google.com' |
| 16 | |
| 17 | import apiclient.discovery |
| 18 | import logging |
| 19 | import oauth_wrap |
| 20 | import oauth2 as oauth |
| 21 | import urllib |
| 22 | import urlparse |
| 23 | |
| 24 | try: |
| 25 | from urlparse import parse_qs, parse_qsl, urlparse |
| 26 | except ImportError: |
| 27 | from cgi import parse_qs, parse_qsl |
| 28 | |
| 29 | # TODO(ade) Replace user-agent with something specific |
| 30 | HEADERS = { |
| 31 | 'user-agent': 'gdata-python-v3-sample-client/0.1', |
| 32 | 'content-type': 'application/x-www-form-urlencoded' |
| 33 | } |
| 34 | |
| 35 | REQUEST_TOKEN_URL = 'https://www.google.com/accounts/OAuthGetRequestToken?domain=anonymous&scope=https://www.googleapis.com/auth/buzz' |
| 36 | AUTHORIZE_URL = 'https://www.google.com/buzz/api/auth/OAuthAuthorizeToken?domain=anonymous&scope=https://www.googleapis.com/auth/buzz' |
| 37 | ACCESS_TOKEN_URL = 'https://www.google.com/accounts/OAuthGetAccessToken' |
| 38 | |
Tom Miller | 05cd4f5 | 2010-10-06 11:09:12 -0700 | [diff] [blame] | 39 | |
| 40 | class Error(Exception): |
| 41 | """Base error for this module.""" |
| 42 | pass |
| 43 | |
| 44 | |
| 45 | class RequestError(Error): |
| 46 | """Request returned failure or unexpected data.""" |
| 47 | pass |
| 48 | |
| 49 | |
ade@google.com | 2ab0de7 | 2010-09-27 23:26:54 +0100 | [diff] [blame] | 50 | # TODO(ade) This class is really a BuzzGaeBuilder. Rename it. |
ade@google.com | ac41d84 | 2010-08-20 17:11:25 +0100 | [diff] [blame] | 51 | class BuzzGaeClient(object): |
| 52 | def __init__(self, consumer_key='anonymous', consumer_secret='anonymous'): |
| 53 | self.consumer = oauth.Consumer(consumer_key, consumer_secret) |
| 54 | self.consumer_key = consumer_key |
| 55 | self.consumer_secret = consumer_secret |
| 56 | |
| 57 | def _make_post_request(self, client, url, parameters): |
| 58 | resp, content = client.request(url, 'POST', headers=HEADERS, |
| 59 | body=urllib.urlencode(parameters, True)) |
| 60 | |
| 61 | if resp['status'] != '200': |
| 62 | logging.warn('Request: %s failed with status: %s. Content was: %s' % (url, resp['status'], content)) |
Tom Miller | 05cd4f5 | 2010-10-06 11:09:12 -0700 | [diff] [blame] | 63 | raise RequestError('Invalid response %s.' % resp['status']) |
ade@google.com | ac41d84 | 2010-08-20 17:11:25 +0100 | [diff] [blame] | 64 | return resp, content |
| 65 | |
| 66 | def get_request_token(self, callback_url, display_name = None): |
| 67 | parameters = { |
| 68 | 'oauth_callback': callback_url |
| 69 | } |
| 70 | |
| 71 | if display_name is not None: |
| 72 | parameters['xoauth_displayname'] = display_name |
| 73 | |
| 74 | client = oauth.Client(self.consumer) |
| 75 | resp, content = self._make_post_request(client, REQUEST_TOKEN_URL, parameters) |
| 76 | |
| 77 | request_token = dict(parse_qsl(content)) |
| 78 | return request_token |
| 79 | |
| 80 | def generate_authorisation_url(self, request_token): |
| 81 | """Returns the URL the user should be redirected to in other to gain access to their account.""" |
| 82 | |
| 83 | base_url = urlparse.urlparse(AUTHORIZE_URL) |
| 84 | query = parse_qs(base_url.query) |
| 85 | query['oauth_token'] = request_token['oauth_token'] |
| 86 | |
| 87 | logging.info(urllib.urlencode(query, True)) |
| 88 | |
| 89 | url = (base_url.scheme, base_url.netloc, base_url.path, base_url.params, |
| 90 | urllib.urlencode(query, True), base_url.fragment) |
| 91 | authorisation_url = urlparse.urlunparse(url) |
| 92 | return authorisation_url |
| 93 | |
| 94 | def upgrade_to_access_token(self, request_token, oauth_verifier): |
| 95 | token = oauth.Token(request_token['oauth_token'], |
| 96 | request_token['oauth_token_secret']) |
| 97 | token.set_verifier(oauth_verifier) |
| 98 | client = oauth.Client(self.consumer, token) |
| 99 | |
| 100 | parameters = {} |
| 101 | resp, content = self._make_post_request(client, ACCESS_TOKEN_URL, parameters) |
| 102 | access_token = dict(parse_qsl(content)) |
| 103 | |
| 104 | d = { |
| 105 | 'consumer_key' : self.consumer_key, |
| 106 | 'consumer_secret' : self.consumer_secret |
| 107 | } |
| 108 | d.update(access_token) |
| 109 | return d |
| 110 | |
ade@google.com | e80fec8 | 2010-08-20 23:42:08 +0100 | [diff] [blame] | 111 | def build_api_client(self, oauth_params=None): |
| 112 | if oauth_params is not None: |
| 113 | http = oauth_wrap.get_authorised_http(oauth_params) |
| 114 | return apiclient.discovery.build('buzz', 'v1', http = http) |
| 115 | else: |
| 116 | return apiclient.discovery.build('buzz', 'v1') |