【问题标题】:How can I proactively trigger a dialog from a bot without a turnContext?如何在没有 turnContext 的情况下主动触发来自机器人的对话?
【发布时间】:2020-08-04 20:35:37
【问题描述】:

我有一个可以通过 webAPI 向用户发送主动消息的 Teams 机器人。我可以从 Microsoft.Bot.Connector 命名空间获取 ConnectorClient,然后我可以从那里识别相关对话,并调用 SendToConversationAsync 向用户发送消息。

如果我想使用它来启动对话,挑战似乎是我没有可供参考的 TurnContext。我发现了一个看起来很有希望的帖子here,但这仍然取决于对话轮流的运行。理想情况下,我希望能够通过我已经拥有的 ConnectorClient 参考来做到这一点,并且尝试使用 null TurnContext 似乎不起作用。例如,试试这个:

var dialogState = _accessors.ConversationState.CreateProperty<DialogState>(nameof(DialogState));
var dialogSet = new DialogSet(dialogState);
dialogSet.Add(new MyDialog());
DialogContext dc = await dialogSet.CreateContextAsync(turnContext, cancellationToken);
var turnResult = await dc.BeginDialogAsync("MyDialog");

如果 turnContext 为空,则抛出异常。

这个答案here 也有一些有希望的想法,建议伪造传入事件,但我可以执行 CreateInvokeActivity() 之类的操作,但将其发送到对话会引发异常。我也不确定如何触发管道以在同一进程中获取消息,而无需使用 HTTPCLient 来发布原始消息(我相信这需要获取令牌)。该机器人已经与用户进行了 1:1 的对话,但如果可能的话,我想让它启动一个对话。有没有办法让 ConnectorClient 主动开始对话,或者以编程方式触发对机器人管道的调用以允许它在那里启动?

【问题讨论】:

    标签: c# asp.net botframework chatbot microsoft-teams


    【解决方案1】:

    我设法找到了一种方法来做到这一点,但这可能不是一个理想的方案。我想从 API 启动一个对话框,特别是一个获取用户 OAuth 令牌以访问图形的身份验证对话框。如果用户已登录,则立即返回令牌,否则,他们会收到登录提示。我的机器人代码中有这样的东西(为简洁而编辑):

    public static async Task<string> GetTokenAsync(ITurnContext turnContext, CancellationToken cancellationToken)
    {
        var dialogState = _accessors.ConversationState.CreateProperty<DialogState>(nameof(DialogState));
        var dialogSet = new DialogSet(dialogState);
        dialogSet.Add(new AuthDialog());
        DialogContext dc = await dialogSet.CreateContextAsync(turnContext, cancellationToken);
        var turnResult = await dc.BeginDialogAsync("AuthDialog");
        await _accessors.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
    
        if(turnResult.Status== DialogTurnStatus.Waiting)
        {
            _log.Debug("Got login request for user-waiting for response");
            return string.Empty;
        }
        else if(turnResult.Result is TokenResponse)
        {
            return ((TokenResponse)turnResult.Result).Token;
        }
        return null;
    }
    

    这将创建对话框,并在可能的情况下返回令牌。在我的 webAPI 中,我有这样的东西可以主动调用它:

    string conversationID = "CONV_ID_FROM_STATE";
    
    var members = await m_client.Conversations.GetConversationMembersAsync(conversationID);
    
    BotFrameworkAdapter b = new BotFrameworkAdapter(new SimpleCredentialProvider("BOT ID", "BOT_SECRET"));
    var message = Activity.CreateMessageActivity();
    message.Text = "login";
    message.From = new ChannelAccount(members[0].Id);
    message.Conversation = new ConversationAccount(id: conversationID, conversationType: "personal", tenantId: :BOT_TENANT_ID);
    message.ChannelId = "msteams";
    
    TurnContext t = new TurnContext(b, (Activity)message);
    ClaimsIdentity id = new ClaimsIdentity();
    id.AddClaim(new Claim("aud", "BOT_ID"));
    t.TurnState.Add("BotIdentity", id);
    t.TurnState.Add("Microsoft.Bot.Builder.BotAdapter.OAuthScope", "https://api.botframework.com");
    t.TurnState.Add("Microsoft.Bot.Connector.IConnectorClient", m_client);
    string token = await myBot<AuthDialog>.GetTokenAsync(t, default);
    

    此时,如果令牌是空字符串,则用户尚未登录,否则它应该是用于进行图形调用的有效令牌。我已经用几个新帐户对此进行了测试,它似乎有效,所以我现在称之为胜利。如果这里有什么从根本上被破坏的东西,请发表评论。

    【讨论】:

    • 这似乎不是您问题的直接答案。它似乎与身份验证令牌有关,而不是主动对话。
    • 没错,但练习的重点(我还没有真正弄清楚)是在主动消息中获取用于图形调用的 OAuth 令牌。 SDK 中有一个很好的 OAuth 对话流程,所以如果用户已经登录,我可以尝试获取令牌,如果没有,它会推送 OAuth 卡并允许用户登录。这里的好处是OAuth 提示处理大部分令牌逻辑,但您必须能够启动对话才能使用它。
    【解决方案2】:

    您可以使用ContinueConversationAsync 从转化引用创建转弯上下文。更多信息请参考docssample

    【讨论】:

    • 谢谢-我喜欢那个示例,并且我知道它的去向,但是您是否有理由仅使用对话 ID 调用 SendToConversationAsync,但您需要完整的对话参考才能执行相同的操作ContinueConversationAsync 的事情?我没有保存那些。不过,我确实想出了一个替代解决方案,我很想知道你是否认为它是有效的。
    • 您不能仅使用对话 ID 调用 SendToConversationAsync。您还需要一个活动,一个活动包含对话引用包含的所有信息等等。您可以忽略哪些信息的问题取决于频道,因此在 Teams 中您可能只需要对话 ID。您可以尝试以此创建对话参考。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 2012-02-06
    • 1970-01-01
    相关资源
    最近更新 更多