如何处理来自 websocket 流的数据并有条件地在 Azure Bot 中发送主动消息?

How can I process data from a websocket stream and conditionally send a proactive message in Azure Bot?

我有一个数据提供者通过 WebSocket 提供他们的数据。我需要实时处理它,然后根据某些条件,我必须触发一个警报,该警报需要在 Azure Bot Framework 中作为主动消息发送。 现在我的问题是: 1. 我们能否在 Azure Bot Project 中处理来自 WebSocket 流的数据并使用它有条件地触发主动消息? 2. 如果不可能,完成这样的事情的最佳方法是什么?创建一个单独的项目来通过网络挂钩处理 WebSocket 数据流和 post 警报?在这种情况下,我如何根据通过 webhook 收到的警报发送主动消息?

我所有的网络搜索都指向了通过 WebSockets 将活动发送到 Azure Bot 的结果,以及通过 webhook 将 Bot 连接到第三方服务的方法。

为此,您需要在您的机器人中创建一个 API 来接受和处理任何主动消息。您可以参考此 dotnet doc and this sample, 16.proactive-messages 作为指导。

对于要处理的 WebSocket 数据,您可能希望在单独的服务中进行设置。当触发器通过时,将生成主动消息并将其发送到您设置为由机器人使用的 API。

简而言之(借用文档):

首先,您创建一个 conversationReference,它在 OnConversationUpdateActivityAsync activity 处理程序期间从 activity 派生。

private void AddConversationReference(Activity activity)
{
    var conversationReference = activity.GetConversationReference();
    _conversationReferences.AddOrUpdate(conversationReference.User.Id, conversationReference, (key, newValue) => conversationReference);
}

protected override Task OnConversationUpdateActivityAsync(ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    AddConversationReference(turnContext.Activity as Activity);

    return base.OnConversationUpdateActivityAsync(turnContext, cancellationToken);
}

接下来,您将设计处理传入请求的路由。检索 conversationReference 并调用 ContinueConversationAsyncBotCallback 来处理传入消息。

[Route("api/notify")]
[ApiController]
public class NotifyController : ControllerBase
{
    private readonly IBotFrameworkHttpAdapter _adapter;
    private readonly string _appId;
    private readonly ConcurrentDictionary<string, ConversationReference> _conversationReferences;

    public NotifyController(IBotFrameworkHttpAdapter adapter, IConfiguration configuration, ConcurrentDictionary<string, ConversationReference> conversationReferences)
    {
        _adapter = adapter;
        _conversationReferences = conversationReferences;
        _appId = configuration["MicrosoftAppId"];

        // If the channel is the Emulator, and authentication is not in use,
        // the AppId will be null.  We generate a random AppId for this case only.
        // This is not required for production, since the AppId will have a value.
        if (string.IsNullOrEmpty(_appId))
        {
            _appId = Guid.NewGuid().ToString(); //if no AppId, use a random Guid
        }
    }

    public async Task<IActionResult> Get()
    {
        foreach (var conversationReference in _conversationReferences.Values)
        {
            await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, conversationReference, BotCallback, default(CancellationToken));
        }

        // Let the caller know proactive messages have been sent
        return new ContentResult()
        {
            Content = "<html><body><h1>Proactive messages have been sent.</h1></body></html>",
            ContentType = "text/html",
            StatusCode = (int)HttpStatusCode.OK,
        };
    }

    private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
    {
        // If you encounter permission-related errors when sending this message, see
        // https://aka.ms/BotTrustServiceUrl
        await turnContext.SendActivityAsync("proactive hello");
    }
}

最后,为避免 401 'Unauthorized' 错误,您需要在发送主动消息的代码之前包含 TrustServiceUrl()

MicrosoftAppCredentials.TrustServiceUrl(serviceUrl);

希望得到帮助!