#はじめに
40名ほどの企業で社内SE(1人情シス)やってます。
社内にSlackを導入し、日々ある「問い合わせ」をbotに任せられないかと思ってGAS(Google Apps Script)で作成しました。(テレワークで質問が急増して、一つずつ答えてられないというのが本音です…笑)
会社用にこちら(「Slack App+GASでボタン選択式botを作ろう」)の記事を参考にさせていただいて作成する中でハマった部分や、最新の情報を詳しく説明していきたいと思います!
#やりたいこと
よくある問い合わせはパターンが決まっているので、人間(僕)がメールやSlackでいちいち回答せず、簡単な問い合わせ対応をbotに任せたい。
- カテゴリ別・パターン別で、質問を3階層くらいにしたい
- 「終了」を押すまではループさせたい
- 外国籍の社員もいるので英語対応させたい(コンテンツは実装中)
- 癒しが欲しいので、田中みな実が答えてくれる風にする(ここはあまり注視しないでください…)
#前提条件
- Googleアカウントを持っている
- Slackのワークスペースの管理者権限を持っている
#手順
- Slack Appの作成(これがbot本体)
- GASでスクリプトA作成(スラッシュコマンドのレシーバー)
- GASでスクリプトB作成(条件分岐の結果を返す)
- GASを公開→Slack Appに連携
- 完成!
##1. Slack Appの作成
###①Slack APIへアクセス
※botを導入したいワークスペースに、管理者権限があるアカウントでサインインすること
サインインしていなければ下記の画面が表示されるので、botを導入したいワークスペースにサインイン
###③アプリ名と、アプリの作成場所を選択してCreate App
App Name
→ botの名前を入力(日本語でもなんでもOK)
Development Slack Workspace
→ Slack botを導入したいワークスペースを選択
※サインインしているワークスペース名が表示されます。
###⑤Scopes
の Add an OAuth Scope
をクリック
###⑥2つの権限を追加
chat:write
chat:write.public
###⑦App Display Name
の確認
App Home
→ App Display Name
のEdit
をクリック
###⑧名前の確認 → ブランクなら任意の名前を入力(アルファベット)
※画像のように入力されていれば次へ
###⑨botの画像設定 → Save Changes
-
App name
→ Slack Appの名前 -
Short description
→ Slack上でのbotの説明 -
App icon & Preview
→ Slack上でのbotのアイコン -
Background color
→ Slack上でのbotの背景
###⑩Slack Appの設定は一旦完了
##2. GASでスクリプトA作成(スラッシュコマンドのレシーバー)
###①Google Driveにアクセス
※注意1:G Suiteでない、無料アカウントを使用してください!!
→G Suiteアカウントだと、利用範囲が同一ドメイン内に制限
されてしまいます。僕はここでハマりました。
###②新規
→ その他
→ Google Apps Script
をクリック
###③別タブで「無題のプロジェクト」というスクリプトファイルが立ち上がるので、名前を入力
※無題のプロジェクト
をクリックすると下記画像の画面になるので、任意の名前を入力してOK
###④下記のコードをコピペ
※デフォルトで入っているfunction myFunction...
とあるがそれは削除
スクリプトAのコード(クリックして開く)
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 Information
のApp Credentials
内にあるVerification Token
をコピー
###⑦ 2-④コード内の"★トークン
"部分を、⑥でコピーしたVerification Tokenの文字列に置き換える
###⑧スクリプトAは完成
##3. GASでスクリプトB作成(条件分岐の結果を返す)
※①〜③は2. GASでスクリプトA作成
と同じ
###①Google Driveにアクセス
###②新規
→ その他
→ Google Apps Script
をクリック
###③別タブで「無題のプロジェクト」というスクリプトファイルが立ち上がるので、名前を入力
###④下記のコードをコピペ
※デフォルトで入っているfunction myFunction...
とあるがそれは削除
スクリプトBのコード(クリックして開く)
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のコード画面を開く
###②メニューバーの公開
→ ウェブ アプリケーションとして導入…
をクリック
###③Deploy as web app
のダイアログを下記画像のように設定して、Deploy
をクリック
-
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をコピー
###⑤Salck AppのBuilding Apps for Slack
→ Add features and functionality
をクリック
###⑥Slash Commands
をクリック → Create New Command
をクリック
-
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
をクリック
###⑪Request URL
に先ほど(4-⑧)コピーしたスクリプトBのURLをペーストしてSave Changes
##5. 完成!
###①ワークスペースにインストール:Install App to Workspace
をクリック
###②確認画面が出てくるので、投稿したいチャンネルを選択して許可
###③動作確認
設定したスラッシュコマンドを送信して、botが起動すれば完了です!
#終わりに
ハマったポイントは大きく2つです。
- G Suite(有料アカウント)でスクリプトを作成して、権限の問題でスクリプト起動できなかった(注意1)
⇒ 無料アカウントでスクリプト作成して対応 - スクリプトの実行者を
User
とすると起動できなかった(注意2)
⇒Me
を選択
条件分岐や返す内容はうちの会社用に作成したものなので、適宜変更して使用してください。
この手順通り行っても起動できなかった、誤りがある、などありましたらご指摘いただけますと幸いです。
#参考記事