Notifictaion not working in SSO enabled BOT build using teams tool kit

83 Views Asked by At

I am new to teams tool kit . I am trying to build a bot which can message and receive notifications. I am using the sample code available in teams tool kit. When i run the SSO enabled app alone, it works fine . When I run the notification bot alone it works fine and I get notification. When i try to merge both , the notification doesn't work . It fails to extract the member. The bot has to send notification to member not for channels. Currently i am testing in local in VS code only. Not using any Azure funtions.Using below end point to trigger notifiction http://localhost:3978/api/[email protected]

Below code fails and member is undefined

const member = await notificationApp.notification.findMember(
      async (m) => m.account.email === '[email protected]'

    );
    await member?.sendAdaptiveCard(AdaptiveCards.declare<CardData>(notificationTemplate).render({
      title: "New Event Occurred!",
      appName: "Contoso App Notification",
      description: `This is a sample http-triggered notification to`,
      notificationUrl: "https://aka.ms/teamsfx-notification-new",
    }));

Below is my index.js.

// Import required packages
import * as restify from "restify";
import * as path from "path";

// Import required bot services.
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
import {
  CloudAdapter,
  ConfigurationServiceClientCredentialFactory,
  ConfigurationBotFrameworkAuthentication, TurnContext
} from "botbuilder";

// This bot's main dialog.
import { TeamsBot } from "./teamsBot";
import config from "./config";
import { AdaptiveCards } from "@microsoft/adaptivecards-tools";
import notificationTemplate from "./adaptiveCards/notification-default.json";
import { notificationApp } from "./internal/initialize";
import { CardData } from "./cardModels";

// Create adapter.
// See https://aka.ms/about-bot-adapter to learn more about adapters.
const credentialsFactory = new ConfigurationServiceClientCredentialFactory({
  MicrosoftAppId: config.botId,
  MicrosoftAppPassword: config.botPassword,
  MicrosoftAppType: "MultiTenant",
});

const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(
  {},
  credentialsFactory
);

const adapter = new CloudAdapter(botFrameworkAuthentication);

// Catch-all for errors.
const onTurnErrorHandler = async (context: TurnContext, error: Error) => {
  // This check writes out errors to console log .vs. app insights.
  // NOTE: In production environment, you should consider logging this to Azure
  //       application insights.
  console.error(`\n [onTurnError] unhandled error: ${error}`);

  // Send a trace activity, which will be displayed in Bot Framework Emulator
  await context.sendTraceActivity(
    "OnTurnError Trace",
    `${error}`,
    "https://www.botframework.com/schemas/error",
    "TurnError"
  );

  // Send a message to the user
  await context.sendActivity(`The bot encountered unhandled error:\n ${error.message}`);
  await context.sendActivity("To continue to run this bot, please fix the bot source code.");
};

// Set the onTurnError for the singleton CloudAdapter
adapter.onTurnError = onTurnErrorHandler;

// Create the bot that will handle incoming messages.
const bot = new TeamsBot();

// Create HTTP server.
const server = restify.createServer();
server.use(restify.plugins.bodyParser());
server.listen(process.env.port || process.env.PORT || 3978, () => {
  console.log(`\nBot Started, ${server.name} listening to ${server.url}`);
});


// Listen for incoming requests.
server.post("/api/messages", async (req, res) => {
  console.log('api/messages')
  await adapter
    .process(req, res, async (context) => {
      await bot.run(context);
    })
    .catch((err) => {
      // Error message including "412" means it is waiting for user's consent, which is a normal process of SSO, sholdn't throw this error.
      if (!err.message.includes("412")) {
        throw err;
      }
    });
});

server.get(
  "/auth-:name(start|end).html",
  restify.plugins.serveStatic({
    directory: path.join(__dirname, "public"),
  })
);

server.post(
  "/api/notification",
  restify.plugins.queryParser(),
  restify.plugins.bodyParser(), // Add more parsers if needed
  async (req, res) => {

    await target.adapter.continueConversationAsync(
      botId,
      target.conversationReference,
      async (context) => {
          // trigger sso
  });
    // By default this function will iterate all the installation points and send an Adaptive Card
    // to every installation.
    const pageSize = 100;
    const email= req.query.email;
    console.log('notiictaion api call ')
    let continuationToken: string | undefined = undefined;
    const member = await notificationApp.notification.findMember(
      async (m) => m.account.email === email

    );
    await member?.sendAdaptiveCard(AdaptiveCards.declare<CardData>(notificationTemplate).render({
      title: "New Event Occurred!",
      appName: "Contoso App Notification",
      description: `This is a sample http-triggered notification to`,
      notificationUrl: "https://aka.ms/teamsfx-notification-new",
    }));


    res.json({});
  }
);

Below is the Notifictaionapp configured

import { BotBuilderCloudAdapter } from "@microsoft/teamsfx";
import ConversationBot = BotBuilderCloudAdapter.ConversationBot;
import config from "./../config";

// Create bot.

    export const notificationApp = new ConversationBot({
      // The bot id and password to create CloudAdapter.
      // See https://aka.ms/about-bot-adapter to learn more about adapters.
      adapterConfig: {
        MicrosoftAppId: config.botId,
        MicrosoftAppPassword: config.botPassword,
        MicrosoftAppType: "MultiTenant",
      },
      // Enable notification
      notification: {
        enabled: true,
      },
    });

Any help or guidance will be appreciated.

1

There are 1 best solutions below

2
On

From your description, seems the problem you met is await notificationApp.notification.findMember(...) returns undefined.

Please check whether your current project contains .notification.localstore.json file and the content in it is not empty. The code relies on the content inside it to search members. You can find more information at https://github.com/OfficeDev/TeamsFx/wiki/Send-notification-to-Teams#customize-storage.

If the file is empty, you can uninstall the app in Teams and install it again so the package can record your installation to the file.