Инициировать сообщение от бота к пользователю в BotFramework

У меня есть бот, построенный на BotFramework 3.5 и размещенный на Azure как WebApp. У меня не возникало никаких проблем с реализацией сценариев, когда бот должен отвечать на ввод пользователя. Однако есть необходимость научить его начинать разговоры по некоторому графику. Чтобы достичь цели, я создал веб-приложение, которое в основном представляет собой консольное приложение. Вот код, используемый для инициирования сообщения от бота к пользователю:

            var botAccount = new ChannelAccount(id: from);
            var userAccount = new ChannelAccount(id: to);
            var conversation = new ConversationAccount(false, conversationId);

            var connector = new ConnectorClient(serviceUrl);

            IMessageActivity message = Activity.CreateMessageActivity();
            message.From = botAccount;
            message.Recipient = userAccount;
            message.Conversation = conversation;
            message.Text = text;
            message.Locale = locale;
            await connector.Conversations.SendToConversationAsync((Activity)message);

from, to, serviceUrl, conversationId - взяты из предыдущего разговора, поэтому я ожидаю, что они действительны. Однако при SendToConversationAsync исключается исключение:

System.UnauthorizedAccessException: Authorization for Microsoft App ID 3a26a4d4-f75a-4feb-b3e0-37a7fa24e5fc failed with status code Unauthorized and reason phrase 'Unauthorized' ---> System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized)

Файл app.config содержит те же значения, что и исходный API-интерфейс, включая AppId и AppSecret. Я видел несколько вопросов, поднятых по одной теме, но не нашел ответа.

Я что-то упустил? Является ли он действительным подходом для отправки сообщений от имени бота из консольного приложения?

Ответ 1

В соответствии с вашим описанием я последовал за этим учебником для начала работы с Connector и после этого учебник для отправки и получения действий.

Основываясь на вашем коде, я создал свое консольное приложение, и я мог воспроизвести ту же проблему, затем нашел git issue о подобной проблеме. После некоторых испытаний я мог бы заставить его работать, как ожидалось, на моей стороне, вы могли бы сослаться на него:

MicrosoftAppCredentials.TrustServiceUrl("{ServiceUrl}", DateTime.Now.AddDays(7));
var account=new MicrosoftAppCredentials("MicrosoftAppIdKey", "MicrosoftAppPasswordKey");
var connector = new ConnectorClient(new Uri("{ServiceUrl}"),account);

ИЛИ

Реализовать ваш DelegatingHandler

public class MyDelegatingHandler : DelegatingHandler
{
    private string _token;
    public MyDelegatingHandler(string token)
    {
        _token = token;
    }

    protected override Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _token);
        return base.SendAsync(request, cancellationToken);
    }
}

Затем вам нужно построить ConnectorClient следующим образом:

var account=new MicrosoftAppCredentials("{MicrosoftAppIdKey}", "{MicrosoftAppPasswordKey}");
var jwtToken=await account.GetTokenAsync();
var connector = new ConnectorClient(new Uri("{serviceUrl}"),handlers:new MyDelegatingHandler(jwtToken));

Вот фрагмент кода моего консольного приложения, вы можете обратиться к нему:

try
{
    var userAccount = new ChannelAccount() { Id = "default-user", Name = "user" };
    var botAccount = new ChannelAccount() { Id = "934493jn5f6f348f", Name = "console-Bot" };
    string url = "{serviceUrl}";

    MicrosoftAppCredentials.TrustServiceUrl(url, DateTime.Now.AddDays(7));
    var account = new MicrosoftAppCredentials("{MicrosoftAppIdKey}", "{MicrosoftAppPasswordKey}");
    var connector = new ConnectorClient(new Uri(url), account);

    IMessageActivity message = Activity.CreateMessageActivity();
    message.From = botAccount;
    message.Recipient = userAccount;
    message.Conversation = new ConversationAccount() { Id = "{conversationId}" };
    message.Text = "Message sent from console application!!!";
    message.Locale = "en-us";
    var response = await connector.Conversations.SendToConversationAsync((Activity)message);
    Console.WriteLine($"response:{response.Id}");
}
catch (Exception e)
{
    Console.WriteLine($"exception:{e.Message}\r\n{e.StackTrace}");
}

Результат

введите описание изображения здесь

Ответ 2

Попробуйте создать новый разговор следующим образом:

var conversationId = await connector.Conversations.CreateDirectConversationAsync(botAccount, userAccount);