【问题标题】:Microsoft DirectLine API to bot does not work机器人的 Microsoft DirectLine API 不起作用
【发布时间】:2017-05-14 14:41:45
【问题描述】:

所以为了解释我的问题,我必须给你上下文。

我在 slack 上部署了一个使用 microsoft bot 框架构建的 Bot。现在它可以在机器人与之通信的我的后端发生这些“事件”。当一个事件发生时,我想通知我的机器人,然后让它向它的所有对话发送一条消息,告诉它发生了什么事。所以基本上:

Backend>Microserivce>Bot>users

为此,我必须将所有对话存储在我的后端,我在后端的数据库中进行。当事件发生时,后端将向机器人发布一个活动,其中包含所有对话(基本上是他们的 id)以及它应该显示的事件。

所以本质上我的后端需要向我的机器人发布消息。

为此,我在这里找到了充当中间人的 microsoft directline api,这是一种与机器人交谈的更抽象的方式。问题是我不知道该怎么做。我遵循了微软自己的教程,但它似乎对我不起作用:

这是我的后端用来通知机器人的端点。 “内容”包含对话和事件作为 json 格式的字符串。

    [HttpPost]
    [Route("conversationsEvents")]
    public HttpResponseMessage PostConversationsEvents([FromBody]string content)
    {
        NotifyBot.Notify(content);
        return Request.CreateResponse(HttpStatusCode.NoContent );
    }

NotifyBot.Notify(content) 看起来像这样:

        private static async Task StartBotConversation( string contents)
    {
        string directLineSecret = "secret";
        string fromUser = "microserviceNotifyEndpoint";
        Activity activity = new Activity
        {
            From = new ChannelAccount(fromUser),
            Text = contents,
            Type = ActivityTypes.Event
        };
        DirectLineClient client = new DirectLineClient(directLineSecret);
        var conversation = await client.Conversations.StartConversationAsync();
        await client.Conversations.PostActivityAsync(conversation.ConversationId, activity);
    }

基本上执行卡在var conversation = await client.Conversations.StartConversationAsync();,它只是永远等待。 我尝试将其更改为 var conversation = await client.Conversations.StartConversationAsync().ConfigureAwait(continueOnCapturedContext: false);´ 执行继续,但似乎没有发布活动。

【问题讨论】:

    标签: c# botframework direct-line-botframework


    【解决方案1】:

    我不确定为什么在您的情况下对 .StartConversationAsync() 的调用会冻结。也许您还没有在dev.botframework.com/bots 上启用Direct Line 频道?尽管如此,正如 Sergey 所指出的,Direct Line 是一个频道,而不是在其他频道上与您的机器人进行通信的一种方式。

    查看连接器客户端:bot-builder-dotnet-connector

    这是一个使用它从机器人主动向用户发送消息的静态示例:MicrosoftDX/botFramework-proactiveMessages - sample: ConversationStarter.cs

    示例中的相关代码:

    public static async Task Resume(string conversationId,string channelId)
        {
            var userAccount = new ChannelAccount(toId,toName);
            var botAccount = new ChannelAccount(fromId, fromName);
            var connector = new ConnectorClient(new Uri(serviceUrl));
    
            IMessageActivity message = Activity.CreateMessageActivity();
            if (!string.IsNullOrEmpty(conversationId) && !string.IsNullOrEmpty(channelId))
            {
                message.ChannelId = channelId;
            }
            else
            {
                conversationId = (await connector.Conversations.CreateDirectConversationAsync( botAccount, userAccount)).Id;
            }
            message.From = botAccount;
            message.Recipient = userAccount;
            message.Conversation = new ConversationAccount(id: conversationId);
            message.Text = "Hello, this is a notification";
            message.Locale = "en-Us";
            await connector.Conversations.SendToConversationAsync((Activity)message);
        }
    

    serviceUrl、channelId、conversationId、toId、fromId 等从用户先前与机器人的通信中缓存(这些在本示例中静态存储,因此仅适用于一个用户)。此示例展示了如何从机器人主动向用户发送消息。 Direct Line api 不是必需的。

    【讨论】:

      【解决方案2】:

      您不需要使用 DirectLine,它专为创建替代机器人 UI 而设计。

      要实现您想要的,您可以尝试以下方法:

      首先,您需要存储要向其发送消息的用户地址。我可以通过将用户上一条消息的 ResumptionCookie 存储在您的后端数据库中来完成。

      var state = new ResumptionCookie(message).GZipSerialize();
      

      当您的PostConversationsEvents 被调用时,您可以在最晚的时间点恢复与每个用户的对话。

              var resumptionCookie = ResumptionCookie.GZipDeserialize(state);
              var message = resumptionCookie.GetMessage();
              message.Text = content;
              await Conversation.ResumeAsync(resumptionCookie, message);
      

      这不是唯一的解决方案。正如我所说,在这种情况下,您最近才恢复与用户的对话。另一种解决方案是保存用户地址(用户同 ResumptionCookie 类)但在需要时开始对话:

              var resumptionCookie = ResumptionCookie.GZipDeserialize(state);
              var message = cookie.GetMessage();
      
              ConnectorClient client = new ConnectorClient(new Uri(message.ServiceUrl));
      
              var conversation = await 
              client.Conversations.CreateDirectConversationAsync(message.Recipient, message.From);
              message.Conversation.Id = conversation.Id;
              var newMessage = message.CreateReply();
              newMessage.Text = content;
              await client.Conversations.SendToConversationAsync(newMessage);
      

      查看有关 BotFramework 文档的更多详细信息。

      【讨论】:

      • 我认为使用 directline api 是一种很好的做法。我也刚刚尝试在我可以调用的机器人内部定义一个“正常”端点,但它给了我相同的结果。我会研究你的例子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-02
      • 2018-05-04
      • 1970-01-01
      相关资源
      最近更新 更多