80 lines
2.0 KiB
JavaScript
80 lines
2.0 KiB
JavaScript
const {text, json, createError} = require('micro')
|
|
const {get, post, withNamespace} = require('microrouter')
|
|
const FB = require('fb')
|
|
|
|
FB.setAccessToken(process.env.FB_ACCESS_TOKEN)
|
|
|
|
const fbParser = require('claudia-bot-builder/lib/facebook/parse')
|
|
const fbValidate = require('claudia-bot-builder/lib/facebook/validate-integrity')
|
|
|
|
const conversation = require('./conversation')
|
|
|
|
/**
|
|
* In-Memory cache for FB graph results
|
|
*/
|
|
const recipients = []
|
|
|
|
/**
|
|
* GET webhook
|
|
*
|
|
* Gets executed when you add the Webhook URL to the Facebook and it tries
|
|
* to validate it.
|
|
*/
|
|
const verifyToken = req => {
|
|
if (req.query['hub.verify_token'] === process.env.FB_VERIFY_TOKEN) {
|
|
return req.query['hub.challenge']
|
|
}
|
|
console.info(
|
|
`Your Facebook Access Token (that Facebook will echo back to you as part of callback URL verification): ${
|
|
process.env.FB_VERIFY_TOKEN
|
|
}`
|
|
)
|
|
return 'INVALID TOKEN'
|
|
}
|
|
|
|
/**
|
|
* Validate and convert request to a common message format
|
|
*/
|
|
const fbMessage = async req => {
|
|
req.env = {facebookAppSecret: process.env.FB_APP_SECRET}
|
|
req.rawBody = await text(req)
|
|
const data = await json(req)
|
|
const [[message]] = data.entry.map(entry =>
|
|
entry.messaging.map(message => fbParser(message))
|
|
)
|
|
|
|
const isValid = fbValidate(req) && message.type === 'facebook'
|
|
|
|
return isValid ? message : false
|
|
}
|
|
|
|
/**
|
|
* POST webhook
|
|
*
|
|
* Gets executed on any message to the Bot.
|
|
*/
|
|
const respond = async (req, res) => {
|
|
const message = await fbMessage(req)
|
|
if (message) {
|
|
const recipient =
|
|
recipients[message.sender] || (await FB.api(message.sender))
|
|
|
|
// Cache recipients
|
|
recipients[message.sender] = recipient
|
|
|
|
try {
|
|
await conversation(message, recipient)
|
|
} catch (err) {
|
|
console.error(err)
|
|
res.end(err.message)
|
|
}
|
|
|
|
res.end()
|
|
} else {
|
|
throw createError(400, 'Invalid message signature.')
|
|
}
|
|
}
|
|
|
|
const fbApi = withNamespace('/api/v1/facebook')
|
|
module.exports = fbApi(get('/', verifyToken), post('/', respond))
|