Search code examples
node.jsnotificationsbotframeworkmicrosoft-teamsazure-bot-service

How do I get notifications when a bot sends a message in Teams?


I developed a bot for Microsoft Teams using the Microsoft Bot Framework v4 Nodejs SDK (botbuilder-sdk for nodejs). We have implemented the bot in such a way that, when we receive data using a REST API call from one of our CRMs, the data is posted to the channels on Microsoft Teams. However, when I do that, we do not receive a notification on the devices. Has anyone faced such an issue?

I am saving the context state initially. Everytime we receive data from a CRM, I am incrementing the activity id of the message (to send it as a new message and not a reply) and sending it to Microsoft Teams using context.sendActivity().

enter image description here

When we receive that adaptive card, we do not receive a notification in the activity feed or on any of the devices.

I have gone through all the steps as you described above. I've also gone through the troubleshooting steps. However, it still doesn't give me a notification for the card. However, when I initiate a conversation with the bot, I get a notification when the bot responds.

https://i.sstatic.net/Bi4fc.png

https://i.sstatic.net/ab6uP.png

In this image, I get a notification when I get the TMS Bot started! message. However, I don't get a notification for the next two messages.


Solution

  • Edit: OP and I have exchanged a few emails to get this answered. This answer, as a whole, is good information for accomplishing Teams Proactive messaging, in general, but the main answer is in the last section, Simplified Code.

    This is a long answer that covers many areas, simply because I'm not 100% sure I know what kind of notification you aren't receiving.

    Troubleshooting

    • Troubleshooting Guide
      • Pay special attention to the many areas where notifications need to be enabled
        • In particular, the user may need to "Follow" and/or "Favorite" the channel to receive notifications from it
    • If a user has the desktop app open, they will receive the notification there and will not receive one on their phone unless they have been inactive on the desktop app for 3+ minutes. Otherwise, it's likely a bug in Teams.

    Chat Notifications

    If you've followed the Troubleshooting Guide linked above, your users should receive chat notifications. If not, you can try updating your MS Teams desktop or mobile client. As @KyleDelaney mentioned, it may be helpful to @ mention users and/or channels

    Activity Feed Notifications

    You can also create Activity Feed Notifications. The gist of it is that you need to:

    1. Include text and summary in the message
    2. Include channelData that sets notifications.alert to true

    This code will accomplish that:

    const msg = MessageFactory.text('my message');
    msg.summary = 'my summary';
    msg.channelData = {
        notification: {
            alert: true,
        },
    };
    return await dc.context.sendActivity(msg);
    

    Result:

    enter image description here enter image description here

    Note: If your bot only creates notifications and doesn't have conversations, you may benefit from creating a notifications-only bot.

    Full Implementation Code

    import * as adaptiveCard from '../src/adaptiveCard.json';
    ...
    const card = CardFactory.adaptiveCard(adaptiveCard);
    const activity = {
        attachments: [card],
        text: 'Test Card',
        summary: 'my summary',
        channelData: {
            notification: {
                alert: true,
            },
        },
    };
    await turnContext.sendActivity(activity);
    

    Result:

    enter image description here enter image description here

    Using the Teams Extension

    There's a Teams Extension for BobBuilder V4 that's currently in Beta, but seems to accomplish what you need. I believe the reason you weren't getting notifications while using the above is because your bot is creating a new reply chain in the channel and not replying directly to a user. I believe you can do all of this without the extension (by manually editing activity/context properties), but the extension should make it easier.

    Here's the code I used to get working notifications within a channel:

    In index.js (or app.js):

    import * as teams from 'botbuilder-teams';
    
    [...]
    
    // Change existing to use "new teams.TeamsAdapter..."
    const adapter = new teams.TeamsAdapter({
        appId: endpointConfig.appId || process.env.microsoftAppID,
        appPassword: endpointConfig.appPassword || process.env.microsoftAppPassword,
    });
    

    Wherever you're sending the message:

    import * as teams from 'botbuilder-teams';
    import * as adaptiveCard from '../src/adaptiveCard.json';
    ...
    const card = CardFactory.adaptiveCard(adaptiveCard);
    const activity = {
        attachments: [card],
        text: 'Test Card',
        summary: 'my summary',
        channelData: {
            notification: {
                alert: true,
            },
        },
    };
    const adapter = context.adapter as teams.TeamsAdapter;
    await adapter.createReplyChain(context, [activity]);
    

    Simplified Code

    OP and I have emailed back and forth a bit and the key issue is that he needed to add the trustServiceUrl code from below. Normally, this manifests itself with a 500 error, but in this case, it appears to not create notifications.. After significant testing, here's all you really have to do to send different notifications to different channels. It basically amounts to setting a couple of properties of turncontext.activity and trusting the serviceUrl. No touching activity ID or using the Teams Extension at all. My code below is how I sent messages from Emulator that could then send cards to different Teams channels:

    public onTurn = async (turnContext: TurnContext) => {
        const dc = await this.dialogs.createContext(turnContext);
    
        const dialogResult = await dc.continueDialog();
    
        // Route message from Emulator to Teams Channel - I can send "1", "2", or "3" in emulator and bot will create message for Channel
        let teamsChannel;
        switch (turnContext.activity.text) {
            // You can get teamsChannel IDs from turnContext.activity.channelData.channel.id
            case '1':
                teamsChannel = '19:[email protected]';
                break;
            case '2':
                teamsChannel = '19:[email protected]';
                break;
            case '3':
                teamsChannel = '19:[email protected]';
                break;
            default:
                break;
        }
        if (teamsChannel) {
            const card = CardFactory.adaptiveCard(adaptiveCard);
            const activity = {
                attachments: [card],
                summary: 'my summary',
                text: 'Test Card',
            };
            const serviceUrl = 'https://smba.trafficmanager.net/amer/';
            turnContext.activity.conversation.id = teamsChannel;
            turnContext.activity.serviceUrl = serviceUrl;
            // This ensures that your bot can send to Teams
            MicrosoftAppCredentials.trustServiceUrl(serviceUrl);
            await turnContext.sendActivity(activity);
    
        } else {
            [...Normal onTurn Code...]
    
        await this.conversationState.saveChanges(turnContext);
    }
    

    Note: To receive notifications, you and your users must follow the channel.