0

It's possible to send a proactive message (=private) to the sender of a message in a teams groups chat using the next part of code:

if (stepContext.Context.Activity.ChannelId == Channels.Msteams &&
    stepContext.Context.Activity.Conversation.IsGroup.HasValue &&
    stepContext.Context.Activity.Conversation.IsGroup.Value) {
        var teamConversationData = stepContext.Context.Activity.GetChannelData<TeamsChannelData>();
        var connectorClient = new ConnectorClient(new Uri(stepContext.Context.Activity.ServiceUrl), _credentialOptions.MicrosoftAppId, _credentialOptions.MicrosoftAppPassword);
        var userId = stepContext.Context.Activity.From.Id;
        var tenantId = teamConversationData.Tenant.Id;
        var parameters = new ConversationParameters
            {
                  Members = new[] { new ChannelAccount(userId) },
                  ChannelData = new TeamsChannelData
                  {
                       Tenant = new TenantInfo(tenantId),
                  },
            };
        var conversationResource = await connectorClient.Conversations.CreateConversationAsync(parameters, cancellationToken: cancellationToken);
        var message = Activity.CreateMessageActivity();
        message.Text = "This is a proactive message. I've sent it from a group conversation.";
        await connectorClient.Conversations.SendToConversationAsync(conversationResource.Id, (Activity)message, cancellationToken: cancellationToken);
}

But the issue is that I also want to be able to trigger a Dialog for that calling user instead of sending an Activity. It doesn't looks like that is possible after searching the web? I played a bit with the code and found out that I could replace

await connectorClient.Conversations.SendToConversationAsync(conversationResource.Id, (Activity)message, cancellationToken: cancellationToken);

with

stepContext.Context.Activity.Conversation.Id = conversationResource.Id;
stepContext.Context.Activity.Conversation.IsGroup = false;

This way it is possible to send dialogs to the private chat of the sending user.

When I look in the database I can see the saved dialog stack of the user populated with the dialog (waiting for user interaction). I can also see the group conversation dialog stack which remains empty, so the bot is still responsive in the group chat and for other users.

When the dialog ends I put the Conversation.Id and .IsGroup back to the previous group chat values I've saved on the context and it's able to pass the final answer(s) in the group chat just like I would like it to be.

Basically my code can switch to send stuff in private mid dialog, and at any other point in the dialog it can switch back to the group conversation.

The question is about me changing the Conversation Id mid dialog. Is this something normal to do? Will this break stuff I didn't think about yet?

Jordy
  • 99
  • 7
  • Did you check this doc? - [Proactive Messages](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/bot-v3/bot-conversations/bots-conv-proactive#best-practices-for-proactive-messaging) – Hunaid Hanfee-MSFT Dec 16 '21 at 13:47
  • Yeah, that is where I started from. But that only works for sending an Activity, not a Dialog. But I don't know how or why but now it all seems to work like want it. I probably was looking in a wrong database document. I'll update the question. – Jordy Dec 16 '21 at 13:56
  • Try this approach - [MS Team Proactive message](https://www.vrdmn.com/2020/02/microsoft-bot-framework-v4-send.html) – Rajeesh Menoth Dec 16 '21 at 13:56
  • That is also the same as my initial approach, but is not able to send Dialogs, it can only send Activities. – Jordy Dec 16 '21 at 14:02
  • We do not use this approach and it is normal to use it this way, – Hunaid Hanfee-MSFT Dec 20 '21 at 19:30
  • Yes but this way you can only tell a user something in private. By beginning a dialog you can ask the user for input in private instead. This is a big benefit, for example just for logging in so not the whole group is spammed by such things. – Jordy Dec 21 '21 at 07:14
  • @Jordy - I tried this scenario my end and came to know it is successfully switching to Group & personal or reverse but if try to talk to bot again in group its continuing from where I left earlier(*when I switch personal*). Did you handle this as well in your code? I haven't tried to write some code to handle that – Hunaid Hanfee-MSFT Dec 27 '21 at 12:00
  • This might break the user experience by not starting dialog from first step. – Hunaid Hanfee-MSFT Dec 27 '21 at 12:01
  • @HunaidHanfee-MSFT yes in our implementation we tested all cases with multiple people using the group bot, and it handles everything well in personal chat if we sent it there (because the dialogStack is moved to the private conversation) and the group bot doesn't block on private input this way in the group chat. Everything works atm, I only question if we are supposed/allowed to use the ConversationId this way and the implementation will not break in the feature. – Jordy Dec 28 '21 at 13:25
  • @HunaidHanfee-MSFT in your case it was continuing in the group because your dialogStack was saved in the group conversation and not in the personal conversation (because it should have the private conversationId set when it is saving the context when waiting for input from the user). – Jordy Dec 28 '21 at 13:27
  • Correction: *Future – Jordy Dec 28 '21 at 15:27

1 Answers1

1

I don't see any problem with this approach, but I think typically you'd start a new dialog rather than continue to use the same one.

I think any code accessing state prior to the hack would be persisted under the new id when state is saved. Middleware running prior to the turn, vs after the turn completes, would have two separate conversation ids.

Hunaid Hanfee-MSFT
  • 836
  • 1
  • 3
  • 8