GASとslackでヘルプデスクフォームを作った話(スラッシュコマンド版 コード編)
GASとslackでヘルプデスクフォームを作った話(スラッシュコマンド版 準備編)の続きです。
処理の流れ
doPostで受けとったデータの内容によって分岐するようにしています。
フォームからのリクエストの場合
- フォームのcallback_idをチェック
- 質問者のslackのユーザーIDからメールアドレスを取得
- 内容をGSSに書き込む
- 質問者をチャンネルへ招待
- 内容をチャンネルへポスト
コード全体
コメントアウトで説明を入れています。
function doPost(e) { //スクリプトのプロパティからトークンやIDを取得 var verifiy_token = PropertiesService.getScriptProperties().getProperty('verifiy_token'); //slackアプリ Basic InformationのVerification Token var bot_token = PropertiesService.getScriptProperties().getProperty('bot_token'); //slackアプリ OAuth & PermissionsのBot User OAuth Access Token var channel_id = PropertiesService.getScriptProperties().getProperty('channel_id'); //#helpdeskのチャンネルID var gss_id = PropertiesService.getScriptProperties().getProperty('gss_id'); //スプレッドシートのID var sup_mem1 = PropertiesService.getScriptProperties().getProperty('sup_mem1'); //サポートメンバー1のslackUserID //メンバー数に応じて、必要があれば追加してください。(スクリプトプロパティも) //var sup_mem2 = PropertiesService.getScriptProperties().getProperty('sup_mem2'); //サポートメンバー2のslackUserID var time = new Date(); //投稿時間作成用に現在時刻を取得 //verification tokenの検証 var verification_token = e.parameter.token || JSON.parse(e.parameter.payload).token || null; //リクエストされたトークンを格納 if (verification_token !== verifiy_token) { // アプリのトークンと一致しない場合終了 return ContentService.createTextOutput(); } //----------------------------------------スラッシュコマンドから投稿された場合の処理 if (e.parameter.command === "/helpjosys") { var created_dialog = createDialog(e,bot_token); //ダイアログを作成する var response = UrlFetchApp.fetch("https://slack.com/api/dialog.open", created_dialog); //チャンネルへポストする return ContentService.createTextOutput(); //空文字をreturnしないとダイアログが消えない //----------------------------------------フォーム(Dialog)から投稿された場合の処理 } else { var p = JSON.parse(e.parameter.payload); var s = p.submission; if (p.callback_id === "helpdesk_dialog") { //想定しているフォームからの投稿かチェック //質問者のslack User IDから、メールアドレスと取得 var user_email = findUserBySlackID(p.user.id,bot_token) //スプレッドシートへ記録 var spread_sheet = SpreadsheetApp.openById(gss_id); var sheet_name = "helplist"; var no = spread_sheet.getSheetByName(sheet_name).getLastRow() //現在の最終行を管理Noにする spread_sheet.getSheetByName(sheet_name).appendRow( [no, time, user_email, p.user.id, s.username, //s.*****の*****はfunction createDialogで作成したelementsのnameです s.urgency, s.question_content ] ) //質問者をチャンネルへ招待 var created_invite = createInvite(p.user.id,bot_token,channel_id) var response = UrlFetchApp.fetch("https://slack.com/api/conversations.invite", created_invite); //チャンネルへポスト var message_data = "<@" + sup_mem1 + ">" // サポートメンバー増があれば必要に応じて追加<@" + sup_mem2 + ">" + "\n<@" + p.user.id + "> から問い合わせがありました。" + "\n\n*No*\n" + no + "\n\n*氏名*\n" + s.username + "\n\n*緊急度*\n" + s.urgency + "\n\n*問い合わせ内容*\n" + s.question_content var created_message = createMessage(message_data,bot_token,channel_id) var response = UrlFetchApp.fetch("https://slack.com/api/chat.postMessage", created_message); } return ContentService.createTextOutput(); } return ContentService.createTextOutput(); } //----------------------------------------フォーム(Dialog)作成 function createDialog(e,bot_token){ var trigger_id = e.parameter.trigger_id; var dialog = { "token": bot_token, "trigger_id": trigger_id, "dialog": JSON.stringify( { "callback_id": "helpdesk_dialog", "title": "ヘルプデスクフォーム", "submit_label": "送信する", "elements": [ { "type": "text", "label": "氏名", "name": "username", "placeholder": "佐藤裕也(`ェ´)ピャー" //記入例を表示させたい場合placeholderを使用 }, { "type": "select", "label": "緊急度", "name": "urgency", "options": [ { "label": "低 (1週間以上)", "value": "低 (1週間以上)" }, { "label": "中 (1週間以内)", "value": "中 (1週間以内)" }, { "label": "高 (3日以内)", "value": "高 (3日以内)" }, { "label": "緊急 (当日)", "value": "緊急 (当日)" }] }, { "type": "textarea", "label": "問い合わせ内容", "name": "question_content", "placeholder": "なにもしてないのにパソコンがこわれた" //"optional":"true" ←これを追加することで任意の項目になる(直前にカンマ追加も忘れないよう) } ]} ) } var options = { 'method' : 'POST', 'payload' : dialog } return options; } //----------------------------------------slackIDからメールアドレスを取得 function findUserBySlackID(slackID){ var url="https://slack.com/api/users.info" var payload = { "token" : bot_token, "user" : slackID } var options = { "method" : "GET", "payload" : payload, "headers": { "contentType": "x-www-form-urlencoded", } } var json_data = UrlFetchApp.fetch(url, options); var otp = json_data json_data = JSON.parse(json_data) if (json_data["ok"]){ var user_email = String(json_data["user"]["profile"]["email"]) } else { var user_email = "null" //slackユーザーが居てメールが無いことはないと思いますが念のため } return user_email } //----------------------------------------postMessage作成 function createMessage(message_data,bot_token,channel_id){ var payload = { "token" : bot_token, "channel" : channel_id, "text" : message_data } var options = { "method" : "POST", "payload" : payload, "headers": { "contentType": "x-www-form-urlencoded", } } return options; } //----------------------------------------Invite作成 function createInvite(user_id,bot_token,channel_id){ var payload = { "token" : bot_token, "channel" : channel_id, "users" : user_id } var options = { "method" : "POST", "payload" : payload, "headers": { "contentType": "x-www-form-urlencoded", } } return options; }
スクリプトプロパティの設定
Googleフォーム版と同様に設定してきます。
下記のパラメータを設定します。
sup_mem1
サポートメンバーのslackユーザーID(メンション通知用)
※ユーザーIDの調べ方は別途ググってくださいm(_ _)m
gss_id
スプレッドシートのID
bot_token
slackアプリのOAuth & Permissions → Bot User OAuth Access Token
channel_id
slackのヘルプデスク用チャンネルのID
verify_token
slackのアプリのBasic Information → Verification Token
Verification Tokenはこちら
functionの説明
doPost
メインの処理
createDialog
dialog.openメソッドに必要な中身を作る処理
メイン処理の中に入れるとハイパー見辛いので
findUserBySlackID
slackからユーザーリストを貰い、ユーザーIDを元にメールアドレスを探す処理
createMessage
chat.postMessageメソッドに必要な中身を作る処理
createInvite
channels.inviteメソッドに必要な中身を作る処理
権限のチェック
コードが完成したら、保存して再度公開しましょう。
その際に、新たに権限が必要なコードが追加されていた場合、許可を求められるので許可します。
実行テスト
スラッシュコマンドの実行
コマンド入力→送信
フォームが表示されます(`ェ´)ピャー
入力せずに送ろうとすると怒られます。
slackの通知
入力して送信します。
うまく投稿されました。