How can I get my bot to post a message to a Microsoft Teams channel?

andydavies picture andydavies · Nov 23, 2017 · Viewed 9.1k times · Source

I have a bot that is identical to the one demonstrated in the docs quickstart. It repeats back whatever the user says (for now).

It is currently running locally and exposed with ngrok. I've registered the bot with the Microsoft Bot Framework.

I have configured the Microsoft Teams channel in the Microsoft Bot Framework, and I've sideloaded my bot into Teams. My bot can receive messages from Teams users.

At present, the bot just repeats whatever it receives back to the user, but what I want it to do is post to a Microsoft Teams channel. I want it to post to a Teams channel - not a user - without being prompted first by a user. So for example given a certain condition (eg. triggered by some event such as time of day, a pull request, etc.) it posts a message in a channel.

I've read the documentation about sending proactive messages, and I gather that in order to send a message to a teams channel, the bot needs to know the "address" of the user. This information is stored in the session.message.address object, and it gets this from the current conversation. However, in my case I don't have a 'current conservation', because I don't want to just respond to a user, I want to post in a channel proactively.

So, how do I permanently set the necessary credentials/address/session-data for the Teams channel?

Things I've looked into:

  • Webhooks. I've configured a webhook in my Teams channel, and I can send it a message easily enough (using the webhook url) using curl. So I can send the Teams channel a simple message with just a url (no authentication required), but I'm not sure how I'd get this url into my bot.

  • How do we maintain different session for different users in Microsoft Bot Framework? I'm not sure that the answer here answers my question. My problem is that the bot is initiating the 'conversation', not a Teams user, so I need to be able to set the session data myself so the bot knows where to go.

App.js:

require('dotenv').config();
var restify = require('restify');
var builder = require('botbuilder');

// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
   console.log('%s listening to %s', server.name, server.url); 
});

// Create chat connector for communicating with the Bot Framework Service
var connector = new builder.ChatConnector({
    appId: process.env.MICROSOFT_APP_ID,
    appPassword: process.env.MICROSOFT_APP_PASSWORD    
});

// Listen for messages from users 
server.post('/api/messages', connector.listen());

// Receive messages from the user and respond by echoing each message back (prefixed with 'You said:')
var bot = new builder.UniversalBot(connector, function (session) {
    session.send("You said: %s", session.message.text);
});

Answer

redmondcoffehead picture redmondcoffehead · Dec 30, 2018

For anyone who is wondering about the same for c#, here is the solution that worked for me:

    var channelData = context.Activity.GetChannelData<TeamsChannelData>();
    var message = Activity.CreateMessageActivity();
    message.Text = "Hello World";

    var conversationParameters = new ConversationParameters
    {
         IsGroup = true,
         ChannelData = new TeamsChannelData
          {
             Channel = new ChannelInfo(channelData.Channel.Id),
         },
         Activity = (Activity) message
    };

    var connectorClient = new ConnectorClient(new Uri(activity.ServiceUrl));
    var response = await 
    connectorClient.Conversations.CreateConversationAsync(conversationParameters);

Note: If you are calling this outside Bot's controller code then you need to call TrustServiceUrl on serviceUrl as shown here:

    MicrosoftAppCredentials.TrustServiceUrl(serviceUrl, DateTime.MaxValue);
    var connectorClient = new ConnectorClient(new Uri(serviceUrl));

Source of answer: https://github.com/OfficeDev/BotBuilder-MicrosoftTeams/issues/162