moto blog

SlackとGASで作るおもしろ雑談Bot

f:id:nmmmk:20180503172932j:plain GAS(Google Apps Script)とdocomo雑談対話APIを使用して、SlackのChat Botを作成します。 Botに話しかけると、気の利いた言葉(面白い言葉)を返してくれて、楽しいですよ〜(^ ^)

GASを使用すると、サーバレスで気軽にBotを作ることができますのでオススメです!

本記事で使用しているdocomo雑談対話APIが提供終了となりました。
新しいAPIであるdocomo自然対話(雑談対話)APIを利用した記事となっている、以下を参照ください。

nmmmk.hatenablog.com

構造

  1. Slack上のBotに話しかける。
  2. GASでメッセージを受信する
  3. GASからdocomo雑談対話APIにメッセージを送信する
  4. GASにdocomo雑談対話APIから回答が返ってくる
  5. GASからSlackへdocomo雑談対話APIの回答を送信する

f:id:nmmmk:20181029190128p:plain

Slackの設定

Incoming Webhooksの設定

GASからメッセージを受け取れる様に、Incoming Webhooksの設定を行います。
以下にアクセスして設定してください。
https://api.slack.com/apps

  1. Create New Appを押下します。 f:id:nmmmk:20180502142058p:plain

  2. 作成するBotの名称設定と対象のワークスペースを選択します。 f:id:nmmmk:20180502112518p:plain

  3. Incoming Webhooksの設定をONにします。 f:id:nmmmk:20180502134810p:plain

  4. Add a Bot Userを押下します。 f:id:nmmmk:20180502134836p:plain

  5. Botの名称を設定します。 f:id:nmmmk:20180502134852p:plain

  6. アプリケーションをインストールします。 f:id:nmmmk:20180502134918p:plain

  7. 投稿先を設定します。 f:id:nmmmk:20180502135027p:plain

  8. Botのアイコンを設定します(任意) f:id:nmmmk:20180502135354p:plain

  9. Incoming WebhooksのURLを確認します。
    GASの実装でこのURLを使用します。 f:id:nmmmk:20180502135558p:plain

Outgoing Webhooksの設定

GASへメッセージを送信できる様に、Outgoing Webhooksの設定を行います。
App管理へ移動し、カスタムインテグレーションを設定後、Outgoing Webhooksの設定をしてください。

  1. 引き金となる言葉には、メッセージの送信相手+「:」と考えてください。
    例えば、以下の様な投稿の仕方となります。
    例)ZatsudanBot: テストメッセージ

  2. URLの部分は、後述するGASのURLを設定します。

  3. トークンの部分はGASで使用します。 f:id:nmmmk:20180502140131p:plain

docomo雑談対話APIの登録

今回使用するのは、docomo雑談対話APIです。 https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_name=dialogue&p_name=api_referencedev.smt.docomo.ne.jp

必要事項を入力して、APIを申請し、APIキーを取得します。 f:id:nmmmk:20180502104656p:plain

GASでSlackからのメッセージを受け取れる様にする

基本となるソースコード

doPost()でSlackからのメッセージを受け取ります。
また、addLog()で受信した情報をスプレッドシートに書き込みます。

XXXXXの部分は、Outgoing Webhooks設定時に割り当てられたトークンを使用してください。
YYYYYの部分はスプレッドシートのID、ZZZZZの部分はシート名を指定してください。

スプレッドシートのIDは、スプレッドシートのURLの下記の部分です。
https://docs.google.com/spreadsheets/d/スプレッドシートのID/edit#gid=0

//-----------------------------
// Slackからのメッセージ受信
//-----------------------------
function doPost(e) {

  // SlackのOutgoing WebhooksのTokenであるかを比較
  if (e.parameter.token != "XXXXX") {
    return;
  }
  
  // テキスト部を抜き出し
  var text = e.parameter.text;

  // 「:」でテキスト分割する
  text = text.split(":");
  
  if (text[1].length > 1) {
    
    addLog(text[1]);
  }
}

//-----------------------------
// スプレッドシートへのログ出力
//-----------------------------
function addLog(text) {
  var spreadsheetId = "YYYYY";
  var sheetName = "ZZZZZ";
  var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
  var sheet = spreadsheet.getSheetByName(sheetName);
  sheet.appendRow([new Date(),text]);
  return text;
}

GASをウェブアプリケーションとして公開する

  1. スクリプトエディタにて公開 -> ウェブアプリケーションとして導入 を選択します。 f:id:nmmmk:20180502115443p:plain

  2. 公開設定を行います。 以下の様に設定します。
    プロジェクトバージョンは、新規作成
    アプリケーションにアクセスできるユーザーは、全員(匿名ユーザーを含む)
    f:id:nmmmk:20180502152239p:plain

  3. 割り当てられたURLをSlackのOutgoing WebhooksのURLに設定します。 f:id:nmmmk:20180502152225p:plain

ソースコードを修正した場合は、1, 2の手順を毎回行う必要がありますので注意してください。

Slackからメッセージを送信する

以下の様にメッセージを送信します。
ZatsudanBot: テスト

f:id:nmmmk:20180502222544p:plain

スプレッドシートを確認すると、「テスト」が記録されていますのでGASでのメッセージ受信ができていることが分かります。
f:id:nmmmk:20180502222310p:plain

メンションの変換文字列を取得する

現時点では、メンションでの呼び出しに対応していません。
@ZatsudanBot テスト と投稿しても反応しません。
仮に、Outgoing Webhooksの「引き金となる言葉」を「@ZatsudanBot」に変更しても、期待した動作とはなりません。

「@ZatsudanBot」が「 <@UAG876W49>」の様なユーザーID文字列に変換されているためです。

ユーザーID文字列を取得するために、以下のメッセージを送信します。
ZatsudanBot: @ZatsudanBot
f:id:nmmmk:20180502220727p:plain

スプレッドシートを参照すると、「 <@UAG876W49>」の記載があることが分かります。
これがユーザーIDです。

f:id:nmmmk:20180502220740p:plain

取得したIDをOutgoing Webhooksの「引き金となる言葉」に設定します。

f:id:nmmmk:20180502221127p:plain

Slackへの投稿処理を準備する

XXXXXの部分は、 Incoming Webhooksの設定時に取得した投稿先のチャンネルのURL を設定してください。

function postSlack(text) {
  // Incoming WebhooksのURL
  var url = "XXXXX";
  
  var payload = {
    text: text
  };
 
  var options = {
    "method" : "POST",
    "headers": {"Content-type": "application/json"},
    "payload": JSON.stringify(payload)
  };
  UrlFetchApp.fetch(url, options); 
}

docomo雑談対話APIとの送受信処理を準備する

XXXXXの部分は雑談対話API KEYを設定してください。

//-----------------------------
// docomo雑談APIにメッセージを送信し、回答を受け取る
//-----------------------------
function getDialogueMessage(mes) {
  var dialogue_options = {
    'utt': mes
  }
  var options = {
    'method': 'POST',
    'contentType': 'text/json',
    'payload': JSON.stringify(dialogue_options)
  };

  // APIのURL
  var dialogueUrl = "https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=XXXXX";
  
  // API実行
  var response = UrlFetchApp.fetch(dialogueUrl, options);

  // 回答を受信する
  var content = JSON.parse(response.getContentText());

  return content.utt;
}

メンションでBotに話かけられる様にする

メンションでのBot呼び出しに対応するため、doPost()を以下の様に変更します。
XXXXXの部分は、Outgoing Webhooks設定時に割り当てられたトークンを使用してください。

※addLog()は削除しましたが、必要に応じて実装してください。

function doPost(e) {

  // SlackのOutgoing WebhooksのTokenであるかを比較
  if (e.parameter.token != "XXXXX") {
    return;
  }
  
  // テキスト部を抜き出し
  var text = e.parameter.text;
  
  // <@YYYYYYYYY>の部分は削除
  text = text.substring(13);
  
  if (text.length > 1) {
    
    var message = "<@"+e.parameter.user_id+"> " + getDialogueMessage(text);
    
    postSlack(message);
  }
}

最終ソースコード

全体

//-----------------------------
// Slackからのメッセージ受信
//-----------------------------
function doPost(e) {

  // SlackのOutgoing WebhooksのTokenであるかを比較
  if (e.parameter.token != "XXXXX") {
    return;
  }
  
  // テキスト部を抜き出し
  var text = e.parameter.text;
  
  // テキスト部を抜き出し
  var text = e.parameter.text;
  
  // <@YYYYYYYYY>の部分は削除
  text = text.substring(13);
  
  if (text.length > 1) {
    
    var message = "<@"+e.parameter.user_id+"> " + getDialogueMessage(text);
    
    postSlack(message);
  }
}

//-----------------------------
// docomo雑談APIにメッセージを送信し、回答を受け取る
//-----------------------------
function getDialogueMessage(mes) {
  var dialogue_options = {
    'utt': mes
  }
  var options = {
    'method': 'POST',
    'contentType': 'text/json',
    'payload': JSON.stringify(dialogue_options)
  };

  // APIのURL
  var dialogueUrl = "https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=XXXXX";
  
  // API実行
  var response = UrlFetchApp.fetch(dialogueUrl, options);

  // 回答を受信する
  var content = JSON.parse(response.getContentText());

  return content.utt;
}

//-----------------------------
// Slackへ投稿
//-----------------------------
function postSlack(text) {
  // Incoming WebhooksのURL
  var url = "XXXXX";
  
  var payload = {
    text: text
  };
 
  var options = {
    "method" : "POST",
    "headers": {"Content-type": "application/json"},
    "payload": JSON.stringify(payload)
  };
  UrlFetchApp.fetch(url, options); 
}

実行してみる!

f:id:nmmmk:20180502223956p:plain

ごもっともです・・・