auth.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. """Wrapper for Google OAuth2 API."""
  2. import sys
  3. import json
  4. import gtk
  5. import webkit
  6. import googleapiclient.discovery
  7. import oauth2client
  8. import httplib2
  9. YOUTUBE_UPLOAD_SCOPE = "https://www.googleapis.com/auth/youtube.upload"
  10. JAVASCRIPT_AUTHORIZATION_SET_STATUS = """
  11. var code = document.getElementById("code");
  12. var access_denied = document.getElementById("access_denied");
  13. var result;
  14. if (code) {
  15. result = {authorized: true, code: code.value};
  16. } else if (access_denied) {
  17. result = {authorized: false, message: access_denied.innerText};
  18. } else {
  19. result = {};
  20. }
  21. window.status = JSON.stringify(result);
  22. """
  23. def _on_webview_status_bar_changed(webview, status, dialog):
  24. if status:
  25. result = json.loads(status)
  26. if result.has_key("authorized"):
  27. dialog.set_data("authorization", result)
  28. dialog.response(0)
  29. def _get_code_from_browser(url, size=(640, 480), title=None):
  30. """Open a webkit window and return the code the user wrote."""
  31. webview = webkit.WebView()
  32. dialog = gtk.Dialog(title=(title or "Google authentication"))
  33. scrolled = gtk.ScrolledWindow()
  34. scrolled.add(webview)
  35. dialog.get_children()[0].add(scrolled)
  36. webview.load_uri(url)
  37. dialog.resize(*size)
  38. dialog.show_all()
  39. dialog.connect("delete-event", lambda ev, data: dialog.response(1))
  40. webview.connect("load-finished",
  41. lambda view, frame: webview.execute_script(JAVASCRIPT_AUTHORIZATION_SET_STATUS))
  42. webview.connect("status-bar-text-changed", _on_webview_status_bar_changed, dialog)
  43. dialog.set_data("authorization", None)
  44. status = dialog.run()
  45. dialog.destroy()
  46. while gtk.events_pending():
  47. gtk.main_iteration(False)
  48. authorization = dialog.get_data("authorization")
  49. if status == 0 and authorization and authorization["authorized"]:
  50. return authorization["code"]
  51. def _get_code_from_prompt(authorize_url):
  52. """Show authorization URL and return the code the user wrote."""
  53. message = "Check this link in your browser: {0}".format(authorize_url)
  54. sys.stderr.write(message + "\n")
  55. return raw_input("Enter verification code: ").strip()
  56. def _get_credentials_interactively(flow, storage, get_code_callback):
  57. """Return the credentials asking the user."""
  58. flow.redirect_uri = oauth2client.client.OOB_CALLBACK_URN
  59. authorize_url = flow.step1_get_authorize_url()
  60. code = get_code_callback(authorize_url)
  61. if code:
  62. credential = flow.step2_exchange(code, http=None)
  63. storage.put(credential)
  64. credential.set_store(storage)
  65. return credential
  66. def _get_credentials(flow, storage, get_code_callback):
  67. """Return the user credentials. If not found, run the interactive flow."""
  68. existing_credentials = storage.get()
  69. if existing_credentials and not existing_credentials.invalid:
  70. return existing_credentials
  71. else:
  72. return _get_credentials_interactively(flow, storage, get_code_callback)
  73. def get_resource(client_secrets_file, credentials_file, get_code_callback=None):
  74. """Authenticate and return a googleapiclient.discovery.Resource object."""
  75. get_flow = oauth2client.client.flow_from_clientsecrets
  76. flow = get_flow(client_secrets_file, scope=YOUTUBE_UPLOAD_SCOPE)
  77. storage = oauth2client.file.Storage(credentials_file)
  78. get_code = get_code_callback or _get_code_from_prompt
  79. credentials = _get_credentials(flow, storage, get_code)
  80. if credentials:
  81. http = credentials.authorize(httplib2.Http())
  82. return googleapiclient.discovery.build("youtube", "v3", http=http)