101
104

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-05-05

#はじめに
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を選択

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

#参考記事

101
104
10

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
101
104

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?