アドベントカレンダー18日目の編集後記(Google DriveAPIでのHTMLファイル作成、GAEでのOAuth認証とコールバック実装 等)

アドベントカレンダーのネタ向け調査のまとめ、今回は18日目のネタの編集後記(リンク多め)となります。
GoogleAppEngine(以下、GAE)からGoogleドライブ形式以外のファイルを作成できたのが、大きな収穫でした。
GoogleDriveAPIでHTMLファイルを作成し、GoogleドライブでWebサイト公開してアルクマを追いかける - メモ的な思考的な





GoogleDriveのアイコンなど

以下よりダウンロードできます。
https://developers.google.com/academy/apis/drive/drive-apps/distribute/badge?hl=ja



Google Driveをプログラムから扱うには

Google DriveSDKとDriveAPIの2つの方法があり、使用する方をAPI ConsleにてONにする必要があります。
今回のGAEではGoogle DriveAPIを使います*1
Google DriveAPIのドキュメントについては、Google Drive SDKの中の「API Reference」以下のようです。
API Reference - Google Drive SDK — Google Developers


なお、今回はGoogleCalendarAPIも使用するため、API ConsoleでそのAPIもONにする必要があります。Offのままの場合、以下のエラーメッセージが出ます。

HttpError: /events?alt=json returned "Access Not Configured">

GAEにて、Google DriveAPIを用いてファイルを作成する方法

以下の前提で、DriveAPIでファイルを作成する方法を探してみました。

  • 作成するのはHTMLファイル (通常のGoogleドライブの形式とは異なる)
  • HTMLファイルの元データを文字列として作成→Googleドライブへアップロード (ローカルへファイルの保存は行わない)
  • APIへのアクセスはGAE用ライブラリ「google-api-python-client-gae-1.0.zip」を使う


公式ドキュメントを読んでもさらっと記載されているだけでした。
Media Upload - Google APIs Client Library for Python — Google Developers


一方、stackoverflowには「Google APIs Client Library for Python」ライブラリの「MediaInMemoryUpload()」を使う実装例がありましたので、参考にして実装しました。
Google Drive API V2 , Python — create new file without uploading new file and without using Google Drive UI - Stack Overflow


ライブラリの公式ドキュメントは以下のところにあります。リンク先のPyDocにて使い方などが記載されています。
https://developers.google.com/api-client-library/python/reference/supported_apis



GoogleAppEngineでライブラリを使った場合のOAuthについて

コールバック用URLについては、上記のGAE用ライブラリを使った場合、「/oauth2callback」で決め打ちとなります。
認証やコールバックについては、以下を参考にしました。


なお、OAuth認証の方法は2種類あるようですが、今回は自分のアカウントにあるGoogleドライブやGoogleカレンダーを扱ったため、「OAuth2Decorator」で作成しています。
Using Google App Engine - Google APIs Client Library for Python — Google Developers


実際には以下を組み込みました。

app.yaml

handlersとして、「/oauth2callback」と「OAuth付で処理を行うURL」の2種類を記載します。
なお、後者については、コールバック時のパラメータがついてくるので、「.*」のような記載としました。

handlers:
- url: /oauth2callback
  script: googledrivehandler.app
  login: admin

- url: /cron/googledrive.*
  script: googledrivehandler.app
  login: admin
googledrivehandler.py

1. グローバルな変数を用意します。
scopeが複数ある場合は、リストで指定しておくことで両方とも動作するようになります。

OAUTH_SCOPE = ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/calendar']
decorator = OAuth2Decorator(
        client_id=apiKeys['client_id'],
        client_secret=apiKeys['client_secret'],
        scope=OAUTH_SCOPE,
        )

2. URLのルーティングに、「decorator.callback_path, decorator.callback_handler()」を設定します。

app = webapp2.WSGIApplication([
                               ('/cron/googledrive', GoogleDriveHandler),
                               (decorator.callback_path, decorator.callback_handler()),
                              ],
                              debug=debug)


3. webapp2のgetメソッドにてデコレータを使います。

@decorator.oauth_required
def get(self):
    # Googleカレンダーから抽出
    events = self.create_events_from_calendar()

    # Googleドライブへファイルを作成
    self.create_google_dirve_file(events)


4. OAuthを使うところで、「decorator.http()」を渡します。

def create_google_dirve_file(self, events):
    drive_service = build('drive', 'v2', http=decorator.http())


以上により、OAuth認証付でうまいこと処理してくれます。



公式ドキュメント

  • ファイルの操作

 Files - Google Drive SDK — Google Developers

  • insertに関する公式ドキュメント。テストもできます。

 Files: insert - Google Drive SDK — Google Developers



参考:API Explorer

GoogleAPIのまとめです。実際にAPIのテストもできるので、便利かもしれません。
Google APIs Explorer




参考:他の言語でGoogle DriveAPIを使う例

言語はRubyですが、書き方などが参考になりました。

参考:GoogleドライブでClickOnceアプリを配布することができるか

試してみるのも面白いかもしれません。
.net - Can Google Drive web pages host ClickOnce applications? - Stack Overflow

*1:当初、SDKの方だけをONにしていて、動作せずに悩みました