如何在机器人生成器框架4.0中发送转弯消息和回复

时间:2018-11-29 08:12:20

标签: c# botframework

我(在外部事件中)将消息发布到我的Microsoft团队频道。

var activity = new Activity("message", text: $"", attachments: new List<Microsoft.Bot.Schema.Attachment>
    {
        new Microsoft.Bot.Schema.Attachment{ ContentType = "application/vnd.microsoft.card.adaptive" , Content= new JRaw(json)}
    });
var a = await connector.Conversations.SendToConversationAsync("hardcoded channel string, cant find it anywhere",
    activity);

在哪个频道上,自适应卡显示在我的频道中。

我现在想稍后再对此活动进行回复。

 var b = await connector.Conversations.ReplyToActivityAsync("same channel id hardcoded", a.Id, new Activity("message", text: "user disconected",replyToId : a.Id));

,但该消息不会显示为回复,而是频道中的新消息。

从SendToConversationAsync响应返回的ID看起来不像活动ID,所以我如何获取活动ID,以便可以正确地对其进行回复。

connectorClient的创建方式如下:

var connector = new ConnectorClient(new Uri("https://smba.trafficmanager.net/emea/"), appCredentials);

1 个答案:

答案 0 :(得分:1)

看看这个示例,看看如何在BotBuilder V4中发送主动消息:https://github.com/Microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/16.proactive-messages

应该特别关注CompleteJobAsync method

// Sends a proactive message to the user.
private async Task CompleteJobAsync(
    BotAdapter adapter,
    string botId,
    JobLog.JobData jobInfo,
    CancellationToken cancellationToken = default(CancellationToken))
{
    await adapter.ContinueConversationAsync(botId, jobInfo.Conversation, CreateCallback(jobInfo), cancellationToken);
}

由此可见,诀窍是使用BotAdapter.ContinueConversationAsync

我已经在Teams中进行了测试,发现通过继续对话而不是开始新的对话,它可以名副其实。


编辑:我现在了解到您是想问类似以下问题的问题:Microsoft Bot Connector - get activity id from response after sending message

也就是说,您了解在Microsoft Teams团队频道中,所有活动将共享相同的“ root”对话ID,如下所示:19:ad2f5f5a246241718826833354894656@thread.skype

每个“线程”将有自己的会话ID,该会话ID由根ID加上启动该线程的消息ID组成:19:ad2f5f5a246241718826833354894656@thread.skype;messageid=1545970892795

因此,如果要启动新线程,则可以将消息发送到根会话ID;如果要回复线程,则可以将消息发送到线程的会话ID。在这方面,SendToConversationAsyncReplyToActivityAsync之间没有区别,因为尽管出现了,但Teams不会在其他消息下“嵌套”消息。相反,每个消息链都由其自己的会话ID标识。

因此,为了将消息发送到线程,您发现需要知道启动线程的消息的ID。不幸的是,SendToConversationAsyncReplyToActivityAsync返回的ID与您所需的ID格式不同。经过大量测试,我发现团队似乎有两种形式的消息ID:

  • Epoch时间戳(1545970800530)
    • 用作发送给机器人的消息中的活动ID
    • 用作会话ID的一部分以定义线程(19:ad2f5f5a246241718826833354894656@thread.skype; messageid = 1545970892795)
  • 字母数字代码(1:1zDTpbvf1DFFLC5cL0n72d-wPdIIV2L6L5LZ5H_nzqhs)
    • 从对REST API的调用中返回为HTTP内容
    • 用于更新,大概用于删除活动

那么你不走运吗?一点也不!事实证明,如果您使用CreateConversationAsync创建线程,则它将返回线程的会话ID,您可以将其用于回复。这是一个扩展类,可让您轻松使用它:

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Connector.Teams.Models;
using Microsoft.Bot.Schema;

namespace Microsoft.Bot.Connector.Teams
{
    public static class TeamsExtensions
    {
        public static async Task<ConversationResourceResponse> CreateTeamsThreadAsync(
            this ITurnContext turnContext,
            Activity activity,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var connectorClient = turnContext.TurnState.Get<IConnectorClient>() as ConnectorClient;
            activity.ChannelData = turnContext.Activity.ChannelData;

            return await connectorClient.Conversations.CreateTeamsThreadAsync(turnContext.Activity.Conversation.Id, activity, cancellationToken);
        }

        public static async Task<ConversationResourceResponse> CreateTeamsThreadAsync(
            this IConversations conversations,
            string conversationId,
            Activity activity,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var channelData = activity.GetChannelData<TeamsChannelData>();

            var parameters = new ConversationParameters
            {
                ChannelData = new TeamsChannelData
                {
                    Channel = channelData.Channel,
                    Team = channelData.Team,
                    Tenant = channelData.Tenant,
                },
                Activity = activity,
            };

            return await conversations.CreateConversationAsync(parameters, cancellationToken);
        }
    }
}

由于我看到您已经有一个ConnectorClient和一个对话ID,因此我制定了使用它们的方法。如果要响应来自用户的消息创建线程,也可以调用扩展ITurnContext的方法。您所需要做的就是保存方法返回的Id的{​​{1}}值,以便将其用于主动消息。

Bot replying to itself