3
votes

I'm basically trying to create a proactive conversation with the Microsoft Bot Framework. I succeeded to do so for Skype for BUsiness with the following code:

string serviceUrl = "https://api.skypeforbusiness.com/platformservice/botframework";
MicrosoftAppCredentials.TrustServiceUrl(serviceUrl);

var connector = new ConnectorClient(new Uri(serviceUrl), "{app-id}", "{app-password}");

var user = new ChannelAccount("[email protected]", "Name of User");
var bot = new ChannelAccount("[email protected]", "Name of bot");

ConversationParameters cpMessage = new ConversationParameters(true, bot, new List<ChannelAccount> { user }, "Topic of the conversation");

ConversationResourceResponse response = await connector.Conversations.CreateConversationAsync(cpMessage);

After initiating the conversation I am able to send messages to the user, works perfectly. But for MS Teams, I have two questions: 1. Which serviceURL is the right one? I found several hints, including urls starting with "https://smba.trafficmanager.net …" but none of them worked, I always get an exception "Bad Request".

The second question: Do I need a Teams-Context (Teams ID) to actually post a message or is it (as in my example with skype) possible to just initiate a chat with a user?

EDIT: I tried to add channelData (teamsChannelId) and used the Service URL "https://smba.trafficmanager.net/emea-client-ss.msg" - then I get the response code "Forbidden". This brings me to the question: Is it actually possible to initiate a conversation into teams WITHOUT any Team-Context (just a chat)?

Thanks in advance, Martin

2
Just to be sure: bot v3 or v4? - Nicolas R
I don't care which version, I tried v3 and v4 - see my next answer now, I think I found the solution why my code does not work and the answer why the base use case will never work. - kolbi

2 Answers

2
votes

So, I think I found the answer myself:

The following code will work for MS Teams to write proactively (Bot Services v3):

string serviceUrl = "https://smba.trafficmanager.net/emea/";
MicrosoftAppCredentials.TrustServiceUrl(serviceUrl);

var connector = new ConnectorClient(new Uri(serviceUrl), botAppId, appSecret);
var teamsBotAccount = new ChannelAccount("28:<BOT-APP-ID>", "Smart Office Bot");
var teamsUserAccount = new ChannelAccount("29:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_x", "Martin");

ConversationResourceResponse response = connector.Conversations.CreateOrGetDirectConversation(teamsBotAccount, teamsUserAccount, "9e73e135-fe7a-447f-baba-b0312d3aa55d");

The crucial point is the ChannelAccount ID of the user to send the message to. My first misunderstanding was, that the channelaccount ID for MS Teams works with Emails as well - this is NOT the case. ChannelAccounts for MS Teams are cryptic and furthermore Channel-Specific.

That means: The User ID to use in the ChannelAccount for the Message Recipient does ONLY exist in a Channel Context. For direct 1:1 Chats it seems that my user has a different ID in every chat.

My conclusion: The problem is not the Bot Framework, but MS Teams, which simply does not support initiating a chat from an automated component. As I conclude by other similar threads, it is intentionally not supported to prevent spam (unfortunately it's quite inconsistent - that does not apply to Skype for Business obviously).

0
votes

@kolbi The ideal solution will be to do so with the Botframework V4, Here is an approach similar to what you are trying to achieve but written with the Botframework V4 version. Here is a detailed blog post about accomplishing this (Initiating conversations, and proactively replying to specific conversations)

            var channelData = turnContext.Activity.GetChannelData<TeamsChannelData>();

            var conversationParameter = new ConversationParameters
            {
                Bot = turnContext.Activity.Recipient,
                IsGroup = true,
                ChannelData = channelData,
                TenantId = channelData.Tenant.Id,
                Activity = MessageFactory.Text(message)
            };
            var response = await _client.Conversations.CreateConversationAsync(conversationParameter);