Creación bots de Whatsapp en Node.JS

Repositorio con fuente bot

Introduccion

Ahora, vamos a explicar cómo crear un bot en WhatsApp Node JS usando una puerta de enlace de API de WhatsApp.

El bot responderá a los comandos que recibe como mensajes normales de WhatsApp y responderá a ellos. En nuestro ejemplo, intentaremos cubrir las características más utilizadas y necesarias en el desarrollo:

  • Capacidad de reaccionar y responder al comando
  • Muestra la ID de chat actual (en el mensaje privado o en la conversación)
  • Muestra el nombre de quién se comunica con el bot
  • Envío de archivos de varios formatos (pdf, jpg, doc, mp3, etc.)
  • Envío de mensajes de voz (archivos *.ogg)
  • Envío de geolocalización (coordenadas - latitud y longitud)
  • Creación de una conferencia (grupo) con un bot

Atención: todo el sistema funciona a través de WhatsApp Web, respectivamente, su teléfono siempre debe estar conectado a Internet

1 Paso. Preparación

Un poco de teoría

Autorización de Whatsapp mediante código QR

Al principio, conectemos whatsapp con nuestro script de inmediato para verificar su funcionamiento mientras escribimos el código. Para hacer esto, vamos a una cuenta personal y obtenemos un código QR allí. Luego abra WhatsApp en su teléfono móvil, vaya a Configuración -> WhatsApp Web -> Escanear código QR.

Las capacidades del servicio Chat-Api nos permitirán instalar un Webhook que transmitirá información sobre nuevos mensajes (y no solo) a su servidor web. Para que el servidor llame a nuestro script en los nuevos mensajes, es necesario especificar la URL de WebHook. WebHook URL es un enlace donde se enviará por método POST, datos JSON con información sobre mensajes entrantes o notificaciones. En consecuencia, para que el bot funcione, necesitamos un servidor, que recibirá y procesará estos datos.

Implementaremos un servidor web en su computadora/VPS/VDS (en adelante, Host), respectivamente, será necesario especificarlo en su cuenta personal. Por lo tanto, en la configuración de la cuenta, especificamos la dirección de WebHook'a; en mi caso, es https://subdomain.domain.com/webhook. En su caso, si usa un dominio separado, se verá más o menos así: https://domain.com/webhook.

Haga clic en "Guardar". Bien, ahora todas las notificaciones de mensajes nuevos llegarán a nuestra dirección, sólo tienes que procesarlos.

Obtenga acceso gratuito a la API de WhatsApp

2.1 paso. Implementar un bot en su dispositivo.

Recomendamos comenzar con la clonación de nuestro repositorio Git seguido de un cambio personalizado.

Entonces, cree la carpeta WhatsAppBot, clone o git (o descárguelo) en sus archivos desde el repositorio. En primer lugar, instalaremos las dependencias necesarias para nuestro bot utilizando el comando npm install, un conjunto de bibliotecas a través del cual trabajará.

Luego, vaya a la configuración (archivo config.js) y especifique entre comillas su dirección url para solicitudes y token (puede tomarlos en su cuenta personal). Así es como su cede:

                        module.exports = {
    // API reference URL
    apiUrl: "https://eu14.chat-api.com/instance12345/",
    // API token from your personal account
    token: "xb1s668fphzmr9m"
}
                    

Guardamos el archivo y escribimos en el terminal del node index.js - Con este comando, iniciaremos el servidor web para procesar las solicitudes. Si hiciste todo bien, el bot funcionará.

2.2 Paso. Desarrollar un bot desde cero

Si decide escribir un bot desde cero, ahora le diremos cómo hacerlo.

Dejamos la descripción de la instalación de Node.JS y NPM (suponiendo que ya esté familiarizado con esto, solo lea esta guía).

Entonces, creamos la carpeta WhatsAppBot, la ingresamos y abrimos la terminal. Comenzamos el proyecto con el comando npm init, completamos los datos o simplemente presionamos Enter varias veces hasta que aparezca Is this OK? (yes).

Luego, creamos nuestro archivo principal - index.js. Contendrá toda la lógica básica del bot. También creamos config.js, allí colocaremos los parámetros principales, que pueden ser dinámicos (para no ingresar el archivo principal para corregirlos).

Abrimos config.js y agregamos dos parámetros: apiUrl y token:

                        module.exports = {
    apiUrl: "",
    token: ""
}
                    

No olvide la primera línea, module.exports, que le permitirá trabajar con estos datos desde otro archivo. Podemos completar de inmediato los datos para la configuración con los datos de su cuenta personal. Guardar y cerrar.

Utilizaremos las siguientes dependencias (requirements):

Abrimos index.js y comenzamos a crear un bot con un requisito de dependencia:

                        const config = require("./config.js");
const token = config.token, apiUrl = config.apiUrl;
const app = require('express')();
const bodyParser = require('body-parser');
const fetch = require('node-fetch');
                    

En detalle: node-fetch permite realizar solicitudes de API, config cargará nuestros datos desde otro archivo, colocaremos inmediatamente los datos de configuración en las variables token y apiUrl (para facilitar el acceso a ellos). El módulo Express es necesario para implementar el servidor web y Un body-parser le permite recuperar convenientemente el flujo de solicitudes recibidas.

A continuación, le explicaremos a nuestro parser (analizador) que trabajaremos con datos JSON:

                        app.use(bodyParser.json());
                    

Por cierto, para saber cómo se verá el JSON recibido, puede ir a una sección de prueba fácil de usar, que proporcionamos en la cuenta personal. Aquí puede probar las solicitudes y Webhook.

Como precaución, hemos suspendido el controlador de errores completo que puede generar prequest durante el proceso de solicitud:

                        process.on('unhandledRejection', err => {
    console.log(err)
});
                    

Y ahora vamos a comenzar a escribir el código principal.

Para verificar el dominio estacionado en el Host, procesaremos la página principal (una especie de index.html) con el siguiente bloque:

                        app.get('/', function (req, res) {
    res.send("It's working");
}); 
                    

En pocas palabras, esto le permitirá comprobar el rendimiento de nuestro sitio, después de que se inicie el proyecto, cuando cambie a yoursite.com,si todo se hace correctamente, verá la inscripción “It's working". Ahora, escribiremos una función para comunicarnos con nuestra API.

                        async function apiChatApi(method, params){
    const options = {};
    options['method'] = "POST";
    options['body'] = JSON.stringify(params);
    options['headers'] = { 'Content-Type': 'application/json' };
    
    const url = `${apiUrl}/${method}?token=${token}`; 
    
    const apiResponse = await fetch(url, options);
    const jsonResponse = await apiResponse.json();
    return jsonResponse;
}
                    

Analizaremos con más detalle: creamos la función asincrónica apiChatApi, que acepta dos parámetros: el método al que queremos acceder y el objeto de parámetro con el que accedemos a este método. Bueno, para ser sincero, queremos enviar un mensaje: accedemos al método message y transferimos el texto del mensaje y el destinatario en el objeto.

Dentro de la función, creamos el objeto de opciones, que reponemos inmediatamente con dos claves: json e method. En el primero, pasamos los parámetros necesarios a la API y, en el segundo, indicamos el método que accedemos y en el que queremos obtener la respuesta.

Luego declaramos una constante: nuestra dirección url para acceder a la API. En resumen, contendrá la propia url (de la configuración), el método y token transmitidos por la solicitud GET.

Después de eso, enviamos la solicitud y escribimos la respuesta en apiResponse, que devolvemos (en el bot más simple, por cierto, el retorno de la respuesta de la función, en principio, no será necesario, excepto para detectar errores)

La función de comunicación con la API está listo. Es hora de comenzar a escribir la lógica del bot.

Elegimos, ya que se llamará a nuestra página para su procesamiento. En mi caso, es un webhook (es decir, el webhook enviará solicitudes a http://domain.com/webhook). Escribimos este controlador de url:

                        app.post('/webhook', async function (req, res) {

});
                    

Dentro del manipulador, escribimos todo lo que obtenemos en la variable data:

                        app.post('/webhook', async function (req, res) {
    const data = req.body;

});
                    

Y la ejecutemos a través de un bucle for para analizar todos los mensajes:

                        app.post('/webhook', async function (req, res) {
    const data = req.body;
    for (var i in data.messages) {

    }
});
                    

Ahora, escribiremos la información sobre el mensaje recibido en variables y también aislaremos inmediatamente la información sobre los mensajes enviados:

                        app.post('/webhook', async function (req, res) {
    const data = req.body;
    for (var i in data.messages) {
        const author = data.messages[i].author;
        const body = data.messages[i].body;
        const chatId = data.messages[i].chatId;
        const senderName = data.messages[i].senderName;

        if(data.messages[i].fromMe)return;
    }
});
                    

Por lo tanto, en el author, ahora tenemos información sobre el autor del mensaje, body contiene el texto, chatId es el Id de chat actual y senderName recibió el nombre de la persona que nos está hablando.

No olvide agregar el código para iniciar el servidor web al final del archivo:

                        app.listen(80, function () {
    console.log('Listening on port 80..');
});
                    

Y ahora podemos probar el rendimiento del bot escribiendo el siguiente código en un bucle for después de las variables declaradas:

                        console.log(senderName, author, chatId, body);
                    

Inicie el bot con el comando node index.js y escriba el mensaje bot: Test. Si todo está correcto, en la consola, veremos: Eugene 79123456789@c.us 79123456789@c.us Test

Si todo funciona, sigue adelante. Eliminamos (o comentamos) la línea de depuración con console.log y pensamos en cómo procesar los comandos.

En realidad, hay varias opciones, pero recomendamos la construcción if else if junto con expresiones regulares: esto permitirá, en primer lugar, crear comandos complejos con argumentos y, en segundo lugar, no preocuparse por la repetición de variables (como sería en el caso de switch-case), y en tercer lugar, es muy fácil verificar el comando ingresado incorrectamente (cierre else) y enviar el mensaje correspondiente.

A continuación, examinaremos el código incorporado en el for, no se confundan 😉

Entonces empezaremos editando la estructura de mando:

                        if(/help/.test(body)) {
    // This section will work when the user enters "help"
    } else if(/chatId/.test(body)) {
    // This section will work when the user enters "chatId"
    } else if(/file (pdf|jpg|doc|mp3)/.test(body)) {
    // This section will work when the user enters "file pdf, file jpg, etc"
    } else if(/ptt/.test(body)) {            
    // This section will work when the user enters "ptt"
    } else if(/geo/.test(body)) {
    // This section will work when the user enters "geo"
    } else if(/group/.test(body)) {
    // This section will work when the user enters "group"
}
                    

Bueno, ahora, de hecho, escribiremos manejadores de comandos. Vamos a empezar con help: aquí todo es fácil:

                        const text = `${senderName}, this is a demo bot for https://chat-api.com/.
Commands:
1. chatId - view the current chat ID
2. file [pdf/jpg/doc/mp3] - get a file
3. ptt - get a voice message
4. geo - get a location
5. group - create a group with you and the bot`;
await apiChatApi('message', {chatId: chatId, body: text});
                    

Aquí todo está claro: en la variable text, escribiremos un texto prepreparado, colocaremos en él la variable senderName, que contiene el nombre del usuario que escribió el bot.

Bueno, la última línea es una llamada a nuestra función para trabajar con la API, en la cual pasamos un método - 'message' y un objeto con parámetros - {chatId: chatId, body: text}.

Podemos ejecutar nuestro proyecto con el comando node index.js y escribir en el bot help.

Por cierto, le recomendamos que envíe un texto con todos los comandos para cualquier comando no escrito al bot, por ejemplo, si una persona escribe "¡Hola!" Para el bot, aunque no hemos colocado este comando. Entonces ese mensaje inicial estará a la vista del usuario todo el tiempo.

Ahora escribamos un controlador para el comando chatId. En principio, todo aquí también es simple:

                        await apiChatApi('message', {chatId: chatId, body: chatId});
                    

Accedemos a la API, al método message y la solicitud de envío al chat, chatld texto chatld

whatsapp api

Es muy simple, ¿estás de acuerdo? Continuamos En nuestro camino, la parte más difícil del código es la funcionalidad del comando file.

Para comenzar, echemos un vistazo más de cerca al texto:

                        /file (pdf|jpg|doc|mp3)/.test(body)
                    

Describiré brevemente su lógica: verificamos si body es igual al file + uno de los valores entre paréntesis. Por ejemplo, body es igual al valor del file pdf o al valor del file jpg, y así sucesivamente.

Si es lo mismo, ejecutamos nuestro controlador, que primero, usando la función de coincidencia, calcula el tipo de archivo que se enviará a la variable fileType:

                        const fileType = body.match(/file (pdf|jpg|doc|mp3)/)[1];
                    

Es decir, en fileType, ahora tenemos el valor pdf/jpg/doc/mp3. Ahora vamos a crear el objeto con los datos que deben enviarse:

                        const files = {
     doc: "https://domain.com/tra.docx",
     jpg: "https://domain.com/tra.jpg",
     mp3: "https://domain.com/tra.mp3",
     pdf: "https://domain.com/tra.pdf"
};
                    

Respectivamente, nos permitirá obtener la url del archivo accediendo a ella a través del índice clave, por ejemplo:

                        files["doc"] // => "https://domain.com/tra.docx"
files["mp3"] // => "https://domain.com/tra.mp3"
                    

Por lo tanto, files[fileType] proporcionarán la url del archivo que necesitamos.

Lo único que queda es crear un objeto de parámetro que necesitemos pasar a la API:

                        var dataFile = {
     phone: author,
     body: files[fileType],
     filename: `File *.${fileType}`            
};
                    

En phone, transferimos al autor del mensaje, en body un enlace al archivo (ver en la API), y en el filename ponemos el nombre visible del archivo (como ejemplo, pongo la palabra "Archivo" y su extensión).

Escribimos una pequeña construcción que agregará la clave "caption" (la línea inferior del texto debajo de la figura) por si acaso, si la solicitud es para una imagen:

                        if (fileType == "jpg") dataFile['caption'] = "Photo text";
                    

En resumen, pasamos todo esto a nuestra función, lo que indica que queremos llamar al método sendFile:

                        await apiChatApi('sendFile', dataFile);
                    

Ahora, hemos implementado el controlador de comando ptt - mensajes de voz.

                        await apiChatApi('sendAudio', {audio: "https://domain.com/tra.ogg", chatId: chatId});
                    

Accedemos a nuestra función pasando el método sendAudio y la clave audio con un enlace directo al archivo en el objeto de parámetro.

Sending audio bot Whatsapp

En este artículo, los enlaces a los archivos son estáticos (en referencia al alojamiento). Le recomendamos que transfiera archivos en el formato base64.

El controlador para el comando geo también es muy simple:

                        await apiChatApi('sendLocation', {lat: 51.178843, lng: -1.826210, address: 'Stonehenge', chatId: chatId});
                    

En lugar de audio, pasamos las claves lat y lng - la latitud y longitud del espacio requerido, respectivamente. En la clave "address", pasamos el nombre. Las propias coordenadas se pueden obtener, por ejemplo, en Google Maps.

Se convirtió en un comando grupo, creando un grupo de bot con una persona. Su manipulador es casi el mismo que varios anteriores:

                        let arrayPhones = [ author.replace("@c.us","") ];

await apiChatApi('group', {groupName: 'Group with a bot', phones: arrayPhones, messageText: 'Welcome to the new group!'});
                    

Creamos una matriz arrayPhones, en la que colocamos al autor de inmediato, eliminando @c.us en su línea, dejando solo el número.

Construyendo bots de WhatsApp en Node JS

Podemos colocar varios números al mismo tiempo, y ejecutamos la solicitud de la función utilizando el método de grupo, pasando las teclas groupName - el nombre de la conversación, la matriz de usuario en phones y el texto de bienvenida en messageText..

De hecho, esto completa el desarrollo de los manipuladores.

Todo lo que necesita hacer es configurar su token desde su cuenta personal y número de instance.

Obtener clave API


Whatsapp bot en Node.JS

Ahora necesita cargar nuestro servidor con el bot en hosting y, como webhook, especifique su dominio. En cada mensaje entrante al servidor vendrá y procesará datos.

El código estará disponible a través de un enlace a Github: https://github.com/chatapi/whatsapp-nodejs-bot-en