This repository contains materials for bot workshop at devcamp. It's based mainly on Messenger Platform Quick Start Guide
See the Conversational UI presentation
In this section you'll find steps that should be during the workshop.
1. Get familiar with Express
Create a node project:
npm init
Install Express:
npm install express --save
Create your first Express app (from expressjs.com):
const express = require('express')
const app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
Start your app:
node index.js
Navigate to: http://localhost:3000/
Use nodemon:
npm install -g nodemon
Start your app:
nodemon index.js
Download and install ngrok https://ngrok.com/download
Start tunneling:
ngrok 3000
Facebook page will represent your bot. Create it here: https://www.facebook.com/pages/create
- Go to: https://developers.facebook.com/apps
- Click + Add a New App button
- Select Messenger product - click Set Up
A webhook is an address towards which Messenger Platform will forward messages.
First you have to create a route in your Express app:
app.get('/webhook', function(req, res) {
...
});
This route will be used to verify our app. Use the code below. Remember to set your own VERIFY_TOKEN
.
app.get('/webhook', function(req, res) {
if (req.query['hub.mode'] === 'subscribe' &&
req.query['hub.verify_token'] === <VERIFY_TOKEN>) {
console.log("Validating webhook");
res.status(200).send(req.query['hub.challenge']);
} else {
console.error("Failed validation. Make sure the validation tokens match.");
res.sendStatus(403);
}
});
Now go to your facebook app and click Setup Webhooks.
Paste your ngrok address into Callback URL field.
Paste in your VERIFY_TOKEN
.
Select messages and messaging postbacks checkboxes.
Click Verify and Save button.
Go to Token Generation section on your facebook app page.
Select your page and generate the token.
Accept the permission request.
Go to Webhooks section. Select the page that you've created before and click Subscribe.
Now all the messages sent to your page will be forwarded to your webhook.
To catch the message we have to handle a POST request.
app.post('/webhook', function (req, res) {
var data = req.body;
console.log(data);
// You must send back a 200, within 20 seconds, to let us know
// you've successfully received the callback. Otherwise, the request
// will time out and we will keep trying to resend.
res.sendStatus(200);
});
In order to see anything useful in our console we have to add a body-parser
. Add the following code at the beginning of your app:
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
Now open Messenger, find your page and send a message to it. Check out your console.
As you can see messages are sent in JSON format. Ngrok has a web interface that will help us examine this format. Please open it, it's probably here: http://127.0.0.1:4040
Now when we've got familiar with the message format we can parse it. Use the following code:
app.post('/webhook', function (req, res) {
var data = req.body;
// Make sure this is a page subscription
if (data.object === 'page') {
// Iterate over each entry - there may be multiple if batched
data.entry.forEach(function(entry) {
var pageID = entry.id;
var timeOfEvent = entry.time;
// Iterate over each messaging event
entry.messaging.forEach(function(event) {
if (event.message) {
receivedMessage(event);
} else {
console.log("Webhook received unknown event: ", event);
}
});
});
// Assume all went well.
//
// You must send back a 200, within 20 seconds, to let us know
// you've successfully received the callback. Otherwise, the request
// will time out and we will keep trying to resend.
res.sendStatus(200);
}
});
function receivedMessage(event) {
// Putting a stub for now, we'll expand it in the following steps
console.log("Message data: ", event.message);
}
What we'd like to do now is answer the message. Messages are sent by sending a POST request to the facebook API. Let's implement a function that we'll comunicate with this API.
First we have to install request module.
npm i request --save
Let's import it into our project:
const request = require('request');
Let's use it:
function callSendAPI(messageData) {
request({
uri: 'https://graph.facebook.com/v2.6/me/messages',
qs: { access_token: PAGE_ACCESS_TOKEN },
method: 'POST',
json: messageData
}, function (error, response, body) {
if (!error && response.statusCode == 200) {
var recipientId = body.recipient_id;
var messageId = body.message_id;
console.log("Successfully sent generic message with id %s to recipient %s",
messageId, recipientId);
} else {
console.error("Unable to send message.");
console.error(response);
console.error(error);
}
});
}
Now we have to generate a PAGE_ACCESS_TOKEN
.
Go to Token Generation section on your facebook app page.
Select your page and generate the token.
Copy it and paste into your code.
Now we can use our callSendAPI function:
function receivedMessage(event) {
var senderID = event.sender.id;
var recipientID = event.recipient.id;
var timeOfMessage = event.timestamp;
var message = event.message;
console.log("Received message for user %d and page %d at %d with message:",
senderID, recipientID, timeOfMessage);
console.log(JSON.stringify(message));
var messageId = message.mid;
var messageText = message.text;
var messageAttachments = message.attachments;
echo(senderID, messageText);
}
function echo(recipientId, messageText){
// Construct reply message
var echo = {
recipient: {
id: recipientId
},
message: {
text: messageText
}
};
callSendAPI(echo);
}
Cool, we're able to talk with our bot! Now let's make this conversation more interactive.
Let's add sendStructuredMessage
function:
function sendStructuredMessage(recipientId) {
var messageData = {
recipient: {
id: recipientId
},
message: {
attachment: {
type: "template",
payload: {
template_type: "generic",
elements: [{
title: "Codecool",
subtitle: "The best programming school",
item_url: "https://codecool.pl/",
image_url: "https://crossweb.pl/job/wp-content/uploads/2016/06/codecool.png",
buttons: [{
type: "web_url",
url: "https://codecool.pl/",
title: "Open Web URL"
}, {
type: "postback",
title: "Call Postback One", // button text
payload: "Payload for first bubble", // postback body
}],
}, {
title: "DevCamp",
subtitle: "The best IT event",
item_url: "http://devcamp.pl/",
image_url: "https://d1ll4kxfi4ofbm.cloudfront.net/images/621921/3af0f2b904c54475f17a7919b166e900.png",
buttons: [{
type: "web_url",
url: "http://devcamp.pl/",
title: "Open Web URL"
}, {
type: "postback",
title: "Call Postback Two",
payload: "Payload for second bubble",
}]
}]
}
}
}
};
callSendAPI(messageData);
}
Now let's call it. Modify receivedMessage
function this way:
function receivedMessage(event) {
var senderID = event.sender.id;
var recipientID = event.recipient.id;
var timeOfMessage = event.timestamp;
var message = event.message;
console.log("Received message for user %d and page %d at %d with message:",
senderID, recipientID, timeOfMessage);
console.log(JSON.stringify(message));
var messageId = message.mid;
var messageText = message.text;
var messageAttachments = message.attachments;
if(messageText=='magic'){
sendStructuredMessage(senderID);
} else {
echo(senderID, messageText);
}
}
Send magic message to your bot and see what happens.
Messenger Platform Docs: https://developers.facebook.com/docs/messenger-platform
Express JS: https://expressjs.com/
Nodemon: https://nodemon.io/
ngrok: https://ngrok.com/
- The Bot UI
- The Complete Beginner’s Guide To Chatbots
- Messenger Platform Docs
- Chatbot Platforms Comparison
- Very simple messenger bot framework
Mateusz Ostafil - Mentor/Developer @ Codecool