Cómo enviar mensajes de WhatsApp desde Google Sheets con JavaScript y Node.js

September 14, 2019
Redactado por
Alex Baban
Colaborador
Las opiniones expresadas por los colaboradores de Twilio son propias.

Cómo enviar mensajes de WhatsApp desde Google Sheets con JavaScript y Node.js

Con Google Sheets (app de planillas en línea de Google), puede colaborar fácilmente en tiempo real con compañeros de trabajo, clientes u otras personas. La estructura y la simplicidad de mantener los datos en filas y columnas ofrecen muchos beneficios.

WhatsApp es una app popular para teléfonos inteligentes que ofrece un reemplazo de los sistemas tradicionales de mensajería de texto. Le permite enviar mensajes a otra persona que también utilice WhatsApp. Puede enviar mensajes de texto simples y también puede enviar archivos adjuntos con imágenes, grabaciones de audio o grabaciones de video.

En esta publicación, aprenderá a crear una aplicación Node.js que se puede utilizar para enviar mensajes de WhatsApp a varios destinatarios. Utiliza una planilla de Google Sheets como la fuente de datos para los contactos y API de Twilio para WhatsApp para enviar los mensajes.

Vamos a adoptar un enfoque iterativo para desarrollar esta aplicación. Comience con un nombre, llámelo “Remitente de un mensaje”.

Lo que necesitará

Google Sheets como fuente de datos

Utilice un navegador web y vaya a https://drive.google.com (inicie sesión si es necesario).

Una vez que haya iniciado sesión en su cuenta de Google, cree una nueva planilla en blanco de “Google Sheets” haciendo clic en el botón “+ New” (+ Nueva) en la parte superior izquierda. Puede nombrar su planilla como desee, porque va a acceder a ella con su ID y no con su nombre, pero por ahora cámbielo a “Citas”. La nueva planilla viene con una hoja de cálculo predeterminada con el nombre “Hoja1” (este nombre importa; la utilizará más tarde para referirse a esta hoja de cálculo específica).

Usaremos la primera fila como encabezado de las columnas y nombraremos las primeras cuatro columnas como “cita_fecha”, “cita_hora”, “nombre_cliente” y “número_teléfono”.

Complete las tres primeras filas con datos para la fecha y hora de la cita, el nombre del cliente y el número de teléfono de WhatsApp del cliente (para propósitos de prueba, uno o todos los números pueden ser su número).

Al introducir el número de teléfono, para poder introducir el signo +, es necesario prepararlo con un apóstrofo (o comillas simples) de este modo: '+17775553333.

Aquí hay una captura de pantalla de la planilla, “Citas”, “Hoja1”:

Google Sheets con las columnas apropiadas para este proyecto

Otra cosa que debe hacer aquí es encontrar el ID de la planilla. Este ID se utilizará en su código y es el valor entre “/d/” y “/edit” en la URL de su planilla.

Por ejemplo, si la URL es:

https://docs.google.com/spreadsheets/d/3-bOVJ58P9_-M_dwB37LYWy5h88EvekWBr6KzflVVTbw/edit#gid=0

Entonces el ID de la planilla es:

3-bOVJ58P9_-M_dwB37LYWy5h88EvekWBr6KzflVVTbw

La planilla ya está lista para su uso como nuestra fuente de datos. A continuación, comience a escribir el código Node.js para su aplicación. Puede utilizar su editor de texto favorito o Visual Studio Code.

Lectura de datos de Google Sheets desde Node.js

Su aplicación no funcionará todavía, no podrá conectarse a la planilla, pero le aseguro que solucionará este problema a medida que continúe con el tutorial.

Cree una nueva carpeta llamada remitente-de-un-mensaje para nuestra aplicación (puede hacerlo con su editor de texto favorito o ejecutando mkdir remitente-de-un-mensaje en una ventana terminal).

Cree un nuevo archivo index.js dentro de remitente-de-un-mensaje (puede hacerlo con su editor de texto favorito o ejecutando touch index.js en una ventana de terminal. Si está en Windows y touch no está disponible, puede ejecutar echo > index.js en el terminal).

Agregue el siguiente código inicial para index.js:

// A Message Sender

const { google } = require('googleapis');

// configure a JWT auth client
const privatekey = require("./privatekey.json");

const authClient = new google.auth.JWT(
    privatekey.client_email,
    null,
    privatekey.private_key,
    ['https://www.googleapis.com/auth/spreadsheets.readonly']);

// authentication 
authClient.authorize()
    .then(function (tokens) {
        // console.log(tokens);
        console.log("Authentication successful.\n");
    })
    .catch(function (err) {
        console.log(err);
    });

El código anterior comienza con el módulo “googleapis”, que es una biblioteca de cliente Node.js para utilizar API de Google. Es compatible con la autorización y la autenticación. Puede leer más sobre el tema aquí.

A continuación, cree una solicitud de un cliente para las API de Google (en nuestro caso, acceso a Google Sheets) y, luego, llame al método de autorización para obtener acceso. Si se pregunta lo que hace privatekey.json, se explica en la siguiente sección.

Hora de ejecutar su código. Abra una ventana del terminal y cambie el directorio a remitente-de-un-mensaje. Ejecute npm init:--yes para crear un archivo package.json predeterminado (inicie su aplicación Node.js). A continuación, ejecute npm install googleapis --save para instalar la biblioteca de clientes de Google.

Cuando intentamos ejecutar nuestra aplicación con node index.js, obtenemos un error:

Cannot find module './privatekey.json' 

Este error se produce porque falta el archivo privatekey.json. Este archivo es algo que debe obtener desde la consola de la plataforma Google Cloud.

Acceder a la planilla a través de una cuenta de servicio de Google

Una cuenta de servicio es un tipo especial de cuenta de Google diseñada para representar a un usuario no humano que debe autenticarse y estar autorizado para acceder a los datos en las API de Google.

Vaya a “plataforma Google Cloud” https://console.cloud.google.com/getting-started?pli=1.

Cree un “nuevo proyecto” haciendo clic en “Select a project” (Seleccionar un proyecto) en la parte superior de la página. A continuación, vaya a “API & Services” > “Library” (API y servicios > Biblioteca) y busque “Sheets” (Hojas). Seleccione la tarjeta “Google Sheets API” (API de Google Sheets) y, a continuación, “ENABLE” (HABILITAR). A continuación, vaya a “API & Services” > “Credentials” (API y servicios > Credenciales). Haga clic en “Create credentials” > “Help me choose” (Crear credenciales > Ayúdeme a elegir).

Agregue credenciales para “API de Google Sheets”, “otra IU (por ejemplo, Windows, herramienta CLI)”, “datos de la aplicación”. Haga clic en “What credentials do I need” (¿Qué credenciales necesito?).

Credenciales de la plataforma Google Cloud

En la siguiente pantalla, haga clic en “Create a Service account” (Crear una cuenta de servicio). Ingrese un “nombre de cuenta de servicio”, ya sea “Remitente de un mensaje” o el nombre de su propio proyecto.

Seleccione una “Función” de “Proyecto” > “Editor” y “Tipo de clave” como “JSON”.

Haga clic en “Continue” (Continuar) para descargar la clave de la cuenta de servicio como un archivo .jsonMantenga este archivo a salvo y nunca lo haga público.

Agregar credenciales al proyecto de la plataforma Google Cloud

Mueva el archivo .json a su directorio de aplicaciones y cámbiele el nombre a privatekey.json.

En este momento, intente ejecutar su aplicación nuevamente con node index.js. Esta vez no hay errores, en lugar de eso, puede ver “Autenticación exitosa”.

Pero la autenticación no es suficiente, también necesita autorización. Le mostraré lo que quiero decir. Agregue más códigos a su aplicación, este código realmente intenta leer datos de su planilla.

// A Message Sender

const { google } = require('googleapis');


// configure a JWT auth client
const privatekey = require("./privatekey.json");

const authClient = new google.auth.JWT(
    privatekey.client_email,
    null,
    privatekey.private_key,
    ['https://www.googleapis.com/auth/spreadsheets.readonly']);


// authentication
authClient.authorize()
    .then(function (tokens) {
        console.log("Authentication successful.\n");
    })
    .catch(function (error) {
        throw (error);
    });


// things we shouldn't share with our code
const secrets = require("./secrets.json");

const sheets = google.sheets('v4');
sheets.spreadsheets.values.get({
    // ID of the spreadsheet to retrieve data from
    // A1 notation of the values to retrieve  
    // authorized client  
    spreadsheetId: secrets.spreadsheet_id,
    range: 'Sheet1!A2:D',
    auth: authClient
})
    .then(function (response) {
        const rows = response.data.values;
        console.log(rows);
    })
    .catch(function (err) {
        console.log(err);
    });

El nuevo código que agrega aquí intentará leer los valores de su planilla de Google usando el método get de la recopilación de valores de planillas. Puede leer más sobre el tema en el sitio web de documentación de Google.

Tenga en cuenta que hay algunas cosas que no debe compartir con su código, y el ID de la planilla es una de ellas, por lo que la guardará en un nuevo archivo: secrets.json, ubicado en la raíz de su aplicación (mantenga este archivo seguro y no lo haga público). Este es el formato de código para secrets.json:

{
    "spreadsheet_id": "REPLACE WITH SPREADSHEET ID"
}

Otra cosa que hay que tener en cuenta es la referencia de rango para los datos, definida desde el rango A2 al D: 'Hoja1!A2:D'. “Hoja1” es el nombre de su hoja de trabajo, A2 es la celda inicial en la columna A, fila 2 y D es la celda final, pero no va seguida de un número para la fila, así que tendremos todas las filas.

El método get devuelve una promesa y, una vez que tenga la respuesta, las filas que pidió para (response.data.values), solo registre los datos en la consola y más adelante los pasaremos a la función de “enviar mensaje”.

Ejecute la aplicación nuevamente con el comando node index.js. Aparecerá “Authentication successful” (Autenticación exitosa), pero seguido de “Error: The caller does not have permission” (Error: El agente de llamada no tiene permiso), y esto se debe a que aún no ha compartido su hoja de cálculo con la cuenta de servicio, como se muestra en la siguiente captura de pantalla:

Mensaje de autenticación exitosa del nodo

Solucionemos este problema. Abra el archivo privatekey.json y copie la dirección de correo electrónico que es el valor de la clave/par de valores de client_email. Vuelva a su hoja de cálculo y haga clic en el botón “Share” (Compartir) ubicado en la parte superior derecha.

En la ventana modal “Share with others” > “People” (Compartir con otros > Personas), pegue la dirección de correo electrónico y haga clic en el botón “Send” (Enviar).

Si ejecuta ahora con node index.js, no recibirá ningún error y los datos de su hoja de cálculo están impresos en la consola.

Salida de la aplicación del nodo

Configurar Twilio para mensajes de WhatsApp

Necesitará su cuenta de Twilio y deberá activar “el sandbox de Twilio para WhatsApp” en esta sección.

Inicie sesión en Consola de Twilio y tome nota del “SID DE CUENTA” y del “TOKEN DE AUTENTICACIÓN” de su cuenta de Twilio, ya que los necesita para enviar mensajes.

Active el sandbox de WhatsApp. Tome nota del número de teléfono que elija en el sandbox, será el que utilice para enviar los mensajes. Los destinatarios de WhatsApp deben suscribirse mediante el mensaje “unirse a [PALABRA CLAVE]” de WhatsApp al número de teléfono que elija en el sandbox.

Puede encontrar más información acerca de la “API de Twilio para WhatsApp” en los documentos.

Los valores del SID DE LA CUENTA y del TOKEN DE AUTENTICACIÓN, así como del NÚMERO DEL SANDBOX DE WHATSAPP también son cosas que debe guardar en secrets.json. Agréguelos al archivo como se indica a continuación:

{
    "spreadsheet_id": "REPLACE WITH SPREADSHEET ID",
    "account_sid": "REPLACE WITH ACCOUNT SID",
    "auth_token": "REPLACE WITH AUTH TOKEN",
    "sandbox_number": "REPLACE WITH WHATSAPP SANDBOX NUMBER"
}

Con su cuenta de Twilio configurada para WhatsApp y con sus credenciales de Twilio agregadas a su aplicación Node.js ya está listo para la última parte: el envío de los mensajes.

Enviar mensajes de WhatsApp

Comience por instalar la biblioteca auxiliar de Twilio para Node.js con:

npm install twilio --save

Al desarrollarse con el sandbox de WhatsApp, Twilio cuenta con varias plantillas de texto predeterminadas y, a menos que obtenga una cuenta aprobada, utilizará una de ellas. Utilizará la plantilla “Su cita se acerca el {{1}} a las {{2}}”.

Puede leer más acerca de los formatos de plantilla en los documentos de Twilio.

Está listo para el código completo:

// A Message Sender

const { google } = require('googleapis');

// configure a JWT auth client
const privatekey = require("./privatekey.json");

const authClient = new google.auth.JWT(
    privatekey.client_email,
    null,
    privatekey.private_key,
    ['https://www.googleapis.com/auth/spreadsheets.readonly']);

// authentication
authClient.authorize()
    .then(function (tokens) {
        // console.log(tokens);
        console.log("Authentication successfull.\n");
    })
    .catch(function (error) {
        throw (error);
    });


// things we shouldn't share with our code
const secrets = require("./secrets.json");

const sheets = google.sheets('v4');
sheets.spreadsheets.values.get({
    // ID of the spreadsheet to retrieve data from
    // A1 notation of the values to retrieve  
    // authorized client  
    spreadsheetId: secrets.spreadsheet_id,
    range: 'Sheet1!A2:D',
    auth: authClient
})
    .then(function (response) {
const rows = response.data.values || [];
if (rows.length) {
        sendMessage(rows);
        }
    })
    .catch(function (err) {
        console.log(err);
    });

const accountSid = secrets.account_sid;
const authToken = secrets.auth_token;
const client = require('twilio')(accountSid, authToken);
const sandboxNumber = secrets.sandbox_number;

function sendMessage(rows) {

   // stop condition
   if (!rows.length) {
        console.log("---------------------------------");
        return;
    }

   // take information from the first row
    const firstRow = rows.shift();
    const appointmentDate = firstRow[0];
    const appointmentTime = firstRow[1];
    const clientName = firstRow[2];
    const phoneNumber = firstRow[3];

   // send the message
    client.messages
        .create({
            from: 'whatsapp:' + sandboxNumber,
            to: 'whatsapp:' + phoneNumber,
            body: `Your appointment is coming up on ${appointmentDate} at ${appointmentTime}.` +
                ` A message for ${clientName}`
        })
        .then(function (message) {
            console.log(message.sid + '\n');
            sendMessage(rows);
        })
        .catch(function (err) {
            console.log(err);
        });

}

En esta sección, agregue la función sendMessage. Esta función se utiliza para enviar los mensajes uno por uno.

La primera llamada de esta función se realiza una vez que recibe los datos de nuestra planilla de Google y sendMessage (filas) toma un argumento, un conjunto de filas con sus datos de la planilla.

Entonces sendMessage (filas) se llama de forma recursiva cuando obtiene la respuesta de Twilio después de enviar cada mensaje. Esto continúa siempre que el argumento “filas” no esté vacío.

Para cada llamada de esta función, utilice rows.shift() para tomar el primer elemento del conjunto, extraer el número de teléfono, el nombre del cliente y la información de la cita y, luego, llame al método messages.create de la librería de Twilio para enviar el mensaje.

Ejecute la aplicación nuevamente con node index.js.

A medida que se envían los mensajes, la consola muestra los SID y, si está probando el número de WhatsApp, recibirá un mensaje de WhatsApp.

Mensajes en el sandbox de Twilio

Conclusión 

Al usar la API de Twilio para WhatsApp junto con los datos de contacto almacenados en planilla de Google Sheets y algunas líneas del código Node.js, enviamos mensajes personalizados de WhatsApp a varios destinatarios.

Gracias por su interés en esta publicación. Espero que haya quedado satisfecho. Definitivamente he aprendido mucho creándola. Si tiene alguna pregunta, contáctenos. Espero con ansias ver sus construcciones.

Este artículo fue traducido del original "How to Send WhatsApp Messages from Google Sheets with JavaScript and Node.js". Mientras estamos en nuestros procesos de traducción, nos encantaría recibir sus comentarios en help@twilio.com - las contribuciones valiosas pueden generar regalos de Twilio.