Slackの招待メール送信をGoogle Apps Scriptで自動化する

## はじめに
We Are JavascriptersというJavascripter向けのイベントのもくもく会をおこなうことになり、もくもく会専用のSlackを作成しました。
しかし、参加者全員にメールを送ってSlackに招待するのが結構な手間になりそうだったので、どうにかスクリプトでこの手間を省略できないかなぁと考えていました。
探しているとSlackInというアプリが見つかったのですが、筆者がherokuへのデプロイとかやったことないレベルなので今回はAjaxでWebアプリケーションとして公開したGAS(Google Apps Script)へリクエストを送り、GAS内でSlackチームへの招待メールを送るようにしましたので知見を共有します！
無料で全て完結するのでおすすめですよーーー！

## 必要知識
- html, css, Javascript（ajax）
- Google Apps Script（記法はほぼJavascript）

基本的なWebの知識があれば問題ないと思います。

## 簡単な流れ
Slackの招待メールを送信するための、基本的な処理の流れは以下のとおりです。

```
フロント側からGASへEmailをパラメータとして渡したAjaxを飛ばす
↓
Emailへ招待メールを送るために、GASからSlackのAPIへEmailをパラメータとしてpostする
↓
SlackのAPIからresponseが返ってくる（この時点でSlackによってEmailは送信されている）
↓
Slackのpostが成功したか確認するために、Slackのresponseをそのまま、ajaxのresponseとしてフロント側に返す
```

## コードの最小構成
見た目などは無視してhtmlのform, それに必要なjavascriptのコード、Google Apps Scriptを書いています。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>WeJS: Send Slack Invitation</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
  </head>

  <body>
    <!-- 招待メールを入力させるform -->
    <form action="#" id="form">
      <div>
        <label for="email">Email Address</label>
        <input type="email" id="email" name="email">
      </div>
      <input type="submit" value="送信">
    </form>

    <!-- Google Apps ScriptへのAjax -->
    <script type="application/javascript">
      $('#form').on('submit', function(e){
        e.preventDefault()
        $.ajax({
          url: '【Your Google Apps Script Endpoint】',
          data: $(this).serialize(),
          dataType: 'jsonp'
        })
        .then(function(res){
          alert(res);
        }, function(res){
          alert("Oops...Something went wrong!");
        })
      })
    </script>
  </body>
</html>

```

```js
// Google Apps Script

// Getでリクエストを受け取ったときに呼ばれる関数（デフォルトではdoGet関数が定義されていると呼ばれる）
function doGet(e) {
  var TOKEN = '【Your Slack App Token】'
  var URL   = 'https://【Your Slack Team Name】.slack.com/api/users.admin.invite'

　　　　// UrlFetchAppでslackのAPIにpostでemailtとtoken、set_activeを投げる
  var res = UrlFetchApp.fetch(URL, {
    'method': 'post',
    'payload': {
      'token': TOKEN,
      'email': e.parameter.email,
      'set_active': true
    }
  });
  
  var content = {
    output:   e.parameter.callback + '(' + res.getContentText() + ');',
    mimeType: ContentService.MimeType.JAVASCRIPT
  };
  return ContentService.createTextOutput(content.output).setMimeType(content.mimeType);
}

```

コードの中にある定数は以下のとおりです。

- 【Your Slack App Token】 ・・・ Slack Appのtoken
- 【Your Slack Team Name】 ・・・ どのチームに招待した以下の名前
- 【Your Google Apps Script Endpoint】 ・・・ GASをWebアプリケーションとして公開したときのエンドポイント

## 定数の準備
### Your Slack App Token
これはSlack Appのtokenになります。
これは以下の記事がわかりやすかったので参考にして下さい。
[Slack APIのTokenの取得・場所](http://qiita.com/ykhirao/items/0d6b9f4a0cc626884dbb)

おそらくこのような感じになります。


```
xoxp-xxxxxxxxxxxx-yyyyyyyyyyyy-zzzzzzzzzzzz-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
```
<img width="691" alt="スクリーンショット 2017-05-31 10.36.20.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/5186/38694960-27a9-a18f-feca-e892fa3f7934.jpeg">

### Your Slack Team Name
これはSlackのチームの名前です。
今回招待メールを送りたいSlackのチームは`team-wejs.slack.com`というチームだったので`team-wejs`の部分になります。

### Your Google Apps Script Endpoint
こちらですが、少し手順が長いです。
そもそもGoogle Apps Scriptの説明なのですが、Google Apps Scriptは使用したスクリプトを外部のアプリケーションとして公開することが出来ます。
また、その際にエンドポイントとしてurlが発行され、GetとPostでアクセス時に呼ばれる関数を設定することも可能です。

```js
// Google Apps Script
doGet(){
  // Endpointにgetでアクセスすると呼ばれる
}
doPost(){
  // Endpointにpostでアクセスすると呼ばれる
}
```

なので、もちろんブラウザのURL欄に発行されたurl`https://script.google.com/macros/s/xxxxxxxxxxxx/exec`をいれてアクセスすると`doGet()`で返したものが表示されます。

さて、やってみましょう。
ます[Google Apps Script](https://script.google.com/start)にアクセスします。
<img width="1437" alt="スクリーンショット 2017-05-31 11.48.13.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/5186/75efcd13-e8f5-401a-a9c0-d4c54690aaf6.jpeg">

今回使用するのは`doGet()`になります。
ここで、Emailを送るのにgetでアクセスするのかと思われるかもしれませんが、Google Apps Scriptで公開したアプリケーションはCORSが許可されておらず、異なるドメインからのPostを受け付けていません。
なのでAjaxでエンドポイントに対してGetでアクセスし、jsonp形式でレスポンスデータを受け取ります。
もちろんGoogle Apps Scriptでは`doGet()`内でjsonp形式でデータを返して上げる必要があります。

それでは先ほどのコードをコピペしてみましょう。

```js
// Google Apps Script

// Getでリクエストを受け取ったときに呼ばれる関数（デフォルトではdoGet関数が定義されていると呼ばれる）
function doGet(e) {
  var TOKEN = '【Your Slack App Token】'
  var URL   = 'https://【Your Slack Team Name】.slack.com/api/users.admin.invite'

　　　　// UrlFetchAppでslackのAPIにpostでemailtとtoken、set_activeを投げる
  var res = UrlFetchApp.fetch(URL, {
    'method': 'post',
    'payload': {
      'token': TOKEN,
      'email': e.parameter.email,
      'set_active': true
    }
  });
  
  var content = {
    output:   e.parameter.callback + '(' + res.getContentText() + ');',
    mimeType: ContentService.MimeType.JAVASCRIPT
  };
  return ContentService.createTextOutput(content.output).setMimeType(content.mimeType);
}
```

やってることは単純です、`doGet()`が呼ばれた後、先ほど準備した`【Your Slack App Token】`と`【Your Slack Team Name】`を使って定数を定義します。
その後SlackのエンドポイントにPostするためにGoogle Apps Scriptの`UrlFetchApp`を使用し、値として`e.parameter.email`から取得したemailをpostして上げます。

Slackにpostした後、SlackのAPIからレスポンスを受け取り、ajax側に返してあげるデータを整形します。
上記の以下の部分です。

```js
var content = {
  output:   e.parameter.callback + '(' + res.getContentText() + ');',
  mimeType: ContentService.MimeType.JAVASCRIPT
};
return ContentService.createTextOutput(content.output).setMimeType(content.mimeType);
```
※ Google Apps Scriptで値を返却する際の型の指定方式が少々特殊なので下にまとめました。

これだけでGoogle Apps Script側の処理は終了です。

それでは外部のWebアプリケーションとして公開してきましょう。
①公開 → ウェブアプリケーションとして導入
<img width="1436" alt="スクリーンショット_2017-05-31_12_30_40.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/5186/7adc745b-cbbc-0d6c-9b47-b5c86f55cfc0.jpeg">

②諸々埋める

<img width="1436" alt="スクリーンショット_2017-05-31_12_31_08.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/5186/31aaa87b-b789-68bd-6fd3-4c44cb0737c7.jpeg">


③URLの発行が完了する

<img width="1436" alt="スクリーンショット_2017-05-31_12_31_42.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/5186/d1334017-4382-da3e-abb2-7666bbc3bbf6.jpeg">

これでhtmlの中のajaxのurlを埋めることが可能です！

```js
$.ajax({
  url: '【Your Google Apps Script Endpoint】',
  data: $(this).serialize(),
  dataType: 'jsonp'
})
```

これで全部完了です！
あとはフロント側でAjaxで返ってくる値の中身に応じて色々処理を変えてみるとUX的に良いと思います！

また、今回はhtmlをgithub-pagesに上げたのでまったく料金がかからずこのアプリケーションを作成することが出来ました。
サーバレスで気軽に作成できるので良かったら作成してみて下さい！(๑•̀ㅂ•́)و✧

## We Are Javascriptersの場合
ちなみにWe Are Javascriptersのサイトでは以下のようなデザインにしています。
<img width="528" alt="スクリーンショット 2017-05-31 12.27.25.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/5186/aa174b39-df62-1944-df2f-7efafc17ef00.jpeg">
<img width="1435" alt="スクリーンショット 2017-05-31 12.29.22.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/5186/77075b46-f3ad-a4b8-d0fa-1fc797313136.jpeg">




## 注釈
### Google Apps Scriptの返却する値について
Google Apps Scriptを使用するときに注意して欲しいことなのですが、return 'hogehoge'などにしても正しく値が返ってくれません。
戻り値の型を`ContentService.createTextOutput(【値】).setMimeType(【型】)`を使用して指定するようにして下さい。

#### 普通にtextをreturnした場合
<img width="1439" alt="スクリーンショット 2017-05-31 12.04.33.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/5186/b51f955f-77b1-1fea-a4e6-332020f46bd7.jpeg">

#### text/plainを返したい場合
plain/textを返したい場合は
`ContentService.createTextOutput('aaaa').setMimeType(ContentService.MimeType.TEXT)`
と指定しましょう。

```js
function doGet() {
  return ContentService.createTextOutput('aaaa').setMimeType(ContentService.MimeType.TEXT)
}
```

<img width="1434" alt="スクリーンショット_2017-05-31_12_13_44.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/5186/ed23a470-cf4d-2fb3-67a5-0cdf320af81d.jpeg">

#### application/jsonを返したい場合
application/jsonを返したい場合は
`ContentService.createTextOutput('aaaa').setMimeType(ContentService.MimeType.JSON)`
と指定しましょう。

```js
function doGet() {
  return ContentService.createTextOutput('aaaa').setMimeType(ContentService.MimeType.JSON)
}
```

<img width="1437" alt="スクリーンショット_2017-05-31_12_14_09.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/5186/b45a989c-1ce0-392f-af4e-72136e624a54.jpeg">

ちなみにjsonをさくっと返したい場合はGoogle Apps Scriptで可能なので、僕はよくテストに使ってます（笑）