Build a Facebook Messenger Bot App

3 min readWeb DevelopmentBuilding Products

visitor in MessengermessagereplyFacebook PageMessenger platformGET · verify token, challengengrok tunnel→ localhost:3000each message is POSTed herereply · chat.say(...)Bot app · TypeScript · Node.js · ExpressBootBotaccessToken · verifyToken · appSecret, from .envits subserver listens on :3000; Express itself on :8080handlerssetGreetingText → shown when the chat is first openedon('message') → loggedon('attachment') → 'We do not support this message type'modules, via bot.module()greetFunc · hears hello / sup / hey → 'Hello, human friend!',then asks for a genre; bye / adios / see ya → 'Bye, human!'helpFunc · genreFunc — not shown in the postthe pattern: bot.hear([...]) → chat.say(...)
The post's setup. Facebook verifies the webhook once with a GET carrying the verify token and a challenge, then POSTs each message to it through an ngrok tunnel to port 3000, where BootBot's subserver listens. Modules registered with bot.module() match incoming text with bot.hear() and answer with chat.say(); attachments get a fixed reply, and every message is logged.

Here is the source code {Github Link}

The goal of this post is to showcase how easy it is to create a Facebbok Messenger Bot which is capable of handling almost all of your customer’s queries or questions etc. Lets dive into the code.

Installation

git clone https://github.com/prashantban/Facebook-Bot-App
cd Facebook-Bot-App
npm install
npm build (To build app)
npm run (To run app)

Before we begin running this app, we need coupld of things from Facebook Developer . Here is the list of things needed -

Facebook Page 
Facebook Developer App
Access Token
App Secret
Verify Token

Here is the link for Facebook Developer Panel. Now follow the instruction to create a new Facebook Messenger App.

Add a product Messenger
Select your FB Page and generate the token. This will be your access token.
Then you need to setup webhook endpoint. For this, we will have to write some code and expose a Webhook endpoint on our app.

Webhook Endpoint

Facebook expects an endpoint in your system where messages will be posted. But prior to posting messages, facebook makes a GET call to the same api to verify the access token. Remember, above we Verify Token, put some random string in your .env file for now.

# Any secret to be kept

APP_SECRET='<Your App Secret>'
ACCESS_TOKEN='Access Token Copied from Your FB Page'
VERIFY_TOKEN='my random string'

We will leave this for now, and get started with our code. This project will be built in TypeScript. To those who have little to no idea about TypeScript, can read here. Here are the following things need to be present -

nodejs
npm
typescript
express

Obviously we have done npm install, so I assume all these things are available. Here is how our folder structure looks (this is the layout of the repository linked above) -

src/
  server.ts, app.ts              Express server; PORT comes from .env
  controllers/
    api.ts                       the bot, the code below
    home.ts, bootbot.d.ts
  modules/
    greet.ts, help.ts, genre.ts
  types/
    payloadTypes.ts, chatTypes.ts, genreResponse.ts
  util/
    logger.ts, genreData.ts, utilFunctions.ts
.env.example
package.json, tsconfig.json

As simple as it can get, here is the code for our bot.

"use strict";
import express from "express";
const router = express.Router()
import logger from "../util/logger";
import BootBot from 'bootbot';
import {Payload} from "../types/payloadTypes";
import {Chat} from "../types/chatTypes";
import {helpFunc} from "../modules/help";
import {genreFunc} from "../modules/genre";
import {greetFunc} from "../modules/greet";

const bot = new BootBot({
    accessToken: process.env.ACCESS_TOKEN,
    verifyToken: process.env.VERIFY_TOKEN,
    appSecret: process.env.APP_SECRET
});

/**
 * Define Home page route
 * Not using this here though
 */
router.get('/', function (_req, res) {
    res.send('Thanks for Checking Us Out');
});

/**
 * This will get triggered as and when any one
 * opens the chat window for the first time
 */
bot.setGreetingText("Hello, Welcome to XYZ Page. Lets start by knowing your favorite genre.");

/**
 * Log the message we receive.
 * All the message with type `message`
 * will appear in this function
 */
bot.on('message', (payload : Payload, _chat : Chat) => {
    logger.info({"module": "Api Controller", "message": payload.message.text, "details": payload});
});

/**
 * Log the Attachment message we receive.
 * All the message with type `Attachment message`
 * will appear in this function
 */
bot.on('attachment', (payload : Payload, chat : Chat) => {
    logger.info({"module": "Api Controller", "message": "Recieved Attachment", "details": payload});
    chat.say('We do not support this message type');
});

/**
 * Assign Bot Modules
 */
bot.module(greetFunc);
bot.module(helpFunc);
bot.module(genreFunc);

/**
 * Start the Bot
 */
bot.start(process.env.BOTPORT);

export default router;

To explain, FB supports several different types of messages, for example - Normal Message, Greeting Text, Quick Reply, Options etc , so instead of creating the structure of each of those, we are using a library named bootbot. This library has a pretty neat interface to define what type of message to be sent. Note, for instantiating an instance of bootbot, we are passing all the necessary client details to it at the top.

Let me put up the greetFunc module as well, to give more context on how a message is programmed.

import {Payload} from "../types/payloadTypes";
import {Chat} from "../types/chatTypes";
import logger from "../util/logger";

export const greetFunc = (bot : any) => {

    bot.hear(['hello', 'sup', /hey( there)?/i], (payload : Payload, chat : Chat) => {
        logger.info({"module": "Api Controller", "message": payload.message.text, "details": chat});
        chat.say('Hello, human friend!').then(() => {
            chat.say('Please say genre to get the list of genres to search from', { typing: true });
        });
    });

    bot.hear([/(good)?bye/i, /see (ya|you)/i, 'adios', 'get lost', 'thankyou'], (_payload : Payload, chat : Chat) => {
        chat.say('Bye, human!');
    });

};

All we are doing is defining a set of array with possible values and as soon as a visitor sends any of these values, we respond back with the defined message.

Assuming, that now its pretty staright forward code, lets come back to the webhook verification part. First, lets follow the following steps -

npm build
npm run
./ngrok http 3000

Note, we are starting our app in port 8080, but are forwarding port 3000 as bootbot creates a subserver which by default utilizes port 3000. Now, go back to Facebook Developer Webhook page, select Create Subscription, enter the ngrok or localtunnel or forward url, paste the secret string defined above and hit verify. Once facebook is able to hit the endpoint, it will send a challenge which will be verified against your app secret.

Thats it, we are pretty much done. You can start the conversation with the bot.

As part of extension, you can use some sort of Database to store the User and probably the received messages, run some analytics to improve the bot responses. This has a very different challenge, but I leave that to you to determine.

Here is the source code again {Github Link}

Feel free to contact for any suggestion - dev[at]prashantb[dot]me