O material, cuja tradução apresentamos hoje à sua atenção, é dedicado ao desenvolvimento de um bot de bate-papo para o Facebook Messenger. Um bot chamado Aww Bot, que se comunica com os usuários, envia fotos de gatos e cachorros fofos.

Introdução
Vamos começar criando uma página no
Facebook preenchendo os campos obrigatórios. Esta página é para o bot. Além disso,
criaremos um aplicativo do Facebook, após o qual, na página Adicionar um produto, conectaremos o produto Messenger ao aplicativo. Em seguida, nos encontraremos na página de configurações do messenger. Aqui você precisa encontrar a seção Geração de token - selecione a página do bot na lista Página. Depois disso, seremos questionados sobre permissões e um token de acesso será criado. O bot usará esse token para fazer chamadas para a API do Facebook Messenger, o que permitirá que ele se comunique com os usuários.
Configuração do servidor da Web
Usaremos node.js e express.js para criar um servidor HTTP. Execute o seguinte comando:
npm install express body-parser request config
Adicione o seguinte código ao
index.js
que permite criar um servidor HTTP simples:
'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!'));
Agora, se você iniciar o servidor e continuar usando o navegador em
http://127.0.0.1:8989
, verá uma página com a resposta do servidor -
Hello World!
.
HTTPS e o ambiente de desenvolvimento local
Antes de passar para a tecnologia Webhook, precisamos configurar o HTTPS para o ambiente de desenvolvimento. O messenger não aceitará o endereço Webhook usado para enviar notificações ao nosso servidor se você usar um certificado SSL autoassinado. Um certificado gratuito está disponível no
Let's Encrypt . Aqui, no entanto, você pode obter um certificado apenas para um domínio e não para um endereço IP. Usaremos o serviço
ngrok , que permitirá organizar o acesso ao servidor local por meio de uma URL pública que usa HTTPS.
Configuração do Ngrok
ngrok
fácil. Você só precisa baixar o
arquivo compactado do site do projeto, descompactá-lo e executar o seguinte comando:
./ngrok http 80
Lembre-se de redirecionar a porta 80 para 8989 nas configurações de WAN do seu roteador. Como resultado, o
ngrok
criará endereços HTTP e HTTPS públicos para o servidor local.
Trabalhando com notificações do Webhook
O messenger usa a tecnologia Webhook para autenticação e para enviar notificações sobre eventos ao seu aplicativo. Do ponto de vista da programação, tudo isso se resume às funções usuais de retorno de chamada para processar solicitações HTTP que receberão dados sobre eventos, como mensagens recebidas pelo chatbot. Para analisar solicitações GET e POST, usaremos o módulo
body-parser
.
Adicione a seguinte rota ao aplicativo. É necessário para processar solicitações de verificação do 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); } } });
Agora você precisa abrir as configurações do messenger, encontrar a seção Webhooks lá e configurar a integração do aplicativo com as notificações do Webhook. Na página de configurações, no campo URL de retorno de chamada, insira nosso URL HTTPS recebido do ngrok. O token de verificação (aquele que está presente no código e representa uma sequência aleatória que criamos) deve ser colocado no campo Verify Token. Depois disso, você poderá verificar e salvar as configurações clicando no botão Verificar e Salvar se o seu URL para processar notificações do Webhook estiver disponível e o token de verificação corresponder ao do código.
Configure o token e o URL para o aplicativo receber notificações do WebhookApós salvar, selecione sua página na lista suspensa e assine os eventos da página.
Agora crie uma rota POST para manipular eventos POST do messenger. Adicione o seguinte código ao aplicativo.
// 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); } });
Configuramos o aplicativo para que ele lide com dois tipos de eventos -
message
e
postback
. Para verificar o funcionamento do mecanismo de notificação do Webhook, abra o messenger e envie uma mensagem para a página bot. Se tudo funcionar como deveria, o PSID do remetente, as informações do evento e o conteúdo da mensagem serão registrados. Agora vamos escrever funções de manipulador para os eventos de seu interesse.
// 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'){ } }
O método
handleMessage()
é responsável pelo processamento de mensagens recebidas e o método
handlePostback()
é
handlePostback()
pelo processamento de eventos de
postback
recebidos. Atualize seu código existente adicionando chamadas a estes métodos:
// // - if (webhook_event.message) { handleMessage(sender_psid, webhook_event.message); } else if (webhook_event.postback) { handlePostback(sender_psid, webhook_event.postback); }
Agora, quando recebermos
postback
message
ou
postback
, os dados serão transmitidos para os manipuladores correspondentes, juntamente com o PSID do remetente.
Configurando a tela de boas-vindas e os eventos de postagem para iniciar um diálogo com o bot
Quando um novo usuário inicia uma conversa com o bot, o botão Introdução é exibido na janela de bate-papo. Você pode configurar seu próprio evento de postagem para esta situação. Por exemplo, defina uma mensagem para um usuário que descreva o bot e como se comunicar com ele. Para configurar sua própria saudação, execute este comando
curl
no terminal:
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"
Montamos o Aww Bot para exibir uma mensagem perguntando ao usuário se ele está pronto para ver os cães e gatos mais fofos. Para configurar o evento de postagem, execute este comando no terminal:
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"
Aqui está a aparência da sessão de bate-papo com o bot.
Tela de introduçãoConfiguração do aplicativo
Usaremos o módulo de configuração npm para armazenar o token de acesso à página em um arquivo de configuração separado. Crie o diretório
config
em nosso projeto e o arquivo
default.json
nele. Nesse arquivo, você precisa adicionar o token de acesso à página e registrar esse arquivo em
.gitignore
.
{ "facebook": { "page": { "access_token": "PAGE_ACCESS_TOKEN" } } }
callSendAPI()
o token de acesso à página no método
callSendAPI()
usando o comando
config.get('facebook.page.access_token')
.
Manipulando um Evento Inicial
Aqui está o código de manipulação de eventos de início.
const handlePostback = (sender_psid, received_postback) => { let response;
Vamos criar o método
askTemplate()
, que retornará um objeto de resposta preparado corretamente para a API do messenger. O método
callSendAPI()
enviará uma mensagem ao usuário. Adicione os seguintes métodos ao aplicativo:
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); } }); }
Enviamos ao usuário uma mensagem contendo dois botões e texto. Quando o usuário seleciona o que ele precisa clicando no botão apropriado, uma solicitação será enviada ao nosso endereço Webhook com os dados do evento de
postback
e nós a processaremos.
O usuário é solicitado a selecionar o tipo de imagem que lhe interessa.Manipulação de eventos de postagem personalizados
Atualize o código da função do manipulador de eventos de postagem:
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); } // }
Quando o usuário clica no botão
Cats
, uma solicitação com um evento de
postback
com dados
CAT_PICS
será
CAT_PICS
ao nosso endereço usado para processar as notificações do Webhook. A escolha da opção
Dogs
enviará um evento de
postback
com dados
DOG_PICS
. Adicionamos outro método ao sistema,
imageTemplate()
, que retorna uma mensagem contendo um link para a imagem de um gato ou cachorro.
Crie uma API simples que retorne links de imagem
Escreveremos uma API simples para retornar links para imagens de gatos ou cães que serão usados em mensagens enviadas pelo bot aos usuários. Crie um arquivo
pics.js
e adicione o seguinte código:
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' ] };
Agora conecte-o no aplicativo.
images = require('./pics');
Adicione o seguinte método ao código usado para compor uma mensagem contendo um link para a imagem.
const = imageTemplate(type, sender_id) => { return { "attachment":{ "type":"image", "payload":{ "url": getImage(type, sender_id), "is_reusable":true } } } }
No processo de interação do usuário com o bot, as imagens são extraídas seqüencialmente da matriz e enviadas como respostas do bot ao usuário. Depois de enviar a última imagem, retornamos ao topo da lista.
Adicionamos o código a seguir ao projeto, projetado para armazenar e processar dados sobre usuários que se comunicam com o bot.
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]; }
Armazenamos o PSID de cada usuário que se comunica com o bot como uma chave no objeto de
users
. Se ainda não houver um registro do usuário, crie um novo registro. Atualizaremos as informações do número da imagem sempre que um usuário solicitar uma foto de um gato ou cachorro. Em seguida, retornamos o caminho absoluto para a imagem que será usada no modelo de mensagem. Em seguida, enviamos uma mensagem com a imagem na forma de uma resposta ao evento de
postback
gerado quando o usuário seleciona o tipo de imagem que lhe interessa.
// , 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); }
Além disso, após enviar a imagem, passamos uma função de retorno de chamada para o método
callSendAPI()
para enviar ao usuário uma nova pergunta sobre em quais imagens ele está interessado. Se for bem-sucedido, chamamos essa função. Esse esquema de trabalho, levando em consideração a natureza assíncrona das funções de retorno de chamada, permite que o usuário receba uma mensagem com uma pergunta sobre a próxima imagem depois que uma mensagem lhe foi enviada com a imagem solicitada anteriormente.
Comunicação com o botSumário
Aqui está o repositório para este projeto. Lá, no arquivo
readme.md
, você encontra instruções para instalar e configurar o bot. Para que outras pessoas conversem com seu bot, seu aplicativo do Facebook deve ser aprovado. Até esse ponto, apenas administradores e testadores do seu aplicativo poderão conversar com o bot.
Aqui está um vídeo demonstrando o processo de comunicação com o bot.
Caros leitores! Você está planejando criar bots para o Facebook Messenger?
