如何在没有 turnContext 的情况下主动触发来自机器人的对话?
How can I proactively trigger a dialog from a bot without a turnContext?
我有一个 Teams 机器人,可以通过 webAPI 向用户发送主动消息。我可以从 Microsoft.Bot.Connector 命名空间获取 ConnectorClient,然后我可以从那里识别相关对话,并调用 SendToConversationAsync 向用户发送消息。
如果我想用它来启动对话,挑战似乎是我没有可供参考的 TurnContext。我发现 post 看起来很有前途,但这仍然取决于对话 运行。理想情况下,我希望能够通过我已经拥有的 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 为 null,则抛出异常。
这个答案 也有一些有前途的想法,建议伪造传入事件,但我可以做类似 CreateInvokeActivity() 的事情,但将其发送到对话会引发异常。我也不确定如何触发管道以在同一过程中获取消息,而无需像使用 HTTPCLient 那样 POST 原始消息(我相信这需要获取令牌)。该机器人已经与用户进行了 1:1 对话,但如果可能的话,我想让它启动一个对话。有没有办法让 ConnectorClient 主动开始对话,或者以编程方式触发对机器人管道的调用以允许它在那里启动?
您可以使用 ContinueConversationAsync
. Please refer to the docs and the sample 从转换参考创建转弯上下文以获取更多信息。
我想出了一个方法来做到这一点,但这可能不是一个理想的方案。我想从 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;
}
这会创建对话框,如果可能的话,returns 令牌。在我的网站API中,我有这样的东西可以主动调用它:
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);
此时,如果令牌是空字符串,则用户尚未登录,否则它应该是用于进行图形调用的有效令牌。我已经用几个新帐户对此进行了测试,它似乎有效,所以我暂时称其为胜利。如果这里有什么根本性的问题,请发表评论。
我有一个 Teams 机器人,可以通过 webAPI 向用户发送主动消息。我可以从 Microsoft.Bot.Connector 命名空间获取 ConnectorClient,然后我可以从那里识别相关对话,并调用 SendToConversationAsync 向用户发送消息。
如果我想用它来启动对话,挑战似乎是我没有可供参考的 TurnContext。我发现 post
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 为 null,则抛出异常。
这个答案
您可以使用 ContinueConversationAsync
. Please refer to the docs and the sample 从转换参考创建转弯上下文以获取更多信息。
我想出了一个方法来做到这一点,但这可能不是一个理想的方案。我想从 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;
}
这会创建对话框,如果可能的话,returns 令牌。在我的网站API中,我有这样的东西可以主动调用它:
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);
此时,如果令牌是空字符串,则用户尚未登录,否则它应该是用于进行图形调用的有效令牌。我已经用几个新帐户对此进行了测试,它似乎有效,所以我暂时称其为胜利。如果这里有什么根本性的问题,请发表评论。