【问题标题】:Start dialog from trigger从触发器开始对话框
【发布时间】:2017-03-08 14:37:55
【问题描述】:

这是在 C# 中,在 Skype 频道上:

是否可以从触发器开始与用户的对话?

情况: 在某个定时时刻,我想向所有注册用户显示一个对话框(从中我有一个恢复cookie) 所以我有一个天蓝色的功能来监控队列并触发我的机器人。在那个触发器上,我可以发送一条简单的消息,但我想在那一刻开始一个对话。

[BotAuthentication]
public class MessagesController: ApiController {
  public async Task < HttpResponseMessage > Post([FromBody] Activity activity) {
    if (activity != null) {
     switch (activity.GetActivityType()) {
      case ActivityTypes.Message:
       //some stuff here, not important for now
       break;

      case ActivityTypes.Trigger:
       //This does not work:
       await Conversation.SendAsync(activity, () => new ExceptionHandlerDialog < object > (new BroodjesDialog(), true));

       //But this does:
       IEventActivity trigger = activity;
       var message = JsonConvert.DeserializeObject < Message > (((JObject) trigger.Value).GetValue("Message").ToString());

       await Resume((Activity) message.ResumptionCookie.GetMessage());

       var messageactivity = (Activity) message.ResumptionCookie.GetMessage();
       client = new ConnectorClient(new Uri(messageactivity.ServiceUrl));
       var triggerReply = messageactivity.CreateReply();
       triggerReply.Text = $ "Let's do some talking";
       await client.Conversations.ReplyToActivityAsync(triggerReply);
       break;
     }
    }
    var response = Request.CreateResponse(HttpStatusCode.OK);
    return response;
}

【问题讨论】:

  • C# 还是节点?您打算使用哪个频道?这不可能在所有频道上实现。请向我们展示您发送简单消息的触发器的代码。谢谢。
  • 在原问题上添加了相关代码。
  • 您可以发布您的 Azure Function 触发器的代码吗?
  • Azure 函数代码是在 Azure 上创建机器人时生成的标准代码。我只更改了 Direct Line Api Key 以触发不同的机器人。

标签: c# triggers dialog queue botframework


【解决方案1】:

查看机器人框架提供的这个 AlarmBot 示例,它展示了如何从外部事件启动对话框。

namespace Microsoft.Bot.Sample.AlarmBot.Models
{
    /// <summary>
    /// This method represents the logic necessary to respond to an external event.
    /// </summary>
    public static class ExternalEvent
    {
        public static async Task HandleAlarm(Alarm alarm, DateTime now, CancellationToken token)
        {
            // since this is an externally-triggered event, this is the composition root
            // find the dependency injection container
            var container = Global.FindContainer();

            await HandleAlarm(container, alarm, now, token);
        }

        public static async Task HandleAlarm(ILifetimeScope container, Alarm alarm, DateTime now, CancellationToken token)
        {
            // the ResumptionCookie has the "key" necessary to resume the conversation
            var message = alarm.Cookie.GetMessage();
            // we instantiate our dependencies based on an IMessageActivity implementation
            using (var scope = DialogModule.BeginLifetimeScope(container, message))
            {
                // find the bot data interface and load up the conversation dialog state
                var botData = scope.Resolve<IBotData>();
                await botData.LoadAsync(token);

                // resolve the dialog stack
                var stack = scope.Resolve<IDialogStack>();
                // make a dialog to push on the top of the stack
                var child = scope.Resolve<AlarmRingDialog>(TypedParameter.From(alarm.Title));
                // wrap it with an additional dialog that will restart the wait for
                // messages from the user once the child dialog has finished
                var interruption = child.Void(stack);

                try
                {
                    // put the interrupting dialog on the stack
                    stack.Call(interruption, null);
                    // start running the interrupting dialog
                    await stack.PollAsync(token);
                }
                finally
                {
                    // save out the conversation dialog state
                    await botData.FlushAsync(token);
                }
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    ResumptionCookie 自 3.5.5 起已弃用。 (rip),从现在开始,如果你打算在未来恢复对话,你应该使用/跟踪ConversationReference

    要获得ConversationReference,我直接在控制器中使用 Autofac。

    using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
    {
        var convRef = scope.Resolve<ConversationReference>();
    
        StoreInSomewhere(convRef);
    }
    

    当您想恢复对话时,您可以使用ResumeAsync或直接向用户发送消息,如下所示:

    // this is the previously recorded CR
    ConversationReference convRef = GetFromSomewhere();
    
    ConnectorClient connector = new ConnectorClient(new Uri(convRef.ServiceUrl));
    IMessageActivity newMessage = Activity.CreateMessageActivity();
    newMessage.From = convRef.Bot;
    newMessage.Conversation = convRef.Conversation;
    newMessage.Recipient = convRef.User;
    newMessage.Text = "This is the message";
    await connector.Conversations.SendToConversationAsync((Activity)newMessage);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-09
      • 2019-10-21
      • 1970-01-01
      • 1970-01-01
      • 2019-12-06
      • 2022-01-21
      相关资源
      最近更新 更多