Created
October 18, 2011 15:28
-
-
Save joerussbowman/1295709 to your computer and use it in GitHub Desktop.
YoutubeMixin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class YoutubeMixin(OAuth10aMixin): | |
""" To authenticate with Youtube, register your application with Google. | |
See http://code.google.com/apis/accounts/docs/RegistrationForWebAppsAuto.html | |
Then copy your Consumer Key and Consumer Secret to the application settings | |
'google_consumer_key' and 'google_consumer_secret'. Use this Mixin on the | |
handler for the URL you registered as your application's Callback URL. | |
When your application is set up, you can use this Mixin like this | |
to authenticate the user with Twitter and get access to their stream: | |
class YoutubeHandler(tornado.web.RequestHandler, | |
tornado.auth.YoutubeMixin): | |
@tornado.web.asynchronous | |
def get(self): | |
if self.get_argument("oauth_token", None): | |
self.get_authenticated_user(self.async_callback(self._on_auth), | |
{"scope": "http://gdata.youtube.com"}) | |
return | |
self.authorize_redirect() | |
def _on_auth(self, user): | |
if not user: | |
raise tornado.web.HTTPError(500, "Youtube auth failed") | |
# Save the user using, e.g., set_secure_cookie() | |
The user object returned by get_authenticated_user() includes the | |
attribute. 'username' in addition to 'access_token'. You should save the | |
access token with the user; it is required to make requests on behalf of the | |
user later with youtube_request(). | |
""" | |
_OAUTH_REQUEST_TOKEN_URL = "https://www.google.com/accounts/OAuthGetRequestToken" | |
_OAUTH_ACCESS_TOKEN_URL = "https://www.google.com/accounts/OAuthGetAccessToken" | |
_OAUTH_AUTHORIZE_URL = "https://www.google.com/accounts/OAuthAuthorizeToken" | |
def youtube_request(self, path, callback, access_token=None, | |
post_args=None, scope="http://gdata.youtube.com", **args): | |
"""Fetches the given API path, e.g., "/users/default/playlists" | |
The /feeds/api portion of the path is included for you already. | |
If you do not add version (v) or output type (alt) paramters they | |
will default to v=2&alt=json | |
If the request is a POST, post_args should be provided. Query | |
string arguments should be given as keyword arguments. | |
Extensive documentation on the Youtube API can be found here | |
http://code.google.com/apis/youtube/2.0/reference.html | |
Many methods require an OAuth access token which you can obtain | |
through authorize_redirect() and get_authenticated_user(). The | |
user returned through that process includes an 'access_token' | |
attribute that can be used to make authenticated requests via | |
this method. Example usage: | |
class MainHandler(tornado.web.RequestHandler, | |
tornado.auth.YoutubeMixin): | |
@tornado.web.authenticated | |
@tornado.web.asynchronous | |
def get(self): | |
self.youtube_request( | |
"/users/default/playlists", | |
access_token=user["access_token"], | |
callback=self.async_callback(self._on_post)) | |
def _on_post(self, new_entry): | |
if not output: | |
# Call failed; perhaps missing permission? | |
self.authorize_redirect() | |
return | |
# parse json output to display playlists | |
self.finish("Got my playlists!") | |
""" | |
url = "http://gdata.youtube.com/feeds/api" + path | |
if access_token: | |
all_args = {"scope": scope} | |
if not "v" in args: | |
all_args["v"] = 2 | |
if not "alt" in args: | |
all_args["alt"] = "json" | |
all_args.update(args) | |
all_args.update(post_args or {}) | |
method = "POST" if post_args is not None else "GET" | |
oauth = self._oauth_request_parameters( | |
url, access_token, all_args, method=method) | |
all_args.update(oauth) | |
if all_args: url += "?" + urllib.urlencode(all_args) | |
callback = self.async_callback(self._on_youtube_request, callback) | |
http = httpclient.AsyncHTTPClient() | |
if post_args is not None: | |
http.fetch(url, method="POST", body=urllib.urlencode(post_args), | |
callback=callback) | |
else: | |
http.fetch(url, callback=callback) | |
def _on_youtube_request(self, callback, response): | |
if response.error: | |
logging.warning("Error response %s fetching %s", response.error, | |
response.request.url) | |
callback(None) | |
return | |
callback(escape.json_decode(response.body)) | |
def _oauth_consumer_token(self): | |
self.require_setting("google_consumer_key", "Google OAuth") | |
self.require_setting("google_consumer_secret", "Google OAuth") | |
return dict( | |
key=self.settings["google_consumer_key"], | |
secret=self.settings["google_consumer_secret"]) | |
def _oauth_get_user(self, access_token, callback): | |
callback = self.async_callback(self._parse_user_response, callback) | |
self.youtube_request( | |
"/users/default", | |
access_token=access_token, callback=callback) | |
def _parse_user_response(self, callback, user): | |
if user: | |
user["username"] = user["entry"]["yt$username"]["$t"] | |
callback(user) | |
def get_authenticated_user(self, callback, auth_token_retry=3): | |
""" override get_authenticated_user to default auth_token_retry to 3 """ | |
return OAuth10aMixin.get_authenticated_user(self, | |
callback, | |
auth_token_retry=auth_token_retry) | |
def authorize_redirect(self, callback_uri): | |
""" override authorize_redirect to set scope """ | |
return OAuth10aMixin.authorize_redirect(self, | |
callback_uri = callback_uri, | |
extra_params = {"scope": "http://gdata.youtube.com"}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment