コンソールアプリからBot Frameworkを使ってBotからクライアントにメッセージを送る


Microsoft の Bot Framework を使った Botアプリケーションの開発にハマっています(楽しい方の意味で)。

自作BotをAzureにデプロイしてSkypeで対話

まず、

このあたりの情報を元に、

  • 簡単な Bot アプリをビルドして Botエミュレータで実行してみる
  • その Bot を Azure にデプロイする
  • Azure に配置した Bot を Skype と繋げる
  • 自分の Skype アカウントと Bot で対話する

まで行うことができました。

コンソールアプリから Skype のユーザー(クライアント)へメッセージを送信する

さて、私が本当にやりたいのは「定期的にBotからユーザーへメッセージを送る(時報とか)」ことです。
が、 Visual Studio の Bot Application のプロジェクトテンプレートでは?(あるいは「Botアプリケーション」では)、処理の起点は必ずユーザー(クライアント)からBotへのメッセージ送信をBotが受信するところから始まるようです(違ってたら教えてください)。

Bot Framework の REST API には Send and receive messages もあるので、任意のタイミングでメッセージを送信することも可能なはず。

いろいろ探していたら

という情報を発見。おお、コンソールアプリからメッセージを送信できれば、これをcron的なものやAzure Functionsで定期的に実行させられそうです。

コード例を元に悪戦苦闘した結果、下のようなコードでメッセージ送信ができました。

// Program.cs
static void Main(string[] args)
{
    var serviceUrl = "https://smba.trafficmanager.net/apis/";
    var appId = "<APP_ID>";
    var appPassword = "<APP_PASSWORD>";

    MicrosoftAppCredentials.TrustServiceUrl(serviceUrl); ※これがないと認証エラーになる
    var connector = new ConnectorClient(new Uri(serviceUrl), appId, appPassword);
    var botAccount = new ChannelAccount(id: "28:8734b597-b313-2457-bda6-d7c342245fea"); // 送信元(Botの)ユーザー ※IDは適当だけどこんな感じの文字列だった
    var userAccount = new ChannelAccount(id: "29:2WLwfakXxSbEze4gfeGxeS31nXfELePLX3deELoxHw"); // 送信先ユーザー ※IDは適当だけどこんな感じの文字列だった
    var res = connector.Conversations.CreateDirectConversation(botAccount, userAccount);

    IMessageActivity message = Activity.CreateMessageActivity();
    message.From = botAccount;
    message.Recipient = userAccount;
    message.Conversation = new ConversationAccount(id: res.Id);
    message.Text = "こんにちわ";
    message.Locale = "ja-Jp";
    connector.Conversations.SendToConversation((Activity)message);
}

以下、ポイント

  • コンソールアプリプロジェクトを作ったら、ターゲットフレームワークを .NET Framework 4.6 に上げる(4.5 だと Bot.Builder が入れられなかった)
  • Nugetパッケージマネージャから「Microsoft.Bot.Builder」を入れる(ここで入れたのは v3.8.0 です)
  • <APP_ID>、<APP_PASSWORD>は、Botを https://dev.botframework.com/ に登録する仮定で得られるやつ
  • MicrosoftAppCredentials.TrustServiceUrl(serviceUrl) をしないと、CreateDirectConversation で認証(401)エラーになりました。 Bot Framework Unauthorized when creating a conversation (C#) - Codedump.io が大変役に立ちました。
  • serviceUrl は、なんかよく分からんけどこれらしい
  • serviceUrlbotAccount のId、 userAccount のIdは、BotBuilder-Samples/CSharp/core-GetConversationMembers も参考にして、Bot ApplicationのHelloWorldを改造して取得しました。

このプログラムを実行すると、 userAccount が示すSkypeユーザー(ここでは私)に「こんにちわ」のメッセージが送信されます、やった!

今作りたいと思っているのは「タイムカード打刻BOT」で、月末に EXCEL に退勤時間を書くのが面倒なので、毎日、18:00 になったら、Botに「仕事おわった?」と聞いて欲しいのです。「はい」と回答すればその時刻を打刻、「いいえ」と答えたら1時間後にまた聞いてくる・・・、という感じで(弊社は Skype 常時起動させてるから Skype で試してるけど Bot Connector により Slack などの別ツールにも対応できるはず)。

これを行うには、クライアント起点の対話でなく、BOT起点の対話が必要で、コンソールアプリからメッセージ送信することができたので、次はAzure Functionでやってみようかと思います。

BOT開発、しばらく楽しめそうです。