6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GoogleAppScriptでPhoto Library APIを使用してアルバム一覧をSpreadsheetに書き出す

Posted at

1. OAuth認証ライブラリを追加する

1-1. OAuth2ライブラリにProject追加

Google Photo APIは基本的に認証にOAuthを用いています。

Oauthについてはこちらの記事が分かりやすいと思います。
https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be

まずはOAuthをGASで簡単に使えるように「OAuth2 for Apps Script」をプロジェクトに追加しましょう。

1.メニューの「リソース > ライブラリ」を選択
スクリーンショット 2020-02-21 15.11.38.png

2.ID「1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF」を入力して「追加」を押す(バージョンは最新のものを選択)
スクリーンショット 2020-02-21 15.13.43.png

3.「保存」を押してダイアログを閉じる

2.Photos Library APIの有効化

2.1 Google Cloud PlatformでProjectを新規作成

2.2 APIを有効化

スクリーンショット 2020-02-21 16.31.13.png スクリーンショット 2020-02-21 16.32.03.png

2.3 Oauthの認証情報を追加する

「認証情報 > OAuthクライアントID」を選択

スクリーンショット 2020-02-21 16.49.27.png

認証情報を登録する

スクリーンショット 2020-02-21 16.51.23.png

①ウェブアプリケーションを選択

②承認済みのJavaScript 生成元

https://script.google.com

③承認済みのリダイレクトURI

https://script.google.com/macros/d/スクリプトID/usercallback
スクリプトIDはスクリプトエディターにて「ファイル > プロジェクトのプロパティー」から確認できます。
スクリーンショット 2020-02-21 16.37.02.png

2.4 クライアントIDとクライアントシークレットを控える

クライアントIDとクライアントシークレットは控えておきます
スクリーンショット 2020-02-21 16.42.26.png

3.認証部分のGASを記述する

3.1 Spreadsheet上にボタンを作成する

アルバム一覧を取得、認証をリセットするという2つのボタンを用意します。

main.gas
//スプレッドシートを開いた時に呼ばれる関数
function onOpen() {
  SpreadsheetApp
  .getUi()
  .createMenu('スクリプト')
  .addItem('アルバム一覧を取得', 'getAlbumInformation')
  .addItem('認証のリセット', 'reset')
  .addToUi()
}

実行結果
スクリーンショット 2020-02-22 14.36.15.png

3.2 OAuth認証の確認

OAuth認証が通っているかどうかの確認をします。
もし通っていなかったら認証画面を出力します。

3.2.1 認証HTMLファイルの作成

スクリーンショット 2020-02-22 14.41.30.png
template.html
<!DOCTYPE html>
<html>
  <head>
    <style>
      center {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
      }
      center > b > a {
        text-decoration: none;
        color: aliceblue;
        background-color: cadetblue;
        padding: 30px;
        border-radius: 15px;
      }
    </style>
    <base target="_top">
  </head>
  <body style="margin: 0;">
    
  </body>
</html>

3.2.2 認証部分の作成

main.gs
//PhotoLibrary用定数
var baseUrl = 'https://photoslibrary.googleapis.com/v1/albums'
var accessToken = ''

//認証用各種変数
var tokenurl = "https://accounts.google.com/o/oauth2/token"
var authurl = "https://accounts.google.com/o/oauth2/auth"
var clientid =    '〇〇〇〇';// 先程作成したclientIdを用いる
var clientsecret= '〇〇〇〇';// 先程作成したclientsecretを用いる
var scope = "https://www.googleapis.com/auth/photoslibrary"// 使いたいAPIによって変える

//共通定数
var currentSpreadheet = SpreadsheetApp.getActive();

// ボタンを押した時に呼ばれる関数
function getAlbumInformation() {
  var ui = SpreadsheetApp.getUi()
  
  //1. 認証の確認
  var service = checkOAuth()
  if (!service.hasAccess()) {
    //認証画面を出力
    var output = HtmlService.createHtmlOutputFromFile('template').setHeight(310).setWidth(500).append(authpage()).setSandboxMode(HtmlService.SandboxMode.IFRAME)
    ui.showModalDialog(output, 'OAuth2.0認証')
  } else {
    //2. 認証されている場合、Albumを取得する
    getAllAlbums() //後ほど記述します。
  }
}

//アクセストークンURLを含んだHTMLを返す関数
function authpage(){
  var service = checkOAuth();
  var authorizationUrl = service.getAuthorizationUrl();
  var html = "<center><b><a href='" + authorizationUrl + "' target='_blank' onclick='closeMe();'>アクセス承認</a></b></center>"
  return html;
}

//認証チェック
function checkOAuth() {
  return OAuth2.createService("PhotosAPI")
    .setAuthorizationBaseUrl(authurl)
    .setTokenUrl(tokenurl)
    .setClientId(clientid)
    .setClientSecret(clientsecret)
    .setCallbackFunction("authCallback") //認証を受けたら受け取る関数を指定する
    .setPropertyStore(PropertiesService.getScriptProperties())  //スクリプトプロパティに保存する
    .setScope(scope)
    .setParam('login_hint', Session.getActiveUser().getEmail())
    .setParam('access_type', 'offline')
    .setParam('approval_prompt', 'force');
}
 
//認証コールバック
function authCallback(request) {
  var service = checkOAuth();
  var isAuthorized = service.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput("認証に成功しました。ページを閉じて再度実行ボタンを押してください");
  } else {
    return HtmlService.createHtmlOutput("認証に失敗しました。再度お試しください");
  }
}
 

この段階でボタンを押すと次のような認証ボタンが出てきます。
スクリーンショット 2020-02-22 14.50.36.png

ここでアクセス承認ボタンを押して認証を通すことができます。

4.アルバム範囲を取得するGASを書く

main.gas

//認証が通っている場合呼ばれる関数
function getAllAlbums() {
  // OAuth認証情報を取得
  const service = checkOAuth()
  // Access Tokenを取得
  accessToken = service.getAccessToken()

  //1. アルバム一覧を取得する
  var rawAlbums = getAlbums()
  if (!rawAlbums) {
    return Browser.msgBox('アルバムの取得に失敗しました')
  }
  
  //3.アルバムを二元配列に変換する
  var classAlbums = rawAlbums.map(function(e) {
    // e['title']でアルバムの名前を取得できる
    return [e['title']]
  })
  
  //4.セルに書き出す
  albumSheet.getRange(1, 1, classAlbums.length).setValues(classAlbums)
}

//アルバム一覧を取得する
function getAlbums(){  
  //defalutで20件しか取得できないのでparamaterを設定して50件取得する
  var response = UrlFetchApp.fetch(baseUrl + '?pageSize=50', {
    method: 'GET',
    headers: {
      Authorization: 'Bearer ' + accessToken
    },
    contentType: "application/json",
    muteHttpExceptions: true
  });
  var responseCode = response.getResponseCode()
  // 50件しか取得できない
  if (responseCode === 200) {
    var result = JSON.parse(response.getContentText())
    return result['albums']
  } else {
    return null
  }
  
}

以上でアルバムの名前をシートに書き出すことができました!

まとめ

main.gas

//PhotoLibrary用定数
var baseUrl = 'https://photoslibrary.googleapis.com/v1/albums'
var accessToken = ''

//認証用各種変数
var tokenurl = "https://accounts.google.com/o/oauth2/token"
var authurl = "https://accounts.google.com/o/oauth2/auth"
var clientid =    '〇〇〇〇';// 先程作成したclientIdを用いる
var clientsecret= '〇〇〇〇';// 先程作成したclientsecretを用いる
var scope = "https://www.googleapis.com/auth/photoslibrary"// 使いたいAPIによって変える

//共通定数
var currentSpreadheet = SpreadsheetApp.getActive();

// ボタンを押した時に呼ばれる関数
function getAlbumInformation() {
  var ui = SpreadsheetApp.getUi()

  //1. 認証の確認
  var service = checkOAuth()
  if (!service.hasAccess()) {
    //認証画面を出力
    var output = HtmlService.createHtmlOutputFromFile('template').setHeight(310).setWidth(500).append(authpage()).setSandboxMode(HtmlService.SandboxMode.IFRAME)
    ui.showModalDialog(output, 'OAuth2.0認証')
  } else {
    //2. 認証されている場合、Albumを取得する
    getAllAlbums() //後ほど記述します。
  }
}

//アクセストークンURLを含んだHTMLを返す関数
function authpage(){
  var service = checkOAuth();
  var authorizationUrl = service.getAuthorizationUrl();
  var html = "<center><b><a href='" + authorizationUrl + "' target='_blank' onclick='closeMe();'>アクセス承認</a></b></center>"
  return html;
}

//認証チェック
function checkOAuth() {
  return OAuth2.createService("PhotosAPI")
    .setAuthorizationBaseUrl(authurl)
    .setTokenUrl(tokenurl)
    .setClientId(clientid)
    .setClientSecret(clientsecret)
    .setCallbackFunction("authCallback") //認証を受けたら受け取る関数を指定する
    .setPropertyStore(PropertiesService.getScriptProperties())  //スクリプトプロパティに保存する
    .setScope(scope)
    .setParam('login_hint', Session.getActiveUser().getEmail())
    .setParam('access_type', 'offline')
    .setParam('approval_prompt', 'force');
}

//認証コールバック
function authCallback(request) {
  var service = checkOAuth();
  var isAuthorized = service.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput("認証に成功しました。ページを閉じて再度実行ボタンを押してください");
  } else {
    return HtmlService.createHtmlOutput("認証に失敗しました。再度お試しください");
  }
}


function getAllAlbums() {
  // OAuth認証情報を取得
  const service = checkOAuth()
  // Access Tokenを取得
  accessToken = service.getAccessToken()

  //1. アルバム一覧を取得する
  var rawAlbums = getAlbums()
  if (!rawAlbums) {
    return Browser.msgBox('アルバムの取得に失敗しました')
  }
  
  //3.アルバムを二元配列に変換する
  var classAlbums = rawAlbums.map(function(e) {
    // e['title']でアルバムの名前を取得できる
    return [e['title']]
  })
  
  //4.セルに書き出す
  albumSheet.getRange(1, 1, classAlbums.length).setValues(classAlbums)
}

//アルバム一覧を取得する
function getAlbums(){  
  //defalutで20件しか取得できないのでparamaterを設定して50件取得する
  var response = UrlFetchApp.fetch(baseUrl + '?pageSize=50', {
    method: 'GET',
    headers: {
      Authorization: 'Bearer ' + accessToken
    },
    contentType: "application/json",
    muteHttpExceptions: true
  });
  var responseCode = response.getResponseCode()
  // 50件しか取得できない
  if (responseCode === 200) {
    var result = JSON.parse(response.getContentText())
    return result['albums']
  } else {
    return null
  }
  
}
template.html
<!DOCTYPE html>
<html>
  <head>
    <style>
      center {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
      }
      center > b > a {
        text-decoration: none;
        color: aliceblue;
        background-color: cadetblue;
        padding: 30px;
        border-radius: 15px;
      }
    </style>
    <base target="_top">
  </head>
  <body style="margin: 0;">

  </body>
</html>
6
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?