ごった煮

色々な事を書いてます

Botのv3対応について

Bot Framework v3への更新に際してかなり大幅な変更があるのでとりあえずベースの部分だけまとめます。

初めに

V3対応前の最終バージョンのEmulatorを開くと以下のように警告が出ます。

image

hereの部分から更新用のリンクに飛べるのでそこで更新しましょう。

v3対応Emulator

hereのところから入れると、古いEmulatorの更新じゃなくて新規アプリケーションとしてインストールされるようです。

バージョン番号は、3.0.0.54のようです。

アプリ名も以前のものは、Microsoft Bot Framework EmulatorだったのがMicrosoft Bot Framework Channel Emulatorに名称が変わっています。

image

挙動もちょこちょこ変わっているので動かしてみます。

 

v1デフォルトでの動作

以前配布されていたテンプレート(v1.0.0)で実行してメッセージを投げると下記のように失敗します。

image

v3対応

結構大幅に変わってて辛いです。

設定ファイル

v1の設定ファイル

  
<add key="AppId" value="YourAppId" /> <add key="AppSecret" value="YourAppSecret" />

 

AppIdとAppSecretを記述する必要がありました。

v3の設定ファイル

    
<add key="BotId" value="YourBotId" />
<add key="MicrosoftAppId" value="" />
<add key="MicrosoftAppPassword" value="" />

 

AppId、AppSecretの代わりに

BotId、MicrosoftAppId、MicrosoftAppPasswordの3つを設定するように変更になります。

この中のMicrosoftAppIdとMicrosoftAppPasswordをEmulatorの上部に入れます。

image

公式のドキュメントだとBot Idの入力欄も用意されているように見えますが、公式の画像が3.0.0.49になっていて、最新版は、3.0.0.54になってBot Idの入力欄が省かれているので必要ないようです。

ちなみにローカルのBotに対してAppIdとAppPasswordを空白以外にしてEmulatorにもその値を入れると認証失敗で通信にコケるので一旦入力しないようにしたほうがよさそうです。

ライブラリ

Bot Builder、Bot Connectorのライブラリも3.0.0に変更されています。

3.0.0にしないとv3用のEmulatorと通信できません。

現在NuGetからBot Connectorを入れようとすると1.1.0が最新として公開されていて3.0.0が手に入らないように見えますが、Bot Builderを入れると自動的にBot Connectorの3.0.0も入るのでBot Builderだけ入れましょう。

 

ソースコードの改変

下記のコードは、v1用のコードです。

v3にするとほぼ完全に名称変更されたりして完全に互換性がないので修正します。

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using Microsoft.Bot.Connector;
using Newtonsoft.Json;

namespace v3Sample
{
    [BotAuthentication]
    public class MessagesController : ApiController
    {
        /// 
        /// POST: api/Messages
        /// Receive a message from a user and reply to it
        /// 
        public async Task Post([FromBody]Message message)
        {
            if (message.Type == "Message")
            {
                // calculate something for us to return
                int length = (message.Text ?? string.Empty).Length;

                // return our reply to the user
                return message.CreateReplyMessage($"You sent {length} characters");
            }
            else
            {
                return HandleSystemMessage(message);
            }
        }

        private Message HandleSystemMessage(Message message)
        {
            if (message.Type == "Ping")
            {
                Message reply = message.CreateReplyMessage();
                reply.Type = "Ping";
                return reply;
            }
            else if (message.Type == "DeleteUserData")
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == "BotAddedToConversation")
            {
            }
            else if (message.Type == "BotRemovedFromConversation")
            {
            }
            else if (message.Type == "UserAddedToConversation")
            {
            }
            else if (message.Type == "UserRemovedFromConversation")
            {
            }
            else if (message.Type == "EndOfConversation")
            {
            }

            return null;
        }
    }
}

 

v3用のベースコードは、下記のような感じになります。

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using Microsoft.Bot.Connector;
using Newtonsoft.Json;

namespace v3Sample2
{
    [BotAuthentication]
    public class MessagesController : ApiController
    {
        /// 
        /// POST: api/Messages
        /// Receive a message from a user and reply to it
        /// 
        public async Task Post([FromBody]Activity activity)
        {
            if (activity.Type == ActivityTypes.Message)
            {
                ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
                // calculate something for us to return
                int length = (activity.Text ?? string.Empty).Length;

                // return our reply to the user
                Activity reply = activity.CreateReply($"You sent {activity.Text} which was {length} characters");
                await connector.Conversations.ReplyToActivityAsync(reply);
            }
            else
            {
                HandleSystemMessage(activity);
            }
            var response = Request.CreateResponse(HttpStatusCode.OK);
            return response;
        }

        private Activity HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                // Handle conversation state changes, like members being added and removed
                // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
                // Not available in all channels
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }

            return null;
        }
    }
}

 

以前のコードでは、Botとのやり取りは、大体WebAPIのリクエストとレスポンスの一対一のやり取りをメインに据えている感じでしたが、

このコードを見る限りだと、POSTのレスポンスにメッセージを乗せるのではなく、ConnectorClientクラスでBot Connectorと明示的に接続してReplyToActivityAsyncメソッドでメッセージを送信する形を推奨するのかなって感じです。

また、今までMessageクラスをメッセージの一つの単位として扱ってましたが、これからは、Activityクラスを使うようになるようです。というかMessageクラスは、消滅したっぽいので気を付けましょう。

このコードを使うと、v3用のEmulatroと下記のように通信できます。

image

 

v3用のEmulatorで通信出来たら、一応v3対応ができたのではないかと思われます。

まとめ

とりあえず公式の提供するテンプレートを使ってざっくりv1とv3の変更点とどうすればv3用になるのかをざっくりまとめました。

v1はバージョン番号の扱い的に完全にベータ扱いっぽい雰囲気でしたがここまで変更してくるのは想定外です。

すさまじい量の変更点があるっぽいので誰かまとめてください。