bot

ユーザの投稿メッセージに応答するSkypeボットをGoogle Apps Scriptで作成する手順

はじめに

ユーザの投稿メッセージに応答するSkypeボットをGoogle Apps Scriptで作成する手順をメモします。

できるようになること

Skypeにてユーザからボットのへの投稿メッセージに応じて適当なメッセージを送り返すボットをGoogle Apps Scriptで作成します。ここではあらかじめ決めたメッセージを返すだけですが、この記事での内容を元に色々な応用に使えると思います。
なお、ユーザの投稿に関わらず任意のタイミングでボットからメッセージを送りたい場合は、Skypeにメッセージを投稿するSkypeボットをGoogle Apps Scriptで作成する手順にまとめています。

動作イメージ図

今回作成するSkypeボットの動作イメージ図になります。

上記の動作イメージ図に登場する要素は以下の3つです。

  • ボット:Google Apps Scriptで作成
  • エンドポイント:ユーザからボットへのメッセージを受信するサーバです。ここでは、エンドポイントとしてGoogle Apps Scriptを指定し、ユーザからボットへのメッセージをGoogle Apps Scriptで受信して処理できるようにします。
  • Bot Connector:作成したボットとチャットサービス(ここではSkype)を繋げるサービス。例えば、今回はGoogle Apps ScritpからこのBot Connectorにメッセージを送ると、そのメッセージをBot ConnectorがSkypeに転送してくれます。

前提と環境と必要となるもの

以下を前提としています。

  • Googleアカウントは取得済とする。Google Apps Script使用のため。
  • Microsoftアカウントは取得済とする。Microsoft Azure使用のため。
  • Microsoft Azure上で何かしらのボットを作成済とします。Microsoft Azureには、ボットテンプレートというボットの元となるものがいくつか用意されており、その中の「Basic」を使用すれば簡単に素の状態に近いボットを作成できます。詳しくはMicrosoft Bot FrameworkでSkypeのエコーボットを作成する手順にまとめていますのでまだ作成していない場合はご覧ください。この記事での作業が前提となっています。
  • Microsoft App IDとパスワードは取得済とする。(取得方法はこちらMicrosoft App IDとパスワードの取得手順

Skypeボットのエンドポイントを変更する

まずGoogle Apps ScriptでSkypeからのメッセージを受信するには、Microsoft Azureのダッシュボード上で、ボットの「エンドポイント」を変更する必要があります。このエンドポイントとは、ユーザからボットに対するメッセージの受信先です。ボットの置き場所と言ってもいいかもしれません。このエンドポイントのURLをGoogle Apps Scriptで作成したWebアプリケーションのURLに変更し、Google Apps Script側で適切な処理をすればユーザからのボットに対するメッセージを受信することができ、さらに受信したメッセージに応じて任意の応答をユーザに返すことができます。
Microsoft Azure上で、作成したボットのダッシュボードには、以下の赤線枠のようにエンドポイントが記載されています。

デフォルトでは、以下のようなURLになっています。

デフォルトのエンドポイントhttps://ボット名.azurewebsites.net/api/messages

エンドポイントを変更するには、以下のように左メニューにある「設定」をクリックし、その中にある「構成」の「メッセージング エンドポイント」に好きなURLを指定します。以下では、Webアプリケーションとして公開しているGoogle Apps ScriptのURLを指定しています。なお、念のためにデフォルトのエンドポイントはどこかにメモしておきましょう。エンドポイントを変更したら、最後に「保存」をクリックします。

以上でエンドポイントの変更は完了です。

メモ

エンドポイントとは

エンドポイントとは、Skypeなどのチャットアプリにおいて、ユーザからボットへのメッセージが届く場所です。具体的には、サーバのURLになります。ユーザがボットに対してメッセージを送信すると、そのメッセージがエンドポイントに届きます。おそらくどのチャットアプリでもおおよそ同じですが、作成したボットでは大体エンドポイントを設定できます。通常であれば、そのチャットアプリ側が用意してくれているエンドポイントがデフォルトで設定されていますが、このエンドポイントを自分の好きなURLに変更することができます。例えば、自前のVPSのサーバを指定したり、Google Apps Scriptのウェブアプリケーション、その他のクラウドサービス上のサーバなどをもちろん指定できます。

ユーザの投稿メッセージに応答するSkypeボットのGoogle Apps Scriptコード

エンドポイントの変更により、ユーザからボットに対して投稿されたメッセージは指定したGoogle Apps Scriptに届くようになります。そこでGoogle Apps Script側ではユーザから送信されてきたメッセージを処理し、応答するための処理を記述します。なお、ユーザからのメッセージを含むデータはJSON形式でHTTP POSTリクエストがエンドポイントに届きます。したがって、記述する処理は、POSTリクエストを受信し、受信したJSONデータから必要な情報を抽出した上でレスポンスを返すという流れになります。以下がそのためのGoogle Apps Scriptのコードになります。

function doPost(e) {
  
  // 受信するJSONデータから必要な情報を抽出。受信するJSONデータの中身は後述。
  var params = JSON.parse(e.postData.getDataAsString());  // 受信したPOSTリクエストに含まれるJSONデータを解析
  var conversationID = params.conversation.id;            // チャットを特定するためのConversation ID
  var activityID = params.id;                             // 後述
  var sender = params.recipient;                          // 送信者情報(ボットのID、名前)
  var receiver = params.from;                             // 返答先の情報(メッセージを送信したユーザのID、名前)
  var baseURL = params.serviceUrl;                        // ボットの応答内容を送り返すURL。Microsoft公式ドキュメント
  var conversation = params.conversation;                 // Conversation IDとグループチャットかどうかの情報

  // Bot ConnectorのURL。ここにボットからユーザへの応答内容を送ります。baseURLとConversation IDとActivity IDから組み立て
  var POST_URL = baseURL + "/v3/conversations/" + conversationID + "/activities/" + activityID;

  // ボットの応答内容
  var payload = {
    "type": "message",
    "from": sender,
    "conversation": conversation,
    "recipient":receiver,
    "text": "My bot's reply", // ボットの応答内容メッセージ
    "replyToId": activityID
  };
  
   var accesstoken = getAccessToken(); // アクセストークン

   // ボットの応答内容含むデータ
   var options = {
    'method': 'post',
    'Content-Type': 'application/json',
    'headers': {
      'Authorization': 'Bearer ' + accesstoken
    },
    'payload':  JSON.stringify(payload)
  };
  
  // 確認のためにスプレッドシートにログ
  addLog("payload is " + JSON.stringify(payload));
  
  UrlFetchApp.fetch(POST_URL, options);
}

// アクセストークン取得用関数
function getAccessToken(){
  
  var url        = 'https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token';
  var APPID      = 'Microsoft APP ID';
  var APP_PASS   = 'Microsoft APP IDのパスワード';
  var requestBody = 'grant_type=client_credentials&client_id=' + APPID + '&client_secret=' + APP_PASS + '&scope=https%3A%2F%2Fapi.botframework.com%2F.default';

  var options = {
      'method' : 'post',
      'contentType': 'application/x-www-form-urlencoded',
      'payload' : requestBody
  };
  
  var accesstoken = '';
 
  try {
         var response = UrlFetchApp.fetch(url, options);
         accesstoken = (JSON.parse(response.getContentText())).access_token;
         addLog(accesstoken);
    
       } catch (er) { //エラー発生時にログを記録
         var logText = "エラー : line - " + er.lineNumber + '\n Error: ' + er.message;
         addLog(logText);
       }
  
  return accesstoken;
}

// ログ取得用関数
function addLog(text) {
  var spreadsheetId = "スプレッドシートID";
  var sheetName = "スプレッドシート名";
  var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
  var sheet = spreadsheet.getSheetByName(sheetName);
  sheet.appendRow([new Date()/*タイムスタンプ*/,text]);
}

上記を見てわかるとおり、以下の3つの関数に分かれています。

  • doPost(e):POSTリクエストを受信して処理する関数。Google Apps Script公式に用意されている関数です。
  • getAccessToken():アクセストークンを取得するための関数
  • addLog(text) :ログを記録するための関数です。
メモ

Activity IDについて

Conversation IDがチャットを識別するためのものであるのに対し、Activity IDは特定のチャット内における各メッセージやイベント(ユーザをグループに招待、ユーザがグループから退出など)に対するIDになります。

エンドポイントが受け取るJSONデータの中身

Skype上でユーザがボット宛にメッセージを投稿すると、以下の内容のJSONデータがエンドポイント、すなわちここではGoogle Apps Scriptに届きます。前述したコードでは、これをdoPost関数で受け取って処理しています。

{
    "text": "myBot Hello !", // 送信されたメッセージ内容
    "type": "message",
    "timestamp": "2018-10-07T23:55:12.384Z",
    "id": "2349862469489",
    "channelId": "skype", // メッセージが送信されたアプリ
    "serviceUrl": "https://smba.trafficmanager.net/apis/",
    "from": { // ボットに対してメッセージを送信したユーザのID、名前
        "id": "45:403687230-46889023j49f843920jfy0493j0f",
        "name": "satoshi"
    },
    "conversation": {
        "isGroup": true, // グループチャットであるかどうか
        "id": "19:240685y32pnjf8094760234867023j4@thread.skype" // Conversation ID
    },
    "recipient": { // メッセージ受信者の情報。ここではボットのIDと名前
        "id": "28:2436957fnj792046yhd87902ht45", 
        "name": "myBot"
    },
    "entities": [{
        "mentioned": {
            "id": "28:2436957fnj792046yhd87902ht45"
        },
        "text": "myBot",
        "type": "mention"
    }, {
        "locale": "ja-JP",
        "country": "JP",
        "timezone": "Asia/Singapore",
        "type": "clientInfo"
    }],
    "channelData": {
        "text": "myBot Hello !"
    }
}

ボットから返すJSONデータの中身

ボットからは以下のJSONデータを返します。以下のようなデータをすでに述べたdoPost(e)関数の中で作成しています。見てわかるとおり、基本的に受信したJSONデータをそのまま再利用しています。ボットからユーザに返す以下のJSONデータとボットがユーザから受け取ったJSONデータは、from(メッセージの送信者、すなわちボット)とrecipient(メッセージの受信者、すなわちユーザ)が入れ替わっている点に注意です。

{
    "type": "message",
    "from": {
        "id": "28:2436957fnj792046yhd87902ht45",
        "name": "myBot"
    },
    "conversation": {
        "isGroup": true,
        "id": "19:240685y32pnjf8094760234867023j4@thread.skype"
    },
    "recipient": {
        "id": "45:403687230-46889023j49f843920jfy0493j0f",
        "name": "satoshi"
    },
    "text": "My bot's reply",
    "replyToId": "2349862469489"
}

まとめ

Google Apps Scriptを使って、Skypeに投稿されるユーザのメッセージに応答できるボットを作成しました。エンドポイントの変更とdoPostでのデータ受信、応答処理が分かれば、後はGoogle Apps Scriptでできることを組み合わせて色々な応用ができると思います。

SPONSORED LINK

コメントを残す

メールアドレスが公開されることはありません。