0

I have developed a simple bot using microsoft bot framework with nodejs. the code is just two files like below.

I saw on google firebase function docs https://firebase.google.com/docs/functions/http-events#using_existing_express_apps

it seems i can simply deploy my ms bot nodejs to firebase. question is how exactly should i do it .

app.js

'use strict';

var express = require('express');
var app = express();

// Adding a bot to our app
var bot = require('./bot');
bot.setup(app);

// Adding a messaging extension to our app
var messagingExtension = require('./messaging-extension');
messagingExtension.setup();

// Deciding which port to use
var port = process.env.PORT || 3333;

// Start our nodejs app
app.listen(port, function() {
    console.log(`App started listening on port ${port}`);
});

bot.js

'use strict';

module.exports.setup = function(app) {
    var builder = require('botbuilder');
    var teams = require('botbuilder-teams');
    var config = require('config');

    if (!config.has("bot.appId")) {
        process.env.NODE_CONFIG_DIR = "../config";
        delete require.cache[require.resolve('config')];
        config = require('config');
    }

    // Create a connector to handle the conversations
    var connector = new teams.TeamsChatConnector({
       appId: config.get("bot.appId"),
       appPassword: config.get("bot.appPassword")
    });

    var inMemoryBotStorage = new builder.MemoryBotStorage();

    var bot = new builder.UniversalBot(connector, async function(session) {

        session.send("Hello world");  

    }).set('storage', inMemoryBotStorage);

    // Setup an endpoint on the router for the bot to listen.
    // NOTE: This endpoint cannot be changed and must be api/messages
    app.post('/api/messages', connector.listen());

    // Export the connector for any downstream integration - e.g. registering a messaging extension
    module.exports.connector = connector;
};

Moblize IT
  • 1,140
  • 2
  • 18
  • 44
  • If you only have two files then what is './messaging-extension'? – Kyle Delaney Aug 30 '19 at 20:40
  • Bot Builder v3 is no longer supported. Would you accept an answer that shows you how to do this with Bot Builder v4? – Kyle Delaney Aug 31 '19 at 00:52
  • yes as long as i can run it and deploy on firebase function – Moblize IT Aug 31 '19 at 04:17
  • Possible duplicate of [Microsoft bot does not respond back from firebase cloud function](https://stackoverflow.com/questions/57446390/microsoft-bot-does-not-respond-back-from-firebase-cloud-function) – Kyle Delaney Sep 03 '19 at 15:46
  • I can see in your [other question](https://stackoverflow.com/questions/57446390/microsoft-bot-does-not-respond-back-from-firebase-cloud-function) that you want to use Firebase for this because you're already using Firebase DB. However, are you sure you need Firebase Functions? When I deploy a bot to Firebase Functions I can see that the bot adapter is getting errors back from its token endpoint, so authentication is failing. I think Firebase Functions has limitations on API calls. Would you consider just normal [Firebase Hosting](https://firebase.google.com/docs/hosting)? – Kyle Delaney Sep 03 '19 at 15:49
  • 1
    yes firebase hosting is fine even if that works. any firebase solution will work as it is just super easy to stay connected with firebase db. no matter is is firebase functions or firebase hosting. – Moblize IT Sep 03 '19 at 18:51
  • And you're targeting Microsoft Teams as your channel, right? – Kyle Delaney Sep 04 '19 at 00:01
  • Is my answer acceptable? – Kyle Delaney Sep 09 '19 at 22:56

1 Answers1

1

I got the echo bot sample to work as a Firebase function. The files from the sample should all go in your functions folder with index.js, bot.js, and .env being the important ones. I made some modifications to index.js so that it uses express and not restify, though it's unclear if that's really necessary. My final index.js looks like this (note the use of the firebase-functions package):

const functions = require('firebase-functions');
const dotenv = require('dotenv');
const path = require('path');
const express = require('express');

// Import required bot services.
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
const { BotFrameworkAdapter } = require('botbuilder');

// This bot's main dialog.
const { EchoBot } = require('./bot');

// Import required bot configuration.
const ENV_FILE = path.join(__dirname, '.env');
dotenv.config({ path: ENV_FILE });

// Create adapter.
// See https://aka.ms/about-bot-adapter to learn more about how bots work.
const adapter = new BotFrameworkAdapter({
    appId: process.env.MicrosoftAppId,
    appPassword: process.env.MicrosoftAppPassword
});

// Catch-all for errors.
adapter.onTurnError = async (context, error) => {
    // This check writes out errors to console log .vs. app insights.
    console.error(`\n [onTurnError]: ${error}`);
    // Send a message to the user
    await context.sendActivity(`Oops. Something went wrong!`);
};

// Create the main dialog.
const bot = new EchoBot();

// Listen for incoming requests.    
const app = express();
app.post('/api/messages', (req, res) => {
    adapter.processActivity(req, res, async (context) => {
        // Route to main dialog.
        await bot.run(context);
    });
});

// Expose Express API as a single Cloud Function:
exports.bot = functions.https.onRequest(app);

Your bot's Microsoft app ID and password will need to be in the .env file because they're used to authenticate requests to and from Microsoft Teams. In order to do this, the bot must make requests to an external token server which is naturally not a part of Google. You'll need a paid plan in order for your function to call an external API like that, as you can see here: Use firebase cloud function to send POST request to non-google server

With a free plan, you can still test the function locally with firebase emulators:start. However, it sounds like you already have a paid plan so I believe this shouldn't be a problem for you. Whether running your bot locally or deployed, your endpoint should end with /bot/api/messages (if you use "bot" as your function name like I have). Once you deploy your bot, you can use the deployed endpoint in the settings blade of your bot resource in Azure.

Kyle Delaney
  • 11,616
  • 6
  • 39
  • 66
  • Sorry for taking forever to come back to this. there are 2 questions: 1. i am getting error with above code as . TypeError: BotFrameworkAdapter is not a constructor at Object. (/Users/moblizeit/code-repo/apps/business-card-scanner/functions/lib/index.js:73:19) at Module._compile (internal/modules/cjs/loader.js:688:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10) at Module.load (internal/modules/cjs/loader.js:598:32) Q2: what would be the minimal code in ./bot.ts file – Moblize IT Nov 30 '19 at 03:46
  • @MobilizeIT - You need to make sure you've installed all the necessary packages, like `botbuilder`. You can install the packages that the sample needs using `npm i`. I've already linked you to the sample which answers your second question. Please remember to accept this answer. – Kyle Delaney Dec 01 '19 at 18:10
  • i do have done npm i botbuilder but no luck. my google firebase function still fails with error Error: Error occurred while parsing your function triggers. TypeError: BotFrameworkAdapter is not a constructor at Object. (/Users/moblizeit/code-repo/apps/business-card-scanner/functions/lib/index.js:71:19) at Module._compile (internal/modules/cjs/loader.js:688:30) – Moblize IT Dec 02 '19 at 03:57
  • @MoblizeIT - What version of `botbuilder` is installed for your project? – Kyle Delaney Dec 02 '19 at 05:38
  • "botbuilder": "^3.16.0", "botbuilder-teams": "^0.2.7", – Moblize IT Dec 02 '19 at 05:44
  • @MoblizeIT - That doesn't answer the question, but also my answer uses Bot Builder v4 and not v3. You said you would accept an answer that uses v4. – Kyle Delaney Dec 02 '19 at 05:47
  • moving to v4 helped the error go away. the new error is on const { EchoBot } = require('./scanbuddymsbot'); where it says EchoBot is not a constructor. The error makes sense to me as the scanbuddymsbot.ts is a blank file. The help i need is what it should have at the minimum to extend on? – Moblize IT Dec 02 '19 at 05:57
  • @MoblizeIT - Did you use the sample that I linked to? – Kyle Delaney Dec 02 '19 at 06:14
  • oops i totally missed that. checking it now – Moblize IT Dec 02 '19 at 06:22