Google Apps - 通知メールを飛ばさずにGoogle Driveフォルダに権限追加する方法

SpreadsheetAppクラスで取得したspreadsheetに対してaddEditor(*email*)とやっても通知メールは飛ばないのですが、DriveAppクラスで取得したspreadsheetやfolderでそれをやると、例の「編集へのご招待」や「共同作業への〜」という通知メールが飛んでしまいます。

フォルダの操作だとDriveAppクラスを使うしかないので通知メールを避けられないのですが、なんとか通知無しでフォルダに権限を付与したいなぁ、というシーンに出くわしまして、Stack OverflowやGoogle Developersを調べて上手くできたので共有したいと思います。

# 権限付与の基本
## DriveAppクラスとSpreadsheetAppクラスの違い

Google Appsのファイルやフォルダへの権限付与/削除（および移動）にはいくつか注意点があります。

- DriveAppクラスで取得したファイル（spreadsheet）にSpreadsheetAppクラスのaddEditor()は使用できない（逆もまたしかり）
- from ~ to ~ での移動や付け替えはなく、add\*\*\*()とremove\*\*\*()をそれぞれ行う必要がある

そして本記事で取り上げている、

- spreadsheetAppクラスでは通知メールが飛ばないが、DriveAppクラスでは通知メールが飛ぶ

といったところでしょうか。

## SpreadsheetAppクラスでの権限付与

処理するスプレッドシートが初めから明確にわかっている場合は、シンプルにSpreadsheetAppクラスを使用するのがいいでしょう。

```test01.js
function Spreadsheet_addEditor() {

  var ss = SpreadsheetApp.openById("*****************");   //URLのhttps://docs.google.com/spreadsheets/d/*****************/editのアスタリスク部分がID
  ss.addEditor("hoge@hoge.com");   //権限を付与したいユーザ、配列で複数指定も可能

}
```

## DriveAppクラスでの権限付与

プログラムの中で、フォルダ内の特定のスプレッドシートを特定してファイルを取得するところまでは、DriveAppクラスで処理するしかありません。（詳しくは[Google Apps Script 実践メモ（Googleドライブ）](http://qiita.com/nurburg/items/28883e0d8e0ee4a6ca6f)をご参考ください）

ここで、手っ取り早く通知メールを飛ばさずに処理する簡単な方法としては、DriveAppクラスで取得したIDを用いてSpreadsheetAppクラスでファイルを再取得してから、SpreadsheetAppクラスで処理するやり方があります。
しかし、それは "スプレッドシートだからSpreadsheetAppクラスで処理できているだけ" なので、フォルダなどに対して通知メール無しで権限付与する場合はやはり困ることになります。

話がそれましたが、とりあえずDriveAppクラスで上と同じ権限付与を書くなら以下のようになります。

```test02.js
function Drive_addEditor() {

  var ss = DriveApp.getFileById("*****************");
  ss.addEditor("hoge@hoge.com");

}
```

そして、この方法では通知メールが飛んでしまうので別の方法を探る、ということでいよいよ本題に入ります。

# Apps Script を使わず Google Drive をWebから使う

## 結論を先に

Google Apps Scriptで用意されているDriveAppクラスのaddEditor()というAPIは、前述の通り通知メールが自動的に飛んでしまいますが、別途用意されているGoogle DriveのAPIを利用すると、通知メールを飛ばす/飛ばさないが指定できるのです。

## 二つのAPIの違いは何か

Google Apps Scriptは、いわゆるGoogle Appsとして提供されているGmailやCalendar、Spreadsheet、Form、Docs、Driveなどの各アプリに簡単にアドオンプログラムを実装することができる開発環境およびAPI群です。

そして一方で、Google Driveのサービス単体としてもAndroidやiOS、Webアプリで利用できるようAPIが用意されており、Google Apps Scriptとはまったく仕組みの異なるAPI群がGoogle Drive APIとして提供されているのです。

今回は、その内のWebアプリ用である[Google Drive REST API](https://developers.google.com/drive/web/about-sdk)を、Google Apps Scriptで実装したプログラムから利用することになります。（Google Apps自体はWebアプリですからね）

## 書き方

前述のGoogle Drive REST APIのページに、様々な環境（言語）での使い方が載っているのですが、Google Apps Scriptもその環境の一つとして[使い方](https://developers.google.com/drive/web/quickstart/apps-script?hl=ja-AU)が載っています。

ポイントは、Advanced Google Services（拡張サービス）から目的のDrive APIを有効にしてから利用する、です。ではさっそくみていきましょう。

### Step1.コード

こんな感じで書きます。

```test03.js
function DrivePermissionInsert(){

  Drive.Permissions.insert(
    {
      'role': 'writer',                   //"編集者"として追加するよ
      'type': 'user',                     //"ユーザー"を追加するよ
      'value': "hoge@hoge.com",           //配列での指定も可能←←間違いのようです。訂正します[2016.2.9]
    },
    '*****************',                  //対象となるスプレッドシート（やフォルダ）のIDを指定します
    {
      'sendNotificationEmails': 'false'   //★ココ!★"false"にすると通知メールが飛びません
    }
  );
 
}
```

しかし、このまま普通に実行しようとしても、次のようなエラーが出ると思います。

![ReferncesError: 「Drive」が定義されていません。](https://qiita-image-store.s3.amazonaws.com/0/49702/d3b33c96-487d-055f-70a3-202fdbc40b74.png)

これは、Step2.で説明する"Drive"APIが有効になっていないから、「そんなAPI（ライブラリ）は存在しねーよ」といわれています。

### Step2.Drive APIを有効にする

1.. Scriptエディタを開いて、メニューから「リソース > Googleの拡張サービス」を選択

![Googleの拡張サービス](https://qiita-image-store.s3.amazonaws.com/0/49702/b0f2724c-7139-326f-ec7f-6ffe86195b08.png)

2.. Googleの拡張サービスの設定画面で、Drive APIを「ON」にします。

![Drive API ON](https://qiita-image-store.s3.amazonaws.com/0/49702/549d38cf-1e20-d1ce-5018-381b35365cce.png)

3.. 続いてGoogleデベロッパーコンソールでもDrive APIを有効にしにいきましょう。
ポップアップのリンクを押すと、自動的に今書いているスクリプトが現在関連付けられているプロジェクトの画面に飛びます。
"Drive API"を検索いただいても結構ですし、画面上に表示されているリンクを押してもOKです。
![Developer Console](https://qiita-image-store.s3.amazonaws.com/0/49702/c6a746ac-d9d5-2c72-011f-1c6d6366d987.png)

4.. 次の画面で「APIを有効にする」を押してください。（スクリーンショットは押す前の状態）
![Drive API APIを有効にする](https://qiita-image-store.s3.amazonaws.com/0/49702/b867dae5-c0fe-4bff-b8f6-445f2b6dfd6a.png)

さぁ、これで準備はOKです。

### Step3. いざ実行！

ということで、特に何も書くことないですが、通知メールなしで権限が付与されているのが確認できると思います。

念のため、以下のように"true"にすると通知メールが飛びますのでぜひ試してみてください。

```
      'sendNotificationEmails': 'true'   //★ココ!★"true"にすると通知メールが飛びます
```

# さいごに
いかがでしたでしょうか。
これで、特定（かつ大量の）メンバーを閲覧者に設定したり/外したり、事前に個別の権限がついた個々人用のフォルダをこっそり作っておいてタイミングをはかってご案内する、というようなことができるようになると思います。

また、私はこのDrive REST APIを使って、フォルダ・ファイルの権限の一括付与・削除などのツールも作ったりしています。
そして、他チームの普通のスキルのスタッフさんがデモチしながら大量の権限の付与作業をやっているのを見かけた場合は、嫌味にならないように、また「自分が数十分かけていた作業が1分で戻って来る」というあまりの衝撃でさらに本人がデモチしないよう、変な気を遣いながら、自分の作ったツールを提供してあげてます。。 :relaxed: 

# Appendix

- プロジェクトの確認は、メニュー「リソース > Developers Console プロジェクト」から確認できます
![Developers Console プロジェクト](https://qiita-image-store.s3.amazonaws.com/0/49702/1141155f-f21d-e727-7c27-69ac6941e2ee.png)

- Step2.の(3)には、プロジェクトのリンクを押せば飛べます
![Developers Console](https://qiita-image-store.s3.amazonaws.com/0/49702/da167964-ac60-d6ba-70ff-9bf8e1938c04.png)

以上