该材料的译文(我们今天将向您介绍该译文)致力于开发Facebook Messenger聊天机器人。 与用户交流的名为Aww Bot的机器人将向他们发送可爱的猫和狗的图片。

开始使用
首先,通过填写必填字段在
Facebook上创建一个页面。 此页面适用于机器人。 此外,
我们将创建一个 Facebook应用程序,然后在“添加产品”页面上,将Messenger产品连接到该应用程序。 接下来,我们将在Messenger设置页面上找到自己。 在这里,您需要找到“令牌生成”部分,在其中-在“页面”列表中选择机器人页面。 之后,将询问我们有关权限的信息,并创建一个访问令牌。 该机器人将使用此令牌来调用Facebook Messenger API,这将使其与用户进行通信。
Web服务器设置
我们将使用node.js和express.js创建一个HTTP服务器。 运行以下命令:
npm install express body-parser request config
将以下代码添加到
index.js
,以使您可以创建简单的HTTP服务器:
'use strict'; let express = require('express'), bodyParser = require('body-parser'), app = express(); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.listen(8989, () => console.log('Example app listening on port 8989!')); app.get('/', (req, res) => res.send('Hello World!'));
现在,如果您启动服务器并使用浏览器访问
http://127.0.0.1:8989
,则会看到一个包含服务器响应的页面
Hello World!
。
HTTPS和本地开发环境
在继续使用Webhook技术之前,我们需要为开发环境配置HTTPS。 如果您使用自签名SSL证书,则Messenger不会接受用于向我们的服务器发送通知的Webhook地址。 可以从
Let's Encrypt获得免费证书。 但是,在这里,您只能获得一个域的证书,而不能获得IP地址的证书。 我们将使用
ngrok服务,该服务将允许您通过使用HTTPS的公共URL来组织对本地服务器的访问。
Ngrok设置
ngrok
容易。 您只需要从项目站点下载压缩
存档 ,解压缩并运行以下命令:
./ngrok http 80
切记在路由器的WAN设置中将端口80重定向到8989。 结果,
ngrok
将为本地服务器创建公共HTTP和HTTPS地址。
使用Webhook通知
该Messenger使用Webhook技术进行身份验证并将有关事件的通知发送到您的应用程序。 从编程的角度来看,所有这些都归结为用于处理HTTP请求的常用回调函数,该HTTP请求将接收有关事件的数据,例如聊天机器人接收到的消息。 为了解析GET和POST请求,我们将使用
body-parser
模块。
将以下路由添加到应用程序。 处理Webhook验证请求是必需的。
// GET- webhook app.get('/webhook', (req, res) => { // . , let VERIFY_TOKEN = "SOMETHING_RANDOM"; // let mode = req.query['hub.mode']; let token = req.query['hub.verify_token']; let challenge = req.query['hub.challenge']; // , mode token if (mode && token) { // mode token if (mode === 'subscribe' && token === VERIFY_TOKEN) { // challenge console.log('WEBHOOK_VERIFIED'); res.status(200).send(challenge); } else { // '403 Forbidden' res.sendStatus(403); } } });
现在,您需要打开Messenger设置,在此处找到Webhooks部分,并使用Webhook通知配置应用程序集成。 在设置页面的“回调URL”字段中,输入从ngrok收到的我们的HTTPS URL。 验证令牌(代码中存在的一个令牌,代表我们创建的随机字符串)必须放在“验证令牌”字段中。 之后,如果您有用于处理Webhook通知的URL可用,并且验证令牌与代码中的一个相匹配,那么您应该能够通过单击“验证并保存”按钮来验证并保存设置。
配置应用程序的令牌和URL以接收Webhook通知保存后,从下拉列表中选择页面并订阅页面事件。
现在创建一个POST路由来处理来自Messenger的POST事件。 将以下代码添加到应用程序。
// webhook app.post('/webhook', (req, res) => { let body = req.body; if (body.object === 'page') { // , body.entry.forEach(function(entry) { // entry.messaging , // , 0 let webhook_event = entry.messaging[0]; console.log(webhook_event); // PSID let sender_psid = webhook_event.sender.id; console.log('Sender PSID: ' + sender_psid); // , , message postback, // - if (webhook_event.message) { console.log(webhook_event.message) } else if (webhook_event.postback) { console.log(webhook_event.postback) } }); // '200 OK' res.status(200).send('EVENT_RECEIVED'); } else { // '404 Not Found', , res.sendStatus(404); } });
我们将应用程序设置为可以处理两种类型的事件:
message
和
postback
。 为了检查Webhook通知机制的操作,请打开Messenger并将消息发送到bot页面。 如果一切正常,将记录发件人的PSID,事件信息和消息内容。 现在,我们将为我们感兴趣的事件编写处理程序函数。
// message const handleMessage = (sender_psid, received_message) => { let response; if (received_message.text) { } } // postback const handlePostback = (sender_psid, received_postback) => { let response; // postback let payload = received_postback.payload; if(payload === 'GET_STARTED'){ } }
handleMessage()
方法负责处理传入的消息,
handlePostback()
方法
handlePostback()
处理传入的
postback
事件。 通过添加对以下方法的调用来更新现有代码:
// // - if (webhook_event.message) { handleMessage(sender_psid, webhook_event.message); } else if (webhook_event.postback) { handlePostback(sender_psid, webhook_event.postback); }
现在,当我们接收到
message
或
postback
,数据将与发送者的PSID一起传输到相应的处理程序。
配置欢迎屏幕和回发事件以启动与机器人的对话
当新用户开始与漫游器进行对话时,聊天窗口中将显示“入门”按钮。 您可以针对这种情况配置自己的回发事件。 例如,为用户设置一条描述机器人以及如何与机器人通信的消息。 要配置自己的问候语,请在终端中运行以下
curl
命令:
curl -X POST -H "Content-Type: application/json" -d '{ "greeting": [ { "locale":"default", "text":"Hello {{user_first_name}}! Are you ready to see the cutests cats and dogs" } ] }' "https://graph.facebook.com/v2.6/me/messenger_profile?access_token=YOUR_PAGE_ACCESS_TOKEN"
我们设置了Aww Bot,以便它显示一条消息,询问用户是否准备好看最可爱的猫和狗。 为了配置回发事件,请在终端中执行以下命令:
curl -X POST -H "Content-Type: application/json" -d '{ "get_started": {"payload": "GET_STARTED"} }' "https://graph.facebook.com/v2.6/me/messenger_profile?access_token=YOUR_PAGE_ACCESS_TOKEN"
这是与机器人的聊天会话的样子。
入门屏幕应用设置
我们将使用npm配置模块将页面访问令牌存储在单独的配置文件中。 在我们的项目中创建
config
目录,并在其中创建
default.json
文件。 在此文件中,您需要将访问令牌添加到页面并将此文件记录在
.gitignore
。
{ "facebook": { "page": { "access_token": "PAGE_ACCESS_TOKEN" } } }
我们将使用
config.get('facebook.page.access_token')
命令在
callSendAPI()
方法中获取页面访问令牌。
处理开始事件
这是开始事件处理代码。
const handlePostback = (sender_psid, received_postback) => { let response;
让我们创建一个
askTemplate()
方法,该方法将为Messenger Messenger返回正确准备的响应对象。
callSendAPI()
方法将向用户发送一条消息。 将以下方法添加到应用程序:
const askTemplate = (text) => { return { "attachment":{ "type":"template", "payload":{ "template_type":"button", "text": text, "buttons":[ { "type":"postback", "title":"Cats", "payload":"CAT_PICS" }, { "type":"postback", "title":"Dogs", "payload":"DOG_PICS" } ] } } } } // API Send const callSendAPI = (sender_psid, response, cb = null) => { // let request_body = { "recipient": { "id": sender_psid }, "message": response }; // HTTP- Messenger Platform request({ "uri": "https://graph.facebook.com/v2.6/me/messages", "qs": { "access_token": config.get('facebook.page.access_token') }, "method": "POST", "json": request_body }, (err, res, body) => { if (!err) { if(cb){ cb(); } } else { console.error("Unable to send message:" + err); } }); }
我们向用户发送包含两个按钮和文本的消息。 当用户通过单击适当的按钮选择所需的内容时,会将请求与
postback
事件的数据一起发送到我们的Webhook地址,然后我们将对其进行处理。
提示用户选择他感兴趣的图像类型。处理自定义回发事件
更新回发事件处理程序功能代码:
const handlePostback = (sender_psid, received_postback) => { let response; // postback- let payload = received_postback.payload; // , if (payload === 'CAT_PICS') { response = imageTemplate('cats', sender_psid); callSendAPI(sender_psid, response, function(){ callSendAPI(sender_psid, askTemplate('Show me more')); }); } else if (payload === 'DOG_PICS') { response = imageTemplate('dogs', sender_psid); callSendAPI(sender_psid, response, function(){ callSendAPI(sender_psid, askTemplate('Show me more')); }); } else if(payload === 'GET_STARTED'){ response = askTemplate('Are you a Cat or Dog Person?'); callSendAPI(sender_psid, response); } // }
当用户单击“
Cats
按钮时,带有
postback
事件的请求(包含
CAT_PICS
数据)将被
CAT_PICS
到我们用于处理Webhook通知的地址。 选择“
Dogs
选项将发送带有
DOG_PICS
数据的
postback
事件。 我们向系统添加了另一个方法
imageTemplate()
,该方法返回一条消息,其中包含指向猫或狗的图像的链接。
创建一个简单的API,返回图像链接
我们将编写一个简单的API,以返回指向猫或狗图像的链接,这些链接将在机器人发送给用户的消息中使用。 创建一个
pics.js
文件,并添加以下代码:
module.exports = { cats : [ 'https://i.imgur.com/Qbg7CeM.jpg', 'https://i.imgur.com/nUzkpJY.jpg', 'https://i.imgur.com/NpDcKph.jpg', 'https://i.imgur.com/oJtSDaO.jpg', 'https://i.redd.it/82ajpsrd17111.jpg', 'https://i.redd.it/00km1d2rt0111.jpg', 'https://i.redd.it/rdbavhp0y7111.jpg', 'https://i.redd.it/5hn3mg0n98111.jpg', 'https://i.redd.it/d23pb8mta6111.jpg', 'https://i.redd.it/d2gyrwgy7oz01.jpg', 'https://i.redd.it/z4sgl84q72z01.jpg', 'https://i.redd.it/wvykzo8n1cy01.jpg' ], dogs : [ 'https://i.redd.it/6tjihi2qe7111.jpg', 'https://i.imgur.com/etRCs56.jpg', 'https://i.redd.it/nibw50f8y4111.jpg', 'https://i.redd.it/izcvnvj1o7111.jpg', 'https://i.redd.it/eqs1g9dldz011.jpg', 'https://i.redd.it/civ9dnu9u1111.jpg', 'https://i.redd.it/kk03qwclkp011.jpg', 'https://i.redd.it/2694pupjne011.jpg', 'https://i.redd.it/qk49ls5y6oy01.jpg', 'https://i.imgur.com/oM3mKgB.jpg', 'https://i.redd.it/8kx2riaulux01.jpg' ] };
现在将其连接到应用程序中。
images = require('./pics');
将以下方法添加到用于编写包含图像链接的消息的代码中。
const = imageTemplate(type, sender_id) => { return { "attachment":{ "type":"image", "payload":{ "url": getImage(type, sender_id), "is_reusable":true } } } }
在与机器人进行用户交互的过程中,图像从阵列中顺序提取,并作为机器人响应发送给用户。 发送完最后一张图像后,我们返回列表顶部。
我们将以下代码添加到项目中,旨在存储和处理有关与机器人通信的用户的数据。
let users = {}; const = getImage(type, sender_id) => { // - if(users[sender_id] === undefined){ users = Object.assign({ [sender_id] : { 'cats_count' : 0, 'dogs_count' : 0 } }, users); } let count = images[type].length, // user = users[sender_id], // , user_type_count = user[type+'_count']; // let updated_user = { [sender_id] : Object.assign(user, { [type+'_count'] : count === user_type_count + 1 ? 0 : user_type_count + 1 }) }; // users = Object.assign(users, updated_user); console.log(users); return images[type][user_type_count]; }
我们将与机器人通信的每个用户的PSID作为密钥存储在
users
对象中。 如果尚无用户记录,请创建一个新记录。 每次用户请求猫或狗的照片时,我们都会更新图像编号信息。 然后,我们将返回将在消息模板中使用的图像的绝对路径。 接下来,当用户选择感兴趣的图像类型时,我们以对
postback
事件的响应的形式发送带有图像的消息。
// , postback- if (payload === 'CAT_PICS') { response = imageTemplate('cats', sender_psid); callSendAPI(sender_psid, response, function(){ callSendAPI(sender_psid, askTemplate('Show me more')); }); } else if (payload === 'DOG_PICS') { response = imageTemplate('dogs', sender_psid); callSendAPI(sender_psid, response, function(){ callSendAPI(sender_psid, askTemplate('Show me more')); }); } else if(payload === 'GET_STARTED'){ response = askTemplate('Are you a Cat or Dog Person?'); callSendAPI(sender_psid, response); }
另外,在发送图像之后,我们将回调函数传递给
callSendAPI()
方法,以向用户发送有关他感兴趣的图像的新问题。 如果成功,我们将调用此函数。 考虑到回调函数的异步特性,该工作方案允许用户在收到带有下一个图像的消息后,收到带有下一个图像问题的消息。
与机器人通讯总结
这是该项目
的存储库。 在
readme.md
文件中,您可以找到有关安装和配置bot的说明。 为了让其他人与您的漫游器聊天,必须批准您的Facebook应用程序。 到目前为止,只有您的应用程序的管理员和测试人员才能与该机器人进行对话。
这是一个视频,演示了与机器人进行通信的过程。
亲爱的读者们! 您是否打算为Facebook Messenger创建机器人?
