Skip to content

Instantly share code, notes, and snippets.

@ispiropoulos
Forked from mikkipastel/index.js
Last active September 14, 2023 12:29
Show Gist options
  • Save ispiropoulos/ffa7e4dc352b4024440a89af1616dcf3 to your computer and use it in GitHub Desktop.
Save ispiropoulos/ffa7e4dc352b4024440a89af1616dcf3 to your computer and use it in GitHub Desktop.
facebook chatbot from cloud function in firebase

Firebase Cloud function for simple Messenger greet and echo Bot

Notes

You need to add 3 environment variables:

ACCESS_TOKEN

This is the page specific access token you have generated, from the app settings on the Facebook developers console

VERIFY_TOKEN

This is the verify token you will provide when you subscribe the app to the webhook on the Facebook developers console

APP_SECRET

This is the App Secret that Facebook has generated for your app. It can be found on the Facebook developers console under the basic settings of your app. It is used to validate the request so that your cloud function can take actions only upon requests originating from Facebook.

// import needed modules
const functions = require('firebase-functions');
const crypto = require('crypto');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// Create and Deploy Your First Cloud Functions
// https://firebase.google.com/docs/functions/write-firebase-functions
exports.botHook = functions.https.onRequest((request, response) => {
if (request.method == "GET") {
if (request.query['hub.mode'] === 'subscribe' &&
request.query['hub.verify_token'] === process.env.VERIFY_TOKEN) {
console.log("Validating webhook");
response.status(200).send(request.query['hub.challenge']);
} else {
console.error("Failed validation. Make sure the validation tokens match.");
response.sendStatus(403);
}
} else if (request.method == "POST") {
const hmac = crypto.createHmac('sha1', process.env.APP_SECRET);
hmac.update(request.rawBody, 'utf-8');
//Validate webhook event
if (request.get('X-Hub-Signature') === `sha1=${hmac.digest('hex')}`) {
var data = request.body;
if (data.object === 'page') {
data.entry.forEach(entry => {
var pageID = entry.id;
var timeOfEvent = entry.time;
entry.messaging.forEach(event => {
if (event.message) {
receivedMessage(event)
} else {
console.log("Webhook received unknown event: ", event)
}
})
})
response.sendStatus(200)
}
} else {
console.log("Received request from unknown origin.");
response.sendSstatus(400);
}
}
});
function writeToFirebaseDB(theUser, theTimeStamp, theMessage, theSender) {
/*
This function inserts the messages into the firebase database for quick history access.
The path is users -> userId (the page-specific id of the user) -> timestamp
The object is pretty much self-explainatory
*/
const refPath = 'users/messenger/' + theUser + '/' + theTimeStamp;
var ref = admin.database().ref(refPath);
return ref.set({
timestamp: theTimeStamp,
message: theMessage,
sender: theSender
});
}
function receivedMessage(event) {
let senderId = event.sender.id
let recipientId = event.recipient.id
let timeOfMessage = event.timestamp
let 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))
let messageId = message.mid
let messageText = message.text
let messageAttachments = message.attachments
if (messageText) {
//Uncomment the next line to write the message into the firebase db.
//writeToFirebaseDB(senderId, timeOfMessage, messageText, 'user');
if (messageText.toLowerCase()) {
//If the user wrote 'hello', then greet them. If not, then echo back their message.
if (messageText.search('hello') >= 0) {
greeting(senderId)
} else {
sendTextMessage(senderId, messageText)
}
}
} else if (messageAttachments) {
sendTextMessage(senderId, "Message with attachment received");
}
}
function greeting(recipientId) {
let messageData = {
recipient: {
id: recipientId
},
message: {
text: "Welcome! Nice to meet you"
}
}
callSendAPI(messageData)
}
function sendTextMessage(recipientId, messageText) {
let messageData = {
recipient: {
id: recipientId
},
message: {
text: messageText
}
}
callSendAPI(messageData)
}
const axios = require('axios')
function callSendAPI(messageData) {
axios({
method: 'POST',
url: 'https://graph.facebook.com/v2.6/me/messages',
params: {
'access_token': process.env.ACCESS_TOKEN
},
data: messageData
})
.then(response => {
if (response.status == 200) {
let body = response.data
let recipientId = body.recipient_id;
let messageId = body.message_id;
if (messageId) {
console.log("Successfully sent message with id %s to recipient %s",
messageId, recipientId);
} else {
console.log("Successfully called Send API for recipient %s",
recipientId);
}
const timeOfMessage = new Date().getTime();
//Uncomment the next line to write the message into the firebase db
//writeToFirebaseDB(recipientId, timeOfMessage, messageData.message.text, 'me');
} else {
console.error("Failed calling Send API", response.status,
response.statusText, response.data.error);
}
})
.catch(error => {
console.error(error);
})
}
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"dependencies": {
"firebase-admin": "~5.2.1",
"firebase-functions": "^0.6.2",
"axios": "0.16.2"
},
"private": true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment