今さらGmail AddOnを作ってみるよ。添付ファイルを選んでGoogleDriveのフォルダに入れるやーつ。

こんにちは。:relaxed:だよ。
夏休みが終わったね。開発が楽しくて楽しくて仕方がなかったよね。


さて、今日はタイトル通り、GoogleのAdd-onsを使ってみたので紹介するよー。
>[Gmail add-ons](https://developers.google.com/gsuite/add-ons/concepts/types#gmail_add-ons)


###どんなことができるAddOnを作るの？
Gmailで添付が送られてきたらGoogleDriveに格納したいよね。
でも、現在の仕様だとダウンロードの方法は、個々or一括で、
場所のデフォルト指定もできないので、マイドライブ直下において、その後、整理するしかないよね。
でもたくさんファイルが送られてきたら、その場で必要なファイルを分類しながらフォルダに格納したいよね。
:relaxed: はしたいよ。なので作ったよ。

###まずはAddOnのお勉強。公式のQuickStartをやってみるよ。
[猫ちゃんのQuickStart](https://developers.google.com/gsuite/add-ons/cats-quickstart)

手順は公式にある通りだけれど、ここでもやってみるよ。

1. [GoogleAppsScript](https://script.google.com/home)にて新しいプロジェクトを作る。
プロジェクト名はお好きな名前にしてね。（今回はCuteCatQuickStart）


2. 必要なスクリプトファイルを作っていくよ。デフォルトでできる、Code.gsはRenameで名前を変更してね。
Common.gs, Gmail.gs, Drive.gs, Calendar.gsの４ファイルを作るよ。
スクリプトファイルの作り方は「ファイル」→「New」→「スクリプトファイル」だよ。
![スクリーンショット 2020-08-22 11.39.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/614f8301-a832-3dff-81b3-8614d46ed33e.png)

3. 各シートに公式のコードをコピーしていくよ。
![スクリーンショット 2020-08-22 11.42.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/4edc3968-b78e-e9b1-8091-e2ccbbea4c24.png)


4.　マニフェストファイルを編集するよ。
「表示」→「マニフェストファイルを表示」でappsscript.jsonを表示するよ。
公式のサンプルをコピペするよ。

これでコードの準備はOK！　簡単だね！

5.　非公開でアドオンをインストールする。
「公開」→「マニフェストから配置」を選択するよ。
画像のようなページが表示されるから、「アドオンをインストール」をクリック。
![スクリーンショット 2020-08-22 11.57.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/fed29fd8-7ce4-fba7-eff5-4c5426ec84f2.png)


6.　アドオンを使用するために、認証をするよ。
Gmail、Drive、カレンダーどれでもOKなので、開いてみよう。
可愛い肉球が追加されているのが分かるね。

![スクリーンショット 2020-08-22 12.00.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/f4e46a7c-be54-d3d4-b3de-0effba968f5a.png)

クリックすると、アドオンの認証が出るので、「アクセスを承認」をクリック。

![スクリーンショット 2020-08-22 12.11.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/e57d48ce-f037-6a0f-c2f8-7b900735ae27.png)

危険な感じの警告も出るけれど、自分はよく知っている信頼できるデベロッパーだから続行しようね。
![スクリーンショット 2020-08-22 12.03.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/807a5739-9a98-b8ee-1d42-aa12f7530e4c.png)

リクエストも許可しよう。いっぱい使っているんだねー。
![スクリーンショット 2020-08-22 12.03.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/8f3d3360-4a41-40ff-e1fe-a976fbc1baed.png)



７.　猫ちゃんが表示されることを確認しよう。

Gmailでも猫ちゃん。
![スクリーンショット 2020-08-22 12.04.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/f6459074-18a3-8e72-9344-e0cf30d1057b.png)

ドライブでも猫ちゃん。
![スクリーンショット 2020-08-22 12.05.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/ba481758-de27-b5b0-f170-5c894800d72c.png)

簡単だね。


###添付ファイルをGoogleDriveに保存するAddOnを作っていくよ。
今回のポイントは、
・アップロード先のフォルダを選択できる。
・アップロードする添付ファイルを選べる。
・ユーザーが最後に選んだフォルダがデフォルトセットされる。
の３つだよ。

####【前準備】
１つ目の、フォルダの選択のためには、Driveのフォルダ構成を取得する必要があるよね。
ただ、現状のGASだと、あるフォルダの子フォルダを参照することはできるんだけれど、全ての階層情報を取得することができなかったんだ！そのため、先に、スプレッドシートに階層情報を保存しておき、そこから該当のフォルダを選択するようにしたよ。

フォルダ階層の取得コードはこちらのサイトを参考させていただいたよ。
>[officeの杜: Google Apps Scriptでファイルフォルダの探索](https://officeforest.org/wp/2019/02/02/google-apps-script%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%81%AE%E6%8E%A2%E7%B4%A2/)

ここのサイトの「基準フォルダから下のフォルダ階層をすべてリストアップするコード」を参考にフォルダリストを取得するようにしたよ。
改変したところとしては、フォルダを選ぶときに階層情報を見ながら選びたかったので、
親情報を含めた項目を作ったよ。また、並び変えもしたよ。

![スクリーンショット 2020-08-22 13.17.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/47b7e813-2292-5255-e403-86f1a02a52e5.png)

フォルダ情報をこんな感じで保管したよ。



####【GAS】
今回は、Gmailでだけ作れば良いので、スクリプトファイルの構成は
appsscript.json, common.gs, gmail.gsの３つにしたよ。

```json:appsscript.json
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
    "enabledAdvancedServices": [{
      "userSymbol": "Sheets",
      "serviceId": "sheets",
      "version": "v4"
    }]
  },
  "exceptionLogging": "STACKDRIVER",
  "oauthScopes": [
                  "https://www.googleapis.com/auth/drive.addons.metadata.readonly", 
                  "https://www.googleapis.com/auth/gmail.addons.current.action.compose", 
                  "https://www.googleapis.com/auth/gmail.addons.current.message.readonly", 
                  "https://www.googleapis.com/auth/gmail.addons.execute", 
                  "https://www.googleapis.com/auth/script.locale", 
                  "https://www.googleapis.com/auth/drive",
                  "https://www.googleapis.com/auth/userinfo.email"],
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "My First Addon!",
      "logoUrl": "https://XXXXXXXX",//アイコンのURL
      "useLocaleFromApp": true,
      "homepageTrigger": {
        "runFunction": "onHomepage",　
        "enabled": false　//メールを開いた時だけ、作用するようにする。
      }
    },
    "gmail": {
      "contextualTriggers": [{
        "unconditional": {
        },
        "onTriggerFunction": "onGmailMessageOpen"
      }]
    }
  }
}

```

```javascript:common.gs
function onHomepage(e) {
}

function makeCard(e) {
  
  var accessToken = e.gmail.accessToken;
  GmailApp.setCurrentMessageAccessToken(accessToken);
  var messageId = e.gmail.messageId;
  var message   = GmailApp.getMessageById(messageId);
  var subject   = message.getSubject();
  var sender    = message.getFrom();
  var attachments = message.getAttachments();
    
  
  var mainCard = CardService.newCardBuilder();
  var sectionSettings = CardService.newCardSection();
  mainCard.setHeader(CardService.newCardHeader().setTitle('メッセージの詳細'));
  sectionSettings.addWidget(CardService.newKeyValue()
                 .setTopLabel('Subject')
                 .setContent(subject));
 
  
  // 添付がある場合だけ、保存用のフォルダ選択、アイテム選択、アップロードボタンを表示する。
  if (attachments.length > 0) {
    sectionSettings.addWidget(makeFolderSelect());
    sectionSettings.addWidget(makeAttachSelect(attachments));
    sectionSettings.addWidget(makeUploadButton());
  }
   
  return   mainCard.addSection(sectionSettings).build();

}

/**
** フォルダ選択のWidgetを作る。
**/
function makeFolderSelect(){
  
  var scriptProperties = PropertiesService.getScriptProperties();
  
  var folderSelect = CardService.newSelectionInput()
                    .setType(CardService.SelectionInputType.DROPDOWN)
                    .setTitle("アップロード先を選んでください")
                    .setFieldName("folderSelect");
  
  var rangeName      = 'folderlist!A2:C';
  var values         = Sheets.Spreadsheets.Values.get(scriptProperties.getProperty('SPREADSHEET_ID'), rangeName).values;
  var userProperties = PropertiesService.getUserProperties();
  
  if (!values) {
    Logger.log('No data found.');
  } else {
    
  
    for (var row = 0; row < values.length; row++) {
      
      //そのユーザーに以前選択肢したFolder情報がある場合、それをデフォルト設定する。//
      if (userProperties.getProperty("folderId") == values[row][1]) {
        folderSelect.addItem(values[row][0],values[row][1], true);
      } else {
        folderSelect.addItem(values[row][0],values[row][1], false);
      }
    }
  }
  
  return folderSelect;
}

/**
**添付をチェックボックスで選べるWidgetを作る。
**/
function makeAttachSelect(attachments){

  var attachmentCheckBox = CardService.newSelectionInput()
                          .setType(CardService.SelectionInputType.CHECK_BOX)
                          .setTitle("アップロードする添付を選んでください")
                          .setFieldName("uploadItems");
  
  for (var i = 0; i < attachments.length; i++){
    
    attachmentCheckBox.addItem(attachments[i].getName(),i.toString(), true);
  }

  return attachmentCheckBox;
  
}


/**
**アップロードボタンの Widgetを作る。
**/

function makeUploadButton(){

  var action = CardService.newAction()
              .setFunctionName('onUploadtoDrive')
              .setParameters({});
     
  var button = CardService.newTextButton()
              .setText('Upload to Drive')
              .setOnClickAction(action)
              .setTextButtonStyle(CardService.TextButtonStyle.FILLED);
  var buttonSet = CardService.newButtonSet().addButton(button);

  return buttonSet;

}


/**
** Drive上にアップロードするための処理
**/
function onUploadtoDrive(e) {
  console.log(e);

  
  let accessToken = e.gmail.accessToken
  GmailApp.setCurrentMessageAccessToken(accessToken);
  
  let messageId   = e.messageMetadata.messageId;
  let message     = GmailApp.getMessageById(messageId);
  let attachments = message.getAttachments();
  
  //upload先のFolderを取得する//
  let folder      = DriveApp.getFolderById(e.formInputs.folderSelect);
  
  //選択された添付をアップロードする//
  for (let i=0; i<e.formInputs.uploadItems.length; i++){
    folder.createFile(attachments[e.formInputs.uploadItems[i].toString()]);
  }
  
  //その時選択されていたフォルダーをUserPropertyに保存する/
  var userProperties = PropertiesService.getUserProperties();
  userProperties.setProperty('folderId',e.formInput.folderSelect);
  console.log(userProperties.getProperty('folderId'));
}

```

```javascript:gmail.gs
  
function onGmailMessageOpen(e) {

  return makeCard(e);
}
```




###どんな感じで動くの？
猫ちゃんの時と同じように、アドオンをインストールしてみよう。
今回は、人食いザメのアイコンだよ。[ICOOON MONO](https://icooon-mono.com/)さんからお借りしたよ。

添付があるメッセージを開くと・・


ほい！　一覧が出てきたよー。
![スクリーンショット 2020-08-22 14.09.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/db89fdab-6e1d-bea9-c72b-ae14964c6659.png)


ファイルを選んでーフォルダを選んでー　UPLOAD！！
![スクリーンショット 2020-08-22 14.11.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/d4058e3c-0d0d-73ba-f983-46996056becb.png)

ハイどーん!!!
![スクリーンショット 2020-08-22 14.11.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/607a19f5-7029-0fd2-f328-f9dea4b4f9a4.png)


もういっかい :relaxed: 

ファイルを選んでーフォルダを選んでー　UPLOAD！！
![スクリーンショット 2020-08-22 14.14.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/256986aa-28ee-4477-ea4e-1e68b9f363a3.png)

ハイどーん!!!
![スクリーンショット 2020-08-22 14.14.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482103/ac30f5f2-c674-4105-4807-db100817f1b1.png)



これで誰かから偏愛アルバムの写真を送られてきても、大丈夫だね！
:relaxed: は偏愛音楽多めだよ。
昨今、アーティストの皆さんも厳しいようだけれど、頑張って欲しいな！
アルバムもグッズも応援の気持ちを込めて買っているよ :relaxed:  


##参考にさせていただいたサイト
[Google AddOns](https://developers.google.com/gsuite/add-ons/overview)
[officeの杜さま](https://officeforest.org/wp/2019/02/02/google-apps-script%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%81%AE%E6%8E%A2%E7%B4%A2/)

皆さん本当にありがとうございます。すごくすごく参考にさせていただきました！！