【GAS】Slackのbotを利用してメールアドレスからDMを送る

## はじめに
Google Apps Scriptを用いてSlackAPIを利用したDM送信については記事がいくつかあります。
実際に利用してみるとメールアドレスからIDを検索してDMを送るにはSlack APIを3回叩く必要があるため、一回利用したものはGoogle SpreadSheetでリスト化し、以降はそこからIDを検索して読み出すようにします。

## Slack API用トークンを取得
トークンを取得するまでの流れは他の記事にもあるので紹介しておきます。
[参考：Slack API を使って email から User ID を取得](https://qiita.com/samiii/items/102727d77758c6a0c906)
必要なScopeだけ下記に記載します。
![slack_scopes.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311544/06d830ba-e78d-3f51-410f-9a520c8a7017.png)

## メールアドレスからSlackのユーザIDを取得
他記事を見るとGETリクエストでIDを取得しているものが多いのですが、現在だと[tokenはpostで送ってください](https://api.slack.com/methods/users.lookupByEmail)とあるので、postで送ります(getで送るとinvalid_authでエラーになります)。
SLACK_APP_TOKENには取得したトークンが入ります。
```javascript
//=========================================================================================
// メールアドレスからSlackのユーザIDを戻す
//=========================================================================================
function getSlackIdfromEmail(email) {
  var options = {
    "method": "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload" : {
      "token": SLACK_APP_TOKEN,
      "email":email
    }
  };
  var response = UrlFetchApp.fetch('https://slack.com/api/users.lookupByEmail', options);
  var res = JSON.parse(response);

  if(res.ok){
    return res.user.id;
  }else{
    Logger.log(res);
    return null;
  }
}
```

## ユーザIDからDMのIDを取得
ユーザIDだけではDM送信できないので、DMのチャンネルIDを取得します。

```javascript
//=========================================================================================
// SlackのユーザIDからDM用のIDを戻す
//=========================================================================================
function getChannelID(memberId) {
 
  var options = {
    "method" : "post",
    "contentType": "application/x-www-form-urlencoded",
    "payload" : {
      "token": SLACK_APP_TOKEN,
      "users": memberId
    }
  };
  

  var response = UrlFetchApp.fetch('https://slack.com/api/conversations.open', options);
  var res = JSON.parse(response);
  
  if(res.ok){
    return res.channel.id;
  }else{
    Logger.log(res);
    return null;
  }
}
```
## リスト保存用のスプレッドシートを作る
ここまでで取得した、
* メールアドレス
* SlackのユーザID
* DMのチャンネルID
の3つをリストとして保存するためのシートを作ります。
![sheet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311544/86ea900e-e1cd-d029-cc0a-82067a6b1170.png)
作成したリストをメールアドレスで検索し、あればその情報を返す関数を作ります。
MEMBER_SHEET_IDにはスプレッドシートのIDが、SLACKID_LIST_NAMEにはシート名が入ります。
```javascript
//=========================================================================================
// スプレッドシートにメールアドレスがあるか検索し、あれば詳細を返す（なければnull）
//=========================================================================================
function getSlackUserfromSpreadSheet(email){
  var ss = SpreadsheetApp.openById(MEMBER_SHEET_ID).getSheetByName(SLACKID_LIST_NAME);
  var values = ss.getRange(1,1,ss.getLastRow(),3).getValues();
  values.forEach(function(value){
    if(value[0] == email){
      var response = {
        "mail":email,
        "id":value[1],
        "channelId":value[2]
      }
      return response;
    }
  });
  return null;
}
```

## DMを送信＆ID情報を保存
DMを送りつつ、新しいユーザ情報だった場合はSpreadSheetに保存するようにします。
```javascript
//=========================================================================================
// SlackのメールアドレスからIDを取得してDMを送る
//=========================================================================================
function postDirectMessage(email,message) {

  var id;
  var channelId;

  //スプレッドシートにユーザ情報があるか検索
  var user = getSlackUserfromSpreadSheet(email);

  //ユーザ情報があればそのまま格納
  if(user != null){
    id = user.id;
    channelId = user.channelId

  //ユーザ情報が無い場合はSlackAPIを叩いて取得し、スプレッドシートに追加する
  }else{
    id = getSlackIdfromEmail(email);
    if(id != null){
      channelId = getChannelID(id);
      //チャンネルIDもあればスプレッドシートに追加
      if(channelId != null){
        var ss = SpreadsheetApp.openById(MEMBER_SHEET_ID).getSheetByName(SLACKID_LIST_NAME);
        ss.appendRow([email,id,channelId]);
      }
    }
  }

  //ユーザがいた場合
  if(id != null && channelId != null){

    var message_options = {
      "method" : "post",
      "contentType": "application/x-www-form-urlencoded",
      "payload" : {
        "token": SLACK_APP_TOKEN,
        "channel":channelId,
        "text": '<@' + id + '>\n' + message
      }
    };
    
    //DM送信
    UrlFetchApp.fetch('https://slack.com/api/chat.postMessage', message_options);
  }
}

```
これで取得～送信～保存までの処理ができるようになりました。