[GAS]Slack botの作り方を、お節介なほど丁寧に説明

#はじめに
40名ほどの企業で社内SE(1人情シス)やってます。
社内にSlackを導入し、日々ある「問い合わせ」をbotに任せられないかと思ってGAS(Google Apps Script)で作成しました。（テレワークで質問が急増して、一つずつ答えてられないというのが本音です…笑）

会社用にこちら（「[Slack App+GASでボタン選択式botを作ろう](https://qiita.com/tomoharr24/items/0b4c0f2d9097ab7fc7da)」）の記事を参考にさせていただいて作成する中でハマった部分や、最新の情報を詳しく説明していきたいと思います！

#やりたいこと
よくある問い合わせはパターンが決まっているので、人間(僕)がメールやSlackでいちいち回答せず、簡単な問い合わせ対応をbotに任せたい。

- カテゴリ別・パターン別で、質問を3階層くらいにしたい
- 「終了」を押すまではループさせたい
- 外国籍の社員もいるので英語対応させたい（コンテンツは実装中）
- 癒しが欲しいので、田中みな実が答えてくれる風にする（ここはあまり注視しないでください…）

#前提条件
- Googleアカウントを持っている
- Slackのワークスペースの管理者権限を持っている

#手順

1. **Slack Appの作成（これがbot本体）**
2. **GASでスクリプトA作成（スラッシュコマンドのレシーバー）**
3. **GASでスクリプトB作成（条件分岐の結果を返す）**
4. **GASを公開→Slack Appに連携**
5. **完成！**


##1. Slack Appの作成
###①[Slack API](https://api.slack.com/apps)へアクセス
※botを導入したいワークスペースに、管理者権限があるアカウントでサインインすること
サインインしていなければ下記の画面が表示されるので、botを導入したいワークスペースにサインイン

![スクリーンショット 2020-05-04 23.33.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/6b46649c-c6e7-ee0d-4e9d-c23cb98da798.png)

###②`Create New App`をクリック
![スクリーンショット 2020-05-05 0.00.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/556a2495-4a82-93b0-ac70-c826f4ae22ac.png)

###③アプリ名と、アプリの作成場所を選択して`Create App`
![スクリーンショット 2020-05-05 0.02.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/d389be57-9030-273a-96b1-0f49929e5bc6.png)
`App Name` → botの名前を入力（日本語でもなんでもOK）
`Development Slack Workspace` → Slack botを導入したいワークスペースを選択
※サインインしているワークスペース名が表示されます。

###④権限の付与 → `Permissions`をクリック
![スクリーンショット 2020-04-29 13.57.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/77b1e5ed-4215-d6b1-9890-2a2f4a74a49a.png)

###⑤`Scopes`の `Add an OAuth Scope`をクリック
![スクリーンショット 2020-04-29 13.58.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/cf82f5f8-304b-fdde-7b17-f13158809cc7.png)

###⑥2つの権限を追加

- `chat:write`
- `chat:write.public`

※選択すれば、変更は自動で保存されます
![スクリーンショット 2020-04-29 13.59.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/6a85e391-d237-2db1-0963-f1d66cff92ed.png)

###⑦`App Display Name`の確認
`App Home` → `App Display Name`の`Edit`をクリック
![スクリーンショット 2020-05-05 0.31.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/5242f79b-e6f2-c799-0244-2b886d123310.png)

###⑧名前の確認 → ブランクなら任意の名前を入力（アルファベット）
※画像のように入力されていれば次へ
![スクリーンショット 2020-05-05 0.35.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/cff6ac1d-887e-deb3-cf3d-dcc3a6416e32.png)

###⑨botの画像設定 → `Save Changes`

- `App name` → Slack Appの名前
- `Short description` → Slack上でのbotの説明
- `App icon & Preview` → Slack上でのbotのアイコン
- `Background color` → Slack上でのbotの背景
![スクリーンショット 2020-05-05 0.38.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/eee0c315-fd94-e0e2-eff5-7949344929a3.png)

###⑩Slack Appの設定は一旦完了

##2. GASでスクリプトA作成（スラッシュコマンドのレシーバー）
###①[Google Drive](https://drive.google.com/drive/u/0/my-drive)にアクセス
**※注意1：G Suiteでない、無料アカウントを使用してください！！**
→`G Suiteアカウントだと、利用範囲が同一ドメイン内に制限`されてしまいます。僕はここでハマりました。

###②`新規` → `その他` → `Google Apps Script`をクリック
<img width="521" alt="スクリーンショット 2020-05-05 0.47.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/60f6bbab-4d57-3338-0ead-07931676880a.png">

###③別タブで「無題のプロジェクト」というスクリプトファイルが立ち上がるので、名前を入力
※`無題のプロジェクト`をクリックすると下記画像の画面になるので、任意の名前を入力して`OK`
<img width="470" alt="スクリーンショット 2020-05-05 0.50.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/6b93944a-05c1-bac8-b74d-6a1fc200673c.png">

###④下記のコードをコピペ
※デフォルトで入っている`function myFunction...`とあるがそれは削除

<details><summary>スクリプトAのコード(クリックして開く)</summary><div>

```javascript:コード.js
function doPost(e) {
  var slack_token = '★トークン'; // Verification Tokenで取得するトークン
  // 指定したチャンネルからの命令しか受け付けない
  if (slack_token != e.parameter.token) {
    throw new Error(e.parameter.token);
  }
// 返答データ本体
  var data = {
    "text": "み〜んなのみな実だよ！まずは言語を選んでね♡", //アタッチメントではない通常メッセージ
    "response_type":"ephemeral", // ここを"ephemeral"から"in_chanel"に変えると他の人にも表示されるらしい（？）
    //アタッチメント部分
    "attachments": [{
      "title": "Language Select",//　アタッチメントのタイトル
      "text": "Please select language.",//アタッチメント内テキスト
      "fallback": "Yeeeeeeeeeeah!!!",//ボタン表示に対応してない環境での表示メッセージ. 
      "callback_id": "callback_button",
      "color": "#00bfff", //左の棒の色を指定する
      "attachment_type": "default",
      // ボタン部分
      "actions": [
        //ボタン1
        {
          "name": "eng",
          "text": "English",
          "type": "button",//
          "value": "language"
        },
        //ボタン2
        {
          "name": "jpn",
          "text": "日本語",
          "type": "button",
          "value": "language"
        }
        ]
      }]
  };
  return ContentService.createTextOutput(JSON.stringify(data)).setMimeType(ContentService.MimeType.JSON);
}
```
</div></details>

###⑤`Verification Token`を取得するために、[Slack App](https://api.slack.com/apps)の該当のアプリ名をクリック

###⑥`Basic Information`の`App Credentials`内にある`Verification Token`をコピー
![スクリーンショット 2020-05-05 1.00.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/4149a9f8-92b4-2aac-5465-e539d6f00733.png)

###⑦ 2-④コード内の"`★トークン`"部分を、⑥でコピーしたVerification Tokenの文字列に置き換える

###⑧スクリプトAは完成

##3. GASでスクリプトB作成（条件分岐の結果を返す）
※①〜③は`2. GASでスクリプトA作成`と同じ
###①[Google Drive](https://drive.google.com/drive/u/0/my-drive)にアクセス
###②`新規` → `その他` → `Google Apps Script`をクリック
###③別タブで「無題のプロジェクト」というスクリプトファイルが立ち上がるので、名前を入力
###④下記のコードをコピペ
※デフォルトで入っている`function myFunction...`とあるがそれは削除

<details><summary>スクリプトBのコード(クリックして開く)</summary><div>

```javascript:コード.js
function doPost(e) {
  // ペイロード部分の取り出し
  var payload = JSON.parse(e["parameter"]["payload"]);
  var name = payload["actions"][0]["name"];
  var value = payload["actions"][0]["value"];

  // nameの値についてswitch分岐(nameを言語モードの分岐条件にしている)
  switch (name) {
    // 英語モードの場合
    case 'eng':
      var head_text = "Answer in English♡";
      var quest_attachment = {
        "title": "Question Select",
        "text": "Sorry, I'm just getting ready 🙇‍♂️🙇‍♂️🙇‍♂️",
        "fallback": "Opps",
        "callback_id": "callback_button",
        "color": "#00bfff",
        "attachment_type": "default",
        "actions": [
          {
            "name": "eng",
            "text": "Exit",
            "type": "button",
            "value": "quit"
          }
        ]
      };
      break;
    // 日本語モードの場合
    case 'jpn':
      var head_text = '日本語で答えるね♡';
      // 2段階目の選択肢ボタン用アタッチメント
      var quest_attachment = {
        "title": '質問選択',
        "text": '何について知りたいの？',
        "fallback": "ほえ〜",
        "callback_id": "callback_button",
        "color": "#FFC0CB",
        "attachment_type": "default",
        "actions": [
          {
            "name": "jpn",
            "text": "働くDB関連",
            "type": "button",
            "value": "htdb"
          },
          {
            "name": "jpn",
            "text": "テレワーク関連",
            "type": "button",
            "value": "telework"
          },
          {
            "name": "jpn",
            "text": "ツールの使い方",
            "type": "button",
            "value": "how-tools"
          },
          {
            "name": "jpn",
            "text": "みな実のこと！",
            "type": "button",
            "value": "about-minami"
          },
          {
            "name": "jpn",
            "text": "終了",
            "type": "button",
            "value": "quit"
          }
        ]
      }
      break;
  }

  // 選択肢に応じた応答をするためにvalueでswitch分岐する
  switch (value) {
    case 'htdb':
      // 言語モードに応じた答えに分岐する
      switch (name) {
        case 'eng':
          var r_text = "英語版";
          var exp_text = "英語版";
          break;
        case 'jpn':
          var head_text = "働くDBついて答えるよ♡"
          var quest_attachment = {
            "title": '',
            "text": 'どうしたの？',
            "fallback": "ほえ〜",
            "callback_id": "callback_button",
            "color": "#FFC0CB",
            "attachment_type": "default",
            "actions": [
              {
                "name": "jpn",
                "text": "データを削除したい",
                "type": "button",
                "value": "htdb__delete-data"
              },
              {
                "name": "jpn",
                "text": "質問・要望を送りたい",
                "type": "button",
                "value": "htdb__qandr"
              },
              {
                "name": "jpn",
                "text": "バグがあった",
                "type": "button",
                "value": "htdb__report-bug"
              },
              {
                "name": "jpn",
                "text": "パスワードを忘れた",
                "type": "button",
                "value": "htdb__reset-pw"
              },
              {
                "name": "jpn",
                "text": "その他",
                "type": "button",
                "value": "other"
              },
              {
                "name": "jpn",
                "text": "終了",
                "type": "button",
                "value": "quit"
              }
            ]
          }
          break;
      }
      break;
    case 'telework':
      switch (name) {
        case 'eng':
          var r_text = "英語版";
          var exp_text = "英語版";
          break;
        case 'jpn':
          var head_text = "テレワークついて答えるよ♡"
          var quest_attachment = {
            "title": '質問選択',
            "text": '何について知りたいの？',
            "fallback": "ほえ〜",
            "callback_id": "callback_button",
            "color": "#FFC0CB",
            "attachment_type": "default",
            "actions": [
              {
                "name": "jpn",
                "text": "テレワーク実施までの手順",
                "type": "button",
                "value": "tele__start"
              },
              {
                "name": "jpn",
                "text": "リモートデスクトップの使い方",
                "type": "button",
                "value": "howto-rdt"
              },
              {
                "name": "jpn",
                "text": "VPNの使い方",
                "type": "button",
                "value": "howto-vpn"
              },
              {
                "name": "jpn",
                "text": "テレワークの規定を確認したい",
                "type": "button",
                "value": "tele__guideline"
              },
              {
                "name": "jpn",
                "text": "その他",
                "type": "button",
                "value": "other"
              },
              {
                "name": "jpn",
                "text": "終了",
                "type": "button",
                "value": "quit"
              }
            ]
          }
          break;
      }
      break;
    case 'how-tools':
      switch (name) {
        case 'eng':
          var r_text = "英語版";
          var exp_text = "英語版";
          break;
        case 'jpn':
          var head_text = "ツールついて答えるよ♡"
          var quest_attachment = {
            "title": '質問選択',
            "text": '何について知りたいの？',
            "fallback": "ほえ〜",
            "callback_id": "callback_button",
            "color": "#FFC0CB",
            "attachment_type": "default",
            "actions": [
              {
                "name": "jpn",
                "text": "Slackの使い方",
                "type": "button",
                "value": "howto-slack"
              },
              {
                "name": "jpn",
                "text": "Zoomの使い方",
                "type": "button",
                "value": "howto-zoom"
              },
              {
                "name": "jpn",
                "text": "VPNの使い方",
                "type": "button",
                "value": "howto-vpn"
              },
              {
                "name": "jpn",
                "text": "irucaの使い方",
                "type": "button",
                "value": "howto-iruca"
              },
              {
                "name": "jpn",
                "text": "その他",
                "type": "button",
                "value": "other"
              },
              {
                "name": "jpn",
                "text": "終了",
                "type": "button",
                "value": "quit"
              }
            ]
          }
          break;
      }
      break;
    case 'about-minami':
      var image = 'https://livedoor.blogimg.jp/moriagarisokuho/imgs/7/b/7b3dcc21-s.jpg';
      switch (name) {
        case 'eng':
          var r_text = "Which key corresponds to each room?";
          var exp_text = "Correspondence of the key of each room is as this photo";
          break;
        case 'jpn':
          var exp_text = "＼＼＼教えてあーげない！／／／";
          break;

      }
      break;
    
    //////////// 子項目の選択肢 ////////////
    case 'other':
      var r_text = "その他の問い合わせ";
      var exp_text = "このチャンネルでメンションをして質問してね！";
      break;

    case 'htdb__delete-data':
      var r_text = "働くDBのデータ削除の方法";
      var exp_text = "こちらのURLから削除依頼をしてね！\nhttps://hogehoge";
      break;

    case 'htdb__qandr':
      var r_text = "働くDBへの質問・要望の出し方";
      var exp_text = "こちらのURLから質問・要望を送信してね！\nhttps://fugafuga";
      break;

    case 'htdb__report-bug':
      var r_text = "働くDBのバグ報告の方法";
      var exp_text = "バグ出しちゃってごめんね😢\nこちらのURLからバグを報告してね！\nhttps://hogehoge";
      break;      
    
    case 'htdb__reset-pw':
      var r_text = "働くDBのパスワード再設定の方法";
      var exp_text = "こちらのURLからパスワード再設定依頼をしてね！\nhttps://fugafuga";
      break; 

    case 'tele__start':
      var r_text = "テレワーク実施までの手順";
      var exp_text = "こちらのURLから確認してね！\nhttps://hogehoge";
      break; 

    case 'howto-rdt':
      var r_text = "リモートデスクトップの利用手順";
      var exp_text = "こちらのURLから確認してね！\nhttps://fugafuga";
      break; 

    case 'howto-vpn':
      var r_text = "VPNの接続方法";
      var exp_text = "こちらのURLから確認してね！\nhttps://hogehoge";
      break; 

    case 'tele__guideline':
      var r_text = "テレワーク・モバイルワーク規定";
      var exp_text = "こちらのURLから確認してね！\nhttps://fugafuga";
      break; 

    case 'howto-slack':
      var r_text = "Slackの使い方";
      var exp_text = "こちらのURLから確認してね！\n利用までの手順や利用ガイドへのリンクも載ってるよ！\nhttps://hogehoge";
      break; 

    case 'howto-zoom':
      var r_text = "Zoomの使い方";
      var exp_text = "こちらのURLから確認してね！\nhttps://fugafuga";
      break; 

    case 'howto-iruca':
      var r_text = "irucaの使い方";
      var exp_text = "こちらのURLから確認してね！\nhttps://hogehoge";
      break;       
  }
  // 質問に応じたアタッチメントの定義
  var response = {
    "title": r_text,
    "text": exp_text,
    "image_url": image,
    "color": "#ffa500"
  };
  // 送信されるメッセージの定義
  var new_rep = {
    "text": head_text,
    "attachments": [
      response,
      quest_attachment
    ]
  };

  // 「終了」という選択肢が選ばれた時のみ異なる処理をしてボタンを消す(ボタン無しメッセージで上書きする)
  if (value == "quit"){
    // 終了時
    var reply = {
      "attachments": [
        {
          "text": "今日もみな実とがんばろうね♡",
          "color": "FFC0CB"
        }
      ]
    };
    return ContentService.createTextOutput(JSON.stringify(reply)).setMimeType(ContentService.MimeType.JSON);
  } else{
    // それ以外の場合は選択肢メッセージを出し続ける
    return ContentService.createTextOutput(JSON.stringify(new_rep)).setMimeType(ContentService.MimeType.JSON);
  }

}
```
</div></details>

###⑤スクリプトB完成

##4. GASを公開→Slack Appに連携
###①スクリプトAのコード画面を開く
###②メニューバーの`公開` → `ウェブ アプリケーションとして導入…`をクリック
![スクリーンショット 2020-05-05 12.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/ffa5fecc-7109-c1ef-6041-40d57ee0bf79.png)

###③`Deploy as web app`のダイアログを下記画像のように設定して、`Deploy`をクリック
<img width="457" alt="スクリーンショット 2020-04-29 14.04.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/ad95fc01-25f9-c861-c612-3e299d7027d6.png">

- `Project version:` → `New` ※変更があるたびNewを選択
- `Execute the app as:` 　→ `Me(hoge@gmail.com)` ※スクリプトを作成した無料アカウントのメールアドレス
**※注意2：ここで`Me`を選択しないとうまくbotが起動しません**
- `Who has access to the app:` → `Anyone, even anonymous` ※G Suite(有料アカウント)だとこの選択肢が表示されない

###④`Cuurent web app URL:`に表示されたURLをコピー
<img width="460" alt="スクリーンショット 2020-04-29 14.04.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/a7d20530-182b-ec02-dd8f-414cc4f34837.png">

###⑤Salck Appの`Building Apps for Slack` → `Add features and functionality`をクリック
![スクリーンショット 2020-05-05 13.12.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/dc406ca1-6cb8-6e3f-4999-10b483880cd1.png)

###⑥`Slash Commands`をクリック → `Create New Command`をクリック
![スクリーンショット 2020-05-05 13.13.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/f12a686c-0097-75fa-e78e-ae1e7d446ed9.png)

###⑦コマンドを設定して`Save`
<img width="613" alt="スクリーンショット 2020-04-29 14.06.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/98631e3f-6bd6-a4f4-b7e6-6f2989379ce3.png">

- `Command` → `必須`：Slack上でbotを起動する際のコマンドを指定（アルファベット）
- `Request URL` → `必須`：先ほど(4-④)コピーしたスクリプトAのURLをペースト
- `Short Description` → `必須`：Slack botの説明

###⑧スクリプトBの`Cuurent web app URL`を取得してコピー
※方法は4-①〜4-④と同様

###⑨`Add features and functionality`の`Interactive Components`をクリック
![スクリーンショット 2020-05-05 13.21.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/09f4789e-5abe-4396-8e04-039052f95d91.png)

###⑩`Interactivity`を`On`
![スクリーンショット 2020-05-05 13.22.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/0061a9e1-dd1a-34a4-0d93-703f5b093a3d.png)

###⑪`Request URL`に先ほど(4-⑧)コピーしたスクリプトBのURLをペーストして`Save Changes`
![スクリーンショット 2020-05-05 13.25.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/8c4b8000-e87d-37b3-8687-338403bcf28d.png)

##5. 完成！
###①ワークスペースにインストール：`Install App to Workspace`をクリック
![スクリーンショット 2020-05-05 13.29.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/aad01080-7bd7-fea4-7ad6-0bd6b0ac61c7.png)

###②確認画面が出てくるので、投稿したいチャンネルを選択して`許可`
![スクリーンショット 2020-04-29 14.27.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/35740bff-1498-85c7-5038-8367d77de7ef.png)

###③動作確認
設定したスラッシュコマンドを送信して、botが起動すれば完了です！
<img width="601" alt="スクリーンショット 2020-05-05 13.37.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/32f6cc39-58dc-5daa-9e1b-9aaab7ed1805.png">
<img width="563" alt="スクリーンショット 2020-05-05 13.37.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602794/abf09fa4-0dc0-b5da-35b6-237a49686b15.png">

#終わりに
ハマったポイントは大きく2つです。

1. G Suite(有料アカウント)でスクリプトを作成して、権限の問題でスクリプト起動できなかった（注意1）
　　⇒　無料アカウントでスクリプト作成して対応
2. スクリプトの実行者を`User`とすると起動できなかった（注意2)
　　⇒　`Me`を選択

条件分岐や返す内容はうちの会社用に作成したものなので、適宜変更して使用してください。
この手順通り行っても起動できなかった、誤りがある、などありましたらご指摘いただけますと幸いです。

#参考記事

- [Slack App+GASでボタン選択式botを作ろう](https://qiita.com/tomoharr24/items/0b4c0f2d9097ab7fc7da)
- [Slack Appの作り方について]
(https://qiita.com/yuukiw00w/items/94e4495fc593cfbda45c)
- [Slack Botの種類と大まかな作り方](https://qiita.com/namutaka/items/233a83100c94af033575)