Develop Facebook chat bot using Javascript – Part 2

Continued from Develop Facebook chat bot using Javascript – Part 1

Basic verification is complete, Now lets test webhook and see if we are receiving messages sent to bot page to our webhook or not.

Receiving messages

Add the following code to server.js

app.post('/',handleMessage);

This code tells express to run handleMessage function whenever a POST request is made.

And add handleMessage function

function handleMessage(req, res) {
  messaging_events = req.body.entry[0].messaging;
  for (i = 0; i < messaging_events.length; i++) {
    event = req.body.entry[0].messaging[i];
    sender = event.sender.id;
    if (event.message && event.message.text) {
      text = event.message.text;
      console.log(text);
    }
  }
  res.end('received!');
}

Note: Dont forget to restart server after making changes in code everytime. Use Nodemon if you want to restart server automatically on file change

Messages sent to bot page are sent in an array named messaging with sender Id and message. Sender Id will be used to reply to the sender. Messenger platform may queue the messages sometime and send multiple messages in same POST request, so we make sure that all messages are captured by looping through the messaging array.

We are using console.log(text) to log the message to console for testing.

Subscribe to bot page in app dashboard and you should start receiving messages to webhook as shown in gif below.

Testing messenger bot

We are building a wiki bot which searches wikipedia and sends relevant results. We will be using wikipedia REST API to search wikipedia and return results. Read more about wikipedia API here

If user sends wiki space ‘search query’ then bot should make a request to wikipedia API with search query, return results and send them to user using Facebook send API.

If user sends anything else then bot should reply with a help message Send Wiki space ‘Search query’ to search wikipedia.

Send a basic Message to user

Messages can be sent using send API by making a POST request to https://graph.facebook.com/v2.6/me/messages?access_token=PAGE_ACCESS_TOKEN

Page Access token can be accessed in messenger platform dashboard.

I’m using request, a NodeJS module which helps in making HTTP requests easier. As we have to make GET requests to wikipedia API and POST requests to messenger send API. Read more about request module here

In command line type npm install request --save

This will install request module and adds it as a dependency in Package.json file. Now lets write some code to send a simple message to user.

Note: Make sure to import request module wherever you are using it.
var request = require('request');

var url = "https://graph.facebook.com/v2.6/me/messages?access_token=<PAGE_ACCESS_TOKEN>" //replace with your page token
function sendHelp(id) {
var options = {
    uri: url,
    method: 'POST',
    json: {
      "recipient": {
        "id": id
      },
      "message": {
        "text": "Send wiki space 'Your query' to search wikipedia"
      }
    }
  }
  request(options, function(error, response, body) {
    if (error) {
      console.log(error.message);
    }
  });
};

This function takes a sender id as parameter and sends a JSON to send API. Read more about FB send API here

Now replace the line console.log(text); with sendHelp(sender);

Now whenever someone sends a message to your bot page, bot replies them with a help message.

Structured messages in chat bot

Messenger platform allows 2 types of messages – Normal text messages and Structured messages. There are 3 types of templates in structured messages allowed by messenger platform. They are Button template, Generic template and receipt template.

Read more about different templates here

Code examples for structured messages are availabe here

I’m using generic template for wiki bot as shown in the demo video. Generic template can contain title, description and some buttons which is perfect for this case.

To send a structured message, we just have to send JSON to send API in a specific format.

Send wikipedia results

The final part where bot searches wikipedia and sends results. We’ll be making a GET request to https://en.wikipedia.org/w/api.php?format=json&action=query&generator=search&gsrnamespace=0&gsrlimit=10&prop=extracts&exintro&explaintext&exsentences=5&exlimit=max&gsrsearch=searchquery

After getting response fron API, results are stuffed into generic template and send to user using messenger bot send API.

function wikibot(query, userid) {
  var queryUrl = "https://en.wikipedia.org/w/api.php?format=json&action=query&generator=search&gsrnamespace=0&gsrlimit=10&prop=extracts&exintro&explaintext&exsentences=5&exlimit=max&gsrsearch=" + query;
  var myTemplate = {
    recipient: {
      id: userid
    },
    message: {
      attachment: {
        type: "template",
        payload: {
          template_type: "generic",
          elements: []
        }
      }
    }
  };
  var options = {
    url: url,
    method: 'POST',
    body: myTemplate,
    json: true
  }
  request(queryUrl, function(error, response, body) {
    if (error) {
      console.log(error);
    }
    try {
      body = JSON.parse(body);
      var pages = body.query.pages;
      for (var i = 0 in pages) {
        var myelement = {
          title: "",
          subtitle: "",
          buttons: [{
            type: "postback",
            title: "Read more",
            payload: "Nothing here, Please view in browser"
          }, {
            type: "web_url",
            url: "",
            title: "View in browser"
          }]
        };
        myelement.title = pages[i].title;
        myelement.subtitle = pages[i].extract.substr(0, 80).trim();
        myelement.buttons[1].url = "https://en.wikipedia.org/?curid=" + pages[i].pageid;
        if (pages[i].extract != "") {
        myelement.buttons[0].payload = pages[i].extract.substr(0, 1000).trim();
        }
        myTemplate.message.attachment.payload.elements.push(myelement);
      }
      options.body = myTemplate;
    }
    catch (err) {
      console.log("error : " + err.message);
      options = {
        uri: url,
        method: 'POST',
        json: {
          "recipient": {
            "id": userid
          },
          "message": {
            "text": "Something went wrong, please try again."
          }
        }
      }
    }
    request(options, function(error, response, body) {
      if (error) {
        console.log(error.message);
      }
      console.log(body);
    });
  })
};

Code Explanation

  1. This function takes search query and sender id as parameters. Makes a GET request to wikipedia API and returns an array of page results which are saved to pages variable.

  2. generic template JSON is saved to mytemplate variable. generic template contains elements in which page results should be pushed.

  3. Element’s format is saved in myelement. Loop through each page in pages, add title sub-title, description to payload button Read more and page URL to View in browser button and push myelement to elements array in mytemplate.

  4. Generic template with search results is ready. Now just send it using send API.

  5. If any error occurs with Wikipedia API then send a regular help message.

Character Limits

Sending message using Send API has few limits. They are as follows :

Normal message : 320 character limit

Generic Template limits :
Title: 80 characters
Subtitle: 80 characters
Call-to-action title: 20 characters
Call-to-action items: 3 buttons
Bubbles per message (horizontal scroll): 10 elements

Note : Message won’t be sent if these limits are exceeded, so make sure to trim messages to appropriate character limits before they are sent.

Chat bot payload button

Payload button is used when bot has to be notified with some data when user clicks a button. In wikibot, payload button is used to let the bot know that user wants to read more information about the search result when he clicks read more button.

When user clicks read more button, a postback is sent to webhook. To identify whether the request is a message or post back, we can check the properties in messaging event. If its a message then there would be a message property else there would be a post back property in messaging event.

Utiliity functions

A format message function which is used to trim down page description to 320 characters.

function formatmsg(msg){
    msg = msg.substr(0,320);
    if(msg.lastIndexOf(".") == -1) {
        return msg;
    }
    return msg.substr(0,msg.lastIndexOf(".")+1);
}

One more sendMessage function which takes in sender id and message as parameters and sends message to that sender id. It is same as sendHelp function but takes message as a paramter. This function is used to reply to postbacks.

Putting it all together

Final handleMessage function looks like this

function handleMessage(req, res) {
    var messaging_events = req.body.entry[0].messaging;
    for (i = 0; i < messaging_events.length; i++) {
        event = req.body.entry[0].messaging[i];
        var sender = event.sender.id;
        console.log(sender);
        if (event.message && event.message.text) {
            var text = event.message.text.toLowerCase().trim();
            console.log(text);
            if (text.toLowerCase().substr(0,4) == 'wiki') {
                wikibot(text.replace("wiki ", ""),sender)
            }
            else {
                sendHelp(sender);
            }
        }
        else if(event.postback && event.postback.payload){
           sendMessage(sender,event.postback.payload) ;
        }
    }
    res.end('replied!');
}

I’ll be uploading complete source code soon. Meanwhile, try building this chat bot and think about what else can be built using this technology. The same code can be used in hook.io to deploy the bot with some changes.

Read how to deploy chat bot to hook.io

You can start using wiki bot by clicking on Message Us button below!

Wrapping up

I’ve neither optimised this bot for best use nor handled all the errors. This was built just to get started with chat bots for facebook messenger. There’s always lot more that can be done, read official documentation and build better bots.

We can use wit.ai which provides full API with artificial intelligence for interacting with users. It is also free. We can build full conversational bots using wit.ai

A paid alternative to wit.ai is api.ai which also has inbuilt integration for facebook messenger platform. Try it too, It has a free plan with limitations.

Chat bots for facebook messenger can also be used for business but has few limitations, so start building bots for your business too.

If you have and questions or feedback, comment below.

Ranjith kumar
0 0 votes
Article Rating
Subscribe
Notify of
guest

27 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Duncan
Duncan
7 years ago

Great tutorial. Would love to see how it comes together with hook.io

Cobus
Cobus
7 years ago

I cannot get my bot to send back messages?

What am I doing wrong?

AT
AT
7 years ago

Hi! Thanks for the Tutorial! I have one problem: I think Facebook didn’t match to my webhook and if I want to run the post I only have errors. Where is the decleration of the messaging_event?

AT
AT
7 years ago
Reply to  AT

I only use Cloud9!

AT
AT
7 years ago
Reply to  Ranjith kumar

No…I setuped the webhook. I am only an amateur coder, so maybe I forgot something in settings or something to install?Now I got this error (The code is the same of you
re code here in the tutorial):
TypeError: Cannot read property ‘entry’ of undefined
at handleMessage (/home/ubuntu/workspace/server.js:41:30)
at callbacks (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:161:37)
at param (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:135:11)
at pass (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:142:5)
at Router._dispatch (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:170:5)
at Object.router (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:33:10)
at next (/home/ubuntu/workspace/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Object.expressInit [as handle] (/home/ubuntu/workspace/node_modules/express/lib/middleware.js:31:5)
at next (/home/ubuntu/workspace/node_modules/express/node_modules/connect/lib/proto.js:190:15)
at Object.query [as handle] (/home/ubuntu/workspace/node_modules/express/node_modules/connect/lib/middleware/query.js:44:5)

AT
AT
7 years ago
Reply to  AT

Thanks for yu’re help!!!!!

AT
AT
7 years ago
Reply to  Ranjith kumar

You got an email (Email which is written by the newsletter of this page)!

Arpit
Arpit
7 years ago

Hello,
Thanks Ranjith for this awesome tutorial.
I can run the code on cloud9.
But when I deployed the code on hook.io, it seems like request module is not working.

Do we need to do anything to ask HOOK.io to install this dependency?
Code:
console.log(‘before calling api’);
request(url,options, function(error, response, body) {
if (error) {
console.log(error.message);
}
});

Gauhar Shakeel
Gauhar Shakeel
7 years ago

Hi Ranjith,
Great tutorial!!! Everything is almost working. There is a small issue that when I press Read more it is not doing anything. I don’t get a reply. If I press “View in Browser” it works. Can you please help me why am I not getting a reply when I press “read more” button? Thank you.

Swapnil
Swapnil
7 years ago

Hi sir, great article!But I need your help. I want to send the messages longer than 320 characters using facebook messenger. what should i do? Please suggest me a suitable solution. (I have created a facebook bot using node.js running on ubuntu 14.04.)

victor
victor
7 years ago

For me the bot just answer myself… Any thoughts on it?
https://gist.github.com/augustovictor/02d2d6b02828fe9d4cadb98181240533

Vianney
Vianney
7 years ago

Hello,
Thanks for the great tutorial!
I would like to host my bot on my own server, at OVH https://www.ovh.com/ .
Could you explain what would be the differences?
Many thanks!
Vianney

Lewi
Lewi
7 years ago

Hi Ranjith,
Great tutorial, thank you so much. For unknown reasons the first two codes on top of this page (for receiving messages) are not being recognized in the c9 server.js tab. When I load the page on the right side i get: Error, wrong validation token!
Although i typed verifycode.
Also i get yellow marks in the line of code which say i need to include “global”. but when i do that i do not get any result and it says that global cannot be used. Would appreciate your help.

Lewi
Lewi
7 years ago
Reply to  Ranjith kumar

hi, i figured it out already. Thanks!