Фреймворк ботов, реализующий пользовательский коннектор "client.Conversations.GetActivities (dialogId, watermark)", возвращающий несколько действий - PullRequest
0 голосов
/ 05 июня 2018

Я пытаюсь реализовать пользовательский соединитель для моего бота Microsoft внутри webapi, чтобы его можно было вызывать из разных приложений через Rest API (например, из rasberripy). Цель состоит в том, чтобы внедрить пользовательский соединитель в WebAPIиспользуя прямой API, чтобы другое приложение могло просто использовать вызовы rest для связи с этим API, который, в свою очередь, будет общаться с моим ботом с помощью API dirtectline.Я протестировал следующий код от micrososft , который работает внутри консольного приложения.Я переместил тот же код в WebAPI, здесь тот же код ведет себя по-разному.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Threading.Tasks;
using Microsoft.Bot.Connector.DirectLine;
using Newtonsoft.Json;
using System.Configuration;

namespace BotConnector.Web.Controllers
{
public class BotController : Controller
{

    private static string directLineSecret = ConfigurationManager.AppSettings["DirectLineSecret"];
    private static string botId = ConfigurationManager.AppSettings["BotId"];
    private static string fromUser = "APISampleClientUser";

    // GET: Bot
    public ActionResult Index()
    {
        return View();
    }

    public string Connect()
    {
        var conversation=StartBotConversation();
        return conversation.ConversationId;
    }

    public string ReadBotMessages(string conversationId,string message)
    {

        //DirectLineClient client = (Session["client"] == null) ? new DirectLineClient(directLineSecret) : Session["client"] as DirectLineClient;
        //Session["client"] = client;

        DirectLineClient client = new DirectLineClient(directLineSecret);

         var activity = new Activity
        {
            From = new ChannelAccount(fromUser),
            Text = message,
            Type = ActivityTypes.Message
        };

        client.Conversations.PostActivityAsync(conversationId, activity);
        var response = ReadBotMessagesAsync(client, conversationId);

        //var heroCard = JsonConvert.DeserializeObject<HeroCard>(response[0].Content.ToString());
        return response.Result;
    }

    private static Conversation StartBotConversation()
    {
        //var session = System.Web.HttpContext.Current.Session["client"];
        //DirectLineClient client = (session == null) ? new DirectLineClient(directLineSecret) : session as DirectLineClient;
        //System.Web.HttpContext.Current.Session["client"] = client;
        var client = new DirectLineClient(directLineSecret);

        var conversation = client.Conversations.StartConversationAsync().Result;

        //new System.Threading.Thread(async () => await ReadBotMessagesAsync(client, conversation.ConversationId)).Start();

        return conversation;
    }


    private static async Task<string> ReadBotMessagesAsync(DirectLineClient client, string conversationId)
    {
        string watermark = null;
        var attachments = new List<Attachment>();
        string message = string.Empty;

        while (true)
        {
            var activitySet =  client.Conversations.GetActivities(conversationId, watermark);
            watermark = activitySet?.Watermark;

            var activities = from x in activitySet.Activities
                             where x.From.Id == botId
                             select x;

            foreach (Activity activity in activities)
            {
                message = activity.Text;

                if (activity.Attachments != null)
                {
                    foreach (Attachment attachment in activity.Attachments)
                    {
                        if (attachment.ContentType== "application/vnd.microsoft.card.hero")
                        {
                            var heroCard = JsonConvert.DeserializeObject<HeroCard>(attachment.Content.ToString());
                            message = heroCard.Text;
                            //attachments.Add(attachment);
                        }
                    }
                }
            }
            //if (attachments.Count > 0) break;
            if (!string.IsNullOrEmpty(message)) break;


            //await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
        }

        return message;
    }

}

}

Сначала я позвоню Bot / Connect, чтобы сгенерировать Идентификатор разговора, а позже я 'Позвоню Bot / ReadBotMessages с идентификатором и пользовательским вопросом.

Проблема, с которой я сталкиваюсь, заключается в коде

var activitySet = client.Conversations.GetActivities(conversationId, watermark);, возвращающем несколько действий каждый раз при получении удара, а также ответы на предыдущие вопросы (Image here), но я должен получить одно действие, связанное с текущим ответом. Та же логика прекрасно работает в консольном приложении от github , который возвращает только одно единственное текущее действие.Кто-нибудь может предложить обходной путь, или я делаю что-нибудь еще?

1 Ответ

0 голосов
/ 05 июня 2018

Чтобы получить самые последние действия, вам нужно сохранить текущий водяной знак где-нибудь в вашем соединителе.

Вызов следующего метода:

Client.Conversations.PostActivityAsync(conversationId, activity);

вернет строку в следующем формате:

"IRBO9ZhxkwID1QnNbAoOHX|0000008"

т.е.

"{ConversationId|Watermark}"

Youзахочет сохранить часть водяного знака этого вызова где-нибудь в вашем соединителе, так как использование его позже в вызове приема сообщений для вашего соединителя позволит вам получать только немедленные ответы на ваше сообщение:

    private static async Task<string> ReadBotMessagesAsync(DirectLineClient client, string conversationId)
    {
        string watermark = null; //this should be the current watermark

Как правило, конечная точка для вызовов GET разговора:

/v3/directline/conversations/{conversationID}/activities?watermark={watermark}

возвращает разговор, сохраненный ботом, начиная с «водяного знака» или, если он установлен на ноль, часть разговора, доступную в памяти бота.начиная с последнего сообщения, отправленного ботом до повторного соединения с ботом (что вы и видели).

...