Created
November 1, 2016 17:48
-
-
Save stripethree/e22d6d9a095bddca0ba76d60e2ffe798 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Example Facebook Messenger app that pulls the user's public profile and echoes back any messages sent | |
with the user's first and last name. | |
So if I sent the bot "Good morning!" it will reply to me with "Echoing message from Jeff Israel: Good morning!" | |
*/ | |
const bodyParser = require('body-parser'); | |
const crypto = require('crypto'); | |
const express = require('express'); | |
const reqPromise = require('request-promise'); | |
const facebookHookUrl = '/webhook'; | |
const graphApiUrl = 'https://graph.facebook.com/v2.6'; | |
const FB_ACCESS_TOKEN = process.env.MESSENGER_PAGE_ACCESS_TOKEN; | |
const FB_APP_SECRET = process.env.MESSENGER_APP_SECRET; | |
const FB_VERIFY_TOKEN = process.env.MESSENGER_VALIDATION_TOKEN; | |
const app = express(); | |
function sendPayload(recipientId, payload) { | |
const msgJson = { | |
message: payload, | |
recipient: { id: recipientId } | |
}; | |
const options = { | |
json: msgJson, | |
method: 'POST', | |
qs: { access_token: FB_ACCESS_TOKEN }, | |
url: graphApiUrl + '/me/messages' | |
}; | |
reqPromise(options) | |
.then((jsonString) => { | |
// TODO: parse the jsonString and act on returned data if needed | |
console.log(jsonString); | |
}) | |
.catch((err) => { | |
// TODO: better error handling | |
throw err; | |
}); | |
} | |
function sendMessage(senderId, text) { | |
const messageData = { text: text }; | |
sendPayload(senderId, messageData); | |
} | |
function verifyRequestSignature(req, res, buf) { | |
var signature = req.headers['x-hub-signature']; | |
// I would probably not would log the FB_APP_SECRET in a non-dev env... | |
if (!signature) { | |
console.error('Couldn\'t validate the signature with app secret:' + FB_APP_SECRET); | |
} else { | |
const elements = signature.split('='); | |
const signatureHash = elements[1]; | |
const expectedHash = crypto.createHmac('sha1', FB_APP_SECRET) | |
.update(buf) | |
.digest('hex'); | |
if (signatureHash !== expectedHash) { | |
throw new Error('Couldn\'t validate the request signature: ' + FB_APP_SECRET); | |
} | |
} | |
} | |
app.use(bodyParser.json()); | |
app.use(bodyParser.json({ verify: verifyRequestSignature })); | |
app.use(bodyParser.urlencoded({ extended: true })); | |
// nice to have as a simple check that the app is running in addition to the initial logs | |
app.get('/', (req, res) => { | |
res.send('Hello.'); | |
}); | |
// Facebook Messenger verification | |
app.get(facebookHookUrl, (req, res) => { | |
console.log(FB_VERIFY_TOKEN); | |
if (req.query['hub.verify_token'] === FB_VERIFY_TOKEN) { | |
res.send(req.query['hub.challenge']); | |
} | |
res.send('Error, wrong token'); | |
}); | |
app.post(facebookHookUrl, (req, res) => { | |
const data = req.body; | |
if (data.object === 'page') { | |
data.entry.forEach(function (pageEntry) { | |
pageEntry.messaging.forEach(function (messagingEvent) { | |
if (messagingEvent.message) { | |
// we've got a messaging event! | |
if (messagingEvent.message.is_echo) { | |
// https://developers.facebook.com/docs/messenger-platform/webhook-reference/message-echo | |
// these are messages sent by the page back to the user | |
console.log('Is there an echo in here?'); | |
} else if (messagingEvent.message && messagingEvent.message.text) { | |
// setup options for call to Graph API for public profile | |
const options = { | |
qs: { | |
access_token: FB_ACCESS_TOKEN, | |
fields: 'first_name,last_name,profile_pic,locale,timezone,gender' | |
}, | |
url: `${graphApiUrl}/${messagingEvent.sender.id}` | |
}; | |
// call the Graph API! | |
reqPromise(options) | |
.then((jsonString) => { | |
const jsonObj = JSON.parse(jsonString); | |
const message = `Echoing message from ${jsonObj.first_name} ${jsonObj.last_name}: ${messagingEvent.message.text}`; | |
sendMessage(messagingEvent.sender.id, message); | |
}) | |
.catch((err) => { | |
throw err; | |
}); | |
} | |
} | |
}); | |
}); | |
} | |
res.sendStatus(200); | |
}); | |
app.set('port', process.env.PORT || 3000); | |
app.listen(app.get('port'), function (err) { | |
if (err) throw err; | |
console.log('Server running on port ' + app.get('port')); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment