Desarrollo de Chatbot para Facebook Messenger en node.js

El material, cuya traducción presentamos hoy a su atención, está dedicado al desarrollo de un bot de chat para Facebook Messenger. Un bot llamado Aww Bot, que se comunica con los usuarios, les enviará fotos de lindos gatos y perros.



Empezando


Comencemos creando una página en Facebook completando los campos obligatorios. Esta página es para el bot. Además, crearemos una aplicación de Facebook, luego de lo cual, en la página Agregar un producto, conectaremos el producto Messenger a la aplicación. A continuación, nos encontraremos en la página de configuración de messenger. Aquí debe encontrar la sección Generación de tokens, en ella: seleccione la página bot en la lista de páginas. Después de eso, se nos preguntará sobre los permisos y se creará un token de acceso. El bot usará este token para hacer llamadas a la API de Facebook Messenger, lo que le permitirá comunicarse con los usuarios.

Configuración del servidor web


Utilizaremos node.js y express.js para crear un servidor HTTP. Ejecute el siguiente comando:

npm install express body-parser request config --save 

Agregue el siguiente código a index.js que le permite crear un servidor HTTP simple:

 '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!')); 

Ahora, si inicia el servidor y se va, usando su navegador, en http://127.0.0.1:8989 , verá una página con la respuesta del servidor: Hello World! .

HTTPS y el entorno de desarrollo local.


Antes de pasar a la tecnología Webhook, necesitamos configurar HTTPS para el entorno de desarrollo. El mensajero no aceptará la dirección de Webhook utilizada para enviar notificaciones a nuestro servidor si utiliza un certificado SSL autofirmado. Hay un certificado gratuito disponible de Let's Encrypt . Aquí, sin embargo, puede obtener un certificado solo para un dominio, y no para una dirección IP. Utilizaremos el servicio ngrok , que le permitirá organizar el acceso al servidor local a través de una URL pública que utiliza HTTPS.

Configuración de Ngrok


ngrok fácil. Solo necesita descargar el archivo comprimido del sitio del proyecto, descomprimirlo y ejecutar el siguiente comando:

 ./ngrok http 80 

Recuerde redirigir el puerto 80 al 8989 en la configuración WAN de su enrutador. Como resultado, ngrok creará direcciones públicas HTTP y HTTPS para el servidor local.

Trabajar con notificaciones de Webhook


El messenger utiliza la tecnología Webhook para la autenticación y para enviar notificaciones sobre eventos a su aplicación. Desde el punto de vista de la programación, todo esto se reduce a las funciones habituales de devolución de llamada para procesar solicitudes HTTP que recibirán datos sobre eventos, como mensajes recibidos por el chatbot. Para analizar las solicitudes GET y POST, utilizaremos el módulo body-parser .

Agregue la siguiente ruta a la aplicación. Es necesario para procesar solicitudes de verificación de 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);       }   } }); 

Ahora necesita abrir la configuración de Messenger, encontrar la sección Webhooks allí y configurar la integración de la aplicación con notificaciones Webhook. En la página de configuración, en el campo URL de devolución de llamada, ingrese nuestra URL HTTPS recibida de ngrok. El token de verificación (el que está presente en el código y representa una cadena aleatoria que creamos) debe colocarse en el campo Verificar token. Después de eso, debería poder verificar y guardar la configuración haciendo clic en el botón Verificar y guardar si su URL para procesar notificaciones de Webhook está disponible y el token de verificación coincide con el del código.


Configure el token y la URL para que la aplicación reciba notificaciones de Webhook

Después de guardar, seleccione su página de la lista desplegable y suscríbase a los eventos de la página.

Ahora cree una ruta POST para manejar eventos POST desde el messenger. Agregue el siguiente código a la aplicación.

 //     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 la aplicación para que maneje dos tipos de eventos: message y postback . Para verificar el funcionamiento del mecanismo de notificación de Webhook, abra el messenger y envíe un mensaje a la página del bot. Si todo funciona como debería, se registrará el PSID del remitente, la información del evento y el contenido del mensaje. Ahora escribiremos funciones de controlador para los eventos que nos interesen.

 //   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'){   } } 

El método handleMessage() es responsable de procesar los mensajes entrantes y el método handlePostback() es handlePostback() de procesar los eventos de postback de datos entrantes. Actualice su código existente agregando llamadas a estos métodos:

 //   //     - if (webhook_event.message) {   handleMessage(sender_psid, webhook_event.message); } else if (webhook_event.postback) {   handlePostback(sender_psid, webhook_event.postback); } 

Ahora, cuando recibamos message o postback datos, los datos se transmitirán a los controladores correspondientes junto con el PSID del remitente.

Configurar la pantalla de bienvenida y los eventos de devolución para iniciar un diálogo con el bot


Cuando un nuevo usuario inicia una conversación con el bot, se muestra el botón Comenzar en la ventana de chat. Puede configurar su propio evento de devolución de datos para esta situación. Por ejemplo, configure un mensaje para un usuario que describa el bot y cómo comunicarse con él. Para configurar su propio saludo, ejecute este comando curl en la 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" 

Configuramos Aww Bot para que muestre un mensaje preguntándole al usuario si está listo para ver los gatos y perros más lindos. Para configurar el evento de devolución de datos, ejecute este comando en la 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" 

Así es como se ve la sesión de chat con el bot.


Pantalla de inicio

Configuración de la aplicación


Utilizaremos el módulo de configuración npm para almacenar el token de acceso a la página en un archivo de configuración separado. Cree el directorio de config en nuestro proyecto y el archivo default.json en él. En este archivo, debe agregar el token de acceso a la página y registrar este archivo en .gitignore .

 { "facebook": {   "page": {     "access_token": "PAGE_ACCESS_TOKEN"   } } } 

callSendAPI() el token de acceso a la página en el método callSendAPI() usando el config.get('facebook.page.access_token') .

Manejo de un evento de inicio


Aquí está el código de manejo del evento de inicio.

 const handlePostback = (sender_psid, received_postback) => {   let response;   //   postback-   let payload = received_postback.payload;   if(payload === 'GET_STARTED'){       response = askTemplate('Are you a Cat or Dog Person?');       callSendAPI(sender_psid, response);   } } 

askTemplate() método askTemplate() , que devolverá un objeto de respuesta preparado correctamente para la API de messenger. El método callSendAPI() enviará un mensaje al usuario. Agregue los siguientes métodos a la aplicación:

 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 al usuario un mensaje que contiene dos botones y texto. Cuando el usuario selecciona lo que necesita haciendo clic en el botón correspondiente, se enviará una solicitud a nuestra dirección de Webhook con los datos del evento de postback y lo procesaremos.


Se le solicita al usuario que seleccione el tipo de imagen que le interesa.

Manejo de eventos de devolución personalizados


Actualice el código de función del controlador de eventos de devolución de datos:

 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);   }   //   } 

Cuando el usuario hace clic en el botón Cats , se CAT_PICS una solicitud con un evento de postback que contiene datos de CAT_PICS a nuestra dirección utilizada para procesar las notificaciones de Webhook. Al elegir la opción Dogs , se enviará un evento de postback datos con datos DOG_PICS . imageTemplate() otro método al sistema, imageTemplate() , que devuelve un mensaje que contiene un enlace a una imagen de un gato o un perro.

Cree una API simple que devuelva enlaces de imágenes


Escribiremos una API simple para devolver enlaces a imágenes de gatos o perros que se utilizarán en los mensajes enviados por el bot a los usuarios. Cree un archivo pics.js y agregue el siguiente 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'   ] }; 

Ahora conéctelo en la aplicación.

 images = require('./pics'); 

Agregue el siguiente método al código utilizado para redactar un mensaje que contenga un enlace a la imagen.

 const = imageTemplate(type, sender_id) => {   return {       "attachment":{           "type":"image",           "payload":{               "url": getImage(type, sender_id),               "is_reusable":true           }       }   } } 

En el proceso de interacción del usuario con el bot, las imágenes se extraen secuencialmente de la matriz y se envían como respuestas del bot al usuario. Después de enviar la última imagen, volvemos a la parte superior de la lista.

Agregamos el siguiente código al proyecto, diseñado para almacenar y procesar datos sobre los usuarios que se comunican con el 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]; } 

Almacenamos el PSID de cada uno de los usuarios que se comunican con el bot como una clave en el objeto de los users . Si todavía no hay un registro de usuario, cree un nuevo registro. Actualizaremos la información del número de imagen cada vez que un usuario solicite una foto de un gato o un perro. Luego devolvemos la ruta absoluta a la imagen que se utilizará en la plantilla de mensaje. A continuación, enviamos un mensaje con la imagen en forma de respuesta al evento de postback generado cuando el usuario selecciona el tipo de imagen que le interesa.

 //  ,    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); } 

Además, después de enviar la imagen, pasamos una función de devolución de llamada al método callSendAPI() para enviar al usuario una nueva pregunta sobre qué imágenes le interesan. Si tiene éxito, llamamos a esta función. Este esquema de trabajo, teniendo en cuenta la naturaleza asincrónica de las funciones de devolución de llamada, permite al usuario recibir un mensaje con una pregunta sobre la siguiente imagen después de que se le haya enviado un mensaje con la imagen solicitada anteriormente.


Comunicación con el bot

Resumen


Aquí está el repositorio para este proyecto. Allí, en el archivo readme.md , puede encontrar instrucciones para instalar y configurar el bot. Para que otras personas puedan chatear con su bot, su aplicación de Facebook debe ser aprobada. Hasta este punto, solo los administradores y evaluadores de su aplicación podrán hablar con el bot. Aquí hay un video que muestra el proceso de comunicación con el bot.

Estimados lectores! ¿Estás planeando crear bots para Facebook Messenger?

Source: https://habr.com/ru/post/es414081/


All Articles