代码之家  ›  专栏  ›  技术社区  ›  Ein2012

实现自定义连接器“client.conversations.getactivities(conversationid,watermark)”的bot框架返回多个活动

  •  2
  • Ein2012  · 技术社区  · 7 年前

    我正试图在WebAPI中实现我的Microsoft bot的自定义连接器,以便可以通过Rest API从不同的应用程序调用它(对于Exmp:from Rasberripy)。使用rest调用与此api对话,后者将使用dirtectline api与我的bot对话。我已经测试了 code from 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来生成会话id,然后,我将使用id和用户问题调用bot/readbotmessages。

    我面临的问题是代码

    var activitySet = client.Conversations.GetActivities(conversationId, watermark); 每次被击中时返回多个活动,同时返回以前问题的回答( Image here ,但是我应该得到与当前响应相关的单个活动,相同的逻辑在控制台应用程序中运行良好 github 只返回一个当前活动。有人能建议一个解决办法吗?还是我在干什么?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Mark B    7 年前

    为了获得最近的活动,您需要确保将当前水印存储在连接器中的某个位置。

    调用以下方法:

    Client.Conversations.PostActivityAsync(conversationId, activity);
    

    将返回格式如下的字符串:

    "IRBO9ZhxkwID1QnNbAoOHX|0000008"
    

    "{ConversationId|Watermark}"
    

    您将希望将此呼叫的水印部分保存在连接器中的某个位置,因为稍后在连接器的邮件接收呼叫中使用它将只允许您获得对邮件的即时响应:

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

    基本上,会话的端点获取调用:

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

    从“水印”开始返回bot存储的会话,如果设置为空,则从bot之前发送的最后一条消息开始返回bot内存中可用的会话部分 reconnecting 和机器人(这就是你看到的)。