リクルートの提供するAPIを使ってそれっぽいAsureBotを作る

online.kosen-career.tech こちらのイベントでそれっぽいAsureBotを作ったのでその手順を備忘録。 基本的な環境構築からオウム返しBotまでは以下を参照。 qiita.com 無料で使えるそれっぽいAPIを探したところA3RTというものがリクルートから提供されていたので、これをBotに組み込むことを目標とする。 a3rt.recruit-tech.co.jp EchoBot.csの初期状態を読むと

  • OnMessageActivityAsyncでメッセージ送信時の反応
  • OnMembersAddedAsyncで接続時の最初のメッセージ

を行っていることが分かる。

なので基本的にはOnMessageActivityAsyncの方を拡張していくような形。今回はBot上で画像を扱ってみたかったこともあり、ImageSearchAPIを使ってみた。
Image Search API | PRODUCT | A3RT
結果画像の送信はこちらのプログラムを参考にして実装した。
メッセージにメディアを追加する - Bot Service | Microsoft Docs

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using System.IO;

namespace Microsoft.BotBuilderSamples.Bots
{
    public class EchoBot : ActivityHandler
    {
        protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            var replyText = $"{turnContext.Activity.Text}";

            //API処理
            string search_word = replyText;
            WebRequest request = WebRequest.Create("https://api.a3rt.recruit-tech.co.jp/image_search/v1/search_by_text?apikey=AAAAAAAAAAAAAAAAAAAAAAAA&query=" + search_word);
            WebResponse response = request.GetResponse();

            using (Stream dataStream = response.GetResponseStream())
            {
                // Open the stream using a StreamReader for easy access.
                StreamReader reader = new StreamReader(dataStream);
                // Read the content.
                string responseFromServer = reader.ReadToEnd();

                string jsonString = JsonConvert.SerializeObject(responseFromServer);

                JObject deserial = (JObject)JsonConvert.DeserializeObject(responseFromServer);

                string send_img = deserial["result"]["img"][0]["url"].ToString();

                //返信処理
                IMessageActivity reply = null;
                reply = MessageFactory.Text("This is an inline attachment.");
                reply.Attachments = new List<Attachment>() { GetInternetAttachment(send_img) };

                await turnContext.SendActivityAsync(reply, cancellationToken);
            }

            // Close the response.
            response.Close();
        }

        protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            var welcomeText = "Hello and welcome!";
            foreach (var member in membersAdded)
            {
                if (member.Id != turnContext.Activity.Recipient.Id)
                {
                    await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText, welcomeText), cancellationToken);
                }
            }
        }

        private static Attachment GetInternetAttachment(string img_url)
        {
            // ContentUrl must be HTTPS.
            return new Attachment
            {
                Name = @"Resources\architecture-resize.jpg",
                ContentType = "image/jpg",
                ContentUrl = img_url,
            };
        }
    }
}

これを実行してみるとこんな感じ

 f:id:massiro-myaon:20210320172212j:plain

画像の数には限りがあるみたいで、見当違いな結果になることも多いが、キーワード次第でそれっぽい結果を返す。 今はJson内の1つ目の画像URLを参照しているが、全部表示or最も類似するものを推定みたいなことが出来るといいかもしれない。

C# による JSON 相互変換 (Json.NET 利用) - clock-up-blog

基本的に他のAPIもリクエストするURLと受け取ったJsonの読み方を変えてやることでほぼ全部実装可能。必要に応じて組み合わせて見てほしい。