flatfisher
google-cloud-jp
Published in
8 min readJan 19, 2019

--

FunctionsとSchedulerを使ってSlackにアップロードした画像をGoogle Photos のアルバムに保存してみる

本業や趣味でGCP, Actions on Google, Androidなどを触っている fish です🐟
今回はCloud Functions と Cloud Schedulerを使って、Slackにアップロードした画像をGoogle Photosのアルバムに保存するサンプルの紹介をしたいと思います。

このサンプルは Firebase Meetup #9 Cloud Functions Day でお話した「Cloud Functions と Cloud Scheduler で作るお手軽バッチ処理」と同じ内容となります。登壇ではお話できなかった実装の方法を紹介したいと思います。

大体のながれ

  • Cloud Functions から Slack APIを叩いてSlackにアップロードしている画像を取得
  • 画像をGoogle Photos APIを使いGoogle Photosのアルバムにアップロード
  • Cloud SchedulerとCloud Pub/Subを使用しCloud Functionsを定期実行
※Cloud FirestoreによるID管理は割愛します

使用技術

  • Slack API
  • Google Photos API
  • OAuth 2.0 to Access Google APIs
  • Google Cloud Scheduler
  • Google Cloud Pub/Sub
  • Cloud Functions for Firebase

実装の流れ

  • Google Photos APIの準備
  • Slack API で使用する TokenとChannel ID を取得
  • サンプルアプリの実装とデプロイ
  • Functionsの実行

Google Photos APIの準備

こちらを参考にGoogle Photos API の有効化とサービスアカウントを作成し認証に必要なAPI Key を取得する。コマンドラインを開き下記の環境変数を作成する。今回はGoogle Photosのアルバムに書き込み行いたいのでScopeには photoslibrary を指定する。

$ CLIENT_ID=取得したclient id
$ CLIENT_SECRET=取得したclient secret
$ REDIRECT_URI=urn:ietf:wg:oauth:2.0:oob
$ SCOPE=https://www.googleapis.com/auth/photoslibrary

Google Photosのアルバムに書き込みを許可するための認証ページにアクセスする。ブラウザから下記のURLにアクセス。アクセスすると認証ページが書き込みをしたいアカウントを選択し許可する。許可したあとに表示されるコードをコピーする。

https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=$SCOPE&access_type=offline

取得したコードを環境変数に保存する。

$ AUTHORIZATION_CODE=取得したコードを入れる

Google PhotosへアクセスするためのTokenを取得する。なおこちらのTokenは1時間で有効期限が切れるので切れたらRefresh Tokenを使い新しいTokenを取得する。

$ curl -s --data "code=$AUTHORIZATION_CODE" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "redirect_uri=$REDIRECT_URI" --data "grant_type=authorization_code" --data "access_type=offline" https://www.googleapis.com/oauth2/v4/token// 結果
{
"access_token": "xxx",
"expires_in": 3600,
"refresh_token": "abcdef",
"scope": "https://www.googleapis.com/auth/photoslibrary",
"token_type": "Bearer"
}
// Tokenの保存
$ ACCESS_TOKEN=xxxxxxxx
$ REFRESH_TOKEN=abcdef
// 有効期限がきれたら下記のコマンドで再取得
$ curl -s --data "refresh_token=$REFRESH_TOKEN" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token

APIからアルバムを作成しアルバムIDを取得する。

$ curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-type: application/json" -d '{ "album": { "title":"slack_photos" } }' https://photoslibrary.googleapis.com/v1/albums{
"id": "xxxx", //アルバムIDを控えておく
"title": "slack_photos",
"productUrl": "",
"isWriteable": true
}

今回のサンプルでは client_id, client_secret, refresh_token, album_idの4つを使用します。

Slack API で使用する TokenとChannel ID を取得

今回のサンプルでは TokenとChannel IDを使用します。

サンプルアプリの実装とデプロイ

こちらからサンプルアプリをCloneします。このサンプルアプリにあるFirebaseの設定ファイルにご自身の設定を入れます。

下記コマンドで、client_id, client_secret, refresh_token, album_id, SlackのTokenとChannel IDをFirebase Functionsの環境変数に設定します。

$ firebase functions:config:set slack.token=""
$ firebase functions:config:set slack.channel=""
$ firebase functions:config:set google.refresh_token=""
$ firebase functions:config:set google.client_id=""
$ firebase functions:config:set google.client_secret=""
$ firebase functions:config:set photos.album_id=""
$ firebase deploy --only functions

下記コマンドでデプロイをします。このFunctionsはCloud Pub/Sub のトピックに slack-to-googlephotos が作成されると実行されます。

$ npm run deploy

Functionsの実行

Cloud Schedulerを使って定期実行する。

$ gcloud beta scheduler jobs create pubsub Saver --schedule "0 */3 * * *" --time-zone Asia/Tokyo --description "Upload photo to GooglePhotos" --topic slack-to-googlephotos --message-body "{"count":1}"

Cloud Schedulerの設定について詳しく知りたい場合は こちら をご参照ください。

定期実行ではなく1回だけ実行したい場合は直接Pub/Subのトピックを作成します。

$ gcloud pubsub topics publish slack-to-googlephotos --message "{"count":1}"

Functionsを実行しGoogle Photosのアルバムに画像がアップロードされたら成功です。

このサンプルの注意事項

  • 今回のサンプルではファイル一覧結果の1ファイルのみアップロード対象にしています
  • 画像以外のアップロードには対応していません
  • Google Photos API を通じてアップロードした画像はオリジナルクオリティになるのでGoogle PhotosやGoogle Driveの料金プラン(容量制限)にご注意ください

--

--