Search code examples
node.jsbotframeworkmicrosoft-teams

Sending proactive messages to a channel in Teams


So,

I searched far and wide, read everything I could find on the topic and I am still failing at this. I have managed to send proactive message to user, reply to a topic in team, etc. but I am unable to send a proactive message (create new post) in a team channel.

Is there an available example (I was unable to find any)? MS Docs for NodeJS seem to show an example of messaging each user in the team, but not the channel itself.

I explored the source code, and channelData is hardcoded to null inside botFrameworkAdapter.js, which only adds to the confusion.

So, basic code is:

const builder = require('botbuilder');
const adapter = new builder.BotFrameworkAdapter({
    appId: 'XXX',
    appPassword: 'YYY'
});

const conversation = {
  channelData: {
    //I have all this (saved from event when bot joined the Team)
  },
  ...
  // WHAT THIS OBJECT NEEDS TO BE TO SEND A SIMPLE "HELLO" TO A CHANNEL?
  // I have all the d
};

adapter.createConversation(conversation, async (turnContext) => {
  turnContext.sendActivity('HELLO'); //This may or may not be needed?
});

Has anyone done this with Node ? If so, can anyone show me a working example (with properly constructed conversation object)?

* EDIT *

As Hilton suggested in the answer below, I tried using ConnectorClient directly, but it returns resource unavailable (/v3/conversations)

Here is the code that I am using (it's literally only that, just trying to send demo message):

const path = require('path');
const { ConnectorClient, MicrosoftAppCredentials } = require('botframework-connector');

const ENV_FILE = path.join(__dirname, '.env');
require('dotenv').config({ path: ENV_FILE });

const serviceUrl = 'https://smba.trafficmanager.net/emea/';

async function sendToChannel() {
    MicrosoftAppCredentials.trustServiceUrl(serviceUrl);

    var credentials = new MicrosoftAppCredentials(process.env.MicrosoftAppId, process.env.MicrosoftAppPassword);
    var client = new ConnectorClient(credentials, { baseUri: serviceUrl });

    var conversationResponse = await client.conversations.createConversation({
        bot: {
            id: process.env.MicrosoftAppId,
            name: process.env.BotName
        },
        isGroup: true,
        conversationType: "channel",
        id: "19:[email protected]"
    });

    var acivityResponse = await client.conversations.sendToConversation(conversationResponse.id, {
        type: 'message',
        from: { id: process.env.MicrosoftAppId },
        text: 'This a message from Bot Connector Client (NodeJS)'
    });

}

sendToChannel();

What am I doing wrong?


Solution

  • Okay, so, this is how I made it work. I am posting it here for future reference.

    DISCLAIMER: I still have no idea how to use it with botbuilder as was asked in my initial question, and this answer is going to use ConnectorClient, which is acceptable (for me, at least). Based on Hilton's directions and a GitHub issue that I saw earlier ( https://github.com/OfficeDev/BotBuilder-MicrosoftTeams/issues/162#issuecomment-434978847 ), I made it work finally. MS Documentation is not that helpful, since they always use context variable which is available when your Bot is responding to a message or activity, and they keep a record of these contexts internally while the Bot is running. However, if your Bot is restarted for some reason or you want to store your data in your database to be used later, this is the way to go.

    So, the code (NodeJS):

    const path = require('path');
    const { ConnectorClient, MicrosoftAppCredentials } = require('botframework-connector');
    
    const ENV_FILE = path.join(__dirname, '.env');
    require('dotenv').config({ path: ENV_FILE });
    
    const serviceUrl = 'https://smba.trafficmanager.net/emea/';
    
    async function sendToChannel() {
        MicrosoftAppCredentials.trustServiceUrl(serviceUrl);
    
        var credentials = new MicrosoftAppCredentials(process.env.MicrosoftAppId, process.env.MicrosoftAppPassword);
        var client = new ConnectorClient(credentials, { baseUri: serviceUrl });
    
        var conversationResponse = await client.conversations.createConversation({
            bot: {
                id: process.env.MicrosoftAppId,
                name: process.env.BotName
            },
            isGroup: true,
            conversationType: "channel",
            channelData: {
                channel: { id: "19:[email protected]" }
            },
            activity: {
                type: 'message',
                text: 'This a message from Bot Connector Client (NodeJS)'
            }
        });
    
    }
    
    sendToChannel();
    

    NOTE: As Hilton pointed out, serviceUrl also needs to be loaded from your database, along with the channel id. It is available inside the activity which you receive initially when your Bot is added to team / channel / group along with channelId which you will also need, and you need to store those for future reference (do not hardcode them like in the example).

    So, there is no separate createConversation and sendActivity, it's all in one call.

    Thanks Hilton for your time, and a blurred image of my hand to MS Docs :)

    Hope this helps someone else