GASでGCS上のプロジェクトのレポートをダウンロードする

# はじめに
Google Play Consoleの1日のインストール数のレポートを自動で取得しようと考えたのがきっかけです。GASを選んだ理由ですが、定期実行するのに都合がいいのと、Google関連のサービスだから簡単に終わるだろと算段をつけたからです。蓋を開けてみればあまり参考にできるものが見当たらず手探りで進めたものの記録を残します。
完全自動でアクセスしたいため、サービスアカウントを使用します。[ドキュメント](https://support.google.com/googleplay/android-developer/answer/6135870?visit_id=638467820063938540-3750614565&p=stats_export&rd=1#export&zippy=%2C%E4%BE%8Bpython%2C%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%95%B0%2C%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88-%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%A8%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9-%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88%E3%82%92%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E3%81%99%E3%82%8B)を参考に進めます。

# Step1.サービスアカウントを作成する

1. [Google Developers Console](https://console.developers.google.com/)を開き、プロジェクトを選択する
1. 左上の![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629819/09575562-ad0f-4ac5-98b9-a8f863d65017.png) > [IAMと管理] > [サービスアカウント] > [サービスアカウントを作成]を選択します![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629819/7f0fb24d-ab13-1407-ac20-ccbcafc9cca9.png)


1. サービスアカウント名・サービスアカウントの説明を入力し、[作成] を選択します
1. アカウント情報が書かれたjsonがダウンロードされるので、安全な場所に保存します

1. 表示されたメールアドレスをコピーします
例: accountName@project.iam.gserviceaccount.com

# Step2.Google Play Console にサービス アカウントを追加する
1. [Google Play Console](https://play.google.com/apps/publish/) を開きます
1. 左上の![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629819/09575562-ad0f-4ac5-98b9-a8f863d65017.png) > [ユーザーと権限] > [新しいユーザーを招待] を選択します
1. メールアドレスに先ほどコピーしたメールアドレスを貼り付けます
1. [アプリの権限]でレポートを取得したいプロジェクトを選択します
1. [アカウントの権限]で
[アプリ情報の閲覧、一括レポートのダウンロード（読み取り専用）]を選択します
1. [ユーザーを追加] をクリックします


# Step3.API 呼び出しを使用してレポートを取得する
1. GASでOauth2を行うためのライブラリを追加します。現在のIDは`1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF`ですが、変更される可能性もあるので[GitHub](https://github.com/googleworkspace/apps-script-oauth2)で確認してください

1. [サンプル](https://github.com/googleworkspace/apps-script-oauth2/blob/master/samples/GoogleServiceAccount.gs)を参考に、（https://www.googleapis.com/auth/devstorage.read_only )への権限を要求する関数を作成します
   
    ```javascript
    function getService_() {
      return OAuth2.createService('GCS')
          .setTokenUrl('https://oauth2.googleapis.com/token')
          .setPrivateKey(PRIVATE_KEY_GCS)
          .setIssuer(CLIENT_EMAIL_GCS)
          .setPropertyStore(PropertiesService.getScriptProperties())       
          .setScope('https://www.googleapis.com/auth/devstorage.read_only');
    }
    ```
    `PRIVATE_KEY`と`CLIENT_EMAIL`は、Step1でダウンロードしたものです。

1. 同様にサンプルを参考に、レポートをダウンロードする関数を作成します
    ```javascript
    function run() {
      var service = getService_();
      if (service.hasAccess()) {
        var url = `https://storage.googleapis.com/${BUCKET}/${OBJECT}`
        var response = UrlFetchApp.fetch(url, {
          headers: {
            Authorization: 'Bearer ' + service.getAccessToken(),
          },
          method:"GET"
        });
        //responseを出力。utf-16であることに注意
        var content = response.getBlob()
        var csvContent = content.getDataAsString("UTF-16")
        var csvData = Utilities.parseCsv(csvContent);//二次元配列に変換
        Logger.log(csvData)
    
      } else {
        Logger.log(service.getLastError());
      }
    }
    
    ```
    `BUCKET`は`pubsite_prod_xxx~`という形式です。[Google Play Console](https://play.google.com/apps/publish/)の[レポートのダウンロード] > [任意のレポートの種類] > [Cloud Storage URIをコピー]から確認できます。
    `OBJECT`は入手したいレポートのパスです。[ドキュメントのレポートのコマンドとファイル形式](https://support.google.com/googleplay/android-developer/answer/6135870?visit_id=638467820063938540-3750614565&p=stats_export&rd=1#export&zippy=%2C%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88-%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%A8%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9-%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88%E3%82%92%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E3%81%99%E3%82%8B:~:text=%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82-,%E8%A9%B3%E7%B4%B0%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88%E3%81%AE%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A8%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%BD%A2%E5%BC%8F,-%E3%82%AF%E3%83%A9%E3%83%83%E3%82%B7%E3%83%A5%E3%81%A8%20ANR)から確認できます。
    例えばインストール数では以下のように記載されています。`stats/installs/installs_[package_name]_yyyyMM_[dimension].csv`が`OBJECT`に該当し、`developer_bucket_id`は`BUCKET`のことです。
    ![スクリーンショット 2024-03-24 22.50.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629819/c0bf6f89-aaa9-316a-da84-1fa6c6c73ee1.png)
    `package_name`は`com.my.app`の形式です。Google Play Consoleで確認することができます。
    `dimention`は先ほどのドキュメントにも書いてありますが、Google Play Consoleに表示されているものの方が種類が多いようです。一度手動でレポートをダウンロードし、`dimension`を確認して指定するといいです。

:::note warn
スクリプトを実行した際に、権限がない旨のエラーが返ってくる可能性があります。
筆者は翌日同じ環境、スクリプトで実行したところエラーが解消されたため、Google Play Consoleの設定反映に時間がかかるのかもと推測しています。
私はこのエラーで数時間溶かしましたが、同様の状況になった方は大人しく待ってみることをお勧めします。
:::

# まとめ
実際に完成したコードはこちらです。用途に合わせてGoogleDriveに保存するなど、処理を加えることになると思います。
```javascript
function run() {
  var service = getService_();
  if (service.hasAccess()) {
    var url = `https://storage.googleapis.com/${BUCKET}/${OBJECT}`
    var response = UrlFetchApp.fetch(url, {
      headers: {
        Authorization: 'Bearer ' + service.getAccessToken(),
      },
      method:"GET"
    });
    //responseを出力。utf-16であることに注意
    var content = response.getBlob()
    var csvContent = content.getDataAsString("UTF-16")
    var csvData = Utilities.parseCsv(csvContent);//二次元配列に変換
    Logger.log(csvData)

  } else {
    Logger.log(service.getLastError());
  }
}

function getService_() {
  return OAuth2.createService('GCS')
      .setTokenUrl('https://oauth2.googleapis.com/token')
      .setPrivateKey(PRIVATE_KEY_GCS)
      .setIssuer(CLIENT_EMAIL_GCS)
      .setPropertyStore(PropertiesService.getScriptProperties())
      .setScope('https://www.googleapis.com/auth/devstorage.read_only');
}
```