95
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

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

はじめに

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

会社用にこちら(「Slack App+GASでボタン選択式botを作ろう」)の記事を参考にさせていただいて作成する中でハマった部分や、最新の情報を詳しく説明していきたいと思います!

やりたいこと

よくある問い合わせはパターンが決まっているので、人間(僕)がメールや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へアクセス

※botを導入したいワークスペースに、管理者権限があるアカウントでサインインすること
サインインしていなければ下記の画面が表示されるので、botを導入したいワークスペースにサインイン

スクリーンショット 2020-05-04 23.33.35.png

Create New Appをクリック

スクリーンショット 2020-05-05 0.00.52.png

③アプリ名と、アプリの作成場所を選択してCreate App

スクリーンショット 2020-05-05 0.02.45.png
App Name → botの名前を入力(日本語でもなんでもOK)
Development Slack Workspace → Slack botを導入したいワークスペースを選択
※サインインしているワークスペース名が表示されます。

④権限の付与 → Permissionsをクリック

スクリーンショット 2020-04-29 13.57.17.png

ScopesAdd an OAuth Scopeをクリック

スクリーンショット 2020-04-29 13.58.21.png

⑥2つの権限を追加

  • chat:write
  • chat:write.public

※選択すれば、変更は自動で保存されます
スクリーンショット 2020-04-29 13.59.38.png

App Display Nameの確認

App HomeApp Display NameEditをクリック
スクリーンショット 2020-05-05 0.31.28.png

⑧名前の確認 → ブランクなら任意の名前を入力(アルファベット)

※画像のように入力されていれば次へ
スクリーンショット 2020-05-05 0.35.11.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

⑩Slack Appの設定は一旦完了

2. GASでスクリプトA作成(スラッシュコマンドのレシーバー)

Google Driveにアクセス

※注意1:G Suiteでない、無料アカウントを使用してください!!
G Suiteアカウントだと、利用範囲が同一ドメイン内に制限されてしまいます。僕はここでハマりました。

新規その他Google Apps Scriptをクリック

スクリーンショット 2020-05-05 0.47.39.png

③別タブで「無題のプロジェクト」というスクリプトファイルが立ち上がるので、名前を入力

無題のプロジェクトをクリックすると下記画像の画面になるので、任意の名前を入力してOK
スクリーンショット 2020-05-05 0.50.33.png

④下記のコードをコピペ

※デフォルトで入っているfunction myFunction...とあるがそれは削除

スクリプトAのコード(クリックして開く)
コード.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);
}

Verification Tokenを取得するために、Slack Appの該当のアプリ名をクリック

Basic InformationApp Credentials内にあるVerification Tokenをコピー

スクリーンショット 2020-05-05 1.00.53.png

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

⑧スクリプトAは完成

3. GASでスクリプトB作成(条件分岐の結果を返す)

※①〜③は2. GASでスクリプトA作成と同じ

Google Driveにアクセス

新規その他Google Apps Scriptをクリック

③別タブで「無題のプロジェクト」というスクリプトファイルが立ち上がるので、名前を入力

④下記のコードをコピペ

※デフォルトで入っているfunction myFunction...とあるがそれは削除

スクリプトBのコード(クリックして開く)
コード.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);
  }

}

⑤スクリプトB完成

4. GASを公開→Slack Appに連携

①スクリプトAのコード画面を開く

②メニューバーの公開ウェブ アプリケーションとして導入…をクリック

スクリーンショット 2020-05-05 12.59.17.png

Deploy as web appのダイアログを下記画像のように設定して、Deployをクリック

スクリーンショット 2020-04-29 14.04.40.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をコピー

スクリーンショット 2020-04-29 14.04.49.png

⑤Salck AppのBuilding Apps for SlackAdd features and functionalityをクリック

スクリーンショット 2020-05-05 13.12.35.png

Slash Commandsをクリック → Create New Commandをクリック

スクリーンショット 2020-05-05 13.13.53.png

⑦コマンドを設定してSave

スクリーンショット 2020-04-29 14.06.33.png

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

⑧スクリプトBのCuurent web app URLを取得してコピー

※方法は4-①〜4-④と同様

Add features and functionalityInteractive Componentsをクリック

スクリーンショット 2020-05-05 13.21.27.png

InteractivityOn

スクリーンショット 2020-05-05 13.22.38.png

Request URLに先ほど(4-⑧)コピーしたスクリプトBのURLをペーストしてSave Changes

スクリーンショット 2020-05-05 13.25.30.png

5. 完成!

①ワークスペースにインストール:Install App to Workspaceをクリック

スクリーンショット 2020-05-05 13.29.37.png

②確認画面が出てくるので、投稿したいチャンネルを選択して許可

スクリーンショット 2020-04-29 14.27.51.png

③動作確認

設定したスラッシュコマンドを送信して、botが起動すれば完了です!
スクリーンショット 2020-05-05 13.37.31.png
スクリーンショット 2020-05-05 13.37.45.png

終わりに

ハマったポイントは大きく2つです。

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

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

参考記事

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
95
Help us understand the problem. What are the problem?